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.
187 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
188 IN OUT UINTN
*MemoryMapSize
,
189 IN UINTN DescriptorSize
192 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
193 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
194 UINT64 MemoryBlockLength
;
195 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
196 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
198 MemoryMapEntry
= MemoryMap
;
199 NewMemoryMapEntry
= MemoryMap
;
200 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
201 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
202 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
203 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
206 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
207 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
208 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
209 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
210 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
211 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
212 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
213 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
216 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
219 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
224 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
225 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
228 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
234 Enforce memory map attributes.
235 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
237 @param MemoryMap A pointer to the buffer in which firmware places
238 the current memory map.
239 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
240 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
244 EnforceMemoryMapAttribute (
245 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
246 IN UINTN MemoryMapSize
,
247 IN UINTN DescriptorSize
250 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
251 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
253 MemoryMapEntry
= MemoryMap
;
254 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
255 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
256 switch (MemoryMapEntry
->Type
) {
257 case EfiRuntimeServicesCode
:
260 case EfiRuntimeServicesData
:
261 case EfiMemoryMappedIO
:
262 case EfiMemoryMappedIOPortSpace
:
263 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
265 case EfiReservedMemoryType
:
266 case EfiACPIMemoryNVS
:
270 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
277 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
279 @param Buffer Start Address
280 @param Length Address length
282 @return first image record covered by [buffer, length]
285 IMAGE_PROPERTIES_RECORD
*
286 GetImageRecordByAddress (
287 IN EFI_PHYSICAL_ADDRESS Buffer
,
291 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
292 LIST_ENTRY
*ImageRecordLink
;
293 LIST_ENTRY
*ImageRecordList
;
295 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
297 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
298 ImageRecordLink
!= ImageRecordList
;
299 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
302 IMAGE_PROPERTIES_RECORD
,
304 IMAGE_PROPERTIES_RECORD_SIGNATURE
307 if ((Buffer
<= ImageRecord
->ImageBase
) &&
308 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
317 Set the memory map to new entries, according to one old entry,
318 based upon PE code section and data section in image record
320 @param ImageRecord An image record whose [ImageBase, ImageSize] covered
321 by old memory map entry.
322 @param NewRecord A pointer to several new memory map entries.
323 The caller gurantee the buffer size be 1 +
324 (SplitRecordCount * DescriptorSize) calculated
326 @param OldRecord A pointer to one old memory map entry.
327 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
332 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
333 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
334 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
335 IN UINTN DescriptorSize
338 EFI_MEMORY_DESCRIPTOR TempRecord
;
339 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
340 LIST_ENTRY
*ImageRecordCodeSectionLink
;
341 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
342 LIST_ENTRY
*ImageRecordCodeSectionList
;
343 UINTN NewRecordCount
;
347 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
348 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
351 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
353 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
354 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
355 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
356 ImageRecordCodeSection
= CR (
357 ImageRecordCodeSectionLink
,
358 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
360 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
362 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
364 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
368 if (!mPropertiesTableEnable
) {
369 NewRecord
->Type
= TempRecord
.Type
;
371 NewRecord
->Type
= EfiRuntimeServicesData
;
373 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
374 NewRecord
->VirtualStart
= 0;
375 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
376 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
377 if (NewRecord
->NumberOfPages
!= 0) {
378 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
385 if (!mPropertiesTableEnable
) {
386 NewRecord
->Type
= TempRecord
.Type
;
388 NewRecord
->Type
= EfiRuntimeServicesCode
;
390 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
391 NewRecord
->VirtualStart
= 0;
392 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
393 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
394 if (NewRecord
->NumberOfPages
!= 0) {
395 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
399 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
400 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
401 if (TempRecord
.NumberOfPages
== 0) {
407 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
412 if (TempRecord
.PhysicalStart
< ImageEnd
) {
413 if (!mPropertiesTableEnable
) {
414 NewRecord
->Type
= TempRecord
.Type
;
416 NewRecord
->Type
= EfiRuntimeServicesData
;
418 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
419 NewRecord
->VirtualStart
= 0;
420 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
421 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
425 return NewRecordCount
;
429 Return the max number of new splitted entries, according to one old entry,
430 based upon PE code section and data section.
432 @param OldRecord A pointer to one old memory map entry.
434 @retval 0 no entry need to be splitted.
435 @return the max number of new splitted entries
439 GetMaxSplitRecordCount (
440 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
443 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
444 UINTN SplitRecordCount
;
445 UINT64 PhysicalStart
;
448 SplitRecordCount
= 0;
449 PhysicalStart
= OldRecord
->PhysicalStart
;
450 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
453 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
454 if (ImageRecord
== NULL
) {
457 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 1);
458 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
459 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
461 if (SplitRecordCount
!= 0) {
465 return SplitRecordCount
;
469 Split the memory map to new entries, according to one old entry,
470 based upon PE code section and data section.
472 @param OldRecord A pointer to one old memory map entry.
473 @param NewRecord A pointer to several new memory map entries.
474 The caller gurantee the buffer size be 1 +
475 (SplitRecordCount * DescriptorSize) calculated
477 @param MaxSplitRecordCount The max number of splitted entries
478 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
480 @retval 0 no entry is splitted.
481 @return the real number of splitted record.
486 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
487 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
488 IN UINTN MaxSplitRecordCount
,
489 IN UINTN DescriptorSize
492 EFI_MEMORY_DESCRIPTOR TempRecord
;
493 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
494 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
495 UINT64 PhysicalStart
;
497 UINTN NewRecordCount
;
498 UINTN TotalNewRecordCount
;
499 BOOLEAN IsLastRecordData
;
501 if (MaxSplitRecordCount
== 0) {
502 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
506 TotalNewRecordCount
= 0;
509 // Override previous record
511 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
512 PhysicalStart
= TempRecord
.PhysicalStart
;
513 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
517 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
518 if (NewImageRecord
== NULL
) {
520 // No more image covered by this range, stop
522 if ((PhysicalEnd
> PhysicalStart
) && (ImageRecord
!= NULL
)) {
524 // If this is still address in this record, need record.
526 NewRecord
= PREVIOUS_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
527 IsLastRecordData
= FALSE
;
528 if (!mPropertiesTableEnable
) {
529 if ((NewRecord
->Attribute
& EFI_MEMORY_XP
) != 0) {
530 IsLastRecordData
= TRUE
;
533 if (NewRecord
->Type
== EfiRuntimeServicesData
) {
534 IsLastRecordData
= TRUE
;
537 if (IsLastRecordData
) {
539 // Last record is DATA, just merge it.
541 NewRecord
->NumberOfPages
= EfiSizeToPages(PhysicalEnd
- NewRecord
->PhysicalStart
);
544 // Last record is CODE, create a new DATA entry.
546 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
547 if (!mPropertiesTableEnable
) {
548 NewRecord
->Type
= TempRecord
.Type
;
550 NewRecord
->Type
= EfiRuntimeServicesData
;
552 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
553 NewRecord
->VirtualStart
= 0;
554 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
555 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
556 TotalNewRecordCount
++;
561 ImageRecord
= NewImageRecord
;
566 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
567 TotalNewRecordCount
+= NewRecordCount
;
568 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
571 // Update PhysicalStart, in order to exclude the image buffer already splitted.
573 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
574 TempRecord
.PhysicalStart
= PhysicalStart
;
575 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
576 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
579 // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
580 // code reaches here.
582 ASSERT (TotalNewRecordCount
!= 0);
583 return TotalNewRecordCount
- 1;
587 Split the original memory map, and add more entries to describe PE code section and data section.
588 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
589 This function will merge entries with same attributes finally.
591 NOTE: It assumes PE code/data section are page aligned.
592 NOTE: It assumes enough entry is prepared for new memory map.
605 +---------------+ ----
608 | Record RtCode | |-> PE/COFF1
611 +---------------+ ----
614 | Record RtCode | |-> PE/COFF2
617 +---------------+ ----
621 @param MemoryMapSize A pointer to the size, in bytes, of the
622 MemoryMap buffer. On input, this is the size of
623 old MemoryMap before split. The actual buffer
624 size of MemoryMap is MemoryMapSize +
625 (AdditionalRecordCount * DescriptorSize) calculated
626 below. On output, it is the size of new MemoryMap
628 @param MemoryMap A pointer to the buffer in which firmware places
629 the current memory map.
630 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
635 IN OUT UINTN
*MemoryMapSize
,
636 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
637 IN UINTN DescriptorSize
642 UINTN MaxSplitRecordCount
;
643 UINTN RealSplitRecordCount
;
644 UINTN TotalSplitRecordCount
;
645 UINTN AdditionalRecordCount
;
647 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
649 TotalSplitRecordCount
= 0;
651 // Let old record point to end of valid MemoryMap buffer.
653 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
655 // Let new record point to end of full MemoryMap buffer.
657 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
658 for (; IndexOld
>= 0; IndexOld
--) {
659 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
661 // Split this MemoryMap record
663 IndexNew
-= MaxSplitRecordCount
;
664 RealSplitRecordCount
= SplitRecord (
665 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
666 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
671 // Adjust IndexNew according to real split.
674 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
675 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
676 RealSplitRecordCount
* DescriptorSize
678 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
679 TotalSplitRecordCount
+= RealSplitRecordCount
;
683 // Move all records to the beginning.
687 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
688 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
691 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
694 // Sort from low to high (Just in case)
696 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
699 // Set RuntimeData to XP
701 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
704 // Merge same type to save entry size
706 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
712 This function for GetMemoryMap() with properties table capability.
714 It calls original GetMemoryMap() to get the original memory map information. Then
715 plus the additional memory map entries for PE Code/Data seperation.
717 @param MemoryMapSize A pointer to the size, in bytes, of the
718 MemoryMap buffer. On input, this is the size of
719 the buffer allocated by the caller. On output,
720 it is the size of the buffer returned by the
721 firmware if the buffer was large enough, or the
722 size of the buffer needed to contain the map if
723 the buffer was too small.
724 @param MemoryMap A pointer to the buffer in which firmware places
725 the current memory map.
726 @param MapKey A pointer to the location in which firmware
727 returns the key for the current memory map.
728 @param DescriptorSize A pointer to the location in which firmware
729 returns the size, in bytes, of an individual
730 EFI_MEMORY_DESCRIPTOR.
731 @param DescriptorVersion A pointer to the location in which firmware
732 returns the version number associated with the
733 EFI_MEMORY_DESCRIPTOR.
735 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
737 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
738 buffer size needed to hold the memory map is
739 returned in MemoryMapSize.
740 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
745 CoreGetMemoryMapWithSeparatedImageSection (
746 IN OUT UINTN
*MemoryMapSize
,
747 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
749 OUT UINTN
*DescriptorSize
,
750 OUT UINT32
*DescriptorVersion
754 UINTN OldMemoryMapSize
;
755 UINTN AdditionalRecordCount
;
758 // If PE code/data is not aligned, just return.
760 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
761 return CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
764 if (MemoryMapSize
== NULL
) {
765 return EFI_INVALID_PARAMETER
;
768 CoreAcquirePropertiesTableLock ();
770 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
772 OldMemoryMapSize
= *MemoryMapSize
;
773 Status
= CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
774 if (Status
== EFI_BUFFER_TOO_SMALL
) {
775 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
776 } else if (Status
== EFI_SUCCESS
) {
777 ASSERT (MemoryMap
!= NULL
);
778 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
779 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
781 // Need update status to buffer too small
783 Status
= EFI_BUFFER_TOO_SMALL
;
786 // Split PE code/data
788 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
792 CoreReleasePropertiesTableLock ();
797 // Below functions are for ImageRecord
801 Set PropertiesTable according to PE/COFF image section alignment.
803 @param SectionAlignment PE/COFF section alignment
807 SetPropertiesTableSectionAlignment (
808 IN UINT32 SectionAlignment
811 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
812 ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
813 DEBUG ((EFI_D_VERBOSE
, "SetPropertiesTableSectionAlignment - Clear\n"));
814 mPropertiesTable
.MemoryProtectionAttribute
&= ~((UINT64
)EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
815 gBS
->GetMemoryMap
= CoreGetMemoryMap
;
817 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
822 Swap two code sections in image record.
824 @param FirstImageRecordCodeSection first code section in image record
825 @param SecondImageRecordCodeSection second code section in image record
829 SwapImageRecordCodeSection (
830 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
831 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
834 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
836 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
837 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
839 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
840 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
842 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
843 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
847 Sort code section in image record, based upon CodeSegmentBase from low to high.
849 @param ImageRecord image record to be sorted
852 SortImageRecordCodeSection (
853 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
856 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
857 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
858 LIST_ENTRY
*ImageRecordCodeSectionLink
;
859 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
860 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
861 LIST_ENTRY
*ImageRecordCodeSectionList
;
863 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
865 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
866 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
867 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
868 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
869 ImageRecordCodeSection
= CR (
870 ImageRecordCodeSectionLink
,
871 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
873 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
875 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
876 NextImageRecordCodeSection
= CR (
877 NextImageRecordCodeSectionLink
,
878 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
880 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
882 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
883 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
885 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
888 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
889 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
894 Check if code section in image record is valid.
896 @param ImageRecord image record to be checked
898 @retval TRUE image record is valid
899 @retval FALSE image record is invalid
902 IsImageRecordCodeSectionValid (
903 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
906 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
907 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
908 LIST_ENTRY
*ImageRecordCodeSectionLink
;
909 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
910 LIST_ENTRY
*ImageRecordCodeSectionList
;
912 DEBUG ((EFI_D_VERBOSE
, "ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
914 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
916 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
917 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
918 LastImageRecordCodeSection
= NULL
;
919 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
920 ImageRecordCodeSection
= CR (
921 ImageRecordCodeSectionLink
,
922 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
924 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
926 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
929 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
932 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
935 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
938 if (LastImageRecordCodeSection
!= NULL
) {
939 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
944 LastImageRecordCodeSection
= ImageRecordCodeSection
;
945 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
952 Swap two image records.
954 @param FirstImageRecord first image record.
955 @param SecondImageRecord second image record.
960 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
961 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
964 IMAGE_PROPERTIES_RECORD TempImageRecord
;
966 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
967 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
968 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
970 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
971 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
972 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
974 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
975 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
976 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
978 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
982 Sort image record based upon the ImageBase from low to high.
990 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
991 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
992 LIST_ENTRY
*ImageRecordLink
;
993 LIST_ENTRY
*NextImageRecordLink
;
994 LIST_ENTRY
*ImageRecordEndLink
;
995 LIST_ENTRY
*ImageRecordList
;
997 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
999 ImageRecordLink
= ImageRecordList
->ForwardLink
;
1000 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1001 ImageRecordEndLink
= ImageRecordList
;
1002 while (ImageRecordLink
!= ImageRecordEndLink
) {
1005 IMAGE_PROPERTIES_RECORD
,
1007 IMAGE_PROPERTIES_RECORD_SIGNATURE
1009 while (NextImageRecordLink
!= ImageRecordEndLink
) {
1010 NextImageRecord
= CR (
1011 NextImageRecordLink
,
1012 IMAGE_PROPERTIES_RECORD
,
1014 IMAGE_PROPERTIES_RECORD_SIGNATURE
1016 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
1017 SwapImageRecord (ImageRecord
, NextImageRecord
);
1019 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
1022 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
1023 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1036 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1037 LIST_ENTRY
*ImageRecordLink
;
1038 LIST_ENTRY
*ImageRecordList
;
1041 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1043 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1044 ImageRecordLink
!= ImageRecordList
;
1045 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1048 IMAGE_PROPERTIES_RECORD
,
1050 IMAGE_PROPERTIES_RECORD_SIGNATURE
1052 DEBUG ((EFI_D_VERBOSE
, " Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1057 Insert image record.
1059 @param RuntimeImage Runtime image information
1063 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1067 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1068 UINT32 PeCoffHeaderOffset
;
1069 UINT32 SectionAlignment
;
1070 EFI_IMAGE_SECTION_HEADER
*Section
;
1071 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1074 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1076 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1079 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%x\n", RuntimeImage
));
1080 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1082 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1083 if (ImageRecord
== NULL
) {
1086 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1088 DEBUG ((EFI_D_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1091 // Step 1: record whole region
1093 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1094 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1096 ImageAddress
= RuntimeImage
->ImageBase
;
1098 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1099 if (PdbPointer
!= NULL
) {
1100 DEBUG ((EFI_D_VERBOSE
, " Image - %a\n", PdbPointer
));
1104 // Check PE/COFF image
1106 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1107 PeCoffHeaderOffset
= 0;
1108 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1109 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1112 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1113 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1114 DEBUG ((EFI_D_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1115 // It might be image in SMM.
1120 // Get SectionAlignment
1122 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1124 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1125 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1126 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1127 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1129 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1132 // Get the magic value from the PE/COFF Optional Header
1134 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1136 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1137 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1139 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1142 SetPropertiesTableSectionAlignment (SectionAlignment
);
1143 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1144 DEBUG ((EFI_D_WARN
, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1145 SectionAlignment
, RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1146 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1147 if (PdbPointer
!= NULL
) {
1148 DEBUG ((EFI_D_WARN
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1153 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1154 (UINT8
*) (UINTN
) ImageAddress
+
1155 PeCoffHeaderOffset
+
1157 sizeof(EFI_IMAGE_FILE_HEADER
) +
1158 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1160 ImageRecord
->CodeSegmentCount
= 0;
1161 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1162 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1163 Name
= Section
[Index
].Name
;
1166 " Section - '%c%c%c%c%c%c%c%c'\n",
1177 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1178 DEBUG ((EFI_D_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1179 DEBUG ((EFI_D_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1180 DEBUG ((EFI_D_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1181 DEBUG ((EFI_D_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1182 DEBUG ((EFI_D_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1183 DEBUG ((EFI_D_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1184 DEBUG ((EFI_D_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1185 DEBUG ((EFI_D_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1186 DEBUG ((EFI_D_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1189 // Step 2: record code section
1191 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1192 if (ImageRecordCodeSection
== NULL
) {
1195 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1197 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1198 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1200 DEBUG ((EFI_D_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1202 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1203 ImageRecord
->CodeSegmentCount
++;
1207 if (ImageRecord
->CodeSegmentCount
== 0) {
1208 SetPropertiesTableSectionAlignment (1);
1209 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1210 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1211 if (PdbPointer
!= NULL
) {
1212 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1220 SortImageRecordCodeSection (ImageRecord
);
1222 // Check overlap all section in ImageBase/Size
1224 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1225 DEBUG ((EFI_D_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1229 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1230 mImagePropertiesPrivateData
.ImageRecordCount
++;
1232 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1233 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1243 Find image record according to image base and size.
1245 @param ImageBase Base of PE image
1246 @param ImageSize Size of PE image
1248 @return image record
1251 IMAGE_PROPERTIES_RECORD
*
1253 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1257 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1258 LIST_ENTRY
*ImageRecordLink
;
1259 LIST_ENTRY
*ImageRecordList
;
1261 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1263 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1264 ImageRecordLink
!= ImageRecordList
;
1265 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1268 IMAGE_PROPERTIES_RECORD
,
1270 IMAGE_PROPERTIES_RECORD_SIGNATURE
1273 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1274 (ImageSize
== ImageRecord
->ImageSize
)) {
1283 Remove Image record.
1285 @param RuntimeImage Runtime image information
1289 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1292 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1293 LIST_ENTRY
*CodeSegmentListHead
;
1294 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1296 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1297 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1299 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1300 if (ImageRecord
== NULL
) {
1301 DEBUG ((EFI_D_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1305 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1306 while (!IsListEmpty (CodeSegmentListHead
)) {
1307 ImageRecordCodeSection
= CR (
1308 CodeSegmentListHead
->ForwardLink
,
1309 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1311 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1313 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1314 FreePool (ImageRecordCodeSection
);
1317 RemoveEntryList (&ImageRecord
->Link
);
1318 FreePool (ImageRecord
);
1319 mImagePropertiesPrivateData
.ImageRecordCount
--;
1324 Install PropertiesTable.
1326 @param[in] Event The Event this notify function registered to.
1327 @param[in] Context Pointer to the context data registered to the Event.
1331 InstallPropertiesTable (
1336 if (PcdGetBool (PcdPropertiesTableEnable
)) {
1339 Status
= gBS
->InstallConfigurationTable (&gEfiPropertiesTableGuid
, &mPropertiesTable
);
1340 ASSERT_EFI_ERROR (Status
);
1342 DEBUG ((EFI_D_INFO
, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable
.MemoryProtectionAttribute
));
1343 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1344 DEBUG ((EFI_D_ERROR
, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));
1345 DEBUG ((EFI_D_ERROR
, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1349 gBS
->GetMemoryMap
= CoreGetMemoryMapWithSeparatedImageSection
;
1351 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
1353 DEBUG ((EFI_D_VERBOSE
, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1354 DEBUG ((EFI_D_VERBOSE
, "Dump ImageRecord:\n"));
1357 mPropertiesTableEnable
= TRUE
;
1362 Initialize PropertiesTable support.
1366 CoreInitializePropertiesTable (
1371 EFI_EVENT EndOfDxeEvent
;
1373 Status
= gBS
->CreateEventEx (
1376 InstallPropertiesTable
,
1378 &gEfiEndOfDxeEventGroupGuid
,
1381 ASSERT_EFI_ERROR (Status
);