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
;
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 if (mPropertiesTableEndOfDxe
) {
1084 DEBUG ((DEBUG_INFO
, "Do not insert runtime image record after EndOfDxe\n"));
1088 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1089 if (ImageRecord
== NULL
) {
1092 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1094 DEBUG ((EFI_D_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1097 // Step 1: record whole region
1099 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1100 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1102 ImageAddress
= RuntimeImage
->ImageBase
;
1104 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1105 if (PdbPointer
!= NULL
) {
1106 DEBUG ((EFI_D_VERBOSE
, " Image - %a\n", PdbPointer
));
1110 // Check PE/COFF image
1112 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1113 PeCoffHeaderOffset
= 0;
1114 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1115 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1118 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1119 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1120 DEBUG ((EFI_D_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1121 // It might be image in SMM.
1126 // Get SectionAlignment
1128 if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1129 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1131 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1134 SetPropertiesTableSectionAlignment (SectionAlignment
);
1135 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1136 DEBUG ((EFI_D_WARN
, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1137 SectionAlignment
, RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1138 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1139 if (PdbPointer
!= NULL
) {
1140 DEBUG ((EFI_D_WARN
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1145 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1146 (UINT8
*) (UINTN
) ImageAddress
+
1147 PeCoffHeaderOffset
+
1149 sizeof(EFI_IMAGE_FILE_HEADER
) +
1150 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1152 ImageRecord
->CodeSegmentCount
= 0;
1153 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1154 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1155 Name
= Section
[Index
].Name
;
1158 " Section - '%c%c%c%c%c%c%c%c'\n",
1169 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1170 DEBUG ((EFI_D_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1171 DEBUG ((EFI_D_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1172 DEBUG ((EFI_D_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1173 DEBUG ((EFI_D_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1174 DEBUG ((EFI_D_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1175 DEBUG ((EFI_D_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1176 DEBUG ((EFI_D_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1177 DEBUG ((EFI_D_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1178 DEBUG ((EFI_D_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1181 // Step 2: record code section
1183 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1184 if (ImageRecordCodeSection
== NULL
) {
1187 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1189 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1190 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1192 DEBUG ((EFI_D_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1194 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1195 ImageRecord
->CodeSegmentCount
++;
1199 if (ImageRecord
->CodeSegmentCount
== 0) {
1200 SetPropertiesTableSectionAlignment (1);
1201 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1202 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1203 if (PdbPointer
!= NULL
) {
1204 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1212 SortImageRecordCodeSection (ImageRecord
);
1214 // Check overlap all section in ImageBase/Size
1216 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1217 DEBUG ((EFI_D_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1221 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1222 mImagePropertiesPrivateData
.ImageRecordCount
++;
1224 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1225 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1235 Find image record according to image base and size.
1237 @param ImageBase Base of PE image
1238 @param ImageSize Size of PE image
1240 @return image record
1243 IMAGE_PROPERTIES_RECORD
*
1245 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1249 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1250 LIST_ENTRY
*ImageRecordLink
;
1251 LIST_ENTRY
*ImageRecordList
;
1253 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1255 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1256 ImageRecordLink
!= ImageRecordList
;
1257 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1260 IMAGE_PROPERTIES_RECORD
,
1262 IMAGE_PROPERTIES_RECORD_SIGNATURE
1265 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1266 (ImageSize
== ImageRecord
->ImageSize
)) {
1275 Remove Image record.
1277 @param RuntimeImage Runtime image information
1281 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1284 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1285 LIST_ENTRY
*CodeSegmentListHead
;
1286 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1288 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1289 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1291 if (mPropertiesTableEndOfDxe
) {
1292 DEBUG ((DEBUG_INFO
, "Do not remove runtime image record after EndOfDxe\n"));
1296 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1297 if (ImageRecord
== NULL
) {
1298 DEBUG ((EFI_D_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1302 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1303 while (!IsListEmpty (CodeSegmentListHead
)) {
1304 ImageRecordCodeSection
= CR (
1305 CodeSegmentListHead
->ForwardLink
,
1306 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1308 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1310 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1311 FreePool (ImageRecordCodeSection
);
1314 RemoveEntryList (&ImageRecord
->Link
);
1315 FreePool (ImageRecord
);
1316 mImagePropertiesPrivateData
.ImageRecordCount
--;
1321 Install PropertiesTable.
1323 @param[in] Event The Event this notify function registered to.
1324 @param[in] Context Pointer to the context data registered to the Event.
1328 InstallPropertiesTable (
1333 mPropertiesTableEndOfDxe
= TRUE
;
1334 if (PcdGetBool (PcdPropertiesTableEnable
)) {
1337 Status
= gBS
->InstallConfigurationTable (&gEfiPropertiesTableGuid
, &mPropertiesTable
);
1338 ASSERT_EFI_ERROR (Status
);
1340 DEBUG ((EFI_D_INFO
, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable
.MemoryProtectionAttribute
));
1341 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1342 DEBUG ((EFI_D_ERROR
, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));
1343 DEBUG ((EFI_D_ERROR
, "because Runtime Driver Section Alignment is not %dK.\n", RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1347 gBS
->GetMemoryMap
= CoreGetMemoryMapWithSeparatedImageSection
;
1349 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
1351 DEBUG ((EFI_D_VERBOSE
, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1352 DEBUG ((EFI_D_VERBOSE
, "Dump ImageRecord:\n"));
1355 mPropertiesTableEnable
= TRUE
;
1360 Initialize PropertiesTable support.
1364 CoreInitializePropertiesTable (
1369 EFI_EVENT EndOfDxeEvent
;
1371 Status
= gBS
->CreateEventEx (
1374 InstallPropertiesTable
,
1376 &gEfiEndOfDxeEventGroupGuid
,
1379 ASSERT_EFI_ERROR (Status
);