]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/CCode/Source/PeiRebase/PeiRebaseExe.c
1. Updated LOG file format generated by PeiRebase.
[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 ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
109 (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
110 Usage();
111 return STATUS_ERROR;
112 }
113
114 if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
115 Version();
116 return STATUS_ERROR;
117 }
118
119 //
120 // Verify the correct number of arguments
121 //
122 if (argc < MAX_ARGS) {
123 Usage ();
124 return STATUS_ERROR;
125 }
126
127 //
128 // Initialize variables
129 //
130 InputFileName[0] = '\0';
131 OutputFileName = NULL;
132 XipBase = BsBase = RtBase = 0;
133 BaseTypes = 0;
134 FvOffset = 0;
135 FileCount = 0;
136 ErasePolarity = FALSE;
137 InputFile = NULL;
138 OutputFile = NULL;
139 LogFile = NULL;
140 FvImage = NULL;
141
142 //
143 // Parse the command line arguments
144 //
145 for (Index = 1; Index < argc; Index += 2) {
146 //
147 // Make sure argument pair begin with - or /
148 //
149 if (argv[Index][0] != '-' && argv[Index][0] != '/') {
150 Usage ();
151 Error (NULL, 0, 0, argv[Index], "unrecognized option");
152 return STATUS_ERROR;
153 }
154 //
155 // Make sure argument specifier is only one letter
156 //
157 if (argv[Index][2] != 0) {
158 Usage ();
159 Error (NULL, 0, 0, argv[Index], "unrecognized option");
160 return STATUS_ERROR;
161 }
162 //
163 // Determine argument to read
164 //
165 switch (argv[Index][1]) {
166 case 'I':
167 case 'i':
168 if (strlen (InputFileName) == 0) {
169 strcpy (InputFileName, argv[Index + 1]);
170 } else {
171 Usage ();
172 Error (NULL, 0, 0, argv[Index + 1], "only one -i InputFileName may be specified");
173 return STATUS_ERROR;
174 }
175 break;
176
177 case 'O':
178 case 'o':
179 if (OutputFileName == NULL) {
180 OutputFileName = argv[Index + 1];
181 } else {
182 Usage ();
183 Error (NULL, 0, 0, argv[Index + 1], "only one -o OutputFileName may be specified");
184 return STATUS_ERROR;
185 }
186 break;
187
188 case 'F':
189 case 'f':
190 //
191 // Load INF file into memory & initialize MEMORY_FILE structure
192 //
193 Status = GetFileImage (argv[Index + 1], &InfMemoryFile.FileImage, (UINT32*)&InfMemoryFile.Eof);
194 InfMemoryFile.Eof = InfMemoryFile.FileImage + (UINT32)(UINTN)InfMemoryFile.Eof;
195 InfMemoryFile.CurrentFilePointer = InfMemoryFile.FileImage;
196 if (EFI_ERROR (Status)) {
197 Error (NULL, 0, 0, argv[Index + 1], "Error opening FvInfFile");
198 return STATUS_ERROR;
199 }
200
201 //
202 // Read BaseAddress from fv.inf file
203 //
204 FindToken (&InfMemoryFile, "[options]", "EFI_BASE_ADDRESS", 0, StringBuffer);
205
206 //
207 // Free INF file image
208 //
209 free (InfMemoryFile.FileImage);
210
211 //
212 // Point argv[Index + 1] to StringBuffer so that it could be processed as "-b"
213 //
214 argv[Index + 1] = StringBuffer;
215
216 case 'B':
217 case 'b':
218 if (BaseTypes & 1) {
219 Usage ();
220 Error (NULL, 0, 0, argv[Index + 1], "XipBaseAddress may be specified only once by either -b or -f");
221 return STATUS_ERROR;
222 }
223
224 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &XipBase);
225 if (EFI_ERROR (Status)) {
226 Usage ();
227 Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for XIP base address");
228 return STATUS_ERROR;
229 }
230
231 BaseTypes |= 1;
232 break;
233
234 case 'D':
235 case 'd':
236 if (BaseTypes & 2) {
237 Usage ();
238 Error (NULL, 0, 0, argv[Index + 1], "-d BsBaseAddress may be specified only once");
239 return STATUS_ERROR;
240 }
241
242 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &BsBase);
243 if (EFI_ERROR (Status)) {
244 Usage ();
245 Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for BS_DRIVER base address");
246 return STATUS_ERROR;
247 }
248
249 BaseTypes |= 2;
250 break;
251
252 case 'R':
253 case 'r':
254 if (BaseTypes & 4) {
255 Usage ();
256 Error (NULL, 0, 0, argv[Index + 1], "-r RtBaseAddress may be specified only once");
257 return STATUS_ERROR;
258 }
259
260 Status = AsciiStringToUint64 (argv[Index + 1], FALSE, &RtBase);
261 if (EFI_ERROR (Status)) {
262 Usage ();
263 Error (NULL, 0, 0, argv[Index + 1], "invalid hex digit given for RT_DRIVER base address");
264 return STATUS_ERROR;
265 }
266
267 BaseTypes |= 4;
268 break;
269
270 default:
271 Usage ();
272 Error (NULL, 0, 0, argv[Index], "unrecognized argument");
273 return STATUS_ERROR;
274 break;
275 }
276 }
277
278 //
279 // Open the file containing the FV
280 //
281 InputFile = fopen (InputFileName, "rb");
282 if (InputFile == NULL) {
283 Error (NULL, 0, 0, InputFileName, "could not open input file for reading");
284 return STATUS_ERROR;
285 }
286
287 //
288 // Open the log file
289 //
290 strcat (InputFileName, ".log");
291 LogFile = fopen (InputFileName, "w");
292 if (LogFile == NULL) {
293 Error (NULL, 0, 0, InputFileName, "could not append to log file");
294 }
295
296 //
297 // Determine size of FV
298 //
299 Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);
300 if (EFI_ERROR (Status)) {
301 Error (NULL, 0, 0, "could not parse the FV header", NULL);
302 goto Finish;
303 }
304 //
305 // Allocate a buffer for the FV image
306 //
307 FvImage = malloc (FvSize);
308 if (FvImage == NULL) {
309 Error (NULL, 0, 0, "application error", "memory allocation failed");
310 goto Finish;
311 }
312 //
313 // Read the entire FV to the buffer
314 //
315 BytesRead = fread (FvImage, 1, FvSize, InputFile);
316 fclose (InputFile);
317 InputFile = NULL;
318 if ((unsigned int) BytesRead != FvSize) {
319 Error (NULL, 0, 0, InputFileName, "failed to read from file");
320 goto Finish;
321 }
322 //
323 // Prepare to walk the FV image
324 //
325 InitializeFvLib (FvImage, FvSize);
326 //
327 // Get the first file
328 //
329 Status = GetNextFile (NULL, &CurrentFile);
330 if (EFI_ERROR (Status)) {
331 Error (NULL, 0, 0, "cannot find the first file in the FV image", NULL);
332 goto Finish;
333 }
334 //
335 // Check if each file should be rebased
336 //
337 while (CurrentFile != NULL) {
338 //
339 // Rebase this file
340 //
341 FfsRebase (
342 CurrentFile,
343 BaseTypes,
344 XipBase + (UINTN)CurrentFile - (UINTN)FvImage,
345 &BsBase,
346 &RtBase,
347 LogFile
348 );
349
350 if (EFI_ERROR (Status)) {
351 switch (Status) {
352
353 case EFI_INVALID_PARAMETER:
354 Error (NULL, 0, 0, "invalid parameter passed to FfsRebase", NULL);
355 break;
356
357 case EFI_ABORTED:
358 Error (NULL, 0, 0, "error detected while rebasing -- aborted", NULL);
359 break;
360
361 case EFI_OUT_OF_RESOURCES:
362 Error (NULL, 0, 0, "FfsRebase could not allocate required resources", NULL);
363 break;
364
365 case EFI_NOT_FOUND:
366 Error (NULL, 0, 0, "FfsRebase could not locate a PE32 section", NULL);
367 break;
368
369 default:
370 Error (NULL, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status);
371 break;
372 }
373
374 goto Finish;
375 }
376 //
377 // Get the next file
378 //
379 Status = GetNextFile (CurrentFile, &CurrentFile);
380 if (EFI_ERROR (Status)) {
381 Error (NULL, 0, 0, "cannot find the next file in the FV image", NULL);
382 goto Finish;
383 }
384 }
385 //
386 // Open the output file
387 //
388 OutputFile = fopen (OutputFileName, "wb");
389 if (OutputFile == NULL) {
390 Error (NULL, 0, 0, OutputFileName, "failed to open output file");
391 goto Finish;
392 }
393
394 if (fwrite (FvImage, 1, FvSize, OutputFile) != FvSize) {
395 Error (NULL, 0, 0, "failed to write to output file", 0);
396 goto Finish;
397 }
398
399 Finish:
400 if (InputFile != NULL) {
401 fclose (InputFile);
402 }
403 //
404 // If we created an output file, and there was an error, remove it so
405 // subsequent builds will rebuild it.
406 //
407 if (OutputFile != NULL) {
408 if (GetUtilityStatus () == STATUS_ERROR) {
409 remove (OutputFileName);
410 }
411
412 fclose (OutputFile);
413 }
414
415 if (LogFile != NULL) {
416 fclose (LogFile);
417 }
418
419 if (FvImage != NULL) {
420 free (FvImage);
421 }
422
423 return GetUtilityStatus ();
424 }
425
426 EFI_STATUS
427 ReadHeader (
428 IN FILE *InputFile,
429 OUT UINT32 *FvSize,
430 OUT BOOLEAN *ErasePolarity
431 )
432 /*++
433
434 Routine Description:
435
436 This function determines the size of the FV and the erase polarity. The
437 erase polarity is the FALSE value for file state.
438
439 Arguments:
440
441 InputFile The file that contains the FV image.
442 FvSize The size of the FV.
443 ErasePolarity The FV erase polarity.
444
445 Returns:
446
447 EFI_SUCCESS Function completed successfully.
448 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
449 EFI_ABORTED The function encountered an error.
450
451 --*/
452 {
453 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
454 EFI_FV_BLOCK_MAP_ENTRY BlockMap;
455 UINTN Signature[2];
456 UINTN BytesRead;
457 UINT32 Size;
458
459 BytesRead = 0;
460 Size = 0;
461 //
462 // Check input parameters
463 //
464 if ((InputFile == NULL) || (FvSize == NULL) || (ErasePolarity == NULL)) {
465 Error (NULL, 0, 0, "ReadHeader()", "invalid input parameter");
466 return EFI_INVALID_PARAMETER;
467 }
468 //
469 // Read the header
470 //
471 fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
472 BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
473 Signature[0] = VolumeHeader.Signature;
474 Signature[1] = 0;
475
476 //
477 // Get erase polarity
478 //
479 if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {
480 *ErasePolarity = TRUE;
481 }
482
483 do {
484 fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
485 BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
486
487 if (BlockMap.NumBlocks != 0) {
488 Size += BlockMap.NumBlocks * BlockMap.BlockLength;
489 }
490
491 } while (!(BlockMap.NumBlocks == 0 && BlockMap.BlockLength == 0));
492
493 if (VolumeHeader.FvLength != Size) {
494 Error (NULL, 0, 0, "volume size not consistant with block maps", NULL);
495 return EFI_ABORTED;
496 }
497
498 *FvSize = Size;
499
500 rewind (InputFile);
501
502 return EFI_SUCCESS;
503 }
504
505 VOID
506 Version (
507 VOID
508 )
509 /*++
510
511 Routine Description:
512
513 Displays the standard utility information to SDTOUT
514
515 Arguments:
516
517 None
518
519 Returns:
520
521 None
522
523 --*/
524 {
525 printf ("%s v%d.%d -PEI Rebase Utility.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
526 printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
527 }
528
529 VOID
530 Usage (
531 VOID
532 )
533 /*++
534
535 Routine Description:
536
537 Displays the utility usage syntax to STDOUT
538
539 Arguments:
540
541 None
542
543 Returns:
544
545 None
546
547 --*/
548 {
549 Version();
550
551 printf (
552 "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress [-F InputFvInfName]\n",
553 UTILITY_NAME
554 );
555 printf (" [-D BootDriverBaseAddress] [-R RuntimeDriverBaseAddress]\n");
556 printf (" Where:\n");
557 printf (" InputFileName is the name of the EFI FV file to rebase.\n");
558 printf (" OutputFileName is the desired output file name.\n");
559 printf (" BaseAddress is the rebase address for all drivers run in Flash.\n");
560 printf (" InputFvInfName is the Fv.inf file that contains this FV base address to rebase against.\n");
561 printf (" BootDriverBaseAddress is the rebase address for all boot drivers in this fv image.\n");
562 printf (" RuntimeDriverBaseAddress is the rebase address for all runtime drivers in this fv image.\n");
563 printf (" Argument pair may be in any order.\n\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 EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;
600 UINTN Index;
601 EFI_FILE_SECTION_POINTER CurrentPe32Section;
602 EFI_FFS_FILE_STATE SavedState;
603 EFI_IMAGE_NT_HEADERS32 *PeHdr;
604 EFI_TE_IMAGE_HEADER *TEImageHeader;
605 UINT8 FileGuidString[80];
606 UINT32 TailSize;
607 EFI_FFS_FILE_TAIL TailValue;
608 EFI_PHYSICAL_ADDRESS *BaseToUpdate;
609 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
610
611
612 //
613 // Verify input parameters
614 //
615 if (FfsFile == NULL) {
616 return EFI_INVALID_PARAMETER;
617 }
618 //
619 // Convert the GUID to a string so we can at least report which file
620 // if we find an error.
621 //
622 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
623 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
624 TailSize = sizeof (EFI_FFS_FILE_TAIL);
625 } else {
626 TailSize = 0;
627 }
628 //
629 // Do some cursory checks on the FFS file contents
630 //
631 Status = VerifyFfsFile (FfsFile);
632 if (EFI_ERROR (Status)) {
633 Error (NULL, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString);
634 return EFI_INVALID_PARAMETER;
635 }
636
637 //
638 // We only process files potentially containing PE32 sections.
639 //
640 switch (FfsFile->Type) {
641 case EFI_FV_FILETYPE_SECURITY_CORE:
642 case EFI_FV_FILETYPE_PEI_CORE:
643 case EFI_FV_FILETYPE_PEIM:
644 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
645 case EFI_FV_FILETYPE_DRIVER:
646 case EFI_FV_FILETYPE_DXE_CORE:
647 break;
648 default:
649 return EFI_SUCCESS;
650 }
651
652 //
653 // Rebase each PE32 section
654 //
655 Status = EFI_SUCCESS;
656 for (Index = 1;; Index++) {
657 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
658 if (EFI_ERROR (Status)) {
659 break;
660 }
661
662 //
663 // Initialize context
664 //
665 memset (&ImageContext, 0, sizeof (ImageContext));
666 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
667 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
668 Status = PeCoffLoaderGetImageInfo (&ImageContext);
669 if (EFI_ERROR (Status)) {
670 Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);
671 return Status;
672 }
673
674 //
675 // Don't Load PeImage, only to relocate current image.
676 //
677 ImageContext.ImageAddress = (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION);
678
679 //
680 // Check if section-alignment and file-alignment match or not
681 //
682 PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext.ImageAddress + ImageContext.PeCoffHeaderOffset);
683 if (PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment) {
684 //
685 // Nor XIP module can be ignored.
686 //
687 if ((Flags & 1) == 0) {
688 continue;
689 }
690 Error (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileGuidString);
691 return EFI_ABORTED;
692 }
693
694 //
695 // Update CodeView and PdbPointer in ImageContext
696 //
697 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
698 ImageContext.ImageAddress +
699 ImageContext.DebugDirectoryEntryRva
700 );
701 ImageContext.CodeView = (VOID *)(UINTN)(
702 ImageContext.ImageAddress +
703 DebugEntry->RVA
704 );
705 switch (*(UINT32 *) ImageContext.CodeView) {
706 case CODEVIEW_SIGNATURE_NB10:
707 ImageContext.PdbPointer = (CHAR8 *) ImageContext.CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
708 break;
709
710 case CODEVIEW_SIGNATURE_RSDS:
711 ImageContext.PdbPointer = (CHAR8 *) ImageContext.CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
712 break;
713
714 default:
715 break;
716 }
717
718 //
719 // Calculate the PE32 base address, based on file type
720 //
721 switch (FfsFile->Type) {
722 case EFI_FV_FILETYPE_SECURITY_CORE:
723 case EFI_FV_FILETYPE_PEI_CORE:
724 case EFI_FV_FILETYPE_PEIM:
725 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
726 if ((Flags & 1) == 0) {
727 //
728 // We aren't relocating XIP code, so skip it.
729 //
730 return EFI_SUCCESS;
731 }
732
733 NewPe32BaseAddress =
734 XipBase + (UINTN)ImageContext.ImageAddress - (UINTN)FfsFile;
735 BaseToUpdate = &XipBase;
736 break;
737
738 case EFI_FV_FILETYPE_DRIVER:
739 PeHdr = (EFI_IMAGE_NT_HEADERS32*)(ImageContext.ImageAddress + ImageContext.PeCoffHeaderOffset);
740 switch (PeHdr->OptionalHeader.Subsystem) {
741 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
742 if ((Flags & 4) == 0) {
743 //
744 // RT drivers aren't supposed to be relocated
745 //
746 continue;
747 }
748
749 NewPe32BaseAddress = *RtBase;
750 BaseToUpdate = RtBase;
751 break;
752
753 default:
754 //
755 // We treat all other subsystems the same as BS_DRIVER
756 //
757 if ((Flags & 2) == 0) {
758 //
759 // Skip all BS_DRIVER's
760 //
761 continue;
762 }
763
764 NewPe32BaseAddress = *BsBase;
765 BaseToUpdate = BsBase;
766 break;
767 }
768 break;
769
770 case EFI_FV_FILETYPE_DXE_CORE:
771 if ((Flags & 2) == 0) {
772 //
773 // Skip DXE core
774 //
775 return EFI_SUCCESS;
776 }
777
778 NewPe32BaseAddress = *BsBase;
779 BaseToUpdate = BsBase;
780 break;
781
782 default:
783 //
784 // Not supported file type
785 //
786 return EFI_SUCCESS;
787 }
788
789 ImageContext.DestinationAddress = NewPe32BaseAddress;
790 Status = PeCoffLoaderRelocateImage (&ImageContext);
791 if (EFI_ERROR (Status)) {
792 Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);
793 return Status;
794 }
795
796 //
797 // Update BASE address
798 //
799 fprintf (
800 LogFile,
801 "%s %016I64X\n",
802 FileGuidString,
803 ImageContext.DestinationAddress
804 );
805 *BaseToUpdate += EFI_SIZE_TO_PAGES (ImageContext.ImageSize) * EFI_PAGE_SIZE;
806
807 //
808 // Now update file checksum
809 //
810 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
811 TailSize = sizeof (EFI_FFS_FILE_TAIL);
812 } else {
813 TailSize = 0;
814 }
815
816 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
817 SavedState = FfsFile->State;
818 FfsFile->IntegrityCheck.Checksum.File = 0;
819 FfsFile->State = 0;
820 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
821 FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
822 (UINT8 *) FfsFile,
823 GetLength (FfsFile->Size) - TailSize
824 );
825 } else {
826 FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
827 }
828
829 FfsFile->State = SavedState;
830 }
831 //
832 // Update tail if present
833 //
834 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
835 TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
836 *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
837 }
838 }
839
840 if ((Flags & 1) == 0 || (
841 FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
842 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
843
844 FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
845 FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
846 )) {
847 //
848 // Only XIP code may have a TE section
849 //
850 return EFI_SUCCESS;
851 }
852
853 //
854 // Now process TE sections
855 //
856 for (Index = 1;; Index++) {
857 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
858 if (EFI_ERROR (Status)) {
859 break;
860 }
861
862 //
863 // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
864 // by GenTEImage
865 //
866 TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
867
868 //
869 // Initialize context, load image info.
870 //
871 memset (&ImageContext, 0, sizeof (ImageContext));
872 ImageContext.Handle = (VOID *) TEImageHeader;
873 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
874
875 Status = PeCoffLoaderGetImageInfo (&ImageContext);
876
877 if (EFI_ERROR (Status)) {
878 Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);
879 return Status;
880 }
881 //
882 // Don't reload TeImage
883 //
884 ImageContext.ImageAddress = (UINTN) TEImageHeader;
885
886 //
887 // Update CodeView and PdbPointer in ImageContext
888 //
889 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
890 ImageContext.ImageAddress +
891 ImageContext.DebugDirectoryEntryRva +
892 sizeof(EFI_TE_IMAGE_HEADER) -
893 TEImageHeader->StrippedSize
894 );
895
896 ImageContext.CodeView = (VOID *)(UINTN)(
897 ImageContext.ImageAddress +
898 DebugEntry->RVA +
899 sizeof(EFI_TE_IMAGE_HEADER) -
900 TEImageHeader->StrippedSize
901 );
902
903 switch (*(UINT32 *) ImageContext.CodeView) {
904 case CODEVIEW_SIGNATURE_NB10:
905 ImageContext.PdbPointer = (CHAR8 *) ImageContext.CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
906 break;
907
908 case CODEVIEW_SIGNATURE_RSDS:
909 ImageContext.PdbPointer = (CHAR8 *) ImageContext.CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
910 break;
911
912 default:
913 break;
914 }
915
916 //
917 // Reloacate TeImage
918 //
919 ImageContext.DestinationAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \
920 - TEImageHeader->StrippedSize - (UINTN) FfsFile;
921 Status = PeCoffLoaderRelocateImage (&ImageContext);
922 if (EFI_ERROR (Status)) {
923 Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);
924 return Status;
925 }
926
927 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
928 TailSize = sizeof (EFI_FFS_FILE_TAIL);
929 } else {
930 TailSize = 0;
931 }
932 //
933 // Now update file checksum
934 //
935 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
936 SavedState = FfsFile->State;
937 FfsFile->IntegrityCheck.Checksum.File = 0;
938 FfsFile->State = 0;
939 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
940 FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
941 (UINT8 *) FfsFile,
942 GetLength (FfsFile->Size) - TailSize
943 );
944 } else {
945 FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
946 }
947
948 FfsFile->State = SavedState;
949 }
950 //
951 // Update tail if present
952 //
953 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
954 TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
955 *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
956 }
957
958 fprintf (
959 LogFile,
960 "%s %016I64X\n",
961 FileGuidString,
962 ImageContext.DestinationAddress
963 );
964 }
965
966 return EFI_SUCCESS;
967 }
968
969 EFI_STATUS
970 FfsRebaseImageRead (
971 IN VOID *FileHandle,
972 IN UINTN FileOffset,
973 IN OUT UINT32 *ReadSize,
974 OUT VOID *Buffer
975 )
976 /*++
977
978 Routine Description:
979
980 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
981
982 Arguments:
983
984 FileHandle - The handle to the PE/COFF file
985
986 FileOffset - The offset, in bytes, into the file to read
987
988 ReadSize - The number of bytes to read from the file starting at FileOffset
989
990 Buffer - A pointer to the buffer to read the data into.
991
992 Returns:
993
994 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
995
996 --*/
997 {
998 CHAR8 *Destination8;
999 CHAR8 *Source8;
1000 UINT32 Length;
1001
1002 Destination8 = Buffer;
1003 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
1004 Length = *ReadSize;
1005 while (Length--) {
1006 *(Destination8++) = *(Source8++);
1007 }
1008
1009 return EFI_SUCCESS;
1010 }