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
;
65 BOOLEAN mPropertiesTableEndOfDxe
= FALSE
;
68 // Below functions are for MemoryMap
72 Converts a number of EFI_PAGEs to a size in bytes.
74 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
76 @param Pages The number of EFI_PAGES.
78 @return The number of bytes associated with the number of EFI_PAGEs specified
87 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
91 Converts a size, in bytes, to a number of EFI_PAGESs.
93 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
95 @param Size A size in bytes.
97 @return The number of EFI_PAGESs associated with the number of bytes specified
107 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
111 Acquire memory lock on mPropertiesTableLock.
115 CoreAcquirePropertiesTableLock (
119 CoreAcquireLock (&mPropertiesTableLock
);
123 Release memory lock on mPropertiesTableLock.
127 CoreReleasePropertiesTableLock (
131 CoreReleaseLock (&mPropertiesTableLock
);
135 Sort memory map entries based upon PhysicalStart, from low to high.
137 @param MemoryMap A pointer to the buffer in which firmware places
138 the current memory map.
139 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
140 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
145 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
146 IN UINTN MemoryMapSize
,
147 IN UINTN DescriptorSize
150 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
151 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
152 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
153 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
155 MemoryMapEntry
= MemoryMap
;
156 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
157 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
158 while (MemoryMapEntry
< MemoryMapEnd
) {
159 while (NextMemoryMapEntry
< MemoryMapEnd
) {
160 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
161 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
162 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
163 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
166 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
169 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
170 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
177 Merge continous memory map entries whose have same attributes.
179 @param MemoryMap A pointer to the buffer in which firmware places
180 the current memory map.
181 @param MemoryMapSize A pointer to the size, in bytes, of the
182 MemoryMap buffer. On input, this is the size of
183 the current memory map. On output,
184 it is the size of new memory map after merge.
185 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
189 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
190 IN OUT UINTN
*MemoryMapSize
,
191 IN UINTN DescriptorSize
194 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
195 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
196 UINT64 MemoryBlockLength
;
197 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
198 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
200 MemoryMapEntry
= MemoryMap
;
201 NewMemoryMapEntry
= MemoryMap
;
202 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
203 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
204 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
205 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
208 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
209 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
210 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
211 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
212 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
213 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
214 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
215 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
218 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
221 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
226 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
227 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
230 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
236 Enforce memory map attributes.
237 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
239 @param MemoryMap A pointer to the buffer in which firmware places
240 the current memory map.
241 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
242 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
246 EnforceMemoryMapAttribute (
247 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
248 IN UINTN MemoryMapSize
,
249 IN UINTN DescriptorSize
252 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
253 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
255 MemoryMapEntry
= MemoryMap
;
256 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
257 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
258 switch (MemoryMapEntry
->Type
) {
259 case EfiRuntimeServicesCode
:
262 case EfiRuntimeServicesData
:
263 case EfiMemoryMappedIO
:
264 case EfiMemoryMappedIOPortSpace
:
265 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
267 case EfiReservedMemoryType
:
268 case EfiACPIMemoryNVS
:
272 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
279 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
281 @param Buffer Start Address
282 @param Length Address length
284 @return first image record covered by [buffer, length]
287 IMAGE_PROPERTIES_RECORD
*
288 GetImageRecordByAddress (
289 IN EFI_PHYSICAL_ADDRESS Buffer
,
293 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
294 LIST_ENTRY
*ImageRecordLink
;
295 LIST_ENTRY
*ImageRecordList
;
297 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
299 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
300 ImageRecordLink
!= ImageRecordList
;
301 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
304 IMAGE_PROPERTIES_RECORD
,
306 IMAGE_PROPERTIES_RECORD_SIGNATURE
309 if ((Buffer
<= ImageRecord
->ImageBase
) &&
310 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
319 Set the memory map to new entries, according to one old entry,
320 based upon PE code section and data section in image record
322 @param ImageRecord An image record whose [ImageBase, ImageSize] covered
323 by old memory map entry.
324 @param NewRecord A pointer to several new memory map entries.
325 The caller gurantee the buffer size be 1 +
326 (SplitRecordCount * DescriptorSize) calculated
328 @param OldRecord A pointer to one old memory map entry.
329 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
334 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
335 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
336 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
337 IN UINTN DescriptorSize
340 EFI_MEMORY_DESCRIPTOR TempRecord
;
341 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
342 LIST_ENTRY
*ImageRecordCodeSectionLink
;
343 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
344 LIST_ENTRY
*ImageRecordCodeSectionList
;
345 UINTN NewRecordCount
;
349 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
350 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
353 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
355 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
356 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
357 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
358 ImageRecordCodeSection
= CR (
359 ImageRecordCodeSectionLink
,
360 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
362 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
364 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
366 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
370 if (!mPropertiesTableEnable
) {
371 NewRecord
->Type
= TempRecord
.Type
;
373 NewRecord
->Type
= EfiRuntimeServicesData
;
375 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
376 NewRecord
->VirtualStart
= 0;
377 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
378 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
379 if (NewRecord
->NumberOfPages
!= 0) {
380 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
387 if (!mPropertiesTableEnable
) {
388 NewRecord
->Type
= TempRecord
.Type
;
390 NewRecord
->Type
= EfiRuntimeServicesCode
;
392 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
393 NewRecord
->VirtualStart
= 0;
394 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
395 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
396 if (NewRecord
->NumberOfPages
!= 0) {
397 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
401 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
402 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
403 if (TempRecord
.NumberOfPages
== 0) {
409 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
414 if (TempRecord
.PhysicalStart
< ImageEnd
) {
415 if (!mPropertiesTableEnable
) {
416 NewRecord
->Type
= TempRecord
.Type
;
418 NewRecord
->Type
= EfiRuntimeServicesData
;
420 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
421 NewRecord
->VirtualStart
= 0;
422 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
423 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
427 return NewRecordCount
;
431 Return the max number of new splitted entries, according to one old entry,
432 based upon PE code section and data section.
434 @param OldRecord A pointer to one old memory map entry.
436 @retval 0 no entry need to be splitted.
437 @return the max number of new splitted entries
441 GetMaxSplitRecordCount (
442 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
445 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
446 UINTN SplitRecordCount
;
447 UINT64 PhysicalStart
;
450 SplitRecordCount
= 0;
451 PhysicalStart
= OldRecord
->PhysicalStart
;
452 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
455 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
456 if (ImageRecord
== NULL
) {
459 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 1);
460 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
461 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
463 if (SplitRecordCount
!= 0) {
467 return SplitRecordCount
;
471 Split the memory map to new entries, according to one old entry,
472 based upon PE code section and data section.
474 @param OldRecord A pointer to one old memory map entry.
475 @param NewRecord A pointer to several new memory map entries.
476 The caller gurantee the buffer size be 1 +
477 (SplitRecordCount * DescriptorSize) calculated
479 @param MaxSplitRecordCount The max number of splitted entries
480 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
482 @retval 0 no entry is splitted.
483 @return the real number of splitted record.
488 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
489 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
490 IN UINTN MaxSplitRecordCount
,
491 IN UINTN DescriptorSize
494 EFI_MEMORY_DESCRIPTOR TempRecord
;
495 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
496 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
497 UINT64 PhysicalStart
;
499 UINTN NewRecordCount
;
500 UINTN TotalNewRecordCount
;
501 BOOLEAN IsLastRecordData
;
503 if (MaxSplitRecordCount
== 0) {
504 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
508 TotalNewRecordCount
= 0;
511 // Override previous record
513 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
514 PhysicalStart
= TempRecord
.PhysicalStart
;
515 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
519 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
520 if (NewImageRecord
== NULL
) {
522 // No more image covered by this range, stop
524 if ((PhysicalEnd
> PhysicalStart
) && (ImageRecord
!= NULL
)) {
526 // If this is still address in this record, need record.
528 NewRecord
= PREVIOUS_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
529 IsLastRecordData
= FALSE
;
530 if (!mPropertiesTableEnable
) {
531 if ((NewRecord
->Attribute
& EFI_MEMORY_XP
) != 0) {
532 IsLastRecordData
= TRUE
;
535 if (NewRecord
->Type
== EfiRuntimeServicesData
) {
536 IsLastRecordData
= TRUE
;
539 if (IsLastRecordData
) {
541 // Last record is DATA, just merge it.
543 NewRecord
->NumberOfPages
= EfiSizeToPages(PhysicalEnd
- NewRecord
->PhysicalStart
);
546 // Last record is CODE, create a new DATA entry.
548 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
549 if (!mPropertiesTableEnable
) {
550 NewRecord
->Type
= TempRecord
.Type
;
552 NewRecord
->Type
= EfiRuntimeServicesData
;
554 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
555 NewRecord
->VirtualStart
= 0;
556 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
557 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
558 TotalNewRecordCount
++;
563 ImageRecord
= NewImageRecord
;
568 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
569 TotalNewRecordCount
+= NewRecordCount
;
570 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
573 // Update PhysicalStart, in order to exclude the image buffer already splitted.
575 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
576 TempRecord
.PhysicalStart
= PhysicalStart
;
577 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
578 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
581 // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
582 // code reaches here.
584 ASSERT (TotalNewRecordCount
!= 0);
585 return TotalNewRecordCount
- 1;
589 Split the original memory map, and add more entries to describe PE code section and data section.
590 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
591 This function will merge entries with same attributes finally.
593 NOTE: It assumes PE code/data section are page aligned.
594 NOTE: It assumes enough entry is prepared for new memory map.
607 +---------------+ ----
610 | Record RtCode | |-> PE/COFF1
613 +---------------+ ----
616 | Record RtCode | |-> PE/COFF2
619 +---------------+ ----
623 @param MemoryMapSize A pointer to the size, in bytes, of the
624 MemoryMap buffer. On input, this is the size of
625 old MemoryMap before split. The actual buffer
626 size of MemoryMap is MemoryMapSize +
627 (AdditionalRecordCount * DescriptorSize) calculated
628 below. On output, it is the size of new MemoryMap
630 @param MemoryMap A pointer to the buffer in which firmware places
631 the current memory map.
632 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
637 IN OUT UINTN
*MemoryMapSize
,
638 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
639 IN UINTN DescriptorSize
644 UINTN MaxSplitRecordCount
;
645 UINTN RealSplitRecordCount
;
646 UINTN TotalSplitRecordCount
;
647 UINTN AdditionalRecordCount
;
649 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
651 TotalSplitRecordCount
= 0;
653 // Let old record point to end of valid MemoryMap buffer.
655 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
657 // Let new record point to end of full MemoryMap buffer.
659 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
660 for (; IndexOld
>= 0; IndexOld
--) {
661 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
663 // Split this MemoryMap record
665 IndexNew
-= MaxSplitRecordCount
;
666 RealSplitRecordCount
= SplitRecord (
667 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
668 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
673 // Adjust IndexNew according to real split.
676 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
677 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
678 RealSplitRecordCount
* DescriptorSize
680 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
681 TotalSplitRecordCount
+= RealSplitRecordCount
;
685 // Move all records to the beginning.
689 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
690 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
693 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
696 // Sort from low to high (Just in case)
698 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
701 // Set RuntimeData to XP
703 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
706 // Merge same type to save entry size
708 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
714 This function for GetMemoryMap() with properties table capability.
716 It calls original GetMemoryMap() to get the original memory map information. Then
717 plus the additional memory map entries for PE Code/Data seperation.
719 @param MemoryMapSize A pointer to the size, in bytes, of the
720 MemoryMap buffer. On input, this is the size of
721 the buffer allocated by the caller. On output,
722 it is the size of the buffer returned by the
723 firmware if the buffer was large enough, or the
724 size of the buffer needed to contain the map if
725 the buffer was too small.
726 @param MemoryMap A pointer to the buffer in which firmware places
727 the current memory map.
728 @param MapKey A pointer to the location in which firmware
729 returns the key for the current memory map.
730 @param DescriptorSize A pointer to the location in which firmware
731 returns the size, in bytes, of an individual
732 EFI_MEMORY_DESCRIPTOR.
733 @param DescriptorVersion A pointer to the location in which firmware
734 returns the version number associated with the
735 EFI_MEMORY_DESCRIPTOR.
737 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
739 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
740 buffer size needed to hold the memory map is
741 returned in MemoryMapSize.
742 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
747 CoreGetMemoryMapWithSeparatedImageSection (
748 IN OUT UINTN
*MemoryMapSize
,
749 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
751 OUT UINTN
*DescriptorSize
,
752 OUT UINT32
*DescriptorVersion
756 UINTN OldMemoryMapSize
;
757 UINTN AdditionalRecordCount
;
760 // If PE code/data is not aligned, just return.
762 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
763 return CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
766 if (MemoryMapSize
== NULL
) {
767 return EFI_INVALID_PARAMETER
;
770 CoreAcquirePropertiesTableLock ();
772 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
774 OldMemoryMapSize
= *MemoryMapSize
;
775 Status
= CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
776 if (Status
== EFI_BUFFER_TOO_SMALL
) {
777 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
778 } else if (Status
== EFI_SUCCESS
) {
779 ASSERT (MemoryMap
!= NULL
);
780 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
781 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
783 // Need update status to buffer too small
785 Status
= EFI_BUFFER_TOO_SMALL
;
788 // Split PE code/data
790 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
794 CoreReleasePropertiesTableLock ();
799 // Below functions are for ImageRecord
803 Set PropertiesTable according to PE/COFF image section alignment.
805 @param SectionAlignment PE/COFF section alignment
809 SetPropertiesTableSectionAlignment (
810 IN UINT32 SectionAlignment
813 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
814 ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
815 DEBUG ((EFI_D_VERBOSE
, "SetPropertiesTableSectionAlignment - Clear\n"));
816 mPropertiesTable
.MemoryProtectionAttribute
&= ~((UINT64
)EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
817 gBS
->GetMemoryMap
= CoreGetMemoryMap
;
819 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
824 Swap two code sections in image record.
826 @param FirstImageRecordCodeSection first code section in image record
827 @param SecondImageRecordCodeSection second code section in image record
831 SwapImageRecordCodeSection (
832 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
833 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
836 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
838 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
839 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
841 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
842 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
844 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
845 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
849 Sort code section in image record, based upon CodeSegmentBase from low to high.
851 @param ImageRecord image record to be sorted
854 SortImageRecordCodeSection (
855 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
858 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
859 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
860 LIST_ENTRY
*ImageRecordCodeSectionLink
;
861 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
862 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
863 LIST_ENTRY
*ImageRecordCodeSectionList
;
865 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
867 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
868 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
869 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
870 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
871 ImageRecordCodeSection
= CR (
872 ImageRecordCodeSectionLink
,
873 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
875 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
877 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
878 NextImageRecordCodeSection
= CR (
879 NextImageRecordCodeSectionLink
,
880 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
882 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
884 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
885 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
887 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
890 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
891 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
896 Check if code section in image record is valid.
898 @param ImageRecord image record to be checked
900 @retval TRUE image record is valid
901 @retval FALSE image record is invalid
904 IsImageRecordCodeSectionValid (
905 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
908 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
909 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
910 LIST_ENTRY
*ImageRecordCodeSectionLink
;
911 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
912 LIST_ENTRY
*ImageRecordCodeSectionList
;
914 DEBUG ((EFI_D_VERBOSE
, "ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
916 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
918 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
919 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
920 LastImageRecordCodeSection
= NULL
;
921 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
922 ImageRecordCodeSection
= CR (
923 ImageRecordCodeSectionLink
,
924 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
926 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
928 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
931 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
934 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
937 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
940 if (LastImageRecordCodeSection
!= NULL
) {
941 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
946 LastImageRecordCodeSection
= ImageRecordCodeSection
;
947 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
954 Swap two image records.
956 @param FirstImageRecord first image record.
957 @param SecondImageRecord second image record.
962 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
963 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
966 IMAGE_PROPERTIES_RECORD TempImageRecord
;
968 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
969 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
970 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
972 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
973 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
974 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
976 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
977 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
978 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
980 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
984 Sort image record based upon the ImageBase from low to high.
992 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
993 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
994 LIST_ENTRY
*ImageRecordLink
;
995 LIST_ENTRY
*NextImageRecordLink
;
996 LIST_ENTRY
*ImageRecordEndLink
;
997 LIST_ENTRY
*ImageRecordList
;
999 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1001 ImageRecordLink
= ImageRecordList
->ForwardLink
;
1002 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1003 ImageRecordEndLink
= ImageRecordList
;
1004 while (ImageRecordLink
!= ImageRecordEndLink
) {
1007 IMAGE_PROPERTIES_RECORD
,
1009 IMAGE_PROPERTIES_RECORD_SIGNATURE
1011 while (NextImageRecordLink
!= ImageRecordEndLink
) {
1012 NextImageRecord
= CR (
1013 NextImageRecordLink
,
1014 IMAGE_PROPERTIES_RECORD
,
1016 IMAGE_PROPERTIES_RECORD_SIGNATURE
1018 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
1019 SwapImageRecord (ImageRecord
, NextImageRecord
);
1021 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
1024 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
1025 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1038 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1039 LIST_ENTRY
*ImageRecordLink
;
1040 LIST_ENTRY
*ImageRecordList
;
1043 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1045 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1046 ImageRecordLink
!= ImageRecordList
;
1047 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1050 IMAGE_PROPERTIES_RECORD
,
1052 IMAGE_PROPERTIES_RECORD_SIGNATURE
1054 DEBUG ((EFI_D_VERBOSE
, " Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1059 Insert image record.
1061 @param RuntimeImage Runtime image information
1065 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1069 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1070 UINT32 PeCoffHeaderOffset
;
1071 UINT32 SectionAlignment
;
1072 EFI_IMAGE_SECTION_HEADER
*Section
;
1073 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1076 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1078 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1081 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%x\n", RuntimeImage
));
1082 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1084 if (mPropertiesTableEndOfDxe
) {
1085 DEBUG ((DEBUG_INFO
, "Do not insert runtime image record after EndOfDxe\n"));
1089 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1090 if (ImageRecord
== NULL
) {
1093 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1095 DEBUG ((EFI_D_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1098 // Step 1: record whole region
1100 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1101 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1103 ImageAddress
= RuntimeImage
->ImageBase
;
1105 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1106 if (PdbPointer
!= NULL
) {
1107 DEBUG ((EFI_D_VERBOSE
, " Image - %a\n", PdbPointer
));
1111 // Check PE/COFF image
1113 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1114 PeCoffHeaderOffset
= 0;
1115 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1116 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1119 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1120 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1121 DEBUG ((EFI_D_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1122 // It might be image in SMM.
1127 // Get SectionAlignment
1129 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1131 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1132 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1133 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1134 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1136 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1139 // Get the magic value from the PE/COFF Optional Header
1141 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1143 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1144 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1146 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1149 SetPropertiesTableSectionAlignment (SectionAlignment
);
1150 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1151 DEBUG ((EFI_D_WARN
, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1152 SectionAlignment
, RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1153 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1154 if (PdbPointer
!= NULL
) {
1155 DEBUG ((EFI_D_WARN
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1160 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1161 (UINT8
*) (UINTN
) ImageAddress
+
1162 PeCoffHeaderOffset
+
1164 sizeof(EFI_IMAGE_FILE_HEADER
) +
1165 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1167 ImageRecord
->CodeSegmentCount
= 0;
1168 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1169 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1170 Name
= Section
[Index
].Name
;
1173 " Section - '%c%c%c%c%c%c%c%c'\n",
1184 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1185 DEBUG ((EFI_D_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1186 DEBUG ((EFI_D_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1187 DEBUG ((EFI_D_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1188 DEBUG ((EFI_D_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1189 DEBUG ((EFI_D_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1190 DEBUG ((EFI_D_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1191 DEBUG ((EFI_D_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1192 DEBUG ((EFI_D_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1193 DEBUG ((EFI_D_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1196 // Step 2: record code section
1198 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1199 if (ImageRecordCodeSection
== NULL
) {
1202 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1204 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1205 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1207 DEBUG ((EFI_D_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1209 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1210 ImageRecord
->CodeSegmentCount
++;
1214 if (ImageRecord
->CodeSegmentCount
== 0) {
1215 SetPropertiesTableSectionAlignment (1);
1216 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1217 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1218 if (PdbPointer
!= NULL
) {
1219 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1227 SortImageRecordCodeSection (ImageRecord
);
1229 // Check overlap all section in ImageBase/Size
1231 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1232 DEBUG ((EFI_D_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1236 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1237 mImagePropertiesPrivateData
.ImageRecordCount
++;
1239 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1240 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1250 Find image record according to image base and size.
1252 @param ImageBase Base of PE image
1253 @param ImageSize Size of PE image
1255 @return image record
1258 IMAGE_PROPERTIES_RECORD
*
1260 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1264 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1265 LIST_ENTRY
*ImageRecordLink
;
1266 LIST_ENTRY
*ImageRecordList
;
1268 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1270 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1271 ImageRecordLink
!= ImageRecordList
;
1272 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1275 IMAGE_PROPERTIES_RECORD
,
1277 IMAGE_PROPERTIES_RECORD_SIGNATURE
1280 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1281 (ImageSize
== ImageRecord
->ImageSize
)) {
1290 Remove Image record.
1292 @param RuntimeImage Runtime image information
1296 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1299 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1300 LIST_ENTRY
*CodeSegmentListHead
;
1301 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1303 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1304 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1306 if (mPropertiesTableEndOfDxe
) {
1307 DEBUG ((DEBUG_INFO
, "Do not remove runtime image record after EndOfDxe\n"));
1311 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1312 if (ImageRecord
== NULL
) {
1313 DEBUG ((EFI_D_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1317 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1318 while (!IsListEmpty (CodeSegmentListHead
)) {
1319 ImageRecordCodeSection
= CR (
1320 CodeSegmentListHead
->ForwardLink
,
1321 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1323 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1325 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1326 FreePool (ImageRecordCodeSection
);
1329 RemoveEntryList (&ImageRecord
->Link
);
1330 FreePool (ImageRecord
);
1331 mImagePropertiesPrivateData
.ImageRecordCount
--;
1336 Install PropertiesTable.
1338 @param[in] Event The Event this notify function registered to.
1339 @param[in] Context Pointer to the context data registered to the Event.
1343 InstallPropertiesTable (
1348 mPropertiesTableEndOfDxe
= TRUE
;
1349 if (PcdGetBool (PcdPropertiesTableEnable
)) {
1352 Status
= gBS
->InstallConfigurationTable (&gEfiPropertiesTableGuid
, &mPropertiesTable
);
1353 ASSERT_EFI_ERROR (Status
);
1355 DEBUG ((EFI_D_INFO
, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable
.MemoryProtectionAttribute
));
1356 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1357 DEBUG ((EFI_D_ERROR
, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));
1358 DEBUG ((EFI_D_ERROR
, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1362 gBS
->GetMemoryMap
= CoreGetMemoryMapWithSeparatedImageSection
;
1364 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
1366 DEBUG ((EFI_D_VERBOSE
, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1367 DEBUG ((EFI_D_VERBOSE
, "Dump ImageRecord:\n"));
1370 mPropertiesTableEnable
= TRUE
;
1375 Initialize PropertiesTable support.
1379 CoreInitializePropertiesTable (
1384 EFI_EVENT EndOfDxeEvent
;
1386 Status
= gBS
->CreateEventEx (
1389 InstallPropertiesTable
,
1391 &gEfiEndOfDxeEventGroupGuid
,
1394 ASSERT_EFI_ERROR (Status
);