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