+\r
+/**\r
+ This function set given attributes of the memory region specified by\r
+ BaseAddress and Length.\r
+\r
+ @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+ @param BaseAddress The physical address that is the start address of\r
+ a memory region.\r
+ @param Length The size in bytes of the memory region.\r
+ @param Attributes The bit mask of attributes to set for the memory\r
+ region.\r
+\r
+ @retval EFI_SUCCESS The attributes were set for the memory region.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ Attributes specified an illegal combination of\r
+ attributes that cannot be set together.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more\r
+ bytes of the memory resource range specified\r
+ by BaseAddress and Length.\r
+ The bit mask of attributes is not supported for\r
+ the memory resource range specified by\r
+ BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmSetMemoryAttributes (\r
+ IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ return SmmSetMemoryAttributes (BaseAddress, Length, Attributes);\r
+}\r
+\r
+/**\r
+ This function clears given attributes of the memory region specified by\r
+ BaseAddress and Length.\r
+\r
+ @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+ @param BaseAddress The physical address that is the start address of\r
+ a memory region.\r
+ @param Length The size in bytes of the memory region.\r
+ @param Attributes The bit mask of attributes to clear for the memory\r
+ region.\r
+\r
+ @retval EFI_SUCCESS The attributes were cleared for the memory region.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ Attributes specified an illegal combination of\r
+ attributes that cannot be cleared together.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more\r
+ bytes of the memory resource range specified\r
+ by BaseAddress and Length.\r
+ The bit mask of attributes is not supported for\r
+ the memory resource range specified by\r
+ BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmClearMemoryAttributes (\r
+ IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ IN UINT64 Attributes\r
+ )\r
+{\r
+ return SmmClearMemoryAttributes (BaseAddress, Length, Attributes);\r
+}\r
+\r
+/**\r
+ This function retrieves the attributes of the memory region specified by\r
+ BaseAddress and Length. If different attributes are got from different part\r
+ of the memory region, EFI_NO_MAPPING will be returned.\r
+\r
+ @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.\r
+ @param BaseAddress The physical address that is the start address of\r
+ a memory region.\r
+ @param Length The size in bytes of the memory region.\r
+ @param Attributes Pointer to attributes returned.\r
+\r
+ @retval EFI_SUCCESS The attributes got for the memory region.\r
+ @retval EFI_INVALID_PARAMETER Length is zero.\r
+ Attributes is NULL.\r
+ @retval EFI_NO_MAPPING Attributes are not consistent cross the memory\r
+ region.\r
+ @retval EFI_UNSUPPORTED The processor does not support one or more\r
+ bytes of the memory resource range specified\r
+ by BaseAddress and Length.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EdkiiSmmGetMemoryAttributes (\r
+ IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL *This,\r
+ IN EFI_PHYSICAL_ADDRESS BaseAddress,\r
+ IN UINT64 Length,\r
+ OUT UINT64 *Attributes\r
+ )\r
+{\r
+ EFI_PHYSICAL_ADDRESS Address;\r
+ UINT64 *PageEntry;\r
+ UINT64 MemAttr;\r
+ PAGE_ATTRIBUTE PageAttr;\r
+ INT64 Size;\r
+\r
+ if (Length < SIZE_4KB || Attributes == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Size = (INT64)Length;\r
+ MemAttr = (UINT64)-1;\r
+\r
+ do {\r
+\r
+ PageEntry = GetPageTableEntry (BaseAddress, &PageAttr);\r
+ if (PageEntry == NULL || PageAttr == PageNone) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ //\r
+ // If the memory range is cross page table boundary, make sure they\r
+ // share the same attribute. Return EFI_NO_MAPPING if not.\r
+ //\r
+ *Attributes = GetAttributesFromPageEntry (PageEntry);\r
+ if (MemAttr != (UINT64)-1 && *Attributes != MemAttr) {\r
+ return EFI_NO_MAPPING;\r
+ }\r
+\r
+ switch (PageAttr) {\r
+ case Page4K:\r
+ Address = *PageEntry & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64;\r
+ Size -= (SIZE_4KB - (BaseAddress - Address));\r
+ BaseAddress += (SIZE_4KB - (BaseAddress - Address));\r
+ break;\r
+\r
+ case Page2M:\r
+ Address = *PageEntry & ~mAddressEncMask & PAGING_2M_ADDRESS_MASK_64;\r
+ Size -= SIZE_2MB - (BaseAddress - Address);\r
+ BaseAddress += SIZE_2MB - (BaseAddress - Address);\r
+ break;\r
+\r
+ case Page1G:\r
+ Address = *PageEntry & ~mAddressEncMask & PAGING_1G_ADDRESS_MASK_64;\r
+ Size -= SIZE_1GB - (BaseAddress - Address);\r
+ BaseAddress += SIZE_1GB - (BaseAddress - Address);\r
+ break;\r
+\r
+ default:\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ MemAttr = *Attributes;\r
+\r
+ } while (Size > 0);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r