3 Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
8 #include "PiSmmCpuDxeSmm.h"
11 // attributes for reserved memory before it is promoted to system memory
13 #define EFI_MEMORY_PRESENT 0x0100000000000000ULL
14 #define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL
15 #define EFI_MEMORY_TESTED 0x0400000000000000ULL
17 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
18 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
20 EFI_MEMORY_DESCRIPTOR
*mUefiMemoryMap
;
21 UINTN mUefiMemoryMapSize
;
22 UINTN mUefiDescriptorSize
;
24 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*mGcdMemSpace
= NULL
;
25 UINTN mGcdMemNumberOfDesc
= 0;
27 EFI_MEMORY_ATTRIBUTES_TABLE
*mUefiMemoryAttributesTable
= NULL
;
29 PAGE_ATTRIBUTE_TABLE mPageAttributeTable
[] = {
30 {Page4K
, SIZE_4KB
, PAGING_4K_ADDRESS_MASK_64
},
31 {Page2M
, SIZE_2MB
, PAGING_2M_ADDRESS_MASK_64
},
32 {Page1G
, SIZE_1GB
, PAGING_1G_ADDRESS_MASK_64
},
38 Set the internal page table base address.
39 If it is non zero, further MemoryAttribute modification will be on this page table.
40 If it is zero, further MemoryAttribute modification will be on real page table.
42 @param Cr3 page table base.
53 Return page table base.
55 @return page table base.
62 if (mInternalGr3
!= 0) {
65 return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64
);
69 Return length according to page attributes.
71 @param[in] PageAttributes The page attribute of the page entry.
73 @return The length of page entry.
76 PageAttributeToLength (
77 IN PAGE_ATTRIBUTE PageAttribute
81 for (Index
= 0; Index
< sizeof(mPageAttributeTable
)/sizeof(mPageAttributeTable
[0]); Index
++) {
82 if (PageAttribute
== mPageAttributeTable
[Index
].Attribute
) {
83 return (UINTN
)mPageAttributeTable
[Index
].Length
;
90 Return address mask according to page attributes.
92 @param[in] PageAttributes The page attribute of the page entry.
94 @return The address mask of page entry.
98 IN PAGE_ATTRIBUTE PageAttribute
102 for (Index
= 0; Index
< sizeof(mPageAttributeTable
)/sizeof(mPageAttributeTable
[0]); Index
++) {
103 if (PageAttribute
== mPageAttributeTable
[Index
].Attribute
) {
104 return (UINTN
)mPageAttributeTable
[Index
].AddressMask
;
111 Return page table entry to match the address.
113 @param[in] Address The address to be checked.
114 @param[out] PageAttributes The page attribute of the page entry.
116 @return The page entry.
120 IN PHYSICAL_ADDRESS Address
,
121 OUT PAGE_ATTRIBUTE
*PageAttribute
135 BOOLEAN Enable5LevelPaging
;
137 Index5
= ((UINTN
)RShiftU64 (Address
, 48)) & PAGING_PAE_INDEX_MASK
;
138 Index4
= ((UINTN
)RShiftU64 (Address
, 39)) & PAGING_PAE_INDEX_MASK
;
139 Index3
= ((UINTN
)Address
>> 30) & PAGING_PAE_INDEX_MASK
;
140 Index2
= ((UINTN
)Address
>> 21) & PAGING_PAE_INDEX_MASK
;
141 Index1
= ((UINTN
)Address
>> 12) & PAGING_PAE_INDEX_MASK
;
143 Cr4
.UintN
= AsmReadCr4 ();
144 Enable5LevelPaging
= (BOOLEAN
) (Cr4
.Bits
.LA57
== 1);
146 if (sizeof(UINTN
) == sizeof(UINT64
)) {
147 if (Enable5LevelPaging
) {
148 L5PageTable
= (UINT64
*)GetPageTableBase ();
149 if (L5PageTable
[Index5
] == 0) {
150 *PageAttribute
= PageNone
;
154 L4PageTable
= (UINT64
*)(UINTN
)(L5PageTable
[Index5
] & ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
);
156 L4PageTable
= (UINT64
*)GetPageTableBase ();
158 if (L4PageTable
[Index4
] == 0) {
159 *PageAttribute
= PageNone
;
163 L3PageTable
= (UINT64
*)(UINTN
)(L4PageTable
[Index4
] & ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
);
165 L3PageTable
= (UINT64
*)GetPageTableBase ();
167 if (L3PageTable
[Index3
] == 0) {
168 *PageAttribute
= PageNone
;
171 if ((L3PageTable
[Index3
] & IA32_PG_PS
) != 0) {
173 *PageAttribute
= Page1G
;
174 return &L3PageTable
[Index3
];
177 L2PageTable
= (UINT64
*)(UINTN
)(L3PageTable
[Index3
] & ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
);
178 if (L2PageTable
[Index2
] == 0) {
179 *PageAttribute
= PageNone
;
182 if ((L2PageTable
[Index2
] & IA32_PG_PS
) != 0) {
184 *PageAttribute
= Page2M
;
185 return &L2PageTable
[Index2
];
189 L1PageTable
= (UINT64
*)(UINTN
)(L2PageTable
[Index2
] & ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
);
190 if ((L1PageTable
[Index1
] == 0) && (Address
!= 0)) {
191 *PageAttribute
= PageNone
;
194 *PageAttribute
= Page4K
;
195 return &L1PageTable
[Index1
];
199 Return memory attributes of page entry.
201 @param[in] PageEntry The page entry.
203 @return Memory attributes of page entry.
206 GetAttributesFromPageEntry (
212 if ((*PageEntry
& IA32_PG_P
) == 0) {
213 Attributes
|= EFI_MEMORY_RP
;
215 if ((*PageEntry
& IA32_PG_RW
) == 0) {
216 Attributes
|= EFI_MEMORY_RO
;
218 if ((*PageEntry
& IA32_PG_NX
) != 0) {
219 Attributes
|= EFI_MEMORY_XP
;
225 Modify memory attributes of page entry.
227 @param[in] PageEntry The page entry.
228 @param[in] Attributes The bit mask of attributes to modify for the memory region.
229 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
230 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
233 ConvertPageEntryAttribute (
234 IN UINT64
*PageEntry
,
235 IN UINT64 Attributes
,
237 OUT BOOLEAN
*IsModified
240 UINT64 CurrentPageEntry
;
243 CurrentPageEntry
= *PageEntry
;
244 NewPageEntry
= CurrentPageEntry
;
245 if ((Attributes
& EFI_MEMORY_RP
) != 0) {
247 NewPageEntry
&= ~(UINT64
)IA32_PG_P
;
249 NewPageEntry
|= IA32_PG_P
;
252 if ((Attributes
& EFI_MEMORY_RO
) != 0) {
254 NewPageEntry
&= ~(UINT64
)IA32_PG_RW
;
255 if (mInternalGr3
!= 0) {
257 // ReadOnly page need set Dirty bit for shadow stack
258 NewPageEntry
|= IA32_PG_D
;
259 // Clear user bit for supervisor shadow stack
260 NewPageEntry
&= ~(UINT64
)IA32_PG_U
;
263 // Clear dirty bit for non shadow stack, to protect RO page.
264 NewPageEntry
&= ~(UINT64
)IA32_PG_D
;
267 NewPageEntry
|= IA32_PG_RW
;
270 if ((Attributes
& EFI_MEMORY_XP
) != 0) {
273 NewPageEntry
|= IA32_PG_NX
;
275 NewPageEntry
&= ~IA32_PG_NX
;
279 *PageEntry
= NewPageEntry
;
280 if (CurrentPageEntry
!= NewPageEntry
) {
282 DEBUG ((DEBUG_VERBOSE
, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry
));
283 DEBUG ((DEBUG_VERBOSE
, "->0x%lx\n", NewPageEntry
));
290 This function returns if there is need to split page entry.
292 @param[in] BaseAddress The base address to be checked.
293 @param[in] Length The length to be checked.
294 @param[in] PageEntry The page entry to be checked.
295 @param[in] PageAttribute The page attribute of the page entry.
297 @retval SplitAttributes on if there is need to split page entry.
301 IN PHYSICAL_ADDRESS BaseAddress
,
303 IN UINT64
*PageEntry
,
304 IN PAGE_ATTRIBUTE PageAttribute
307 UINT64 PageEntryLength
;
309 PageEntryLength
= PageAttributeToLength (PageAttribute
);
311 if (((BaseAddress
& (PageEntryLength
- 1)) == 0) && (Length
>= PageEntryLength
)) {
315 if (((BaseAddress
& PAGING_2M_MASK
) != 0) || (Length
< SIZE_2MB
)) {
323 This function splits one page entry to small page entries.
325 @param[in] PageEntry The page entry to be splitted.
326 @param[in] PageAttribute The page attribute of the page entry.
327 @param[in] SplitAttribute How to split the page entry.
329 @retval RETURN_SUCCESS The page entry is splitted.
330 @retval RETURN_UNSUPPORTED The page entry does not support to be splitted.
331 @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.
335 IN UINT64
*PageEntry
,
336 IN PAGE_ATTRIBUTE PageAttribute
,
337 IN PAGE_ATTRIBUTE SplitAttribute
341 UINT64
*NewPageEntry
;
344 ASSERT (PageAttribute
== Page2M
|| PageAttribute
== Page1G
);
346 if (PageAttribute
== Page2M
) {
350 ASSERT (SplitAttribute
== Page4K
);
351 if (SplitAttribute
== Page4K
) {
352 NewPageEntry
= AllocatePageTableMemory (1);
353 DEBUG ((DEBUG_VERBOSE
, "Split - 0x%x\n", NewPageEntry
));
354 if (NewPageEntry
== NULL
) {
355 return RETURN_OUT_OF_RESOURCES
;
357 BaseAddress
= *PageEntry
& PAGING_2M_ADDRESS_MASK_64
;
358 for (Index
= 0; Index
< SIZE_4KB
/ sizeof(UINT64
); Index
++) {
359 NewPageEntry
[Index
] = (BaseAddress
+ SIZE_4KB
* Index
) | mAddressEncMask
| ((*PageEntry
) & PAGE_PROGATE_BITS
);
361 (*PageEntry
) = (UINT64
)(UINTN
)NewPageEntry
| mAddressEncMask
| PAGE_ATTRIBUTE_BITS
;
362 return RETURN_SUCCESS
;
364 return RETURN_UNSUPPORTED
;
366 } else if (PageAttribute
== Page1G
) {
369 // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K to get more compact page table.
371 ASSERT (SplitAttribute
== Page2M
|| SplitAttribute
== Page4K
);
372 if ((SplitAttribute
== Page2M
|| SplitAttribute
== Page4K
)) {
373 NewPageEntry
= AllocatePageTableMemory (1);
374 DEBUG ((DEBUG_VERBOSE
, "Split - 0x%x\n", NewPageEntry
));
375 if (NewPageEntry
== NULL
) {
376 return RETURN_OUT_OF_RESOURCES
;
378 BaseAddress
= *PageEntry
& PAGING_1G_ADDRESS_MASK_64
;
379 for (Index
= 0; Index
< SIZE_4KB
/ sizeof(UINT64
); Index
++) {
380 NewPageEntry
[Index
] = (BaseAddress
+ SIZE_2MB
* Index
) | mAddressEncMask
| IA32_PG_PS
| ((*PageEntry
) & PAGE_PROGATE_BITS
);
382 (*PageEntry
) = (UINT64
)(UINTN
)NewPageEntry
| mAddressEncMask
| PAGE_ATTRIBUTE_BITS
;
383 return RETURN_SUCCESS
;
385 return RETURN_UNSUPPORTED
;
388 return RETURN_UNSUPPORTED
;
393 This function modifies the page attributes for the memory region specified by BaseAddress and
394 Length from their current attributes to the attributes specified by Attributes.
396 Caller should make sure BaseAddress and Length is at page boundary.
398 @param[in] BaseAddress The physical address that is the start address of a memory region.
399 @param[in] Length The size in bytes of the memory region.
400 @param[in] Attributes The bit mask of attributes to modify for the memory region.
401 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
402 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
403 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
405 @retval RETURN_SUCCESS The attributes were modified for the memory region.
406 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
407 BaseAddress and Length cannot be modified.
408 @retval RETURN_INVALID_PARAMETER Length is zero.
409 Attributes specified an illegal combination of attributes that
410 cannot be set together.
411 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
412 the memory resource range.
413 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory
414 resource range specified by BaseAddress and Length.
415 The bit mask of attributes is not support for the memory resource
416 range specified by BaseAddress and Length.
420 ConvertMemoryPageAttributes (
421 IN PHYSICAL_ADDRESS BaseAddress
,
423 IN UINT64 Attributes
,
425 OUT BOOLEAN
*IsSplitted
, OPTIONAL
426 OUT BOOLEAN
*IsModified OPTIONAL
430 PAGE_ATTRIBUTE PageAttribute
;
431 UINTN PageEntryLength
;
432 PAGE_ATTRIBUTE SplitAttribute
;
433 RETURN_STATUS Status
;
434 BOOLEAN IsEntryModified
;
435 EFI_PHYSICAL_ADDRESS MaximumSupportMemAddress
;
437 ASSERT (Attributes
!= 0);
438 ASSERT ((Attributes
& ~(EFI_MEMORY_RP
| EFI_MEMORY_RO
| EFI_MEMORY_XP
)) == 0);
440 ASSERT ((BaseAddress
& (SIZE_4KB
- 1)) == 0);
441 ASSERT ((Length
& (SIZE_4KB
- 1)) == 0);
444 return RETURN_INVALID_PARAMETER
;
447 MaximumSupportMemAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(LShiftU64 (1, mPhysicalAddressBits
) - 1);
448 if (BaseAddress
> MaximumSupportMemAddress
) {
449 return RETURN_UNSUPPORTED
;
451 if (Length
> MaximumSupportMemAddress
) {
452 return RETURN_UNSUPPORTED
;
454 if ((Length
!= 0) && (BaseAddress
> MaximumSupportMemAddress
- (Length
- 1))) {
455 return RETURN_UNSUPPORTED
;
458 // DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));
460 if (IsSplitted
!= NULL
) {
463 if (IsModified
!= NULL
) {
468 // Below logic is to check 2M/4K page to make sure we do not waste memory.
470 while (Length
!= 0) {
471 PageEntry
= GetPageTableEntry (BaseAddress
, &PageAttribute
);
472 if (PageEntry
== NULL
) {
473 return RETURN_UNSUPPORTED
;
475 PageEntryLength
= PageAttributeToLength (PageAttribute
);
476 SplitAttribute
= NeedSplitPage (BaseAddress
, Length
, PageEntry
, PageAttribute
);
477 if (SplitAttribute
== PageNone
) {
478 ConvertPageEntryAttribute (PageEntry
, Attributes
, IsSet
, &IsEntryModified
);
479 if (IsEntryModified
) {
480 if (IsModified
!= NULL
) {
485 // Convert success, move to next
487 BaseAddress
+= PageEntryLength
;
488 Length
-= PageEntryLength
;
490 Status
= SplitPage (PageEntry
, PageAttribute
, SplitAttribute
);
491 if (RETURN_ERROR (Status
)) {
492 return RETURN_UNSUPPORTED
;
494 if (IsSplitted
!= NULL
) {
497 if (IsModified
!= NULL
) {
501 // Just split current page
502 // Convert success in next around
507 return RETURN_SUCCESS
;
511 FlushTlb on current processor.
513 @param[in,out] Buffer Pointer to private data buffer.
517 FlushTlbOnCurrentProcessor (
525 FlushTlb for all processors.
534 FlushTlbOnCurrentProcessor (NULL
);
536 for (Index
= 0; Index
< gSmst
->NumberOfCpus
; Index
++) {
537 if (Index
!= gSmst
->CurrentlyExecutingCpu
) {
538 // Force to start up AP in blocking mode,
539 SmmBlockingStartupThisAp (FlushTlbOnCurrentProcessor
, Index
, NULL
);
540 // Do not check return status, because AP might not be present in some corner cases.
546 This function sets the attributes for the memory region specified by BaseAddress and
547 Length from their current attributes to the attributes specified by Attributes.
549 @param[in] BaseAddress The physical address that is the start address of a memory region.
550 @param[in] Length The size in bytes of the memory region.
551 @param[in] Attributes The bit mask of attributes to set for the memory region.
552 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
554 @retval EFI_SUCCESS The attributes were set for the memory region.
555 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
556 BaseAddress and Length cannot be modified.
557 @retval EFI_INVALID_PARAMETER Length is zero.
558 Attributes specified an illegal combination of attributes that
559 cannot be set together.
560 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
561 the memory resource range.
562 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
563 resource range specified by BaseAddress and Length.
564 The bit mask of attributes is not support for the memory resource
565 range specified by BaseAddress and Length.
570 SmmSetMemoryAttributesEx (
571 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
573 IN UINT64 Attributes
,
574 OUT BOOLEAN
*IsSplitted OPTIONAL
580 Status
= ConvertMemoryPageAttributes (BaseAddress
, Length
, Attributes
, TRUE
, IsSplitted
, &IsModified
);
581 if (!EFI_ERROR(Status
)) {
584 // Flush TLB as last step
594 This function clears the attributes for the memory region specified by BaseAddress and
595 Length from their current attributes to the attributes specified by Attributes.
597 @param[in] BaseAddress The physical address that is the start address of a memory region.
598 @param[in] Length The size in bytes of the memory region.
599 @param[in] Attributes The bit mask of attributes to clear for the memory region.
600 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
602 @retval EFI_SUCCESS The attributes were cleared for the memory region.
603 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
604 BaseAddress and Length cannot be modified.
605 @retval EFI_INVALID_PARAMETER Length is zero.
606 Attributes specified an illegal combination of attributes that
607 cannot be cleared together.
608 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
609 the memory resource range.
610 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
611 resource range specified by BaseAddress and Length.
612 The bit mask of attributes is not supported for the memory resource
613 range specified by BaseAddress and Length.
618 SmmClearMemoryAttributesEx (
619 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
621 IN UINT64 Attributes
,
622 OUT BOOLEAN
*IsSplitted OPTIONAL
628 Status
= ConvertMemoryPageAttributes (BaseAddress
, Length
, Attributes
, FALSE
, IsSplitted
, &IsModified
);
629 if (!EFI_ERROR(Status
)) {
632 // Flush TLB as last step
642 This function sets the attributes for the memory region specified by BaseAddress and
643 Length from their current attributes to the attributes specified by Attributes.
645 @param[in] BaseAddress The physical address that is the start address of a memory region.
646 @param[in] Length The size in bytes of the memory region.
647 @param[in] Attributes The bit mask of attributes to set for the memory region.
649 @retval EFI_SUCCESS The attributes were set for the memory region.
650 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
651 BaseAddress and Length cannot be modified.
652 @retval EFI_INVALID_PARAMETER Length is zero.
653 Attributes specified an illegal combination of attributes that
654 cannot be set together.
655 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
656 the memory resource range.
657 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
658 resource range specified by BaseAddress and Length.
659 The bit mask of attributes is not supported for the memory resource
660 range specified by BaseAddress and Length.
665 SmmSetMemoryAttributes (
666 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
671 return SmmSetMemoryAttributesEx (BaseAddress
, Length
, Attributes
, NULL
);
675 This function clears the attributes for the memory region specified by BaseAddress and
676 Length from their current attributes to the attributes specified by Attributes.
678 @param[in] BaseAddress The physical address that is the start address of a memory region.
679 @param[in] Length The size in bytes of the memory region.
680 @param[in] Attributes The bit mask of attributes to clear for the memory region.
682 @retval EFI_SUCCESS The attributes were cleared for the memory region.
683 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
684 BaseAddress and Length cannot be modified.
685 @retval EFI_INVALID_PARAMETER Length is zero.
686 Attributes specified an illegal combination of attributes that
687 cannot be cleared together.
688 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
689 the memory resource range.
690 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
691 resource range specified by BaseAddress and Length.
692 The bit mask of attributes is not supported for the memory resource
693 range specified by BaseAddress and Length.
698 SmmClearMemoryAttributes (
699 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
704 return SmmClearMemoryAttributesEx (BaseAddress
, Length
, Attributes
, NULL
);
708 Set ShadowStack memory.
710 @param[in] Cr3 The page table base address.
711 @param[in] BaseAddress The physical address that is the start address of a memory region.
712 @param[in] Length The size in bytes of the memory region.
714 @retval EFI_SUCCESS The shadow stack memory is set.
719 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
725 SetPageTableBase (Cr3
);
727 Status
= SmmSetMemoryAttributes (BaseAddress
, Length
, EFI_MEMORY_RO
);
729 SetPageTableBase (0);
735 Set not present memory.
737 @param[in] Cr3 The page table base address.
738 @param[in] BaseAddress The physical address that is the start address of a memory region.
739 @param[in] Length The size in bytes of the memory region.
741 @retval EFI_SUCCESS The not present memory is set.
746 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
752 SetPageTableBase (Cr3
);
754 Status
= SmmSetMemoryAttributes (BaseAddress
, Length
, EFI_MEMORY_RP
);
756 SetPageTableBase (0);
762 Retrieves a pointer to the system configuration table from the SMM System Table
763 based on a specified GUID.
765 @param[in] TableGuid The pointer to table's GUID type.
766 @param[out] Table The pointer to the table associated with TableGuid in the EFI System Table.
768 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
769 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.
774 SmmGetSystemConfigurationTable (
775 IN EFI_GUID
*TableGuid
,
781 ASSERT (TableGuid
!= NULL
);
782 ASSERT (Table
!= NULL
);
785 for (Index
= 0; Index
< gSmst
->NumberOfTableEntries
; Index
++) {
786 if (CompareGuid (TableGuid
, &(gSmst
->SmmConfigurationTable
[Index
].VendorGuid
))) {
787 *Table
= gSmst
->SmmConfigurationTable
[Index
].VendorTable
;
792 return EFI_NOT_FOUND
;
796 This function sets SMM save state buffer to be RW and XP.
799 PatchSmmSaveStateMap (
808 TileCodeSize
= GetSmiHandlerSize ();
809 TileCodeSize
= ALIGN_VALUE(TileCodeSize
, SIZE_4KB
);
810 TileDataSize
= (SMRAM_SAVE_STATE_MAP_OFFSET
- SMM_PSD_OFFSET
) + sizeof (SMRAM_SAVE_STATE_MAP
);
811 TileDataSize
= ALIGN_VALUE(TileDataSize
, SIZE_4KB
);
812 TileSize
= TileDataSize
+ TileCodeSize
- 1;
813 TileSize
= 2 * GetPowerOfTwo32 ((UINT32
)TileSize
);
815 DEBUG ((DEBUG_INFO
, "PatchSmmSaveStateMap:\n"));
816 for (Index
= 0; Index
< mMaxNumberOfCpus
- 1; Index
++) {
820 SmmSetMemoryAttributes (
821 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
,
825 SmmClearMemoryAttributes (
826 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
,
834 SmmClearMemoryAttributes (
835 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
836 TileSize
- TileCodeSize
,
839 SmmSetMemoryAttributes (
840 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
841 TileSize
- TileCodeSize
,
849 SmmSetMemoryAttributes (
850 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
,
854 SmmClearMemoryAttributes (
855 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
,
863 SmmClearMemoryAttributes (
864 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
865 SIZE_32KB
- TileCodeSize
,
868 SmmSetMemoryAttributes (
869 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
870 SIZE_32KB
- TileCodeSize
,
876 This function sets GDT/IDT buffer to be RO and XP.
883 EFI_PHYSICAL_ADDRESS BaseAddress
;
889 DEBUG ((DEBUG_INFO
, "PatchGdtIdtMap - GDT:\n"));
891 BaseAddress
= mGdtBuffer
;
892 Size
= ALIGN_VALUE(mGdtBufferSize
, SIZE_4KB
);
894 // The range should have been set to RO
895 // if it is allocated with EfiRuntimeServicesCode.
897 SmmSetMemoryAttributes (
906 DEBUG ((DEBUG_INFO
, "PatchGdtIdtMap - IDT:\n"));
908 BaseAddress
= gcSmiIdtr
.Base
;
909 Size
= ALIGN_VALUE(gcSmiIdtr
.Limit
+ 1, SIZE_4KB
);
911 // The range should have been set to RO
912 // if it is allocated with EfiRuntimeServicesCode.
914 SmmSetMemoryAttributes (
922 This function sets memory attribute according to MemoryAttributesTable.
925 SetMemMapAttributes (
929 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
930 EFI_MEMORY_DESCRIPTOR
*MemoryMapStart
;
931 UINTN MemoryMapEntryCount
;
932 UINTN DescriptorSize
;
934 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
936 SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid
, (VOID
**)&MemoryAttributesTable
);
937 if (MemoryAttributesTable
== NULL
) {
938 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable - NULL\n"));
942 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable:\n"));
943 DEBUG ((DEBUG_INFO
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
944 DEBUG ((DEBUG_INFO
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
945 DEBUG ((DEBUG_INFO
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
947 MemoryMapEntryCount
= MemoryAttributesTable
->NumberOfEntries
;
948 DescriptorSize
= MemoryAttributesTable
->DescriptorSize
;
949 MemoryMapStart
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
950 MemoryMap
= MemoryMapStart
;
951 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
952 DEBUG ((DEBUG_INFO
, "Entry (0x%x)\n", MemoryMap
));
953 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", MemoryMap
->Type
));
954 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", MemoryMap
->PhysicalStart
));
955 DEBUG ((DEBUG_INFO
, " VirtualStart - 0x%016lx\n", MemoryMap
->VirtualStart
));
956 DEBUG ((DEBUG_INFO
, " NumberOfPages - 0x%016lx\n", MemoryMap
->NumberOfPages
));
957 DEBUG ((DEBUG_INFO
, " Attribute - 0x%016lx\n", MemoryMap
->Attribute
));
958 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
961 MemoryMap
= MemoryMapStart
;
962 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
963 DEBUG ((DEBUG_VERBOSE
, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", MemoryMap
->PhysicalStart
, MemoryMap
->NumberOfPages
));
964 switch (MemoryMap
->Type
) {
965 case EfiRuntimeServicesCode
:
966 SmmSetMemoryAttributes (
967 MemoryMap
->PhysicalStart
,
968 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
972 case EfiRuntimeServicesData
:
973 SmmSetMemoryAttributes (
974 MemoryMap
->PhysicalStart
,
975 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
980 SmmSetMemoryAttributes (
981 MemoryMap
->PhysicalStart
,
982 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
987 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
990 PatchSmmSaveStateMap ();
997 Sort memory map entries based upon PhysicalStart, from low to high.
999 @param MemoryMap A pointer to the buffer in which firmware places
1000 the current memory map.
1001 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
1002 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
1007 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
1008 IN UINTN MemoryMapSize
,
1009 IN UINTN DescriptorSize
1012 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
1013 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
1014 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
1015 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
1017 MemoryMapEntry
= MemoryMap
;
1018 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
1019 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
1020 while (MemoryMapEntry
< MemoryMapEnd
) {
1021 while (NextMemoryMapEntry
< MemoryMapEnd
) {
1022 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
1023 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
1024 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
1025 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
1028 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
1031 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
1032 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
1037 Return if a UEFI memory page should be marked as not present in SMM page table.
1038 If the memory map entries type is
1039 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
1040 EfiUnusableMemory, EfiACPIReclaimMemory, return TRUE.
1043 @param[in] MemoryMap A pointer to the memory descriptor.
1045 @return TRUE The memory described will be marked as not present in SMM page table.
1046 @return FALSE The memory described will not be marked as not present in SMM page table.
1049 IsUefiPageNotPresent (
1050 IN EFI_MEMORY_DESCRIPTOR
*MemoryMap
1053 switch (MemoryMap
->Type
) {
1056 case EfiBootServicesCode
:
1057 case EfiBootServicesData
:
1058 case EfiConventionalMemory
:
1059 case EfiUnusableMemory
:
1060 case EfiACPIReclaimMemory
:
1068 Merge continuous memory map entries whose type is
1069 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
1070 EfiUnusableMemory, EfiACPIReclaimMemory, because the memory described by
1071 these entries will be set as NOT present in SMM page table.
1073 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
1074 the current memory map.
1075 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
1076 MemoryMap buffer. On input, this is the size of
1077 the current memory map. On output,
1078 it is the size of new memory map after merge.
1079 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
1083 MergeMemoryMapForNotPresentEntry (
1084 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
1085 IN OUT UINTN
*MemoryMapSize
,
1086 IN UINTN DescriptorSize
1089 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
1090 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
1091 UINT64 MemoryBlockLength
;
1092 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
1093 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
1095 MemoryMapEntry
= MemoryMap
;
1096 NewMemoryMapEntry
= MemoryMap
;
1097 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
1098 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
1099 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
1100 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
1103 MemoryBlockLength
= (UINT64
) (EFI_PAGES_TO_SIZE((UINTN
)MemoryMapEntry
->NumberOfPages
));
1104 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
1105 IsUefiPageNotPresent(MemoryMapEntry
) && IsUefiPageNotPresent(NextMemoryMapEntry
) &&
1106 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
1107 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
1108 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
1109 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
1112 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
1115 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
1120 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
1121 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
1124 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
1130 This function caches the GCD memory map information.
1137 UINTN NumberOfDescriptors
;
1138 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemSpaceMap
;
1142 Status
= gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemSpaceMap
);
1143 if (EFI_ERROR (Status
)) {
1147 mGcdMemNumberOfDesc
= 0;
1148 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
1149 if (MemSpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeReserved
&&
1150 (MemSpaceMap
[Index
].Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
1151 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
)
1153 mGcdMemNumberOfDesc
++;
1157 mGcdMemSpace
= AllocateZeroPool (mGcdMemNumberOfDesc
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1158 ASSERT (mGcdMemSpace
!= NULL
);
1159 if (mGcdMemSpace
== NULL
) {
1160 mGcdMemNumberOfDesc
= 0;
1161 gBS
->FreePool (MemSpaceMap
);
1165 mGcdMemNumberOfDesc
= 0;
1166 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
1167 if (MemSpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeReserved
&&
1168 (MemSpaceMap
[Index
].Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
1169 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
)
1172 &mGcdMemSpace
[mGcdMemNumberOfDesc
],
1173 &MemSpaceMap
[Index
],
1174 sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR
)
1176 mGcdMemNumberOfDesc
++;
1180 gBS
->FreePool (MemSpaceMap
);
1184 Get UEFI MemoryAttributesTable.
1187 GetUefiMemoryAttributesTable (
1192 EFI_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
1193 UINTN MemoryAttributesTableSize
;
1195 Status
= EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid
, (VOID
**)&MemoryAttributesTable
);
1196 if (!EFI_ERROR (Status
) && (MemoryAttributesTable
!= NULL
)) {
1197 MemoryAttributesTableSize
= sizeof(EFI_MEMORY_ATTRIBUTES_TABLE
) + MemoryAttributesTable
->DescriptorSize
* MemoryAttributesTable
->NumberOfEntries
;
1198 mUefiMemoryAttributesTable
= AllocateCopyPool (MemoryAttributesTableSize
, MemoryAttributesTable
);
1199 ASSERT (mUefiMemoryAttributesTable
!= NULL
);
1204 This function caches the UEFI memory map information.
1213 UINT32 DescriptorVersion
;
1214 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1215 UINTN UefiMemoryMapSize
;
1217 DEBUG ((DEBUG_INFO
, "GetUefiMemoryMap\n"));
1219 UefiMemoryMapSize
= 0;
1221 Status
= gBS
->GetMemoryMap (
1225 &mUefiDescriptorSize
,
1228 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
1231 Status
= gBS
->AllocatePool (EfiBootServicesData
, UefiMemoryMapSize
, (VOID
**)&MemoryMap
);
1232 ASSERT (MemoryMap
!= NULL
);
1233 if (MemoryMap
== NULL
) {
1237 Status
= gBS
->GetMemoryMap (
1241 &mUefiDescriptorSize
,
1244 if (EFI_ERROR (Status
)) {
1245 gBS
->FreePool (MemoryMap
);
1248 } while (Status
== EFI_BUFFER_TOO_SMALL
);
1250 if (MemoryMap
== NULL
) {
1254 SortMemoryMap (MemoryMap
, UefiMemoryMapSize
, mUefiDescriptorSize
);
1255 MergeMemoryMapForNotPresentEntry (MemoryMap
, &UefiMemoryMapSize
, mUefiDescriptorSize
);
1257 mUefiMemoryMapSize
= UefiMemoryMapSize
;
1258 mUefiMemoryMap
= AllocateCopyPool (UefiMemoryMapSize
, MemoryMap
);
1259 ASSERT (mUefiMemoryMap
!= NULL
);
1261 gBS
->FreePool (MemoryMap
);
1264 // Get additional information from GCD memory map.
1269 // Get UEFI memory attributes table.
1271 GetUefiMemoryAttributesTable ();
1275 This function sets UEFI memory attribute according to UEFI memory map.
1277 The normal memory region is marked as not present, such as
1278 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
1279 EfiUnusableMemory, EfiACPIReclaimMemory.
1282 SetUefiMemMapAttributes (
1287 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1288 UINTN MemoryMapEntryCount
;
1290 EFI_MEMORY_DESCRIPTOR
*Entry
;
1292 DEBUG ((DEBUG_INFO
, "SetUefiMemMapAttributes\n"));
1294 if (mUefiMemoryMap
!= NULL
) {
1295 MemoryMapEntryCount
= mUefiMemoryMapSize
/mUefiDescriptorSize
;
1296 MemoryMap
= mUefiMemoryMap
;
1297 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
1298 if (IsUefiPageNotPresent(MemoryMap
)) {
1299 Status
= SmmSetMemoryAttributes (
1300 MemoryMap
->PhysicalStart
,
1301 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
1306 "UefiMemory protection: 0x%lx - 0x%lx %r\n",
1307 MemoryMap
->PhysicalStart
,
1308 MemoryMap
->PhysicalStart
+ (UINT64
)EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
1312 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, mUefiDescriptorSize
);
1316 // Do not free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().
1320 // Set untested memory as not present.
1322 if (mGcdMemSpace
!= NULL
) {
1323 for (Index
= 0; Index
< mGcdMemNumberOfDesc
; Index
++) {
1324 Status
= SmmSetMemoryAttributes (
1325 mGcdMemSpace
[Index
].BaseAddress
,
1326 mGcdMemSpace
[Index
].Length
,
1331 "GcdMemory protection: 0x%lx - 0x%lx %r\n",
1332 mGcdMemSpace
[Index
].BaseAddress
,
1333 mGcdMemSpace
[Index
].BaseAddress
+ mGcdMemSpace
[Index
].Length
,
1339 // Do not free mGcdMemSpace, it will be checked in IsSmmCommBufferForbiddenAddress().
1343 // Set UEFI runtime memory with EFI_MEMORY_RO as not present.
1345 if (mUefiMemoryAttributesTable
!= NULL
) {
1346 Entry
= (EFI_MEMORY_DESCRIPTOR
*)(mUefiMemoryAttributesTable
+ 1);
1347 for (Index
= 0; Index
< mUefiMemoryAttributesTable
->NumberOfEntries
; Index
++) {
1348 if (Entry
->Type
== EfiRuntimeServicesCode
|| Entry
->Type
== EfiRuntimeServicesData
) {
1349 if ((Entry
->Attribute
& EFI_MEMORY_RO
) != 0) {
1350 Status
= SmmSetMemoryAttributes (
1351 Entry
->PhysicalStart
,
1352 EFI_PAGES_TO_SIZE((UINTN
)Entry
->NumberOfPages
),
1357 "UefiMemoryAttribute protection: 0x%lx - 0x%lx %r\n",
1358 Entry
->PhysicalStart
,
1359 Entry
->PhysicalStart
+ (UINT64
)EFI_PAGES_TO_SIZE((UINTN
)Entry
->NumberOfPages
),
1364 Entry
= NEXT_MEMORY_DESCRIPTOR (Entry
, mUefiMemoryAttributesTable
->DescriptorSize
);
1368 // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
1373 Return if the Address is forbidden as SMM communication buffer.
1375 @param[in] Address the address to be checked
1377 @return TRUE The address is forbidden as SMM communication buffer.
1378 @return FALSE The address is allowed as SMM communication buffer.
1381 IsSmmCommBufferForbiddenAddress (
1385 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1386 UINTN MemoryMapEntryCount
;
1388 EFI_MEMORY_DESCRIPTOR
*Entry
;
1390 if (mUefiMemoryMap
!= NULL
) {
1391 MemoryMap
= mUefiMemoryMap
;
1392 MemoryMapEntryCount
= mUefiMemoryMapSize
/mUefiDescriptorSize
;
1393 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
1394 if (IsUefiPageNotPresent (MemoryMap
)) {
1395 if ((Address
>= MemoryMap
->PhysicalStart
) &&
1396 (Address
< MemoryMap
->PhysicalStart
+ EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
)) ) {
1400 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, mUefiDescriptorSize
);
1404 if (mGcdMemSpace
!= NULL
) {
1405 for (Index
= 0; Index
< mGcdMemNumberOfDesc
; Index
++) {
1406 if ((Address
>= mGcdMemSpace
[Index
].BaseAddress
) &&
1407 (Address
< mGcdMemSpace
[Index
].BaseAddress
+ mGcdMemSpace
[Index
].Length
) ) {
1413 if (mUefiMemoryAttributesTable
!= NULL
) {
1414 Entry
= (EFI_MEMORY_DESCRIPTOR
*)(mUefiMemoryAttributesTable
+ 1);
1415 for (Index
= 0; Index
< mUefiMemoryAttributesTable
->NumberOfEntries
; Index
++) {
1416 if (Entry
->Type
== EfiRuntimeServicesCode
|| Entry
->Type
== EfiRuntimeServicesData
) {
1417 if ((Entry
->Attribute
& EFI_MEMORY_RO
) != 0) {
1418 if ((Address
>= Entry
->PhysicalStart
) &&
1419 (Address
< Entry
->PhysicalStart
+ LShiftU64 (Entry
->NumberOfPages
, EFI_PAGE_SHIFT
))) {
1422 Entry
= NEXT_MEMORY_DESCRIPTOR (Entry
, mUefiMemoryAttributesTable
->DescriptorSize
);
1431 This function set given attributes of the memory region specified by
1432 BaseAddress and Length.
1434 @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1435 @param BaseAddress The physical address that is the start address of
1437 @param Length The size in bytes of the memory region.
1438 @param Attributes The bit mask of attributes to set for the memory
1441 @retval EFI_SUCCESS The attributes were set for the memory region.
1442 @retval EFI_INVALID_PARAMETER Length is zero.
1443 Attributes specified an illegal combination of
1444 attributes that cannot be set together.
1445 @retval EFI_UNSUPPORTED The processor does not support one or more
1446 bytes of the memory resource range specified
1447 by BaseAddress and Length.
1448 The bit mask of attributes is not supported for
1449 the memory resource range specified by
1450 BaseAddress and Length.
1455 EdkiiSmmSetMemoryAttributes (
1456 IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL
*This
,
1457 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1459 IN UINT64 Attributes
1462 return SmmSetMemoryAttributes (BaseAddress
, Length
, Attributes
);
1466 This function clears given attributes of the memory region specified by
1467 BaseAddress and Length.
1469 @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1470 @param BaseAddress The physical address that is the start address of
1472 @param Length The size in bytes of the memory region.
1473 @param Attributes The bit mask of attributes to clear for the memory
1476 @retval EFI_SUCCESS The attributes were cleared for the memory region.
1477 @retval EFI_INVALID_PARAMETER Length is zero.
1478 Attributes specified an illegal combination of
1479 attributes that cannot be cleared together.
1480 @retval EFI_UNSUPPORTED The processor does not support one or more
1481 bytes of the memory resource range specified
1482 by BaseAddress and Length.
1483 The bit mask of attributes is not supported for
1484 the memory resource range specified by
1485 BaseAddress and Length.
1490 EdkiiSmmClearMemoryAttributes (
1491 IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL
*This
,
1492 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1494 IN UINT64 Attributes
1497 return SmmClearMemoryAttributes (BaseAddress
, Length
, Attributes
);
1501 This function retrieves the attributes of the memory region specified by
1502 BaseAddress and Length. If different attributes are got from different part
1503 of the memory region, EFI_NO_MAPPING will be returned.
1505 @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1506 @param BaseAddress The physical address that is the start address of
1508 @param Length The size in bytes of the memory region.
1509 @param Attributes Pointer to attributes returned.
1511 @retval EFI_SUCCESS The attributes got for the memory region.
1512 @retval EFI_INVALID_PARAMETER Length is zero.
1514 @retval EFI_NO_MAPPING Attributes are not consistent cross the memory
1516 @retval EFI_UNSUPPORTED The processor does not support one or more
1517 bytes of the memory resource range specified
1518 by BaseAddress and Length.
1523 EdkiiSmmGetMemoryAttributes (
1524 IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL
*This
,
1525 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1527 OUT UINT64
*Attributes
1530 EFI_PHYSICAL_ADDRESS Address
;
1533 PAGE_ATTRIBUTE PageAttr
;
1536 if (Length
< SIZE_4KB
|| Attributes
== NULL
) {
1537 return EFI_INVALID_PARAMETER
;
1540 Size
= (INT64
)Length
;
1541 MemAttr
= (UINT64
)-1;
1545 PageEntry
= GetPageTableEntry (BaseAddress
, &PageAttr
);
1546 if (PageEntry
== NULL
|| PageAttr
== PageNone
) {
1547 return EFI_UNSUPPORTED
;
1551 // If the memory range is cross page table boundary, make sure they
1552 // share the same attribute. Return EFI_NO_MAPPING if not.
1554 *Attributes
= GetAttributesFromPageEntry (PageEntry
);
1555 if (MemAttr
!= (UINT64
)-1 && *Attributes
!= MemAttr
) {
1556 return EFI_NO_MAPPING
;
1561 Address
= *PageEntry
& ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
;
1562 Size
-= (SIZE_4KB
- (BaseAddress
- Address
));
1563 BaseAddress
+= (SIZE_4KB
- (BaseAddress
- Address
));
1567 Address
= *PageEntry
& ~mAddressEncMask
& PAGING_2M_ADDRESS_MASK_64
;
1568 Size
-= SIZE_2MB
- (BaseAddress
- Address
);
1569 BaseAddress
+= SIZE_2MB
- (BaseAddress
- Address
);
1573 Address
= *PageEntry
& ~mAddressEncMask
& PAGING_1G_ADDRESS_MASK_64
;
1574 Size
-= SIZE_1GB
- (BaseAddress
- Address
);
1575 BaseAddress
+= SIZE_1GB
- (BaseAddress
- Address
);
1579 return EFI_UNSUPPORTED
;
1582 MemAttr
= *Attributes
;