]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c
MdeModulePkg: disable properties table generation but retain the code
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Misc / PropertiesTable.c
1 /** @file
2 UEFI PropertiesTable support
3
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9 #include <PiDxe.h>
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>
18
19 #include <Guid/EventGroup.h>
20 #include <Protocol/DxeSmmReadyToLock.h>
21
22 #include <Library/PeCoffLib.h>
23 #include <Library/PeCoffGetEntryPointLib.h>
24 #include <Protocol/Runtime.h>
25
26 #include "DxeMain.h"
27 #include "HeapGuard.h"
28
29 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
30 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
31
32 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
33
34 typedef struct {
35 UINT32 Signature;
36 UINTN ImageRecordCount;
37 UINTN CodeSegmentCountMax;
38 LIST_ENTRY ImageRecordList;
39 } IMAGE_PROPERTIES_PRIVATE_DATA;
40
41 IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData = {
42 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE,
43 0,
44 0,
45 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList)
46 };
47
48 EFI_LOCK mPropertiesTableLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
49
50 BOOLEAN mPropertiesTableEndOfDxe = FALSE;
51
52 extern BOOLEAN mMemoryAttributesTableEnable;
53
54 //
55 // Below functions are for MemoryMap
56 //
57
58 /**
59 Converts a number of EFI_PAGEs to a size in bytes.
60
61 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
62
63 @param Pages The number of EFI_PAGES.
64
65 @return The number of bytes associated with the number of EFI_PAGEs specified
66 by Pages.
67 **/
68 STATIC
69 UINT64
70 EfiPagesToSize (
71 IN UINT64 Pages
72 )
73 {
74 return LShiftU64 (Pages, EFI_PAGE_SHIFT);
75 }
76
77 /**
78 Converts a size, in bytes, to a number of EFI_PAGESs.
79
80 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
81
82 @param Size A size in bytes.
83
84 @return The number of EFI_PAGESs associated with the number of bytes specified
85 by Size.
86
87 **/
88 STATIC
89 UINT64
90 EfiSizeToPages (
91 IN UINT64 Size
92 )
93 {
94 return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
95 }
96
97 /**
98 Acquire memory lock on mPropertiesTableLock.
99 **/
100 STATIC
101 VOID
102 CoreAcquirePropertiesTableLock (
103 VOID
104 )
105 {
106 CoreAcquireLock (&mPropertiesTableLock);
107 }
108
109 /**
110 Release memory lock on mPropertiesTableLock.
111 **/
112 STATIC
113 VOID
114 CoreReleasePropertiesTableLock (
115 VOID
116 )
117 {
118 CoreReleaseLock (&mPropertiesTableLock);
119 }
120
121 /**
122 Sort memory map entries based upon PhysicalStart, from low to high.
123
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.
128 **/
129 STATIC
130 VOID
131 SortMemoryMap (
132 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
133 IN UINTN MemoryMapSize,
134 IN UINTN DescriptorSize
135 )
136 {
137 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
138 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
139 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
140 EFI_MEMORY_DESCRIPTOR TempMemoryMap;
141
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));
151 }
152
153 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
154 }
155
156 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
157 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
158 }
159
160 return ;
161 }
162
163 /**
164 Merge continous memory map entries whose have same attributes.
165
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.
173 **/
174 VOID
175 MergeMemoryMap (
176 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
177 IN OUT UINTN *MemoryMapSize,
178 IN UINTN DescriptorSize
179 )
180 {
181 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
182 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
183 UINT64 MemoryBlockLength;
184 EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;
185 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
186
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);
193
194 do {
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);
203 continue;
204 } else {
205 MemoryMapEntry = PREVIOUS_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
206 break;
207 }
208 } while (TRUE);
209
210 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
211 NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
212 }
213
214 *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
215
216 return ;
217 }
218
219 /**
220 Enforce memory map attributes.
221 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
222
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.
227 **/
228 STATIC
229 VOID
230 EnforceMemoryMapAttribute (
231 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
232 IN UINTN MemoryMapSize,
233 IN UINTN DescriptorSize
234 )
235 {
236 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
237 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
238
239 MemoryMapEntry = MemoryMap;
240 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);
241 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
242 switch (MemoryMapEntry->Type) {
243 case EfiRuntimeServicesCode:
244 // do nothing
245 break;
246 case EfiRuntimeServicesData:
247 case EfiMemoryMappedIO:
248 case EfiMemoryMappedIOPortSpace:
249 MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
250 break;
251 case EfiReservedMemoryType:
252 case EfiACPIMemoryNVS:
253 break;
254 }
255
256 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
257 }
258
259 return ;
260 }
261
262 /**
263 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
264
265 @param Buffer Start Address
266 @param Length Address length
267
268 @return first image record covered by [buffer, length]
269 **/
270 STATIC
271 IMAGE_PROPERTIES_RECORD *
272 GetImageRecordByAddress (
273 IN EFI_PHYSICAL_ADDRESS Buffer,
274 IN UINT64 Length
275 )
276 {
277 IMAGE_PROPERTIES_RECORD *ImageRecord;
278 LIST_ENTRY *ImageRecordLink;
279 LIST_ENTRY *ImageRecordList;
280
281 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
282
283 for (ImageRecordLink = ImageRecordList->ForwardLink;
284 ImageRecordLink != ImageRecordList;
285 ImageRecordLink = ImageRecordLink->ForwardLink) {
286 ImageRecord = CR (
287 ImageRecordLink,
288 IMAGE_PROPERTIES_RECORD,
289 Link,
290 IMAGE_PROPERTIES_RECORD_SIGNATURE
291 );
292
293 if ((Buffer <= ImageRecord->ImageBase) &&
294 (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) {
295 return ImageRecord;
296 }
297 }
298
299 return NULL;
300 }
301
302 /**
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
305
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
311 below.
312 @param OldRecord A pointer to one old memory map entry.
313 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
314 **/
315 STATIC
316 UINTN
317 SetNewRecord (
318 IN IMAGE_PROPERTIES_RECORD *ImageRecord,
319 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,
320 IN EFI_MEMORY_DESCRIPTOR *OldRecord,
321 IN UINTN DescriptorSize
322 )
323 {
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;
330 UINT64 PhysicalEnd;
331 UINT64 ImageEnd;
332
333 CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));
334 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);
335 NewRecordCount = 0;
336
337 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
338
339 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
340 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
341 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
342 ImageRecordCodeSection = CR (
343 ImageRecordCodeSectionLink,
344 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
345 Link,
346 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
347 );
348 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
349
350 if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
351 //
352 // DATA
353 //
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);
361 NewRecordCount ++;
362 }
363
364 //
365 // CODE
366 //
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);
374 NewRecordCount ++;
375 }
376
377 TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize));
378 TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);
379 if (TempRecord.NumberOfPages == 0) {
380 break;
381 }
382 }
383 }
384
385 ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
386
387 //
388 // Final DATA
389 //
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;
396 NewRecordCount ++;
397 }
398
399 return NewRecordCount;
400 }
401
402 /**
403 Return the max number of new splitted entries, according to one old entry,
404 based upon PE code section and data section.
405
406 @param OldRecord A pointer to one old memory map entry.
407
408 @retval 0 no entry need to be splitted.
409 @return the max number of new splitted entries
410 **/
411 STATIC
412 UINTN
413 GetMaxSplitRecordCount (
414 IN EFI_MEMORY_DESCRIPTOR *OldRecord
415 )
416 {
417 IMAGE_PROPERTIES_RECORD *ImageRecord;
418 UINTN SplitRecordCount;
419 UINT64 PhysicalStart;
420 UINT64 PhysicalEnd;
421
422 SplitRecordCount = 0;
423 PhysicalStart = OldRecord->PhysicalStart;
424 PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize(OldRecord->NumberOfPages);
425
426 do {
427 ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
428 if (ImageRecord == NULL) {
429 break;
430 }
431 SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);
432 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
433 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
434
435 if (SplitRecordCount != 0) {
436 SplitRecordCount--;
437 }
438
439 return SplitRecordCount;
440 }
441
442 /**
443 Split the memory map to new entries, according to one old entry,
444 based upon PE code section and data section.
445
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
450 below.
451 @param MaxSplitRecordCount The max number of splitted entries
452 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
453
454 @retval 0 no entry is splitted.
455 @return the real number of splitted record.
456 **/
457 STATIC
458 UINTN
459 SplitRecord (
460 IN EFI_MEMORY_DESCRIPTOR *OldRecord,
461 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,
462 IN UINTN MaxSplitRecordCount,
463 IN UINTN DescriptorSize
464 )
465 {
466 EFI_MEMORY_DESCRIPTOR TempRecord;
467 IMAGE_PROPERTIES_RECORD *ImageRecord;
468 IMAGE_PROPERTIES_RECORD *NewImageRecord;
469 UINT64 PhysicalStart;
470 UINT64 PhysicalEnd;
471 UINTN NewRecordCount;
472 UINTN TotalNewRecordCount;
473 BOOLEAN IsLastRecordData;
474
475 if (MaxSplitRecordCount == 0) {
476 CopyMem (NewRecord, OldRecord, DescriptorSize);
477 return 0;
478 }
479
480 TotalNewRecordCount = 0;
481
482 //
483 // Override previous record
484 //
485 CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));
486 PhysicalStart = TempRecord.PhysicalStart;
487 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);
488
489 ImageRecord = NULL;
490 do {
491 NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
492 if (NewImageRecord == NULL) {
493 //
494 // No more image covered by this range, stop
495 //
496 if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
497 //
498 // If this is still address in this record, need record.
499 //
500 NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
501 IsLastRecordData = FALSE;
502 if ((NewRecord->Attribute & EFI_MEMORY_XP) != 0) {
503 IsLastRecordData = TRUE;
504 }
505 if (IsLastRecordData) {
506 //
507 // Last record is DATA, just merge it.
508 //
509 NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart);
510 } else {
511 //
512 // Last record is CODE, create a new DATA entry.
513 //
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 ++;
521 }
522 }
523 break;
524 }
525 ImageRecord = NewImageRecord;
526
527 //
528 // Set new record
529 //
530 NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
531 TotalNewRecordCount += NewRecordCount;
532 NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);
533
534 //
535 // Update PhysicalStart, in order to exclude the image buffer already splitted.
536 //
537 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
538 TempRecord.PhysicalStart = PhysicalStart;
539 TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
540 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
541
542 //
543 // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
544 // code reaches here.
545 //
546 ASSERT (TotalNewRecordCount != 0);
547 return TotalNewRecordCount - 1;
548 }
549
550 /**
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.
554
555 NOTE: It assumes PE code/data section are page aligned.
556 NOTE: It assumes enough entry is prepared for new memory map.
557
558 Split table:
559 +---------------+
560 | Record X |
561 +---------------+
562 | Record RtCode |
563 +---------------+
564 | Record Y |
565 +---------------+
566 ==>
567 +---------------+
568 | Record X |
569 +---------------+ ----
570 | Record RtData | |
571 +---------------+ |
572 | Record RtCode | |-> PE/COFF1
573 +---------------+ |
574 | Record RtData | |
575 +---------------+ ----
576 | Record RtData | |
577 +---------------+ |
578 | Record RtCode | |-> PE/COFF2
579 +---------------+ |
580 | Record RtData | |
581 +---------------+ ----
582 | Record Y |
583 +---------------+
584
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
591 after split.
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.
595 **/
596 STATIC
597 VOID
598 SplitTable (
599 IN OUT UINTN *MemoryMapSize,
600 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
601 IN UINTN DescriptorSize
602 )
603 {
604 INTN IndexOld;
605 INTN IndexNew;
606 UINTN MaxSplitRecordCount;
607 UINTN RealSplitRecordCount;
608 UINTN TotalSplitRecordCount;
609 UINTN AdditionalRecordCount;
610
611 AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
612
613 TotalSplitRecordCount = 0;
614 //
615 // Let old record point to end of valid MemoryMap buffer.
616 //
617 IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;
618 //
619 // Let new record point to end of full MemoryMap buffer.
620 //
621 IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount;
622 for (; IndexOld >= 0; IndexOld--) {
623 MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));
624 //
625 // Split this MemoryMap record
626 //
627 IndexNew -= MaxSplitRecordCount;
628 RealSplitRecordCount = SplitRecord (
629 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
630 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
631 MaxSplitRecordCount,
632 DescriptorSize
633 );
634 //
635 // Adjust IndexNew according to real split.
636 //
637 CopyMem (
638 ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
639 ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
640 RealSplitRecordCount * DescriptorSize
641 );
642 IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
643 TotalSplitRecordCount += RealSplitRecordCount;
644 IndexNew --;
645 }
646 //
647 // Move all records to the beginning.
648 //
649 CopyMem (
650 MemoryMap,
651 (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize,
652 (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
653 );
654
655 *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
656
657 //
658 // Sort from low to high (Just in case)
659 //
660 SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
661
662 //
663 // Set RuntimeData to XP
664 //
665 EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize);
666
667 //
668 // Merge same type to save entry size
669 //
670 MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);
671
672 return ;
673 }
674
675 /**
676 This function for GetMemoryMap() with properties table capability.
677
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.
680
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.
698
699 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
700 buffer.
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.
705
706 **/
707 EFI_STATUS
708 EFIAPI
709 CoreGetMemoryMapWithSeparatedImageSection (
710 IN OUT UINTN *MemoryMapSize,
711 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
712 OUT UINTN *MapKey,
713 OUT UINTN *DescriptorSize,
714 OUT UINT32 *DescriptorVersion
715 )
716 {
717 EFI_STATUS Status;
718 UINTN OldMemoryMapSize;
719 UINTN AdditionalRecordCount;
720
721 //
722 // If PE code/data is not aligned, just return.
723 //
724 if (!mMemoryAttributesTableEnable) {
725 return CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
726 }
727
728 if (MemoryMapSize == NULL) {
729 return EFI_INVALID_PARAMETER;
730 }
731
732 CoreAcquirePropertiesTableLock ();
733
734 AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
735
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;
744 //
745 // Need update status to buffer too small
746 //
747 Status = EFI_BUFFER_TOO_SMALL;
748 } else {
749 //
750 // Split PE code/data
751 //
752 SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize);
753 }
754 }
755
756 CoreReleasePropertiesTableLock ();
757 return Status;
758 }
759
760 //
761 // Below functions are for ImageRecord
762 //
763
764 /**
765 Set PropertiesTable according to PE/COFF image section alignment.
766
767 @param SectionAlignment PE/COFF section alignment
768 **/
769 STATIC
770 VOID
771 SetPropertiesTableSectionAlignment (
772 IN UINT32 SectionAlignment
773 )
774 {
775 if (((SectionAlignment & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) &&
776 mMemoryAttributesTableEnable) {
777 DEBUG ((EFI_D_VERBOSE, "SetPropertiesTableSectionAlignment - Clear\n"));
778 mMemoryAttributesTableEnable = FALSE;
779 }
780 }
781
782 /**
783 Swap two code sections in image record.
784
785 @param FirstImageRecordCodeSection first code section in image record
786 @param SecondImageRecordCodeSection second code section in image record
787 **/
788 STATIC
789 VOID
790 SwapImageRecordCodeSection (
791 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection,
792 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection
793 )
794 {
795 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection;
796
797 TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
798 TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
799
800 FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
801 FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
802
803 SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
804 SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
805 }
806
807 /**
808 Sort code section in image record, based upon CodeSegmentBase from low to high.
809
810 @param ImageRecord image record to be sorted
811 **/
812 VOID
813 SortImageRecordCodeSection (
814 IN IMAGE_PROPERTIES_RECORD *ImageRecord
815 )
816 {
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;
823
824 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
825
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,
833 Link,
834 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
835 );
836 while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
837 NextImageRecordCodeSection = CR (
838 NextImageRecordCodeSectionLink,
839 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
840 Link,
841 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
842 );
843 if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
844 SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
845 }
846 NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
847 }
848
849 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
850 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
851 }
852 }
853
854 /**
855 Check if code section in image record is valid.
856
857 @param ImageRecord image record to be checked
858
859 @retval TRUE image record is valid
860 @retval FALSE image record is invalid
861 **/
862 BOOLEAN
863 IsImageRecordCodeSectionValid (
864 IN IMAGE_PROPERTIES_RECORD *ImageRecord
865 )
866 {
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;
872
873 DEBUG ((EFI_D_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
874
875 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
876
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,
884 Link,
885 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
886 );
887 if (ImageRecordCodeSection->CodeSegmentSize == 0) {
888 return FALSE;
889 }
890 if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
891 return FALSE;
892 }
893 if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
894 return FALSE;
895 }
896 if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
897 return FALSE;
898 }
899 if (LastImageRecordCodeSection != NULL) {
900 if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
901 return FALSE;
902 }
903 }
904
905 LastImageRecordCodeSection = ImageRecordCodeSection;
906 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
907 }
908
909 return TRUE;
910 }
911
912 /**
913 Swap two image records.
914
915 @param FirstImageRecord first image record.
916 @param SecondImageRecord second image record.
917 **/
918 STATIC
919 VOID
920 SwapImageRecord (
921 IN IMAGE_PROPERTIES_RECORD *FirstImageRecord,
922 IN IMAGE_PROPERTIES_RECORD *SecondImageRecord
923 )
924 {
925 IMAGE_PROPERTIES_RECORD TempImageRecord;
926
927 TempImageRecord.ImageBase = FirstImageRecord->ImageBase;
928 TempImageRecord.ImageSize = FirstImageRecord->ImageSize;
929 TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
930
931 FirstImageRecord->ImageBase = SecondImageRecord->ImageBase;
932 FirstImageRecord->ImageSize = SecondImageRecord->ImageSize;
933 FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
934
935 SecondImageRecord->ImageBase = TempImageRecord.ImageBase;
936 SecondImageRecord->ImageSize = TempImageRecord.ImageSize;
937 SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
938
939 SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
940 }
941
942 /**
943 Sort image record based upon the ImageBase from low to high.
944 **/
945 STATIC
946 VOID
947 SortImageRecord (
948 VOID
949 )
950 {
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;
957
958 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
959
960 ImageRecordLink = ImageRecordList->ForwardLink;
961 NextImageRecordLink = ImageRecordLink->ForwardLink;
962 ImageRecordEndLink = ImageRecordList;
963 while (ImageRecordLink != ImageRecordEndLink) {
964 ImageRecord = CR (
965 ImageRecordLink,
966 IMAGE_PROPERTIES_RECORD,
967 Link,
968 IMAGE_PROPERTIES_RECORD_SIGNATURE
969 );
970 while (NextImageRecordLink != ImageRecordEndLink) {
971 NextImageRecord = CR (
972 NextImageRecordLink,
973 IMAGE_PROPERTIES_RECORD,
974 Link,
975 IMAGE_PROPERTIES_RECORD_SIGNATURE
976 );
977 if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
978 SwapImageRecord (ImageRecord, NextImageRecord);
979 }
980 NextImageRecordLink = NextImageRecordLink->ForwardLink;
981 }
982
983 ImageRecordLink = ImageRecordLink->ForwardLink;
984 NextImageRecordLink = ImageRecordLink->ForwardLink;
985 }
986 }
987
988 /**
989 Insert image record.
990
991 @param RuntimeImage Runtime image information
992 **/
993 VOID
994 InsertImageRecord (
995 IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
996 )
997 {
998 VOID *ImageAddress;
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;
1004 UINT8 *Name;
1005 UINTN Index;
1006 IMAGE_PROPERTIES_RECORD *ImageRecord;
1007 CHAR8 *PdbPointer;
1008 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
1009
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));
1012
1013 if (mPropertiesTableEndOfDxe) {
1014 DEBUG ((DEBUG_INFO, "Do not insert runtime image record after EndOfDxe\n"));
1015 return ;
1016 }
1017
1018 ImageRecord = AllocatePool (sizeof(*ImageRecord));
1019 if (ImageRecord == NULL) {
1020 return ;
1021 }
1022 ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
1023
1024 DEBUG ((EFI_D_VERBOSE, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
1025
1026 //
1027 // Step 1: record whole region
1028 //
1029 ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase;
1030 ImageRecord->ImageSize = RuntimeImage->ImageSize;
1031
1032 ImageAddress = RuntimeImage->ImageBase;
1033
1034 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);
1035 if (PdbPointer != NULL) {
1036 DEBUG ((EFI_D_VERBOSE, " Image - %a\n", PdbPointer));
1037 }
1038
1039 //
1040 // Check PE/COFF image
1041 //
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;
1046 }
1047
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.
1052 goto Finish;
1053 }
1054
1055 //
1056 // Get SectionAlignment
1057 //
1058 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1059 SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
1060 } else {
1061 SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
1062 }
1063
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));
1071 }
1072 goto Finish;
1073 }
1074
1075 Section = (EFI_IMAGE_SECTION_HEADER *) (
1076 (UINT8 *) (UINTN) ImageAddress +
1077 PeCoffHeaderOffset +
1078 sizeof(UINT32) +
1079 sizeof(EFI_IMAGE_FILE_HEADER) +
1080 Hdr.Pe32->FileHeader.SizeOfOptionalHeader
1081 );
1082 ImageRecord->CodeSegmentCount = 0;
1083 InitializeListHead (&ImageRecord->CodeSegmentList);
1084 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
1085 Name = Section[Index].Name;
1086 DEBUG ((
1087 EFI_D_VERBOSE,
1088 " Section - '%c%c%c%c%c%c%c%c'\n",
1089 Name[0],
1090 Name[1],
1091 Name[2],
1092 Name[3],
1093 Name[4],
1094 Name[5],
1095 Name[6],
1096 Name[7]
1097 ));
1098
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));
1109
1110 //
1111 // Step 2: record code section
1112 //
1113 ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection));
1114 if (ImageRecordCodeSection == NULL) {
1115 return ;
1116 }
1117 ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
1118
1119 ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;
1120 ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;
1121
1122 DEBUG ((EFI_D_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));
1123
1124 InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
1125 ImageRecord->CodeSegmentCount++;
1126 }
1127 }
1128
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));
1135 }
1136 goto Finish;
1137 }
1138
1139 //
1140 // Final
1141 //
1142 SortImageRecordCodeSection (ImageRecord);
1143 //
1144 // Check overlap all section in ImageBase/Size
1145 //
1146 if (!IsImageRecordCodeSectionValid (ImageRecord)) {
1147 DEBUG ((EFI_D_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
1148 goto Finish;
1149 }
1150
1151 InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
1152 mImagePropertiesPrivateData.ImageRecordCount++;
1153
1154 if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
1155 mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
1156 }
1157
1158 SortImageRecord ();
1159
1160 Finish:
1161 return ;
1162 }
1163
1164 /**
1165 Find image record according to image base and size.
1166
1167 @param ImageBase Base of PE image
1168 @param ImageSize Size of PE image
1169
1170 @return image record
1171 **/
1172 STATIC
1173 IMAGE_PROPERTIES_RECORD *
1174 FindImageRecord (
1175 IN EFI_PHYSICAL_ADDRESS ImageBase,
1176 IN UINT64 ImageSize
1177 )
1178 {
1179 IMAGE_PROPERTIES_RECORD *ImageRecord;
1180 LIST_ENTRY *ImageRecordLink;
1181 LIST_ENTRY *ImageRecordList;
1182
1183 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
1184
1185 for (ImageRecordLink = ImageRecordList->ForwardLink;
1186 ImageRecordLink != ImageRecordList;
1187 ImageRecordLink = ImageRecordLink->ForwardLink) {
1188 ImageRecord = CR (
1189 ImageRecordLink,
1190 IMAGE_PROPERTIES_RECORD,
1191 Link,
1192 IMAGE_PROPERTIES_RECORD_SIGNATURE
1193 );
1194
1195 if ((ImageBase == ImageRecord->ImageBase) &&
1196 (ImageSize == ImageRecord->ImageSize)) {
1197 return ImageRecord;
1198 }
1199 }
1200
1201 return NULL;
1202 }
1203
1204 /**
1205 Remove Image record.
1206
1207 @param RuntimeImage Runtime image information
1208 **/
1209 VOID
1210 RemoveImageRecord (
1211 IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
1212 )
1213 {
1214 IMAGE_PROPERTIES_RECORD *ImageRecord;
1215 LIST_ENTRY *CodeSegmentListHead;
1216 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
1217
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));
1220
1221 if (mPropertiesTableEndOfDxe) {
1222 DEBUG ((DEBUG_INFO, "Do not remove runtime image record after EndOfDxe\n"));
1223 return ;
1224 }
1225
1226 ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize);
1227 if (ImageRecord == NULL) {
1228 DEBUG ((EFI_D_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1229 return ;
1230 }
1231
1232 CodeSegmentListHead = &ImageRecord->CodeSegmentList;
1233 while (!IsListEmpty (CodeSegmentListHead)) {
1234 ImageRecordCodeSection = CR (
1235 CodeSegmentListHead->ForwardLink,
1236 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
1237 Link,
1238 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1239 );
1240 RemoveEntryList (&ImageRecordCodeSection->Link);
1241 FreePool (ImageRecordCodeSection);
1242 }
1243
1244 RemoveEntryList (&ImageRecord->Link);
1245 FreePool (ImageRecord);
1246 mImagePropertiesPrivateData.ImageRecordCount--;
1247 }
1248
1249
1250 /**
1251 Install PropertiesTable.
1252
1253 @param[in] Event The Event this notify function registered to.
1254 @param[in] Context Pointer to the context data registered to the Event.
1255 **/
1256 VOID
1257 EFIAPI
1258 InstallPropertiesTable (
1259 EFI_EVENT Event,
1260 VOID *Context
1261 )
1262 {
1263 mPropertiesTableEndOfDxe = TRUE;
1264 }
1265
1266 /**
1267 Initialize PropertiesTable support.
1268 **/
1269 VOID
1270 EFIAPI
1271 CoreInitializePropertiesTable (
1272 VOID
1273 )
1274 {
1275 EFI_STATUS Status;
1276 EFI_EVENT EndOfDxeEvent;
1277
1278 Status = gBS->CreateEventEx (
1279 EVT_NOTIFY_SIGNAL,
1280 TPL_NOTIFY,
1281 InstallPropertiesTable,
1282 NULL,
1283 &gEfiEndOfDxeEventGroupGuid,
1284 &EndOfDxeEvent
1285 );
1286 ASSERT_EFI_ERROR (Status);
1287 return ;
1288 }