]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Core/Dxe/Misc/PropertiesTable.c
MdeModulePkg Core/Dxe/Misc: Fix typos in function descriptions
[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 according 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 & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 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 &= ~((UINT64)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 & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) {
1123 DEBUG ((EFI_D_WARN, "!!!!!!!! InsertImageRecord - Section Alignment(0x%x) is not %dK !!!!!!!!\n",
1124 SectionAlignment, EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT >> 10));
1125 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);
1126 if (PdbPointer != NULL) {
1127 DEBUG ((EFI_D_WARN, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
1128 }
1129 goto Finish;
1130 }
1131
1132 Section = (EFI_IMAGE_SECTION_HEADER *) (
1133 (UINT8 *) (UINTN) ImageAddress +
1134 PeCoffHeaderOffset +
1135 sizeof(UINT32) +
1136 sizeof(EFI_IMAGE_FILE_HEADER) +
1137 Hdr.Pe32->FileHeader.SizeOfOptionalHeader
1138 );
1139 ImageRecord->CodeSegmentCount = 0;
1140 InitializeListHead (&ImageRecord->CodeSegmentList);
1141 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
1142 Name = Section[Index].Name;
1143 DEBUG ((
1144 EFI_D_VERBOSE,
1145 " Section - '%c%c%c%c%c%c%c%c'\n",
1146 Name[0],
1147 Name[1],
1148 Name[2],
1149 Name[3],
1150 Name[4],
1151 Name[5],
1152 Name[6],
1153 Name[7]
1154 ));
1155
1156 if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
1157 DEBUG ((EFI_D_VERBOSE, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize));
1158 DEBUG ((EFI_D_VERBOSE, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress));
1159 DEBUG ((EFI_D_VERBOSE, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData));
1160 DEBUG ((EFI_D_VERBOSE, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData));
1161 DEBUG ((EFI_D_VERBOSE, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
1162 DEBUG ((EFI_D_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
1163 DEBUG ((EFI_D_VERBOSE, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations));
1164 DEBUG ((EFI_D_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers));
1165 DEBUG ((EFI_D_VERBOSE, " Characteristics - 0x%08x\n", Section[Index].Characteristics));
1166
1167 //
1168 // Step 2: record code section
1169 //
1170 ImageRecordCodeSection = AllocatePool (sizeof(*ImageRecordCodeSection));
1171 if (ImageRecordCodeSection == NULL) {
1172 return ;
1173 }
1174 ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
1175
1176 ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageAddress + Section[Index].VirtualAddress;
1177 ImageRecordCodeSection->CodeSegmentSize = Section[Index].SizeOfRawData;
1178
1179 DEBUG ((EFI_D_VERBOSE, "ImageCode: 0x%016lx - 0x%016lx\n", ImageRecordCodeSection->CodeSegmentBase, ImageRecordCodeSection->CodeSegmentSize));
1180
1181 InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
1182 ImageRecord->CodeSegmentCount++;
1183 }
1184 }
1185
1186 if (ImageRecord->CodeSegmentCount == 0) {
1187 SetPropertiesTableSectionAlignment (1);
1188 DEBUG ((EFI_D_ERROR, "!!!!!!!! InsertImageRecord - CodeSegmentCount is 0 !!!!!!!!\n"));
1189 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID*) (UINTN) ImageAddress);
1190 if (PdbPointer != NULL) {
1191 DEBUG ((EFI_D_ERROR, "!!!!!!!! Image - %a !!!!!!!!\n", PdbPointer));
1192 }
1193 goto Finish;
1194 }
1195
1196 //
1197 // Final
1198 //
1199 SortImageRecordCodeSection (ImageRecord);
1200 //
1201 // Check overlap all section in ImageBase/Size
1202 //
1203 if (!IsImageRecordCodeSectionValid (ImageRecord)) {
1204 DEBUG ((EFI_D_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
1205 goto Finish;
1206 }
1207
1208 InsertTailList (&mImagePropertiesPrivateData.ImageRecordList, &ImageRecord->Link);
1209 mImagePropertiesPrivateData.ImageRecordCount++;
1210
1211 SortImageRecord ();
1212
1213 if (mImagePropertiesPrivateData.CodeSegmentCountMax < ImageRecord->CodeSegmentCount) {
1214 mImagePropertiesPrivateData.CodeSegmentCountMax = ImageRecord->CodeSegmentCount;
1215 }
1216
1217 Finish:
1218 return ;
1219 }
1220
1221 /**
1222 Find image record according to image base and size.
1223
1224 @param ImageBase Base of PE image
1225 @param ImageSize Size of PE image
1226
1227 @return image record
1228 **/
1229 STATIC
1230 IMAGE_PROPERTIES_RECORD *
1231 FindImageRecord (
1232 IN EFI_PHYSICAL_ADDRESS ImageBase,
1233 IN UINT64 ImageSize
1234 )
1235 {
1236 IMAGE_PROPERTIES_RECORD *ImageRecord;
1237 LIST_ENTRY *ImageRecordLink;
1238 LIST_ENTRY *ImageRecordList;
1239
1240 ImageRecordList = &mImagePropertiesPrivateData.ImageRecordList;
1241
1242 for (ImageRecordLink = ImageRecordList->ForwardLink;
1243 ImageRecordLink != ImageRecordList;
1244 ImageRecordLink = ImageRecordLink->ForwardLink) {
1245 ImageRecord = CR (
1246 ImageRecordLink,
1247 IMAGE_PROPERTIES_RECORD,
1248 Link,
1249 IMAGE_PROPERTIES_RECORD_SIGNATURE
1250 );
1251
1252 if ((ImageBase == ImageRecord->ImageBase) &&
1253 (ImageSize == ImageRecord->ImageSize)) {
1254 return ImageRecord;
1255 }
1256 }
1257
1258 return NULL;
1259 }
1260
1261 /**
1262 Remove Image record.
1263
1264 @param RuntimeImage Runtime image information
1265 **/
1266 VOID
1267 RemoveImageRecord (
1268 IN EFI_RUNTIME_IMAGE_ENTRY *RuntimeImage
1269 )
1270 {
1271 IMAGE_PROPERTIES_RECORD *ImageRecord;
1272 LIST_ENTRY *CodeSegmentListHead;
1273 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
1274
1275 DEBUG ((EFI_D_VERBOSE, "RemoveImageRecord - 0x%x\n", RuntimeImage));
1276 DEBUG ((EFI_D_VERBOSE, "RemoveImageRecord - 0x%016lx - 0x%016lx\n", (EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize));
1277
1278 ImageRecord = FindImageRecord ((EFI_PHYSICAL_ADDRESS)(UINTN)RuntimeImage->ImageBase, RuntimeImage->ImageSize);
1279 if (ImageRecord == NULL) {
1280 DEBUG ((EFI_D_ERROR, "!!!!!!!! ImageRecord not found !!!!!!!!\n"));
1281 return ;
1282 }
1283
1284 CodeSegmentListHead = &ImageRecord->CodeSegmentList;
1285 while (!IsListEmpty (CodeSegmentListHead)) {
1286 ImageRecordCodeSection = CR (
1287 CodeSegmentListHead->ForwardLink,
1288 IMAGE_PROPERTIES_RECORD_CODE_SECTION,
1289 Link,
1290 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
1291 );
1292 RemoveEntryList (&ImageRecordCodeSection->Link);
1293 FreePool (ImageRecordCodeSection);
1294 }
1295
1296 RemoveEntryList (&ImageRecord->Link);
1297 FreePool (ImageRecord);
1298 mImagePropertiesPrivateData.ImageRecordCount--;
1299 }
1300
1301
1302 /**
1303 Install PropertiesTable.
1304
1305 @param[in] Event The Event this notify function registered to.
1306 @param[in] Context Pointer to the context data registered to the Event.
1307 **/
1308 VOID
1309 EFIAPI
1310 InstallPropertiesTable (
1311 EFI_EVENT Event,
1312 VOID *Context
1313 )
1314 {
1315 if (PcdGetBool (PcdPropertiesTableEnable)) {
1316 EFI_STATUS Status;
1317
1318 Status = gBS->InstallConfigurationTable (&gEfiPropertiesTableGuid, &mPropertiesTable);
1319 ASSERT_EFI_ERROR (Status);
1320
1321 DEBUG ((EFI_D_INFO, "MemoryProtectionAttribute - 0x%016lx\n", mPropertiesTable.MemoryProtectionAttribute));
1322 if ((mPropertiesTable.MemoryProtectionAttribute & EFI_PROPERTIES_RUNTIME_MEMORY_PROTECTION_NON_EXECUTABLE_PE_DATA) == 0) {
1323 DEBUG ((EFI_D_ERROR, "MemoryProtectionAttribute NON_EXECUTABLE_PE_DATA is not set, "));
1324 DEBUG ((EFI_D_ERROR, "because Runtime Driver Section Alignment is not %dK.\n", EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT >> 10));
1325 return ;
1326 }
1327
1328 gBS->GetMemoryMap = CoreGetMemoryMapPropertiesTable;
1329 gBS->Hdr.CRC32 = 0;
1330 gBS->CalculateCrc32 ((UINT8 *)gBS, gBS->Hdr.HeaderSize, &gBS->Hdr.CRC32);
1331
1332 DEBUG ((EFI_D_VERBOSE, "Total Image Count - 0x%x\n", mImagePropertiesPrivateData.ImageRecordCount));
1333 DEBUG ((EFI_D_VERBOSE, "Dump ImageRecord:\n"));
1334 DumpImageRecord ();
1335 }
1336 }
1337
1338 /**
1339 Initialize PropertiesTable support.
1340 **/
1341 VOID
1342 EFIAPI
1343 CoreInitializePropertiesTable (
1344 VOID
1345 )
1346 {
1347 EFI_STATUS Status;
1348 EFI_EVENT EndOfDxeEvent;
1349
1350 Status = gBS->CreateEventEx (
1351 EVT_NOTIFY_SIGNAL,
1352 TPL_NOTIFY,
1353 InstallPropertiesTable,
1354 NULL,
1355 &gEfiEndOfDxeEventGroupGuid,
1356 &EndOfDxeEvent
1357 );
1358 ASSERT_EFI_ERROR (Status);
1359 return ;
1360 }