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);
112 Sort memory map entries based upon PhysicalStart, from low to high.
114 @param[in,out] MemoryMap A pointer to the buffer in which firmware places
115 the current memory map.
116 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.
117 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
122 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
123 IN UINTN MemoryMapSize
,
124 IN UINTN DescriptorSize
127 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
128 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
129 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
130 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
132 MemoryMapEntry
= MemoryMap
;
133 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
134 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ MemoryMapSize
);
135 while (MemoryMapEntry
< MemoryMapEnd
) {
136 while (NextMemoryMapEntry
< MemoryMapEnd
) {
137 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
138 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
139 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
140 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof (EFI_MEMORY_DESCRIPTOR
));
143 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
146 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
147 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
154 Merge continuous memory map entries whose have same attributes.
156 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
157 the current memory map.
158 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
159 MemoryMap buffer. On input, this is the size of
160 the current memory map. On output,
161 it is the size of new memory map after merge.
162 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
167 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
168 IN OUT UINTN
*MemoryMapSize
,
169 IN UINTN DescriptorSize
172 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
173 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
174 UINT64 MemoryBlockLength
;
175 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
176 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
178 MemoryMapEntry
= MemoryMap
;
179 NewMemoryMapEntry
= MemoryMap
;
180 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ *MemoryMapSize
);
181 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
182 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof (EFI_MEMORY_DESCRIPTOR
));
183 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
186 MemoryBlockLength
= (UINT64
)(EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
187 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
188 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
189 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
190 ((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
;
251 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
258 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
260 @param[in] Buffer Start Address
261 @param[in] Length Address length
263 @return first image record covered by [buffer, length]
266 IMAGE_PROPERTIES_RECORD
*
267 GetImageRecordByAddress (
268 IN EFI_PHYSICAL_ADDRESS Buffer
,
272 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
273 LIST_ENTRY
*ImageRecordLink
;
274 LIST_ENTRY
*ImageRecordList
;
276 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
278 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
279 ImageRecordLink
!= ImageRecordList
;
280 ImageRecordLink
= ImageRecordLink
->ForwardLink
)
284 IMAGE_PROPERTIES_RECORD
,
286 IMAGE_PROPERTIES_RECORD_SIGNATURE
289 if ((Buffer
<= ImageRecord
->ImageBase
) &&
290 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
))
300 Set the memory map to new entries, according to one old entry,
301 based upon PE code section and data section in image record
303 @param[in] ImageRecord An image record whose [ImageBase, ImageSize] covered
304 by old memory map entry.
305 @param[in, out] NewRecord A pointer to several new memory map entries.
306 The caller guarantee the buffer size be 1 +
307 (SplitRecordCount * DescriptorSize) calculated
309 @param[in] OldRecord A pointer to one old memory map entry.
310 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
315 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
316 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
317 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
318 IN UINTN DescriptorSize
321 EFI_MEMORY_DESCRIPTOR TempRecord
;
322 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
323 LIST_ENTRY
*ImageRecordCodeSectionLink
;
324 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
325 LIST_ENTRY
*ImageRecordCodeSectionList
;
326 UINTN NewRecordCount
;
330 CopyMem (&TempRecord
, OldRecord
, sizeof (EFI_MEMORY_DESCRIPTOR
));
331 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize (TempRecord
.NumberOfPages
);
335 // Always create a new entry for non-PE image record
337 if (ImageRecord
->ImageBase
> TempRecord
.PhysicalStart
) {
338 NewRecord
->Type
= TempRecord
.Type
;
339 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
340 NewRecord
->VirtualStart
= 0;
341 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageRecord
->ImageBase
- TempRecord
.PhysicalStart
);
342 NewRecord
->Attribute
= TempRecord
.Attribute
;
343 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
345 TempRecord
.PhysicalStart
= ImageRecord
->ImageBase
;
346 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- TempRecord
.PhysicalStart
);
349 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
351 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
352 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
353 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
354 ImageRecordCodeSection
= CR (
355 ImageRecordCodeSectionLink
,
356 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
358 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
360 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
362 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
366 NewRecord
->Type
= EfiRuntimeServicesData
;
367 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
368 NewRecord
->VirtualStart
= 0;
369 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
370 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
371 if (NewRecord
->NumberOfPages
!= 0) {
372 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
379 NewRecord
->Type
= EfiRuntimeServicesCode
;
380 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
381 NewRecord
->VirtualStart
= 0;
382 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageRecordCodeSection
->CodeSegmentSize
);
383 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
384 if (NewRecord
->NumberOfPages
!= 0) {
385 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
389 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection
->CodeSegmentSize
));
390 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- TempRecord
.PhysicalStart
);
391 if (TempRecord
.NumberOfPages
== 0) {
397 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
402 if (TempRecord
.PhysicalStart
< ImageEnd
) {
403 NewRecord
->Type
= EfiRuntimeServicesData
;
404 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
405 NewRecord
->VirtualStart
= 0;
406 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
407 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
411 return NewRecordCount
;
415 Return the max number of new splitted entries, according to one old entry,
416 based upon PE code section and data section.
418 @param[in] OldRecord A pointer to one old memory map entry.
420 @retval 0 no entry need to be splitted.
421 @return the max number of new splitted entries
425 GetMaxSplitRecordCount (
426 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
429 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
430 UINTN SplitRecordCount
;
431 UINT64 PhysicalStart
;
434 SplitRecordCount
= 0;
435 PhysicalStart
= OldRecord
->PhysicalStart
;
436 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize (OldRecord
->NumberOfPages
);
439 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
440 if (ImageRecord
== NULL
) {
444 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 2);
445 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
446 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
448 return SplitRecordCount
;
452 Split the memory map to new entries, according to one old entry,
453 based upon PE code section and data section.
455 @param[in] OldRecord A pointer to one old memory map entry.
456 @param[in, out] NewRecord A pointer to several new memory map entries.
457 The caller guarantee the buffer size be 1 +
458 (SplitRecordCount * DescriptorSize) calculated
460 @param[in] MaxSplitRecordCount The max number of splitted entries
461 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
463 @retval 0 no entry is splitted.
464 @return the real number of splitted record.
469 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
470 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
471 IN UINTN MaxSplitRecordCount
,
472 IN UINTN DescriptorSize
475 EFI_MEMORY_DESCRIPTOR TempRecord
;
476 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
477 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
478 UINT64 PhysicalStart
;
480 UINTN NewRecordCount
;
481 UINTN TotalNewRecordCount
;
483 if (MaxSplitRecordCount
== 0) {
484 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
488 TotalNewRecordCount
= 0;
491 // Override previous record
493 CopyMem (&TempRecord
, OldRecord
, sizeof (EFI_MEMORY_DESCRIPTOR
));
494 PhysicalStart
= TempRecord
.PhysicalStart
;
495 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize (TempRecord
.NumberOfPages
);
499 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
500 if (NewImageRecord
== NULL
) {
502 // No more image covered by this range, stop
504 if (PhysicalEnd
> PhysicalStart
) {
506 // Always create a new entry for non-PE image record
508 NewRecord
->Type
= TempRecord
.Type
;
509 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
510 NewRecord
->VirtualStart
= 0;
511 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
512 NewRecord
->Attribute
= TempRecord
.Attribute
;
513 TotalNewRecordCount
++;
519 ImageRecord
= NewImageRecord
;
524 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
525 TotalNewRecordCount
+= NewRecordCount
;
526 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
529 // Update PhysicalStart, in order to exclude the image buffer already splitted.
531 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
532 TempRecord
.PhysicalStart
= PhysicalStart
;
533 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
534 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
536 return TotalNewRecordCount
- 1;
540 Split the original memory map, and add more entries to describe PE code section and data section.
541 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
542 This function will merge entries with same attributes finally.
544 NOTE: It assumes PE code/data section are page aligned.
545 NOTE: It assumes enough entry is prepared for new memory map.
560 +---------------+ ----
563 | Record RtCode | |-> PE/COFF1
566 +---------------+ ----
568 +---------------+ ----
571 | Record RtCode | |-> PE/COFF2
574 +---------------+ ----
580 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
581 MemoryMap buffer. On input, this is the size of
582 old MemoryMap before split. The actual buffer
583 size of MemoryMap is MemoryMapSize +
584 (AdditionalRecordCount * DescriptorSize) calculated
585 below. On output, it is the size of new MemoryMap
587 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
588 the current memory map.
589 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
594 IN OUT UINTN
*MemoryMapSize
,
595 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
596 IN UINTN DescriptorSize
601 UINTN MaxSplitRecordCount
;
602 UINTN RealSplitRecordCount
;
603 UINTN TotalSplitRecordCount
;
604 UINTN AdditionalRecordCount
;
606 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 2) * mImagePropertiesPrivateData
.ImageRecordCount
;
608 TotalSplitRecordCount
= 0;
610 // Let old record point to end of valid MemoryMap buffer.
612 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
614 // Let new record point to end of full MemoryMap buffer.
616 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
617 for ( ; IndexOld
>= 0; IndexOld
--) {
618 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
620 // Split this MemoryMap record
622 IndexNew
-= MaxSplitRecordCount
;
623 RealSplitRecordCount
= SplitRecord (
624 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
625 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
630 // Adjust IndexNew according to real split.
632 if (MaxSplitRecordCount
!= RealSplitRecordCount
) {
634 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
635 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
636 (RealSplitRecordCount
+ 1) * DescriptorSize
640 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
641 TotalSplitRecordCount
+= RealSplitRecordCount
;
646 // Move all records to the beginning.
650 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
651 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
654 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
657 // Sort from low to high (Just in case)
659 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
662 // Set RuntimeData to XP
664 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
667 // Merge same type to save entry size
669 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
675 This function for GetMemoryMap() with memory attributes table.
677 It calls original GetMemoryMap() to get the original memory map information. Then
678 plus the additional memory map entries for PE Code/Data separation.
680 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
681 MemoryMap buffer. On input, this is the size of
682 the buffer allocated by the caller. On output,
683 it is the size of the buffer returned by the
684 firmware if the buffer was large enough, or the
685 size of the buffer needed to contain the map if
686 the buffer was too small.
687 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
688 the current memory map.
689 @param[out] MapKey A pointer to the location in which firmware
690 returns the key for the current memory map.
691 @param[out] DescriptorSize A pointer to the location in which firmware
692 returns the size, in bytes, of an individual
693 EFI_MEMORY_DESCRIPTOR.
694 @param[out] DescriptorVersion A pointer to the location in which firmware
695 returns the version number associated with the
696 EFI_MEMORY_DESCRIPTOR.
698 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
700 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
701 buffer size needed to hold the memory map is
702 returned in MemoryMapSize.
703 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
709 SmmCoreGetMemoryMapMemoryAttributesTable (
710 IN OUT UINTN
*MemoryMapSize
,
711 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
713 OUT UINTN
*DescriptorSize
,
714 OUT UINT32
*DescriptorVersion
718 UINTN OldMemoryMapSize
;
719 UINTN AdditionalRecordCount
;
722 // If PE code/data is not aligned, just return.
724 if ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
725 return SmmCoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
728 if (MemoryMapSize
== NULL
) {
729 return EFI_INVALID_PARAMETER
;
732 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 2) * mImagePropertiesPrivateData
.ImageRecordCount
;
734 OldMemoryMapSize
= *MemoryMapSize
;
735 Status
= SmmCoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
736 if (Status
== EFI_BUFFER_TOO_SMALL
) {
737 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
738 } else if (Status
== EFI_SUCCESS
) {
739 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
740 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
742 // Need update status to buffer too small
744 Status
= EFI_BUFFER_TOO_SMALL
;
747 // Split PE code/data
749 ASSERT (MemoryMap
!= NULL
);
750 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
758 // Below functions are for ImageRecord
762 Set MemoryProtectionAttribute according to PE/COFF image section alignment.
764 @param[in] SectionAlignment PE/COFF section alignment
768 SetMemoryAttributesTableSectionAlignment (
769 IN UINT32 SectionAlignment
772 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
773 ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0))
775 DEBUG ((DEBUG_VERBOSE
, "SMM SetMemoryAttributesTableSectionAlignment - Clear\n"));
776 mMemoryProtectionAttribute
&= ~((UINT64
)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
781 Swap two code sections in image record.
783 @param[in] FirstImageRecordCodeSection first code section in image record
784 @param[in] SecondImageRecordCodeSection second code section in image record
788 SwapImageRecordCodeSection (
789 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
790 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
793 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
795 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
796 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
798 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
799 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
801 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
802 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
806 Sort code section in image record, based upon CodeSegmentBase from low to high.
808 @param[in] ImageRecord image record to be sorted
812 SortImageRecordCodeSection (
813 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
816 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
817 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
818 LIST_ENTRY
*ImageRecordCodeSectionLink
;
819 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
820 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
821 LIST_ENTRY
*ImageRecordCodeSectionList
;
823 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
825 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
826 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
827 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
828 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
829 ImageRecordCodeSection
= CR (
830 ImageRecordCodeSectionLink
,
831 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
833 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
835 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
836 NextImageRecordCodeSection
= CR (
837 NextImageRecordCodeSectionLink
,
838 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
840 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
842 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
843 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
846 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
849 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
850 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
855 Check if code section in image record is valid.
857 @param[in] ImageRecord image record to be checked
859 @retval TRUE image record is valid
860 @retval FALSE image record is invalid
864 IsImageRecordCodeSectionValid (
865 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
868 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
869 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
870 LIST_ENTRY
*ImageRecordCodeSectionLink
;
871 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
872 LIST_ENTRY
*ImageRecordCodeSectionList
;
874 DEBUG ((DEBUG_VERBOSE
, "SMM ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
876 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
878 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
879 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
880 LastImageRecordCodeSection
= NULL
;
881 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
882 ImageRecordCodeSection
= CR (
883 ImageRecordCodeSectionLink
,
884 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
886 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
888 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
892 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
896 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
900 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
904 if (LastImageRecordCodeSection
!= NULL
) {
905 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
910 LastImageRecordCodeSection
= ImageRecordCodeSection
;
911 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
918 Swap two image records.
920 @param[in] FirstImageRecord first image record.
921 @param[in] SecondImageRecord second image record.
926 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
927 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
930 IMAGE_PROPERTIES_RECORD TempImageRecord
;
932 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
933 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
934 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
936 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
937 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
938 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
940 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
941 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
942 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
944 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
948 Sort image record based upon the ImageBase from low to high.
956 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
957 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
958 LIST_ENTRY
*ImageRecordLink
;
959 LIST_ENTRY
*NextImageRecordLink
;
960 LIST_ENTRY
*ImageRecordEndLink
;
961 LIST_ENTRY
*ImageRecordList
;
963 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
965 ImageRecordLink
= ImageRecordList
->ForwardLink
;
966 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
967 ImageRecordEndLink
= ImageRecordList
;
968 while (ImageRecordLink
!= ImageRecordEndLink
) {
971 IMAGE_PROPERTIES_RECORD
,
973 IMAGE_PROPERTIES_RECORD_SIGNATURE
975 while (NextImageRecordLink
!= ImageRecordEndLink
) {
976 NextImageRecord
= CR (
978 IMAGE_PROPERTIES_RECORD
,
980 IMAGE_PROPERTIES_RECORD_SIGNATURE
982 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
983 SwapImageRecord (ImageRecord
, NextImageRecord
);
986 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
989 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
990 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1003 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1004 LIST_ENTRY
*ImageRecordLink
;
1005 LIST_ENTRY
*ImageRecordList
;
1008 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1010 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1011 ImageRecordLink
!= ImageRecordList
;
1012 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++)
1016 IMAGE_PROPERTIES_RECORD
,
1018 IMAGE_PROPERTIES_RECORD_SIGNATURE
1020 DEBUG ((DEBUG_VERBOSE
, "SMM Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1025 Insert image record.
1027 @param[in] DriverEntry Driver information
1030 SmmInsertImageRecord (
1031 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
1035 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1036 UINT32 PeCoffHeaderOffset
;
1037 UINT32 SectionAlignment
;
1038 EFI_IMAGE_SECTION_HEADER
*Section
;
1039 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1042 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1044 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1046 DEBUG ((DEBUG_VERBOSE
, "SMM InsertImageRecord - 0x%x\n", DriverEntry
));
1047 DEBUG ((DEBUG_VERBOSE
, "SMM InsertImageRecord - 0x%016lx - 0x%08x\n", DriverEntry
->ImageBuffer
, DriverEntry
->NumberOfPage
));
1049 ImageRecord
= AllocatePool (sizeof (*ImageRecord
));
1050 if (ImageRecord
== NULL
) {
1054 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1056 DEBUG ((DEBUG_VERBOSE
, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1059 // Step 1: record whole region
1061 ImageRecord
->ImageBase
= DriverEntry
->ImageBuffer
;
1062 ImageRecord
->ImageSize
= EfiPagesToSize (DriverEntry
->NumberOfPage
);
1064 ImageAddress
= (VOID
*)(UINTN
)DriverEntry
->ImageBuffer
;
1066 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageAddress
);
1067 if (PdbPointer
!= NULL
) {
1068 DEBUG ((DEBUG_VERBOSE
, "SMM Image - %a\n", PdbPointer
));
1072 // Check PE/COFF image
1074 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)(UINTN
)ImageAddress
;
1075 PeCoffHeaderOffset
= 0;
1076 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1077 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1080 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*)(UINTN
)ImageAddress
+ PeCoffHeaderOffset
);
1081 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1082 DEBUG ((DEBUG_VERBOSE
, "SMM Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1087 // Get SectionAlignment
1089 if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1090 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1092 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1095 SetMemoryAttributesTableSectionAlignment (SectionAlignment
);
1096 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1099 "SMM !!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1101 RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10
1103 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageAddress
);
1104 if (PdbPointer
!= NULL
) {
1105 DEBUG ((DEBUG_WARN
, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1111 Section
= (EFI_IMAGE_SECTION_HEADER
*)(
1112 (UINT8
*)(UINTN
)ImageAddress
+
1113 PeCoffHeaderOffset
+
1115 sizeof (EFI_IMAGE_FILE_HEADER
) +
1116 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1118 ImageRecord
->CodeSegmentCount
= 0;
1119 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1120 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1121 Name
= Section
[Index
].Name
;
1124 "SMM Section - '%c%c%c%c%c%c%c%c'\n",
1135 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1136 DEBUG ((DEBUG_VERBOSE
, "SMM VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1137 DEBUG ((DEBUG_VERBOSE
, "SMM VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1138 DEBUG ((DEBUG_VERBOSE
, "SMM SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1139 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1140 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1141 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1142 DEBUG ((DEBUG_VERBOSE
, "SMM NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1143 DEBUG ((DEBUG_VERBOSE
, "SMM NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1144 DEBUG ((DEBUG_VERBOSE
, "SMM Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1147 // Step 2: record code section
1149 ImageRecordCodeSection
= AllocatePool (sizeof (*ImageRecordCodeSection
));
1150 if (ImageRecordCodeSection
== NULL
) {
1154 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1156 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1157 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1159 DEBUG ((DEBUG_VERBOSE
, "SMM ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1161 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1162 ImageRecord
->CodeSegmentCount
++;
1166 if (ImageRecord
->CodeSegmentCount
== 0) {
1167 SetMemoryAttributesTableSectionAlignment (1);
1168 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1169 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*)(UINTN
)ImageAddress
);
1170 if (PdbPointer
!= NULL
) {
1171 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1180 SortImageRecordCodeSection (ImageRecord
);
1182 // Check overlap all section in ImageBase/Size
1184 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1185 DEBUG ((DEBUG_ERROR
, "SMM IsImageRecordCodeSectionValid - FAIL\n"));
1189 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1190 mImagePropertiesPrivateData
.ImageRecordCount
++;
1192 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1193 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1203 Publish MemoryAttributesTable to SMM configuration table.
1206 PublishMemoryAttributesTable (
1210 UINTN MemoryMapSize
;
1211 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1213 UINTN DescriptorSize
;
1214 UINT32 DescriptorVersion
;
1217 UINTN RuntimeEntryCount
;
1218 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
1219 EFI_MEMORY_DESCRIPTOR
*MemoryAttributesEntry
;
1220 UINTN MemoryAttributesTableSize
;
1224 Status
= SmmCoreGetMemoryMapMemoryAttributesTable (
1231 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
1234 DEBUG ((DEBUG_VERBOSE
, "MemoryMapSize - 0x%x\n", MemoryMapSize
));
1235 MemoryMap
= AllocatePool (MemoryMapSize
);
1236 ASSERT (MemoryMap
!= NULL
);
1237 DEBUG ((DEBUG_VERBOSE
, "MemoryMap - 0x%x\n", MemoryMap
));
1239 Status
= SmmCoreGetMemoryMapMemoryAttributesTable (
1246 if (EFI_ERROR (Status
)) {
1247 FreePool (MemoryMap
);
1249 } while (Status
== EFI_BUFFER_TOO_SMALL
);
1252 // Allocate MemoryAttributesTable
1254 RuntimeEntryCount
= MemoryMapSize
/DescriptorSize
;
1255 MemoryAttributesTableSize
= sizeof (EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
;
1256 MemoryAttributesTable
= AllocatePool (sizeof (EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
);
1257 ASSERT (MemoryAttributesTable
!= NULL
);
1258 MemoryAttributesTable
->Version
= EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE_VERSION
;
1259 MemoryAttributesTable
->NumberOfEntries
= (UINT32
)RuntimeEntryCount
;
1260 MemoryAttributesTable
->DescriptorSize
= (UINT32
)DescriptorSize
;
1261 MemoryAttributesTable
->Reserved
= 0;
1262 DEBUG ((DEBUG_VERBOSE
, "MemoryAttributesTable:\n"));
1263 DEBUG ((DEBUG_VERBOSE
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
1264 DEBUG ((DEBUG_VERBOSE
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
1265 DEBUG ((DEBUG_VERBOSE
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
1266 MemoryAttributesEntry
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
1267 for (Index
= 0; Index
< MemoryMapSize
/DescriptorSize
; Index
++) {
1268 CopyMem (MemoryAttributesEntry
, MemoryMap
, DescriptorSize
);
1269 DEBUG ((DEBUG_VERBOSE
, "Entry (0x%x)\n", MemoryAttributesEntry
));
1270 DEBUG ((DEBUG_VERBOSE
, " Type - 0x%x\n", MemoryAttributesEntry
->Type
));
1271 DEBUG ((DEBUG_VERBOSE
, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry
->PhysicalStart
));
1272 DEBUG ((DEBUG_VERBOSE
, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry
->VirtualStart
));
1273 DEBUG ((DEBUG_VERBOSE
, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry
->NumberOfPages
));
1274 DEBUG ((DEBUG_VERBOSE
, " Attribute - 0x%016lx\n", MemoryAttributesEntry
->Attribute
));
1275 MemoryAttributesEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryAttributesEntry
, DescriptorSize
);
1277 MemoryMap
= NEXT_MEMORY_DESCRIPTOR (MemoryMap
, DescriptorSize
);
1280 Status
= gSmst
->SmmInstallConfigurationTable (gSmst
, &gEdkiiPiSmmMemoryAttributesTableGuid
, MemoryAttributesTable
, MemoryAttributesTableSize
);
1281 ASSERT_EFI_ERROR (Status
);
1285 This function installs all SMM image record information.
1288 SmmInstallImageRecord (
1294 EFI_HANDLE
*HandleBuffer
;
1295 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
1297 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1299 Status
= SmmLocateHandleBuffer (
1301 &gEfiLoadedImageProtocolGuid
,
1306 if (EFI_ERROR (Status
)) {
1310 for (Index
= 0; Index
< NoHandles
; Index
++) {
1311 Status
= gSmst
->SmmHandleProtocol (
1312 HandleBuffer
[Index
],
1313 &gEfiLoadedImageProtocolGuid
,
1314 (VOID
**)&LoadedImage
1316 if (EFI_ERROR (Status
)) {
1320 DEBUG ((DEBUG_VERBOSE
, "LoadedImage - 0x%x 0x%x ", LoadedImage
->ImageBase
, LoadedImage
->ImageSize
));
1323 PdbPointer
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
1324 if (PdbPointer
!= NULL
) {
1325 DEBUG ((DEBUG_VERBOSE
, "(%a) ", PdbPointer
));
1328 DEBUG ((DEBUG_VERBOSE
, "\n"));
1329 ZeroMem (&DriverEntry
, sizeof (DriverEntry
));
1330 DriverEntry
.ImageBuffer
= (UINTN
)LoadedImage
->ImageBase
;
1331 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES ((UINTN
)LoadedImage
->ImageSize
);
1332 SmmInsertImageRecord (&DriverEntry
);
1335 FreePool (HandleBuffer
);
1339 Install MemoryAttributesTable.
1341 @param[in] Protocol Points to the protocol's unique identifier.
1342 @param[in] Interface Points to the interface instance.
1343 @param[in] Handle The handle on which the interface was installed.
1345 @retval EFI_SUCCESS Notification runs successfully.
1349 SmmInstallMemoryAttributesTable (
1350 IN CONST EFI_GUID
*Protocol
,
1352 IN EFI_HANDLE Handle
1355 SmmInstallImageRecord ();
1357 DEBUG ((DEBUG_VERBOSE
, "SMM MemoryProtectionAttribute - 0x%016lx\n", mMemoryProtectionAttribute
));
1358 if ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1362 DEBUG ((DEBUG_VERBOSE
, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1363 DEBUG ((DEBUG_VERBOSE
, "SMM Dump ImageRecord:\n"));
1366 PublishMemoryAttributesTable ();
1372 Initialize MemoryAttributesTable support.
1376 SmmCoreInitializeMemoryAttributesTable (
1383 Status
= gSmst
->SmmRegisterProtocolNotify (
1384 &gEfiSmmEndOfDxeProtocolGuid
,
1385 SmmInstallMemoryAttributesTable
,
1388 ASSERT_EFI_ERROR (Status
);