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 // Below functions are for MemoryMap
88 Converts a number of EFI_PAGEs to a size in bytes.
90 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
92 @param Pages The number of EFI_PAGES.
94 @return The number of bytes associated with the number of EFI_PAGEs specified
102 return LShiftU64 (Pages
, EFI_PAGE_SHIFT
);
106 Converts a size, in bytes, to a number of EFI_PAGESs.
108 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
110 @param Size A size in bytes.
112 @return The number of EFI_PAGESs associated with the number of bytes specified
121 return RShiftU64 (Size
, EFI_PAGE_SHIFT
) + ((((UINTN
)Size
) & EFI_PAGE_MASK
) ? 1 : 0);
125 Acquire memory lock on mPropertiesTableLock.
128 CoreAcquirePropertiesTableLock (
132 CoreAcquireLock (&mPropertiesTableLock
);
136 Release memory lock on mPropertiesTableLock.
139 CoreReleasePropertiesTableLock (
143 CoreReleaseLock (&mPropertiesTableLock
);
149 @param MemoryMap A pointer to the buffer in which firmware places
150 the current memory map.
151 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
152 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
156 IN EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
157 IN UINTN MemoryMapSize
,
158 IN UINTN DescriptorSize
161 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
162 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
163 UINT64 MemoryBlockLength
;
165 DEBUG ((EFI_D_VERBOSE
, " MemoryMap:\n"));
166 MemoryMapEntry
= MemoryMap
;
167 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
168 while (MemoryMapEntry
< MemoryMapEnd
) {
169 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
170 DEBUG ((EFI_D_VERBOSE
, " Entry(0x%02x) 0x%016lx - 0x%016lx (0x%016lx)\n", MemoryMapEntry
->Type
, MemoryMapEntry
->PhysicalStart
, MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
, MemoryMapEntry
->Attribute
));
171 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
176 Sort memory map entries based upon PhysicalStart, from low to high.
178 @param MemoryMap A pointer to the buffer in which firmware places
179 the current memory map.
180 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
181 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
185 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
186 IN UINTN MemoryMapSize
,
187 IN UINTN DescriptorSize
190 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
191 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
192 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
193 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
195 MemoryMapEntry
= MemoryMap
;
196 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
197 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
198 while (MemoryMapEntry
< MemoryMapEnd
) {
199 while (NextMemoryMapEntry
< MemoryMapEnd
) {
200 if (MemoryMapEntry
->PhysicalStart
> NextMemoryMapEntry
->PhysicalStart
) {
201 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
202 CopyMem (MemoryMapEntry
, NextMemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
203 CopyMem (NextMemoryMapEntry
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
206 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry
, DescriptorSize
);
209 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
210 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
217 Merge continous memory map entries whose have same attributes.
219 @param MemoryMap A pointer to the buffer in which firmware places
220 the current memory map.
221 @param MemoryMapSize A pointer to the size, in bytes, of the
222 MemoryMap buffer. On input, this is the size of
223 the current memory map. On output,
224 it is the size of new memory map after merge.
225 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
229 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
230 IN OUT UINTN
*MemoryMapSize
,
231 IN UINTN DescriptorSize
234 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
235 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
236 UINT64 MemoryBlockLength
;
237 EFI_MEMORY_DESCRIPTOR
*NewMemoryMapEntry
;
238 EFI_MEMORY_DESCRIPTOR
*NextMemoryMapEntry
;
240 MemoryMapEntry
= MemoryMap
;
241 NewMemoryMapEntry
= MemoryMap
;
242 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ *MemoryMapSize
);
243 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
244 CopyMem (NewMemoryMapEntry
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
245 NextMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
247 MemoryBlockLength
= (UINT64
) (EfiPagesToSize (MemoryMapEntry
->NumberOfPages
));
248 if (((UINTN
)NextMemoryMapEntry
< (UINTN
)MemoryMapEnd
) &&
249 (MemoryMapEntry
->Type
== NextMemoryMapEntry
->Type
) &&
250 (MemoryMapEntry
->Attribute
== NextMemoryMapEntry
->Attribute
) &&
251 ((MemoryMapEntry
->PhysicalStart
+ MemoryBlockLength
) == NextMemoryMapEntry
->PhysicalStart
)) {
252 NewMemoryMapEntry
->NumberOfPages
+= NextMemoryMapEntry
->NumberOfPages
;
253 MemoryMapEntry
= NextMemoryMapEntry
;
256 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
257 NewMemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry
, DescriptorSize
);
260 *MemoryMapSize
= (UINTN
)NewMemoryMapEntry
- (UINTN
)MemoryMap
;
266 Enforce memory map attributes.
267 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
269 @param MemoryMap A pointer to the buffer in which firmware places
270 the current memory map.
271 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
272 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
275 EnforceMemoryMapAttribute (
276 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
277 IN UINTN MemoryMapSize
,
278 IN UINTN DescriptorSize
281 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
282 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
284 MemoryMapEntry
= MemoryMap
;
285 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
286 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
287 switch (MemoryMapEntry
->Type
) {
288 case EfiRuntimeServicesCode
:
291 case EfiRuntimeServicesData
:
292 case EfiMemoryMappedIO
:
293 case EfiMemoryMappedIOPortSpace
:
294 MemoryMapEntry
->Attribute
|= EFI_MEMORY_XP
;
296 case EfiReservedMemoryType
:
297 case EfiACPIMemoryNVS
:
301 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
308 Sort memory map entries whose type is EfiRuntimeServicesCode/EfiRuntimeServicesData,
310 This function assumes memory map is already from low to high, so it just reverts them.
312 @param MemoryMap A pointer to the buffer in which firmware places
313 the current memory map.
314 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
315 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
318 RevertRuntimeMemoryMap (
319 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
320 IN UINTN MemoryMapSize
,
321 IN UINTN DescriptorSize
324 EFI_MEMORY_DESCRIPTOR
*MemoryMapEntry
;
325 EFI_MEMORY_DESCRIPTOR
*MemoryMapEnd
;
326 EFI_MEMORY_DESCRIPTOR TempMemoryMap
;
328 EFI_MEMORY_DESCRIPTOR
*RuntimeMapEntryBegin
;
329 EFI_MEMORY_DESCRIPTOR
*RuntimeMapEntryEnd
;
331 MemoryMapEntry
= MemoryMap
;
332 RuntimeMapEntryBegin
= NULL
;
333 RuntimeMapEntryEnd
= NULL
;
334 MemoryMapEnd
= (EFI_MEMORY_DESCRIPTOR
*) ((UINT8
*) MemoryMap
+ MemoryMapSize
);
335 while ((UINTN
)MemoryMapEntry
< (UINTN
)MemoryMapEnd
) {
336 if ((MemoryMapEntry
->Type
== EfiRuntimeServicesCode
) ||
337 (MemoryMapEntry
->Type
== EfiRuntimeServicesData
)) {
338 if (RuntimeMapEntryBegin
== NULL
) {
339 RuntimeMapEntryBegin
= MemoryMapEntry
;
341 RuntimeMapEntryEnd
= MemoryMapEntry
;
343 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
346 MemoryMapEntry
= RuntimeMapEntryBegin
;
347 MemoryMapEnd
= RuntimeMapEntryEnd
;
348 while (MemoryMapEntry
< MemoryMapEnd
) {
349 CopyMem (&TempMemoryMap
, MemoryMapEntry
, sizeof(EFI_MEMORY_DESCRIPTOR
));
350 CopyMem (MemoryMapEntry
, MemoryMapEnd
, sizeof(EFI_MEMORY_DESCRIPTOR
));
351 CopyMem (MemoryMapEnd
, &TempMemoryMap
, sizeof(EFI_MEMORY_DESCRIPTOR
));
353 MemoryMapEntry
= NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry
, DescriptorSize
);
354 MemoryMapEnd
= PREVIOUS_MEMORY_DESCRIPTOR (MemoryMapEnd
, DescriptorSize
);
361 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
363 @param Buffer Start Address
364 @param Length Address length
366 @return first image record covered by [buffer, length]
368 IMAGE_PROPERTIES_RECORD
*
369 GetImageRecordByAddress (
370 IN EFI_PHYSICAL_ADDRESS Buffer
,
374 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
375 LIST_ENTRY
*ImageRecordLink
;
376 LIST_ENTRY
*ImageRecordList
;
378 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
380 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
381 ImageRecordLink
!= ImageRecordList
;
382 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
385 IMAGE_PROPERTIES_RECORD
,
387 IMAGE_PROPERTIES_RECORD_SIGNATURE
390 if ((Buffer
<= ImageRecord
->ImageBase
) &&
391 (Buffer
+ Length
>= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
400 Set the memory map to new entries, according to one old entry,
401 based upon PE code section and data section in image record
403 @param ImageRecord An image record whose [ImageBase, ImageSize] covered
404 by old memory map entry.
405 @param NewRecord A pointer to several new memory map entries.
406 The caller gurantee the buffer size be 1 +
407 (SplitRecordCount * DescriptorSize) calculated
409 @param OldRecord A pointer to one old memory map entry.
410 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
414 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
,
415 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
416 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
417 IN UINTN DescriptorSize
420 EFI_MEMORY_DESCRIPTOR TempRecord
;
421 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
422 LIST_ENTRY
*ImageRecordCodeSectionLink
;
423 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
424 LIST_ENTRY
*ImageRecordCodeSectionList
;
425 UINTN NewRecordCount
;
429 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
430 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
433 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
435 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
436 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
437 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
438 ImageRecordCodeSection
= CR (
439 ImageRecordCodeSectionLink
,
440 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
442 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
444 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
446 if (TempRecord
.PhysicalStart
<= ImageRecordCodeSection
->CodeSegmentBase
) {
450 NewRecord
->Type
= EfiRuntimeServicesData
;
451 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
452 NewRecord
->VirtualStart
= 0;
453 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentBase
- NewRecord
->PhysicalStart
);
454 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
455 if (NewRecord
->NumberOfPages
!= 0) {
456 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
463 NewRecord
->Type
= EfiRuntimeServicesCode
;
464 NewRecord
->PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
;
465 NewRecord
->VirtualStart
= 0;
466 NewRecord
->NumberOfPages
= EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
);
467 NewRecord
->Attribute
= (TempRecord
.Attribute
& (~EFI_MEMORY_XP
)) | EFI_MEMORY_RO
;
468 if (NewRecord
->NumberOfPages
!= 0) {
469 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
473 TempRecord
.PhysicalStart
= ImageRecordCodeSection
->CodeSegmentBase
+ EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection
->CodeSegmentSize
));
474 TempRecord
.NumberOfPages
= EfiSizeToPages(PhysicalEnd
- TempRecord
.PhysicalStart
);
475 if (TempRecord
.NumberOfPages
== 0) {
481 ImageEnd
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
486 if (TempRecord
.PhysicalStart
< ImageEnd
) {
487 NewRecord
->Type
= EfiRuntimeServicesData
;
488 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
489 NewRecord
->VirtualStart
= 0;
490 NewRecord
->NumberOfPages
= EfiSizeToPages (ImageEnd
- TempRecord
.PhysicalStart
);
491 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
495 return NewRecordCount
;
499 Return the max number of new splitted entries, according to one old entry,
500 based upon PE code section and data section.
502 @param OldRecord A pointer to one old memory map entry.
504 @retval 0 no entry need to be splitted.
505 @return the max number of new splitted entries
508 GetMaxSplitRecordCount (
509 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
512 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
513 UINTN SplitRecordCount
;
514 UINT64 PhysicalStart
;
517 SplitRecordCount
= 0;
518 PhysicalStart
= OldRecord
->PhysicalStart
;
519 PhysicalEnd
= OldRecord
->PhysicalStart
+ EfiPagesToSize(OldRecord
->NumberOfPages
);
522 ImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
523 if (ImageRecord
== NULL
) {
526 SplitRecordCount
+= (2 * ImageRecord
->CodeSegmentCount
+ 1);
527 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
528 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
530 if (SplitRecordCount
!= 0) {
534 return SplitRecordCount
;
538 Split the memory map to new entries, according to one old entry,
539 based upon PE code section and data section.
541 @param OldRecord A pointer to one old memory map entry.
542 @param NewRecord A pointer to several new memory map entries.
543 The caller gurantee the buffer size be 1 +
544 (SplitRecordCount * DescriptorSize) calculated
546 @param MaxSplitRecordCount The max number of splitted entries
547 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
549 @retval 0 no entry is splitted.
550 @return the real number of splitted record.
554 IN EFI_MEMORY_DESCRIPTOR
*OldRecord
,
555 IN OUT EFI_MEMORY_DESCRIPTOR
*NewRecord
,
556 IN UINTN MaxSplitRecordCount
,
557 IN UINTN DescriptorSize
560 EFI_MEMORY_DESCRIPTOR TempRecord
;
561 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
562 IMAGE_PROPERTIES_RECORD
*NewImageRecord
;
563 UINT64 PhysicalStart
;
565 UINTN NewRecordCount
;
566 UINTN TotalNewRecordCount
;
568 if (MaxSplitRecordCount
== 0) {
569 CopyMem (NewRecord
, OldRecord
, DescriptorSize
);
573 TotalNewRecordCount
= 0;
576 // Override previous record
578 CopyMem (&TempRecord
, OldRecord
, sizeof(EFI_MEMORY_DESCRIPTOR
));
579 PhysicalStart
= TempRecord
.PhysicalStart
;
580 PhysicalEnd
= TempRecord
.PhysicalStart
+ EfiPagesToSize(TempRecord
.NumberOfPages
);
584 NewImageRecord
= GetImageRecordByAddress (PhysicalStart
, PhysicalEnd
- PhysicalStart
);
585 if (NewImageRecord
== NULL
) {
587 // No more image covered by this range, stop
589 if ((PhysicalEnd
> PhysicalStart
) && (ImageRecord
!= NULL
)) {
591 // If this is still address in this record, need record.
593 NewRecord
= PREVIOUS_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
594 if (NewRecord
->Type
== EfiRuntimeServicesData
) {
596 // Last record is DATA, just merge it.
598 NewRecord
->NumberOfPages
= EfiSizeToPages(PhysicalEnd
- NewRecord
->PhysicalStart
);
601 // Last record is CODE, create a new DATA entry.
603 NewRecord
= NEXT_MEMORY_DESCRIPTOR (NewRecord
, DescriptorSize
);
604 NewRecord
->Type
= EfiRuntimeServicesData
;
605 NewRecord
->PhysicalStart
= TempRecord
.PhysicalStart
;
606 NewRecord
->VirtualStart
= 0;
607 NewRecord
->NumberOfPages
= TempRecord
.NumberOfPages
;
608 NewRecord
->Attribute
= TempRecord
.Attribute
| EFI_MEMORY_XP
;
609 TotalNewRecordCount
++;
614 ImageRecord
= NewImageRecord
;
619 NewRecordCount
= SetNewRecord (ImageRecord
, NewRecord
, &TempRecord
, DescriptorSize
);
620 TotalNewRecordCount
+= NewRecordCount
;
621 NewRecord
= (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)NewRecord
+ NewRecordCount
* DescriptorSize
);
624 // Update PhysicalStart, in order to exclude the image buffer already splitted.
626 PhysicalStart
= ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
;
627 TempRecord
.PhysicalStart
= PhysicalStart
;
628 TempRecord
.NumberOfPages
= EfiSizeToPages (PhysicalEnd
- PhysicalStart
);
629 } while ((ImageRecord
!= NULL
) && (PhysicalStart
< PhysicalEnd
));
631 return TotalNewRecordCount
- 1;
635 Split the original memory map, and add more entries to describe PE code section and data section.
636 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
637 This function will merge entries with same attributes finally.
639 NOTE: It assumes PE code/data section are page aligned.
640 NOTE: It assumes enough entry is prepared for new memory map.
653 +---------------+ ----
656 | Record RtCode | |-> PE/COFF1
659 +---------------+ ----
662 | Record RtCode | |-> PE/COFF2
665 +---------------+ ----
669 @param MemoryMapSize A pointer to the size, in bytes, of the
670 MemoryMap buffer. On input, this is the size of
671 old MemoryMap before split. The actual buffer
672 size of MemoryMap is MemoryMapSize +
673 (AdditionalRecordCount * DescriptorSize) calculated
674 below. On output, it is the size of new MemoryMap
676 @param MemoryMap A pointer to the buffer in which firmware places
677 the current memory map.
678 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
682 IN OUT UINTN
*MemoryMapSize
,
683 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
684 IN UINTN DescriptorSize
689 UINTN MaxSplitRecordCount
;
690 UINTN RealSplitRecordCount
;
691 UINTN TotalSplitRecordCount
;
692 UINTN AdditionalRecordCount
;
694 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
696 TotalSplitRecordCount
= 0;
698 // Let old record point to end of valid MemoryMap buffer.
700 IndexOld
= ((*MemoryMapSize
) / DescriptorSize
) - 1;
702 // Let new record point to end of full MemoryMap buffer.
704 IndexNew
= ((*MemoryMapSize
) / DescriptorSize
) - 1 + AdditionalRecordCount
;
705 for (; IndexOld
>= 0; IndexOld
--) {
706 MaxSplitRecordCount
= GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
));
708 // Split this MemoryMap record
710 IndexNew
-= MaxSplitRecordCount
;
711 RealSplitRecordCount
= SplitRecord (
712 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexOld
* DescriptorSize
),
713 (EFI_MEMORY_DESCRIPTOR
*)((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
718 // Adjust IndexNew according to real split.
721 ((UINT8
*)MemoryMap
+ (IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
) * DescriptorSize
),
722 ((UINT8
*)MemoryMap
+ IndexNew
* DescriptorSize
),
723 RealSplitRecordCount
* DescriptorSize
725 IndexNew
= IndexNew
+ MaxSplitRecordCount
- RealSplitRecordCount
;
726 TotalSplitRecordCount
+= RealSplitRecordCount
;
730 // Move all records to the beginning.
734 (UINT8
*)MemoryMap
+ (AdditionalRecordCount
- TotalSplitRecordCount
) * DescriptorSize
,
735 (*MemoryMapSize
) + TotalSplitRecordCount
* DescriptorSize
738 *MemoryMapSize
= (*MemoryMapSize
) + DescriptorSize
* TotalSplitRecordCount
;
741 // Sort from low to high (Just in case)
743 SortMemoryMap (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
746 // Set RuntimeData to XP
748 EnforceMemoryMapAttribute (MemoryMap
, *MemoryMapSize
, DescriptorSize
);
751 // Merge same type to save entry size
753 MergeMemoryMap (MemoryMap
, MemoryMapSize
, DescriptorSize
);
759 This function for GetMemoryMap() with properties table.
761 It calls original GetMemoryMap() to get the original memory map information. Then
762 plus the additional memory map entries for PE Code/Data seperation.
764 @param MemoryMapSize A pointer to the size, in bytes, of the
765 MemoryMap buffer. On input, this is the size of
766 the buffer allocated by the caller. On output,
767 it is the size of the buffer returned by the
768 firmware if the buffer was large enough, or the
769 size of the buffer needed to contain the map if
770 the buffer was too small.
771 @param MemoryMap A pointer to the buffer in which firmware places
772 the current memory map.
773 @param MapKey A pointer to the location in which firmware
774 returns the key for the current memory map.
775 @param DescriptorSize A pointer to the location in which firmware
776 returns the size, in bytes, of an individual
777 EFI_MEMORY_DESCRIPTOR.
778 @param DescriptorVersion A pointer to the location in which firmware
779 returns the version number associated with the
780 EFI_MEMORY_DESCRIPTOR.
782 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
784 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
785 buffer size needed to hold the memory map is
786 returned in MemoryMapSize.
787 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
792 CoreGetMemoryMapPropertiesTable (
793 IN OUT UINTN
*MemoryMapSize
,
794 IN OUT EFI_MEMORY_DESCRIPTOR
*MemoryMap
,
796 OUT UINTN
*DescriptorSize
,
797 OUT UINT32
*DescriptorVersion
801 UINTN OldMemoryMapSize
;
802 UINTN AdditionalRecordCount
;
805 // If PE code/data is not aligned, just return.
807 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
808 return CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
811 if (MemoryMapSize
== NULL
) {
812 return EFI_INVALID_PARAMETER
;
815 CoreAcquirePropertiesTableLock ();
817 AdditionalRecordCount
= (2 * mImagePropertiesPrivateData
.CodeSegmentCountMax
+ 1) * mImagePropertiesPrivateData
.ImageRecordCount
;
819 OldMemoryMapSize
= *MemoryMapSize
;
820 Status
= CoreGetMemoryMap (MemoryMapSize
, MemoryMap
, MapKey
, DescriptorSize
, DescriptorVersion
);
821 if (Status
== EFI_BUFFER_TOO_SMALL
) {
822 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
823 } else if (Status
== EFI_SUCCESS
) {
824 if (OldMemoryMapSize
- *MemoryMapSize
< (*DescriptorSize
) * AdditionalRecordCount
) {
825 *MemoryMapSize
= *MemoryMapSize
+ (*DescriptorSize
) * AdditionalRecordCount
;
827 // Need update status to buffer too small
829 Status
= EFI_BUFFER_TOO_SMALL
;
832 // Split PE code/data
834 SplitTable (MemoryMapSize
, MemoryMap
, *DescriptorSize
);
838 CoreReleasePropertiesTableLock ();
843 // Below functions are for ImageRecord
847 Set PropertiesTable accroding to PE/COFF image section alignment.
849 @param SectionAlignment PE/COFF section alignment
852 SetPropertiesTableSectionAlignment (
853 IN UINT32 SectionAlignment
856 if (((SectionAlignment
& (SIZE_4KB
- 1)) != 0) &&
857 ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) != 0)) {
858 DEBUG ((EFI_D_VERBOSE
, "SetPropertiesTableSectionAlignment - Clear\n"));
859 mPropertiesTable
.MemoryProtectionAttribute
&= ~EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
;
860 gBS
->GetMemoryMap
= CoreGetMemoryMap
;
862 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
867 Swap two code sections in image record.
869 @param FirstImageRecordCodeSection first code section in image record
870 @param SecondImageRecordCodeSection second code section in image record
873 SwapImageRecordCodeSection (
874 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*FirstImageRecordCodeSection
,
875 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION
*SecondImageRecordCodeSection
878 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection
;
880 TempImageRecordCodeSection
.CodeSegmentBase
= FirstImageRecordCodeSection
->CodeSegmentBase
;
881 TempImageRecordCodeSection
.CodeSegmentSize
= FirstImageRecordCodeSection
->CodeSegmentSize
;
883 FirstImageRecordCodeSection
->CodeSegmentBase
= SecondImageRecordCodeSection
->CodeSegmentBase
;
884 FirstImageRecordCodeSection
->CodeSegmentSize
= SecondImageRecordCodeSection
->CodeSegmentSize
;
886 SecondImageRecordCodeSection
->CodeSegmentBase
= TempImageRecordCodeSection
.CodeSegmentBase
;
887 SecondImageRecordCodeSection
->CodeSegmentSize
= TempImageRecordCodeSection
.CodeSegmentSize
;
891 Sort code section in image record, based upon CodeSegmentBase from low to high.
893 @param ImageRecord image record to be sorted
896 SortImageRecordCodeSection (
897 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
900 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
901 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*NextImageRecordCodeSection
;
902 LIST_ENTRY
*ImageRecordCodeSectionLink
;
903 LIST_ENTRY
*NextImageRecordCodeSectionLink
;
904 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
905 LIST_ENTRY
*ImageRecordCodeSectionList
;
907 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
909 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
910 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
911 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
912 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
913 ImageRecordCodeSection
= CR (
914 ImageRecordCodeSectionLink
,
915 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
917 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
919 while (NextImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
920 NextImageRecordCodeSection
= CR (
921 NextImageRecordCodeSectionLink
,
922 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
924 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
926 if (ImageRecordCodeSection
->CodeSegmentBase
> NextImageRecordCodeSection
->CodeSegmentBase
) {
927 SwapImageRecordCodeSection (ImageRecordCodeSection
, NextImageRecordCodeSection
);
929 NextImageRecordCodeSectionLink
= NextImageRecordCodeSectionLink
->ForwardLink
;
932 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
933 NextImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
938 Check if code section in image record is valid.
940 @param ImageRecord image record to be checked
942 @retval TRUE image record is valid
943 @retval FALSE image record is invalid
946 IsImageRecordCodeSectionValid (
947 IN IMAGE_PROPERTIES_RECORD
*ImageRecord
950 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
951 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*LastImageRecordCodeSection
;
952 LIST_ENTRY
*ImageRecordCodeSectionLink
;
953 LIST_ENTRY
*ImageRecordCodeSectionEndLink
;
954 LIST_ENTRY
*ImageRecordCodeSectionList
;
956 DEBUG ((EFI_D_VERBOSE
, "ImageCode SegmentCount - 0x%x\n", ImageRecord
->CodeSegmentCount
));
958 ImageRecordCodeSectionList
= &ImageRecord
->CodeSegmentList
;
960 ImageRecordCodeSectionLink
= ImageRecordCodeSectionList
->ForwardLink
;
961 ImageRecordCodeSectionEndLink
= ImageRecordCodeSectionList
;
962 LastImageRecordCodeSection
= NULL
;
963 while (ImageRecordCodeSectionLink
!= ImageRecordCodeSectionEndLink
) {
964 ImageRecordCodeSection
= CR (
965 ImageRecordCodeSectionLink
,
966 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
968 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
970 if (ImageRecordCodeSection
->CodeSegmentSize
== 0) {
973 if (ImageRecordCodeSection
->CodeSegmentBase
< ImageRecord
->ImageBase
) {
976 if (ImageRecordCodeSection
->CodeSegmentBase
>= MAX_ADDRESS
- ImageRecordCodeSection
->CodeSegmentSize
) {
979 if ((ImageRecordCodeSection
->CodeSegmentBase
+ ImageRecordCodeSection
->CodeSegmentSize
) > (ImageRecord
->ImageBase
+ ImageRecord
->ImageSize
)) {
982 if (LastImageRecordCodeSection
!= NULL
) {
983 if ((LastImageRecordCodeSection
->CodeSegmentBase
+ LastImageRecordCodeSection
->CodeSegmentSize
) > ImageRecordCodeSection
->CodeSegmentBase
) {
988 LastImageRecordCodeSection
= ImageRecordCodeSection
;
989 ImageRecordCodeSectionLink
= ImageRecordCodeSectionLink
->ForwardLink
;
996 Swap two image records.
998 @param FirstImageRecord first image record.
999 @param SecondImageRecord second image record.
1003 IN IMAGE_PROPERTIES_RECORD
*FirstImageRecord
,
1004 IN IMAGE_PROPERTIES_RECORD
*SecondImageRecord
1007 IMAGE_PROPERTIES_RECORD TempImageRecord
;
1009 TempImageRecord
.ImageBase
= FirstImageRecord
->ImageBase
;
1010 TempImageRecord
.ImageSize
= FirstImageRecord
->ImageSize
;
1011 TempImageRecord
.CodeSegmentCount
= FirstImageRecord
->CodeSegmentCount
;
1013 FirstImageRecord
->ImageBase
= SecondImageRecord
->ImageBase
;
1014 FirstImageRecord
->ImageSize
= SecondImageRecord
->ImageSize
;
1015 FirstImageRecord
->CodeSegmentCount
= SecondImageRecord
->CodeSegmentCount
;
1017 SecondImageRecord
->ImageBase
= TempImageRecord
.ImageBase
;
1018 SecondImageRecord
->ImageSize
= TempImageRecord
.ImageSize
;
1019 SecondImageRecord
->CodeSegmentCount
= TempImageRecord
.CodeSegmentCount
;
1021 SwapListEntries (&FirstImageRecord
->CodeSegmentList
, &SecondImageRecord
->CodeSegmentList
);
1025 Sort image record based upon the ImageBase from low to high.
1032 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1033 IMAGE_PROPERTIES_RECORD
*NextImageRecord
;
1034 LIST_ENTRY
*ImageRecordLink
;
1035 LIST_ENTRY
*NextImageRecordLink
;
1036 LIST_ENTRY
*ImageRecordEndLink
;
1037 LIST_ENTRY
*ImageRecordList
;
1039 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1041 ImageRecordLink
= ImageRecordList
->ForwardLink
;
1042 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1043 ImageRecordEndLink
= ImageRecordList
;
1044 while (ImageRecordLink
!= ImageRecordEndLink
) {
1047 IMAGE_PROPERTIES_RECORD
,
1049 IMAGE_PROPERTIES_RECORD_SIGNATURE
1051 while (NextImageRecordLink
!= ImageRecordEndLink
) {
1052 NextImageRecord
= CR (
1053 NextImageRecordLink
,
1054 IMAGE_PROPERTIES_RECORD
,
1056 IMAGE_PROPERTIES_RECORD_SIGNATURE
1058 if (ImageRecord
->ImageBase
> NextImageRecord
->ImageBase
) {
1059 SwapImageRecord (ImageRecord
, NextImageRecord
);
1061 NextImageRecordLink
= NextImageRecordLink
->ForwardLink
;
1064 ImageRecordLink
= ImageRecordLink
->ForwardLink
;
1065 NextImageRecordLink
= ImageRecordLink
->ForwardLink
;
1077 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1078 LIST_ENTRY
*ImageRecordLink
;
1079 LIST_ENTRY
*ImageRecordList
;
1082 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1084 for (ImageRecordLink
= ImageRecordList
->ForwardLink
, Index
= 0;
1085 ImageRecordLink
!= ImageRecordList
;
1086 ImageRecordLink
= ImageRecordLink
->ForwardLink
, Index
++) {
1089 IMAGE_PROPERTIES_RECORD
,
1091 IMAGE_PROPERTIES_RECORD_SIGNATURE
1093 DEBUG ((EFI_D_VERBOSE
, " Image[%d]: 0x%016lx - 0x%016lx\n", Index
, ImageRecord
->ImageBase
, ImageRecord
->ImageSize
));
1098 Insert image record.
1100 @param RuntimeImage Runtime image information
1104 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1108 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1109 UINT32 PeCoffHeaderOffset
;
1110 UINT32 SectionAlignment
;
1111 EFI_IMAGE_SECTION_HEADER
*Section
;
1112 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1115 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1117 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1120 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%x\n", RuntimeImage
));
1121 DEBUG ((EFI_D_VERBOSE
, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1123 ImageRecord
= AllocatePool (sizeof(*ImageRecord
));
1124 if (ImageRecord
== NULL
) {
1127 ImageRecord
->Signature
= IMAGE_PROPERTIES_RECORD_SIGNATURE
;
1129 DEBUG ((EFI_D_VERBOSE
, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1132 // Step 1: record whole region
1134 ImageRecord
->ImageBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
;
1135 ImageRecord
->ImageSize
= RuntimeImage
->ImageSize
;
1137 ImageAddress
= RuntimeImage
->ImageBase
;
1139 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1140 if (PdbPointer
!= NULL
) {
1141 DEBUG ((EFI_D_VERBOSE
, " Image - %a\n", PdbPointer
));
1145 // Check PE/COFF image
1147 DosHdr
= (EFI_IMAGE_DOS_HEADER
*) (UINTN
) ImageAddress
;
1148 PeCoffHeaderOffset
= 0;
1149 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
1150 PeCoffHeaderOffset
= DosHdr
->e_lfanew
;
1153 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINT8
*) (UINTN
) ImageAddress
+ PeCoffHeaderOffset
);
1154 if (Hdr
.Pe32
->Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
1155 DEBUG ((EFI_D_VERBOSE
, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr
.Pe32
->Signature
));
1156 // It might be image in SMM.
1161 // Get SectionAlignment
1163 if (Hdr
.Pe32
->FileHeader
.Machine
== IMAGE_FILE_MACHINE_IA64
&& Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1165 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1166 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1167 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1168 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1170 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1173 // Get the magic value from the PE/COFF Optional Header
1175 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1177 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1178 SectionAlignment
= Hdr
.Pe32
->OptionalHeader
.SectionAlignment
;
1180 SectionAlignment
= Hdr
.Pe32Plus
->OptionalHeader
.SectionAlignment
;
1183 SetPropertiesTableSectionAlignment (SectionAlignment
);
1184 if ((SectionAlignment
& (SIZE_4KB
- 1)) != 0) {
1185 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not 4K !!!!!!!!\n", SectionAlignment
));
1186 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1187 if (PdbPointer
!= NULL
) {
1188 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1193 Section
= (EFI_IMAGE_SECTION_HEADER
*) (
1194 (UINT8
*) (UINTN
) ImageAddress
+
1195 PeCoffHeaderOffset
+
1197 sizeof(EFI_IMAGE_FILE_HEADER
) +
1198 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1200 ImageRecord
->CodeSegmentCount
= 0;
1201 InitializeListHead (&ImageRecord
->CodeSegmentList
);
1202 for (Index
= 0; Index
< Hdr
.Pe32
->FileHeader
.NumberOfSections
; Index
++) {
1203 Name
= Section
[Index
].Name
;
1206 " Section - '%c%c%c%c%c%c%c%c'\n",
1217 if ((Section
[Index
].Characteristics
& EFI_IMAGE_SCN_CNT_CODE
) != 0) {
1218 DEBUG ((EFI_D_VERBOSE
, " VirtualSize - 0x%08x\n", Section
[Index
].Misc
.VirtualSize
));
1219 DEBUG ((EFI_D_VERBOSE
, " VirtualAddress - 0x%08x\n", Section
[Index
].VirtualAddress
));
1220 DEBUG ((EFI_D_VERBOSE
, " SizeOfRawData - 0x%08x\n", Section
[Index
].SizeOfRawData
));
1221 DEBUG ((EFI_D_VERBOSE
, " PointerToRawData - 0x%08x\n", Section
[Index
].PointerToRawData
));
1222 DEBUG ((EFI_D_VERBOSE
, " PointerToRelocations - 0x%08x\n", Section
[Index
].PointerToRelocations
));
1223 DEBUG ((EFI_D_VERBOSE
, " PointerToLinenumbers - 0x%08x\n", Section
[Index
].PointerToLinenumbers
));
1224 DEBUG ((EFI_D_VERBOSE
, " NumberOfRelocations - 0x%08x\n", Section
[Index
].NumberOfRelocations
));
1225 DEBUG ((EFI_D_VERBOSE
, " NumberOfLinenumbers - 0x%08x\n", Section
[Index
].NumberOfLinenumbers
));
1226 DEBUG ((EFI_D_VERBOSE
, " Characteristics - 0x%08x\n", Section
[Index
].Characteristics
));
1229 // Step 2: record code section
1231 ImageRecordCodeSection
= AllocatePool (sizeof(*ImageRecordCodeSection
));
1232 if (ImageRecordCodeSection
== NULL
) {
1235 ImageRecordCodeSection
->Signature
= IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
;
1237 ImageRecordCodeSection
->CodeSegmentBase
= (UINTN
)ImageAddress
+ Section
[Index
].VirtualAddress
;
1238 ImageRecordCodeSection
->CodeSegmentSize
= Section
[Index
].SizeOfRawData
;
1240 DEBUG ((EFI_D_VERBOSE
, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection
->CodeSegmentBase
, ImageRecordCodeSection
->CodeSegmentSize
));
1242 InsertTailList (&ImageRecord
->CodeSegmentList
, &ImageRecordCodeSection
->Link
);
1243 ImageRecord
->CodeSegmentCount
++;
1247 if (ImageRecord
->CodeSegmentCount
== 0) {
1248 SetPropertiesTableSectionAlignment (1);
1249 DEBUG ((EFI_D_ERROR
, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1250 PdbPointer
= PeCoffLoaderGetPdbPointer ((VOID
*) (UINTN
) ImageAddress
);
1251 if (PdbPointer
!= NULL
) {
1252 DEBUG ((EFI_D_ERROR
, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer
));
1260 SortImageRecordCodeSection (ImageRecord
);
1262 // Check overlap all section in ImageBase/Size
1264 if (!IsImageRecordCodeSectionValid (ImageRecord
)) {
1265 DEBUG ((EFI_D_ERROR
, "IsImageRecordCodeSectionValid - FAIL\n"));
1269 InsertTailList (&mImagePropertiesPrivateData
.ImageRecordList
, &ImageRecord
->Link
);
1270 mImagePropertiesPrivateData
.ImageRecordCount
++;
1274 if (mImagePropertiesPrivateData
.CodeSegmentCountMax
< ImageRecord
->CodeSegmentCount
) {
1275 mImagePropertiesPrivateData
.CodeSegmentCountMax
= ImageRecord
->CodeSegmentCount
;
1283 Find image record accroding to image base and size.
1285 @param ImageBase Base of PE image
1286 @param ImageSize Size of PE image
1288 @return image record
1290 IMAGE_PROPERTIES_RECORD
*
1292 IN EFI_PHYSICAL_ADDRESS ImageBase
,
1296 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1297 LIST_ENTRY
*ImageRecordLink
;
1298 LIST_ENTRY
*ImageRecordList
;
1300 ImageRecordList
= &mImagePropertiesPrivateData
.ImageRecordList
;
1302 for (ImageRecordLink
= ImageRecordList
->ForwardLink
;
1303 ImageRecordLink
!= ImageRecordList
;
1304 ImageRecordLink
= ImageRecordLink
->ForwardLink
) {
1307 IMAGE_PROPERTIES_RECORD
,
1309 IMAGE_PROPERTIES_RECORD_SIGNATURE
1312 if ((ImageBase
== ImageRecord
->ImageBase
) &&
1313 (ImageSize
== ImageRecord
->ImageSize
)) {
1322 Remove Image record.
1324 @param RuntimeImage Runtime image information
1328 IN EFI_RUNTIME_IMAGE_ENTRY
*RuntimeImage
1331 IMAGE_PROPERTIES_RECORD
*ImageRecord
;
1332 LIST_ENTRY
*CodeSegmentListHead
;
1333 IMAGE_PROPERTIES_RECORD_CODE_SECTION
*ImageRecordCodeSection
;
1335 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%x\n", RuntimeImage
));
1336 DEBUG ((EFI_D_VERBOSE
, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
));
1338 ImageRecord
= FindImageRecord ((EFI_PHYSICAL_ADDRESS
)(UINTN
)RuntimeImage
->ImageBase
, RuntimeImage
->ImageSize
);
1339 if (ImageRecord
== NULL
) {
1340 DEBUG ((EFI_D_ERROR
, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1344 CodeSegmentListHead
= &ImageRecord
->CodeSegmentList
;
1345 while (!IsListEmpty (CodeSegmentListHead
)) {
1346 ImageRecordCodeSection
= CR (
1347 CodeSegmentListHead
->ForwardLink
,
1348 IMAGE_PROPERTIES_RECORD_CODE_SECTION
,
1350 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1352 RemoveEntryList (&ImageRecordCodeSection
->Link
);
1353 FreePool (ImageRecordCodeSection
);
1356 RemoveEntryList (&ImageRecord
->Link
);
1357 FreePool (ImageRecord
);
1358 mImagePropertiesPrivateData
.ImageRecordCount
--;
1363 Install PropertiesTable.
1365 @param[in] Event The Event this notify function registered to.
1366 @param[in] Context Pointer to the context data registered to the Event.
1370 InstallPropertiesTable (
1375 if (PcdGetBool (PropertiesTableEnable
)) {
1378 Status
= gBS
->InstallConfigurationTable (&gEfiPropertiesTableGuid
, &mPropertiesTable
);
1379 ASSERT_EFI_ERROR (Status
);
1381 DEBUG ((EFI_D_INFO
, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable
.MemoryProtectionAttribute
));
1382 if ((mPropertiesTable
.MemoryProtectionAttribute
& EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA
) == 0) {
1386 gBS
->GetMemoryMap
= CoreGetMemoryMapPropertiesTable
;
1388 gBS
->CalculateCrc32 ((UINT8
*)gBS
, gBS
->Hdr
.HeaderSize
, &gBS
->Hdr
.CRC32
);
1390 DEBUG ((EFI_D_VERBOSE
, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData
.ImageRecordCount
));
1391 DEBUG ((EFI_D_VERBOSE
, "Dump ImageRecord:\n"));
1397 Initialize PropertiesTable support.
1401 CoreInitializePropertiesTable (
1406 EFI_EVENT EndOfDxeEvent
;
1408 Status
= gBS
->CreateEventEx (
1411 InstallPropertiesTable
,
1413 &gEfiEndOfDxeEventGroupGuid
,
1416 ASSERT_EFI_ERROR (Status
);