2 PI SMM MemoryAttributes support
4 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Library/BaseLib.h>
17 #include <Library/BaseMemoryLib.h>
18 #include <Library/MemoryAllocationLib.h>
19 #include <Library/UefiBootServicesTableLib.h>
20 #include <Library/SmmServicesTableLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/PcdLib.h>
24 #include <Library/PeCoffLib.h>
25 #include <Library/PeCoffGetEntryPointLib.h>
27 #include <Guid/PiSmmMemoryAttributesTable.h>
29 #include "PiSmmCore.h"
31 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
32 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
34 #define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')
39 EFI_PHYSICAL_ADDRESS CodeSegmentBase
;
40 UINT64 CodeSegmentSize
;
41 } IMAGE_PROPERTIES_RECORD_CODE_SECTION
;
43 #define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')
48 EFI_PHYSICAL_ADDRESS ImageBase
;
50 UINTN CodeSegmentCount
;
51 LIST_ENTRY CodeSegmentList
;
52 } IMAGE_PROPERTIES_RECORD
;
54 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
58 UINTN ImageRecordCount
;
59 UINTN CodeSegmentCountMax
;
60 LIST_ENTRY ImageRecordList
;
61 } IMAGE_PROPERTIES_PRIVATE_DATA
;
63 IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData
= {
64 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE
,
67 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData
.ImageRecordList
)
70 #define EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA BIT0
72 UINT64 mMemoryProtectionAttribute
= EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
;
75 // Below functions are for MemoryMap
79 Converts a number of EFI_PAGEs to a size in bytes.
81 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
83 @param[in] Pages The number of EFI_PAGES.
85 @return The number of bytes associated with the number of EFI_PAGEs specified
94 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
98 Converts a size, in bytes, to a number of EFI_PAGESs.
100 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
102 @param[in] Size A size in bytes.
104 @return The number of EFI_PAGESs associated with the number of bytes specified
114 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
119 Sort memory map entries based upon PhysicalStart, from low to high.
121 @param[in,out] MemoryMap A pointer to the buffer in which firmware places
122 the current memory map.
123 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.
124 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
129 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
130 IN UINTN MemoryMapSize
,
131 IN UINTN DescriptorSize
134 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
135 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
136 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
137 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
139 MemoryMapEntry
= MemoryMap
;
140 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
141 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
142 while (MemoryMapEntry
< MemoryMapEnd
) {
143 while (NextMemoryMapEntry
< MemoryMapEnd
) {
144 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
145 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
146 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
147 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
150 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
153 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
154 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
161 Merge continous memory map entries whose have same attributes.
163 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
164 the current memory map.
165 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
166 MemoryMap buffer. On input, this is the size of
167 the current memory map. On output,
168 it is the size of new memory map after merge.
169 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
174 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
175 IN OUT UINTN
*MemoryMapSize
,
176 IN UINTN DescriptorSize
179 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
180 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
181 UINT64 MemoryBlockLength
;
182 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
183 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
185 MemoryMapEntry
= MemoryMap
;
186 NewMemoryMapEntry
= MemoryMap
;
187 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
188 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
189 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
190 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
193 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
194 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
195 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
196 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
197 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
198 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
199 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
200 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
203 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
206 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
211 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
212 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
215 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
221 Enforce memory map attributes.
222 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
224 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
225 the current memory map.
226 @param[in] MemoryMapSize Size, in bytes, of the MemoryMap buffer.
227 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
231 EnforceMemoryMapAttribute (
232 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
233 IN UINTN MemoryMapSize
,
234 IN UINTN DescriptorSize
237 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
238 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
240 MemoryMapEntry
= MemoryMap
;
241 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
242 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
243 if (MemoryMapEntry
->Attribute
!= 0) {
244 // It is PE image, the attribute is already set.
246 switch (MemoryMapEntry
->Type
) {
247 case EfiRuntimeServicesCode
:
248 MemoryMapEntry
->Attribute
= EFI_MEMORY_RO
;
250 case EfiRuntimeServicesData
:
252 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
256 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
263 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
265 @param[in] Buffer Start Address
266 @param[in] Length Address length
268 @return first image record covered by [buffer, length]
271 IMAGE_PROPERTIES_RECORD
*
272 GetImageRecordByAddress (
273 IN EFI_PHYSICAL_ADDRESS Buffer
,
277 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
278 LIST_ENTRY
*ImageRecordLink
;
279 LIST_ENTRY
*ImageRecordList
;
281 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
283 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
284 ImageRecordLink
!= ImageRecordList
;
285 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
288 IMAGE_PROPERTIES_RECORD
,
290 IMAGE_PROPERTIES_RECORD_SIGNATURE
293 if ((Buffer
<= ImageRecord
->ImageBase
) &&
294 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
303 Set the memory map to new entries, according to one old entry,
304 based upon PE code section and data section in image record
306 @param[in] ImageRecord An image record whose [ImageBase, ImageSize] covered
307 by old memory map entry.
308 @param[in, out] NewRecord A pointer to several new memory map entries.
309 The caller gurantee the buffer size be 1 +
310 (SplitRecordCount * DescriptorSize) calculated
312 @param[in] OldRecord A pointer to one old memory map entry.
313 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
318 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
319 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
320 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
321 IN UINTN DescriptorSize
324 EFI_MEMORY_DESCRIPTOR TempRecord
;
325 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
326 LIST_ENTRY
*ImageRecordCodeSectionLink
;
327 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
328 LIST_ENTRY
*ImageRecordCodeSectionList
;
329 UINTN NewRecordCount
;
333 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
334 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
338 // Always create a new entry for non-PE image record
340 if (ImageRecord
->ImageBase
> TempRecord
.PhysicalStart
) {
341 NewRecord
->Type
= TempRecord
.Type
;
342 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
343 NewRecord
->VirtualStart
= 0;
344 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecord
->ImageBase
- TempRecord
.PhysicalStart
);
345 NewRecord
->Attribute
= TempRecord
.Attribute
;
346 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
348 TempRecord
.PhysicalStart
= ImageRecord
->ImageBase
;
349 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
352 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
354 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
355 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
356 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
357 ImageRecordCodeSection
= CR (
358 ImageRecordCodeSectionLink
,
359 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
361 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
363 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
365 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
369 NewRecord
->Type
= EfiRuntimeServicesData
;
370 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
371 NewRecord
->VirtualStart
= 0;
372 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
373 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
374 if (NewRecord
->NumberOfPages
!= 0) {
375 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
382 NewRecord
->Type
= EfiRuntimeServicesCode
;
383 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
384 NewRecord
->VirtualStart
= 0;
385 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
386 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
387 if (NewRecord
->NumberOfPages
!= 0) {
388 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
392 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
393 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
394 if (TempRecord
.NumberOfPages
== 0) {
400 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
405 if (TempRecord
.PhysicalStart
< ImageEnd
) {
406 NewRecord
->Type
= EfiRuntimeServicesData
;
407 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
408 NewRecord
->VirtualStart
= 0;
409 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
410 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
414 return NewRecordCount
;
418 Return the max number of new splitted entries, according to one old entry,
419 based upon PE code section and data section.
421 @param[in] OldRecord A pointer to one old memory map entry.
423 @retval 0 no entry need to be splitted.
424 @return the max number of new splitted entries
428 GetMaxSplitRecordCount (
429 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
432 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
433 UINTN SplitRecordCount
;
434 UINT64 PhysicalStart
;
437 SplitRecordCount
= 0;
438 PhysicalStart
= OldRecord
->PhysicalStart
;
439 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
442 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
443 if (ImageRecord
== NULL
) {
446 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 2);
447 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
448 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
450 return SplitRecordCount
;
454 Split the memory map to new entries, according to one old entry,
455 based upon PE code section and data section.
457 @param[in] OldRecord A pointer to one old memory map entry.
458 @param[in, out] NewRecord A pointer to several new memory map entries.
459 The caller gurantee the buffer size be 1 +
460 (SplitRecordCount * DescriptorSize) calculated
462 @param[in] MaxSplitRecordCount The max number of splitted entries
463 @param[in] DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
465 @retval 0 no entry is splitted.
466 @return the real number of splitted record.
471 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
472 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
473 IN UINTN MaxSplitRecordCount
,
474 IN UINTN DescriptorSize
477 EFI_MEMORY_DESCRIPTOR TempRecord
;
478 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
479 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
480 UINT64 PhysicalStart
;
482 UINTN NewRecordCount
;
483 UINTN TotalNewRecordCount
;
485 if (MaxSplitRecordCount
== 0) {
486 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
490 TotalNewRecordCount
= 0;
493 // Override previous record
495 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
496 PhysicalStart
= TempRecord
.PhysicalStart
;
497 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
501 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
502 if (NewImageRecord
== NULL
) {
504 // No more image covered by this range, stop
506 if (PhysicalEnd
> PhysicalStart
) {
508 // Always create a new entry for non-PE image record
510 NewRecord
->Type
= TempRecord
.Type
;
511 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
512 NewRecord
->VirtualStart
= 0;
513 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
514 NewRecord
->Attribute
= TempRecord
.Attribute
;
515 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
639 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
640 TotalSplitRecordCount
+= RealSplitRecordCount
;
644 // Move all records to the beginning.
648 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
649 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
652 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
655 // Sort from low to high (Just in case)
657 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
660 // Set RuntimeData to XP
662 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
665 // Merge same type to save entry size
667 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
673 This function for GetMemoryMap() with memory attributes table.
675 It calls original GetMemoryMap() to get the original memory map information. Then
676 plus the additional memory map entries for PE Code/Data seperation.
678 @param[in, out] MemoryMapSize A pointer to the size, in bytes, of the
679 MemoryMap buffer. On input, this is the size of
680 the buffer allocated by the caller. On output,
681 it is the size of the buffer returned by the
682 firmware if the buffer was large enough, or the
683 size of the buffer needed to contain the map if
684 the buffer was too small.
685 @param[in, out] MemoryMap A pointer to the buffer in which firmware places
686 the current memory map.
687 @param[out] MapKey A pointer to the location in which firmware
688 returns the key for the current memory map.
689 @param[out] DescriptorSize A pointer to the location in which firmware
690 returns the size, in bytes, of an individual
691 EFI_MEMORY_DESCRIPTOR.
692 @param[out] DescriptorVersion A pointer to the location in which firmware
693 returns the version number associated with the
694 EFI_MEMORY_DESCRIPTOR.
696 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
698 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
699 buffer size needed to hold the memory map is
700 returned in MemoryMapSize.
701 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
707 SmmCoreGetMemoryMapMemoryAttributesTable (
708 IN OUT UINTN
*MemoryMapSize
,
709 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
711 OUT UINTN
*DescriptorSize
,
712 OUT UINT32
*DescriptorVersion
716 UINTN OldMemoryMapSize
;
717 UINTN AdditionalRecordCount
;
720 // If PE code/data is not aligned, just return.
722 if ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
723 return SmmCoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
726 if (MemoryMapSize
== NULL
) {
727 return EFI_INVALID_PARAMETER
;
730 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 2) * mImagePropertiesPrivateData
.ImageRecordCount
;
732 OldMemoryMapSize
= *MemoryMapSize
;
733 Status
= SmmCoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
734 if (Status
== EFI_BUFFER_TOO_SMALL
) {
735 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
736 } else if (Status
== EFI_SUCCESS
) {
737 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
738 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
740 // Need update status to buffer too small
742 Status
= EFI_BUFFER_TOO_SMALL
;
745 // Split PE code/data
747 ASSERT(MemoryMap
!= NULL
);
748 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
756 // Below functions are for ImageRecord
760 Set MemoryProtectionAttribute according to PE/COFF image section alignment.
762 @param[in] SectionAlignment PE/COFF section alignment
766 SetMemoryAttributesTableSectionAlignment (
767 IN UINT32 SectionAlignment
770 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
771 ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
772 DEBUG ((DEBUG_VERBOSE
, "SMM SetMemoryAttributesTableSectionAlignment - Clear\n"));
773 mMemoryProtectionAttribute
&= ~((UINT64
)EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
778 Swap two code sections in image record.
780 @param[in] FirstImageRecordCodeSection first code section in image record
781 @param[in] SecondImageRecordCodeSection second code section in image record
785 SwapImageRecordCodeSection (
786 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
787 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
790 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
792 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
793 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
795 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
796 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
798 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
799 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
803 Sort code section in image record, based upon CodeSegmentBase from low to high.
805 @param[in] ImageRecord image record to be sorted
809 SortImageRecordCodeSection (
810 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
813 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
814 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
815 LIST_ENTRY
*ImageRecordCodeSectionLink
;
816 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
817 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
818 LIST_ENTRY
*ImageRecordCodeSectionList
;
820 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
822 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
823 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
824 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
825 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
826 ImageRecordCodeSection
= CR (
827 ImageRecordCodeSectionLink
,
828 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
830 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
832 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
833 NextImageRecordCodeSection
= CR (
834 NextImageRecordCodeSectionLink
,
835 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
837 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
839 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
840 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
842 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
845 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
846 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
851 Check if code section in image record is valid.
853 @param[in] ImageRecord image record to be checked
855 @retval TRUE image record is valid
856 @retval FALSE image record is invalid
860 IsImageRecordCodeSectionValid (
861 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
864 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
865 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
866 LIST_ENTRY
*ImageRecordCodeSectionLink
;
867 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
868 LIST_ENTRY
*ImageRecordCodeSectionList
;
870 DEBUG ((DEBUG_VERBOSE
, "SMM ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
872 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
874 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
875 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
876 LastImageRecordCodeSection
= NULL
;
877 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
878 ImageRecordCodeSection
= CR (
879 ImageRecordCodeSectionLink
,
880 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
882 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
884 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
887 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
890 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
893 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
896 if (LastImageRecordCodeSection
!= NULL
) {
897 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
902 LastImageRecordCodeSection
= ImageRecordCodeSection
;
903 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
910 Swap two image records.
912 @param[in] FirstImageRecord first image record.
913 @param[in] SecondImageRecord second image record.
918 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
919 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
922 IMAGE_PROPERTIES_RECORD TempImageRecord
;
924 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
925 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
926 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
928 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
929 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
930 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
932 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
933 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
934 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
936 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
940 Sort image record based upon the ImageBase from low to high.
948 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
949 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
950 LIST_ENTRY
*ImageRecordLink
;
951 LIST_ENTRY
*NextImageRecordLink
;
952 LIST_ENTRY
*ImageRecordEndLink
;
953 LIST_ENTRY
*ImageRecordList
;
955 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
957 ImageRecordLink
= ImageRecordList
->ForwardLink
;
958 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
959 ImageRecordEndLink
= ImageRecordList
;
960 while (ImageRecordLink
!= ImageRecordEndLink
) {
963 IMAGE_PROPERTIES_RECORD
,
965 IMAGE_PROPERTIES_RECORD_SIGNATURE
967 while (NextImageRecordLink
!= ImageRecordEndLink
) {
968 NextImageRecord
= CR (
970 IMAGE_PROPERTIES_RECORD
,
972 IMAGE_PROPERTIES_RECORD_SIGNATURE
974 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
975 SwapImageRecord (ImageRecord
, NextImageRecord
);
977 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
980 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
981 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
994 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
995 LIST_ENTRY
*ImageRecordLink
;
996 LIST_ENTRY
*ImageRecordList
;
999 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1001 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1002 ImageRecordLink
!= ImageRecordList
;
1003 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1006 IMAGE_PROPERTIES_RECORD
,
1008 IMAGE_PROPERTIES_RECORD_SIGNATURE
1010 DEBUG ((DEBUG_VERBOSE
, "SMM Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1015 Insert image record.
1017 @param[in] DriverEntry Driver information
1020 SmmInsertImageRecord (
1021 IN EFI_SMM_DRIVER_ENTRY
*DriverEntry
1025 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1026 UINT32 PeCoffHeaderOffset
;
1027 UINT32 SectionAlignment
;
1028 EFI_IMAGE_SECTION_HEADER
*Section
;
1029 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1032 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1034 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1037 DEBUG ((DEBUG_VERBOSE
, "SMM InsertImageRecord - 0x%x\n", DriverEntry
));
1038 DEBUG ((DEBUG_VERBOSE
, "SMM InsertImageRecord - 0x%016lx - 0x%08x\n", DriverEntry
->ImageBuffer
, DriverEntry
->NumberOfPage
));
1040 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1041 if (ImageRecord
== NULL
) {
1044 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1046 DEBUG ((DEBUG_VERBOSE
, "SMM ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1049 // Step 1: record whole region
1051 ImageRecord
->ImageBase
= DriverEntry
->ImageBuffer
;
1052 ImageRecord
->ImageSize
= EfiPagesToSize(DriverEntry
->NumberOfPage
);
1054 ImageAddress
= (VOID
*)(UINTN
)DriverEntry
->ImageBuffer
;
1056 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1057 if (PdbPointer
!= NULL
) {
1058 DEBUG ((DEBUG_VERBOSE
, "SMM Image - %a\n", PdbPointer
));
1062 // Check PE/COFF image
1064 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1065 PeCoffHeaderOffset
= 0;
1066 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1067 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1070 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1071 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1072 DEBUG ((DEBUG_VERBOSE
, "SMM Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1077 // Get SectionAlignment
1079 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1081 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1082 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1083 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1084 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1086 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1089 // Get the magic value from the PE/COFF Optional Header
1091 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1093 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1094 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1096 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1099 SetMemoryAttributesTableSectionAlignment (SectionAlignment
);
1100 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1101 DEBUG ((DEBUG_WARN
, "SMM !!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1102 SectionAlignment
, RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1103 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1104 if (PdbPointer
!= NULL
) {
1105 DEBUG ((DEBUG_WARN
, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1110 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1111 (UINT8
*) (UINTN
) ImageAddress
+
1112 PeCoffHeaderOffset
+
1114 sizeof(EFI_IMAGE_FILE_HEADER
) +
1115 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1117 ImageRecord
->CodeSegmentCount
= 0;
1118 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1119 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1120 Name
= Section
[Index
].Name
;
1123 "SMM Section - '%c%c%c%c%c%c%c%c'\n",
1134 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1135 DEBUG ((DEBUG_VERBOSE
, "SMM VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1136 DEBUG ((DEBUG_VERBOSE
, "SMM VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1137 DEBUG ((DEBUG_VERBOSE
, "SMM SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1138 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1139 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1140 DEBUG ((DEBUG_VERBOSE
, "SMM PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1141 DEBUG ((DEBUG_VERBOSE
, "SMM NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1142 DEBUG ((DEBUG_VERBOSE
, "SMM NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1143 DEBUG ((DEBUG_VERBOSE
, "SMM Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1146 // Step 2: record code section
1148 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1149 if (ImageRecordCodeSection
== NULL
) {
1152 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1154 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1155 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1157 DEBUG ((DEBUG_VERBOSE
, "SMM ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1159 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1160 ImageRecord
->CodeSegmentCount
++;
1164 if (ImageRecord
->CodeSegmentCount
== 0) {
1165 SetMemoryAttributesTableSectionAlignment (1);
1166 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1167 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1168 if (PdbPointer
!= NULL
) {
1169 DEBUG ((DEBUG_ERROR
, "SMM !!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1177 SortImageRecordCodeSection (ImageRecord
);
1179 // Check overlap all section in ImageBase/Size
1181 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1182 DEBUG ((DEBUG_ERROR
, "SMM IsImageRecordCodeSectionValid - FAIL\n"));
1186 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1187 mImagePropertiesPrivateData
.ImageRecordCount
++;
1189 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1190 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1201 Publish MemoryAttributesTable to SMM configuration table.
1204 PublishMemoryAttributesTable (
1208 UINTN MemoryMapSize
;
1209 EFI_MEMORY_DESCRIPTOR
*MemoryMap
;
1211 UINTN DescriptorSize
;
1212 UINT32 DescriptorVersion
;
1215 UINTN RuntimeEntryCount
;
1216 EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
*MemoryAttributesTable
;
1217 EFI_MEMORY_DESCRIPTOR
*MemoryAttributesEntry
;
1218 UINTN MemoryAttributesTableSize
;
1222 Status
= SmmCoreGetMemoryMapMemoryAttributesTable (
1229 ASSERT (Status
== EFI_BUFFER_TOO_SMALL
);
1232 DEBUG ((DEBUG_INFO
, "MemoryMapSize - 0x%x\n", MemoryMapSize
));
1233 MemoryMap
= AllocatePool (MemoryMapSize
);
1234 ASSERT (MemoryMap
!= NULL
);
1235 DEBUG ((DEBUG_INFO
, "MemoryMap - 0x%x\n", MemoryMap
));
1237 Status
= SmmCoreGetMemoryMapMemoryAttributesTable (
1244 if (EFI_ERROR (Status
)) {
1245 FreePool (MemoryMap
);
1247 } while (Status
== EFI_BUFFER_TOO_SMALL
);
1250 // Allocate MemoryAttributesTable
1252 RuntimeEntryCount
= MemoryMapSize
/DescriptorSize
;
1253 MemoryAttributesTableSize
= sizeof(EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
;
1254 MemoryAttributesTable
= AllocatePool (sizeof(EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE
) + DescriptorSize
* RuntimeEntryCount
);
1255 ASSERT (MemoryAttributesTable
!= NULL
);
1256 MemoryAttributesTable
->Version
= EDKII_PI_SMM_MEMORY_ATTRIBUTES_TABLE_VERSION
;
1257 MemoryAttributesTable
->NumberOfEntries
= (UINT32
)RuntimeEntryCount
;
1258 MemoryAttributesTable
->DescriptorSize
= (UINT32
)DescriptorSize
;
1259 MemoryAttributesTable
->Reserved
= 0;
1260 DEBUG ((DEBUG_INFO
, "MemoryAttributesTable:\n"));
1261 DEBUG ((DEBUG_INFO
, " Version - 0x%08x\n", MemoryAttributesTable
->Version
));
1262 DEBUG ((DEBUG_INFO
, " NumberOfEntries - 0x%08x\n", MemoryAttributesTable
->NumberOfEntries
));
1263 DEBUG ((DEBUG_INFO
, " DescriptorSize - 0x%08x\n", MemoryAttributesTable
->DescriptorSize
));
1264 MemoryAttributesEntry
= (EFI_MEMORY_DESCRIPTOR
*)(MemoryAttributesTable
+ 1);
1265 for (Index
= 0; Index
< MemoryMapSize
/DescriptorSize
; Index
++) {
1266 CopyMem (MemoryAttributesEntry
, MemoryMap
, DescriptorSize
);
1267 DEBUG ((DEBUG_INFO
, "Entry (0x%x)\n", MemoryAttributesEntry
));
1268 DEBUG ((DEBUG_INFO
, " Type - 0x%x\n", MemoryAttributesEntry
->Type
));
1269 DEBUG ((DEBUG_INFO
, " PhysicalStart - 0x%016lx\n", MemoryAttributesEntry
->PhysicalStart
));
1270 DEBUG ((DEBUG_INFO
, " VirtualStart - 0x%016lx\n", MemoryAttributesEntry
->VirtualStart
));
1271 DEBUG ((DEBUG_INFO
, " NumberOfPages - 0x%016lx\n", MemoryAttributesEntry
->NumberOfPages
));
1272 DEBUG ((DEBUG_INFO
, " Attribute - 0x%016lx\n", MemoryAttributesEntry
->Attribute
));
1273 MemoryAttributesEntry
= NEXT_MEMORY_DESCRIPTOR(MemoryAttributesEntry
, DescriptorSize
);
1275 MemoryMap
= NEXT_MEMORY_DESCRIPTOR(MemoryMap
, DescriptorSize
);
1278 Status
= gSmst
->SmmInstallConfigurationTable (gSmst
, &gEdkiiPiSmmMemoryAttributesTableGuid
, MemoryAttributesTable
, MemoryAttributesTableSize
);
1279 ASSERT_EFI_ERROR (Status
);
1284 This function installs all SMM image record information.
1287 SmmInstallImageRecord (
1293 EFI_HANDLE
*HandleBuffer
;
1294 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
1296 EFI_SMM_DRIVER_ENTRY DriverEntry
;
1298 Status
= SmmLocateHandleBuffer (
1300 &gEfiLoadedImageProtocolGuid
,
1305 if (EFI_ERROR (Status
)) {
1309 for (Index
= 0; Index
< NoHandles
; Index
++) {
1310 Status
= gSmst
->SmmHandleProtocol (
1311 HandleBuffer
[Index
],
1312 &gEfiLoadedImageProtocolGuid
,
1313 (VOID
**)&LoadedImage
1315 if (EFI_ERROR (Status
)) {
1318 DEBUG ((DEBUG_VERBOSE
, "LoadedImage - 0x%x 0x%x ", LoadedImage
->ImageBase
, LoadedImage
->ImageSize
));
1321 PdbPointer
= PeCoffLoaderGetPdbPointer (LoadedImage
->ImageBase
);
1322 if (PdbPointer
!= NULL
) {
1323 DEBUG ((DEBUG_VERBOSE
, "(%a) ", PdbPointer
));
1326 DEBUG ((DEBUG_VERBOSE
, "\n"));
1327 ZeroMem (&DriverEntry
, sizeof(DriverEntry
));
1328 DriverEntry
.ImageBuffer
= (UINTN
)LoadedImage
->ImageBase
;
1329 DriverEntry
.NumberOfPage
= EFI_SIZE_TO_PAGES((UINTN
)LoadedImage
->ImageSize
);
1330 SmmInsertImageRecord (&DriverEntry
);
1333 FreePool (HandleBuffer
);
1337 Install MemoryAttributesTable.
1339 @param[in] Protocol Points to the protocol's unique identifier.
1340 @param[in] Interface Points to the interface instance.
1341 @param[in] Handle The handle on which the interface was installed.
1343 @retval EFI_SUCCESS Notification runs successfully.
1347 SmmInstallMemoryAttributesTable (
1348 IN CONST EFI_GUID
*Protocol
,
1350 IN EFI_HANDLE Handle
1353 SmmInstallImageRecord ();
1355 DEBUG ((DEBUG_INFO
, "SMM MemoryProtectionAttribute - 0x%016lx\n", mMemoryProtectionAttribute
));
1356 if ((mMemoryProtectionAttribute
& EFI_MEMORY_ATTRIBUTES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1360 DEBUG ((DEBUG_VERBOSE
, "SMM Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1361 DEBUG ((DEBUG_VERBOSE
, "SMM Dump ImageRecord:\n"));
1364 PublishMemoryAttributesTable ();
1370 Initialize MemoryAttributesTable support.
1374 SmmCoreInitializeMemoryAttributesTable (
1381 Status
= gSmst
->SmmRegisterProtocolNotify (
1382 &gEfiSmmEndOfDxeProtocolGuid
,
1383 SmmInstallMemoryAttributesTable
,
1386 ASSERT_EFI_ERROR (Status
);