]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/CCode/Source/PeiRebase/PeiRebaseExe.c
c234ccffaaed3173a04d676418a0a07893638953
[mirror_edk2.git] / Tools / CCode / Source / PeiRebase / PeiRebaseExe.c
1 /*++
2
3 Copyright (c) 1999-2006 Intel Corporation. All rights reserved
4 This program and the accompanying materials are licensed and made available
5 under the terms and conditions of the BSD License which accompanies this
6 distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12
13 Module Name:
14
15 PeiRebaseExe.c
16
17 Abstract:
18
19 This contains all code necessary to build the PeiRebase.exe utility.
20 This utility relies heavily on the PeiRebase DLL. Definitions for both
21 can be found in the PEI Rebase Utility Specification, review draft.
22
23 --*/
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include <Common/UefiBaseTypes.h>
30 #include <Common/FirmwareVolumeImageFormat.h>
31 #include <Common/FirmwareFileSystem.h>
32 #include <Library/PeCoffLib.h>
33
34 #include "CommonLib.h"
35 #include "ParseInf.h"
36 #include "FvLib.h"
37 #include "EfiUtilityMsgs.h"
38 #include "PeiRebaseExe.h"
39
40 EFI_STATUS
41 ReadHeader (
42 IN FILE *InputFile,
43 OUT UINT32 *FvSize,
44 OUT BOOLEAN *ErasePolarity
45 );
46
47 int
48 main (
49 int argc,
50 char **argv
51 )
52 /*++
53
54 Routine Description:
55
56 This utility relocates PEI XIP PE32s in a FV.
57
58 Arguments:
59
60 argc - Number of command line arguments
61 argv[]:
62 BaseAddress The base address to use for rebasing the FV. The correct
63 format is a hex number preceded by 0x.
64 InputFileName The name of the input FV file.
65 OutputFileName The name of the output FV file.
66
67 Arguments come in pair in any order.
68 -I InputFileName
69 -O OutputFileName
70 -B BaseAddress
71
72 Returns:
73
74 0 No error conditions detected.
75 1 One or more of the input parameters is invalid.
76 2 A resource required by the utility was unavailable.
77 Most commonly this will be memory allocation or file creation.
78 3 PeiRebase.dll could not be loaded.
79 4 Error executing the PEI rebase.
80
81 --*/
82 {
83 UINT8 Index;
84 CHAR8 InputFileName[_MAX_PATH];
85 CHAR8 *OutputFileName;
86 EFI_PHYSICAL_ADDRESS XipBase, BsBase, RtBase;
87 UINT32 BaseTypes;
88 EFI_STATUS Status;
89 FILE *InputFile;
90 FILE *OutputFile;
91 FILE *LogFile;
92 UINT64 FvOffset;
93 UINT32 FileCount;
94 int BytesRead;
95 EFI_FIRMWARE_VOLUME_HEADER *FvImage;
96 UINT32 FvSize;
97 EFI_FFS_FILE_HEADER *CurrentFile;
98 BOOLEAN ErasePolarity;
99 MEMORY_FILE InfMemoryFile;
100 CHAR8 StringBuffer[0x100];
101
102 ErasePolarity = FALSE;
103 //
104 // Set utility name for error/warning reporting purposes.
105 //
106 SetUtilityName (UTILITY_NAME);
107
108 if (argc == 1) {
109 Usage();
110 return STATUS_ERROR;
111 }
112
113 if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
114 (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
115 Usage();
116 return STATUS_ERROR;
117 }
118
119 if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
120 Version();
121 return STATUS_ERROR;
122 }
123
124 //
125 // Verify the correct number of arguments
126 //
127 if (argc != MAX_ARGS) {
128 Usage ();
129 return STATUS_ERROR;
130 }
131
132 //
133 // Initialize variables
134 //
135 InputFileName[0] = '\0';
136 OutputFileName = NULL;
137 XipBase = BsBase = RtBase = 0;
138 BaseTypes = 0;
139 FvOffset = 0;
140 FileCount = 0;
141 ErasePolarity = FALSE;
142 InputFile = NULL;
143 OutputFile = NULL;
144 LogFile = NULL;
145 FvImage = NULL;
146
147 //
148 // Parse the command line arguments
149 //
150 for (Index = 1; Index < MAX_ARGS; Index += 2) {
151 //
152 // Make sure argument pair begin with - or /
153 //
154 if (argv[Index][0] != '-' && argv[Index][0] != '/') {
155 Usage ();
156 Error (NULL, 0, 0, argv[Index], "unrecognized option");
157 return STATUS_ERROR;
158 }
159 //
160 // Make sure argument specifier is only one letter
161 //
162 if (argv[Index][2] != 0) {
163 Usage ();
164 Error (NULL, 0, 0, argv[Index], "unrecognized option");
165 return STATUS_ERROR;
166 }
167 //
168 // Determine argument to read
169 //
170 switch (argv[Index][1]) {
171 case 'I':
172 case 'i':
173 if (strlen (InputFileName) == 0) {
174 strcpy (InputFileName, argv[Index + 1]);
175 } else {
176 Usage ();
177 Error (NULL, 0, 0, argv[Index + 1], "only one -i InputFileName may be specified");
178 return STATUS_ERROR;
179 }
180 break;
181
182 case 'O':
183 case 'o':
184 if (OutputFileName == NULL) {
185 OutputFileName = argv[Index + 1];
186 } else {
187 Usage ();
188 Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified");
189 return STATUS_ERROR;
190 }
191 break;
192
193 case 'F':
194 case 'f':
195 //
196 // Load INF file into memory & initialize MEMORY_FILE structure
197 //
198 Status = GetFileImage (argv[Index + 1], &InfMemoryFile.FileImage, (UINT32*)&InfMemoryFile.Eof);
199 InfMemoryFile.Eof = InfMemoryFile.FileImage + (UINT32)(UINTN)InfMemoryFile.Eof;
200 InfMemoryFile.CurrentFilePointer = InfMemoryFile.FileImage;
201 if (EFI_ERROR (Status)) {
202 Error (NULL, 0, 0, argv[Index + 1], "Error opening FvInfFile");
203 return STATUS_ERROR;
204 }
205
206 //
207 // Read BaseAddress from fv.inf file
208 //
209 FindToken (&InfMemoryFile, "[options]", "EFI_BASE_ADDRESS", 0, StringBuffer);
210
211 //
212 // Free INF file image
213 //
214 free (InfMemoryFile.FileImage);
215
216 //
217 // Point argv[Index + 1] to StringBuffer so that it could be processed as "-b"
218 //
219 argv[Index + 1] = StringBuffer;
220
221 case 'B':
222 case 'b':
223 if (BaseTypes & 1) {
224 Usage ();
225 Error (NULL, 0, 0, argv[Index + 1], "XipBaseAddress may be specified only once by either -b or -f");
226 return STATUS_ERROR;
227 }
228
229 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &XipBase);
230 if (EFI_ERROR (Status)) {
231 Usage ();
232 Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for XIP base address");
233 return STATUS_ERROR;
234 }
235
236 BaseTypes |= 1;
237 break;
238
239 case 'D':
240 case 'd':
241 if (BaseTypes & 2) {
242 Usage ();
243 Error (NULL, 0, 0, argv[Index + 1], "-d BsBaseAddress may be specified only once");
244 return STATUS_ERROR;
245 }
246
247 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BsBase);
248 if (EFI_ERROR (Status)) {
249 Usage ();
250 Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for BS_DRIVER base address");
251 return STATUS_ERROR;
252 }
253
254 BaseTypes |= 2;
255 break;
256
257 case 'R':
258 case 'r':
259 if (BaseTypes & 4) {
260 Usage ();
261 Error (NULL, 0, 0, argv[Index + 1], "-r RtBaseAddress may be specified only once");
262 return STATUS_ERROR;
263 }
264
265 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &RtBase);
266 if (EFI_ERROR (Status)) {
267 Usage ();
268 Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for RT_DRIVER base address");
269 return STATUS_ERROR;
270 }
271
272 BaseTypes |= 4;
273 break;
274
275 default:
276 Usage ();
277 Error (NULL, 0, 0, argv[Index], "unrecognized argument");
278 return STATUS_ERROR;
279 break;
280 }
281 }
282 //
283 // Open the file containing the FV
284 //
285 InputFile = fopen (InputFileName, "rb");
286 if (InputFile == NULL) {
287 Error (NULL, 0, 0, InputFileName, "could not open input file for reading");
288 return STATUS_ERROR;
289 }
290
291 //
292 // Open the log file
293 //
294 strcat (InputFileName, ".log");
295 LogFile = fopen (InputFileName, "a");
296 if (LogFile == NULL) {
297 Error (NULL, 0, 0, InputFileName, "could not append to log file");
298 }
299
300 //
301 // Determine size of FV
302 //
303 Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);
304 if (EFI_ERROR (Status)) {
305 Error (NULL, 0, 0, "could not parse the FV header", NULL);
306 goto Finish;
307 }
308 //
309 // Allocate a buffer for the FV image
310 //
311 FvImage = malloc (FvSize);
312 if (FvImage == NULL) {
313 Error (NULL, 0, 0, "application error", "memory allocation failed");
314 goto Finish;
315 }
316 //
317 // Read the entire FV to the buffer
318 //
319 BytesRead = fread (FvImage, 1, FvSize, InputFile);
320 fclose (InputFile);
321 InputFile = NULL;
322 if ((unsigned int) BytesRead != FvSize) {
323 Error (NULL, 0, 0, InputFileName, "failed to read from file");
324 goto Finish;
325 }
326 //
327 // Prepare to walk the FV image
328 //
329 InitializeFvLib (FvImage, FvSize);
330 //
331 // Get the first file
332 //
333 Status = GetNextFile (NULL, &CurrentFile);
334 if (EFI_ERROR (Status)) {
335 Error (NULL, 0, 0, "cannot find the first file in the FV image", NULL);
336 goto Finish;
337 }
338 //
339 // Check if each file should be rebased
340 //
341 while (CurrentFile != NULL) {
342 //
343 // Rebase this file
344 //
345 FfsRebase (
346 CurrentFile,
347 BaseTypes,
348 XipBase + (UINTN)CurrentFile - (UINTN)FvImage,
349 &BsBase,
350 &RtBase,
351 LogFile
352 );
353
354 if (EFI_ERROR (Status)) {
355 switch (Status) {
356
357 case EFI_INVALID_PARAMETER:
358 Error (NULL, 0, 0, "invalid parameter passed to FfsRebase", NULL);
359 break;
360
361 case EFI_ABORTED:
362 Error (NULL, 0, 0, "error detected while rebasing -- aborted", NULL);
363 break;
364
365 case EFI_OUT_OF_RESOURCES:
366 Error (NULL, 0, 0, "FfsRebase could not allocate required resources", NULL);
367 break;
368
369 case EFI_NOT_FOUND:
370 Error (NULL, 0, 0, "FfsRebase could not locate a PE32 section", NULL);
371 break;
372
373 default:
374 Error (NULL, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status);
375 break;
376 }
377
378 goto Finish;
379 }
380 //
381 // Get the next file
382 //
383 Status = GetNextFile (CurrentFile, &CurrentFile);
384 if (EFI_ERROR (Status)) {
385 Error (NULL, 0, 0, "cannot find the next file in the FV image", NULL);
386 goto Finish;
387 }
388 }
389 //
390 // Open the output file
391 //
392 OutputFile = fopen (OutputFileName, "wb");
393 if (OutputFile == NULL) {
394 Error (NULL, 0, 0, OutputFileName, "failed to open output file");
395 goto Finish;
396 }
397
398 if (fwrite (FvImage, 1, FvSize, OutputFile) != FvSize) {
399 Error (NULL, 0, 0, "failed to write to output file", 0);
400 goto Finish;
401 }
402
403 Finish:
404 if (InputFile != NULL) {
405 fclose (InputFile);
406 }
407 //
408 // If we created an output file, and there was an error, remove it so
409 // subsequent builds will rebuild it.
410 //
411 if (OutputFile != NULL) {
412 if (GetUtilityStatus () == STATUS_ERROR) {
413 remove (OutputFileName);
414 }
415
416 fclose (OutputFile);
417 }
418
419 if (LogFile != NULL) {
420 fclose (LogFile);
421 }
422
423 if (FvImage != NULL) {
424 free (FvImage);
425 }
426
427 return GetUtilityStatus ();
428 }
429
430 EFI_STATUS
431 ReadHeader (
432 IN FILE *InputFile,
433 OUT UINT32 *FvSize,
434 OUT BOOLEAN *ErasePolarity
435 )
436 /*++
437
438 Routine Description:
439
440 This function determines the size of the FV and the erase polarity. The
441 erase polarity is the FALSE value for file state.
442
443 Arguments:
444
445 InputFile The file that contains the FV image.
446 FvSize The size of the FV.
447 ErasePolarity The FV erase polarity.
448
449 Returns:
450
451 EFI_SUCCESS Function completed successfully.
452 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
453 EFI_ABORTED The function encountered an error.
454
455 --*/
456 {
457 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
458 EFI_FV_BLOCK_MAP_ENTRY BlockMap;
459 UINTN Signature[2];
460 UINTN BytesRead;
461 UINT32 Size;
462
463 BytesRead = 0;
464 Size = 0;
465 //
466 // Check input parameters
467 //
468 if ((InputFile == NULL) || (FvSize == NULL) || (ErasePolarity == NULL)) {
469 Error (NULL, 0, 0, "ReadHeader()", "invalid input parameter");
470 return EFI_INVALID_PARAMETER;
471 }
472 //
473 // Read the header
474 //
475 fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
476 BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
477 Signature[0] = VolumeHeader.Signature;
478 Signature[1] = 0;
479
480 //
481 // Get erase polarity
482 //
483 if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {
484 *ErasePolarity = TRUE;
485 }
486
487 do {
488 fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
489 BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
490
491 if (BlockMap.NumBlocks != 0) {
492 Size += BlockMap.NumBlocks * BlockMap.BlockLength;
493 }
494
495 } while (!(BlockMap.NumBlocks == 0 && BlockMap.BlockLength == 0));
496
497 if (VolumeHeader.FvLength != Size) {
498 Error (NULL, 0, 0, "volume size not consistant with block maps", NULL);
499 return EFI_ABORTED;
500 }
501
502 *FvSize = Size;
503
504 rewind (InputFile);
505
506 return EFI_SUCCESS;
507 }
508
509 VOID
510 Version (
511 VOID
512 )
513 /*++
514
515 Routine Description:
516
517 Displays the standard utility information to SDTOUT
518
519 Arguments:
520
521 None
522
523 Returns:
524
525 None
526
527 --*/
528 {
529 printf ("%s v%d.%d -PEI Rebase Utility.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
530 printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
531 }
532
533 VOID
534 Usage (
535 VOID
536 )
537 /*++
538
539 Routine Description:
540
541 Displays the utility usage syntax to STDOUT
542
543 Arguments:
544
545 None
546
547 Returns:
548
549 None
550
551 --*/
552 {
553 Version();
554
555 printf (
556 "\nUsage: %s -I InputFileName -O OutputFileName -B BaseAddress\n",
557 UTILITY_NAME
558 );
559 printf (" Where:\n");
560 printf (" InputFileName is the name of the EFI FV file to rebase.\n");
561 printf (" OutputFileName is the desired output file name.\n");
562 printf (" BaseAddress is the FV base address to rebase agains.\n");
563 printf (" Argument pair may be in any order.\n");
564 }
565
566 EFI_STATUS
567 FfsRebase (
568 IN OUT EFI_FFS_FILE_HEADER *FfsFile,
569 IN UINT32 Flags,
570 IN OUT EFI_PHYSICAL_ADDRESS XipBase,
571 IN OUT EFI_PHYSICAL_ADDRESS *BsBase,
572 IN OUT EFI_PHYSICAL_ADDRESS *RtBase,
573 OUT FILE *LogFile
574 )
575 /*++
576
577 Routine Description:
578
579 This function determines if a file is XIP and should be rebased. It will
580 rebase any PE32 sections found in the file using the base address.
581
582 Arguments:
583
584 FfsFile A pointer to Ffs file image.
585 BaseAddress The base address to use for rebasing the file image.
586
587 Returns:
588
589 EFI_SUCCESS The image was properly rebased.
590 EFI_INVALID_PARAMETER An input parameter is invalid.
591 EFI_ABORTED An error occurred while rebasing the input file image.
592 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
593 EFI_NOT_FOUND No compressed sections could be found.
594
595 --*/
596 {
597 EFI_STATUS Status;
598 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
599 UINTN MemoryImagePointer;
600 UINTN MemoryImagePointerAligned;
601 EFI_PHYSICAL_ADDRESS ImageAddress;
602 UINT64 ImageSize;
603 EFI_PHYSICAL_ADDRESS EntryPoint;
604 UINT32 Pe32ImageSize;
605 EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;
606 UINTN Index;
607 EFI_FILE_SECTION_POINTER CurrentPe32Section;
608 EFI_FFS_FILE_STATE SavedState;
609 EFI_IMAGE_NT_HEADERS32 *PeHdr;
610 EFI_IMAGE_NT_HEADERS64 *PePlusHdr;
611 UINT32 *PeHdrSizeOfImage;
612 UINT32 *PeHdrChecksum;
613 EFI_TE_IMAGE_HEADER *TEImageHeader;
614 UINT8 *TEBuffer;
615 EFI_IMAGE_DOS_HEADER *DosHeader;
616 UINT8 FileGuidString[80];
617 UINT32 TailSize;
618 EFI_FFS_FILE_TAIL TailValue;
619 EFI_PHYSICAL_ADDRESS *BaseToUpdate;
620
621 //
622 // Verify input parameters
623 //
624 if (FfsFile == NULL) {
625 return EFI_INVALID_PARAMETER;
626 }
627 //
628 // Convert the GUID to a string so we can at least report which file
629 // if we find an error.
630 //
631 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
632 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
633 TailSize = sizeof (EFI_FFS_FILE_TAIL);
634 } else {
635 TailSize = 0;
636 }
637 //
638 // Do some cursory checks on the FFS file contents
639 //
640 Status = VerifyFfsFile (FfsFile);
641 if (EFI_ERROR (Status)) {
642 Error (NULL, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString);
643 return EFI_INVALID_PARAMETER;
644 }
645
646 //
647 // We only process files potentially containing PE32 sections.
648 //
649 switch (FfsFile->Type) {
650 case EFI_FV_FILETYPE_SECURITY_CORE:
651 case EFI_FV_FILETYPE_PEI_CORE:
652 case EFI_FV_FILETYPE_PEIM:
653 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
654 case EFI_FV_FILETYPE_DRIVER:
655 case EFI_FV_FILETYPE_DXE_CORE:
656 break;
657 default:
658 return EFI_SUCCESS;
659 }
660
661 //
662 // Rebase each PE32 section
663 //
664 Status = EFI_SUCCESS;
665 for (Index = 1;; Index++) {
666 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
667 if (EFI_ERROR (Status)) {
668 break;
669 }
670
671
672 //
673 // Initialize context
674 //
675 memset (&ImageContext, 0, sizeof (ImageContext));
676 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
677 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
678 Status = PeCoffLoaderGetImageInfo (&ImageContext);
679 if (EFI_ERROR (Status)) {
680 Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);
681 return Status;
682 }
683
684 //
685 // Calculate the PE32 base address, based on file type
686 //
687 switch (FfsFile->Type) {
688 case EFI_FV_FILETYPE_SECURITY_CORE:
689 case EFI_FV_FILETYPE_PEI_CORE:
690 case EFI_FV_FILETYPE_PEIM:
691 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
692 if ((Flags & 1) == 0) {
693 //
694 // We aren't relocating XIP code, so skip it.
695 //
696 return EFI_SUCCESS;
697 }
698
699 NewPe32BaseAddress =
700 XipBase +
701 (UINTN)CurrentPe32Section.Pe32Section +
702 sizeof (EFI_COMMON_SECTION_HEADER) -
703 (UINTN)FfsFile;
704 BaseToUpdate = &XipBase;
705 break;
706
707 case EFI_FV_FILETYPE_DRIVER:
708 PeHdr = (EFI_IMAGE_NT_HEADERS32*)(
709 (UINTN)CurrentPe32Section.Pe32Section +
710 sizeof (EFI_COMMON_SECTION_HEADER) +
711 ImageContext.PeCoffHeaderOffset
712 );
713 switch (PeHdr->OptionalHeader.Subsystem) {
714 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
715 if ((Flags & 4) == 0) {
716 //
717 // RT drivers aren't supposed to be relocated
718 //
719 continue;
720 }
721
722 NewPe32BaseAddress = *RtBase;
723 BaseToUpdate = RtBase;
724 break;
725
726 default:
727 //
728 // We treat all other subsystems the same as BS_DRIVER
729 //
730 if ((Flags & 2) == 0) {
731 //
732 // Skip all BS_DRIVER's
733 //
734 continue;
735 }
736
737 NewPe32BaseAddress = *BsBase;
738 BaseToUpdate = BsBase;
739 break;
740 }
741 break;
742
743 case EFI_FV_FILETYPE_DXE_CORE:
744 if ((Flags & 2) == 0) {
745 //
746 // Skip DXE core
747 //
748 return EFI_SUCCESS;
749 }
750
751 NewPe32BaseAddress = *BsBase;
752 BaseToUpdate = BsBase;
753 break;
754
755 default:
756 //
757 // Not supported file type
758 //
759 return EFI_SUCCESS;
760 }
761
762 //
763 // Allocate a buffer for the image to be loaded into.
764 //
765 Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION);
766 MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x100000));
767 if (MemoryImagePointer == 0) {
768 Error (NULL, 0, 0, "memory allocation failure", NULL);
769 return EFI_OUT_OF_RESOURCES;
770 }
771 memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x100000);
772 MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFFF) & (-1 << 16);
773
774 ImageContext.ImageAddress = MemoryImagePointerAligned;
775
776 Status = PeCoffLoaderLoadImage (&ImageContext);
777 if (EFI_ERROR (Status)) {
778 Error (NULL, 0, 0, "LoadImage() call failed on rebase", FileGuidString);
779 free ((VOID *) MemoryImagePointer);
780 return Status;
781 }
782
783 //
784 // Check if section-alignment and file-alignment match or not
785 //
786 if (!(ImageContext.IsTeImage)) {
787 PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext.ImageAddress +
788 ImageContext.PeCoffHeaderOffset);
789 if (PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment) {
790 Error (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileGuidString);
791 free ((VOID *) MemoryImagePointer);
792 return EFI_ABORTED;
793 }
794 }
795 else {
796 //
797 // BUGBUG: TE Image Header lack section-alignment and file-alignment info
798 //
799 }
800
801 ImageContext.DestinationAddress = NewPe32BaseAddress;
802 Status = PeCoffLoaderRelocateImage (&ImageContext);
803 if (EFI_ERROR (Status)) {
804 Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);
805 free ((VOID *) MemoryImagePointer);
806 return Status;
807 }
808
809 ImageAddress = ImageContext.ImageAddress;
810 ImageSize = ImageContext.ImageSize;
811 EntryPoint = ImageContext.EntryPoint;
812
813 if (ImageSize > Pe32ImageSize) {
814 Error (
815 NULL,
816 0,
817 0,
818 "rebased image is larger than original PE32 image",
819 "0x%X > 0x%X, file %s",
820 ImageSize,
821 Pe32ImageSize,
822 FileGuidString
823 );
824 free ((VOID *) MemoryImagePointer);
825 return EFI_ABORTED;
826 }
827
828 //
829 // Update BASE address
830 //
831 fprintf (
832 LogFile,
833 "%s %016I64X %s\n",
834 FileGuidString,
835 ImageContext.DestinationAddress,
836 ImageContext.PdbPointer == NULL ? "*" : ImageContext.PdbPointer
837 );
838 *BaseToUpdate += EFI_SIZE_TO_PAGES (ImageContext.ImageSize) * EFI_PAGE_SIZE;
839
840 //
841 // Since we may have updated the Codeview RVA, we need to insure the PE
842 // header indicates the image is large enough to contain the Codeview data
843 // so it will be loaded properly later if the PEIM is reloaded into memory...
844 //
845 PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);
846 PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;
847 if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
848 PeHdrSizeOfImage = (UINT32 *) (&(PeHdr->OptionalHeader).SizeOfImage);
849 PeHdrChecksum = (UINT32 *) (&(PeHdr->OptionalHeader).CheckSum);
850 } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
851 PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);
852 PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);
853 } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
854 PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);
855 PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);
856 } else {
857 Error (
858 NULL,
859 0,
860 0,
861 "unknown machine type in PE32 image",
862 "machine type=0x%X, file=%s",
863 (UINT32) PeHdr->FileHeader.Machine,
864 FileGuidString
865 );
866 free ((VOID *) MemoryImagePointer);
867 return EFI_ABORTED;
868 }
869
870 if (*PeHdrSizeOfImage != ImageContext.ImageSize) {
871 *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;
872 if (*PeHdrChecksum) {
873 *PeHdrChecksum = 0;
874 }
875 }
876
877 memcpy (CurrentPe32Section.Pe32Section + 1, (VOID *) MemoryImagePointerAligned, (UINT32) ImageSize);
878
879 free ((VOID *) MemoryImagePointer);
880
881 //
882 // Now update file checksum
883 //
884 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
885 TailSize = sizeof (EFI_FFS_FILE_TAIL);
886 } else {
887 TailSize = 0;
888 }
889
890 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
891 SavedState = FfsFile->State;
892 FfsFile->IntegrityCheck.Checksum.File = 0;
893 FfsFile->State = 0;
894 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
895 FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
896 (UINT8 *) FfsFile,
897 GetLength (FfsFile->Size) - TailSize
898 );
899 } else {
900 FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
901 }
902
903 FfsFile->State = SavedState;
904 }
905 //
906 // Update tail if present
907 //
908 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
909 TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
910 *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
911 }
912 }
913
914 if ((Flags & 1) == 0 || (
915 FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
916 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
917
918 FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
919 FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
920 )) {
921 //
922 // Only XIP code may have a TE section
923 //
924 return EFI_SUCCESS;
925 }
926
927 //
928 // Now process TE sections
929 //
930 for (Index = 1;; Index++) {
931 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
932 if (EFI_ERROR (Status)) {
933 break;
934 }
935
936 //
937 // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
938 // by GenTEImage
939 //
940 TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
941
942 NewPe32BaseAddress = ((UINT32) XipBase) +
943 (
944 (UINTN) CurrentPe32Section.Pe32Section +
945 sizeof (EFI_COMMON_SECTION_HEADER) +
946 sizeof (EFI_TE_IMAGE_HEADER) -
947 TEImageHeader->StrippedSize -
948 (UINTN) FfsFile
949 );
950
951 //
952 // Allocate a buffer to unshrink the image into.
953 //
954 Pe32ImageSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
955 sizeof (EFI_TE_IMAGE_HEADER);
956 Pe32ImageSize += TEImageHeader->StrippedSize;
957 TEBuffer = (UINT8 *) malloc (Pe32ImageSize);
958 if (TEBuffer == NULL) {
959 Error (NULL, 0, 0, "failed to allocate memory", NULL);
960 return EFI_OUT_OF_RESOURCES;
961 }
962 //
963 // Expand the image into our buffer and fill in critical fields in the DOS header
964 // Fill in fields required by the loader.
965 // At offset 0x3C is the offset to the PE signature. We'll put it immediately following the offset value
966 // itself.
967 //
968 memset (TEBuffer, 0, Pe32ImageSize);
969 DosHeader = (EFI_IMAGE_DOS_HEADER *) TEBuffer;
970 DosHeader->e_magic = EFI_IMAGE_DOS_SIGNATURE;
971 *(UINT32 *) (TEBuffer + 0x3C) = 0x40;
972 PeHdr = (EFI_IMAGE_NT_HEADERS *) (TEBuffer + 0x40);
973 PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;
974 PeHdr->Signature = EFI_IMAGE_NT_SIGNATURE;
975 PeHdr->FileHeader.Machine = TEImageHeader->Machine;
976 PeHdr->FileHeader.NumberOfSections = TEImageHeader->NumberOfSections;
977
978 //
979 // Say the size of the optional header is the total we stripped off less the size of a PE file header and PE signature and
980 // the 0x40 bytes for our DOS header.
981 //
982 PeHdr->FileHeader.SizeOfOptionalHeader = (UINT16) (TEImageHeader->StrippedSize - 0x40 - sizeof (UINT32) - sizeof (EFI_IMAGE_FILE_HEADER));
983 if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA32) {
984 PeHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
985 } else if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_IA64) {
986 PePlusHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
987 } else if (TEImageHeader->Machine == EFI_IMAGE_MACHINE_X64) {
988 PePlusHdr->OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
989 } else {
990 Error (
991 NULL,
992 0,
993 0,
994 "unknown machine type in TE image",
995 "machine type=0x%X, file=%s",
996 (UINT32) TEImageHeader->Machine,
997 FileGuidString
998 );
999 free (TEBuffer);
1000 return EFI_ABORTED;
1001 }
1002
1003 if (PeHdr->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
1004 PeHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));
1005 PeHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;
1006 PeHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;
1007 PeHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *
1008 sizeof (EFI_IMAGE_SECTION_HEADER) - 12;
1009
1010 //
1011 // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image
1012 //
1013 if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||
1014 (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)
1015 ) {
1016 PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;
1017 PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
1018 PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1019 }
1020
1021 if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||
1022 (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)
1023 ) {
1024 PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
1025 PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
1026 if (PeHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {
1027 PeHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;
1028 }
1029 }
1030 //
1031 // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility
1032 //
1033 PeHdr->OptionalHeader.SectionAlignment = 0x10;
1034 } else {
1035 PePlusHdr->OptionalHeader.ImageBase = (UINTN) (TEImageHeader->ImageBase - TEImageHeader->StrippedSize + sizeof (EFI_TE_IMAGE_HEADER));
1036 PePlusHdr->OptionalHeader.SizeOfImage = Pe32ImageSize;
1037 PePlusHdr->OptionalHeader.Subsystem = TEImageHeader->Subsystem;
1038 PePlusHdr->OptionalHeader.SizeOfHeaders = TEImageHeader->StrippedSize + TEImageHeader->NumberOfSections *
1039 sizeof (EFI_IMAGE_SECTION_HEADER) - 12;
1040
1041 //
1042 // Set NumberOfRvaAndSizes in the optional header to what we had available in the original image
1043 //
1044 if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress != 0) ||
1045 (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)
1046 ) {
1047 PePlusHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC + 1;
1048 PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
1049 PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
1050 }
1051
1052 if ((TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) ||
1053 (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0)
1054 ) {
1055 PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
1056 PePlusHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
1057 if (PePlusHdr->OptionalHeader.NumberOfRvaAndSizes < EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1) {
1058 PePlusHdr->OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_DIRECTORY_ENTRY_DEBUG + 1;
1059 }
1060 }
1061 //
1062 // NOTE: These values are defaults, and should be verified to be correct in the GenTE utility
1063 //
1064 PePlusHdr->OptionalHeader.SectionAlignment = 0x10;
1065 }
1066
1067 //
1068 // Copy the rest of the image to its original offset
1069 //
1070 memcpy (
1071 TEBuffer + TEImageHeader->StrippedSize,
1072 (UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION) + sizeof (EFI_TE_IMAGE_HEADER),
1073 GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
1074 sizeof (EFI_TE_IMAGE_HEADER)
1075 );
1076
1077 //
1078 // Initialize context
1079 //
1080 memset (&ImageContext, 0, sizeof (ImageContext));
1081 ImageContext.Handle = (VOID *) TEBuffer;
1082 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
1083
1084 Status = PeCoffLoaderGetImageInfo (&ImageContext);
1085
1086 if (EFI_ERROR (Status)) {
1087 Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);
1088 free (TEBuffer);
1089 return Status;
1090 }
1091 //
1092 // Allocate a buffer for the image to be loaded into.
1093 //
1094 MemoryImagePointer = (UINTN) (malloc (Pe32ImageSize + 0x100000));
1095 if (MemoryImagePointer == 0) {
1096 Error (NULL, 0, 0, "memory allocation error on rebase of TE image", FileGuidString);
1097 free (TEBuffer);
1098 return EFI_OUT_OF_RESOURCES;
1099 }
1100 memset ((void *) MemoryImagePointer, 0, Pe32ImageSize + 0x100000);
1101 MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFFF) & (-1 << 16);
1102
1103
1104 ImageContext.ImageAddress = MemoryImagePointerAligned;
1105 Status = PeCoffLoaderLoadImage (&ImageContext);
1106 if (EFI_ERROR (Status)) {
1107 Error (NULL, 0, 0, "LoadImage() call failed on rebase of TE image", FileGuidString);
1108 free (TEBuffer);
1109 free ((VOID *) MemoryImagePointer);
1110 return Status;
1111 }
1112
1113 ImageContext.DestinationAddress = NewPe32BaseAddress;
1114 Status = PeCoffLoaderRelocateImage (&ImageContext);
1115 if (EFI_ERROR (Status)) {
1116 Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);
1117 free ((VOID *) MemoryImagePointer);
1118 free (TEBuffer);
1119 return Status;
1120 }
1121
1122 ImageAddress = ImageContext.ImageAddress;
1123 ImageSize = ImageContext.ImageSize;
1124 EntryPoint = ImageContext.EntryPoint;
1125
1126 //
1127 // Since we may have updated the Codeview RVA, we need to insure the PE
1128 // header indicates the image is large enough to contain the Codeview data
1129 // so it will be loaded properly later if the PEIM is reloaded into memory...
1130 //
1131 PeHdr = (VOID *) ((UINTN) ImageAddress + ImageContext.PeCoffHeaderOffset);
1132 PePlusHdr = (EFI_IMAGE_NT_HEADERS64*)PeHdr;
1133 if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) {
1134 PeHdrSizeOfImage = (UINT32 *) (&(PeHdr->OptionalHeader).SizeOfImage);
1135 PeHdrChecksum = (UINT32 *) (&(PeHdr->OptionalHeader).CheckSum);
1136 } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) {
1137 PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);
1138 PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);
1139 } else if (PeHdr->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) {
1140 PeHdrSizeOfImage = (UINT32 *) (&(PePlusHdr->OptionalHeader).SizeOfImage);
1141 PeHdrChecksum = (UINT32 *) (&(PePlusHdr->OptionalHeader).CheckSum);
1142 } else {
1143 Error (
1144 NULL,
1145 0,
1146 0,
1147 "unknown machine type in TE image",
1148 "machine type=0x%X, file=%s",
1149 (UINT32) PeHdr->FileHeader.Machine,
1150 FileGuidString
1151 );
1152 free ((VOID *) MemoryImagePointer);
1153 free (TEBuffer);
1154 return EFI_ABORTED;
1155 }
1156
1157 if (*PeHdrSizeOfImage != ImageContext.ImageSize) {
1158 *PeHdrSizeOfImage = (UINT32) ImageContext.ImageSize;
1159 if (*PeHdrChecksum) {
1160 *PeHdrChecksum = 0;
1161 }
1162 }
1163
1164 TEImageHeader->ImageBase = (UINT64) (NewPe32BaseAddress + TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER));
1165 memcpy (
1166 (UINT8 *) (CurrentPe32Section.Pe32Section + 1) + sizeof (EFI_TE_IMAGE_HEADER),
1167 (VOID *) ((UINT8 *) MemoryImagePointerAligned + TEImageHeader->StrippedSize),
1168 GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size) - sizeof (EFI_PE32_SECTION) -
1169 sizeof (EFI_TE_IMAGE_HEADER)
1170 );
1171 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
1172 TailSize = sizeof (EFI_FFS_FILE_TAIL);
1173 } else {
1174 TailSize = 0;
1175 }
1176 //
1177 // Now update file checksum
1178 //
1179 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
1180 SavedState = FfsFile->State;
1181 FfsFile->IntegrityCheck.Checksum.File = 0;
1182 FfsFile->State = 0;
1183 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
1184 FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
1185 (UINT8 *) FfsFile,
1186 GetLength (FfsFile->Size) - TailSize
1187 );
1188 } else {
1189 FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
1190 }
1191
1192 FfsFile->State = SavedState;
1193 }
1194 //
1195 // Update tail if present
1196 //
1197 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
1198 TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
1199 *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
1200 }
1201
1202 fprintf (
1203 LogFile,
1204 "%s %016I64X %s\n",
1205 FileGuidString,
1206 ImageContext.DestinationAddress,
1207 ImageContext.PdbPointer == NULL ? "*" : ImageContext.PdbPointer
1208 );
1209
1210 //
1211 // Free buffers
1212 //
1213 free ((VOID *) MemoryImagePointer);
1214 free (TEBuffer);
1215 }
1216
1217 return EFI_SUCCESS;
1218 }
1219
1220 EFI_STATUS
1221 FfsRebaseImageRead (
1222 IN VOID *FileHandle,
1223 IN UINTN FileOffset,
1224 IN OUT UINT32 *ReadSize,
1225 OUT VOID *Buffer
1226 )
1227 /*++
1228
1229 Routine Description:
1230
1231 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
1232
1233 Arguments:
1234
1235 FileHandle - The handle to the PE/COFF file
1236
1237 FileOffset - The offset, in bytes, into the file to read
1238
1239 ReadSize - The number of bytes to read from the file starting at FileOffset
1240
1241 Buffer - A pointer to the buffer to read the data into.
1242
1243 Returns:
1244
1245 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1246
1247 --*/
1248 {
1249 CHAR8 *Destination8;
1250 CHAR8 *Source8;
1251 UINT32 Length;
1252
1253 Destination8 = Buffer;
1254 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
1255 Length = *ReadSize;
1256 while (Length--) {
1257 *(Destination8++) = *(Source8++);
1258 }
1259
1260 return EFI_SUCCESS;
1261 }