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
));
580 // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
581 // code reaches here.
583 ASSERT (TotalNewRecordCount
!= 0);
584 return TotalNewRecordCount
- 1;
588 Split the original memory map, and add more entries to describe PE code section and data section.
589 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
590 This function will merge entries with same attributes finally.
592 NOTE: It assumes PE code/data section are page aligned.
593 NOTE: It assumes enough entry is prepared for new memory map.
606 +---------------+ ----
609 | Record RtCode | |-> PE/COFF1
612 +---------------+ ----
615 | Record RtCode | |-> PE/COFF2
618 +---------------+ ----
622 @param MemoryMapSize A pointer to the size, in bytes, of the
623 MemoryMap buffer. On input, this is the size of
624 old MemoryMap before split. The actual buffer
625 size of MemoryMap is MemoryMapSize +
626 (AdditionalRecordCount * DescriptorSize) calculated
627 below. On output, it is the size of new MemoryMap
629 @param MemoryMap A pointer to the buffer in which firmware places
630 the current memory map.
631 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
636 IN OUT UINTN
*MemoryMapSize
,
637 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
638 IN UINTN DescriptorSize
643 UINTN MaxSplitRecordCount
;
644 UINTN RealSplitRecordCount
;
645 UINTN TotalSplitRecordCount
;
646 UINTN AdditionalRecordCount
;
648 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
650 TotalSplitRecordCount
= 0;
652 // Let old record point to end of valid MemoryMap buffer.
654 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
656 // Let new record point to end of full MemoryMap buffer.
658 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
659 for (; IndexOld
>= 0; IndexOld
--) {
660 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
662 // Split this MemoryMap record
664 IndexNew
-= MaxSplitRecordCount
;
665 RealSplitRecordCount
= SplitRecord (
666 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
667 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
672 // Adjust IndexNew according to real split.
675 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
676 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
677 RealSplitRecordCount
* DescriptorSize
679 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
680 TotalSplitRecordCount
+= RealSplitRecordCount
;
684 // Move all records to the beginning.
688 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
689 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
692 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
695 // Sort from low to high (Just in case)
697 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
700 // Set RuntimeData to XP
702 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
705 // Merge same type to save entry size
707 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
713 This function for GetMemoryMap() with properties table capability.
715 It calls original GetMemoryMap() to get the original memory map information. Then
716 plus the additional memory map entries for PE Code/Data seperation.
718 @param MemoryMapSize A pointer to the size, in bytes, of the
719 MemoryMap buffer. On input, this is the size of
720 the buffer allocated by the caller. On output,
721 it is the size of the buffer returned by the
722 firmware if the buffer was large enough, or the
723 size of the buffer needed to contain the map if
724 the buffer was too small.
725 @param MemoryMap A pointer to the buffer in which firmware places
726 the current memory map.
727 @param MapKey A pointer to the location in which firmware
728 returns the key for the current memory map.
729 @param DescriptorSize A pointer to the location in which firmware
730 returns the size, in bytes, of an individual
731 EFI_MEMORY_DESCRIPTOR.
732 @param DescriptorVersion A pointer to the location in which firmware
733 returns the version number associated with the
734 EFI_MEMORY_DESCRIPTOR.
736 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
738 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
739 buffer size needed to hold the memory map is
740 returned in MemoryMapSize.
741 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
746 CoreGetMemoryMapWithSeparatedImageSection (
747 IN OUT UINTN
*MemoryMapSize
,
748 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
750 OUT UINTN
*DescriptorSize
,
751 OUT UINT32
*DescriptorVersion
755 UINTN OldMemoryMapSize
;
756 UINTN AdditionalRecordCount
;
759 // If PE code/data is not aligned, just return.
761 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
762 return CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
765 if (MemoryMapSize
== NULL
) {
766 return EFI_INVALID_PARAMETER
;
769 CoreAcquirePropertiesTableLock ();
771 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
773 OldMemoryMapSize
= *MemoryMapSize
;
774 Status
= CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
775 if (Status
== EFI_BUFFER_TOO_SMALL
) {
776 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
777 } else if (Status
== EFI_SUCCESS
) {
778 ASSERT (MemoryMap
!= NULL
);
779 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
780 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
782 // Need update status to buffer too small
784 Status
= EFI_BUFFER_TOO_SMALL
;
787 // Split PE code/data
789 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
793 CoreReleasePropertiesTableLock ();
798 // Below functions are for ImageRecord
802 Set PropertiesTable according to PE/COFF image section alignment.
804 @param SectionAlignment PE/COFF section alignment
808 SetPropertiesTableSectionAlignment (
809 IN UINT32 SectionAlignment
812 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
813 ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
814 DEBUG ((EFI_D_VERBOSE
, "SetPropertiesTableSectionAlignment - Clear\n"));
815 mPropertiesTable
.MemoryProtectionAttribute
&= ~((UINT64
)EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
816 gBS
->GetMemoryMap
= CoreGetMemoryMap
;
818 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
823 Swap two code sections in image record.
825 @param FirstImageRecordCodeSection first code section in image record
826 @param SecondImageRecordCodeSection second code section in image record
830 SwapImageRecordCodeSection (
831 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
832 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
835 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
837 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
838 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
840 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
841 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
843 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
844 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
848 Sort code section in image record, based upon CodeSegmentBase from low to high.
850 @param ImageRecord image record to be sorted
853 SortImageRecordCodeSection (
854 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
857 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
858 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
859 LIST_ENTRY
*ImageRecordCodeSectionLink
;
860 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
861 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
862 LIST_ENTRY
*ImageRecordCodeSectionList
;
864 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
866 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
867 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
868 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
869 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
870 ImageRecordCodeSection
= CR (
871 ImageRecordCodeSectionLink
,
872 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
874 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
876 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
877 NextImageRecordCodeSection
= CR (
878 NextImageRecordCodeSectionLink
,
879 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
881 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
883 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
884 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
886 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
889 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
890 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
895 Check if code section in image record is valid.
897 @param ImageRecord image record to be checked
899 @retval TRUE image record is valid
900 @retval FALSE image record is invalid
903 IsImageRecordCodeSectionValid (
904 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
907 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
908 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
909 LIST_ENTRY
*ImageRecordCodeSectionLink
;
910 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
911 LIST_ENTRY
*ImageRecordCodeSectionList
;
913 DEBUG ((EFI_D_VERBOSE
, "ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
915 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
917 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
918 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
919 LastImageRecordCodeSection
= NULL
;
920 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
921 ImageRecordCodeSection
= CR (
922 ImageRecordCodeSectionLink
,
923 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
925 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
927 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
930 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
933 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
936 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
939 if (LastImageRecordCodeSection
!= NULL
) {
940 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
945 LastImageRecordCodeSection
= ImageRecordCodeSection
;
946 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
953 Swap two image records.
955 @param FirstImageRecord first image record.
956 @param SecondImageRecord second image record.
961 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
962 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
965 IMAGE_PROPERTIES_RECORD TempImageRecord
;
967 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
968 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
969 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
971 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
972 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
973 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
975 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
976 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
977 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
979 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
983 Sort image record based upon the ImageBase from low to high.
991 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
992 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
993 LIST_ENTRY
*ImageRecordLink
;
994 LIST_ENTRY
*NextImageRecordLink
;
995 LIST_ENTRY
*ImageRecordEndLink
;
996 LIST_ENTRY
*ImageRecordList
;
998 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1000 ImageRecordLink
= ImageRecordList
->ForwardLink
;
1001 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1002 ImageRecordEndLink
= ImageRecordList
;
1003 while (ImageRecordLink
!= ImageRecordEndLink
) {
1006 IMAGE_PROPERTIES_RECORD
,
1008 IMAGE_PROPERTIES_RECORD_SIGNATURE
1010 while (NextImageRecordLink
!= ImageRecordEndLink
) {
1011 NextImageRecord
= CR (
1012 NextImageRecordLink
,
1013 IMAGE_PROPERTIES_RECORD
,
1015 IMAGE_PROPERTIES_RECORD_SIGNATURE
1017 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
1018 SwapImageRecord (ImageRecord
, NextImageRecord
);
1020 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
1023 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
1024 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1037 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1038 LIST_ENTRY
*ImageRecordLink
;
1039 LIST_ENTRY
*ImageRecordList
;
1042 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1044 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1045 ImageRecordLink
!= ImageRecordList
;
1046 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1049 IMAGE_PROPERTIES_RECORD
,
1051 IMAGE_PROPERTIES_RECORD_SIGNATURE
1053 DEBUG ((EFI_D_VERBOSE
, " Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1058 Insert image record.
1060 @param RuntimeImage Runtime image information
1064 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1068 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1069 UINT32 PeCoffHeaderOffset
;
1070 UINT32 SectionAlignment
;
1071 EFI_IMAGE_SECTION_HEADER
*Section
;
1072 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1075 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1077 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1080 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%x\n", RuntimeImage
));
1081 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1083 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1084 if (ImageRecord
== NULL
) {
1087 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1089 DEBUG ((EFI_D_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1092 // Step 1: record whole region
1094 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1095 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1097 ImageAddress
= RuntimeImage
->ImageBase
;
1099 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1100 if (PdbPointer
!= NULL
) {
1101 DEBUG ((EFI_D_VERBOSE
, " Image - %a\n", PdbPointer
));
1105 // Check PE/COFF image
1107 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1108 PeCoffHeaderOffset
= 0;
1109 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1110 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1113 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1114 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1115 DEBUG ((EFI_D_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1116 // It might be image in SMM.
1121 // Get SectionAlignment
1123 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1125 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1126 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1127 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1128 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1130 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1133 // Get the magic value from the PE/COFF Optional Header
1135 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1137 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1138 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1140 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1143 SetPropertiesTableSectionAlignment (SectionAlignment
);
1144 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1145 DEBUG ((EFI_D_WARN
, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1146 SectionAlignment
, RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1147 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1148 if (PdbPointer
!= NULL
) {
1149 DEBUG ((EFI_D_WARN
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1154 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1155 (UINT8
*) (UINTN
) ImageAddress
+
1156 PeCoffHeaderOffset
+
1158 sizeof(EFI_IMAGE_FILE_HEADER
) +
1159 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1161 ImageRecord
->CodeSegmentCount
= 0;
1162 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1163 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1164 Name
= Section
[Index
].Name
;
1167 " Section - '%c%c%c%c%c%c%c%c'\n",
1178 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1179 DEBUG ((EFI_D_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1180 DEBUG ((EFI_D_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1181 DEBUG ((EFI_D_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1182 DEBUG ((EFI_D_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1183 DEBUG ((EFI_D_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1184 DEBUG ((EFI_D_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1185 DEBUG ((EFI_D_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1186 DEBUG ((EFI_D_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1187 DEBUG ((EFI_D_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1190 // Step 2: record code section
1192 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1193 if (ImageRecordCodeSection
== NULL
) {
1196 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1198 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1199 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1201 DEBUG ((EFI_D_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1203 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1204 ImageRecord
->CodeSegmentCount
++;
1208 if (ImageRecord
->CodeSegmentCount
== 0) {
1209 SetPropertiesTableSectionAlignment (1);
1210 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1211 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1212 if (PdbPointer
!= NULL
) {
1213 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1221 SortImageRecordCodeSection (ImageRecord
);
1223 // Check overlap all section in ImageBase/Size
1225 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1226 DEBUG ((EFI_D_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1230 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1231 mImagePropertiesPrivateData
.ImageRecordCount
++;
1235 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1236 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1244 Find image record according to image base and size.
1246 @param ImageBase Base of PE image
1247 @param ImageSize Size of PE image
1249 @return image record
1252 IMAGE_PROPERTIES_RECORD
*
1254 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1258 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1259 LIST_ENTRY
*ImageRecordLink
;
1260 LIST_ENTRY
*ImageRecordList
;
1262 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1264 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1265 ImageRecordLink
!= ImageRecordList
;
1266 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1269 IMAGE_PROPERTIES_RECORD
,
1271 IMAGE_PROPERTIES_RECORD_SIGNATURE
1274 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1275 (ImageSize
== ImageRecord
->ImageSize
)) {
1284 Remove Image record.
1286 @param RuntimeImage Runtime image information
1290 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1293 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1294 LIST_ENTRY
*CodeSegmentListHead
;
1295 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1297 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1298 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1300 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1301 if (ImageRecord
== NULL
) {
1302 DEBUG ((EFI_D_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1306 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1307 while (!IsListEmpty (CodeSegmentListHead
)) {
1308 ImageRecordCodeSection
= CR (
1309 CodeSegmentListHead
->ForwardLink
,
1310 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1312 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1314 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1315 FreePool (ImageRecordCodeSection
);
1318 RemoveEntryList (&ImageRecord
->Link
);
1319 FreePool (ImageRecord
);
1320 mImagePropertiesPrivateData
.ImageRecordCount
--;
1325 Install PropertiesTable.
1327 @param[in] Event The Event this notify function registered to.
1328 @param[in] Context Pointer to the context data registered to the Event.
1332 InstallPropertiesTable (
1337 if (PcdGetBool (PcdPropertiesTableEnable
)) {
1340 Status
= gBS
->InstallConfigurationTable (&gEfiPropertiesTableGuid
, &mPropertiesTable
);
1341 ASSERT_EFI_ERROR (Status
);
1343 DEBUG ((EFI_D_INFO
, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable
.MemoryProtectionAttribute
));
1344 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1345 DEBUG ((EFI_D_ERROR
, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));
1346 DEBUG ((EFI_D_ERROR
, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1350 gBS
->GetMemoryMap
= CoreGetMemoryMapWithSeparatedImageSection
;
1352 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
1354 DEBUG ((EFI_D_VERBOSE
, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1355 DEBUG ((EFI_D_VERBOSE
, "Dump ImageRecord:\n"));
1358 mPropertiesTableEnable
= TRUE
;
1363 Initialize PropertiesTable support.
1367 CoreInitializePropertiesTable (
1372 EFI_EVENT EndOfDxeEvent
;
1374 Status
= gBS
->CreateEventEx (
1377 InstallPropertiesTable
,
1379 &gEfiEndOfDxeEventGroupGuid
,
1382 ASSERT_EFI_ERROR (Status
);