]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c
MdeModulePkg: rename PropertiesTableEnable to PcdPropertiesTableEnable
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Misc / PropertiesTable.c
1 /** @file
2 UEFI PropertiesTable support
3
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
9
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.
12
13 **/
14
15 #include <PiDxe.h>
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>
24
25 #include <Guid/EventGroup.h>
26 #include <Protocol/DxeSmmReadyToLock.h>
27
28 #include <Library/PeCoffLib.h>
29 #include <Library/PeCoffGetEntryPointLib.h>
30 #include <Protocol/Runtime.h>
31
32 #include <Guid/PropertiesTable.h>
33
34 #include "DxeMain.h"
35
36 #define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
37 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
38
39 #define IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE SIGNATURE_32 ('I','P','R','C')
40
41 typedef struct {
42 UINT32 Signature;
43 LIST_ENTRY Link;
44 EFI_PHYSICAL_ADDRESS CodeSegmentBase;
45 UINT64 CodeSegmentSize;
46 } IMAGE_PROPERTIES_RECORD_CODE_SECTION;
47
48 #define IMAGE_PROPERTIES_RECORD_SIGNATURE SIGNATURE_32 ('I','P','R','D')
49
50 typedef struct {
51 UINT32 Signature;
52 LIST_ENTRY Link;
53 EFI_PHYSICAL_ADDRESS ImageBase;
54 UINT64 ImageSize;
55 UINTN CodeSegmentCount;
56 LIST_ENTRY CodeSegmentList;
57 } IMAGE_PROPERTIES_RECORD;
58
59 #define IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('I','P','P','D')
60
61 typedef struct {
62 UINT32 Signature;
63 UINTN ImageRecordCount;
64 UINTN CodeSegmentCountMax;
65 LIST_ENTRY ImageRecordList;
66 } IMAGE_PROPERTIES_PRIVATE_DATA;
67
68 IMAGE_PROPERTIES_PRIVATE_DATA mImagePropertiesPrivateData = {
69 IMAGE_PROPERTIES_PRIVATE_DATA_SIGNATURE,
70 0,
71 0,
72 INITIALIZE_LIST_HEAD_VARIABLE (mImagePropertiesPrivateData.ImageRecordList)
73 };
74
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
79 };
80
81 EFI_LOCK mPropertiesTableLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
82
83 //
84 // Below functions are for MemoryMap
85 //
86
87 /**
88 Converts a number of EFI_PAGEs to a size in bytes.
89
90 NOTE: Do not use EFI_PAGES_TO_SIZE because it handles UINTN only.
91
92 @param Pages The number of EFI_PAGES.
93
94 @return The number of bytes associated with the number of EFI_PAGEs specified
95 by Pages.
96 **/
97 STATIC
98 UINT64
99 EfiPagesToSize (
100 IN UINT64 Pages
101 )
102 {
103 return LShiftU64 (Pages, EFI_PAGE_SHIFT);
104 }
105
106 /**
107 Converts a size, in bytes, to a number of EFI_PAGESs.
108
109 NOTE: Do not use EFI_SIZE_TO_PAGES because it handles UINTN only.
110
111 @param Size A size in bytes.
112
113 @return The number of EFI_PAGESs associated with the number of bytes specified
114 by Size.
115
116 **/
117 STATIC
118 UINT64
119 EfiSizeToPages (
120 IN UINT64 Size
121 )
122 {
123 return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
124 }
125
126 /**
127 Acquire memory lock on mPropertiesTableLock.
128 **/
129 STATIC
130 VOID
131 CoreAcquirePropertiesTableLock (
132 VOID
133 )
134 {
135 CoreAcquireLock (&mPropertiesTableLock);
136 }
137
138 /**
139 Release memory lock on mPropertiesTableLock.
140 **/
141 STATIC
142 VOID
143 CoreReleasePropertiesTableLock (
144 VOID
145 )
146 {
147 CoreReleaseLock (&mPropertiesTableLock);
148 }
149
150 /**
151 Sort memory map entries based upon PhysicalStart, from low to high.
152
153 @param MemoryMap A pointer to the buffer in which firmware places
154 the current memory map.
155 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
156 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
157 **/
158 STATIC
159 VOID
160 SortMemoryMap (
161 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
162 IN UINTN MemoryMapSize,
163 IN UINTN DescriptorSize
164 )
165 {
166 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
167 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
168 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
169 EFI_MEMORY_DESCRIPTOR TempMemoryMap;
170
171 MemoryMapEntry = MemoryMap;
172 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
173 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);
174 while (MemoryMapEntry < MemoryMapEnd) {
175 while (NextMemoryMapEntry < MemoryMapEnd) {
176 if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
177 CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
178 CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
179 CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof(EFI_MEMORY_DESCRIPTOR));
180 }
181
182 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
183 }
184
185 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
186 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
187 }
188
189 return ;
190 }
191
192 /**
193 Merge continous memory map entries whose have same attributes.
194
195 @param MemoryMap A pointer to the buffer in which firmware places
196 the current memory map.
197 @param MemoryMapSize A pointer to the size, in bytes, of the
198 MemoryMap buffer. On input, this is the size of
199 the current memory map. On output,
200 it is the size of new memory map after merge.
201 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
202 **/
203 STATIC
204 VOID
205 MergeMemoryMap (
206 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
207 IN OUT UINTN *MemoryMapSize,
208 IN UINTN DescriptorSize
209 )
210 {
211 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
212 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
213 UINT64 MemoryBlockLength;
214 EFI_MEMORY_DESCRIPTOR *NewMemoryMapEntry;
215 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
216
217 MemoryMapEntry = MemoryMap;
218 NewMemoryMapEntry = MemoryMap;
219 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + *MemoryMapSize);
220 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
221 CopyMem (NewMemoryMapEntry, MemoryMapEntry, sizeof(EFI_MEMORY_DESCRIPTOR));
222 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
223
224 MemoryBlockLength = (UINT64) (EfiPagesToSize (MemoryMapEntry->NumberOfPages));
225 if (((UINTN)NextMemoryMapEntry < (UINTN)MemoryMapEnd) &&
226 (MemoryMapEntry->Type == NextMemoryMapEntry->Type) &&
227 (MemoryMapEntry->Attribute == NextMemoryMapEntry->Attribute) &&
228 ((MemoryMapEntry->PhysicalStart + MemoryBlockLength) == NextMemoryMapEntry->PhysicalStart)) {
229 NewMemoryMapEntry->NumberOfPages += NextMemoryMapEntry->NumberOfPages;
230 MemoryMapEntry = NextMemoryMapEntry;
231 }
232
233 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
234 NewMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NewMemoryMapEntry, DescriptorSize);
235 }
236
237 *MemoryMapSize = (UINTN)NewMemoryMapEntry - (UINTN)MemoryMap;
238
239 return ;
240 }
241
242 /**
243 Enforce memory map attributes.
244 This function will set EfiRuntimeServicesData/EfiMemoryMappedIO/EfiMemoryMappedIOPortSpace to be EFI_MEMORY_XP.
245
246 @param MemoryMap A pointer to the buffer in which firmware places
247 the current memory map.
248 @param MemoryMapSize Size, in bytes, of the MemoryMap buffer.
249 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
250 **/
251 STATIC
252 VOID
253 EnforceMemoryMapAttribute (
254 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
255 IN UINTN MemoryMapSize,
256 IN UINTN DescriptorSize
257 )
258 {
259 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
260 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
261
262 MemoryMapEntry = MemoryMap;
263 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *) ((UINT8 *) MemoryMap + MemoryMapSize);
264 while ((UINTN)MemoryMapEntry < (UINTN)MemoryMapEnd) {
265 switch (MemoryMapEntry->Type) {
266 case EfiRuntimeServicesCode:
267 // do nothing
268 break;
269 case EfiRuntimeServicesData:
270 case EfiMemoryMappedIO:
271 case EfiMemoryMappedIOPortSpace:
272 MemoryMapEntry->Attribute |= EFI_MEMORY_XP;
273 break;
274 case EfiReservedMemoryType:
275 case EfiACPIMemoryNVS:
276 break;
277 }
278
279 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
280 }
281
282 return ;
283 }
284
285 /**
286 Return the first image record, whose [ImageBase, ImageSize] covered by [Buffer, Length].
287
288 @param Buffer Start Address
289 @param Length Address length
290
291 @return first image record covered by [buffer, length]
292 **/
293 STATIC
294 IMAGE_PROPERTIES_RECORD *
295 GetImageRecordByAddress (
296 IN EFI_PHYSICAL_ADDRESS Buffer,
297 IN UINT64 Length
298 )
299 {
300 IMAGE_PROPERTIES_RECORD *ImageRecord;
301 LIST_ENTRY *ImageRecordLink;
302 LIST_ENTRY *ImageRecordList;
303
304 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
305
306 for (ImageRecordLink = ImageRecordList->ForwardLink;
307 ImageRecordLink != ImageRecordList;
308 ImageRecordLink = ImageRecordLink->ForwardLink) {
309 ImageRecord = CR (
310 ImageRecordLink,
311 IMAGE_PROPERTIES_RECORD,
312 Link,
313 IMAGE_PROPERTIES_RECORD_SIGNATURE
314 );
315
316 if ((Buffer <= ImageRecord->ImageBase) &&
317 (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize)) {
318 return ImageRecord;
319 }
320 }
321
322 return NULL;
323 }
324
325 /**
326 Set the memory map to new entries, according to one old entry,
327 based upon PE code section and data section in image record
328
329 @param ImageRecord An image record whose [ImageBase, ImageSize] covered
330 by old memory map entry.
331 @param NewRecord A pointer to several new memory map entries.
332 The caller gurantee the buffer size be 1 +
333 (SplitRecordCount * DescriptorSize) calculated
334 below.
335 @param OldRecord A pointer to one old memory map entry.
336 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
337 **/
338 STATIC
339 UINTN
340 SetNewRecord (
341 IN IMAGE_PROPERTIES_RECORD *ImageRecord,
342 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,
343 IN EFI_MEMORY_DESCRIPTOR *OldRecord,
344 IN UINTN DescriptorSize
345 )
346 {
347 EFI_MEMORY_DESCRIPTOR TempRecord;
348 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
349 LIST_ENTRY *ImageRecordCodeSectionLink;
350 LIST_ENTRY *ImageRecordCodeSectionEndLink;
351 LIST_ENTRY *ImageRecordCodeSectionList;
352 UINTN NewRecordCount;
353 UINT64 PhysicalEnd;
354 UINT64 ImageEnd;
355
356 CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));
357 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);
358 NewRecordCount = 0;
359
360 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
361
362 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
363 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
364 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
365 ImageRecordCodeSection = CR (
366 ImageRecordCodeSectionLink,
367 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
368 Link,
369 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
370 );
371 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
372
373 if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
374 //
375 // DATA
376 //
377 NewRecord->Type = EfiRuntimeServicesData;
378 NewRecord->PhysicalStart = TempRecord.PhysicalStart;
379 NewRecord->VirtualStart = 0;
380 NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);
381 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;
382 if (NewRecord->NumberOfPages != 0) {
383 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
384 NewRecordCount ++;
385 }
386
387 //
388 // CODE
389 //
390 NewRecord->Type = EfiRuntimeServicesCode;
391 NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;
392 NewRecord->VirtualStart = 0;
393 NewRecord->NumberOfPages = EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize);
394 NewRecord->Attribute = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;
395 if (NewRecord->NumberOfPages != 0) {
396 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
397 NewRecordCount ++;
398 }
399
400 TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages(ImageRecordCodeSection->CodeSegmentSize));
401 TempRecord.NumberOfPages = EfiSizeToPages(PhysicalEnd - TempRecord.PhysicalStart);
402 if (TempRecord.NumberOfPages == 0) {
403 break;
404 }
405 }
406 }
407
408 ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
409
410 //
411 // Final DATA
412 //
413 if (TempRecord.PhysicalStart < ImageEnd) {
414 NewRecord->Type = EfiRuntimeServicesData;
415 NewRecord->PhysicalStart = TempRecord.PhysicalStart;
416 NewRecord->VirtualStart = 0;
417 NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);
418 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;
419 NewRecordCount ++;
420 }
421
422 return NewRecordCount;
423 }
424
425 /**
426 Return the max number of new splitted entries, according to one old entry,
427 based upon PE code section and data section.
428
429 @param OldRecord A pointer to one old memory map entry.
430
431 @retval 0 no entry need to be splitted.
432 @return the max number of new splitted entries
433 **/
434 STATIC
435 UINTN
436 GetMaxSplitRecordCount (
437 IN EFI_MEMORY_DESCRIPTOR *OldRecord
438 )
439 {
440 IMAGE_PROPERTIES_RECORD *ImageRecord;
441 UINTN SplitRecordCount;
442 UINT64 PhysicalStart;
443 UINT64 PhysicalEnd;
444
445 SplitRecordCount = 0;
446 PhysicalStart = OldRecord->PhysicalStart;
447 PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize(OldRecord->NumberOfPages);
448
449 do {
450 ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
451 if (ImageRecord == NULL) {
452 break;
453 }
454 SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 1);
455 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
456 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
457
458 if (SplitRecordCount != 0) {
459 SplitRecordCount--;
460 }
461
462 return SplitRecordCount;
463 }
464
465 /**
466 Split the memory map to new entries, according to one old entry,
467 based upon PE code section and data section.
468
469 @param OldRecord A pointer to one old memory map entry.
470 @param NewRecord A pointer to several new memory map entries.
471 The caller gurantee the buffer size be 1 +
472 (SplitRecordCount * DescriptorSize) calculated
473 below.
474 @param MaxSplitRecordCount The max number of splitted entries
475 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
476
477 @retval 0 no entry is splitted.
478 @return the real number of splitted record.
479 **/
480 STATIC
481 UINTN
482 SplitRecord (
483 IN EFI_MEMORY_DESCRIPTOR *OldRecord,
484 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,
485 IN UINTN MaxSplitRecordCount,
486 IN UINTN DescriptorSize
487 )
488 {
489 EFI_MEMORY_DESCRIPTOR TempRecord;
490 IMAGE_PROPERTIES_RECORD *ImageRecord;
491 IMAGE_PROPERTIES_RECORD *NewImageRecord;
492 UINT64 PhysicalStart;
493 UINT64 PhysicalEnd;
494 UINTN NewRecordCount;
495 UINTN TotalNewRecordCount;
496
497 if (MaxSplitRecordCount == 0) {
498 CopyMem (NewRecord, OldRecord, DescriptorSize);
499 return 0;
500 }
501
502 TotalNewRecordCount = 0;
503
504 //
505 // Override previous record
506 //
507 CopyMem (&TempRecord, OldRecord, sizeof(EFI_MEMORY_DESCRIPTOR));
508 PhysicalStart = TempRecord.PhysicalStart;
509 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize(TempRecord.NumberOfPages);
510
511 ImageRecord = NULL;
512 do {
513 NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart);
514 if (NewImageRecord == NULL) {
515 //
516 // No more image covered by this range, stop
517 //
518 if ((PhysicalEnd > PhysicalStart) && (ImageRecord != NULL)) {
519 //
520 // If this is still address in this record, need record.
521 //
522 NewRecord = PREVIOUS_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
523 if (NewRecord->Type == EfiRuntimeServicesData) {
524 //
525 // Last record is DATA, just merge it.
526 //
527 NewRecord->NumberOfPages = EfiSizeToPages(PhysicalEnd - NewRecord->PhysicalStart);
528 } else {
529 //
530 // Last record is CODE, create a new DATA entry.
531 //
532 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
533 NewRecord->Type = EfiRuntimeServicesData;
534 NewRecord->PhysicalStart = TempRecord.PhysicalStart;
535 NewRecord->VirtualStart = 0;
536 NewRecord->NumberOfPages = TempRecord.NumberOfPages;
537 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;
538 TotalNewRecordCount ++;
539 }
540 }
541 break;
542 }
543 ImageRecord = NewImageRecord;
544
545 //
546 // Set new record
547 //
548 NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
549 TotalNewRecordCount += NewRecordCount;
550 NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);
551
552 //
553 // Update PhysicalStart, in order to exclude the image buffer already splitted.
554 //
555 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
556 TempRecord.PhysicalStart = PhysicalStart;
557 TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
558 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
559
560 return TotalNewRecordCount - 1;
561 }
562
563 /**
564 Split the original memory map, and add more entries to describe PE code section and data section.
565 This function will set EfiRuntimeServicesData to be EFI_MEMORY_XP.
566 This function will merge entries with same attributes finally.
567
568 NOTE: It assumes PE code/data section are page aligned.
569 NOTE: It assumes enough entry is prepared for new memory map.
570
571 Split table:
572 +---------------+
573 | Record X |
574 +---------------+
575 | Record RtCode |
576 +---------------+
577 | Record Y |
578 +---------------+
579 ==>
580 +---------------+
581 | Record X |
582 +---------------+ ----
583 | Record RtData | |
584 +---------------+ |
585 | Record RtCode | |-> PE/COFF1
586 +---------------+ |
587 | Record RtData | |
588 +---------------+ ----
589 | Record RtData | |
590 +---------------+ |
591 | Record RtCode | |-> PE/COFF2
592 +---------------+ |
593 | Record RtData | |
594 +---------------+ ----
595 | Record Y |
596 +---------------+
597
598 @param MemoryMapSize A pointer to the size, in bytes, of the
599 MemoryMap buffer. On input, this is the size of
600 old MemoryMap before split. The actual buffer
601 size of MemoryMap is MemoryMapSize +
602 (AdditionalRecordCount * DescriptorSize) calculated
603 below. On output, it is the size of new MemoryMap
604 after split.
605 @param MemoryMap A pointer to the buffer in which firmware places
606 the current memory map.
607 @param DescriptorSize Size, in bytes, of an individual EFI_MEMORY_DESCRIPTOR.
608 **/
609 STATIC
610 VOID
611 SplitTable (
612 IN OUT UINTN *MemoryMapSize,
613 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
614 IN UINTN DescriptorSize
615 )
616 {
617 INTN IndexOld;
618 INTN IndexNew;
619 UINTN MaxSplitRecordCount;
620 UINTN RealSplitRecordCount;
621 UINTN TotalSplitRecordCount;
622 UINTN AdditionalRecordCount;
623
624 AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
625
626 TotalSplitRecordCount = 0;
627 //
628 // Let old record point to end of valid MemoryMap buffer.
629 //
630 IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;
631 //
632 // Let new record point to end of full MemoryMap buffer.
633 //
634 IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + AdditionalRecordCount;
635 for (; IndexOld >= 0; IndexOld--) {
636 MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize));
637 //
638 // Split this MemoryMap record
639 //
640 IndexNew -= MaxSplitRecordCount;
641 RealSplitRecordCount = SplitRecord (
642 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
643 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
644 MaxSplitRecordCount,
645 DescriptorSize
646 );
647 //
648 // Adjust IndexNew according to real split.
649 //
650 CopyMem (
651 ((UINT8 *)MemoryMap + (IndexNew + MaxSplitRecordCount - RealSplitRecordCount) * DescriptorSize),
652 ((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
653 RealSplitRecordCount * DescriptorSize
654 );
655 IndexNew = IndexNew + MaxSplitRecordCount - RealSplitRecordCount;
656 TotalSplitRecordCount += RealSplitRecordCount;
657 IndexNew --;
658 }
659 //
660 // Move all records to the beginning.
661 //
662 CopyMem (
663 MemoryMap,
664 (UINT8 *)MemoryMap + (AdditionalRecordCount - TotalSplitRecordCount) * DescriptorSize,
665 (*MemoryMapSize) + TotalSplitRecordCount * DescriptorSize
666 );
667
668 *MemoryMapSize = (*MemoryMapSize) + DescriptorSize * TotalSplitRecordCount;
669
670 //
671 // Sort from low to high (Just in case)
672 //
673 SortMemoryMap (MemoryMap, *MemoryMapSize, DescriptorSize);
674
675 //
676 // Set RuntimeData to XP
677 //
678 EnforceMemoryMapAttribute (MemoryMap, *MemoryMapSize, DescriptorSize);
679
680 //
681 // Merge same type to save entry size
682 //
683 MergeMemoryMap (MemoryMap, MemoryMapSize, DescriptorSize);
684
685 return ;
686 }
687
688 /**
689 This function for GetMemoryMap() with properties table.
690
691 It calls original GetMemoryMap() to get the original memory map information. Then
692 plus the additional memory map entries for PE Code/Data seperation.
693
694 @param MemoryMapSize A pointer to the size, in bytes, of the
695 MemoryMap buffer. On input, this is the size of
696 the buffer allocated by the caller. On output,
697 it is the size of the buffer returned by the
698 firmware if the buffer was large enough, or the
699 size of the buffer needed to contain the map if
700 the buffer was too small.
701 @param MemoryMap A pointer to the buffer in which firmware places
702 the current memory map.
703 @param MapKey A pointer to the location in which firmware
704 returns the key for the current memory map.
705 @param DescriptorSize A pointer to the location in which firmware
706 returns the size, in bytes, of an individual
707 EFI_MEMORY_DESCRIPTOR.
708 @param DescriptorVersion A pointer to the location in which firmware
709 returns the version number associated with the
710 EFI_MEMORY_DESCRIPTOR.
711
712 @retval EFI_SUCCESS The memory map was returned in the MemoryMap
713 buffer.
714 @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current
715 buffer size needed to hold the memory map is
716 returned in MemoryMapSize.
717 @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
718
719 **/
720 STATIC
721 EFI_STATUS
722 EFIAPI
723 CoreGetMemoryMapPropertiesTable (
724 IN OUT UINTN *MemoryMapSize,
725 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
726 OUT UINTN *MapKey,
727 OUT UINTN *DescriptorSize,
728 OUT UINT32 *DescriptorVersion
729 )
730 {
731 EFI_STATUS Status;
732 UINTN OldMemoryMapSize;
733 UINTN AdditionalRecordCount;
734
735 //
736 // If PE code/data is not aligned, just return.
737 //
738 if ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
739 return CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
740 }
741
742 if (MemoryMapSize == NULL) {
743 return EFI_INVALID_PARAMETER;
744 }
745
746 CoreAcquirePropertiesTableLock ();
747
748 AdditionalRecordCount = (2 * mImagePropertiesPrivateData.CodeSegmentCountMax + 1) * mImagePropertiesPrivateData.ImageRecordCount;
749
750 OldMemoryMapSize = *MemoryMapSize;
751 Status = CoreGetMemoryMap (MemoryMapSize, MemoryMap, MapKey, DescriptorSize, DescriptorVersion);
752 if (Status == EFI_BUFFER_TOO_SMALL) {
753 *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;
754 } else if (Status == EFI_SUCCESS) {
755 if (OldMemoryMapSize - *MemoryMapSize < (*DescriptorSize) * AdditionalRecordCount) {
756 *MemoryMapSize = *MemoryMapSize + (*DescriptorSize) * AdditionalRecordCount;
757 //
758 // Need update status to buffer too small
759 //
760 Status = EFI_BUFFER_TOO_SMALL;
761 } else {
762 //
763 // Split PE code/data
764 //
765 SplitTable (MemoryMapSize, MemoryMap, *DescriptorSize);
766 }
767 }
768
769 CoreReleasePropertiesTableLock ();
770 return Status;
771 }
772
773 //
774 // Below functions are for ImageRecord
775 //
776
777 /**
778 Set PropertiesTable accroding to PE/COFF image section alignment.
779
780 @param SectionAlignment PE/COFF section alignment
781 **/
782 STATIC
783 VOID
784 SetPropertiesTableSectionAlignment (
785 IN UINT32 SectionAlignment
786 )
787 {
788 if (((SectionAlignment & (SIZE_4KB - 1)) != 0) &&
789 ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) != 0)) {
790 DEBUG ((EFI_D_VERBOSE, "SetPropertiesTableSectionAlignment - Clear\n"));
791 mPropertiesTable.MemoryProtectionAttribute &= ~EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA;
792 gBS->GetMemoryMap = CoreGetMemoryMap;
793 gBS->Hdr.CRC32 = 0;
794 gBS->CalculateCrc32 ((UINT8 *)gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
795 }
796 }
797
798 /**
799 Swap two code sections in image record.
800
801 @param FirstImageRecordCodeSection first code section in image record
802 @param SecondImageRecordCodeSection second code section in image record
803 **/
804 STATIC
805 VOID
806 SwapImageRecordCodeSection (
807 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection,
808 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection
809 )
810 {
811 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection;
812
813 TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
814 TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
815
816 FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
817 FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
818
819 SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
820 SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
821 }
822
823 /**
824 Sort code section in image record, based upon CodeSegmentBase from low to high.
825
826 @param ImageRecord image record to be sorted
827 **/
828 STATIC
829 VOID
830 SortImageRecordCodeSection (
831 IN IMAGE_PROPERTIES_RECORD *ImageRecord
832 )
833 {
834 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
835 IMAGE_PROPERTIES_RECORD_CODE_SECTION *NextImageRecordCodeSection;
836 LIST_ENTRY *ImageRecordCodeSectionLink;
837 LIST_ENTRY *NextImageRecordCodeSectionLink;
838 LIST_ENTRY *ImageRecordCodeSectionEndLink;
839 LIST_ENTRY *ImageRecordCodeSectionList;
840
841 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
842
843 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
844 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
845 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
846 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
847 ImageRecordCodeSection = CR (
848 ImageRecordCodeSectionLink,
849 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
850 Link,
851 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
852 );
853 while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
854 NextImageRecordCodeSection = CR (
855 NextImageRecordCodeSectionLink,
856 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
857 Link,
858 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
859 );
860 if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
861 SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
862 }
863 NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
864 }
865
866 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
867 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
868 }
869 }
870
871 /**
872 Check if code section in image record is valid.
873
874 @param ImageRecord image record to be checked
875
876 @retval TRUE image record is valid
877 @retval FALSE image record is invalid
878 **/
879 STATIC
880 BOOLEAN
881 IsImageRecordCodeSectionValid (
882 IN IMAGE_PROPERTIES_RECORD *ImageRecord
883 )
884 {
885 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
886 IMAGE_PROPERTIES_RECORD_CODE_SECTION *LastImageRecordCodeSection;
887 LIST_ENTRY *ImageRecordCodeSectionLink;
888 LIST_ENTRY *ImageRecordCodeSectionEndLink;
889 LIST_ENTRY *ImageRecordCodeSectionList;
890
891 DEBUG ((EFI_D_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
892
893 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
894
895 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
896 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
897 LastImageRecordCodeSection = NULL;
898 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
899 ImageRecordCodeSection = CR (
900 ImageRecordCodeSectionLink,
901 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
902 Link,
903 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
904 );
905 if (ImageRecordCodeSection->CodeSegmentSize == 0) {
906 return FALSE;
907 }
908 if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
909 return FALSE;
910 }
911 if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
912 return FALSE;
913 }
914 if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
915 return FALSE;
916 }
917 if (LastImageRecordCodeSection != NULL) {
918 if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
919 return FALSE;
920 }
921 }
922
923 LastImageRecordCodeSection = ImageRecordCodeSection;
924 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
925 }
926
927 return TRUE;
928 }
929
930 /**
931 Swap two image records.
932
933 @param FirstImageRecord first image record.
934 @param SecondImageRecord second image record.
935 **/
936 STATIC
937 VOID
938 SwapImageRecord (
939 IN IMAGE_PROPERTIES_RECORD *FirstImageRecord,
940 IN IMAGE_PROPERTIES_RECORD *SecondImageRecord
941 )
942 {
943 IMAGE_PROPERTIES_RECORD TempImageRecord;
944
945 TempImageRecord.ImageBase = FirstImageRecord->ImageBase;
946 TempImageRecord.ImageSize = FirstImageRecord->ImageSize;
947 TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
948
949 FirstImageRecord->ImageBase = SecondImageRecord->ImageBase;
950 FirstImageRecord->ImageSize = SecondImageRecord->ImageSize;
951 FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
952
953 SecondImageRecord->ImageBase = TempImageRecord.ImageBase;
954 SecondImageRecord->ImageSize = TempImageRecord.ImageSize;
955 SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
956
957 SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
958 }
959
960 /**
961 Sort image record based upon the ImageBase from low to high.
962 **/
963 STATIC
964 VOID
965 SortImageRecord (
966 VOID
967 )
968 {
969 IMAGE_PROPERTIES_RECORD *ImageRecord;
970 IMAGE_PROPERTIES_RECORD *NextImageRecord;
971 LIST_ENTRY *ImageRecordLink;
972 LIST_ENTRY *NextImageRecordLink;
973 LIST_ENTRY *ImageRecordEndLink;
974 LIST_ENTRY *ImageRecordList;
975
976 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
977
978 ImageRecordLink = ImageRecordList->ForwardLink;
979 NextImageRecordLink = ImageRecordLink->ForwardLink;
980 ImageRecordEndLink = ImageRecordList;
981 while (ImageRecordLink != ImageRecordEndLink) {
982 ImageRecord = CR (
983 ImageRecordLink,
984 IMAGE_PROPERTIES_RECORD,
985 Link,
986 IMAGE_PROPERTIES_RECORD_SIGNATURE
987 );
988 while (NextImageRecordLink != ImageRecordEndLink) {
989 NextImageRecord = CR (
990 NextImageRecordLink,
991 IMAGE_PROPERTIES_RECORD,
992 Link,
993 IMAGE_PROPERTIES_RECORD_SIGNATURE
994 );
995 if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
996 SwapImageRecord (ImageRecord, NextImageRecord);
997 }
998 NextImageRecordLink = NextImageRecordLink->ForwardLink;
999 }
1000
1001 ImageRecordLink = ImageRecordLink->ForwardLink;
1002 NextImageRecordLink = ImageRecordLink->ForwardLink;
1003 }
1004 }
1005
1006 /**
1007 Dump image record.
1008 **/
1009 STATIC
1010 VOID
1011 DumpImageRecord (
1012 VOID
1013 )
1014 {
1015 IMAGE_PROPERTIES_RECORD *ImageRecord;
1016 LIST_ENTRY *ImageRecordLink;
1017 LIST_ENTRY *ImageRecordList;
1018 UINTN Index;
1019
1020 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
1021
1022 for (ImageRecordLink = ImageRecordList->ForwardLink, Index= 0;
1023 ImageRecordLink != ImageRecordList;
1024 ImageRecordLink = ImageRecordLink->ForwardLink, Index++) {
1025 ImageRecord = CR (
1026 ImageRecordLink,
1027 IMAGE_PROPERTIES_RECORD,
1028 Link,
1029 IMAGE_PROPERTIES_RECORD_SIGNATURE
1030 );
1031 DEBUG ((EFI_D_VERBOSE, " Image[%d]: 0x%016lx - 0x%016lx\n", Index, ImageRecord->ImageBase, ImageRecord->ImageSize));
1032 }
1033 }
1034
1035 /**
1036 Insert image record.
1037
1038 @param RuntimeImage Runtime image information
1039 **/
1040 VOID
1041 InsertImageRecord (
1042 IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
1043 )
1044 {
1045 VOID *ImageAddress;
1046 EFI_IMAGE_DOS_HEADER *DosHdr;
1047 UINT32 PeCoffHeaderOffset;
1048 UINT32 SectionAlignment;
1049 EFI_IMAGE_SECTION_HEADER *Section;
1050 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
1051 UINT8 *Name;
1052 UINTN Index;
1053 IMAGE_PROPERTIES_RECORD *ImageRecord;
1054 CHAR8 *PdbPointer;
1055 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
1056 UINT16 Magic;
1057
1058 DEBUG ((EFI_D_VERBOSE, "InsertImageRecord - 0x%x\n", RuntimeImage));
1059 DEBUG ((EFI_D_VERBOSE, "InsertImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));
1060
1061 ImageRecord = AllocatePool (sizeof(*ImageRecord));
1062 if (ImageRecord == NULL) {
1063 return ;
1064 }
1065 ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
1066
1067 DEBUG ((EFI_D_VERBOSE, "ImageRecordCount - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
1068
1069 //
1070 // Step 1: record whole region
1071 //
1072 ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase;
1073 ImageRecord->ImageSize = RuntimeImage->ImageSize;
1074
1075 ImageAddress = RuntimeImage->ImageBase;
1076
1077 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);
1078 if (PdbPointer != NULL) {
1079 DEBUG ((EFI_D_VERBOSE, " Image - %a\n", PdbPointer));
1080 }
1081
1082 //
1083 // Check PE/COFF image
1084 //
1085 DosHdr = (EFI_IMAGE_DOS_HEADER *) (UINTN) ImageAddress;
1086 PeCoffHeaderOffset = 0;
1087 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
1088 PeCoffHeaderOffset = DosHdr->e_lfanew;
1089 }
1090
1091 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *) (UINTN) ImageAddress + PeCoffHeaderOffset);
1092 if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
1093 DEBUG ((EFI_D_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));
1094 // It might be image in SMM.
1095 goto Finish;
1096 }
1097
1098 //
1099 // Get SectionAlignment
1100 //
1101 if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1102 //
1103 // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value
1104 // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the
1105 // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
1106 // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
1107 //
1108 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
1109 } else {
1110 //
1111 // Get the magic value from the PE/COFF Optional Header
1112 //
1113 Magic = Hdr.Pe32->OptionalHeader.Magic;
1114 }
1115 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1116 SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
1117 } else {
1118 SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
1119 }
1120
1121 SetPropertiesTableSectionAlignment (SectionAlignment);
1122 if ((SectionAlignment & (SIZE_4KB - 1)) != 0) {
1123 DEBUG ((EFI_D_ERROR, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not 4K !!!!!!!!\n", SectionAlignment));
1124 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);
1125 if (PdbPointer != NULL) {
1126 DEBUG ((EFI_D_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
1127 }
1128 goto Finish;
1129 }
1130
1131 Section = (EFI_IMAGE_SECTION_HEADER *) (
1132 (UINT8 *) (UINTN) ImageAddress +
1133 PeCoffHeaderOffset +
1134 sizeof(UINT32) +
1135 sizeof(EFI_IMAGE_FILE_HEADER) +
1136 Hdr.Pe32->FileHeader.SizeOfOptionalHeader
1137 );
1138 ImageRecord->CodeSegmentCount = 0;
1139 InitializeListHead (&ImageRecord->CodeSegmentList);
1140 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
1141 Name = Section[Index].Name;
1142 DEBUG ((
1143 EFI_D_VERBOSE,
1144 " Section - '%c%c%c%c%c%c%c%c'\n",
1145 Name[0],
1146 Name[1],
1147 Name[2],
1148 Name[3],
1149 Name[4],
1150 Name[5],
1151 Name[6],
1152 Name[7]
1153 ));
1154
1155 if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
1156 DEBUG ((EFI_D_VERBOSE, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize));
1157 DEBUG ((EFI_D_VERBOSE, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress));
1158 DEBUG ((EFI_D_VERBOSE, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData));
1159 DEBUG ((EFI_D_VERBOSE, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData));
1160 DEBUG ((EFI_D_VERBOSE, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
1161 DEBUG ((EFI_D_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
1162 DEBUG ((EFI_D_VERBOSE, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations));
1163 DEBUG ((EFI_D_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers));
1164 DEBUG ((EFI_D_VERBOSE, " Characteristics - 0x%08x\n", Section[Index].Characteristics));
1165
1166 //
1167 // Step 2: record code section
1168 //
1169 ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection));
1170 if (ImageRecordCodeSection == NULL) {
1171 return ;
1172 }
1173 ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
1174
1175 ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;
1176 ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;
1177
1178 DEBUG ((EFI_D_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));
1179
1180 InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
1181 ImageRecord->CodeSegmentCount++;
1182 }
1183 }
1184
1185 if (ImageRecord->CodeSegmentCount == 0) {
1186 SetPropertiesTableSectionAlignment (1);
1187 DEBUG ((EFI_D_ERROR, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1188 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);
1189 if (PdbPointer != NULL) {
1190 DEBUG ((EFI_D_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
1191 }
1192 goto Finish;
1193 }
1194
1195 //
1196 // Final
1197 //
1198 SortImageRecordCodeSection (ImageRecord);
1199 //
1200 // Check overlap all section in ImageBase/Size
1201 //
1202 if (!IsImageRecordCodeSectionValid (ImageRecord)) {
1203 DEBUG ((EFI_D_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
1204 goto Finish;
1205 }
1206
1207 InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
1208 mImagePropertiesPrivateData.ImageRecordCount++;
1209
1210 SortImageRecord ();
1211
1212 if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
1213 mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
1214 }
1215
1216 Finish:
1217 return ;
1218 }
1219
1220 /**
1221 Find image record accroding to image base and size.
1222
1223 @param ImageBase Base of PE image
1224 @param ImageSize Size of PE image
1225
1226 @return image record
1227 **/
1228 STATIC
1229 IMAGE_PROPERTIES_RECORD *
1230 FindImageRecord (
1231 IN EFI_PHYSICAL_ADDRESS ImageBase,
1232 IN UINT64 ImageSize
1233 )
1234 {
1235 IMAGE_PROPERTIES_RECORD *ImageRecord;
1236 LIST_ENTRY *ImageRecordLink;
1237 LIST_ENTRY *ImageRecordList;
1238
1239 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
1240
1241 for (ImageRecordLink = ImageRecordList->ForwardLink;
1242 ImageRecordLink != ImageRecordList;
1243 ImageRecordLink = ImageRecordLink->ForwardLink) {
1244 ImageRecord = CR (
1245 ImageRecordLink,
1246 IMAGE_PROPERTIES_RECORD,
1247 Link,
1248 IMAGE_PROPERTIES_RECORD_SIGNATURE
1249 );
1250
1251 if ((ImageBase == ImageRecord->ImageBase) &&
1252 (ImageSize == ImageRecord->ImageSize)) {
1253 return ImageRecord;
1254 }
1255 }
1256
1257 return NULL;
1258 }
1259
1260 /**
1261 Remove Image record.
1262
1263 @param RuntimeImage Runtime image information
1264 **/
1265 VOID
1266 RemoveImageRecord (
1267 IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
1268 )
1269 {
1270 IMAGE_PROPERTIES_RECORD *ImageRecord;
1271 LIST_ENTRY *CodeSegmentListHead;
1272 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
1273
1274 DEBUG ((EFI_D_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage));
1275 DEBUG ((EFI_D_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));
1276
1277 ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize);
1278 if (ImageRecord == NULL) {
1279 DEBUG ((EFI_D_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1280 return ;
1281 }
1282
1283 CodeSegmentListHead = &ImageRecord->CodeSegmentList;
1284 while (!IsListEmpty (CodeSegmentListHead)) {
1285 ImageRecordCodeSection = CR (
1286 CodeSegmentListHead->ForwardLink,
1287 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
1288 Link,
1289 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1290 );
1291 RemoveEntryList (&ImageRecordCodeSection->Link);
1292 FreePool (ImageRecordCodeSection);
1293 }
1294
1295 RemoveEntryList (&ImageRecord->Link);
1296 FreePool (ImageRecord);
1297 mImagePropertiesPrivateData.ImageRecordCount--;
1298 }
1299
1300
1301 /**
1302 Install PropertiesTable.
1303
1304 @param[in] Event The Event this notify function registered to.
1305 @param[in] Context Pointer to the context data registered to the Event.
1306 **/
1307 VOID
1308 EFIAPI
1309 InstallPropertiesTable (
1310 EFI_EVENT Event,
1311 VOID *Context
1312 )
1313 {
1314 if (PcdGetBool (PcdPropertiesTableEnable)) {
1315 EFI_STATUS Status;
1316
1317 Status = gBS->InstallConfigurationTable (&gEfiPropertiesTableGuid, &mPropertiesTable);
1318 ASSERT_EFI_ERROR (Status);
1319
1320 DEBUG ((EFI_D_INFO, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable.MemoryProtectionAttribute));
1321 if ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
1322 return ;
1323 }
1324
1325 gBS->GetMemoryMap = CoreGetMemoryMapPropertiesTable;
1326 gBS->Hdr.CRC32 = 0;
1327 gBS->CalculateCrc32 ((UINT8 *)gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
1328
1329 DEBUG ((EFI_D_VERBOSE, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
1330 DEBUG ((EFI_D_VERBOSE, "Dump ImageRecord:\n"));
1331 DumpImageRecord ();
1332 }
1333 }
1334
1335 /**
1336 Initialize PropertiesTable support.
1337 **/
1338 VOID
1339 EFIAPI
1340 CoreInitializePropertiesTable (
1341 VOID
1342 )
1343 {
1344 EFI_STATUS Status;
1345 EFI_EVENT EndOfDxeEvent;
1346
1347 Status = gBS->CreateEventEx (
1348 EVT_NOTIFY_SIGNAL,
1349 TPL_NOTIFY,
1350 InstallPropertiesTable,
1351 NULL,
1352 &gEfiEndOfDxeEventGroupGuid,
1353 &EndOfDxeEvent
1354 );
1355 ASSERT_EFI_ERROR (Status);
1356 return ;
1357 }