2 PI SMM MemoryAttributes support
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Library/SmmServicesTableLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/PcdLib.h>
18 #include <Library/PeCoffLib.h>
19 #include <Library/PeCoffGetEntryPointLib.h>
21 #include <Guid/PiSmmMemoryAttributesTable.h>
23 #include "PiSmmCore.h"
25 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
26 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
28 #define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')
33 EFI_PHYSICAL_ADDRESS CodeSegmentBase
;
34 UINT64 CodeSegmentSize
;
35 } IMAGE_PROPERTIES_RECORD_CODE_SECTION
;
37 #define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')
42 EFI_PHYSICAL_ADDRESS ImageBase
;
44 UINTN CodeSegmentCount
;
45 LIST_ENTRY CodeSegmentList
;
46 } IMAGE_PROPERTIES_RECORD
;
48 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
52 UINTN ImageRecordCount
;
53 UINTN CodeSegmentCountMax
;
54 LIST_ENTRY ImageRecordList
;
55 } IMAGE_PROPERTIES_PRIVATE_DATA
;
57 IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData
= {
58 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE
,
61 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData
.ImageRecordList
)
64 #define EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA BIT0
66 UINT64 mMemoryProtectionAttribute
= EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
;
69 // Below functions are for MemoryMap
73 Converts a number of EFI_PAGEs to a size in bytes.
75 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
77 @param[in] Pages The number of EFI_PAGES.
79 @return The number of bytes associated with the number of EFI_PAGEs specified
88 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
92 Converts a size, in bytes, to a number of EFI_PAGESs.
94 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
96 @param[in] Size A size in bytes.
98 @return The number of EFI_PAGESs associated with the number of bytes specified
108 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
113 Sort memory map entries based upon PhysicalStart, from low to high.
115 @param[in,out] MemoryMap A pointer to the buffer in which firmware places
116 the current memory map.
117 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.
118 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
123 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
124 IN UINTN MemoryMapSize
,
125 IN UINTN DescriptorSize
128 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
129 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
130 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
131 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
133 MemoryMapEntry
= MemoryMap
;
134 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
135 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
136 while (MemoryMapEntry
< MemoryMapEnd
) {
137 while (NextMemoryMapEntry
< MemoryMapEnd
) {
138 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
139 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
140 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
141 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
144 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
147 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
148 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
155 Merge continous memory map entries whose have same attributes.
157 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
158 the current memory map.
159 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
160 MemoryMap buffer. On input, this is the size of
161 the current memory map. On output,
162 it is the size of new memory map after merge.
163 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
168 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
169 IN OUT UINTN
*MemoryMapSize
,
170 IN UINTN DescriptorSize
173 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
174 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
175 UINT64 MemoryBlockLength
;
176 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
177 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
179 MemoryMapEntry
= MemoryMap
;
180 NewMemoryMapEntry
= MemoryMap
;
181 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
182 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
183 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
184 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
187 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
188 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
189 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
190 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
191 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
192 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
193 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
194 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
197 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
200 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
205 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
206 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
209 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
215 Enforce memory map attributes.
216 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
218 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
219 the current memory map.
220 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.
221 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
225 EnforceMemoryMapAttribute (
226 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
227 IN UINTN MemoryMapSize
,
228 IN UINTN DescriptorSize
231 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
232 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
234 MemoryMapEntry
= MemoryMap
;
235 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
236 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
237 if (MemoryMapEntry
->Attribute
!= 0) {
238 // It is PE image, the attribute is already set.
240 switch (MemoryMapEntry
->Type
) {
241 case EfiRuntimeServicesCode
:
242 MemoryMapEntry
->Attribute
= EFI_MEMORY_RO
;
244 case EfiRuntimeServicesData
:
246 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
250 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
257 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
259 @param[in] Buffer Start Address
260 @param[in] Length Address length
262 @return first image record covered by [buffer, length]
265 IMAGE_PROPERTIES_RECORD
*
266 GetImageRecordByAddress (
267 IN EFI_PHYSICAL_ADDRESS Buffer
,
271 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
272 LIST_ENTRY
*ImageRecordLink
;
273 LIST_ENTRY
*ImageRecordList
;
275 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
277 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
278 ImageRecordLink
!= ImageRecordList
;
279 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
282 IMAGE_PROPERTIES_RECORD
,
284 IMAGE_PROPERTIES_RECORD_SIGNATURE
287 if ((Buffer
<= ImageRecord
->ImageBase
) &&
288 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
297 Set the memory map to new entries, according to one old entry,
298 based upon PE code section and data section in image record
300 @param[in] ImageRecord An image record whose [ImageBase, ImageSize] covered
301 by old memory map entry.
302 @param[in, out] NewRecord A pointer to several new memory map entries.
303 The caller gurantee the buffer size be 1 +
304 (SplitRecordCount * DescriptorSize) calculated
306 @param[in] OldRecord A pointer to one old memory map entry.
307 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
312 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
313 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
314 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
315 IN UINTN DescriptorSize
318 EFI_MEMORY_DESCRIPTOR TempRecord
;
319 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
320 LIST_ENTRY
*ImageRecordCodeSectionLink
;
321 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
322 LIST_ENTRY
*ImageRecordCodeSectionList
;
323 UINTN NewRecordCount
;
327 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
328 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
332 // Always create a new entry for non-PE image record
334 if (ImageRecord
->ImageBase
> TempRecord
.PhysicalStart
) {
335 NewRecord
->Type
= TempRecord
.Type
;
336 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
337 NewRecord
->VirtualStart
= 0;
338 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecord
->ImageBase
- TempRecord
.PhysicalStart
);
339 NewRecord
->Attribute
= TempRecord
.Attribute
;
340 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
342 TempRecord
.PhysicalStart
= ImageRecord
->ImageBase
;
343 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
346 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
348 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
349 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
350 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
351 ImageRecordCodeSection
= CR (
352 ImageRecordCodeSectionLink
,
353 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
355 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
357 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
359 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
363 NewRecord
->Type
= EfiRuntimeServicesData
;
364 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
365 NewRecord
->VirtualStart
= 0;
366 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
367 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
368 if (NewRecord
->NumberOfPages
!= 0) {
369 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
376 NewRecord
->Type
= EfiRuntimeServicesCode
;
377 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
378 NewRecord
->VirtualStart
= 0;
379 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
380 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
381 if (NewRecord
->NumberOfPages
!= 0) {
382 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
386 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
387 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
388 if (TempRecord
.NumberOfPages
== 0) {
394 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
399 if (TempRecord
.PhysicalStart
< ImageEnd
) {
400 NewRecord
->Type
= EfiRuntimeServicesData
;
401 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
402 NewRecord
->VirtualStart
= 0;
403 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
404 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
408 return NewRecordCount
;
412 Return the max number of new splitted entries, according to one old entry,
413 based upon PE code section and data section.
415 @param[in] OldRecord A pointer to one old memory map entry.
417 @retval 0 no entry need to be splitted.
418 @return the max number of new splitted entries
422 GetMaxSplitRecordCount (
423 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
426 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
427 UINTN SplitRecordCount
;
428 UINT64 PhysicalStart
;
431 SplitRecordCount
= 0;
432 PhysicalStart
= OldRecord
->PhysicalStart
;
433 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
436 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
437 if (ImageRecord
== NULL
) {
440 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 2);
441 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
442 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
444 return SplitRecordCount
;
448 Split the memory map to new entries, according to one old entry,
449 based upon PE code section and data section.
451 @param[in] OldRecord A pointer to one old memory map entry.
452 @param[in, out] NewRecord A pointer to several new memory map entries.
453 The caller gurantee the buffer size be 1 +
454 (SplitRecordCount * DescriptorSize) calculated
456 @param[in] MaxSplitRecordCount The max number of splitted entries
457 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
459 @retval 0 no entry is splitted.
460 @return the real number of splitted record.
465 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
466 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
467 IN UINTN MaxSplitRecordCount
,
468 IN UINTN DescriptorSize
471 EFI_MEMORY_DESCRIPTOR TempRecord
;
472 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
473 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
474 UINT64 PhysicalStart
;
476 UINTN NewRecordCount
;
477 UINTN TotalNewRecordCount
;
479 if (MaxSplitRecordCount
== 0) {
480 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
484 TotalNewRecordCount
= 0;
487 // Override previous record
489 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
490 PhysicalStart
= TempRecord
.PhysicalStart
;
491 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
495 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
496 if (NewImageRecord
== NULL
) {
498 // No more image covered by this range, stop
500 if (PhysicalEnd
> PhysicalStart
) {
502 // Always create a new entry for non-PE image record
504 NewRecord
->Type
= TempRecord
.Type
;
505 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
506 NewRecord
->VirtualStart
= 0;
507 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
508 NewRecord
->Attribute
= TempRecord
.Attribute
;
509 TotalNewRecordCount
++;
513 ImageRecord
= NewImageRecord
;
518 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
519 TotalNewRecordCount
+= NewRecordCount
;
520 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
523 // Update PhysicalStart, in order to exclude the image buffer already splitted.
525 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
526 TempRecord
.PhysicalStart
= PhysicalStart
;
527 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
528 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
530 return TotalNewRecordCount
- 1;
534 Split the original memory map, and add more entries to describe PE code section and data section.
535 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
536 This function will merge entries with same attributes finally.
538 NOTE: It assumes PE code/data section are page aligned.
539 NOTE: It assumes enough entry is prepared for new memory map.
554 +---------------+ ----
557 | Record RtCode | |-> PE/COFF1
560 +---------------+ ----
562 +---------------+ ----
565 | Record RtCode | |-> PE/COFF2
568 +---------------+ ----
574 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
575 MemoryMap buffer. On input, this is the size of
576 old MemoryMap before split. The actual buffer
577 size of MemoryMap is MemoryMapSize +
578 (AdditionalRecordCount * DescriptorSize) calculated
579 below. On output, it is the size of new MemoryMap
581 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
582 the current memory map.
583 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
588 IN OUT UINTN
*MemoryMapSize
,
589 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
590 IN UINTN DescriptorSize
595 UINTN MaxSplitRecordCount
;
596 UINTN RealSplitRecordCount
;
597 UINTN TotalSplitRecordCount
;
598 UINTN AdditionalRecordCount
;
600 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 2) * mImagePropertiesPrivateData
.ImageRecordCount
;
602 TotalSplitRecordCount
= 0;
604 // Let old record point to end of valid MemoryMap buffer.
606 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
608 // Let new record point to end of full MemoryMap buffer.
610 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
611 for (; IndexOld
>= 0; IndexOld
--) {
612 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
614 // Split this MemoryMap record
616 IndexNew
-= MaxSplitRecordCount
;
617 RealSplitRecordCount
= SplitRecord (
618 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
619 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
624 // Adjust IndexNew according to real split.
626 if (MaxSplitRecordCount
!= RealSplitRecordCount
) {
628 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
629 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
630 (RealSplitRecordCount
+ 1) * DescriptorSize
633 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
634 TotalSplitRecordCount
+= RealSplitRecordCount
;
638 // Move all records to the beginning.
642 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
643 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
646 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
649 // Sort from low to high (Just in case)
651 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
654 // Set RuntimeData to XP
656 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
659 // Merge same type to save entry size
661 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
667 This function for GetMemoryMap() with memory attributes table.
669 It calls original GetMemoryMap() to get the original memory map information. Then
670 plus the additional memory map entries for PE Code/Data seperation.
672 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
673 MemoryMap buffer. On input, this is the size of
674 the buffer allocated by the caller. On output,
675 it is the size of the buffer returned by the
676 firmware if the buffer was large enough, or the
677 size of the buffer needed to contain the map if
678 the buffer was too small.
679 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
680 the current memory map.
681 @param[out] MapKey A pointer to the location in which firmware
682 returns the key for the current memory map.
683 @param[out] DescriptorSize A pointer to the location in which firmware
684 returns the size, in bytes, of an individual
685 EFI_MEMORY_DESCRIPTOR.
686 @param[out] DescriptorVersion A pointer to the location in which firmware
687 returns the version number associated with the
688 EFI_MEMORY_DESCRIPTOR.
690 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
692 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
693 buffer size needed to hold the memory map is
694 returned in MemoryMapSize.
695 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
701 SmmCoreGetMemoryMapMemoryAttributesTable (
702 IN OUT UINTN
*MemoryMapSize
,
703 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
705 OUT UINTN
*DescriptorSize
,
706 OUT UINT32
*DescriptorVersion
710 UINTN OldMemoryMapSize
;
711 UINTN AdditionalRecordCount
;
714 // If PE code/data is not aligned, just return.
716 if ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
717 return SmmCoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
720 if (MemoryMapSize
== NULL
) {
721 return EFI_INVALID_PARAMETER
;
724 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 2) * mImagePropertiesPrivateData
.ImageRecordCount
;
726 OldMemoryMapSize
= *MemoryMapSize
;
727 Status
= SmmCoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
728 if (Status
== EFI_BUFFER_TOO_SMALL
) {
729 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
730 } else if (Status
== EFI_SUCCESS
) {
731 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
732 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
734 // Need update status to buffer too small
736 Status
= EFI_BUFFER_TOO_SMALL
;
739 // Split PE code/data
741 ASSERT(MemoryMap
!= NULL
);
742 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
750 // Below functions are for ImageRecord
754 Set MemoryProtectionAttribute according to PE/COFF image section alignment.
756 @param[in] SectionAlignment PE/COFF section alignment
760 SetMemoryAttributesTableSectionAlignment (
761 IN UINT32 SectionAlignment
764 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
765 ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
766 DEBUG ((DEBUG_VERBOSE
, "SMM SetMemoryAttributesTableSectionAlignment - Clear\n"));
767 mMemoryProtectionAttribute
&= ~((UINT64
)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
772 Swap two code sections in image record.
774 @param[in] FirstImageRecordCodeSection first code section in image record
775 @param[in] SecondImageRecordCodeSection second code section in image record
779 SwapImageRecordCodeSection (
780 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
781 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
784 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
786 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
787 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
789 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
790 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
792 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
793 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
797 Sort code section in image record, based upon CodeSegmentBase from low to high.
799 @param[in] ImageRecord image record to be sorted
803 SortImageRecordCodeSection (
804 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
807 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
808 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
809 LIST_ENTRY
*ImageRecordCodeSectionLink
;
810 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
811 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
812 LIST_ENTRY
*ImageRecordCodeSectionList
;
814 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
816 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
817 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
818 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
819 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
820 ImageRecordCodeSection
= CR (
821 ImageRecordCodeSectionLink
,
822 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
824 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
826 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
827 NextImageRecordCodeSection
= CR (
828 NextImageRecordCodeSectionLink
,
829 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
831 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
833 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
834 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
836 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
839 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
840 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
845 Check if code section in image record is valid.
847 @param[in] ImageRecord image record to be checked
849 @retval TRUE image record is valid
850 @retval FALSE image record is invalid
854 IsImageRecordCodeSectionValid (
855 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
858 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
859 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
860 LIST_ENTRY
*ImageRecordCodeSectionLink
;
861 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
862 LIST_ENTRY
*ImageRecordCodeSectionList
;
864 DEBUG ((DEBUG_VERBOSE
, "SMM ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
866 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
868 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
869 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
870 LastImageRecordCodeSection
= NULL
;
871 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
872 ImageRecordCodeSection
= CR (
873 ImageRecordCodeSectionLink
,
874 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
876 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
878 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
881 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
884 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
887 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
890 if (LastImageRecordCodeSection
!= NULL
) {
891 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
896 LastImageRecordCodeSection
= ImageRecordCodeSection
;
897 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
904 Swap two image records.
906 @param[in] FirstImageRecord first image record.
907 @param[in] SecondImageRecord second image record.
912 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
913 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
916 IMAGE_PROPERTIES_RECORD TempImageRecord
;
918 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
919 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
920 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
922 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
923 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
924 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
926 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
927 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
928 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
930 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
934 Sort image record based upon the ImageBase from low to high.
942 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
943 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
944 LIST_ENTRY
*ImageRecordLink
;
945 LIST_ENTRY
*NextImageRecordLink
;
946 LIST_ENTRY
*ImageRecordEndLink
;
947 LIST_ENTRY
*ImageRecordList
;
949 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
951 ImageRecordLink
= ImageRecordList
->ForwardLink
;
952 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
953 ImageRecordEndLink
= ImageRecordList
;
954 while (ImageRecordLink
!= ImageRecordEndLink
) {
957 IMAGE_PROPERTIES_RECORD
,
959 IMAGE_PROPERTIES_RECORD_SIGNATURE
961 while (NextImageRecordLink
!= ImageRecordEndLink
) {
962 NextImageRecord
= CR (
964 IMAGE_PROPERTIES_RECORD
,
966 IMAGE_PROPERTIES_RECORD_SIGNATURE
968 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
969 SwapImageRecord (ImageRecord
, NextImageRecord
);
971 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
974 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
975 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
988 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
989 LIST_ENTRY
*ImageRecordLink
;
990 LIST_ENTRY
*ImageRecordList
;
993 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
995 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
996 ImageRecordLink
!= ImageRecordList
;
997 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1000 IMAGE_PROPERTIES_RECORD
,
1002 IMAGE_PROPERTIES_RECORD_SIGNATURE
1004 DEBUG ((DEBUG_VERBOSE
, "SMM Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1009 Insert image record.
1011 @param[in] DriverEntry Driver information
1014 SmmInsertImageRecord (
1015 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
1019 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1020 UINT32 PeCoffHeaderOffset
;
1021 UINT32 SectionAlignment
;
1022 EFI_IMAGE_SECTION_HEADER
*Section
;
1023 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1026 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1028 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1030 DEBUG ((DEBUG_VERBOSE
, "SMM InsertImageRecord - 0x%x\n", DriverEntry
));
1031 DEBUG ((DEBUG_VERBOSE
, "SMM InsertImageRecord - 0x%016lx - 0x%08x\n", DriverEntry
->ImageBuffer
, DriverEntry
->NumberOfPage
));
1033 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1034 if (ImageRecord
== NULL
) {
1037 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1039 DEBUG ((DEBUG_VERBOSE
, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1042 // Step 1: record whole region
1044 ImageRecord
->ImageBase
= DriverEntry
->ImageBuffer
;
1045 ImageRecord
->ImageSize
= EfiPagesToSize(DriverEntry
->NumberOfPage
);
1047 ImageAddress
= (VOID
*)(UINTN
)DriverEntry
->ImageBuffer
;
1049 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1050 if (PdbPointer
!= NULL
) {
1051 DEBUG ((DEBUG_VERBOSE
, "SMM Image - %a\n", PdbPointer
));
1055 // Check PE/COFF image
1057 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1058 PeCoffHeaderOffset
= 0;
1059 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1060 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1063 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1064 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1065 DEBUG ((DEBUG_VERBOSE
, "SMM Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1070 // Get SectionAlignment
1072 if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1073 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1075 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1078 SetMemoryAttributesTableSectionAlignment (SectionAlignment
);
1079 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1080 DEBUG ((DEBUG_WARN
, "SMM !!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1081 SectionAlignment
, RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1082 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1083 if (PdbPointer
!= NULL
) {
1084 DEBUG ((DEBUG_WARN
, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1089 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1090 (UINT8
*) (UINTN
) ImageAddress
+
1091 PeCoffHeaderOffset
+
1093 sizeof(EFI_IMAGE_FILE_HEADER
) +
1094 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1096 ImageRecord
->CodeSegmentCount
= 0;
1097 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1098 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1099 Name
= Section
[Index
].Name
;
1102 "SMM Section - '%c%c%c%c%c%c%c%c'\n",
1113 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1114 DEBUG ((DEBUG_VERBOSE
, "SMM VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1115 DEBUG ((DEBUG_VERBOSE
, "SMM VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1116 DEBUG ((DEBUG_VERBOSE
, "SMM SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1117 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1118 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1119 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1120 DEBUG ((DEBUG_VERBOSE
, "SMM NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1121 DEBUG ((DEBUG_VERBOSE
, "SMM NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1122 DEBUG ((DEBUG_VERBOSE
, "SMM Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1125 // Step 2: record code section
1127 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1128 if (ImageRecordCodeSection
== NULL
) {
1131 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1133 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1134 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1136 DEBUG ((DEBUG_VERBOSE
, "SMM ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1138 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1139 ImageRecord
->CodeSegmentCount
++;
1143 if (ImageRecord
->CodeSegmentCount
== 0) {
1144 SetMemoryAttributesTableSectionAlignment (1);
1145 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1146 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1147 if (PdbPointer
!= NULL
) {
1148 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1156 SortImageRecordCodeSection (ImageRecord
);
1158 // Check overlap all section in ImageBase/Size
1160 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1161 DEBUG ((DEBUG_ERROR
, "SMM IsImageRecordCodeSectionValid - FAIL\n"));
1165 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1166 mImagePropertiesPrivateData
.ImageRecordCount
++;
1168 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1169 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1180 Publish MemoryAttributesTable to SMM configuration table.
1183 PublishMemoryAttributesTable (
1187 UINTN MemoryMapSize
;
1188 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1190 UINTN DescriptorSize
;
1191 UINT32 DescriptorVersion
;
1194 UINTN RuntimeEntryCount
;
1195 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
1196 EFI_MEMORY_DESCRIPTOR
*MemoryAttributesEntry
;
1197 UINTN MemoryAttributesTableSize
;
1201 Status
= SmmCoreGetMemoryMapMemoryAttributesTable (
1208 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
1211 DEBUG ((DEBUG_INFO
, "MemoryMapSize - 0x%x\n", MemoryMapSize
));
1212 MemoryMap
= AllocatePool (MemoryMapSize
);
1213 ASSERT (MemoryMap
!= NULL
);
1214 DEBUG ((DEBUG_INFO
, "MemoryMap - 0x%x\n", MemoryMap
));
1216 Status
= SmmCoreGetMemoryMapMemoryAttributesTable (
1223 if (EFI_ERROR (Status
)) {
1224 FreePool (MemoryMap
);
1226 } while (Status
== EFI_BUFFER_TOO_SMALL
);
1229 // Allocate MemoryAttributesTable
1231 RuntimeEntryCount
= MemoryMapSize
/DescriptorSize
;
1232 MemoryAttributesTableSize
= sizeof(EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
;
1233 MemoryAttributesTable
= AllocatePool (sizeof(EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
);
1234 ASSERT (MemoryAttributesTable
!= NULL
);
1235 MemoryAttributesTable
->Version
= EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE_VERSION
;
1236 MemoryAttributesTable
->NumberOfEntries
= (UINT32
)RuntimeEntryCount
;
1237 MemoryAttributesTable
->DescriptorSize
= (UINT32
)DescriptorSize
;
1238 MemoryAttributesTable
->Reserved
= 0;
1239 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable:\n"));
1240 DEBUG ((DEBUG_INFO
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
1241 DEBUG ((DEBUG_INFO
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
1242 DEBUG ((DEBUG_INFO
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
1243 MemoryAttributesEntry
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
1244 for (Index
= 0; Index
< MemoryMapSize
/DescriptorSize
; Index
++) {
1245 CopyMem (MemoryAttributesEntry
, MemoryMap
, DescriptorSize
);
1246 DEBUG ((DEBUG_INFO
, "Entry (0x%x)\n", MemoryAttributesEntry
));
1247 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", MemoryAttributesEntry
->Type
));
1248 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry
->PhysicalStart
));
1249 DEBUG ((DEBUG_INFO
, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry
->VirtualStart
));
1250 DEBUG ((DEBUG_INFO
, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry
->NumberOfPages
));
1251 DEBUG ((DEBUG_INFO
, " Attribute - 0x%016lx\n", MemoryAttributesEntry
->Attribute
));
1252 MemoryAttributesEntry
= NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry
, DescriptorSize
);
1254 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
1257 Status
= gSmst
->SmmInstallConfigurationTable (gSmst
, &gEdkiiPiSmmMemoryAttributesTableGuid
, MemoryAttributesTable
, MemoryAttributesTableSize
);
1258 ASSERT_EFI_ERROR (Status
);
1263 This function installs all SMM image record information.
1266 SmmInstallImageRecord (
1272 EFI_HANDLE
*HandleBuffer
;
1273 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
1275 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1277 Status
= SmmLocateHandleBuffer (
1279 &gEfiLoadedImageProtocolGuid
,
1284 if (EFI_ERROR (Status
)) {
1288 for (Index
= 0; Index
< NoHandles
; Index
++) {
1289 Status
= gSmst
->SmmHandleProtocol (
1290 HandleBuffer
[Index
],
1291 &gEfiLoadedImageProtocolGuid
,
1292 (VOID
**)&LoadedImage
1294 if (EFI_ERROR (Status
)) {
1297 DEBUG ((DEBUG_VERBOSE
, "LoadedImage - 0x%x 0x%x ", LoadedImage
->ImageBase
, LoadedImage
->ImageSize
));
1300 PdbPointer
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
1301 if (PdbPointer
!= NULL
) {
1302 DEBUG ((DEBUG_VERBOSE
, "(%a) ", PdbPointer
));
1305 DEBUG ((DEBUG_VERBOSE
, "\n"));
1306 ZeroMem (&DriverEntry
, sizeof(DriverEntry
));
1307 DriverEntry
.ImageBuffer
= (UINTN
)LoadedImage
->ImageBase
;
1308 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES((UINTN
)LoadedImage
->ImageSize
);
1309 SmmInsertImageRecord (&DriverEntry
);
1312 FreePool (HandleBuffer
);
1316 Install MemoryAttributesTable.
1318 @param[in] Protocol Points to the protocol's unique identifier.
1319 @param[in] Interface Points to the interface instance.
1320 @param[in] Handle The handle on which the interface was installed.
1322 @retval EFI_SUCCESS Notification runs successfully.
1326 SmmInstallMemoryAttributesTable (
1327 IN CONST EFI_GUID
*Protocol
,
1329 IN EFI_HANDLE Handle
1332 SmmInstallImageRecord ();
1334 DEBUG ((DEBUG_INFO
, "SMM MemoryProtectionAttribute - 0x%016lx\n", mMemoryProtectionAttribute
));
1335 if ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1339 DEBUG ((DEBUG_VERBOSE
, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1340 DEBUG ((DEBUG_VERBOSE
, "SMM Dump ImageRecord:\n"));
1343 PublishMemoryAttributesTable ();
1349 Initialize MemoryAttributesTable support.
1353 SmmCoreInitializeMemoryAttributesTable (
1360 Status
= gSmst
->SmmRegisterProtocolNotify (
1361 &gEfiSmmEndOfDxeProtocolGuid
,
1362 SmmInstallMemoryAttributesTable
,
1365 ASSERT_EFI_ERROR (Status
);