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