TianoCore EDK2 master
Loading...
Searching...
No Matches
ImagePropertiesRecordLib.c
Go to the documentation of this file.
1
11#include <PiDxe.h>
12
13#include <Library/BaseLib.h>
15#include <Library/DebugLib.h>
19
20#define PREVIOUS_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
21 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) - (Size)))
22
23#define NEXT_MEMORY_DESCRIPTOR(MemoryDescriptor, Size) \
24 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)(MemoryDescriptor) + (Size)))
25
36UINT64
38 IN UINT64 Pages
39 )
40{
41 return LShiftU64 (Pages, EFI_PAGE_SHIFT);
42}
43
55UINT64
57 IN UINT64 Size
58 )
59{
60 return RShiftU64 (Size, EFI_PAGE_SHIFT) + ((((UINTN)Size) & EFI_PAGE_MASK) ? 1 : 0);
61}
62
71VOID
73 IMAGE_PROPERTIES_RECORD *ImageRecord
74 )
75{
76 LIST_ENTRY *CodeSegmentListHead;
77 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
78
79 if (ImageRecord == NULL) {
80 return;
81 }
82
83 CodeSegmentListHead = &ImageRecord->CodeSegmentList;
84 while (!IsListEmpty (CodeSegmentListHead)) {
85 ImageRecordCodeSection = CR (
86 CodeSegmentListHead->ForwardLink,
88 Link,
89 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
90 );
91 RemoveEntryList (&ImageRecordCodeSection->Link);
92 FreePool (ImageRecordCodeSection);
93 }
94}
95
104STATIC
105VOID
107 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
108 IN UINTN MemoryMapSize,
109 IN UINTN DescriptorSize
110 )
111{
112 EFI_MEMORY_DESCRIPTOR *MemoryMapEntry;
113 EFI_MEMORY_DESCRIPTOR *NextMemoryMapEntry;
114 EFI_MEMORY_DESCRIPTOR *MemoryMapEnd;
115 EFI_MEMORY_DESCRIPTOR TempMemoryMap;
116
117 MemoryMapEntry = MemoryMap;
118 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
119 MemoryMapEnd = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + MemoryMapSize);
120 while (MemoryMapEntry < MemoryMapEnd) {
121 while (NextMemoryMapEntry < MemoryMapEnd) {
122 if (MemoryMapEntry->PhysicalStart > NextMemoryMapEntry->PhysicalStart) {
123 CopyMem (&TempMemoryMap, MemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
124 CopyMem (MemoryMapEntry, NextMemoryMapEntry, sizeof (EFI_MEMORY_DESCRIPTOR));
125 CopyMem (NextMemoryMapEntry, &TempMemoryMap, sizeof (EFI_MEMORY_DESCRIPTOR));
126 }
127
128 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (NextMemoryMapEntry, DescriptorSize);
129 }
130
131 MemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
132 NextMemoryMapEntry = NEXT_MEMORY_DESCRIPTOR (MemoryMapEntry, DescriptorSize);
133 }
134
135 return;
136}
137
148STATIC
152 IN UINT64 Length,
153 IN LIST_ENTRY *ImageRecordList
154 )
155{
156 IMAGE_PROPERTIES_RECORD *ImageRecord;
157 LIST_ENTRY *ImageRecordLink;
158
159 for (ImageRecordLink = ImageRecordList->ForwardLink;
160 ImageRecordLink != ImageRecordList;
161 ImageRecordLink = ImageRecordLink->ForwardLink)
162 {
163 ImageRecord = CR (
164 ImageRecordLink,
166 Link,
167 IMAGE_PROPERTIES_RECORD_SIGNATURE
168 );
169
170 if ((Buffer <= ImageRecord->ImageBase) &&
171 (Buffer + Length >= ImageRecord->ImageBase + ImageRecord->ImageSize))
172 {
173 return ImageRecord;
174 }
175 }
176
177 return NULL;
178}
179
195STATIC
196UINTN
198 IN IMAGE_PROPERTIES_RECORD *ImageRecord,
199 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,
200 IN EFI_MEMORY_DESCRIPTOR *OldRecord,
201 IN UINTN DescriptorSize
202 )
203{
204 EFI_MEMORY_DESCRIPTOR TempRecord;
205 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
206 LIST_ENTRY *ImageRecordCodeSectionLink;
207 LIST_ENTRY *ImageRecordCodeSectionEndLink;
208 LIST_ENTRY *ImageRecordCodeSectionList;
209 UINTN NewRecordCount;
210 UINT64 PhysicalEnd;
211 UINT64 ImageEnd;
212
213 CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
214 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
215 NewRecordCount = 0;
216
217 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
218
219 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
220 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
221 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
222 ImageRecordCodeSection = CR (
223 ImageRecordCodeSectionLink,
225 Link,
226 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
227 );
228 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
229
230 if (TempRecord.PhysicalStart <= ImageRecordCodeSection->CodeSegmentBase) {
231 //
232 // DATA
233 //
234 NewRecord->Type = TempRecord.Type;
235 NewRecord->PhysicalStart = TempRecord.PhysicalStart;
236 NewRecord->VirtualStart = 0;
237 NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentBase - NewRecord->PhysicalStart);
238 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;
239 if (NewRecord->NumberOfPages != 0) {
240 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
241 NewRecordCount++;
242 }
243
244 //
245 // CODE
246 //
247 NewRecord->Type = TempRecord.Type;
248 NewRecord->PhysicalStart = ImageRecordCodeSection->CodeSegmentBase;
249 NewRecord->VirtualStart = 0;
250 NewRecord->NumberOfPages = EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize);
251 NewRecord->Attribute = (TempRecord.Attribute & (~EFI_MEMORY_XP)) | EFI_MEMORY_RO;
252 if (NewRecord->NumberOfPages != 0) {
253 NewRecord = NEXT_MEMORY_DESCRIPTOR (NewRecord, DescriptorSize);
254 NewRecordCount++;
255 }
256
257 TempRecord.PhysicalStart = ImageRecordCodeSection->CodeSegmentBase + EfiPagesToSize (EfiSizeToPages (ImageRecordCodeSection->CodeSegmentSize));
258 TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - TempRecord.PhysicalStart);
259 if (TempRecord.NumberOfPages == 0) {
260 break;
261 }
262 }
263 }
264
265 ImageEnd = ImageRecord->ImageBase + ImageRecord->ImageSize;
266
267 //
268 // Final DATA
269 //
270 if (TempRecord.PhysicalStart < ImageEnd) {
271 NewRecord->Type = TempRecord.Type;
272 NewRecord->PhysicalStart = TempRecord.PhysicalStart;
273 NewRecord->VirtualStart = 0;
274 NewRecord->NumberOfPages = EfiSizeToPages (ImageEnd - TempRecord.PhysicalStart);
275 NewRecord->Attribute = TempRecord.Attribute | EFI_MEMORY_XP;
276 NewRecordCount++;
277 }
278
279 return NewRecordCount;
280}
281
294STATIC
295UINTN
297 IN EFI_MEMORY_DESCRIPTOR *OldRecord,
298 IN LIST_ENTRY *ImageRecordList
299 )
300{
301 IMAGE_PROPERTIES_RECORD *ImageRecord;
302 UINTN SplitRecordCount;
303 UINT64 PhysicalStart;
304 UINT64 PhysicalEnd;
305
306 SplitRecordCount = 0;
307 PhysicalStart = OldRecord->PhysicalStart;
308 PhysicalEnd = OldRecord->PhysicalStart + EfiPagesToSize (OldRecord->NumberOfPages);
309
310 do {
311 ImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
312 if (ImageRecord == NULL) {
313 break;
314 }
315
316 SplitRecordCount += (2 * ImageRecord->CodeSegmentCount + 3);
317 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
318 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
319
320 if (SplitRecordCount != 0) {
321 SplitRecordCount--;
322 }
323
324 return SplitRecordCount;
325}
326
343STATIC
344UINTN
346 IN EFI_MEMORY_DESCRIPTOR *OldRecord,
347 IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord,
348 IN UINTN MaxSplitRecordCount,
349 IN UINTN DescriptorSize,
350 IN LIST_ENTRY *ImageRecordList
351 )
352{
353 EFI_MEMORY_DESCRIPTOR TempRecord;
354 IMAGE_PROPERTIES_RECORD *ImageRecord;
355 IMAGE_PROPERTIES_RECORD *NewImageRecord;
356 UINT64 PhysicalStart;
357 UINT64 PhysicalEnd;
358 UINTN NewRecordCount;
359 UINTN TotalNewRecordCount;
360
361 if (MaxSplitRecordCount == 0) {
362 CopyMem (NewRecord, OldRecord, DescriptorSize);
363 return 0;
364 }
365
366 TotalNewRecordCount = 0;
367
368 //
369 // Override previous record
370 //
371 CopyMem (&TempRecord, OldRecord, sizeof (EFI_MEMORY_DESCRIPTOR));
372 PhysicalStart = TempRecord.PhysicalStart;
373 PhysicalEnd = TempRecord.PhysicalStart + EfiPagesToSize (TempRecord.NumberOfPages);
374
375 ImageRecord = NULL;
376 do {
377 NewImageRecord = GetImageRecordByAddress (PhysicalStart, PhysicalEnd - PhysicalStart, ImageRecordList);
378 if (NewImageRecord == NULL) {
379 //
380 // No more images cover this range, check if we've reached the end of the old descriptor. If not,
381 // add the remaining range to the new descriptor list.
382 //
383 if (PhysicalEnd > PhysicalStart) {
384 NewRecord->Type = TempRecord.Type;
385 NewRecord->PhysicalStart = PhysicalStart;
386 NewRecord->VirtualStart = 0;
387 NewRecord->NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
388 NewRecord->Attribute = TempRecord.Attribute;
389 TotalNewRecordCount++;
390 }
391
392 break;
393 }
394
395 ImageRecord = NewImageRecord;
396
397 //
398 // Update PhysicalStart to exclude the portion before the image buffer
399 //
400 if (TempRecord.PhysicalStart < ImageRecord->ImageBase) {
401 NewRecord->Type = TempRecord.Type;
402 NewRecord->PhysicalStart = TempRecord.PhysicalStart;
403 NewRecord->VirtualStart = 0;
404 NewRecord->NumberOfPages = EfiSizeToPages (ImageRecord->ImageBase - TempRecord.PhysicalStart);
405 NewRecord->Attribute = TempRecord.Attribute;
406 TotalNewRecordCount++;
407
408 PhysicalStart = ImageRecord->ImageBase;
409 TempRecord.PhysicalStart = PhysicalStart;
410 TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
411
412 NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + DescriptorSize);
413 }
414
415 //
416 // Set new record
417 //
418 NewRecordCount = SetNewRecord (ImageRecord, NewRecord, &TempRecord, DescriptorSize);
419 TotalNewRecordCount += NewRecordCount;
420 NewRecord = (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)NewRecord + NewRecordCount * DescriptorSize);
421
422 //
423 // Update PhysicalStart, in order to exclude the image buffer already splitted.
424 //
425 PhysicalStart = ImageRecord->ImageBase + ImageRecord->ImageSize;
426 TempRecord.PhysicalStart = PhysicalStart;
427 TempRecord.NumberOfPages = EfiSizeToPages (PhysicalEnd - PhysicalStart);
428 } while ((ImageRecord != NULL) && (PhysicalStart < PhysicalEnd));
429
430 //
431 // The logic in function SplitTable() ensures that TotalNewRecordCount will not be zero if the
432 // code reaches here.
433 //
434 ASSERT (TotalNewRecordCount != 0);
435 return TotalNewRecordCount - 1;
436}
437
480EFIAPI
482 IN OUT UINTN *MemoryMapSize,
483 IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap,
484 IN UINTN DescriptorSize,
485 IN LIST_ENTRY *ImageRecordList,
486 IN UINTN NumberOfAdditionalDescriptors
487 )
488{
489 INTN IndexOld;
490 INTN IndexNew;
491 INTN IndexNewStarting;
492 UINTN MaxSplitRecordCount;
493 UINTN RealSplitRecordCount;
494 UINTN TotalSkippedRecords;
495
496 if ((MemoryMapSize == NULL) || (MemoryMap == NULL) || (ImageRecordList == NULL)) {
497 return EFI_INVALID_PARAMETER;
498 }
499
500 TotalSkippedRecords = 0;
501 //
502 // Let old record point to end of valid MemoryMap buffer.
503 //
504 IndexOld = ((*MemoryMapSize) / DescriptorSize) - 1;
505 //
506 // Let new record point to end of full MemoryMap buffer.
507 //
508 IndexNew = ((*MemoryMapSize) / DescriptorSize) - 1 + NumberOfAdditionalDescriptors;
509 IndexNewStarting = IndexNew;
510 for ( ; IndexOld >= 0; IndexOld--) {
511 MaxSplitRecordCount = GetMaxSplitRecordCount ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize), ImageRecordList);
512 //
513 // Split this MemoryMap record
514 //
515 IndexNew -= MaxSplitRecordCount;
516 RealSplitRecordCount = SplitRecord (
517 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexOld * DescriptorSize),
518 (EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + IndexNew * DescriptorSize),
519 MaxSplitRecordCount,
520 DescriptorSize,
521 ImageRecordList
522 );
523
524 // If we didn't utilize all the extra allocated descriptor slots, set the physical address of the unused slots
525 // to MAX_ADDRESS so they are moved to the bottom of the list when sorting.
526 for ( ; RealSplitRecordCount < MaxSplitRecordCount; RealSplitRecordCount++) {
527 ((EFI_MEMORY_DESCRIPTOR *)((UINT8 *)MemoryMap + ((IndexNew + RealSplitRecordCount + 1) * DescriptorSize)))->PhysicalStart = MAX_ADDRESS;
528 TotalSkippedRecords++;
529 }
530
531 IndexNew--;
532 }
533
534 //
535 // Move all records to the beginning.
536 //
537 CopyMem (
538 MemoryMap,
539 (UINT8 *)MemoryMap + ((IndexNew + 1) * DescriptorSize),
540 (IndexNewStarting - IndexNew) * DescriptorSize
541 );
542
543 //
544 // Sort from low to high to filter out the MAX_ADDRESS records.
545 //
546 SortMemoryMap (MemoryMap, (IndexNewStarting - IndexNew) * DescriptorSize, DescriptorSize);
547
548 *MemoryMapSize = (IndexNewStarting - IndexNew - TotalSkippedRecords) * DescriptorSize;
549
550 return EFI_SUCCESS;
551}
552
563EFIAPI
565 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection,
566 IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection
567 )
568{
569 IMAGE_PROPERTIES_RECORD_CODE_SECTION TempImageRecordCodeSection;
570
571 if ((FirstImageRecordCodeSection == NULL) || (SecondImageRecordCodeSection == NULL)) {
572 return EFI_INVALID_PARAMETER;
573 }
574
575 TempImageRecordCodeSection.CodeSegmentBase = FirstImageRecordCodeSection->CodeSegmentBase;
576 TempImageRecordCodeSection.CodeSegmentSize = FirstImageRecordCodeSection->CodeSegmentSize;
577
578 FirstImageRecordCodeSection->CodeSegmentBase = SecondImageRecordCodeSection->CodeSegmentBase;
579 FirstImageRecordCodeSection->CodeSegmentSize = SecondImageRecordCodeSection->CodeSegmentSize;
580
581 SecondImageRecordCodeSection->CodeSegmentBase = TempImageRecordCodeSection.CodeSegmentBase;
582 SecondImageRecordCodeSection->CodeSegmentSize = TempImageRecordCodeSection.CodeSegmentSize;
583
584 return EFI_SUCCESS;
585}
586
597EFIAPI
599 IN IMAGE_PROPERTIES_RECORD *ImageRecord
600 )
601{
602 EFI_STATUS Status;
603 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
604 IMAGE_PROPERTIES_RECORD_CODE_SECTION *NextImageRecordCodeSection;
605 LIST_ENTRY *ImageRecordCodeSectionLink;
606 LIST_ENTRY *NextImageRecordCodeSectionLink;
607 LIST_ENTRY *ImageRecordCodeSectionEndLink;
608 LIST_ENTRY *ImageRecordCodeSectionList;
609
610 if (ImageRecord == NULL) {
611 return EFI_INVALID_PARAMETER;
612 }
613
614 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
615
616 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
617 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
618 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
619 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
620 ImageRecordCodeSection = CR (
621 ImageRecordCodeSectionLink,
623 Link,
624 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
625 );
626 while (NextImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
627 NextImageRecordCodeSection = CR (
628 NextImageRecordCodeSectionLink,
630 Link,
631 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
632 );
633 if (ImageRecordCodeSection->CodeSegmentBase > NextImageRecordCodeSection->CodeSegmentBase) {
634 Status = SwapImageRecordCodeSection (ImageRecordCodeSection, NextImageRecordCodeSection);
635 if (EFI_ERROR (Status)) {
636 ASSERT_EFI_ERROR (Status);
637 return EFI_ABORTED;
638 }
639 }
640
641 NextImageRecordCodeSectionLink = NextImageRecordCodeSectionLink->ForwardLink;
642 }
643
644 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
645 NextImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
646 }
647
648 return EFI_SUCCESS;
649}
650
662BOOLEAN
663EFIAPI
665 IN IMAGE_PROPERTIES_RECORD *ImageRecord
666 )
667{
668 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
669 IMAGE_PROPERTIES_RECORD_CODE_SECTION *LastImageRecordCodeSection;
670 LIST_ENTRY *ImageRecordCodeSectionLink;
671 LIST_ENTRY *ImageRecordCodeSectionEndLink;
672 LIST_ENTRY *ImageRecordCodeSectionList;
673
674 if (ImageRecord == NULL) {
675 return FALSE;
676 }
677
678 DEBUG ((DEBUG_VERBOSE, "ImageCode SegmentCount - 0x%x\n", ImageRecord->CodeSegmentCount));
679
680 ImageRecordCodeSectionList = &ImageRecord->CodeSegmentList;
681
682 ImageRecordCodeSectionLink = ImageRecordCodeSectionList->ForwardLink;
683 ImageRecordCodeSectionEndLink = ImageRecordCodeSectionList;
684 LastImageRecordCodeSection = NULL;
685 while (ImageRecordCodeSectionLink != ImageRecordCodeSectionEndLink) {
686 ImageRecordCodeSection = CR (
687 ImageRecordCodeSectionLink,
689 Link,
690 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
691 );
692 if (ImageRecordCodeSection->CodeSegmentSize == 0) {
693 return FALSE;
694 }
695
696 if (ImageRecordCodeSection->CodeSegmentBase < ImageRecord->ImageBase) {
697 return FALSE;
698 }
699
700 if (ImageRecordCodeSection->CodeSegmentBase >= MAX_ADDRESS - ImageRecordCodeSection->CodeSegmentSize) {
701 return FALSE;
702 }
703
704 if ((ImageRecordCodeSection->CodeSegmentBase + ImageRecordCodeSection->CodeSegmentSize) > (ImageRecord->ImageBase + ImageRecord->ImageSize)) {
705 return FALSE;
706 }
707
708 if (LastImageRecordCodeSection != NULL) {
709 if ((LastImageRecordCodeSection->CodeSegmentBase + LastImageRecordCodeSection->CodeSegmentSize) > ImageRecordCodeSection->CodeSegmentBase) {
710 return FALSE;
711 }
712 }
713
714 LastImageRecordCodeSection = ImageRecordCodeSection;
715 ImageRecordCodeSectionLink = ImageRecordCodeSectionLink->ForwardLink;
716 }
717
718 return TRUE;
719}
720
731EFIAPI
733 IN IMAGE_PROPERTIES_RECORD *FirstImageRecord,
734 IN IMAGE_PROPERTIES_RECORD *SecondImageRecord
735 )
736{
737 IMAGE_PROPERTIES_RECORD TempImageRecord;
738
739 if ((FirstImageRecord == NULL) || (SecondImageRecord == NULL)) {
740 return EFI_INVALID_PARAMETER;
741 }
742
743 TempImageRecord.ImageBase = FirstImageRecord->ImageBase;
744 TempImageRecord.ImageSize = FirstImageRecord->ImageSize;
745 TempImageRecord.CodeSegmentCount = FirstImageRecord->CodeSegmentCount;
746
747 FirstImageRecord->ImageBase = SecondImageRecord->ImageBase;
748 FirstImageRecord->ImageSize = SecondImageRecord->ImageSize;
749 FirstImageRecord->CodeSegmentCount = SecondImageRecord->CodeSegmentCount;
750
751 SecondImageRecord->ImageBase = TempImageRecord.ImageBase;
752 SecondImageRecord->ImageSize = TempImageRecord.ImageSize;
753 SecondImageRecord->CodeSegmentCount = TempImageRecord.CodeSegmentCount;
754
755 SwapListEntries (&FirstImageRecord->CodeSegmentList, &SecondImageRecord->CodeSegmentList);
756 return EFI_SUCCESS;
757}
758
769EFIAPI
771 IN LIST_ENTRY *ImageRecordList
772 )
773{
774 IMAGE_PROPERTIES_RECORD *ImageRecord;
775 IMAGE_PROPERTIES_RECORD *NextImageRecord;
776 LIST_ENTRY *ImageRecordLink;
777 LIST_ENTRY *NextImageRecordLink;
778 LIST_ENTRY *ImageRecordEndLink;
779 EFI_STATUS Status;
780
781 if (ImageRecordList == NULL) {
782 return EFI_INVALID_PARAMETER;
783 }
784
785 ImageRecordLink = ImageRecordList->ForwardLink;
786 NextImageRecordLink = ImageRecordLink->ForwardLink;
787 ImageRecordEndLink = ImageRecordList;
788 while (ImageRecordLink != ImageRecordEndLink) {
789 ImageRecord = CR (
790 ImageRecordLink,
792 Link,
793 IMAGE_PROPERTIES_RECORD_SIGNATURE
794 );
795 while (NextImageRecordLink != ImageRecordEndLink) {
796 NextImageRecord = CR (
797 NextImageRecordLink,
799 Link,
800 IMAGE_PROPERTIES_RECORD_SIGNATURE
801
802 );
803 if (ImageRecord->ImageBase > NextImageRecord->ImageBase) {
804 Status = SwapImageRecord (ImageRecord, NextImageRecord);
805 if (EFI_ERROR (Status)) {
806 ASSERT_EFI_ERROR (Status);
807 return EFI_ABORTED;
808 }
809 }
810
811 NextImageRecordLink = NextImageRecordLink->ForwardLink;
812 }
813
814 ImageRecordLink = ImageRecordLink->ForwardLink;
815 NextImageRecordLink = ImageRecordLink->ForwardLink;
816 }
817
818 return EFI_SUCCESS;
819}
820
828STATIC
829VOID
831 IN CHAR8 *PdbPointer,
832 OUT CHAR8 *EfiFileName,
833 IN UINTN EfiFileNameSize
834 )
835{
836 UINTN Index;
837 UINTN StartIndex;
838
839 if ((PdbPointer == NULL) || (EfiFileNameSize < 5)) {
840 return;
841 }
842
843 // Print Module Name by Pdb file path.
844 StartIndex = 0;
845 for (Index = 0; PdbPointer[Index] != 0; Index++) {
846 if ((PdbPointer[Index] == '\\') || (PdbPointer[Index] == '/')) {
847 StartIndex = Index + 1;
848 }
849 }
850
851 // Copy the PDB file name to EfiFileName and replace .pdb with .efi
852 for (Index = 0; Index < EfiFileNameSize - 4; Index++) {
853 EfiFileName[Index] = PdbPointer[Index + StartIndex];
854 if (EfiFileName[Index] == 0) {
855 EfiFileName[Index] = '.';
856 }
857
858 if (EfiFileName[Index] == '.') {
859 EfiFileName[Index + 1] = 'e';
860 EfiFileName[Index + 2] = 'f';
861 EfiFileName[Index + 3] = 'i';
862 EfiFileName[Index + 4] = 0;
863 break;
864 }
865 }
866
867 if (Index == sizeof (EfiFileName) - 4) {
868 EfiFileName[Index] = 0;
869 }
870}
871
877VOID
878EFIAPI
880 IN LIST_ENTRY *ImageRecordList
881 )
882{
883 LIST_ENTRY *ImageRecordLink;
884 IMAGE_PROPERTIES_RECORD *CurrentImageRecord;
885 LIST_ENTRY *CodeSectionLink;
886 IMAGE_PROPERTIES_RECORD_CODE_SECTION *CurrentCodeSection;
887 CHAR8 *PdbPointer;
888 CHAR8 EfiFileName[256];
889
890 if (ImageRecordList == NULL) {
891 return;
892 }
893
894 ImageRecordLink = ImageRecordList->ForwardLink;
895
896 while (ImageRecordLink != ImageRecordList) {
897 CurrentImageRecord = CR (
898 ImageRecordLink,
900 Link,
901 IMAGE_PROPERTIES_RECORD_SIGNATURE
902 );
903
904 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)CurrentImageRecord->ImageBase);
905 if (PdbPointer != NULL) {
906 GetFilename (PdbPointer, EfiFileName, sizeof (EfiFileName));
907 DEBUG ((
908 DEBUG_INFO,
909 "%a: 0x%llx - 0x%llx\n",
910 EfiFileName,
911 CurrentImageRecord->ImageBase,
912 CurrentImageRecord->ImageBase + CurrentImageRecord->ImageSize
913 ));
914 } else {
915 DEBUG ((
916 DEBUG_INFO,
917 "Unknown Image: 0x%llx - 0x%llx\n",
918 CurrentImageRecord->ImageBase,
919 CurrentImageRecord->ImageBase + CurrentImageRecord->ImageSize
920 ));
921 }
922
923 CodeSectionLink = CurrentImageRecord->CodeSegmentList.ForwardLink;
924
925 while (CodeSectionLink != &CurrentImageRecord->CodeSegmentList) {
926 CurrentCodeSection = CR (
927 CodeSectionLink,
929 Link,
930 IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE
931 );
932
933 DEBUG ((
934 DEBUG_INFO,
935 " Code Section: 0x%llx - 0x%llx\n",
936 CurrentCodeSection->CodeSegmentBase,
937 CurrentCodeSection->CodeSegmentBase + CurrentCodeSection->CodeSegmentSize
938 ));
939
940 CodeSectionLink = CodeSectionLink->ForwardLink;
941 }
942
943 ImageRecordLink = ImageRecordLink->ForwardLink;
944 }
945}
946
959EFIAPI
961 IN EFI_PHYSICAL_ADDRESS ImageBase,
962 IN UINT64 ImageSize,
963 IN LIST_ENTRY *ImageRecordList
964 )
965{
966 IMAGE_PROPERTIES_RECORD *ImageRecord;
967 LIST_ENTRY *ImageRecordLink;
968
969 if (ImageRecordList == NULL) {
970 return NULL;
971 }
972
973 for (ImageRecordLink = ImageRecordList->ForwardLink;
974 ImageRecordLink != ImageRecordList;
975 ImageRecordLink = ImageRecordLink->ForwardLink)
976 {
977 ImageRecord = CR (
978 ImageRecordLink,
980 Link,
981 IMAGE_PROPERTIES_RECORD_SIGNATURE
982 );
983
984 if ((ImageBase == ImageRecord->ImageBase) &&
985 (ImageSize == ImageRecord->ImageSize))
986 {
987 return ImageRecord;
988 }
989 }
990
991 return NULL;
992}
993
1012EFIAPI
1014 IN CONST VOID *ImageBase,
1015 IN CONST UINT64 ImageSize,
1016 IN CONST UINT32 *RequiredAlignment OPTIONAL,
1017 OUT IMAGE_PROPERTIES_RECORD *ImageRecord
1018 )
1019{
1020 EFI_STATUS Status;
1021 EFI_IMAGE_DOS_HEADER *DosHdr;
1023 EFI_IMAGE_SECTION_HEADER *Section;
1024 IMAGE_PROPERTIES_RECORD_CODE_SECTION *ImageRecordCodeSection;
1025 UINTN Index;
1026 UINT8 *Name;
1027 UINT32 SectionAlignment;
1028 UINT32 PeCoffHeaderOffset;
1029 CHAR8 *PdbPointer;
1030
1031 if ((ImageRecord == NULL) || (ImageBase == NULL)) {
1032 return EFI_INVALID_PARAMETER;
1033 }
1034
1035 DEBUG ((
1036 DEBUG_VERBOSE,
1037 "Creating Image Properties Record: 0x%016lx - 0x%016lx\n",
1038 (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBase,
1039 ImageSize
1040 ));
1041
1042 //
1043 // Step 1: record whole region
1044 //
1045 Status = EFI_SUCCESS;
1046 ImageRecord->Signature = IMAGE_PROPERTIES_RECORD_SIGNATURE;
1047 ImageRecord->ImageBase = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBase;
1048 ImageRecord->ImageSize = ImageSize;
1049 ImageRecord->CodeSegmentCount = 0;
1050 InitializeListHead (&ImageRecord->Link);
1051 InitializeListHead (&ImageRecord->CodeSegmentList);
1052
1053 PdbPointer = PeCoffLoaderGetPdbPointer ((VOID *)(UINTN)ImageBase);
1054 if (PdbPointer != NULL) {
1055 DEBUG ((DEBUG_VERBOSE, " Image - %a\n", PdbPointer));
1056 }
1057
1058 // Check PE/COFF image
1059 DosHdr = (EFI_IMAGE_DOS_HEADER *)(UINTN)ImageBase;
1060 PeCoffHeaderOffset = 0;
1061 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
1062 PeCoffHeaderOffset = DosHdr->e_lfanew;
1063 }
1064
1065 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINT8 *)(UINTN)ImageBase + PeCoffHeaderOffset);
1066 if (Hdr.Pe32->Signature != EFI_IMAGE_NT_SIGNATURE) {
1067 DEBUG ((DEBUG_VERBOSE, "Hdr.Pe32->Signature invalid - 0x%x\n", Hdr.Pe32->Signature));
1068 return EFI_INVALID_PARAMETER;
1069 }
1070
1071 // Get SectionAlignment
1072 if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1073 SectionAlignment = Hdr.Pe32->OptionalHeader.SectionAlignment;
1074 } else {
1075 SectionAlignment = Hdr.Pe32Plus->OptionalHeader.SectionAlignment;
1076 }
1077
1078 // Check RequiredAlignment
1079 if ((RequiredAlignment != NULL) && ((SectionAlignment & (*RequiredAlignment - 1)) != 0)) {
1080 DEBUG ((
1081 DEBUG_WARN,
1082 "!!!!!!!! Image Section Alignment(0x%x) does not match Required Alignment (0x%x) !!!!!!!!\n",
1083 SectionAlignment,
1084 *RequiredAlignment
1085 ));
1086
1087 return EFI_ABORTED;
1088 }
1089
1090 Section = (EFI_IMAGE_SECTION_HEADER *)(
1091 (UINT8 *)(UINTN)ImageBase +
1092 PeCoffHeaderOffset +
1093 sizeof (UINT32) +
1094 sizeof (EFI_IMAGE_FILE_HEADER) +
1095 Hdr.Pe32->FileHeader.SizeOfOptionalHeader
1096 );
1097 for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
1098 Name = Section[Index].Name;
1099 DEBUG ((
1100 DEBUG_VERBOSE,
1101 " Section - '%c%c%c%c%c%c%c%c'\n",
1102 Name[0],
1103 Name[1],
1104 Name[2],
1105 Name[3],
1106 Name[4],
1107 Name[5],
1108 Name[6],
1109 Name[7]
1110 ));
1111
1112 if ((Section[Index].Characteristics & EFI_IMAGE_SCN_CNT_CODE) != 0) {
1113 DEBUG ((DEBUG_VERBOSE, " VirtualSize - 0x%08x\n", Section[Index].Misc.VirtualSize));
1114 DEBUG ((DEBUG_VERBOSE, " VirtualAddress - 0x%08x\n", Section[Index].VirtualAddress));
1115 DEBUG ((DEBUG_VERBOSE, " SizeOfRawData - 0x%08x\n", Section[Index].SizeOfRawData));
1116 DEBUG ((DEBUG_VERBOSE, " PointerToRawData - 0x%08x\n", Section[Index].PointerToRawData));
1117 DEBUG ((DEBUG_VERBOSE, " PointerToRelocations - 0x%08x\n", Section[Index].PointerToRelocations));
1118 DEBUG ((DEBUG_VERBOSE, " PointerToLinenumbers - 0x%08x\n", Section[Index].PointerToLinenumbers));
1119 DEBUG ((DEBUG_VERBOSE, " NumberOfRelocations - 0x%08x\n", Section[Index].NumberOfRelocations));
1120 DEBUG ((DEBUG_VERBOSE, " NumberOfLinenumbers - 0x%08x\n", Section[Index].NumberOfLinenumbers));
1121 DEBUG ((DEBUG_VERBOSE, " Characteristics - 0x%08x\n", Section[Index].Characteristics));
1122
1123 // Record code section(s)
1124 ImageRecordCodeSection = AllocatePool (sizeof (*ImageRecordCodeSection));
1125 if (ImageRecordCodeSection == NULL) {
1126 Status = EFI_OUT_OF_RESOURCES;
1127 goto CreateImagePropertiesRecordEnd;
1128 }
1129
1130 ImageRecordCodeSection->Signature = IMAGE_PROPERTIES_RECORD_CODE_SECTION_SIGNATURE;
1131
1132 ImageRecordCodeSection->CodeSegmentBase = (UINTN)ImageBase + Section[Index].VirtualAddress;
1133 // We still need to align the VirtualSize to the SectionAlignment because MSVC does not do
1134 // this when creating a PE image. It expects the loader to do this.
1135 ImageRecordCodeSection->CodeSegmentSize = ALIGN_VALUE (Section[Index].Misc.VirtualSize, SectionAlignment);
1136
1137 InsertTailList (&ImageRecord->CodeSegmentList, &ImageRecordCodeSection->Link);
1138 ImageRecord->CodeSegmentCount++;
1139 }
1140 }
1141
1142 if (ImageRecord->CodeSegmentCount > 0) {
1143 SortImageRecordCodeSection (ImageRecord);
1144 }
1145
1146 //
1147 // Check overlap all section in ImageBase/Size
1148 //
1149 if (!IsImageRecordCodeSectionValid (ImageRecord)) {
1150 DEBUG ((DEBUG_ERROR, "IsImageRecordCodeSectionValid - FAIL\n"));
1151 Status = EFI_INVALID_PARAMETER;
1152 goto CreateImagePropertiesRecordEnd;
1153 }
1154
1155 //
1156 // Round up the ImageSize, some CPU arch may return EFI_UNSUPPORTED if ImageSize is not aligned.
1157 // Given that the loader always allocates full pages, we know the space after the image is not used.
1158 //
1159 ImageRecord->ImageSize = ALIGN_VALUE (ImageRecord->ImageSize, EFI_PAGE_SIZE);
1160
1161CreateImagePropertiesRecordEnd:
1162 if (EFI_ERROR (Status)) {
1163 // we failed to create a valid record, free the section memory that was allocated
1164 FreeImageRecordCodeSections (ImageRecord);
1165 }
1166
1167 return Status;
1168}
1169
1177VOID
1178EFIAPI
1180 IN IMAGE_PROPERTIES_RECORD *ImageRecord
1181 )
1182{
1183 FreeImageRecordCodeSections (ImageRecord);
1184
1185 if (!IsListEmpty (&ImageRecord->Link)) {
1186 RemoveEntryList (&ImageRecord->Link);
1187 }
1188
1189 FreePool (ImageRecord);
1190}
UINT64 UINTN
INT64 INTN
#define MAX_ADDRESS
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI SwapListEntries(IN OUT LIST_ENTRY *FirstEntry, IN OUT LIST_ENTRY *SecondEntry)
Definition: LinkedList.c:522
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
UINT64 EFIAPI RShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: RShiftU64.c:28
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS EFIAPI SwapImageRecord(IN IMAGE_PROPERTIES_RECORD *FirstImageRecord, IN IMAGE_PROPERTIES_RECORD *SecondImageRecord)
STATIC UINTN GetMaxSplitRecordCount(IN EFI_MEMORY_DESCRIPTOR *OldRecord, IN LIST_ENTRY *ImageRecordList)
EFI_STATUS EFIAPI SplitTable(IN OUT UINTN *MemoryMapSize, IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, IN UINTN DescriptorSize, IN LIST_ENTRY *ImageRecordList, IN UINTN NumberOfAdditionalDescriptors)
STATIC VOID FreeImageRecordCodeSections(IMAGE_PROPERTIES_RECORD *ImageRecord)
VOID EFIAPI DeleteImagePropertiesRecord(IN IMAGE_PROPERTIES_RECORD *ImageRecord)
EFI_STATUS EFIAPI CreateImagePropertiesRecord(IN CONST VOID *ImageBase, IN CONST UINT64 ImageSize, IN CONST UINT32 *RequiredAlignment OPTIONAL, OUT IMAGE_PROPERTIES_RECORD *ImageRecord)
EFI_STATUS EFIAPI SwapImageRecordCodeSection(IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *FirstImageRecordCodeSection, IN IMAGE_PROPERTIES_RECORD_CODE_SECTION *SecondImageRecordCodeSection)
STATIC IMAGE_PROPERTIES_RECORD * GetImageRecordByAddress(IN EFI_PHYSICAL_ADDRESS Buffer, IN UINT64 Length, IN LIST_ENTRY *ImageRecordList)
STATIC UINT64 EfiPagesToSize(IN UINT64 Pages)
BOOLEAN EFIAPI IsImageRecordCodeSectionValid(IN IMAGE_PROPERTIES_RECORD *ImageRecord)
STATIC UINTN SplitRecord(IN EFI_MEMORY_DESCRIPTOR *OldRecord, IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, IN UINTN MaxSplitRecordCount, IN UINTN DescriptorSize, IN LIST_ENTRY *ImageRecordList)
IMAGE_PROPERTIES_RECORD *EFIAPI FindImageRecord(IN EFI_PHYSICAL_ADDRESS ImageBase, IN UINT64 ImageSize, IN LIST_ENTRY *ImageRecordList)
STATIC UINTN SetNewRecord(IN IMAGE_PROPERTIES_RECORD *ImageRecord, IN OUT EFI_MEMORY_DESCRIPTOR *NewRecord, IN EFI_MEMORY_DESCRIPTOR *OldRecord, IN UINTN DescriptorSize)
STATIC VOID GetFilename(IN CHAR8 *PdbPointer, OUT CHAR8 *EfiFileName, IN UINTN EfiFileNameSize)
VOID EFIAPI DumpImageRecords(IN LIST_ENTRY *ImageRecordList)
STATIC UINT64 EfiSizeToPages(IN UINT64 Size)
STATIC VOID SortMemoryMap(IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, IN UINTN MemoryMapSize, IN UINTN DescriptorSize)
EFI_STATUS EFIAPI SortImageRecord(IN LIST_ENTRY *ImageRecordList)
EFI_STATUS EFIAPI SortImageRecordCodeSection(IN IMAGE_PROPERTIES_RECORD *ImageRecord)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define CR(Record, TYPE, Field, TestSignature)
Definition: DebugLib.h:659
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: PeImage.h:143
#define EFI_IMAGE_SCN_CNT_CODE
0x00000020
Definition: PeImage.h:320
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
UINT32 e_lfanew
File address of new exe header.
Definition: PeImage.h:76
UINT16 e_magic
Magic number.
Definition: PeImage.h:58
EFI_PHYSICAL_ADDRESS PhysicalStart
Definition: UefiSpec.h:155