3 Copyright (c) 2016 - 2018, 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"
17 // attributes for reserved memory before it is promoted to system memory
19 #define EFI_MEMORY_PRESENT 0x0100000000000000ULL
20 #define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL
21 #define EFI_MEMORY_TESTED 0x0400000000000000ULL
23 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
24 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
26 EFI_MEMORY_DESCRIPTOR
*mUefiMemoryMap
;
27 UINTN mUefiMemoryMapSize
;
28 UINTN mUefiDescriptorSize
;
30 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*mGcdMemSpace
= NULL
;
31 UINTN mGcdMemNumberOfDesc
= 0;
33 EFI_MEMORY_ATTRIBUTES_TABLE
*mUefiMemoryAttributesTable
= NULL
;
35 PAGE_ATTRIBUTE_TABLE mPageAttributeTable
[] = {
36 {Page4K
, SIZE_4KB
, PAGING_4K_ADDRESS_MASK_64
},
37 {Page2M
, SIZE_2MB
, PAGING_2M_ADDRESS_MASK_64
},
38 {Page1G
, SIZE_1GB
, PAGING_1G_ADDRESS_MASK_64
},
42 Return page table base.
44 @return page table base.
51 return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64
);
55 Return length according to page attributes.
57 @param[in] PageAttributes The page attribute of the page entry.
59 @return The length of page entry.
62 PageAttributeToLength (
63 IN PAGE_ATTRIBUTE PageAttribute
67 for (Index
= 0; Index
< sizeof(mPageAttributeTable
)/sizeof(mPageAttributeTable
[0]); Index
++) {
68 if (PageAttribute
== mPageAttributeTable
[Index
].Attribute
) {
69 return (UINTN
)mPageAttributeTable
[Index
].Length
;
76 Return address mask according to page attributes.
78 @param[in] PageAttributes The page attribute of the page entry.
80 @return The address mask of page entry.
84 IN PAGE_ATTRIBUTE PageAttribute
88 for (Index
= 0; Index
< sizeof(mPageAttributeTable
)/sizeof(mPageAttributeTable
[0]); Index
++) {
89 if (PageAttribute
== mPageAttributeTable
[Index
].Attribute
) {
90 return (UINTN
)mPageAttributeTable
[Index
].AddressMask
;
97 Return page table entry to match the address.
99 @param[in] Address The address to be checked.
100 @param[out] PageAttributes The page attribute of the page entry.
102 @return The page entry.
106 IN PHYSICAL_ADDRESS Address
,
107 OUT PAGE_ATTRIBUTE
*PageAttribute
119 Index4
= ((UINTN
)RShiftU64 (Address
, 39)) & PAGING_PAE_INDEX_MASK
;
120 Index3
= ((UINTN
)Address
>> 30) & PAGING_PAE_INDEX_MASK
;
121 Index2
= ((UINTN
)Address
>> 21) & PAGING_PAE_INDEX_MASK
;
122 Index1
= ((UINTN
)Address
>> 12) & PAGING_PAE_INDEX_MASK
;
124 if (sizeof(UINTN
) == sizeof(UINT64
)) {
125 L4PageTable
= (UINT64
*)GetPageTableBase ();
126 if (L4PageTable
[Index4
] == 0) {
127 *PageAttribute
= PageNone
;
131 L3PageTable
= (UINT64
*)(UINTN
)(L4PageTable
[Index4
] & ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
);
133 L3PageTable
= (UINT64
*)GetPageTableBase ();
135 if (L3PageTable
[Index3
] == 0) {
136 *PageAttribute
= PageNone
;
139 if ((L3PageTable
[Index3
] & IA32_PG_PS
) != 0) {
141 *PageAttribute
= Page1G
;
142 return &L3PageTable
[Index3
];
145 L2PageTable
= (UINT64
*)(UINTN
)(L3PageTable
[Index3
] & ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
);
146 if (L2PageTable
[Index2
] == 0) {
147 *PageAttribute
= PageNone
;
150 if ((L2PageTable
[Index2
] & IA32_PG_PS
) != 0) {
152 *PageAttribute
= Page2M
;
153 return &L2PageTable
[Index2
];
157 L1PageTable
= (UINT64
*)(UINTN
)(L2PageTable
[Index2
] & ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
);
158 if ((L1PageTable
[Index1
] == 0) && (Address
!= 0)) {
159 *PageAttribute
= PageNone
;
162 *PageAttribute
= Page4K
;
163 return &L1PageTable
[Index1
];
167 Return memory attributes of page entry.
169 @param[in] PageEntry The page entry.
171 @return Memory attributes of page entry.
174 GetAttributesFromPageEntry (
180 if ((*PageEntry
& IA32_PG_P
) == 0) {
181 Attributes
|= EFI_MEMORY_RP
;
183 if ((*PageEntry
& IA32_PG_RW
) == 0) {
184 Attributes
|= EFI_MEMORY_RO
;
186 if ((*PageEntry
& IA32_PG_NX
) != 0) {
187 Attributes
|= EFI_MEMORY_XP
;
193 Modify memory attributes of page entry.
195 @param[in] PageEntry The page entry.
196 @param[in] Attributes The bit mask of attributes to modify for the memory region.
197 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
198 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
201 ConvertPageEntryAttribute (
202 IN UINT64
*PageEntry
,
203 IN UINT64 Attributes
,
205 OUT BOOLEAN
*IsModified
208 UINT64 CurrentPageEntry
;
211 CurrentPageEntry
= *PageEntry
;
212 NewPageEntry
= CurrentPageEntry
;
213 if ((Attributes
& EFI_MEMORY_RP
) != 0) {
215 NewPageEntry
&= ~(UINT64
)IA32_PG_P
;
217 NewPageEntry
|= IA32_PG_P
;
220 if ((Attributes
& EFI_MEMORY_RO
) != 0) {
222 NewPageEntry
&= ~(UINT64
)IA32_PG_RW
;
224 NewPageEntry
|= IA32_PG_RW
;
227 if ((Attributes
& EFI_MEMORY_XP
) != 0) {
230 NewPageEntry
|= IA32_PG_NX
;
232 NewPageEntry
&= ~IA32_PG_NX
;
236 *PageEntry
= NewPageEntry
;
237 if (CurrentPageEntry
!= NewPageEntry
) {
239 DEBUG ((DEBUG_VERBOSE
, "ConvertPageEntryAttribute 0x%lx", CurrentPageEntry
));
240 DEBUG ((DEBUG_VERBOSE
, "->0x%lx\n", NewPageEntry
));
247 This function returns if there is need to split page entry.
249 @param[in] BaseAddress The base address to be checked.
250 @param[in] Length The length to be checked.
251 @param[in] PageEntry The page entry to be checked.
252 @param[in] PageAttribute The page attribute of the page entry.
254 @retval SplitAttributes on if there is need to split page entry.
258 IN PHYSICAL_ADDRESS BaseAddress
,
260 IN UINT64
*PageEntry
,
261 IN PAGE_ATTRIBUTE PageAttribute
264 UINT64 PageEntryLength
;
266 PageEntryLength
= PageAttributeToLength (PageAttribute
);
268 if (((BaseAddress
& (PageEntryLength
- 1)) == 0) && (Length
>= PageEntryLength
)) {
272 if (((BaseAddress
& PAGING_2M_MASK
) != 0) || (Length
< SIZE_2MB
)) {
280 This function splits one page entry to small page entries.
282 @param[in] PageEntry The page entry to be splitted.
283 @param[in] PageAttribute The page attribute of the page entry.
284 @param[in] SplitAttribute How to split the page entry.
286 @retval RETURN_SUCCESS The page entry is splitted.
287 @retval RETURN_UNSUPPORTED The page entry does not support to be splitted.
288 @retval RETURN_OUT_OF_RESOURCES No resource to split page entry.
292 IN UINT64
*PageEntry
,
293 IN PAGE_ATTRIBUTE PageAttribute
,
294 IN PAGE_ATTRIBUTE SplitAttribute
298 UINT64
*NewPageEntry
;
301 ASSERT (PageAttribute
== Page2M
|| PageAttribute
== Page1G
);
303 if (PageAttribute
== Page2M
) {
307 ASSERT (SplitAttribute
== Page4K
);
308 if (SplitAttribute
== Page4K
) {
309 NewPageEntry
= AllocatePageTableMemory (1);
310 DEBUG ((DEBUG_VERBOSE
, "Split - 0x%x\n", NewPageEntry
));
311 if (NewPageEntry
== NULL
) {
312 return RETURN_OUT_OF_RESOURCES
;
314 BaseAddress
= *PageEntry
& PAGING_2M_ADDRESS_MASK_64
;
315 for (Index
= 0; Index
< SIZE_4KB
/ sizeof(UINT64
); Index
++) {
316 NewPageEntry
[Index
] = (BaseAddress
+ SIZE_4KB
* Index
) | mAddressEncMask
| ((*PageEntry
) & PAGE_PROGATE_BITS
);
318 (*PageEntry
) = (UINT64
)(UINTN
)NewPageEntry
| mAddressEncMask
| PAGE_ATTRIBUTE_BITS
;
319 return RETURN_SUCCESS
;
321 return RETURN_UNSUPPORTED
;
323 } else if (PageAttribute
== Page1G
) {
326 // No need support 1G->4K directly, we should use 1G->2M, then 2M->4K to get more compact page table.
328 ASSERT (SplitAttribute
== Page2M
|| SplitAttribute
== Page4K
);
329 if ((SplitAttribute
== Page2M
|| SplitAttribute
== Page4K
)) {
330 NewPageEntry
= AllocatePageTableMemory (1);
331 DEBUG ((DEBUG_VERBOSE
, "Split - 0x%x\n", NewPageEntry
));
332 if (NewPageEntry
== NULL
) {
333 return RETURN_OUT_OF_RESOURCES
;
335 BaseAddress
= *PageEntry
& PAGING_1G_ADDRESS_MASK_64
;
336 for (Index
= 0; Index
< SIZE_4KB
/ sizeof(UINT64
); Index
++) {
337 NewPageEntry
[Index
] = (BaseAddress
+ SIZE_2MB
* Index
) | mAddressEncMask
| IA32_PG_PS
| ((*PageEntry
) & PAGE_PROGATE_BITS
);
339 (*PageEntry
) = (UINT64
)(UINTN
)NewPageEntry
| mAddressEncMask
| PAGE_ATTRIBUTE_BITS
;
340 return RETURN_SUCCESS
;
342 return RETURN_UNSUPPORTED
;
345 return RETURN_UNSUPPORTED
;
350 This function modifies the page attributes for the memory region specified by BaseAddress and
351 Length from their current attributes to the attributes specified by Attributes.
353 Caller should make sure BaseAddress and Length is at page boundary.
355 @param[in] BaseAddress The physical address that is the start address of a memory region.
356 @param[in] Length The size in bytes of the memory region.
357 @param[in] Attributes The bit mask of attributes to modify for the memory region.
358 @param[in] IsSet TRUE means to set attributes. FALSE means to clear attributes.
359 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
360 @param[out] IsModified TRUE means page table modified. FALSE means page table not modified.
362 @retval RETURN_SUCCESS The attributes were modified for the memory region.
363 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
364 BaseAddress and Length cannot be modified.
365 @retval RETURN_INVALID_PARAMETER Length is zero.
366 Attributes specified an illegal combination of attributes that
367 cannot be set together.
368 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
369 the memory resource range.
370 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory
371 resource range specified by BaseAddress and Length.
372 The bit mask of attributes is not support for the memory resource
373 range specified by BaseAddress and Length.
377 ConvertMemoryPageAttributes (
378 IN PHYSICAL_ADDRESS BaseAddress
,
380 IN UINT64 Attributes
,
382 OUT BOOLEAN
*IsSplitted
, OPTIONAL
383 OUT BOOLEAN
*IsModified OPTIONAL
387 PAGE_ATTRIBUTE PageAttribute
;
388 UINTN PageEntryLength
;
389 PAGE_ATTRIBUTE SplitAttribute
;
390 RETURN_STATUS Status
;
391 BOOLEAN IsEntryModified
;
392 EFI_PHYSICAL_ADDRESS MaximumSupportMemAddress
;
394 ASSERT (Attributes
!= 0);
395 ASSERT ((Attributes
& ~(EFI_MEMORY_RP
| EFI_MEMORY_RO
| EFI_MEMORY_XP
)) == 0);
397 ASSERT ((BaseAddress
& (SIZE_4KB
- 1)) == 0);
398 ASSERT ((Length
& (SIZE_4KB
- 1)) == 0);
401 return RETURN_INVALID_PARAMETER
;
404 MaximumSupportMemAddress
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)(LShiftU64 (1, mPhysicalAddressBits
) - 1);
405 if (BaseAddress
> MaximumSupportMemAddress
) {
406 return RETURN_UNSUPPORTED
;
408 if (Length
> MaximumSupportMemAddress
) {
409 return RETURN_UNSUPPORTED
;
411 if ((Length
!= 0) && (BaseAddress
> MaximumSupportMemAddress
- (Length
- 1))) {
412 return RETURN_UNSUPPORTED
;
415 // DEBUG ((DEBUG_ERROR, "ConvertMemoryPageAttributes(%x) - %016lx, %016lx, %02lx\n", IsSet, BaseAddress, Length, Attributes));
417 if (IsSplitted
!= NULL
) {
420 if (IsModified
!= NULL
) {
425 // Below logic is to check 2M/4K page to make sure we donot waist memory.
427 while (Length
!= 0) {
428 PageEntry
= GetPageTableEntry (BaseAddress
, &PageAttribute
);
429 if (PageEntry
== NULL
) {
430 return RETURN_UNSUPPORTED
;
432 PageEntryLength
= PageAttributeToLength (PageAttribute
);
433 SplitAttribute
= NeedSplitPage (BaseAddress
, Length
, PageEntry
, PageAttribute
);
434 if (SplitAttribute
== PageNone
) {
435 ConvertPageEntryAttribute (PageEntry
, Attributes
, IsSet
, &IsEntryModified
);
436 if (IsEntryModified
) {
437 if (IsModified
!= NULL
) {
442 // Convert success, move to next
444 BaseAddress
+= PageEntryLength
;
445 Length
-= PageEntryLength
;
447 Status
= SplitPage (PageEntry
, PageAttribute
, SplitAttribute
);
448 if (RETURN_ERROR (Status
)) {
449 return RETURN_UNSUPPORTED
;
451 if (IsSplitted
!= NULL
) {
454 if (IsModified
!= NULL
) {
458 // Just split current page
459 // Convert success in next around
464 return RETURN_SUCCESS
;
468 FlushTlb on current processor.
470 @param[in,out] Buffer Pointer to private data buffer.
474 FlushTlbOnCurrentProcessor (
482 FlushTlb for all processors.
491 FlushTlbOnCurrentProcessor (NULL
);
493 for (Index
= 0; Index
< gSmst
->NumberOfCpus
; Index
++) {
494 if (Index
!= gSmst
->CurrentlyExecutingCpu
) {
495 // Force to start up AP in blocking mode,
496 SmmBlockingStartupThisAp (FlushTlbOnCurrentProcessor
, Index
, NULL
);
497 // Do not check return status, because AP might not be present in some corner cases.
503 This function sets the attributes for the memory region specified by BaseAddress and
504 Length from their current attributes to the attributes specified by Attributes.
506 @param[in] BaseAddress The physical address that is the start address of a memory region.
507 @param[in] Length The size in bytes of the memory region.
508 @param[in] Attributes The bit mask of attributes to set for the memory region.
509 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
511 @retval EFI_SUCCESS The attributes were set for the memory region.
512 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
513 BaseAddress and Length cannot be modified.
514 @retval EFI_INVALID_PARAMETER Length is zero.
515 Attributes specified an illegal combination of attributes that
516 cannot be set together.
517 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
518 the memory resource range.
519 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
520 resource range specified by BaseAddress and Length.
521 The bit mask of attributes is not support for the memory resource
522 range specified by BaseAddress and Length.
527 SmmSetMemoryAttributesEx (
528 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
530 IN UINT64 Attributes
,
531 OUT BOOLEAN
*IsSplitted OPTIONAL
537 Status
= ConvertMemoryPageAttributes (BaseAddress
, Length
, Attributes
, TRUE
, IsSplitted
, &IsModified
);
538 if (!EFI_ERROR(Status
)) {
541 // Flush TLB as last step
551 This function clears the attributes for the memory region specified by BaseAddress and
552 Length from their current attributes to the attributes specified by Attributes.
554 @param[in] BaseAddress The physical address that is the start address of a memory region.
555 @param[in] Length The size in bytes of the memory region.
556 @param[in] Attributes The bit mask of attributes to clear for the memory region.
557 @param[out] IsSplitted TRUE means page table splitted. FALSE means page table not splitted.
559 @retval EFI_SUCCESS The attributes were cleared for the memory region.
560 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
561 BaseAddress and Length cannot be modified.
562 @retval EFI_INVALID_PARAMETER Length is zero.
563 Attributes specified an illegal combination of attributes that
564 cannot be cleared together.
565 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
566 the memory resource range.
567 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
568 resource range specified by BaseAddress and Length.
569 The bit mask of attributes is not supported for the memory resource
570 range specified by BaseAddress and Length.
575 SmmClearMemoryAttributesEx (
576 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
578 IN UINT64 Attributes
,
579 OUT BOOLEAN
*IsSplitted OPTIONAL
585 Status
= ConvertMemoryPageAttributes (BaseAddress
, Length
, Attributes
, FALSE
, IsSplitted
, &IsModified
);
586 if (!EFI_ERROR(Status
)) {
589 // Flush TLB as last step
599 This function sets the attributes for the memory region specified by BaseAddress and
600 Length from their current attributes to the attributes specified by Attributes.
602 @param[in] BaseAddress The physical address that is the start address of a memory region.
603 @param[in] Length The size in bytes of the memory region.
604 @param[in] Attributes The bit mask of attributes to set for the memory region.
606 @retval EFI_SUCCESS The attributes were set for the memory region.
607 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
608 BaseAddress and Length cannot be modified.
609 @retval EFI_INVALID_PARAMETER Length is zero.
610 Attributes specified an illegal combination of attributes that
611 cannot be set together.
612 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
613 the memory resource range.
614 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
615 resource range specified by BaseAddress and Length.
616 The bit mask of attributes is not supported for the memory resource
617 range specified by BaseAddress and Length.
622 SmmSetMemoryAttributes (
623 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
628 return SmmSetMemoryAttributesEx (BaseAddress
, Length
, Attributes
, NULL
);
632 This function clears the attributes for the memory region specified by BaseAddress and
633 Length from their current attributes to the attributes specified by Attributes.
635 @param[in] BaseAddress The physical address that is the start address of a memory region.
636 @param[in] Length The size in bytes of the memory region.
637 @param[in] Attributes The bit mask of attributes to clear for the memory region.
639 @retval EFI_SUCCESS The attributes were cleared for the memory region.
640 @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by
641 BaseAddress and Length cannot be modified.
642 @retval EFI_INVALID_PARAMETER Length is zero.
643 Attributes specified an illegal combination of attributes that
644 cannot be cleared together.
645 @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
646 the memory resource range.
647 @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory
648 resource range specified by BaseAddress and Length.
649 The bit mask of attributes is not supported for the memory resource
650 range specified by BaseAddress and Length.
655 SmmClearMemoryAttributes (
656 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
661 return SmmClearMemoryAttributesEx (BaseAddress
, Length
, Attributes
, NULL
);
667 Retrieves a pointer to the system configuration table from the SMM System Table
668 based on a specified GUID.
670 @param[in] TableGuid The pointer to table's GUID type.
671 @param[out] Table The pointer to the table associated with TableGuid in the EFI System Table.
673 @retval EFI_SUCCESS A configuration table matching TableGuid was found.
674 @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found.
679 SmmGetSystemConfigurationTable (
680 IN EFI_GUID
*TableGuid
,
686 ASSERT (TableGuid
!= NULL
);
687 ASSERT (Table
!= NULL
);
690 for (Index
= 0; Index
< gSmst
->NumberOfTableEntries
; Index
++) {
691 if (CompareGuid (TableGuid
, &(gSmst
->SmmConfigurationTable
[Index
].VendorGuid
))) {
692 *Table
= gSmst
->SmmConfigurationTable
[Index
].VendorTable
;
697 return EFI_NOT_FOUND
;
701 This function sets SMM save state buffer to be RW and XP.
704 PatchSmmSaveStateMap (
713 TileCodeSize
= GetSmiHandlerSize ();
714 TileCodeSize
= ALIGN_VALUE(TileCodeSize
, SIZE_4KB
);
715 TileDataSize
= (SMRAM_SAVE_STATE_MAP_OFFSET
- SMM_PSD_OFFSET
) + sizeof (SMRAM_SAVE_STATE_MAP
);
716 TileDataSize
= ALIGN_VALUE(TileDataSize
, SIZE_4KB
);
717 TileSize
= TileDataSize
+ TileCodeSize
- 1;
718 TileSize
= 2 * GetPowerOfTwo32 ((UINT32
)TileSize
);
720 DEBUG ((DEBUG_INFO
, "PatchSmmSaveStateMap:\n"));
721 for (Index
= 0; Index
< mMaxNumberOfCpus
- 1; Index
++) {
725 SmmSetMemoryAttributes (
726 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
,
730 SmmClearMemoryAttributes (
731 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
,
739 SmmClearMemoryAttributes (
740 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
741 TileSize
- TileCodeSize
,
744 SmmSetMemoryAttributes (
745 mCpuHotPlugData
.SmBase
[Index
] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
746 TileSize
- TileCodeSize
,
754 SmmSetMemoryAttributes (
755 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
,
759 SmmClearMemoryAttributes (
760 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
,
768 SmmClearMemoryAttributes (
769 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
770 SIZE_32KB
- TileCodeSize
,
773 SmmSetMemoryAttributes (
774 mCpuHotPlugData
.SmBase
[mMaxNumberOfCpus
- 1] + SMM_HANDLER_OFFSET
+ TileCodeSize
,
775 SIZE_32KB
- TileCodeSize
,
781 This function sets GDT/IDT buffer to be RO and XP.
788 EFI_PHYSICAL_ADDRESS BaseAddress
;
794 DEBUG ((DEBUG_INFO
, "PatchGdtIdtMap - GDT:\n"));
796 BaseAddress
= mGdtBuffer
;
797 Size
= ALIGN_VALUE(mGdtBufferSize
, SIZE_4KB
);
799 // The range should have been set to RO
800 // if it is allocated with EfiRuntimeServicesCode.
802 SmmSetMemoryAttributes (
811 DEBUG ((DEBUG_INFO
, "PatchGdtIdtMap - IDT:\n"));
813 BaseAddress
= gcSmiIdtr
.Base
;
814 Size
= ALIGN_VALUE(gcSmiIdtr
.Limit
+ 1, SIZE_4KB
);
816 // The range should have been set to RO
817 // if it is allocated with EfiRuntimeServicesCode.
819 SmmSetMemoryAttributes (
827 This function sets memory attribute according to MemoryAttributesTable.
830 SetMemMapAttributes (
834 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
835 EFI_MEMORY_DESCRIPTOR
*MemoryMapStart
;
836 UINTN MemoryMapEntryCount
;
837 UINTN DescriptorSize
;
839 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
841 SmmGetSystemConfigurationTable (&gEdkiiPiSmmMemoryAttributesTableGuid
, (VOID
**)&MemoryAttributesTable
);
842 if (MemoryAttributesTable
== NULL
) {
843 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable - NULL\n"));
847 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable:\n"));
848 DEBUG ((DEBUG_INFO
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
849 DEBUG ((DEBUG_INFO
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
850 DEBUG ((DEBUG_INFO
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
852 MemoryMapEntryCount
= MemoryAttributesTable
->NumberOfEntries
;
853 DescriptorSize
= MemoryAttributesTable
->DescriptorSize
;
854 MemoryMapStart
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
855 MemoryMap
= MemoryMapStart
;
856 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
857 DEBUG ((DEBUG_INFO
, "Entry (0x%x)\n", MemoryMap
));
858 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", MemoryMap
->Type
));
859 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", MemoryMap
->PhysicalStart
));
860 DEBUG ((DEBUG_INFO
, " VirtualStart - 0x%016lx\n", MemoryMap
->VirtualStart
));
861 DEBUG ((DEBUG_INFO
, " NumberOfPages - 0x%016lx\n", MemoryMap
->NumberOfPages
));
862 DEBUG ((DEBUG_INFO
, " Attribute - 0x%016lx\n", MemoryMap
->Attribute
));
863 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
866 MemoryMap
= MemoryMapStart
;
867 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
868 DEBUG ((DEBUG_VERBOSE
, "SetAttribute: Memory Entry - 0x%lx, 0x%x\n", MemoryMap
->PhysicalStart
, MemoryMap
->NumberOfPages
));
869 switch (MemoryMap
->Type
) {
870 case EfiRuntimeServicesCode
:
871 SmmSetMemoryAttributes (
872 MemoryMap
->PhysicalStart
,
873 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
877 case EfiRuntimeServicesData
:
878 SmmSetMemoryAttributes (
879 MemoryMap
->PhysicalStart
,
880 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
885 SmmSetMemoryAttributes (
886 MemoryMap
->PhysicalStart
,
887 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
892 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
895 PatchSmmSaveStateMap ();
902 Sort memory map entries based upon PhysicalStart, from low to high.
904 @param MemoryMap A pointer to the buffer in which firmware places
905 the current memory map.
906 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
907 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
912 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
913 IN UINTN MemoryMapSize
,
914 IN UINTN DescriptorSize
917 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
918 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
919 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
920 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
922 MemoryMapEntry
= MemoryMap
;
923 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
924 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
925 while (MemoryMapEntry
< MemoryMapEnd
) {
926 while (NextMemoryMapEntry
< MemoryMapEnd
) {
927 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
928 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
929 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
930 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
933 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
936 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
937 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
942 Return if a UEFI memory page should be marked as not present in SMM page table.
943 If the memory map entries type is
944 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
945 EfiUnusableMemory, EfiACPIReclaimMemory, return TRUE.
948 @param[in] MemoryMap A pointer to the memory descriptor.
950 @return TRUE The memory described will be marked as not present in SMM page table.
951 @return FALSE The memory described will not be marked as not present in SMM page table.
954 IsUefiPageNotPresent (
955 IN EFI_MEMORY_DESCRIPTOR
*MemoryMap
958 switch (MemoryMap
->Type
) {
961 case EfiBootServicesCode
:
962 case EfiBootServicesData
:
963 case EfiConventionalMemory
:
964 case EfiUnusableMemory
:
965 case EfiACPIReclaimMemory
:
973 Merge continous memory map entries whose type is
974 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
975 EfiUnusableMemory, EfiACPIReclaimMemory, because the memory described by
976 these entries will be set as NOT present in SMM page table.
978 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
979 the current memory map.
980 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
981 MemoryMap buffer. On input, this is the size of
982 the current memory map. On output,
983 it is the size of new memory map after merge.
984 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
988 MergeMemoryMapForNotPresentEntry (
989 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
990 IN OUT UINTN
*MemoryMapSize
,
991 IN UINTN DescriptorSize
994 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
995 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
996 UINT64 MemoryBlockLength
;
997 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
998 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
1000 MemoryMapEntry
= MemoryMap
;
1001 NewMemoryMapEntry
= MemoryMap
;
1002 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
1003 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
1004 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
1005 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
1008 MemoryBlockLength
= (UINT64
) (EFI_PAGES_TO_SIZE((UINTN
)MemoryMapEntry
->NumberOfPages
));
1009 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
1010 IsUefiPageNotPresent(MemoryMapEntry
) && IsUefiPageNotPresent(NextMemoryMapEntry
) &&
1011 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
1012 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
1013 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
1014 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
1017 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
1020 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
1025 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
1026 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
1029 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
1035 This function caches the GCD memory map information.
1042 UINTN NumberOfDescriptors
;
1043 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemSpaceMap
;
1047 Status
= gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemSpaceMap
);
1048 if (EFI_ERROR (Status
)) {
1052 mGcdMemNumberOfDesc
= 0;
1053 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
1054 if (MemSpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeReserved
&&
1055 (MemSpaceMap
[Index
].Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
1056 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
)
1058 mGcdMemNumberOfDesc
++;
1062 mGcdMemSpace
= AllocateZeroPool (mGcdMemNumberOfDesc
* sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR
));
1063 ASSERT (mGcdMemSpace
!= NULL
);
1064 if (mGcdMemSpace
== NULL
) {
1065 mGcdMemNumberOfDesc
= 0;
1066 gBS
->FreePool (MemSpaceMap
);
1070 mGcdMemNumberOfDesc
= 0;
1071 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
1072 if (MemSpaceMap
[Index
].GcdMemoryType
== EfiGcdMemoryTypeReserved
&&
1073 (MemSpaceMap
[Index
].Capabilities
& (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
| EFI_MEMORY_TESTED
)) ==
1074 (EFI_MEMORY_PRESENT
| EFI_MEMORY_INITIALIZED
)
1077 &mGcdMemSpace
[mGcdMemNumberOfDesc
],
1078 &MemSpaceMap
[Index
],
1079 sizeof(EFI_GCD_MEMORY_SPACE_DESCRIPTOR
)
1081 mGcdMemNumberOfDesc
++;
1085 gBS
->FreePool (MemSpaceMap
);
1089 Get UEFI MemoryAttributesTable.
1092 GetUefiMemoryAttributesTable (
1097 EFI_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
1098 UINTN MemoryAttributesTableSize
;
1100 Status
= EfiGetSystemConfigurationTable (&gEfiMemoryAttributesTableGuid
, (VOID
**)&MemoryAttributesTable
);
1101 if (!EFI_ERROR (Status
) && (MemoryAttributesTable
!= NULL
)) {
1102 MemoryAttributesTableSize
= sizeof(EFI_MEMORY_ATTRIBUTES_TABLE
) + MemoryAttributesTable
->DescriptorSize
* MemoryAttributesTable
->NumberOfEntries
;
1103 mUefiMemoryAttributesTable
= AllocateCopyPool (MemoryAttributesTableSize
, MemoryAttributesTable
);
1104 ASSERT (mUefiMemoryAttributesTable
!= NULL
);
1109 This function caches the UEFI memory map information.
1118 UINT32 DescriptorVersion
;
1119 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1120 UINTN UefiMemoryMapSize
;
1122 DEBUG ((DEBUG_INFO
, "GetUefiMemoryMap\n"));
1124 UefiMemoryMapSize
= 0;
1126 Status
= gBS
->GetMemoryMap (
1130 &mUefiDescriptorSize
,
1133 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
1136 Status
= gBS
->AllocatePool (EfiBootServicesData
, UefiMemoryMapSize
, (VOID
**)&MemoryMap
);
1137 ASSERT (MemoryMap
!= NULL
);
1138 if (MemoryMap
== NULL
) {
1142 Status
= gBS
->GetMemoryMap (
1146 &mUefiDescriptorSize
,
1149 if (EFI_ERROR (Status
)) {
1150 gBS
->FreePool (MemoryMap
);
1153 } while (Status
== EFI_BUFFER_TOO_SMALL
);
1155 if (MemoryMap
== NULL
) {
1159 SortMemoryMap (MemoryMap
, UefiMemoryMapSize
, mUefiDescriptorSize
);
1160 MergeMemoryMapForNotPresentEntry (MemoryMap
, &UefiMemoryMapSize
, mUefiDescriptorSize
);
1162 mUefiMemoryMapSize
= UefiMemoryMapSize
;
1163 mUefiMemoryMap
= AllocateCopyPool (UefiMemoryMapSize
, MemoryMap
);
1164 ASSERT (mUefiMemoryMap
!= NULL
);
1166 gBS
->FreePool (MemoryMap
);
1169 // Get additional information from GCD memory map.
1174 // Get UEFI memory attributes table.
1176 GetUefiMemoryAttributesTable ();
1180 This function sets UEFI memory attribute according to UEFI memory map.
1182 The normal memory region is marked as not present, such as
1183 EfiLoaderCode/Data, EfiBootServicesCode/Data, EfiConventionalMemory,
1184 EfiUnusableMemory, EfiACPIReclaimMemory.
1187 SetUefiMemMapAttributes (
1192 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1193 UINTN MemoryMapEntryCount
;
1195 EFI_MEMORY_DESCRIPTOR
*Entry
;
1197 DEBUG ((DEBUG_INFO
, "SetUefiMemMapAttributes\n"));
1199 if (mUefiMemoryMap
!= NULL
) {
1200 MemoryMapEntryCount
= mUefiMemoryMapSize
/mUefiDescriptorSize
;
1201 MemoryMap
= mUefiMemoryMap
;
1202 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
1203 if (IsUefiPageNotPresent(MemoryMap
)) {
1204 Status
= SmmSetMemoryAttributes (
1205 MemoryMap
->PhysicalStart
,
1206 EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
1211 "UefiMemory protection: 0x%lx - 0x%lx %r\n",
1212 MemoryMap
->PhysicalStart
,
1213 MemoryMap
->PhysicalStart
+ (UINT64
)EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
),
1217 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, mUefiDescriptorSize
);
1221 // Do not free mUefiMemoryMap, it will be checked in IsSmmCommBufferForbiddenAddress().
1225 // Set untested memory as not present.
1227 if (mGcdMemSpace
!= NULL
) {
1228 for (Index
= 0; Index
< mGcdMemNumberOfDesc
; Index
++) {
1229 Status
= SmmSetMemoryAttributes (
1230 mGcdMemSpace
[Index
].BaseAddress
,
1231 mGcdMemSpace
[Index
].Length
,
1236 "GcdMemory protection: 0x%lx - 0x%lx %r\n",
1237 mGcdMemSpace
[Index
].BaseAddress
,
1238 mGcdMemSpace
[Index
].BaseAddress
+ mGcdMemSpace
[Index
].Length
,
1244 // Do not free mGcdMemSpace, it will be checked in IsSmmCommBufferForbiddenAddress().
1248 // Set UEFI runtime memory with EFI_MEMORY_RO as not present.
1250 if (mUefiMemoryAttributesTable
!= NULL
) {
1251 Entry
= (EFI_MEMORY_DESCRIPTOR
*)(mUefiMemoryAttributesTable
+ 1);
1252 for (Index
= 0; Index
< mUefiMemoryAttributesTable
->NumberOfEntries
; Index
++) {
1253 if (Entry
->Type
== EfiRuntimeServicesCode
|| Entry
->Type
== EfiRuntimeServicesData
) {
1254 if ((Entry
->Attribute
& EFI_MEMORY_RO
) != 0) {
1255 Status
= SmmSetMemoryAttributes (
1256 Entry
->PhysicalStart
,
1257 EFI_PAGES_TO_SIZE((UINTN
)Entry
->NumberOfPages
),
1262 "UefiMemoryAttribute protection: 0x%lx - 0x%lx %r\n",
1263 Entry
->PhysicalStart
,
1264 Entry
->PhysicalStart
+ (UINT64
)EFI_PAGES_TO_SIZE((UINTN
)Entry
->NumberOfPages
),
1269 Entry
= NEXT_MEMORY_DESCRIPTOR (Entry
, mUefiMemoryAttributesTable
->DescriptorSize
);
1273 // Do not free mUefiMemoryAttributesTable, it will be checked in IsSmmCommBufferForbiddenAddress().
1278 Return if the Address is forbidden as SMM communication buffer.
1280 @param[in] Address the address to be checked
1282 @return TRUE The address is forbidden as SMM communication buffer.
1283 @return FALSE The address is allowed as SMM communication buffer.
1286 IsSmmCommBufferForbiddenAddress (
1290 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1291 UINTN MemoryMapEntryCount
;
1293 EFI_MEMORY_DESCRIPTOR
*Entry
;
1295 if (mUefiMemoryMap
!= NULL
) {
1296 MemoryMap
= mUefiMemoryMap
;
1297 MemoryMapEntryCount
= mUefiMemoryMapSize
/mUefiDescriptorSize
;
1298 for (Index
= 0; Index
< MemoryMapEntryCount
; Index
++) {
1299 if (IsUefiPageNotPresent (MemoryMap
)) {
1300 if ((Address
>= MemoryMap
->PhysicalStart
) &&
1301 (Address
< MemoryMap
->PhysicalStart
+ EFI_PAGES_TO_SIZE((UINTN
)MemoryMap
->NumberOfPages
)) ) {
1305 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, mUefiDescriptorSize
);
1309 if (mGcdMemSpace
!= NULL
) {
1310 for (Index
= 0; Index
< mGcdMemNumberOfDesc
; Index
++) {
1311 if ((Address
>= mGcdMemSpace
[Index
].BaseAddress
) &&
1312 (Address
< mGcdMemSpace
[Index
].BaseAddress
+ mGcdMemSpace
[Index
].Length
) ) {
1318 if (mUefiMemoryAttributesTable
!= NULL
) {
1319 Entry
= (EFI_MEMORY_DESCRIPTOR
*)(mUefiMemoryAttributesTable
+ 1);
1320 for (Index
= 0; Index
< mUefiMemoryAttributesTable
->NumberOfEntries
; Index
++) {
1321 if (Entry
->Type
== EfiRuntimeServicesCode
|| Entry
->Type
== EfiRuntimeServicesData
) {
1322 if ((Entry
->Attribute
& EFI_MEMORY_RO
) != 0) {
1323 if ((Address
>= Entry
->PhysicalStart
) &&
1324 (Address
< Entry
->PhysicalStart
+ LShiftU64 (Entry
->NumberOfPages
, EFI_PAGE_SHIFT
))) {
1327 Entry
= NEXT_MEMORY_DESCRIPTOR (Entry
, mUefiMemoryAttributesTable
->DescriptorSize
);
1336 This function set given attributes of the memory region specified by
1337 BaseAddress and Length.
1339 @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1340 @param BaseAddress The physical address that is the start address of
1342 @param Length The size in bytes of the memory region.
1343 @param Attributes The bit mask of attributes to set for the memory
1346 @retval EFI_SUCCESS The attributes were set for the memory region.
1347 @retval EFI_INVALID_PARAMETER Length is zero.
1348 Attributes specified an illegal combination of
1349 attributes that cannot be set together.
1350 @retval EFI_UNSUPPORTED The processor does not support one or more
1351 bytes of the memory resource range specified
1352 by BaseAddress and Length.
1353 The bit mask of attributes is not supported for
1354 the memory resource range specified by
1355 BaseAddress and Length.
1360 EdkiiSmmSetMemoryAttributes (
1361 IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL
*This
,
1362 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1364 IN UINT64 Attributes
1367 return SmmSetMemoryAttributes (BaseAddress
, Length
, Attributes
);
1371 This function clears given attributes of the memory region specified by
1372 BaseAddress and Length.
1374 @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1375 @param BaseAddress The physical address that is the start address of
1377 @param Length The size in bytes of the memory region.
1378 @param Attributes The bit mask of attributes to clear for the memory
1381 @retval EFI_SUCCESS The attributes were cleared for the memory region.
1382 @retval EFI_INVALID_PARAMETER Length is zero.
1383 Attributes specified an illegal combination of
1384 attributes that cannot be cleared together.
1385 @retval EFI_UNSUPPORTED The processor does not support one or more
1386 bytes of the memory resource range specified
1387 by BaseAddress and Length.
1388 The bit mask of attributes is not supported for
1389 the memory resource range specified by
1390 BaseAddress and Length.
1395 EdkiiSmmClearMemoryAttributes (
1396 IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL
*This
,
1397 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1399 IN UINT64 Attributes
1402 return SmmClearMemoryAttributes (BaseAddress
, Length
, Attributes
);
1406 This function retrieves the attributes of the memory region specified by
1407 BaseAddress and Length. If different attributes are got from different part
1408 of the memory region, EFI_NO_MAPPING will be returned.
1410 @param This The EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL instance.
1411 @param BaseAddress The physical address that is the start address of
1413 @param Length The size in bytes of the memory region.
1414 @param Attributes Pointer to attributes returned.
1416 @retval EFI_SUCCESS The attributes got for the memory region.
1417 @retval EFI_INVALID_PARAMETER Length is zero.
1419 @retval EFI_NO_MAPPING Attributes are not consistent cross the memory
1421 @retval EFI_UNSUPPORTED The processor does not support one or more
1422 bytes of the memory resource range specified
1423 by BaseAddress and Length.
1428 EdkiiSmmGetMemoryAttributes (
1429 IN EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL
*This
,
1430 IN EFI_PHYSICAL_ADDRESS BaseAddress
,
1432 OUT UINT64
*Attributes
1435 EFI_PHYSICAL_ADDRESS Address
;
1438 PAGE_ATTRIBUTE PageAttr
;
1441 if (Length
< SIZE_4KB
|| Attributes
== NULL
) {
1442 return EFI_INVALID_PARAMETER
;
1445 Size
= (INT64
)Length
;
1446 MemAttr
= (UINT64
)-1;
1450 PageEntry
= GetPageTableEntry (BaseAddress
, &PageAttr
);
1451 if (PageEntry
== NULL
|| PageAttr
== PageNone
) {
1452 return EFI_UNSUPPORTED
;
1456 // If the memory range is cross page table boundary, make sure they
1457 // share the same attribute. Return EFI_NO_MAPPING if not.
1459 *Attributes
= GetAttributesFromPageEntry (PageEntry
);
1460 if (MemAttr
!= (UINT64
)-1 && *Attributes
!= MemAttr
) {
1461 return EFI_NO_MAPPING
;
1466 Address
= *PageEntry
& ~mAddressEncMask
& PAGING_4K_ADDRESS_MASK_64
;
1467 Size
-= (SIZE_4KB
- (BaseAddress
- Address
));
1468 BaseAddress
+= (SIZE_4KB
- (BaseAddress
- Address
));
1472 Address
= *PageEntry
& ~mAddressEncMask
& PAGING_2M_ADDRESS_MASK_64
;
1473 Size
-= SIZE_2MB
- (BaseAddress
- Address
);
1474 BaseAddress
+= SIZE_2MB
- (BaseAddress
- Address
);
1478 Address
= *PageEntry
& ~mAddressEncMask
& PAGING_1G_ADDRESS_MASK_64
;
1479 Size
-= SIZE_1GB
- (BaseAddress
- Address
);
1480 BaseAddress
+= SIZE_1GB
- (BaseAddress
- Address
);
1484 return EFI_UNSUPPORTED
;
1487 MemAttr
= *Attributes
;