3 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #include "PiSmmCpuDxeSmm.h"
16 #define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
17 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
19 PAGE_ATTRIBUTE_TABLE mPageAttributeTable
[] = {
20 {Page4K
, SIZE_4KB
, PAGING_4K_ADDRESS_MASK_64
},
21 {Page2M
, SIZE_2MB
, PAGING_2M_ADDRESS_MASK_64
},
22 {Page1G
, SIZE_1GB
, PAGING_1G_ADDRESS_MASK_64
},
26 Return page table base.
28 @return page table base.
35 return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64
);
39 Return length according to page attributes.
41 @param[in] PageAttributes The page attribute of the page entry.
43 @return The length of page entry.
46 PageAttributeToLength (
47 IN PAGE_ATTRIBUTE PageAttribute
51 for (Index
= 0; Index
< sizeof(mPageAttributeTable
)/sizeof(mPageAttributeTable
[0]); Index
++) {
52 if (PageAttribute
== mPageAttributeTable
[Index
].Attribute
) {
53 return (UINTN
)mPageAttributeTable
[Index
].Length
;
60 Return address mask according to page attributes.
62 @param[in] PageAttributes The page attribute of the page entry.
64 @return The address mask of page entry.
68 IN PAGE_ATTRIBUTE PageAttribute
72 for (Index
= 0; Index
< sizeof(mPageAttributeTable
)/sizeof(mPageAttributeTable
[0]); Index
++) {
73 if (PageAttribute
== mPageAttributeTable
[Index
].Attribute
) {
74 return (UINTN
)mPageAttributeTable
[Index
].AddressMask
;
81 Return page table entry to match the address.
83 @param[in] Address The address to be checked.
84 @param[out] PageAttributes The page attribute of the page entry.
86 @return The page entry.
90 IN PHYSICAL_ADDRESS Address
,
91 OUT PAGE_ATTRIBUTE
*PageAttribute
103 Index4
= ((UINTN
)RShiftU64 (Address
, 39)) & PAGING_PAE_INDEX_MASK
;
104 Index3
= ((UINTN
)Address
>> 30) & PAGING_PAE_INDEX_MASK
;
105 Index2
= ((UINTN
)Address
>> 21) & PAGING_PAE_INDEX_MASK
;
106 Index1
= ((UINTN
)Address
>> 12) & PAGING_PAE_INDEX_MASK
;
108 if (sizeof(UINTN
) == sizeof(UINT64
)) {
109 L4PageTable
= (UINT64
*)GetPageTableBase ();
110 if (L4PageTable
[Index4
] == 0) {
111 *PageAttribute
= PageNone
;
115 L3PageTable
= (UINT64
*)(UINTN
)(L4PageTable
[Index4
] & PAGING_4K_ADDRESS_MASK_64
);
117 L3PageTable
= (UINT64
*)GetPageTableBase ();
119 if (L3PageTable
[Index3
] == 0) {
120 *PageAttribute
= PageNone
;
123 if ((L3PageTable
[Index3
] & IA32_PG_PS
) != 0) {
125 *PageAttribute
= Page1G
;
126 return &L3PageTable
[Index3
];
129 L2PageTable
= (UINT64
*)(UINTN
)(L3PageTable
[Index3
] & PAGING_4K_ADDRESS_MASK_64
);
130 if (L2PageTable
[Index2
] == 0) {
131 *PageAttribute
= PageNone
;
134 if ((L2PageTable
[Index2
] & IA32_PG_PS
) != 0) {
136 *PageAttribute
= Page2M
;
137 return &L2PageTable
[Index2
];
141 L1PageTable
= (UINT64
*)(UINTN
)(L2PageTable
[Index2
] & PAGING_4K_ADDRESS_MASK_64
);
142 if ((L1PageTable
[Index1
] == 0) && (Address
!= 0)) {
143 *PageAttribute
= PageNone
;
146 *PageAttribute
= Page4K
;
147 return &L1PageTable
[Index1
];
151 Return memory attributes of page entry.
153 @param[in] PageEntry The page entry.
155 @return Memory attributes of page entry.
158 GetAttributesFromPageEntry (
164 if ((*PageEntry
& IA32_PG_P
) == 0) {
165 Attributes
|= EFI_MEMORY_RP
;
167 if ((*PageEntry
& IA32_PG_RW
) == 0) {
168 Attributes
|= EFI_MEMORY_RO
;
170 if ((*PageEntry
& IA32_PG_NX
) != 0) {
171 Attributes
|= EFI_MEMORY_XP
;
177 Modify memory attributes of page entry.
179 @param[in] PageEntry The page entry.
180 @param[in] Attributes The bit mask of attributes to modify for the memory region.
181 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
182 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
185 ConvertPageEntryAttribute (
186 IN UINT64
*PageEntry
,
187 IN UINT64 Attributes
,
189 OUT BOOLEAN
*IsModified
192 UINT64 CurrentPageEntry
;
195 CurrentPageEntry
= *PageEntry
;
196 NewPageEntry
= CurrentPageEntry
;
197 if ((Attributes
& EFI_MEMORY_RP
) != 0) {
199 NewPageEntry
&= ~(UINT64
)IA32_PG_P
;
201 NewPageEntry
|= IA32_PG_P
;
204 if ((Attributes
& EFI_MEMORY_RO
) != 0) {
206 NewPageEntry
&= ~(UINT64
)IA32_PG_RW
;
208 NewPageEntry
|= IA32_PG_RW
;
211 if ((Attributes
& EFI_MEMORY_XP
) != 0) {
213 NewPageEntry
|= IA32_PG_NX
;
215 NewPageEntry
&= ~IA32_PG_NX
;
218 *PageEntry
= NewPageEntry
;
219 if (CurrentPageEntry
!= NewPageEntry
) {
221 DEBUG ((DEBUG_VERBOSE
, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry
));
222 DEBUG ((DEBUG_VERBOSE
, "->0x%lx\n", NewPageEntry
));
229 This function returns if there is need to split page entry.
231 @param[in] BaseAddress The base address to be checked.
232 @param[in] Length The length to be checked.
233 @param[in] PageEntry The page entry to be checked.
234 @param[in] PageAttribute The page attribute of the page entry.
236 @retval SplitAttributes on if there is need to split page entry.
240 IN PHYSICAL_ADDRESS BaseAddress
,
242 IN UINT64
*PageEntry
,
243 IN PAGE_ATTRIBUTE PageAttribute
246 UINT64 PageEntryLength
;
248 PageEntryLength
= PageAttributeToLength (PageAttribute
);
250 if (((BaseAddress
& (PageEntryLength
- 1)) == 0) && (Length
>= PageEntryLength
)) {
254 if (((BaseAddress
& PAGING_2M_MASK
) != 0) || (Length
< SIZE_2MB
)) {
262 This function splits one page entry to small page entries.
264 @param[in] PageEntry The page entry to be splitted.
265 @param[in] PageAttribute The page attribute of the page entry.
266 @param[in] SplitAttribute How to split the page entry.
268 @retval RETURN_SUCCESS The page entry is splitted.
269 @retval RETURN_UNSUPPORTED The page entry does not support to be splitted.
270 @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.
274 IN UINT64
*PageEntry
,
275 IN PAGE_ATTRIBUTE PageAttribute
,
276 IN PAGE_ATTRIBUTE SplitAttribute
280 UINT64
*NewPageEntry
;
283 ASSERT (PageAttribute
== Page2M
|| PageAttribute
== Page1G
);
285 if (PageAttribute
== Page2M
) {
289 ASSERT (SplitAttribute
== Page4K
);
290 if (SplitAttribute
== Page4K
) {
291 NewPageEntry
= AllocatePageTableMemory (1);
292 DEBUG ((DEBUG_VERBOSE
, "Split - 0x%x\n", NewPageEntry
));
293 if (NewPageEntry
== NULL
) {
294 return RETURN_OUT_OF_RESOURCES
;
296 BaseAddress
= *PageEntry
& PAGING_2M_ADDRESS_MASK_64
;
297 for (Index
= 0; Index
< SIZE_4KB
/ sizeof(UINT64
); Index
++) {
298 NewPageEntry
[Index
] = BaseAddress
+ SIZE_4KB
* Index
+ ((*PageEntry
) & PAGE_PROGATE_BITS
);
300 (*PageEntry
) = (UINT64
)(UINTN
)NewPageEntry
+ ((*PageEntry
) & PAGE_PROGATE_BITS
);
301 return RETURN_SUCCESS
;
303 return RETURN_UNSUPPORTED
;
305 } else if (PageAttribute
== Page1G
) {
308 // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K to get more compact page table.
310 ASSERT (SplitAttribute
== Page2M
|| SplitAttribute
== Page4K
);
311 if ((SplitAttribute
== Page2M
|| SplitAttribute
== Page4K
)) {
312 NewPageEntry
= AllocatePageTableMemory (1);
313 DEBUG ((DEBUG_VERBOSE
, "Split - 0x%x\n", NewPageEntry
));
314 if (NewPageEntry
== NULL
) {
315 return RETURN_OUT_OF_RESOURCES
;
317 BaseAddress
= *PageEntry
& PAGING_1G_ADDRESS_MASK_64
;
318 for (Index
= 0; Index
< SIZE_4KB
/ sizeof(UINT64
); Index
++) {
319 NewPageEntry
[Index
] = BaseAddress
+ SIZE_2MB
* Index
+ IA32_PG_PS
+ ((*PageEntry
) & PAGE_PROGATE_BITS
);
321 (*PageEntry
) = (UINT64
)(UINTN
)NewPageEntry
+ ((*PageEntry
) & PAGE_PROGATE_BITS
);
322 return RETURN_SUCCESS
;
324 return RETURN_UNSUPPORTED
;
327 return RETURN_UNSUPPORTED
;
332 This function modifies the page attributes for the memory region specified by BaseAddress and
333 Length from their current attributes to the attributes specified by Attributes.
335 Caller should make sure BaseAddress and Length is at page boundary.
337 @param[in] BaseAddress The physical address that is the start address of a memory region.
338 @param[in] Length The size in bytes of the memory region.
339 @param[in] Attributes The bit mask of attributes to modify for the memory region.
340 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
341 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
342 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
344 @retval RETURN_SUCCESS The attributes were modified for the memory region.
345 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
346 BaseAddress and Length cannot be modified.
347 @retval RETURN_INVALID_PARAMETER Length is zero.
348 Attributes specified an illegal combination of attributes that
349 cannot be set together.
350 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
351 the memory resource range.
352 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory
353 resource range specified by BaseAddress and Length.
354 The bit mask of attributes is not support for the memory resource
355 range specified by BaseAddress and Length.
359 ConvertMemoryPageAttributes (
360 IN PHYSICAL_ADDRESS BaseAddress
,
362 IN UINT64 Attributes
,
364 OUT BOOLEAN
*IsSplitted
, OPTIONAL
365 OUT BOOLEAN
*IsModified OPTIONAL
369 PAGE_ATTRIBUTE PageAttribute
;
370 UINTN PageEntryLength
;
371 PAGE_ATTRIBUTE SplitAttribute
;
372 RETURN_STATUS Status
;
373 BOOLEAN IsEntryModified
;
375 ASSERT (Attributes
!= 0);
376 ASSERT ((Attributes
& ~(EFI_MEMORY_RP
| EFI_MEMORY_RO
| EFI_MEMORY_XP
)) == 0);
378 ASSERT ((BaseAddress
& (SIZE_4KB
- 1)) == 0);
379 ASSERT ((Length
& (SIZE_4KB
- 1)) == 0);
382 return RETURN_INVALID_PARAMETER
;
385 // DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));
387 if (IsSplitted
!= NULL
) {
390 if (IsModified
!= NULL
) {
395 // Below logic is to check 2M/4K page to make sure we donot waist memory.
397 while (Length
!= 0) {
398 PageEntry
= GetPageTableEntry (BaseAddress
, &PageAttribute
);
399 if (PageEntry
== NULL
) {
400 return RETURN_UNSUPPORTED
;
402 PageEntryLength
= PageAttributeToLength (PageAttribute
);
403 SplitAttribute
= NeedSplitPage (BaseAddress
, Length
, PageEntry
, PageAttribute
);
404 if (SplitAttribute
== PageNone
) {
405 ConvertPageEntryAttribute (PageEntry
, Attributes
, IsSet
, &IsEntryModified
);
406 if (IsEntryModified
) {
407 if (IsModified
!= NULL
) {
412 // Convert success, move to next
414 BaseAddress
+= PageEntryLength
;
415 Length
-= PageEntryLength
;
417 Status
= SplitPage (PageEntry
, PageAttribute
, SplitAttribute
);
418 if (RETURN_ERROR (Status
)) {
419 return RETURN_UNSUPPORTED
;
421 if (IsSplitted
!= NULL
) {
424 if (IsModified
!= NULL
) {
428 // Just split current page
429 // Convert success in next around
434 return RETURN_SUCCESS
;
438 FlushTlb on current processor.
440 @param[in,out] Buffer Pointer to private data buffer.
444 FlushTlbOnCurrentProcessor (
452 FlushTlb for all processors.
461 FlushTlbOnCurrentProcessor (NULL
);
463 for (Index
= 0; Index
< gSmst
->NumberOfCpus
; Index
++) {
464 if (Index
!= gSmst
->CurrentlyExecutingCpu
) {
465 // Force to start up AP in blocking mode,
466 SmmBlockingStartupThisAp (FlushTlbOnCurrentProcessor
, Index
, NULL
);
467 // Do not check return status, because AP might not be present in some corner cases.
473 This function sets the attributes for the memory region specified by BaseAddress and
474 Length from their current attributes to the attributes specified by Attributes.
476 @param[in] BaseAddress The physical address that is the start address of a memory region.
477 @param[in] Length The size in bytes of the memory region.
478 @param[in] Attributes The bit mask of attributes to set for the memory region.
479 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
481 @retval EFI_SUCCESS The attributes were set for the memory region.
482 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
483 BaseAddress and Length cannot be modified.
484 @retval EFI_INVALID_PARAMETER Length is zero.
485 Attributes specified an illegal combination of attributes that
486 cannot be set together.
487 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
488 the memory resource range.
489 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
490 resource range specified by BaseAddress and Length.
491 The bit mask of attributes is not support for the memory resource
492 range specified by BaseAddress and Length.
497 SmmSetMemoryAttributesEx (
498 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
500 IN UINT64 Attributes
,
501 OUT BOOLEAN
*IsSplitted OPTIONAL
507 Status
= ConvertMemoryPageAttributes (BaseAddress
, Length
, Attributes
, TRUE
, IsSplitted
, &IsModified
);
508 if (!EFI_ERROR(Status
)) {
511 // Flush TLB as last step
521 This function clears the attributes for the memory region specified by BaseAddress and
522 Length from their current attributes to the attributes specified by Attributes.
524 @param[in] BaseAddress The physical address that is the start address of a memory region.
525 @param[in] Length The size in bytes of the memory region.
526 @param[in] Attributes The bit mask of attributes to clear for the memory region.
527 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
529 @retval EFI_SUCCESS The attributes were cleared for the memory region.
530 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
531 BaseAddress and Length cannot be modified.
532 @retval EFI_INVALID_PARAMETER Length is zero.
533 Attributes specified an illegal combination of attributes that
534 cannot be set together.
535 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
536 the memory resource range.
537 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
538 resource range specified by BaseAddress and Length.
539 The bit mask of attributes is not support for the memory resource
540 range specified by BaseAddress and Length.
545 SmmClearMemoryAttributesEx (
546 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
548 IN UINT64 Attributes
,
549 OUT BOOLEAN
*IsSplitted OPTIONAL
555 Status
= ConvertMemoryPageAttributes (BaseAddress
, Length
, Attributes
, FALSE
, IsSplitted
, &IsModified
);
556 if (!EFI_ERROR(Status
)) {
559 // Flush TLB as last step
569 This function sets the attributes for the memory region specified by BaseAddress and
570 Length from their current attributes to the attributes specified by Attributes.
572 @param[in] BaseAddress The physical address that is the start address of a memory region.
573 @param[in] Length The size in bytes of the memory region.
574 @param[in] Attributes The bit mask of attributes to set for the memory region.
576 @retval EFI_SUCCESS The attributes were set for the memory region.
577 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
578 BaseAddress and Length cannot be modified.
579 @retval EFI_INVALID_PARAMETER Length is zero.
580 Attributes specified an illegal combination of attributes that
581 cannot be set together.
582 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
583 the memory resource range.
584 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
585 resource range specified by BaseAddress and Length.
586 The bit mask of attributes is not support for the memory resource
587 range specified by BaseAddress and Length.
592 SmmSetMemoryAttributes (
593 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
598 return SmmSetMemoryAttributesEx (BaseAddress
, Length
, Attributes
, NULL
);
602 This function clears the attributes for the memory region specified by BaseAddress and
603 Length from their current attributes to the attributes specified by Attributes.
605 @param[in] BaseAddress The physical address that is the start address of a memory region.
606 @param[in] Length The size in bytes of the memory region.
607 @param[in] Attributes The bit mask of attributes to clear for the memory region.
609 @retval EFI_SUCCESS The attributes were cleared for the memory region.
610 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
611 BaseAddress and Length cannot be modified.
612 @retval EFI_INVALID_PARAMETER Length is zero.
613 Attributes specified an illegal combination of attributes that
614 cannot be set together.
615 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
616 the memory resource range.
617 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
618 resource range specified by BaseAddress and Length.
619 The bit mask of attributes is not support for the memory resource
620 range specified by BaseAddress and Length.
625 SmmClearMemoryAttributes (
626 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
631 return SmmClearMemoryAttributesEx (BaseAddress
, Length
, Attributes
, NULL
);
637 Retrieves a pointer to the system configuration table from the SMM System Table
638 based on a specified GUID.
640 @param[in] TableGuid The pointer to table's GUID type.
641 @param[out] Table The pointer to the table associated with TableGuid in the EFI System Table.
643 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
644 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.
649 SmmGetSystemConfigurationTable (
650 IN EFI_GUID
*TableGuid
,
656 ASSERT (TableGuid
!= NULL
);
657 ASSERT (Table
!= NULL
);
660 for (Index
= 0; Index
< gSmst
->NumberOfTableEntries
; Index
++) {
661 if (CompareGuid (TableGuid
, &(gSmst
->SmmConfigurationTable
[Index
].VendorGuid
))) {
662 *Table
= gSmst
->SmmConfigurationTable
[Index
].VendorTable
;
667 return EFI_NOT_FOUND
;
671 This function sets SMM save state buffer to be RW and XP.
674 PatchSmmSaveStateMap (
683 TileCodeSize
= GetSmiHandlerSize ();
684 TileCodeSize
= ALIGN_VALUE(TileCodeSize
, SIZE_4KB
);
685 TileDataSize
= sizeof (SMRAM_SAVE_STATE_MAP
) + sizeof (PROCESSOR_SMM_DESCRIPTOR
);
686 TileDataSize
= ALIGN_VALUE(TileDataSize
, SIZE_4KB
);
687 TileSize
= TileDataSize
+ TileCodeSize
- 1;
688 TileSize
= 2 * GetPowerOfTwo32 ((UINT32
)TileSize
);
690 DEBUG ((DEBUG_INFO
, "PatchSmmSaveStateMap:\n"));
691 for (Index
= 0; Index
< mMaxNumberOfCpus
- 1; Index
++) {
695 SmmSetMemoryAttributes (
696 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
,
700 SmmClearMemoryAttributes (
701 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
,
709 SmmClearMemoryAttributes (
710 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
711 TileSize
- TileCodeSize
,
714 SmmSetMemoryAttributes (
715 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
716 TileSize
- TileCodeSize
,
724 SmmSetMemoryAttributes (
725 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
,
729 SmmClearMemoryAttributes (
730 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
,
738 SmmClearMemoryAttributes (
739 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
740 SIZE_32KB
- TileCodeSize
,
743 SmmSetMemoryAttributes (
744 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
745 SIZE_32KB
- TileCodeSize
,
751 This function sets GDT/IDT buffer to be RO and XP.
758 EFI_PHYSICAL_ADDRESS BaseAddress
;
764 DEBUG ((DEBUG_INFO
, "PatchGdtIdtMap - GDT:\n"));
766 BaseAddress
= mGdtBuffer
;
767 Size
= ALIGN_VALUE(mGdtBufferSize
, SIZE_4KB
);
768 SmmSetMemoryAttributes (
773 SmmSetMemoryAttributes (
782 DEBUG ((DEBUG_INFO
, "PatchGdtIdtMap - IDT:\n"));
784 BaseAddress
= gcSmiIdtr
.Base
;
785 Size
= ALIGN_VALUE(gcSmiIdtr
.Limit
+ 1, SIZE_4KB
);
786 SmmSetMemoryAttributes (
791 SmmSetMemoryAttributes (
799 This function sets memory attribute according to MemoryAttributesTable.
802 SetMemMapAttributes (
806 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
807 EFI_MEMORY_DESCRIPTOR
*MemoryMapStart
;
808 UINTN MemoryMapEntryCount
;
809 UINTN DescriptorSize
;
811 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
813 SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid
, (VOID
**)&MemoryAttributesTable
);
814 if (MemoryAttributesTable
== NULL
) {
815 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable - NULL\n"));
819 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable:\n"));
820 DEBUG ((DEBUG_INFO
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
821 DEBUG ((DEBUG_INFO
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
822 DEBUG ((DEBUG_INFO
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
824 MemoryMapEntryCount
= MemoryAttributesTable
->NumberOfEntries
;
825 DescriptorSize
= MemoryAttributesTable
->DescriptorSize
;
826 MemoryMapStart
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
827 MemoryMap
= MemoryMapStart
;
828 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
829 DEBUG ((DEBUG_INFO
, "Entry (0x%x)\n", MemoryMap
));
830 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", MemoryMap
->Type
));
831 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", MemoryMap
->PhysicalStart
));
832 DEBUG ((DEBUG_INFO
, " VirtualStart - 0x%016lx\n", MemoryMap
->VirtualStart
));
833 DEBUG ((DEBUG_INFO
, " NumberOfPages - 0x%016lx\n", MemoryMap
->NumberOfPages
));
834 DEBUG ((DEBUG_INFO
, " Attribute - 0x%016lx\n", MemoryMap
->Attribute
));
835 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
838 MemoryMap
= MemoryMapStart
;
839 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
840 DEBUG ((DEBUG_VERBOSE
, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", MemoryMap
->PhysicalStart
, MemoryMap
->NumberOfPages
));
841 switch (MemoryMap
->Type
) {
842 case EfiRuntimeServicesCode
:
843 SmmSetMemoryAttributes (
844 MemoryMap
->PhysicalStart
,
845 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
849 case EfiRuntimeServicesData
:
850 SmmSetMemoryAttributes (
851 MemoryMap
->PhysicalStart
,
852 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
857 SmmSetMemoryAttributes (
858 MemoryMap
->PhysicalStart
,
859 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
864 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
867 PatchSmmSaveStateMap ();