]> git.proxmox.com Git - mirror_edk2.git/blob - Tools/CCode/Source/PeiRebase/PeiRebaseExe.c
Correct TeImage file format and Clean up PeiRebase tool to remove unused code and...
[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 //
284 // Open the file containing the FV
285 //
286 InputFile = fopen (InputFileName, "rb");
287 if (InputFile == NULL) {
288 Error (NULL, 0, 0, InputFileName, "could not open input file for reading");
289 return STATUS_ERROR;
290 }
291
292 //
293 // Open the log file
294 //
295 strcat (InputFileName, ".log");
296 LogFile = fopen (InputFileName, "a");
297 if (LogFile == NULL) {
298 Error (NULL, 0, 0, InputFileName, "could not append to log file");
299 }
300
301 //
302 // Determine size of FV
303 //
304 Status = ReadHeader (InputFile, &FvSize, &ErasePolarity);
305 if (EFI_ERROR (Status)) {
306 Error (NULL, 0, 0, "could not parse the FV header", NULL);
307 goto Finish;
308 }
309 //
310 // Allocate a buffer for the FV image
311 //
312 FvImage = malloc (FvSize);
313 if (FvImage == NULL) {
314 Error (NULL, 0, 0, "application error", "memory allocation failed");
315 goto Finish;
316 }
317 //
318 // Read the entire FV to the buffer
319 //
320 BytesRead = fread (FvImage, 1, FvSize, InputFile);
321 fclose (InputFile);
322 InputFile = NULL;
323 if ((unsigned int) BytesRead != FvSize) {
324 Error (NULL, 0, 0, InputFileName, "failed to read from file");
325 goto Finish;
326 }
327 //
328 // Prepare to walk the FV image
329 //
330 InitializeFvLib (FvImage, FvSize);
331 //
332 // Get the first file
333 //
334 Status = GetNextFile (NULL, &CurrentFile);
335 if (EFI_ERROR (Status)) {
336 Error (NULL, 0, 0, "cannot find the first file in the FV image", NULL);
337 goto Finish;
338 }
339 //
340 // Check if each file should be rebased
341 //
342 while (CurrentFile != NULL) {
343 //
344 // Rebase this file
345 //
346 FfsRebase (
347 CurrentFile,
348 BaseTypes,
349 XipBase + (UINTN)CurrentFile - (UINTN)FvImage,
350 &BsBase,
351 &RtBase,
352 LogFile
353 );
354
355 if (EFI_ERROR (Status)) {
356 switch (Status) {
357
358 case EFI_INVALID_PARAMETER:
359 Error (NULL, 0, 0, "invalid parameter passed to FfsRebase", NULL);
360 break;
361
362 case EFI_ABORTED:
363 Error (NULL, 0, 0, "error detected while rebasing -- aborted", NULL);
364 break;
365
366 case EFI_OUT_OF_RESOURCES:
367 Error (NULL, 0, 0, "FfsRebase could not allocate required resources", NULL);
368 break;
369
370 case EFI_NOT_FOUND:
371 Error (NULL, 0, 0, "FfsRebase could not locate a PE32 section", NULL);
372 break;
373
374 default:
375 Error (NULL, 0, 0, "FfsRebase returned unknown status", "status=0x%08X", Status);
376 break;
377 }
378
379 goto Finish;
380 }
381 //
382 // Get the next file
383 //
384 Status = GetNextFile (CurrentFile, &CurrentFile);
385 if (EFI_ERROR (Status)) {
386 Error (NULL, 0, 0, "cannot find the next file in the FV image", NULL);
387 goto Finish;
388 }
389 }
390 //
391 // Open the output file
392 //
393 OutputFile = fopen (OutputFileName, "wb");
394 if (OutputFile == NULL) {
395 Error (NULL, 0, 0, OutputFileName, "failed to open output file");
396 goto Finish;
397 }
398
399 if (fwrite (FvImage, 1, FvSize, OutputFile) != FvSize) {
400 Error (NULL, 0, 0, "failed to write to output file", 0);
401 goto Finish;
402 }
403
404 Finish:
405 if (InputFile != NULL) {
406 fclose (InputFile);
407 }
408 //
409 // If we created an output file, and there was an error, remove it so
410 // subsequent builds will rebuild it.
411 //
412 if (OutputFile != NULL) {
413 if (GetUtilityStatus () == STATUS_ERROR) {
414 remove (OutputFileName);
415 }
416
417 fclose (OutputFile);
418 }
419
420 if (LogFile != NULL) {
421 fclose (LogFile);
422 }
423
424 if (FvImage != NULL) {
425 free (FvImage);
426 }
427
428 return GetUtilityStatus ();
429 }
430
431 EFI_STATUS
432 ReadHeader (
433 IN FILE *InputFile,
434 OUT UINT32 *FvSize,
435 OUT BOOLEAN *ErasePolarity
436 )
437 /*++
438
439 Routine Description:
440
441 This function determines the size of the FV and the erase polarity. The
442 erase polarity is the FALSE value for file state.
443
444 Arguments:
445
446 InputFile The file that contains the FV image.
447 FvSize The size of the FV.
448 ErasePolarity The FV erase polarity.
449
450 Returns:
451
452 EFI_SUCCESS Function completed successfully.
453 EFI_INVALID_PARAMETER A required parameter was NULL or is out of range.
454 EFI_ABORTED The function encountered an error.
455
456 --*/
457 {
458 EFI_FIRMWARE_VOLUME_HEADER VolumeHeader;
459 EFI_FV_BLOCK_MAP_ENTRY BlockMap;
460 UINTN Signature[2];
461 UINTN BytesRead;
462 UINT32 Size;
463
464 BytesRead = 0;
465 Size = 0;
466 //
467 // Check input parameters
468 //
469 if ((InputFile == NULL) || (FvSize == NULL) || (ErasePolarity == NULL)) {
470 Error (NULL, 0, 0, "ReadHeader()", "invalid input parameter");
471 return EFI_INVALID_PARAMETER;
472 }
473 //
474 // Read the header
475 //
476 fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
477 BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY);
478 Signature[0] = VolumeHeader.Signature;
479 Signature[1] = 0;
480
481 //
482 // Get erase polarity
483 //
484 if (VolumeHeader.Attributes & EFI_FVB_ERASE_POLARITY) {
485 *ErasePolarity = TRUE;
486 }
487
488 do {
489 fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile);
490 BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY);
491
492 if (BlockMap.NumBlocks != 0) {
493 Size += BlockMap.NumBlocks * BlockMap.BlockLength;
494 }
495
496 } while (!(BlockMap.NumBlocks == 0 && BlockMap.BlockLength == 0));
497
498 if (VolumeHeader.FvLength != Size) {
499 Error (NULL, 0, 0, "volume size not consistant with block maps", NULL);
500 return EFI_ABORTED;
501 }
502
503 *FvSize = Size;
504
505 rewind (InputFile);
506
507 return EFI_SUCCESS;
508 }
509
510 VOID
511 Version (
512 VOID
513 )
514 /*++
515
516 Routine Description:
517
518 Displays the standard utility information to SDTOUT
519
520 Arguments:
521
522 None
523
524 Returns:
525
526 None
527
528 --*/
529 {
530 printf ("%s v%d.%d -PEI Rebase Utility.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
531 printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
532 }
533
534 VOID
535 Usage (
536 VOID
537 )
538 /*++
539
540 Routine Description:
541
542 Displays the utility usage syntax to STDOUT
543
544 Arguments:
545
546 None
547
548 Returns:
549
550 None
551
552 --*/
553 {
554 Version();
555
556 printf (
557 "Usage: %s -I InputFileName -O OutputFileName -B BaseAddress [-F InputFvInfName]\n",
558 UTILITY_NAME
559 );
560 printf (" [-D BootDriverBaseAddress] [-R RuntimeDriverBaseAddress]\n");
561 printf (" Where:\n");
562 printf (" InputFileName is the name of the EFI FV file to rebase.\n");
563 printf (" OutputFileName is the desired output file name.\n");
564 printf (" BaseAddress is the rebase address for all drivers run in Flash.\n");
565 printf (" InputFvInfName is the Fv.inf file that contains this FV base address to rebase against.\n");
566 printf (" BootDriverBaseAddress is the rebase address for all boot drivers in this fv image.\n");
567 printf (" RuntimeDriverBaseAddress is the rebase address for all runtime drivers in this fv image.\n");
568 printf (" Argument pair may be in any order.\n\n");
569 }
570
571 EFI_STATUS
572 FfsRebase (
573 IN OUT EFI_FFS_FILE_HEADER *FfsFile,
574 IN UINT32 Flags,
575 IN OUT EFI_PHYSICAL_ADDRESS XipBase,
576 IN OUT EFI_PHYSICAL_ADDRESS *BsBase,
577 IN OUT EFI_PHYSICAL_ADDRESS *RtBase,
578 OUT FILE *LogFile
579 )
580 /*++
581
582 Routine Description:
583
584 This function determines if a file is XIP and should be rebased. It will
585 rebase any PE32 sections found in the file using the base address.
586
587 Arguments:
588
589 FfsFile A pointer to Ffs file image.
590 BaseAddress The base address to use for rebasing the file image.
591
592 Returns:
593
594 EFI_SUCCESS The image was properly rebased.
595 EFI_INVALID_PARAMETER An input parameter is invalid.
596 EFI_ABORTED An error occurred while rebasing the input file image.
597 EFI_OUT_OF_RESOURCES Could not allocate a required resource.
598 EFI_NOT_FOUND No compressed sections could be found.
599
600 --*/
601 {
602 EFI_STATUS Status;
603 PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
604 EFI_PHYSICAL_ADDRESS NewPe32BaseAddress;
605 UINTN Index;
606 EFI_FILE_SECTION_POINTER CurrentPe32Section;
607 EFI_FFS_FILE_STATE SavedState;
608 EFI_IMAGE_NT_HEADERS32 *PeHdr;
609 EFI_TE_IMAGE_HEADER *TEImageHeader;
610 UINT8 FileGuidString[80];
611 UINT32 TailSize;
612 EFI_FFS_FILE_TAIL TailValue;
613 EFI_PHYSICAL_ADDRESS *BaseToUpdate;
614 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
615
616
617 //
618 // Verify input parameters
619 //
620 if (FfsFile == NULL) {
621 return EFI_INVALID_PARAMETER;
622 }
623 //
624 // Convert the GUID to a string so we can at least report which file
625 // if we find an error.
626 //
627 PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE);
628 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
629 TailSize = sizeof (EFI_FFS_FILE_TAIL);
630 } else {
631 TailSize = 0;
632 }
633 //
634 // Do some cursory checks on the FFS file contents
635 //
636 Status = VerifyFfsFile (FfsFile);
637 if (EFI_ERROR (Status)) {
638 Error (NULL, 0, 0, "file does not appear to be a valid FFS file, cannot be rebased", FileGuidString);
639 return EFI_INVALID_PARAMETER;
640 }
641
642 //
643 // We only process files potentially containing PE32 sections.
644 //
645 switch (FfsFile->Type) {
646 case EFI_FV_FILETYPE_SECURITY_CORE:
647 case EFI_FV_FILETYPE_PEI_CORE:
648 case EFI_FV_FILETYPE_PEIM:
649 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
650 case EFI_FV_FILETYPE_DRIVER:
651 case EFI_FV_FILETYPE_DXE_CORE:
652 break;
653 default:
654 return EFI_SUCCESS;
655 }
656
657 //
658 // Rebase each PE32 section
659 //
660 Status = EFI_SUCCESS;
661 for (Index = 1;; Index++) {
662 Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section);
663 if (EFI_ERROR (Status)) {
664 break;
665 }
666
667 //
668 // Initialize context
669 //
670 memset (&ImageContext, 0, sizeof (ImageContext));
671 ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION));
672 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
673 Status = PeCoffLoaderGetImageInfo (&ImageContext);
674 if (EFI_ERROR (Status)) {
675 Error (NULL, 0, 0, "GetImageInfo() call failed on rebase", FileGuidString);
676 return Status;
677 }
678
679 //
680 // Don't Load PeImage, only to relocate current image.
681 //
682 ImageContext.ImageAddress = (UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION);
683
684 //
685 // Check if section-alignment and file-alignment match or not
686 //
687 PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext.ImageAddress + ImageContext.PeCoffHeaderOffset);
688 if (PeHdr->OptionalHeader.SectionAlignment != PeHdr->OptionalHeader.FileAlignment) {
689 //
690 // Nor XIP module can be ignored.
691 //
692 if ((Flags & 1) == 0) {
693 continue;
694 }
695 Error (NULL, 0, 0, "Section-Alignment and File-Alignment does not match", FileGuidString);
696 return EFI_ABORTED;
697 }
698
699 //
700 // Update CodeView and PdbPointer in ImageContext
701 //
702 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
703 ImageContext.ImageAddress +
704 ImageContext.DebugDirectoryEntryRva
705 );
706 ImageContext.CodeView = (VOID *)(UINTN)(
707 ImageContext.ImageAddress +
708 DebugEntry->RVA
709 );
710 switch (*(UINT32 *) ImageContext.CodeView) {
711 case CODEVIEW_SIGNATURE_NB10:
712 ImageContext.PdbPointer = (CHAR8 *) ImageContext.CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
713 break;
714
715 case CODEVIEW_SIGNATURE_RSDS:
716 ImageContext.PdbPointer = (CHAR8 *) ImageContext.CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
717 break;
718
719 default:
720 break;
721 }
722
723 //
724 // Calculate the PE32 base address, based on file type
725 //
726 switch (FfsFile->Type) {
727 case EFI_FV_FILETYPE_SECURITY_CORE:
728 case EFI_FV_FILETYPE_PEI_CORE:
729 case EFI_FV_FILETYPE_PEIM:
730 case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER:
731 if ((Flags & 1) == 0) {
732 //
733 // We aren't relocating XIP code, so skip it.
734 //
735 return EFI_SUCCESS;
736 }
737
738 NewPe32BaseAddress =
739 XipBase + (UINTN)ImageContext.ImageAddress - (UINTN)FfsFile;
740 BaseToUpdate = &XipBase;
741 break;
742
743 case EFI_FV_FILETYPE_DRIVER:
744 PeHdr = (EFI_IMAGE_NT_HEADERS32*)(ImageContext.ImageAddress + ImageContext.PeCoffHeaderOffset);
745 switch (PeHdr->OptionalHeader.Subsystem) {
746 case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER:
747 if ((Flags & 4) == 0) {
748 //
749 // RT drivers aren't supposed to be relocated
750 //
751 continue;
752 }
753
754 NewPe32BaseAddress = *RtBase;
755 BaseToUpdate = RtBase;
756 break;
757
758 default:
759 //
760 // We treat all other subsystems the same as BS_DRIVER
761 //
762 if ((Flags & 2) == 0) {
763 //
764 // Skip all BS_DRIVER's
765 //
766 continue;
767 }
768
769 NewPe32BaseAddress = *BsBase;
770 BaseToUpdate = BsBase;
771 break;
772 }
773 break;
774
775 case EFI_FV_FILETYPE_DXE_CORE:
776 if ((Flags & 2) == 0) {
777 //
778 // Skip DXE core
779 //
780 return EFI_SUCCESS;
781 }
782
783 NewPe32BaseAddress = *BsBase;
784 BaseToUpdate = BsBase;
785 break;
786
787 default:
788 //
789 // Not supported file type
790 //
791 return EFI_SUCCESS;
792 }
793
794 ImageContext.DestinationAddress = NewPe32BaseAddress;
795 Status = PeCoffLoaderRelocateImage (&ImageContext);
796 if (EFI_ERROR (Status)) {
797 Error (NULL, 0, 0, "RelocateImage() call failed on rebase", FileGuidString);
798 return Status;
799 }
800
801 //
802 // Update BASE address
803 //
804 fprintf (
805 LogFile,
806 "%s %016I64X %s\n",
807 FileGuidString,
808 ImageContext.DestinationAddress,
809 ImageContext.PdbPointer == NULL ? "*" : ImageContext.PdbPointer
810 );
811 *BaseToUpdate += EFI_SIZE_TO_PAGES (ImageContext.ImageSize) * EFI_PAGE_SIZE;
812
813 //
814 // Now update file checksum
815 //
816 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
817 TailSize = sizeof (EFI_FFS_FILE_TAIL);
818 } else {
819 TailSize = 0;
820 }
821
822 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
823 SavedState = FfsFile->State;
824 FfsFile->IntegrityCheck.Checksum.File = 0;
825 FfsFile->State = 0;
826 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
827 FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
828 (UINT8 *) FfsFile,
829 GetLength (FfsFile->Size) - TailSize
830 );
831 } else {
832 FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
833 }
834
835 FfsFile->State = SavedState;
836 }
837 //
838 // Update tail if present
839 //
840 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
841 TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
842 *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
843 }
844 }
845
846 if ((Flags & 1) == 0 || (
847 FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE &&
848 FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE &&
849
850 FfsFile->Type != EFI_FV_FILETYPE_PEIM &&
851 FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
852 )) {
853 //
854 // Only XIP code may have a TE section
855 //
856 return EFI_SUCCESS;
857 }
858
859 //
860 // Now process TE sections
861 //
862 for (Index = 1;; Index++) {
863 Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section);
864 if (EFI_ERROR (Status)) {
865 break;
866 }
867
868 //
869 // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off
870 // by GenTEImage
871 //
872 TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER));
873
874 //
875 // Initialize context, load image info.
876 //
877 memset (&ImageContext, 0, sizeof (ImageContext));
878 ImageContext.Handle = (VOID *) TEImageHeader;
879 ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead;
880
881 Status = PeCoffLoaderGetImageInfo (&ImageContext);
882
883 if (EFI_ERROR (Status)) {
884 Error (NULL, 0, 0, "GetImageInfo() call failed on rebase of TE image", FileGuidString);
885 return Status;
886 }
887 //
888 // Don't reload TeImage
889 //
890 ImageContext.ImageAddress = (UINTN) TEImageHeader;
891
892 //
893 // Update CodeView and PdbPointer in ImageContext
894 //
895 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)(
896 ImageContext.ImageAddress +
897 ImageContext.DebugDirectoryEntryRva +
898 sizeof(EFI_TE_IMAGE_HEADER) -
899 TEImageHeader->StrippedSize
900 );
901
902 ImageContext.CodeView = (VOID *)(UINTN)(
903 ImageContext.ImageAddress +
904 DebugEntry->RVA +
905 sizeof(EFI_TE_IMAGE_HEADER) -
906 TEImageHeader->StrippedSize
907 );
908
909 switch (*(UINT32 *) ImageContext.CodeView) {
910 case CODEVIEW_SIGNATURE_NB10:
911 ImageContext.PdbPointer = (CHAR8 *) ImageContext.CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY);
912 break;
913
914 case CODEVIEW_SIGNATURE_RSDS:
915 ImageContext.PdbPointer = (CHAR8 *) ImageContext.CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY);
916 break;
917
918 default:
919 break;
920 }
921
922 //
923 // Reloacate TeImage
924 //
925 ImageContext.DestinationAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \
926 - TEImageHeader->StrippedSize - (UINTN) FfsFile;
927 Status = PeCoffLoaderRelocateImage (&ImageContext);
928 if (EFI_ERROR (Status)) {
929 Error (NULL, 0, 0, "RelocateImage() call failed on rebase of TE image", FileGuidString);
930 return Status;
931 }
932
933 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
934 TailSize = sizeof (EFI_FFS_FILE_TAIL);
935 } else {
936 TailSize = 0;
937 }
938 //
939 // Now update file checksum
940 //
941 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
942 SavedState = FfsFile->State;
943 FfsFile->IntegrityCheck.Checksum.File = 0;
944 FfsFile->State = 0;
945 if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) {
946 FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 (
947 (UINT8 *) FfsFile,
948 GetLength (FfsFile->Size) - TailSize
949 );
950 } else {
951 FfsFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
952 }
953
954 FfsFile->State = SavedState;
955 }
956 //
957 // Update tail if present
958 //
959 if (FfsFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) {
960 TailValue = (EFI_FFS_FILE_TAIL) (~(FfsFile->IntegrityCheck.TailReference));
961 *(EFI_FFS_FILE_TAIL *) (((UINTN) FfsFile + GetLength (FfsFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue;
962 }
963
964 fprintf (
965 LogFile,
966 "%s %016I64X %s\n",
967 FileGuidString,
968 ImageContext.DestinationAddress,
969 ImageContext.PdbPointer == NULL ? "*" : ImageContext.PdbPointer
970 );
971 }
972
973 return EFI_SUCCESS;
974 }
975
976 EFI_STATUS
977 FfsRebaseImageRead (
978 IN VOID *FileHandle,
979 IN UINTN FileOffset,
980 IN OUT UINT32 *ReadSize,
981 OUT VOID *Buffer
982 )
983 /*++
984
985 Routine Description:
986
987 Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file
988
989 Arguments:
990
991 FileHandle - The handle to the PE/COFF file
992
993 FileOffset - The offset, in bytes, into the file to read
994
995 ReadSize - The number of bytes to read from the file starting at FileOffset
996
997 Buffer - A pointer to the buffer to read the data into.
998
999 Returns:
1000
1001 EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset
1002
1003 --*/
1004 {
1005 CHAR8 *Destination8;
1006 CHAR8 *Source8;
1007 UINT32 Length;
1008
1009 Destination8 = Buffer;
1010 Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);
1011 Length = *ReadSize;
1012 while (Length--) {
1013 *(Destination8++) = *(Source8++);
1014 }
1015
1016 return EFI_SUCCESS;
1017 }