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