2 UEFI PropertiesTable support
4 Copyright (c) 2015 - 2017, 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/DxeServicesTableLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/UefiLib.h>
23 #include <Library/PcdLib.h>
25 #include <Guid/EventGroup.h>
26 #include <Protocol/DxeSmmReadyToLock.h>
28 #include <Library/PeCoffLib.h>
29 #include <Library/PeCoffGetEntryPointLib.h>
30 #include <Protocol/Runtime.h>
32 #include <Guid/PropertiesTable.h>
36 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
37 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
39 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
43 UINTN ImageRecordCount
;
44 UINTN CodeSegmentCountMax
;
45 LIST_ENTRY ImageRecordList
;
46 } IMAGE_PROPERTIES_PRIVATE_DATA
;
48 IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData
= {
49 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE
,
52 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData
.ImageRecordList
)
55 EFI_PROPERTIES_TABLE mPropertiesTable
= {
56 EFI_PROPERTIES_TABLE_VERSION
,
57 sizeof(EFI_PROPERTIES_TABLE
),
58 EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
61 EFI_LOCK mPropertiesTableLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
63 BOOLEAN mPropertiesTableEnable
;
66 // Below functions are for MemoryMap
70 Converts a number of EFI_PAGEs to a size in bytes.
72 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
74 @param Pages The number of EFI_PAGES.
76 @return The number of bytes associated with the number of EFI_PAGEs specified
85 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
89 Converts a size, in bytes, to a number of EFI_PAGESs.
91 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
93 @param Size A size in bytes.
95 @return The number of EFI_PAGESs associated with the number of bytes specified
105 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
109 Acquire memory lock on mPropertiesTableLock.
113 CoreAcquirePropertiesTableLock (
117 CoreAcquireLock (&mPropertiesTableLock
);
121 Release memory lock on mPropertiesTableLock.
125 CoreReleasePropertiesTableLock (
129 CoreReleaseLock (&mPropertiesTableLock
);
133 Sort memory map entries based upon PhysicalStart, from low to high.
135 @param MemoryMap A pointer to the buffer in which firmware places
136 the current memory map.
137 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
138 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
143 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
144 IN UINTN MemoryMapSize
,
145 IN UINTN DescriptorSize
148 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
149 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
150 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
151 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
153 MemoryMapEntry
= MemoryMap
;
154 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
155 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
156 while (MemoryMapEntry
< MemoryMapEnd
) {
157 while (NextMemoryMapEntry
< MemoryMapEnd
) {
158 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
159 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
160 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
161 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
164 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
167 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
168 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
175 Merge continous memory map entries whose have same attributes.
177 @param MemoryMap A pointer to the buffer in which firmware places
178 the current memory map.
179 @param MemoryMapSize A pointer to the size, in bytes, of the
180 MemoryMap buffer. On input, this is the size of
181 the current memory map. On output,
182 it is the size of new memory map after merge.
183 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
188 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
189 IN OUT UINTN
*MemoryMapSize
,
190 IN UINTN DescriptorSize
193 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
194 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
195 UINT64 MemoryBlockLength
;
196 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
197 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
199 MemoryMapEntry
= MemoryMap
;
200 NewMemoryMapEntry
= MemoryMap
;
201 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
202 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
203 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
204 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
207 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
208 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
209 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
210 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
211 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
212 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
213 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
214 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
217 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
220 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
225 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
226 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
229 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
235 Enforce memory map attributes.
236 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
238 @param MemoryMap A pointer to the buffer in which firmware places
239 the current memory map.
240 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
241 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
245 EnforceMemoryMapAttribute (
246 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
247 IN UINTN MemoryMapSize
,
248 IN UINTN DescriptorSize
251 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
252 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
254 MemoryMapEntry
= MemoryMap
;
255 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
256 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
257 switch (MemoryMapEntry
->Type
) {
258 case EfiRuntimeServicesCode
:
261 case EfiRuntimeServicesData
:
262 case EfiMemoryMappedIO
:
263 case EfiMemoryMappedIOPortSpace
:
264 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
266 case EfiReservedMemoryType
:
267 case EfiACPIMemoryNVS
:
271 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
278 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
280 @param Buffer Start Address
281 @param Length Address length
283 @return first image record covered by [buffer, length]
286 IMAGE_PROPERTIES_RECORD
*
287 GetImageRecordByAddress (
288 IN EFI_PHYSICAL_ADDRESS Buffer
,
292 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
293 LIST_ENTRY
*ImageRecordLink
;
294 LIST_ENTRY
*ImageRecordList
;
296 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
298 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
299 ImageRecordLink
!= ImageRecordList
;
300 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
303 IMAGE_PROPERTIES_RECORD
,
305 IMAGE_PROPERTIES_RECORD_SIGNATURE
308 if ((Buffer
<= ImageRecord
->ImageBase
) &&
309 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
318 Set the memory map to new entries, according to one old entry,
319 based upon PE code section and data section in image record
321 @param ImageRecord An image record whose [ImageBase, ImageSize] covered
322 by old memory map entry.
323 @param NewRecord A pointer to several new memory map entries.
324 The caller gurantee the buffer size be 1 +
325 (SplitRecordCount * DescriptorSize) calculated
327 @param OldRecord A pointer to one old memory map entry.
328 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
333 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
334 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
335 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
336 IN UINTN DescriptorSize
339 EFI_MEMORY_DESCRIPTOR TempRecord
;
340 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
341 LIST_ENTRY
*ImageRecordCodeSectionLink
;
342 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
343 LIST_ENTRY
*ImageRecordCodeSectionList
;
344 UINTN NewRecordCount
;
348 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
349 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
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 if (!mPropertiesTableEnable
) {
370 NewRecord
->Type
= TempRecord
.Type
;
372 NewRecord
->Type
= EfiRuntimeServicesData
;
374 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
375 NewRecord
->VirtualStart
= 0;
376 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
377 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
378 if (NewRecord
->NumberOfPages
!= 0) {
379 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
386 if (!mPropertiesTableEnable
) {
387 NewRecord
->Type
= TempRecord
.Type
;
389 NewRecord
->Type
= EfiRuntimeServicesCode
;
391 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
392 NewRecord
->VirtualStart
= 0;
393 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
394 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
395 if (NewRecord
->NumberOfPages
!= 0) {
396 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
400 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
401 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
402 if (TempRecord
.NumberOfPages
== 0) {
408 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
413 if (TempRecord
.PhysicalStart
< ImageEnd
) {
414 if (!mPropertiesTableEnable
) {
415 NewRecord
->Type
= TempRecord
.Type
;
417 NewRecord
->Type
= EfiRuntimeServicesData
;
419 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
420 NewRecord
->VirtualStart
= 0;
421 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
422 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
426 return NewRecordCount
;
430 Return the max number of new splitted entries, according to one old entry,
431 based upon PE code section and data section.
433 @param OldRecord A pointer to one old memory map entry.
435 @retval 0 no entry need to be splitted.
436 @return the max number of new splitted entries
440 GetMaxSplitRecordCount (
441 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
444 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
445 UINTN SplitRecordCount
;
446 UINT64 PhysicalStart
;
449 SplitRecordCount
= 0;
450 PhysicalStart
= OldRecord
->PhysicalStart
;
451 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
454 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
455 if (ImageRecord
== NULL
) {
458 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 1);
459 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
460 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
462 if (SplitRecordCount
!= 0) {
466 return SplitRecordCount
;
470 Split the memory map to new entries, according to one old entry,
471 based upon PE code section and data section.
473 @param OldRecord A pointer to one old memory map entry.
474 @param NewRecord A pointer to several new memory map entries.
475 The caller gurantee the buffer size be 1 +
476 (SplitRecordCount * DescriptorSize) calculated
478 @param MaxSplitRecordCount The max number of splitted entries
479 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
481 @retval 0 no entry is splitted.
482 @return the real number of splitted record.
487 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
488 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
489 IN UINTN MaxSplitRecordCount
,
490 IN UINTN DescriptorSize
493 EFI_MEMORY_DESCRIPTOR TempRecord
;
494 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
495 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
496 UINT64 PhysicalStart
;
498 UINTN NewRecordCount
;
499 UINTN TotalNewRecordCount
;
500 BOOLEAN IsLastRecordData
;
502 if (MaxSplitRecordCount
== 0) {
503 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
507 TotalNewRecordCount
= 0;
510 // Override previous record
512 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
513 PhysicalStart
= TempRecord
.PhysicalStart
;
514 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
518 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
519 if (NewImageRecord
== NULL
) {
521 // No more image covered by this range, stop
523 if ((PhysicalEnd
> PhysicalStart
) && (ImageRecord
!= NULL
)) {
525 // If this is still address in this record, need record.
527 NewRecord
= PREVIOUS_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
528 IsLastRecordData
= FALSE
;
529 if (!mPropertiesTableEnable
) {
530 if ((NewRecord
->Attribute
& EFI_MEMORY_XP
) != 0) {
531 IsLastRecordData
= TRUE
;
534 if (NewRecord
->Type
== EfiRuntimeServicesData
) {
535 IsLastRecordData
= TRUE
;
538 if (IsLastRecordData
) {
540 // Last record is DATA, just merge it.
542 NewRecord
->NumberOfPages
= EfiSizeToPages(PhysicalEnd
- NewRecord
->PhysicalStart
);
545 // Last record is CODE, create a new DATA entry.
547 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
548 if (!mPropertiesTableEnable
) {
549 NewRecord
->Type
= TempRecord
.Type
;
551 NewRecord
->Type
= EfiRuntimeServicesData
;
553 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
554 NewRecord
->VirtualStart
= 0;
555 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
556 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
557 TotalNewRecordCount
++;
562 ImageRecord
= NewImageRecord
;
567 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
568 TotalNewRecordCount
+= NewRecordCount
;
569 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
572 // Update PhysicalStart, in order to exclude the image buffer already splitted.
574 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
575 TempRecord
.PhysicalStart
= PhysicalStart
;
576 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
577 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
579 return TotalNewRecordCount
- 1;
583 Split the original memory map, and add more entries to describe PE code section and data section.
584 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
585 This function will merge entries with same attributes finally.
587 NOTE: It assumes PE code/data section are page aligned.
588 NOTE: It assumes enough entry is prepared for new memory map.
601 +---------------+ ----
604 | Record RtCode | |-> PE/COFF1
607 +---------------+ ----
610 | Record RtCode | |-> PE/COFF2
613 +---------------+ ----
617 @param MemoryMapSize A pointer to the size, in bytes, of the
618 MemoryMap buffer. On input, this is the size of
619 old MemoryMap before split. The actual buffer
620 size of MemoryMap is MemoryMapSize +
621 (AdditionalRecordCount * DescriptorSize) calculated
622 below. On output, it is the size of new MemoryMap
624 @param MemoryMap A pointer to the buffer in which firmware places
625 the current memory map.
626 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
631 IN OUT UINTN
*MemoryMapSize
,
632 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
633 IN UINTN DescriptorSize
638 UINTN MaxSplitRecordCount
;
639 UINTN RealSplitRecordCount
;
640 UINTN TotalSplitRecordCount
;
641 UINTN AdditionalRecordCount
;
643 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
645 TotalSplitRecordCount
= 0;
647 // Let old record point to end of valid MemoryMap buffer.
649 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
651 // Let new record point to end of full MemoryMap buffer.
653 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
654 for (; IndexOld
>= 0; IndexOld
--) {
655 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
657 // Split this MemoryMap record
659 IndexNew
-= MaxSplitRecordCount
;
660 RealSplitRecordCount
= SplitRecord (
661 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
662 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
667 // Adjust IndexNew according to real split.
670 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
671 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
672 RealSplitRecordCount
* DescriptorSize
674 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
675 TotalSplitRecordCount
+= RealSplitRecordCount
;
679 // Move all records to the beginning.
683 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
684 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
687 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
690 // Sort from low to high (Just in case)
692 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
695 // Set RuntimeData to XP
697 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
700 // Merge same type to save entry size
702 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
708 This function for GetMemoryMap() with properties table capability.
710 It calls original GetMemoryMap() to get the original memory map information. Then
711 plus the additional memory map entries for PE Code/Data seperation.
713 @param MemoryMapSize A pointer to the size, in bytes, of the
714 MemoryMap buffer. On input, this is the size of
715 the buffer allocated by the caller. On output,
716 it is the size of the buffer returned by the
717 firmware if the buffer was large enough, or the
718 size of the buffer needed to contain the map if
719 the buffer was too small.
720 @param MemoryMap A pointer to the buffer in which firmware places
721 the current memory map.
722 @param MapKey A pointer to the location in which firmware
723 returns the key for the current memory map.
724 @param DescriptorSize A pointer to the location in which firmware
725 returns the size, in bytes, of an individual
726 EFI_MEMORY_DESCRIPTOR.
727 @param DescriptorVersion A pointer to the location in which firmware
728 returns the version number associated with the
729 EFI_MEMORY_DESCRIPTOR.
731 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
733 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
734 buffer size needed to hold the memory map is
735 returned in MemoryMapSize.
736 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
741 CoreGetMemoryMapWithSeparatedImageSection (
742 IN OUT UINTN
*MemoryMapSize
,
743 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
745 OUT UINTN
*DescriptorSize
,
746 OUT UINT32
*DescriptorVersion
750 UINTN OldMemoryMapSize
;
751 UINTN AdditionalRecordCount
;
754 // If PE code/data is not aligned, just return.
756 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
757 return CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
760 if (MemoryMapSize
== NULL
) {
761 return EFI_INVALID_PARAMETER
;
764 CoreAcquirePropertiesTableLock ();
766 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
768 OldMemoryMapSize
= *MemoryMapSize
;
769 Status
= CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
770 if (Status
== EFI_BUFFER_TOO_SMALL
) {
771 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
772 } else if (Status
== EFI_SUCCESS
) {
773 ASSERT (MemoryMap
!= NULL
);
774 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
775 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
777 // Need update status to buffer too small
779 Status
= EFI_BUFFER_TOO_SMALL
;
782 // Split PE code/data
784 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
788 CoreReleasePropertiesTableLock ();
793 // Below functions are for ImageRecord
797 Set PropertiesTable according to PE/COFF image section alignment.
799 @param SectionAlignment PE/COFF section alignment
803 SetPropertiesTableSectionAlignment (
804 IN UINT32 SectionAlignment
807 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
808 ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
809 DEBUG ((EFI_D_VERBOSE
, "SetPropertiesTableSectionAlignment - Clear\n"));
810 mPropertiesTable
.MemoryProtectionAttribute
&= ~((UINT64
)EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
811 gBS
->GetMemoryMap
= CoreGetMemoryMap
;
813 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
818 Swap two code sections in image record.
820 @param FirstImageRecordCodeSection first code section in image record
821 @param SecondImageRecordCodeSection second code section in image record
825 SwapImageRecordCodeSection (
826 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
827 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
830 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
832 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
833 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
835 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
836 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
838 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
839 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
843 Sort code section in image record, based upon CodeSegmentBase from low to high.
845 @param ImageRecord image record to be sorted
848 SortImageRecordCodeSection (
849 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
852 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
853 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
854 LIST_ENTRY
*ImageRecordCodeSectionLink
;
855 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
856 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
857 LIST_ENTRY
*ImageRecordCodeSectionList
;
859 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
861 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
862 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
863 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
864 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
865 ImageRecordCodeSection
= CR (
866 ImageRecordCodeSectionLink
,
867 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
869 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
871 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
872 NextImageRecordCodeSection
= CR (
873 NextImageRecordCodeSectionLink
,
874 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
876 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
878 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
879 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
881 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
884 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
885 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
890 Check if code section in image record is valid.
892 @param ImageRecord image record to be checked
894 @retval TRUE image record is valid
895 @retval FALSE image record is invalid
898 IsImageRecordCodeSectionValid (
899 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
902 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
903 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
904 LIST_ENTRY
*ImageRecordCodeSectionLink
;
905 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
906 LIST_ENTRY
*ImageRecordCodeSectionList
;
908 DEBUG ((EFI_D_VERBOSE
, "ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
910 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
912 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
913 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
914 LastImageRecordCodeSection
= NULL
;
915 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
916 ImageRecordCodeSection
= CR (
917 ImageRecordCodeSectionLink
,
918 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
920 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
922 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
925 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
928 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
931 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
934 if (LastImageRecordCodeSection
!= NULL
) {
935 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
940 LastImageRecordCodeSection
= ImageRecordCodeSection
;
941 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
948 Swap two image records.
950 @param FirstImageRecord first image record.
951 @param SecondImageRecord second image record.
956 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
957 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
960 IMAGE_PROPERTIES_RECORD TempImageRecord
;
962 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
963 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
964 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
966 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
967 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
968 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
970 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
971 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
972 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
974 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
978 Sort image record based upon the ImageBase from low to high.
986 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
987 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
988 LIST_ENTRY
*ImageRecordLink
;
989 LIST_ENTRY
*NextImageRecordLink
;
990 LIST_ENTRY
*ImageRecordEndLink
;
991 LIST_ENTRY
*ImageRecordList
;
993 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
995 ImageRecordLink
= ImageRecordList
->ForwardLink
;
996 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
997 ImageRecordEndLink
= ImageRecordList
;
998 while (ImageRecordLink
!= ImageRecordEndLink
) {
1001 IMAGE_PROPERTIES_RECORD
,
1003 IMAGE_PROPERTIES_RECORD_SIGNATURE
1005 while (NextImageRecordLink
!= ImageRecordEndLink
) {
1006 NextImageRecord
= CR (
1007 NextImageRecordLink
,
1008 IMAGE_PROPERTIES_RECORD
,
1010 IMAGE_PROPERTIES_RECORD_SIGNATURE
1012 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
1013 SwapImageRecord (ImageRecord
, NextImageRecord
);
1015 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
1018 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
1019 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1032 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1033 LIST_ENTRY
*ImageRecordLink
;
1034 LIST_ENTRY
*ImageRecordList
;
1037 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1039 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1040 ImageRecordLink
!= ImageRecordList
;
1041 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1044 IMAGE_PROPERTIES_RECORD
,
1046 IMAGE_PROPERTIES_RECORD_SIGNATURE
1048 DEBUG ((EFI_D_VERBOSE
, " Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1053 Insert image record.
1055 @param RuntimeImage Runtime image information
1059 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1063 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1064 UINT32 PeCoffHeaderOffset
;
1065 UINT32 SectionAlignment
;
1066 EFI_IMAGE_SECTION_HEADER
*Section
;
1067 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1070 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1072 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1075 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%x\n", RuntimeImage
));
1076 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1078 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1079 if (ImageRecord
== NULL
) {
1082 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1084 DEBUG ((EFI_D_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1087 // Step 1: record whole region
1089 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1090 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1092 ImageAddress
= RuntimeImage
->ImageBase
;
1094 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1095 if (PdbPointer
!= NULL
) {
1096 DEBUG ((EFI_D_VERBOSE
, " Image - %a\n", PdbPointer
));
1100 // Check PE/COFF image
1102 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1103 PeCoffHeaderOffset
= 0;
1104 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1105 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1108 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1109 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1110 DEBUG ((EFI_D_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1111 // It might be image in SMM.
1116 // Get SectionAlignment
1118 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1120 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1121 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1122 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1123 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1125 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1128 // Get the magic value from the PE/COFF Optional Header
1130 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1132 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1133 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1135 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1138 SetPropertiesTableSectionAlignment (SectionAlignment
);
1139 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1140 DEBUG ((EFI_D_WARN
, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1141 SectionAlignment
, RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1142 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1143 if (PdbPointer
!= NULL
) {
1144 DEBUG ((EFI_D_WARN
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1149 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1150 (UINT8
*) (UINTN
) ImageAddress
+
1151 PeCoffHeaderOffset
+
1153 sizeof(EFI_IMAGE_FILE_HEADER
) +
1154 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1156 ImageRecord
->CodeSegmentCount
= 0;
1157 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1158 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1159 Name
= Section
[Index
].Name
;
1162 " Section - '%c%c%c%c%c%c%c%c'\n",
1173 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1174 DEBUG ((EFI_D_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1175 DEBUG ((EFI_D_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1176 DEBUG ((EFI_D_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1177 DEBUG ((EFI_D_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1178 DEBUG ((EFI_D_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1179 DEBUG ((EFI_D_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1180 DEBUG ((EFI_D_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1181 DEBUG ((EFI_D_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1182 DEBUG ((EFI_D_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1185 // Step 2: record code section
1187 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1188 if (ImageRecordCodeSection
== NULL
) {
1191 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1193 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1194 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1196 DEBUG ((EFI_D_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1198 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1199 ImageRecord
->CodeSegmentCount
++;
1203 if (ImageRecord
->CodeSegmentCount
== 0) {
1204 SetPropertiesTableSectionAlignment (1);
1205 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1206 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1207 if (PdbPointer
!= NULL
) {
1208 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1216 SortImageRecordCodeSection (ImageRecord
);
1218 // Check overlap all section in ImageBase/Size
1220 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1221 DEBUG ((EFI_D_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1225 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1226 mImagePropertiesPrivateData
.ImageRecordCount
++;
1230 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1231 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1239 Find image record according to image base and size.
1241 @param ImageBase Base of PE image
1242 @param ImageSize Size of PE image
1244 @return image record
1247 IMAGE_PROPERTIES_RECORD
*
1249 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1253 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1254 LIST_ENTRY
*ImageRecordLink
;
1255 LIST_ENTRY
*ImageRecordList
;
1257 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1259 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1260 ImageRecordLink
!= ImageRecordList
;
1261 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1264 IMAGE_PROPERTIES_RECORD
,
1266 IMAGE_PROPERTIES_RECORD_SIGNATURE
1269 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1270 (ImageSize
== ImageRecord
->ImageSize
)) {
1279 Remove Image record.
1281 @param RuntimeImage Runtime image information
1285 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1288 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1289 LIST_ENTRY
*CodeSegmentListHead
;
1290 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1292 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1293 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1295 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1296 if (ImageRecord
== NULL
) {
1297 DEBUG ((EFI_D_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1301 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1302 while (!IsListEmpty (CodeSegmentListHead
)) {
1303 ImageRecordCodeSection
= CR (
1304 CodeSegmentListHead
->ForwardLink
,
1305 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1307 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1309 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1310 FreePool (ImageRecordCodeSection
);
1313 RemoveEntryList (&ImageRecord
->Link
);
1314 FreePool (ImageRecord
);
1315 mImagePropertiesPrivateData
.ImageRecordCount
--;
1320 Install PropertiesTable.
1322 @param[in] Event The Event this notify function registered to.
1323 @param[in] Context Pointer to the context data registered to the Event.
1327 InstallPropertiesTable (
1332 if (PcdGetBool (PcdPropertiesTableEnable
)) {
1335 Status
= gBS
->InstallConfigurationTable (&gEfiPropertiesTableGuid
, &mPropertiesTable
);
1336 ASSERT_EFI_ERROR (Status
);
1338 DEBUG ((EFI_D_INFO
, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable
.MemoryProtectionAttribute
));
1339 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1340 DEBUG ((EFI_D_ERROR
, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));
1341 DEBUG ((EFI_D_ERROR
, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1345 gBS
->GetMemoryMap
= CoreGetMemoryMapWithSeparatedImageSection
;
1347 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
1349 DEBUG ((EFI_D_VERBOSE
, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1350 DEBUG ((EFI_D_VERBOSE
, "Dump ImageRecord:\n"));
1353 mPropertiesTableEnable
= TRUE
;
1358 Initialize PropertiesTable support.
1362 CoreInitializePropertiesTable (
1367 EFI_EVENT EndOfDxeEvent
;
1369 Status
= gBS
->CreateEventEx (
1372 InstallPropertiesTable
,
1374 &gEfiEndOfDxeEventGroupGuid
,
1377 ASSERT_EFI_ERROR (Status
);