2 UEFI PropertiesTable support
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/BaseLib.h>
11 #include <Library/BaseMemoryLib.h>
12 #include <Library/MemoryAllocationLib.h>
13 #include <Library/UefiBootServicesTableLib.h>
14 #include <Library/DxeServicesTableLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/UefiLib.h>
17 #include <Library/PcdLib.h>
19 #include <Guid/EventGroup.h>
20 #include <Protocol/DxeSmmReadyToLock.h>
22 #include <Library/PeCoffLib.h>
23 #include <Library/PeCoffGetEntryPointLib.h>
24 #include <Protocol/Runtime.h>
27 #include "HeapGuard.h"
29 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
30 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
32 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
36 UINTN ImageRecordCount
;
37 UINTN CodeSegmentCountMax
;
38 LIST_ENTRY ImageRecordList
;
39 } IMAGE_PROPERTIES_PRIVATE_DATA
;
41 IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData
= {
42 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE
,
45 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData
.ImageRecordList
)
48 EFI_LOCK mPropertiesTableLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
50 BOOLEAN mPropertiesTableEndOfDxe
= FALSE
;
52 extern BOOLEAN mMemoryAttributesTableEnable
;
55 // Below functions are for MemoryMap
59 Converts a number of EFI_PAGEs to a size in bytes.
61 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
63 @param Pages The number of EFI_PAGES.
65 @return The number of bytes associated with the number of EFI_PAGEs specified
74 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
78 Converts a size, in bytes, to a number of EFI_PAGESs.
80 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
82 @param Size A size in bytes.
84 @return The number of EFI_PAGESs associated with the number of bytes specified
94 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
98 Acquire memory lock on mPropertiesTableLock.
102 CoreAcquirePropertiesTableLock (
106 CoreAcquireLock (&mPropertiesTableLock
);
110 Release memory lock on mPropertiesTableLock.
114 CoreReleasePropertiesTableLock (
118 CoreReleaseLock (&mPropertiesTableLock
);
122 Sort memory map entries based upon PhysicalStart, from low to high.
124 @param MemoryMap A pointer to the buffer in which firmware places
125 the current memory map.
126 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
127 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
132 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
133 IN UINTN MemoryMapSize
,
134 IN UINTN DescriptorSize
137 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
138 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
139 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
140 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
142 MemoryMapEntry
= MemoryMap
;
143 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
144 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
145 while (MemoryMapEntry
< MemoryMapEnd
) {
146 while (NextMemoryMapEntry
< MemoryMapEnd
) {
147 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
148 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
149 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
150 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
153 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
156 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
157 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
164 Merge continous memory map entries whose have same attributes.
166 @param MemoryMap A pointer to the buffer in which firmware places
167 the current memory map.
168 @param MemoryMapSize A pointer to the size, in bytes, of the
169 MemoryMap buffer. On input, this is the size of
170 the current memory map. On output,
171 it is the size of new memory map after merge.
172 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
176 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
177 IN OUT UINTN
*MemoryMapSize
,
178 IN UINTN DescriptorSize
181 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
182 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
183 UINT64 MemoryBlockLength
;
184 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
185 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
187 MemoryMapEntry
= MemoryMap
;
188 NewMemoryMapEntry
= MemoryMap
;
189 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
190 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
191 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
192 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
195 MergeGuardPages (NewMemoryMapEntry
, NextMemoryMapEntry
->PhysicalStart
);
196 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (NewMemoryMapEntry
->NumberOfPages
));
197 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
198 (NewMemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
199 (NewMemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
200 ((NewMemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
201 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
202 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
205 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
210 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
211 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
214 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
220 Enforce memory map attributes.
221 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
223 @param MemoryMap A pointer to the buffer in which firmware places
224 the current memory map.
225 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
226 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
230 EnforceMemoryMapAttribute (
231 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
232 IN UINTN MemoryMapSize
,
233 IN UINTN DescriptorSize
236 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
237 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
239 MemoryMapEntry
= MemoryMap
;
240 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
241 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
242 switch (MemoryMapEntry
->Type
) {
243 case EfiRuntimeServicesCode
:
246 case EfiRuntimeServicesData
:
247 case EfiMemoryMappedIO
:
248 case EfiMemoryMappedIOPortSpace
:
249 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
251 case EfiReservedMemoryType
:
252 case EfiACPIMemoryNVS
:
256 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
263 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
265 @param Buffer Start Address
266 @param Length Address length
268 @return first image record covered by [buffer, length]
271 IMAGE_PROPERTIES_RECORD
*
272 GetImageRecordByAddress (
273 IN EFI_PHYSICAL_ADDRESS Buffer
,
277 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
278 LIST_ENTRY
*ImageRecordLink
;
279 LIST_ENTRY
*ImageRecordList
;
281 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
283 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
284 ImageRecordLink
!= ImageRecordList
;
285 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
288 IMAGE_PROPERTIES_RECORD
,
290 IMAGE_PROPERTIES_RECORD_SIGNATURE
293 if ((Buffer
<= ImageRecord
->ImageBase
) &&
294 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
303 Set the memory map to new entries, according to one old entry,
304 based upon PE code section and data section in image record
306 @param ImageRecord An image record whose [ImageBase, ImageSize] covered
307 by old memory map entry.
308 @param NewRecord A pointer to several new memory map entries.
309 The caller gurantee the buffer size be 1 +
310 (SplitRecordCount * DescriptorSize) calculated
312 @param OldRecord A pointer to one old memory map entry.
313 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
318 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
319 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
320 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
321 IN UINTN DescriptorSize
324 EFI_MEMORY_DESCRIPTOR TempRecord
;
325 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
326 LIST_ENTRY
*ImageRecordCodeSectionLink
;
327 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
328 LIST_ENTRY
*ImageRecordCodeSectionList
;
329 UINTN NewRecordCount
;
333 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
334 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
337 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
339 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
340 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
341 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
342 ImageRecordCodeSection
= CR (
343 ImageRecordCodeSectionLink
,
344 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
346 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
348 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
350 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
354 NewRecord
->Type
= TempRecord
.Type
;
355 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
356 NewRecord
->VirtualStart
= 0;
357 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
358 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
359 if (NewRecord
->NumberOfPages
!= 0) {
360 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
367 NewRecord
->Type
= TempRecord
.Type
;
368 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
369 NewRecord
->VirtualStart
= 0;
370 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
371 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
372 if (NewRecord
->NumberOfPages
!= 0) {
373 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
377 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
378 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
379 if (TempRecord
.NumberOfPages
== 0) {
385 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
390 if (TempRecord
.PhysicalStart
< ImageEnd
) {
391 NewRecord
->Type
= TempRecord
.Type
;
392 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
393 NewRecord
->VirtualStart
= 0;
394 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
395 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
399 return NewRecordCount
;
403 Return the max number of new splitted entries, according to one old entry,
404 based upon PE code section and data section.
406 @param OldRecord A pointer to one old memory map entry.
408 @retval 0 no entry need to be splitted.
409 @return the max number of new splitted entries
413 GetMaxSplitRecordCount (
414 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
417 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
418 UINTN SplitRecordCount
;
419 UINT64 PhysicalStart
;
422 SplitRecordCount
= 0;
423 PhysicalStart
= OldRecord
->PhysicalStart
;
424 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
427 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
428 if (ImageRecord
== NULL
) {
431 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 1);
432 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
433 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
435 if (SplitRecordCount
!= 0) {
439 return SplitRecordCount
;
443 Split the memory map to new entries, according to one old entry,
444 based upon PE code section and data section.
446 @param OldRecord A pointer to one old memory map entry.
447 @param NewRecord A pointer to several new memory map entries.
448 The caller gurantee the buffer size be 1 +
449 (SplitRecordCount * DescriptorSize) calculated
451 @param MaxSplitRecordCount The max number of splitted entries
452 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
454 @retval 0 no entry is splitted.
455 @return the real number of splitted record.
460 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
461 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
462 IN UINTN MaxSplitRecordCount
,
463 IN UINTN DescriptorSize
466 EFI_MEMORY_DESCRIPTOR TempRecord
;
467 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
468 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
469 UINT64 PhysicalStart
;
471 UINTN NewRecordCount
;
472 UINTN TotalNewRecordCount
;
473 BOOLEAN IsLastRecordData
;
475 if (MaxSplitRecordCount
== 0) {
476 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
480 TotalNewRecordCount
= 0;
483 // Override previous record
485 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
486 PhysicalStart
= TempRecord
.PhysicalStart
;
487 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
491 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
492 if (NewImageRecord
== NULL
) {
494 // No more image covered by this range, stop
496 if ((PhysicalEnd
> PhysicalStart
) && (ImageRecord
!= NULL
)) {
498 // If this is still address in this record, need record.
500 NewRecord
= PREVIOUS_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
501 IsLastRecordData
= FALSE
;
502 if ((NewRecord
->Attribute
& EFI_MEMORY_XP
) != 0) {
503 IsLastRecordData
= TRUE
;
505 if (IsLastRecordData
) {
507 // Last record is DATA, just merge it.
509 NewRecord
->NumberOfPages
= EfiSizeToPages(PhysicalEnd
- NewRecord
->PhysicalStart
);
512 // Last record is CODE, create a new DATA entry.
514 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
515 NewRecord
->Type
= TempRecord
.Type
;
516 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
517 NewRecord
->VirtualStart
= 0;
518 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
519 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
520 TotalNewRecordCount
++;
525 ImageRecord
= NewImageRecord
;
530 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
531 TotalNewRecordCount
+= NewRecordCount
;
532 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
535 // Update PhysicalStart, in order to exclude the image buffer already splitted.
537 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
538 TempRecord
.PhysicalStart
= PhysicalStart
;
539 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
540 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
543 // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
544 // code reaches here.
546 ASSERT (TotalNewRecordCount
!= 0);
547 return TotalNewRecordCount
- 1;
551 Split the original memory map, and add more entries to describe PE code section and data section.
552 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
553 This function will merge entries with same attributes finally.
555 NOTE: It assumes PE code/data section are page aligned.
556 NOTE: It assumes enough entry is prepared for new memory map.
569 +---------------+ ----
572 | Record RtCode | |-> PE/COFF1
575 +---------------+ ----
578 | Record RtCode | |-> PE/COFF2
581 +---------------+ ----
585 @param MemoryMapSize A pointer to the size, in bytes, of the
586 MemoryMap buffer. On input, this is the size of
587 old MemoryMap before split. The actual buffer
588 size of MemoryMap is MemoryMapSize +
589 (AdditionalRecordCount * DescriptorSize) calculated
590 below. On output, it is the size of new MemoryMap
592 @param MemoryMap A pointer to the buffer in which firmware places
593 the current memory map.
594 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
599 IN OUT UINTN
*MemoryMapSize
,
600 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
601 IN UINTN DescriptorSize
606 UINTN MaxSplitRecordCount
;
607 UINTN RealSplitRecordCount
;
608 UINTN TotalSplitRecordCount
;
609 UINTN AdditionalRecordCount
;
611 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
613 TotalSplitRecordCount
= 0;
615 // Let old record point to end of valid MemoryMap buffer.
617 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
619 // Let new record point to end of full MemoryMap buffer.
621 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
622 for (; IndexOld
>= 0; IndexOld
--) {
623 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
625 // Split this MemoryMap record
627 IndexNew
-= MaxSplitRecordCount
;
628 RealSplitRecordCount
= SplitRecord (
629 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
630 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
635 // Adjust IndexNew according to real split.
638 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
639 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
640 RealSplitRecordCount
* DescriptorSize
642 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
643 TotalSplitRecordCount
+= RealSplitRecordCount
;
647 // Move all records to the beginning.
651 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
652 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
655 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
658 // Sort from low to high (Just in case)
660 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
663 // Set RuntimeData to XP
665 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
668 // Merge same type to save entry size
670 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
676 This function for GetMemoryMap() with properties table capability.
678 It calls original GetMemoryMap() to get the original memory map information. Then
679 plus the additional memory map entries for PE Code/Data seperation.
681 @param MemoryMapSize A pointer to the size, in bytes, of the
682 MemoryMap buffer. On input, this is the size of
683 the buffer allocated by the caller. On output,
684 it is the size of the buffer returned by the
685 firmware if the buffer was large enough, or the
686 size of the buffer needed to contain the map if
687 the buffer was too small.
688 @param MemoryMap A pointer to the buffer in which firmware places
689 the current memory map.
690 @param MapKey A pointer to the location in which firmware
691 returns the key for the current memory map.
692 @param DescriptorSize A pointer to the location in which firmware
693 returns the size, in bytes, of an individual
694 EFI_MEMORY_DESCRIPTOR.
695 @param DescriptorVersion A pointer to the location in which firmware
696 returns the version number associated with the
697 EFI_MEMORY_DESCRIPTOR.
699 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
701 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
702 buffer size needed to hold the memory map is
703 returned in MemoryMapSize.
704 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
709 CoreGetMemoryMapWithSeparatedImageSection (
710 IN OUT UINTN
*MemoryMapSize
,
711 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
713 OUT UINTN
*DescriptorSize
,
714 OUT UINT32
*DescriptorVersion
718 UINTN OldMemoryMapSize
;
719 UINTN AdditionalRecordCount
;
722 // If PE code/data is not aligned, just return.
724 if (!mMemoryAttributesTableEnable
) {
725 return CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
728 if (MemoryMapSize
== NULL
) {
729 return EFI_INVALID_PARAMETER
;
732 CoreAcquirePropertiesTableLock ();
734 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
736 OldMemoryMapSize
= *MemoryMapSize
;
737 Status
= CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
738 if (Status
== EFI_BUFFER_TOO_SMALL
) {
739 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
740 } else if (Status
== EFI_SUCCESS
) {
741 ASSERT (MemoryMap
!= NULL
);
742 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
743 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
745 // Need update status to buffer too small
747 Status
= EFI_BUFFER_TOO_SMALL
;
750 // Split PE code/data
752 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
756 CoreReleasePropertiesTableLock ();
761 // Below functions are for ImageRecord
765 Set PropertiesTable according to PE/COFF image section alignment.
767 @param SectionAlignment PE/COFF section alignment
771 SetPropertiesTableSectionAlignment (
772 IN UINT32 SectionAlignment
775 if (((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) &&
776 mMemoryAttributesTableEnable
) {
777 DEBUG ((EFI_D_VERBOSE
, "SetPropertiesTableSectionAlignment - Clear\n"));
778 mMemoryAttributesTableEnable
= FALSE
;
783 Swap two code sections in image record.
785 @param FirstImageRecordCodeSection first code section in image record
786 @param SecondImageRecordCodeSection second code section in image record
790 SwapImageRecordCodeSection (
791 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
792 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
795 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
797 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
798 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
800 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
801 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
803 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
804 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
808 Sort code section in image record, based upon CodeSegmentBase from low to high.
810 @param ImageRecord image record to be sorted
813 SortImageRecordCodeSection (
814 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
817 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
818 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
819 LIST_ENTRY
*ImageRecordCodeSectionLink
;
820 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
821 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
822 LIST_ENTRY
*ImageRecordCodeSectionList
;
824 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
826 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
827 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
828 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
829 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
830 ImageRecordCodeSection
= CR (
831 ImageRecordCodeSectionLink
,
832 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
834 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
836 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
837 NextImageRecordCodeSection
= CR (
838 NextImageRecordCodeSectionLink
,
839 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
841 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
843 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
844 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
846 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
849 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
850 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
855 Check if code section in image record is valid.
857 @param ImageRecord image record to be checked
859 @retval TRUE image record is valid
860 @retval FALSE image record is invalid
863 IsImageRecordCodeSectionValid (
864 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
867 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
868 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
869 LIST_ENTRY
*ImageRecordCodeSectionLink
;
870 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
871 LIST_ENTRY
*ImageRecordCodeSectionList
;
873 DEBUG ((EFI_D_VERBOSE
, "ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
875 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
877 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
878 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
879 LastImageRecordCodeSection
= NULL
;
880 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
881 ImageRecordCodeSection
= CR (
882 ImageRecordCodeSectionLink
,
883 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
885 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
887 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
890 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
893 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
896 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
899 if (LastImageRecordCodeSection
!= NULL
) {
900 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
905 LastImageRecordCodeSection
= ImageRecordCodeSection
;
906 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
913 Swap two image records.
915 @param FirstImageRecord first image record.
916 @param SecondImageRecord second image record.
921 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
922 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
925 IMAGE_PROPERTIES_RECORD TempImageRecord
;
927 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
928 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
929 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
931 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
932 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
933 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
935 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
936 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
937 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
939 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
943 Sort image record based upon the ImageBase from low to high.
951 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
952 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
953 LIST_ENTRY
*ImageRecordLink
;
954 LIST_ENTRY
*NextImageRecordLink
;
955 LIST_ENTRY
*ImageRecordEndLink
;
956 LIST_ENTRY
*ImageRecordList
;
958 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
960 ImageRecordLink
= ImageRecordList
->ForwardLink
;
961 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
962 ImageRecordEndLink
= ImageRecordList
;
963 while (ImageRecordLink
!= ImageRecordEndLink
) {
966 IMAGE_PROPERTIES_RECORD
,
968 IMAGE_PROPERTIES_RECORD_SIGNATURE
970 while (NextImageRecordLink
!= ImageRecordEndLink
) {
971 NextImageRecord
= CR (
973 IMAGE_PROPERTIES_RECORD
,
975 IMAGE_PROPERTIES_RECORD_SIGNATURE
977 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
978 SwapImageRecord (ImageRecord
, NextImageRecord
);
980 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
983 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
984 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
991 @param RuntimeImage Runtime image information
995 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
999 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1000 UINT32 PeCoffHeaderOffset
;
1001 UINT32 SectionAlignment
;
1002 EFI_IMAGE_SECTION_HEADER
*Section
;
1003 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1006 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1008 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1010 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%x\n", RuntimeImage
));
1011 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1013 if (mPropertiesTableEndOfDxe
) {
1014 DEBUG ((DEBUG_INFO
, "Do not insert runtime image record after EndOfDxe\n"));
1018 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1019 if (ImageRecord
== NULL
) {
1022 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1024 DEBUG ((EFI_D_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1027 // Step 1: record whole region
1029 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1030 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1032 ImageAddress
= RuntimeImage
->ImageBase
;
1034 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1035 if (PdbPointer
!= NULL
) {
1036 DEBUG ((EFI_D_VERBOSE
, " Image - %a\n", PdbPointer
));
1040 // Check PE/COFF image
1042 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1043 PeCoffHeaderOffset
= 0;
1044 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1045 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1048 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1049 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1050 DEBUG ((EFI_D_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1051 // It might be image in SMM.
1056 // Get SectionAlignment
1058 if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1059 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1061 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1064 SetPropertiesTableSectionAlignment (SectionAlignment
);
1065 if ((SectionAlignment
& (RUNTIME_PAGE_ALLOCATION_GRANULARITY
- 1)) != 0) {
1066 DEBUG ((EFI_D_WARN
, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1067 SectionAlignment
, RUNTIME_PAGE_ALLOCATION_GRANULARITY
>> 10));
1068 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1069 if (PdbPointer
!= NULL
) {
1070 DEBUG ((EFI_D_WARN
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1075 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1076 (UINT8
*) (UINTN
) ImageAddress
+
1077 PeCoffHeaderOffset
+
1079 sizeof(EFI_IMAGE_FILE_HEADER
) +
1080 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1082 ImageRecord
->CodeSegmentCount
= 0;
1083 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1084 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1085 Name
= Section
[Index
].Name
;
1088 " Section - '%c%c%c%c%c%c%c%c'\n",
1099 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1100 DEBUG ((EFI_D_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1101 DEBUG ((EFI_D_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1102 DEBUG ((EFI_D_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1103 DEBUG ((EFI_D_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1104 DEBUG ((EFI_D_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1105 DEBUG ((EFI_D_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1106 DEBUG ((EFI_D_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1107 DEBUG ((EFI_D_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1108 DEBUG ((EFI_D_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1111 // Step 2: record code section
1113 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1114 if (ImageRecordCodeSection
== NULL
) {
1117 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1119 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1120 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1122 DEBUG ((EFI_D_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1124 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1125 ImageRecord
->CodeSegmentCount
++;
1129 if (ImageRecord
->CodeSegmentCount
== 0) {
1130 SetPropertiesTableSectionAlignment (1);
1131 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1132 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1133 if (PdbPointer
!= NULL
) {
1134 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1142 SortImageRecordCodeSection (ImageRecord
);
1144 // Check overlap all section in ImageBase/Size
1146 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1147 DEBUG ((EFI_D_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1151 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1152 mImagePropertiesPrivateData
.ImageRecordCount
++;
1154 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1155 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1165 Find image record according to image base and size.
1167 @param ImageBase Base of PE image
1168 @param ImageSize Size of PE image
1170 @return image record
1173 IMAGE_PROPERTIES_RECORD
*
1175 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1179 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1180 LIST_ENTRY
*ImageRecordLink
;
1181 LIST_ENTRY
*ImageRecordList
;
1183 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1185 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1186 ImageRecordLink
!= ImageRecordList
;
1187 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1190 IMAGE_PROPERTIES_RECORD
,
1192 IMAGE_PROPERTIES_RECORD_SIGNATURE
1195 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1196 (ImageSize
== ImageRecord
->ImageSize
)) {
1205 Remove Image record.
1207 @param RuntimeImage Runtime image information
1211 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1214 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1215 LIST_ENTRY
*CodeSegmentListHead
;
1216 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1218 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1219 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1221 if (mPropertiesTableEndOfDxe
) {
1222 DEBUG ((DEBUG_INFO
, "Do not remove runtime image record after EndOfDxe\n"));
1226 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1227 if (ImageRecord
== NULL
) {
1228 DEBUG ((EFI_D_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1232 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1233 while (!IsListEmpty (CodeSegmentListHead
)) {
1234 ImageRecordCodeSection
= CR (
1235 CodeSegmentListHead
->ForwardLink
,
1236 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1238 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1240 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1241 FreePool (ImageRecordCodeSection
);
1244 RemoveEntryList (&ImageRecord
->Link
);
1245 FreePool (ImageRecord
);
1246 mImagePropertiesPrivateData
.ImageRecordCount
--;
1251 Install PropertiesTable.
1253 @param[in] Event The Event this notify function registered to.
1254 @param[in] Context Pointer to the context data registered to the Event.
1258 InstallPropertiesTable (
1263 mPropertiesTableEndOfDxe
= TRUE
;
1267 Initialize PropertiesTable support.
1271 CoreInitializePropertiesTable (
1276 EFI_EVENT EndOfDxeEvent
;
1278 Status
= gBS
->CreateEventEx (
1281 InstallPropertiesTable
,
1283 &gEfiEndOfDxeEventGroupGuid
,
1286 ASSERT_EFI_ERROR (Status
);