@@ -1437,3 +1437,298 @@ InitializePageTableLib (
14371437
14381438 return ;
14391439}
1440+
1441+ /**
1442+ This function set given attributes of the memory region specified by
1443+ BaseAddress and Length.
1444+ The valid Attributes is EFI_MEMORY_RP, EFI_MEMORY_XP, and EFI_MEMORY_RO.
1445+
1446+ @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance.
1447+ @param BaseAddress The physical address that is the start address of
1448+ a memory region.
1449+ @param Length The size in bytes of the memory region.
1450+ @param Attributes The bit mask of attributes to set for the memory
1451+ region.
1452+
1453+ @retval EFI_SUCCESS The attributes were set for the memory region.
1454+ @retval EFI_INVALID_PARAMETER Length is zero.
1455+ Attributes specified an illegal combination of
1456+ attributes that cannot be set together.
1457+ @retval EFI_UNSUPPORTED The processor does not support one or more
1458+ bytes of the memory resource range specified
1459+ by BaseAddress and Length.
1460+ The bit mask of attributes is not supported for
1461+ the memory resource range specified by
1462+ BaseAddress and Length.
1463+ @retval EFI_OUT_OF_RESOURCES Requested attributes cannot be applied due to lack of
1464+ system resources.
1465+ @retval EFI_ACCESS_DENIED Attributes for the requested memory region are
1466+ controlled by system firmware and cannot be updated
1467+ via the protocol.
1468+ **/
1469+ EFI_STATUS
1470+ EFIAPI
1471+ EfiSetMemoryAttributes (
1472+ IN EFI_MEMORY_ATTRIBUTE_PROTOCOL * This ,
1473+ IN EFI_PHYSICAL_ADDRESS BaseAddress ,
1474+ IN UINT64 Length ,
1475+ IN UINT64 Attributes
1476+ )
1477+ {
1478+ RETURN_STATUS Status ;
1479+ BOOLEAN IsModified ;
1480+ BOOLEAN IsSplitted ;
1481+
1482+ DEBUG ((DEBUG_VERBOSE , "%a: 0x%lx - 0x%lx (0x%lx)\n" , __func__ , BaseAddress , Length , Attributes ));
1483+
1484+ if (Attributes == 0 ) {
1485+ DEBUG ((DEBUG_ERROR , "%a: Error - Attributes == 0\n" , __func__ ));
1486+ return EFI_INVALID_PARAMETER ;
1487+ }
1488+
1489+ if ((Attributes & ~EFI_MEMORY_ACCESS_MASK ) != 0 ) {
1490+ DEBUG ((DEBUG_ERROR , "%a: Error - Attributes(0x%lx) invalid\n" , __func__ , Attributes ));
1491+ return EFI_INVALID_PARAMETER ;
1492+ }
1493+
1494+ if (Length == 0 ) {
1495+ DEBUG ((DEBUG_ERROR , "%a: Length is 0!\n" , __func__ ));
1496+ return RETURN_INVALID_PARAMETER ;
1497+ }
1498+
1499+ Status = ConvertMemoryPageAttributes (NULL , BaseAddress , Length , Attributes , PageActionSet , NULL , & IsSplitted , & IsModified );
1500+ if (!EFI_ERROR (Status )) {
1501+ if (IsModified ) {
1502+ //
1503+ // Flush TLB as last step.
1504+ //
1505+ // Note: Since APs will always init CR3 register in HLT loop mode or do
1506+ // TLB flush in MWAIT loop mode, there's no need to flush TLB for them
1507+ // here.
1508+ //
1509+ CpuFlushTlb ();
1510+ }
1511+ } else {
1512+ DEBUG ((DEBUG_ERROR , "%a: Failed in ConvertMemoryPageAttributes (%r)\n" , __func__ , Status ));
1513+ }
1514+
1515+ return Status ;
1516+ }
1517+
1518+ /**
1519+ This function clears given attributes of the memory region specified by
1520+ BaseAddress and Length.
1521+ The valid Attributes is EFI_MEMORY_RP, EFI_MEMORY_XP, and EFI_MEMORY_RO.
1522+ @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance.
1523+ @param BaseAddress The physical address that is the start address of
1524+ a memory region.
1525+ @param Length The size in bytes of the memory region.
1526+ @param Attributes The bit mask of attributes to clear for the memory
1527+ region.
1528+
1529+ @retval EFI_SUCCESS The attributes were cleared for the memory region.
1530+ @retval EFI_INVALID_PARAMETER Length is zero.
1531+ Attributes specified an illegal combination of
1532+ attributes that cannot be cleared together.
1533+ @retval EFI_UNSUPPORTED The processor does not support one or more
1534+ bytes of the memory resource range specified
1535+ by BaseAddress and Length.
1536+ The bit mask of attributes is not supported for
1537+ the memory resource range specified by
1538+ BaseAddress and Length.
1539+ @retval EFI_OUT_OF_RESOURCES Requested attributes cannot be applied due to lack of
1540+ system resources.
1541+ @retval EFI_ACCESS_DENIED Attributes for the requested memory region are
1542+ controlled by system firmware and cannot be updated
1543+ via the protocol.
1544+ **/
1545+ EFI_STATUS
1546+ EFIAPI
1547+ EfiClearMemoryAttributes (
1548+ IN EFI_MEMORY_ATTRIBUTE_PROTOCOL * This ,
1549+ IN EFI_PHYSICAL_ADDRESS BaseAddress ,
1550+ IN UINT64 Length ,
1551+ IN UINT64 Attributes
1552+ )
1553+ {
1554+ RETURN_STATUS Status ;
1555+ BOOLEAN IsModified ;
1556+ BOOLEAN IsSplitted ;
1557+
1558+ DEBUG ((DEBUG_VERBOSE , "%a: 0x%lx - 0x%lx (0x%lx)\n" , __func__ , BaseAddress , Length , Attributes ));
1559+
1560+ if (Attributes == 0 ) {
1561+ DEBUG ((DEBUG_ERROR , "%a: Error - Attributes == 0\n" , __func__ ));
1562+ return EFI_INVALID_PARAMETER ;
1563+ }
1564+
1565+ if ((Attributes & ~EFI_MEMORY_ACCESS_MASK ) != 0 ) {
1566+ DEBUG ((DEBUG_ERROR , "%a: Error - Attributes(0x%lx) invalid\n" , __func__ , Attributes ));
1567+ return EFI_INVALID_PARAMETER ;
1568+ }
1569+
1570+ if (Length == 0 ) {
1571+ DEBUG ((DEBUG_ERROR , "%a: Length is 0!\n" , __func__ ));
1572+ return RETURN_INVALID_PARAMETER ;
1573+ }
1574+
1575+ Status = ConvertMemoryPageAttributes (NULL , BaseAddress , Length , Attributes , PageActionClear , NULL , & IsSplitted , & IsModified );
1576+ if (!EFI_ERROR (Status )) {
1577+ if (IsModified ) {
1578+ //
1579+ // Flush TLB as last step.
1580+ //
1581+ // Note: Since APs will always init CR3 register in HLT loop mode or do
1582+ // TLB flush in MWAIT loop mode, there's no need to flush TLB for them
1583+ // here.
1584+ //
1585+ CpuFlushTlb ();
1586+ }
1587+ } else {
1588+ DEBUG ((DEBUG_ERROR , "%a: Failed in ConvertMemoryPageAttributes (%r)\n" , __func__ , Status ));
1589+ }
1590+
1591+ return Status ;
1592+ }
1593+
1594+ /**
1595+ This function retrieves the attributes of the memory region specified by
1596+ BaseAddress and Length. If different attributes are got from different part
1597+ of the memory region, EFI_NO_MAPPING will be returned.
1598+
1599+ @param This The EFI_MEMORY_ATTRIBUTE_PROTOCOL instance.
1600+ @param BaseAddress The physical address that is the start address of
1601+ a memory region.
1602+ @param Length The size in bytes of the memory region.
1603+ @param Attributes Pointer to attributes returned.
1604+
1605+ @retval EFI_SUCCESS The attributes got for the memory region.
1606+ @retval EFI_INVALID_PARAMETER Length is zero.
1607+ Attributes is NULL.
1608+ @retval EFI_NO_MAPPING Attributes are not consistent cross the memory
1609+ region.
1610+ @retval EFI_UNSUPPORTED The processor does not support one or more
1611+ bytes of the memory resource range specified
1612+ by BaseAddress and Length.
1613+ **/
1614+ EFI_STATUS
1615+ EFIAPI
1616+ EfiGetMemoryAttributes (
1617+ IN EFI_MEMORY_ATTRIBUTE_PROTOCOL * This ,
1618+ IN EFI_PHYSICAL_ADDRESS BaseAddress ,
1619+ IN UINT64 Length ,
1620+ OUT UINT64 * Attributes
1621+ )
1622+ {
1623+ PAGE_TABLE_LIB_PAGING_CONTEXT CurrentPagingContext ;
1624+ EFI_PHYSICAL_ADDRESS Address ;
1625+ UINT64 * PageEntry ;
1626+ UINT64 MemAttr ;
1627+ PAGE_ATTRIBUTE PageAttr ;
1628+ INT64 Size ;
1629+ UINT64 AddressEncMask ;
1630+
1631+ DEBUG ((DEBUG_VERBOSE , "%a: 0x%lx - 0x%lx\n" , __func__ , BaseAddress , Length ));
1632+
1633+ if (!IS_ALIGNED (BaseAddress , EFI_PAGE_SIZE )) {
1634+ DEBUG ((DEBUG_ERROR , "%a: BaseAddress(0x%lx) is not aligned!\n" , __func__ , BaseAddress ));
1635+ return EFI_UNSUPPORTED ;
1636+ }
1637+
1638+ if (!IS_ALIGNED (Length , EFI_PAGE_SIZE )) {
1639+ DEBUG ((DEBUG_ERROR , "%a: Length(0x%lx) is not aligned!\n" , __func__ , Length ));
1640+ return EFI_UNSUPPORTED ;
1641+ }
1642+
1643+ if (Length == 0 ) {
1644+ DEBUG ((DEBUG_ERROR , "%a: Length is 0!\n" , __func__ ));
1645+ return RETURN_INVALID_PARAMETER ;
1646+ }
1647+
1648+ if (Attributes == NULL ) {
1649+ DEBUG ((DEBUG_ERROR , "%a: Attributes is NULL\n" , __func__ ));
1650+ return EFI_INVALID_PARAMETER ;
1651+ }
1652+
1653+ Size = (INT64 )Length ;
1654+ MemAttr = (UINT64 )- 1 ;
1655+
1656+ // Make sure AddressEncMask is contained to smallest supported address field.
1657+ //
1658+ AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask ) & PAGING_1G_ADDRESS_MASK_64 ;
1659+
1660+ GetCurrentPagingContext (& CurrentPagingContext );
1661+
1662+ do {
1663+ PageEntry = GetPageTableEntry (& CurrentPagingContext , BaseAddress , & PageAttr );
1664+ if ((PageEntry == NULL ) || (PageAttr == PageNone )) {
1665+ return EFI_UNSUPPORTED ;
1666+ }
1667+
1668+ //
1669+ // If the memory range is cross page table boundary, make sure they
1670+ // share the same attribute. Return EFI_NO_MAPPING if not.
1671+ //
1672+ * Attributes = GetAttributesFromPageEntry (PageEntry );
1673+ if ((MemAttr != (UINT64 )- 1 ) && (* Attributes != MemAttr )) {
1674+ return EFI_NO_MAPPING ;
1675+ }
1676+
1677+ switch (PageAttr ) {
1678+ case Page4K :
1679+ Address = * PageEntry & ~AddressEncMask & PAGING_4K_ADDRESS_MASK_64 ;
1680+ Size -= (EFI_PAGE_SIZE - (BaseAddress - Address ));
1681+ BaseAddress += (EFI_PAGE_SIZE - (BaseAddress - Address ));
1682+ break ;
1683+
1684+ case Page2M :
1685+ Address = * PageEntry & ~AddressEncMask & PAGING_2M_ADDRESS_MASK_64 ;
1686+ Size -= SIZE_2MB - (BaseAddress - Address );
1687+ BaseAddress += SIZE_2MB - (BaseAddress - Address );
1688+ break ;
1689+
1690+ case Page1G :
1691+ Address = * PageEntry & ~AddressEncMask & PAGING_1G_ADDRESS_MASK_64 ;
1692+ Size -= SIZE_1GB - (BaseAddress - Address );
1693+ BaseAddress += SIZE_1GB - (BaseAddress - Address );
1694+ break ;
1695+
1696+ default :
1697+ return EFI_UNSUPPORTED ;
1698+ }
1699+
1700+ MemAttr = * Attributes ;
1701+ } while (Size > 0 );
1702+
1703+ DEBUG ((DEBUG_VERBOSE , "%a: Attributes is 0x%lx\n" , __func__ , * Attributes ));
1704+
1705+ return EFI_SUCCESS ;
1706+ }
1707+
1708+ EFI_MEMORY_ATTRIBUTE_PROTOCOL mMemoryAttributeProtocol = {
1709+ EfiGetMemoryAttributes ,
1710+ EfiSetMemoryAttributes ,
1711+ EfiClearMemoryAttributes ,
1712+ };
1713+
1714+ /**
1715+ Install Efi Memory Attribute Protocol.
1716+
1717+ @param Handle A pointer to the EFI_HANDLE on which the interface is to be installed
1718+
1719+ **/
1720+ VOID
1721+ InstallEfiMemoryAttributeProtocol (
1722+ IN EFI_HANDLE Handle
1723+ )
1724+ {
1725+ EFI_STATUS Status ;
1726+
1727+ Status = gBS -> InstallMultipleProtocolInterfaces (
1728+ & Handle ,
1729+ & gEfiMemoryAttributeProtocolGuid ,
1730+ & mMemoryAttributeProtocol ,
1731+ NULL
1732+ );
1733+ ASSERT_EFI_ERROR (Status );
1734+ }
0 commit comments