2 UEFI PropertiesTable support
4 Copyright (c) 2015, 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_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')
44 EFI_PHYSICAL_ADDRESS CodeSegmentBase
;
45 UINT64 CodeSegmentSize
;
46 } IMAGE_PROPERTIES_RECORD_CODE_SECTION
;
48 #define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')
53 EFI_PHYSICAL_ADDRESS ImageBase
;
55 UINTN CodeSegmentCount
;
56 LIST_ENTRY CodeSegmentList
;
57 } IMAGE_PROPERTIES_RECORD
;
59 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
63 UINTN ImageRecordCount
;
64 UINTN CodeSegmentCountMax
;
65 LIST_ENTRY ImageRecordList
;
66 } IMAGE_PROPERTIES_PRIVATE_DATA
;
68 IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData
= {
69 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE
,
72 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData
.ImageRecordList
)
75 EFI_PROPERTIES_TABLE mPropertiesTable
= {
76 EFI_PROPERTIES_TABLE_VERSION
,
77 sizeof(EFI_PROPERTIES_TABLE
),
78 EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
81 EFI_LOCK mPropertiesTableLock
= EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY
);
84 // Temporary save for original memory map.
85 // This is for MemoryAttributesTable only.
87 extern BOOLEAN mIsConstructingMemoryAttributesTable
;
88 EFI_MEMORY_DESCRIPTOR
*mMemoryMapOrg
;
89 UINTN mMemoryMapOrgSize
;
90 UINTN mDescriptorSize
;
93 // Below functions are for MemoryMap
97 Converts a number of EFI_PAGEs to a size in bytes.
99 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
101 @param Pages The number of EFI_PAGES.
103 @return The number of bytes associated with the number of EFI_PAGEs specified
112 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
116 Converts a size, in bytes, to a number of EFI_PAGESs.
118 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
120 @param Size A size in bytes.
122 @return The number of EFI_PAGESs associated with the number of bytes specified
132 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
136 Acquire memory lock on mPropertiesTableLock.
140 CoreAcquirePropertiesTableLock (
144 CoreAcquireLock (&mPropertiesTableLock
);
148 Release memory lock on mPropertiesTableLock.
152 CoreReleasePropertiesTableLock (
156 CoreReleaseLock (&mPropertiesTableLock
);
160 Sort memory map entries based upon PhysicalStart, from low to high.
162 @param MemoryMap A pointer to the buffer in which firmware places
163 the current memory map.
164 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
165 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
170 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
171 IN UINTN MemoryMapSize
,
172 IN UINTN DescriptorSize
175 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
176 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
177 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
178 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
180 MemoryMapEntry
= MemoryMap
;
181 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
182 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
183 while (MemoryMapEntry
< MemoryMapEnd
) {
184 while (NextMemoryMapEntry
< MemoryMapEnd
) {
185 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
186 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
187 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
188 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
191 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
194 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
195 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
202 Check if this memory entry spans across original memory map boundary.
204 @param PhysicalStart The PhysicalStart of memory
205 @param NumberOfPages The NumberOfPages of memory
207 @retval TRUE This memory entry spans across original memory map boundary.
208 @retval FALSE This memory entry does not span cross original memory map boundary.
212 DoesEntrySpanAcrossBoundary (
213 IN UINT64 PhysicalStart
,
214 IN UINT64 NumberOfPages
217 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
218 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
219 UINT64 MemoryBlockLength
;
221 MemoryMapEntry
= mMemoryMapOrg
;
222 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) mMemoryMapOrg
+ mMemoryMapOrgSize
);
223 while (MemoryMapEntry
< MemoryMapEnd
) {
224 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
226 if ((MemoryMapEntry
->PhysicalStart
<= PhysicalStart
) &&
227 (MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
> PhysicalStart
) &&
228 (MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
< PhysicalStart
+ EfiPagesToSize (NumberOfPages
))) {
232 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, mDescriptorSize
);
238 Merge continous memory map entries whose have same attributes.
240 @param MemoryMap A pointer to the buffer in which firmware places
241 the current memory map.
242 @param MemoryMapSize A pointer to the size, in bytes, of the
243 MemoryMap buffer. On input, this is the size of
244 the current memory map. On output,
245 it is the size of new memory map after merge.
246 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
251 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
252 IN OUT UINTN
*MemoryMapSize
,
253 IN UINTN DescriptorSize
256 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
257 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
258 UINT64 MemoryBlockLength
;
259 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
260 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
262 MemoryMapEntry
= MemoryMap
;
263 NewMemoryMapEntry
= MemoryMap
;
264 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
265 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
266 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
267 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
270 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
271 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
272 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
273 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
274 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
) &&
275 (!DoesEntrySpanAcrossBoundary (MemoryMapEntry
->PhysicalStart
, MemoryMapEntry
->NumberOfPages
+ NextMemoryMapEntry
->NumberOfPages
))) {
276 MemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
277 if (NewMemoryMapEntry
!= MemoryMapEntry
) {
278 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
281 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
284 MemoryMapEntry
= PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
289 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
290 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
293 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
299 Enforce memory map attributes.
300 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
302 @param MemoryMap A pointer to the buffer in which firmware places
303 the current memory map.
304 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
305 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
309 EnforceMemoryMapAttribute (
310 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
311 IN UINTN MemoryMapSize
,
312 IN UINTN DescriptorSize
315 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
316 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
318 MemoryMapEntry
= MemoryMap
;
319 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
320 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
321 switch (MemoryMapEntry
->Type
) {
322 case EfiRuntimeServicesCode
:
325 case EfiRuntimeServicesData
:
326 case EfiMemoryMappedIO
:
327 case EfiMemoryMappedIOPortSpace
:
328 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
330 case EfiReservedMemoryType
:
331 case EfiACPIMemoryNVS
:
335 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
342 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
344 @param Buffer Start Address
345 @param Length Address length
347 @return first image record covered by [buffer, length]
350 IMAGE_PROPERTIES_RECORD
*
351 GetImageRecordByAddress (
352 IN EFI_PHYSICAL_ADDRESS Buffer
,
356 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
357 LIST_ENTRY
*ImageRecordLink
;
358 LIST_ENTRY
*ImageRecordList
;
360 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
362 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
363 ImageRecordLink
!= ImageRecordList
;
364 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
367 IMAGE_PROPERTIES_RECORD
,
369 IMAGE_PROPERTIES_RECORD_SIGNATURE
372 if ((Buffer
<= ImageRecord
->ImageBase
) &&
373 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
382 Set the memory map to new entries, according to one old entry,
383 based upon PE code section and data section in image record
385 @param ImageRecord An image record whose [ImageBase, ImageSize] covered
386 by old memory map entry.
387 @param NewRecord A pointer to several new memory map entries.
388 The caller gurantee the buffer size be 1 +
389 (SplitRecordCount * DescriptorSize) calculated
391 @param OldRecord A pointer to one old memory map entry.
392 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
397 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
398 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
399 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
400 IN UINTN DescriptorSize
403 EFI_MEMORY_DESCRIPTOR TempRecord
;
404 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
405 LIST_ENTRY
*ImageRecordCodeSectionLink
;
406 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
407 LIST_ENTRY
*ImageRecordCodeSectionList
;
408 UINTN NewRecordCount
;
412 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
413 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
416 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
418 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
419 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
420 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
421 ImageRecordCodeSection
= CR (
422 ImageRecordCodeSectionLink
,
423 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
425 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
427 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
429 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
433 NewRecord
->Type
= EfiRuntimeServicesData
;
434 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
435 NewRecord
->VirtualStart
= 0;
436 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
437 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
438 if (NewRecord
->NumberOfPages
!= 0) {
439 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
446 NewRecord
->Type
= EfiRuntimeServicesCode
;
447 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
448 NewRecord
->VirtualStart
= 0;
449 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
450 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
451 if (NewRecord
->NumberOfPages
!= 0) {
452 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
456 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
457 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
458 if (TempRecord
.NumberOfPages
== 0) {
464 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
469 if (TempRecord
.PhysicalStart
< ImageEnd
) {
470 NewRecord
->Type
= EfiRuntimeServicesData
;
471 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
472 NewRecord
->VirtualStart
= 0;
473 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
474 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
478 return NewRecordCount
;
482 Return the max number of new splitted entries, according to one old entry,
483 based upon PE code section and data section.
485 @param OldRecord A pointer to one old memory map entry.
487 @retval 0 no entry need to be splitted.
488 @return the max number of new splitted entries
492 GetMaxSplitRecordCount (
493 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
496 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
497 UINTN SplitRecordCount
;
498 UINT64 PhysicalStart
;
501 SplitRecordCount
= 0;
502 PhysicalStart
= OldRecord
->PhysicalStart
;
503 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
506 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
507 if (ImageRecord
== NULL
) {
510 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 1);
511 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
512 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
514 if (SplitRecordCount
!= 0) {
518 return SplitRecordCount
;
522 Split the memory map to new entries, according to one old entry,
523 based upon PE code section and data section.
525 @param OldRecord A pointer to one old memory map entry.
526 @param NewRecord A pointer to several new memory map entries.
527 The caller gurantee the buffer size be 1 +
528 (SplitRecordCount * DescriptorSize) calculated
530 @param MaxSplitRecordCount The max number of splitted entries
531 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
533 @retval 0 no entry is splitted.
534 @return the real number of splitted record.
539 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
540 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
541 IN UINTN MaxSplitRecordCount
,
542 IN UINTN DescriptorSize
545 EFI_MEMORY_DESCRIPTOR TempRecord
;
546 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
547 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
548 UINT64 PhysicalStart
;
550 UINTN NewRecordCount
;
551 UINTN TotalNewRecordCount
;
553 if (MaxSplitRecordCount
== 0) {
554 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
558 TotalNewRecordCount
= 0;
561 // Override previous record
563 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
564 PhysicalStart
= TempRecord
.PhysicalStart
;
565 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
569 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
570 if (NewImageRecord
== NULL
) {
572 // No more image covered by this range, stop
574 if ((PhysicalEnd
> PhysicalStart
) && (ImageRecord
!= NULL
)) {
576 // If this is still address in this record, need record.
578 NewRecord
= PREVIOUS_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
579 if (NewRecord
->Type
== EfiRuntimeServicesData
) {
581 // Last record is DATA, just merge it.
583 NewRecord
->NumberOfPages
= EfiSizeToPages(PhysicalEnd
- NewRecord
->PhysicalStart
);
586 // Last record is CODE, create a new DATA entry.
588 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
589 NewRecord
->Type
= EfiRuntimeServicesData
;
590 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
591 NewRecord
->VirtualStart
= 0;
592 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
593 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
594 TotalNewRecordCount
++;
599 ImageRecord
= NewImageRecord
;
604 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
605 TotalNewRecordCount
+= NewRecordCount
;
606 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
609 // Update PhysicalStart, in order to exclude the image buffer already splitted.
611 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
612 TempRecord
.PhysicalStart
= PhysicalStart
;
613 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
614 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
616 return TotalNewRecordCount
- 1;
620 Split the original memory map, and add more entries to describe PE code section and data section.
621 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
622 This function will merge entries with same attributes finally.
624 NOTE: It assumes PE code/data section are page aligned.
625 NOTE: It assumes enough entry is prepared for new memory map.
638 +---------------+ ----
641 | Record RtCode | |-> PE/COFF1
644 +---------------+ ----
647 | Record RtCode | |-> PE/COFF2
650 +---------------+ ----
654 @param MemoryMapSize A pointer to the size, in bytes, of the
655 MemoryMap buffer. On input, this is the size of
656 old MemoryMap before split. The actual buffer
657 size of MemoryMap is MemoryMapSize +
658 (AdditionalRecordCount * DescriptorSize) calculated
659 below. On output, it is the size of new MemoryMap
661 @param MemoryMap A pointer to the buffer in which firmware places
662 the current memory map.
663 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
668 IN OUT UINTN
*MemoryMapSize
,
669 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
670 IN UINTN DescriptorSize
675 UINTN MaxSplitRecordCount
;
676 UINTN RealSplitRecordCount
;
677 UINTN TotalSplitRecordCount
;
678 UINTN AdditionalRecordCount
;
680 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
682 TotalSplitRecordCount
= 0;
684 // Let old record point to end of valid MemoryMap buffer.
686 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
688 // Let new record point to end of full MemoryMap buffer.
690 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
691 for (; IndexOld
>= 0; IndexOld
--) {
692 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
694 // Split this MemoryMap record
696 IndexNew
-= MaxSplitRecordCount
;
697 RealSplitRecordCount
= SplitRecord (
698 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
699 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
704 // Adjust IndexNew according to real split.
707 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
708 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
709 RealSplitRecordCount
* DescriptorSize
711 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
712 TotalSplitRecordCount
+= RealSplitRecordCount
;
716 // Move all records to the beginning.
720 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
721 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
724 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
727 // Sort from low to high (Just in case)
729 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
732 // Set RuntimeData to XP
734 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
737 // Merge same type to save entry size
739 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
745 This function for GetMemoryMap() with properties table capability.
747 It calls original GetMemoryMap() to get the original memory map information. Then
748 plus the additional memory map entries for PE Code/Data seperation.
750 @param MemoryMapSize A pointer to the size, in bytes, of the
751 MemoryMap buffer. On input, this is the size of
752 the buffer allocated by the caller. On output,
753 it is the size of the buffer returned by the
754 firmware if the buffer was large enough, or the
755 size of the buffer needed to contain the map if
756 the buffer was too small.
757 @param MemoryMap A pointer to the buffer in which firmware places
758 the current memory map.
759 @param MapKey A pointer to the location in which firmware
760 returns the key for the current memory map.
761 @param DescriptorSize A pointer to the location in which firmware
762 returns the size, in bytes, of an individual
763 EFI_MEMORY_DESCRIPTOR.
764 @param DescriptorVersion A pointer to the location in which firmware
765 returns the version number associated with the
766 EFI_MEMORY_DESCRIPTOR.
768 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
770 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
771 buffer size needed to hold the memory map is
772 returned in MemoryMapSize.
773 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
778 CoreGetMemoryMapPropertiesTable (
779 IN OUT UINTN
*MemoryMapSize
,
780 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
782 OUT UINTN
*DescriptorSize
,
783 OUT UINT32
*DescriptorVersion
787 UINTN OldMemoryMapSize
;
788 UINTN AdditionalRecordCount
;
791 // If PE code/data is not aligned, just return.
793 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
794 return CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
797 if (MemoryMapSize
== NULL
) {
798 return EFI_INVALID_PARAMETER
;
801 CoreAcquirePropertiesTableLock ();
803 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
805 OldMemoryMapSize
= *MemoryMapSize
;
806 Status
= CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
807 if (Status
== EFI_BUFFER_TOO_SMALL
) {
808 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
809 } else if (Status
== EFI_SUCCESS
) {
810 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
811 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
813 // Need update status to buffer too small
815 Status
= EFI_BUFFER_TOO_SMALL
;
817 if (mIsConstructingMemoryAttributesTable
) {
819 // If the memory map is constructed for memory attributes table,
820 // save original memory map, because they will be checked later
821 // to make sure the memory attributes table entry does not cross
822 // the original memory map entry boundary.
823 // This work must NOT be done in normal GetMemoryMap() because
824 // allocating memory is not allowed due to MapKey update.
826 mDescriptorSize
= *DescriptorSize
;
827 mMemoryMapOrgSize
= *MemoryMapSize
;
828 mMemoryMapOrg
= AllocateCopyPool (*MemoryMapSize
, MemoryMap
);
829 if (mMemoryMapOrg
== NULL
) {
830 Status
= EFI_OUT_OF_RESOURCES
;
836 // Split PE code/data
838 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
840 if (mIsConstructingMemoryAttributesTable
) {
841 FreePool (mMemoryMapOrg
);
842 mMemoryMapOrg
= NULL
;
843 mMemoryMapOrgSize
= 0;
849 CoreReleasePropertiesTableLock ();
854 // Below functions are for ImageRecord
858 Set PropertiesTable according to PE/COFF image section alignment.
860 @param SectionAlignment PE/COFF section alignment
864 SetPropertiesTableSectionAlignment (
865 IN UINT32 SectionAlignment
868 if (((SectionAlignment
& (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT
- 1)) != 0) &&
869 ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
870 DEBUG ((EFI_D_VERBOSE
, "SetPropertiesTableSectionAlignment - Clear\n"));
871 mPropertiesTable
.MemoryProtectionAttribute
&= ~((UINT64
)EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
);
872 gBS
->GetMemoryMap
= CoreGetMemoryMap
;
874 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
879 Swap two code sections in image record.
881 @param FirstImageRecordCodeSection first code section in image record
882 @param SecondImageRecordCodeSection second code section in image record
886 SwapImageRecordCodeSection (
887 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
888 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
891 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
893 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
894 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
896 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
897 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
899 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
900 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
904 Sort code section in image record, based upon CodeSegmentBase from low to high.
906 @param ImageRecord image record to be sorted
910 SortImageRecordCodeSection (
911 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
914 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
915 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
916 LIST_ENTRY
*ImageRecordCodeSectionLink
;
917 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
918 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
919 LIST_ENTRY
*ImageRecordCodeSectionList
;
921 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
923 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
924 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
925 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
926 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
927 ImageRecordCodeSection
= CR (
928 ImageRecordCodeSectionLink
,
929 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
931 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
933 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
934 NextImageRecordCodeSection
= CR (
935 NextImageRecordCodeSectionLink
,
936 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
938 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
940 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
941 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
943 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
946 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
947 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
952 Check if code section in image record is valid.
954 @param ImageRecord image record to be checked
956 @retval TRUE image record is valid
957 @retval FALSE image record is invalid
961 IsImageRecordCodeSectionValid (
962 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
965 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
966 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
967 LIST_ENTRY
*ImageRecordCodeSectionLink
;
968 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
969 LIST_ENTRY
*ImageRecordCodeSectionList
;
971 DEBUG ((EFI_D_VERBOSE
, "ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
973 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
975 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
976 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
977 LastImageRecordCodeSection
= NULL
;
978 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
979 ImageRecordCodeSection
= CR (
980 ImageRecordCodeSectionLink
,
981 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
983 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
985 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
988 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
991 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
994 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
997 if (LastImageRecordCodeSection
!= NULL
) {
998 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
1003 LastImageRecordCodeSection
= ImageRecordCodeSection
;
1004 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
1011 Swap two image records.
1013 @param FirstImageRecord first image record.
1014 @param SecondImageRecord second image record.
1019 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
1020 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
1023 IMAGE_PROPERTIES_RECORD TempImageRecord
;
1025 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
1026 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
1027 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
1029 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
1030 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
1031 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
1033 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
1034 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
1035 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
1037 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
1041 Sort image record based upon the ImageBase from low to high.
1049 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1050 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
1051 LIST_ENTRY
*ImageRecordLink
;
1052 LIST_ENTRY
*NextImageRecordLink
;
1053 LIST_ENTRY
*ImageRecordEndLink
;
1054 LIST_ENTRY
*ImageRecordList
;
1056 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1058 ImageRecordLink
= ImageRecordList
->ForwardLink
;
1059 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1060 ImageRecordEndLink
= ImageRecordList
;
1061 while (ImageRecordLink
!= ImageRecordEndLink
) {
1064 IMAGE_PROPERTIES_RECORD
,
1066 IMAGE_PROPERTIES_RECORD_SIGNATURE
1068 while (NextImageRecordLink
!= ImageRecordEndLink
) {
1069 NextImageRecord
= CR (
1070 NextImageRecordLink
,
1071 IMAGE_PROPERTIES_RECORD
,
1073 IMAGE_PROPERTIES_RECORD_SIGNATURE
1075 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
1076 SwapImageRecord (ImageRecord
, NextImageRecord
);
1078 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
1081 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
1082 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1095 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1096 LIST_ENTRY
*ImageRecordLink
;
1097 LIST_ENTRY
*ImageRecordList
;
1100 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1102 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1103 ImageRecordLink
!= ImageRecordList
;
1104 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1107 IMAGE_PROPERTIES_RECORD
,
1109 IMAGE_PROPERTIES_RECORD_SIGNATURE
1111 DEBUG ((EFI_D_VERBOSE
, " Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1116 Insert image record.
1118 @param RuntimeImage Runtime image information
1122 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1126 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1127 UINT32 PeCoffHeaderOffset
;
1128 UINT32 SectionAlignment
;
1129 EFI_IMAGE_SECTION_HEADER
*Section
;
1130 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1133 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1135 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1138 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%x\n", RuntimeImage
));
1139 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1141 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1142 if (ImageRecord
== NULL
) {
1145 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1147 DEBUG ((EFI_D_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1150 // Step 1: record whole region
1152 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1153 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1155 ImageAddress
= RuntimeImage
->ImageBase
;
1157 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1158 if (PdbPointer
!= NULL
) {
1159 DEBUG ((EFI_D_VERBOSE
, " Image - %a\n", PdbPointer
));
1163 // Check PE/COFF image
1165 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1166 PeCoffHeaderOffset
= 0;
1167 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1168 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1171 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1172 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1173 DEBUG ((EFI_D_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1174 // It might be image in SMM.
1179 // Get SectionAlignment
1181 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1183 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1184 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1185 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1186 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1188 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1191 // Get the magic value from the PE/COFF Optional Header
1193 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1195 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1196 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1198 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1201 SetPropertiesTableSectionAlignment (SectionAlignment
);
1202 if ((SectionAlignment
& (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT
- 1)) != 0) {
1203 DEBUG ((EFI_D_WARN
, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1204 SectionAlignment
, EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT
>> 10));
1205 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1206 if (PdbPointer
!= NULL
) {
1207 DEBUG ((EFI_D_WARN
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1212 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1213 (UINT8
*) (UINTN
) ImageAddress
+
1214 PeCoffHeaderOffset
+
1216 sizeof(EFI_IMAGE_FILE_HEADER
) +
1217 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1219 ImageRecord
->CodeSegmentCount
= 0;
1220 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1221 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1222 Name
= Section
[Index
].Name
;
1225 " Section - '%c%c%c%c%c%c%c%c'\n",
1236 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1237 DEBUG ((EFI_D_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1238 DEBUG ((EFI_D_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1239 DEBUG ((EFI_D_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1240 DEBUG ((EFI_D_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1241 DEBUG ((EFI_D_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1242 DEBUG ((EFI_D_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1243 DEBUG ((EFI_D_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1244 DEBUG ((EFI_D_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1245 DEBUG ((EFI_D_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1248 // Step 2: record code section
1250 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1251 if (ImageRecordCodeSection
== NULL
) {
1254 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1256 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1257 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1259 DEBUG ((EFI_D_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1261 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1262 ImageRecord
->CodeSegmentCount
++;
1266 if (ImageRecord
->CodeSegmentCount
== 0) {
1267 SetPropertiesTableSectionAlignment (1);
1268 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1269 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1270 if (PdbPointer
!= NULL
) {
1271 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1279 SortImageRecordCodeSection (ImageRecord
);
1281 // Check overlap all section in ImageBase/Size
1283 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1284 DEBUG ((EFI_D_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1288 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1289 mImagePropertiesPrivateData
.ImageRecordCount
++;
1293 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1294 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1302 Find image record according to image base and size.
1304 @param ImageBase Base of PE image
1305 @param ImageSize Size of PE image
1307 @return image record
1310 IMAGE_PROPERTIES_RECORD
*
1312 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1316 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1317 LIST_ENTRY
*ImageRecordLink
;
1318 LIST_ENTRY
*ImageRecordList
;
1320 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1322 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1323 ImageRecordLink
!= ImageRecordList
;
1324 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1327 IMAGE_PROPERTIES_RECORD
,
1329 IMAGE_PROPERTIES_RECORD_SIGNATURE
1332 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1333 (ImageSize
== ImageRecord
->ImageSize
)) {
1342 Remove Image record.
1344 @param RuntimeImage Runtime image information
1348 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1351 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1352 LIST_ENTRY
*CodeSegmentListHead
;
1353 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1355 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1356 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1358 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1359 if (ImageRecord
== NULL
) {
1360 DEBUG ((EFI_D_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1364 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1365 while (!IsListEmpty (CodeSegmentListHead
)) {
1366 ImageRecordCodeSection
= CR (
1367 CodeSegmentListHead
->ForwardLink
,
1368 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1370 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1372 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1373 FreePool (ImageRecordCodeSection
);
1376 RemoveEntryList (&ImageRecord
->Link
);
1377 FreePool (ImageRecord
);
1378 mImagePropertiesPrivateData
.ImageRecordCount
--;
1383 Install PropertiesTable.
1385 @param[in] Event The Event this notify function registered to.
1386 @param[in] Context Pointer to the context data registered to the Event.
1390 InstallPropertiesTable (
1395 if (PcdGetBool (PcdPropertiesTableEnable
)) {
1398 Status
= gBS
->InstallConfigurationTable (&gEfiPropertiesTableGuid
, &mPropertiesTable
);
1399 ASSERT_EFI_ERROR (Status
);
1401 DEBUG ((EFI_D_INFO
, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable
.MemoryProtectionAttribute
));
1402 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1403 DEBUG ((EFI_D_ERROR
, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));
1404 DEBUG ((EFI_D_ERROR
, "because Runtime Driver Section Alignment is not %dK.\n", EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT
>> 10));
1408 gBS
->GetMemoryMap
= CoreGetMemoryMapPropertiesTable
;
1410 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
1412 DEBUG ((EFI_D_VERBOSE
, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1413 DEBUG ((EFI_D_VERBOSE
, "Dump ImageRecord:\n"));
1419 Initialize PropertiesTable support.
1423 CoreInitializePropertiesTable (
1428 EFI_EVENT EndOfDxeEvent
;
1430 Status
= gBS
->CreateEventEx (
1433 InstallPropertiesTable
,
1435 &gEfiEndOfDxeEventGroupGuid
,
1438 ASSERT_EFI_ERROR (Status
);