1 /** @file
2   This contains all code necessary to build the GenFvImage.exe utility.
3   This utility relies heavily on the GenFvImage Lib.  Definitions for both
4   can be found in the Tiano Firmware Volume Generation Utility
5   Specification, review draft.
6 
7 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9 
10 **/
11 
12 //
13 // File included in build
14 //
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include "GenFvInternalLib.h"
19 
20 //
21 // Utility Name
22 //
23 #define UTILITY_NAME  "GenFv"
24 
25 //
26 // Utility version information
27 //
28 #define UTILITY_MAJOR_VERSION 0
29 #define UTILITY_MINOR_VERSION 1
30 
31 EFI_GUID  mEfiFirmwareFileSystem2Guid = EFI_FIRMWARE_FILE_SYSTEM2_GUID;
32 EFI_GUID  mEfiFirmwareFileSystem3Guid = EFI_FIRMWARE_FILE_SYSTEM3_GUID;
33 
34 STATIC
35 VOID
Version(VOID)36 Version (
37   VOID
38 )
39 /*++
40 
41 Routine Description:
42 
43   Displays the standard utility information to SDTOUT
44 
45 Arguments:
46 
47   None
48 
49 Returns:
50 
51   None
52 
53 --*/
54 {
55   fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
56 }
57 
58 STATIC
59 VOID
Usage(VOID)60 Usage (
61   VOID
62   )
63 /*++
64 
65 Routine Description:
66 
67   Displays the utility usage syntax to STDOUT
68 
69 Arguments:
70 
71   None
72 
73 Returns:
74 
75   None
76 
77 --*/
78 {
79   //
80   // Summary usage
81   //
82   fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME);
83 
84   //
85   // Copyright declaration
86   //
87   fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
88 
89   //
90   // Details Option
91   //
92   fprintf (stdout, "Options:\n");
93   fprintf (stdout, "  -o FileName, --outputfile FileName\n\
94                         File is the FvImage or CapImage to be created.\n");
95   fprintf (stdout, "  -i FileName, --inputfile FileName\n\
96                         File is the input FV.inf or Cap.inf to specify\n\
97                         how to construct FvImage or CapImage.\n");
98   fprintf (stdout, "  -b BlockSize, --blocksize BlockSize\n\
99                         BlockSize is one HEX or DEC format value\n\
100                         BlockSize is required by Fv Image.\n");
101   fprintf (stdout, "  -n NumberBlock, --numberblock NumberBlock\n\
102                         NumberBlock is one HEX or DEC format value\n\
103                         NumberBlock is one optional parameter.\n");
104   fprintf (stdout, "  -f FfsFile, --ffsfile FfsFile\n\
105                         FfsFile is placed into Fv Image\n\
106                         multi files can input one by one\n");
107   fprintf (stdout, "  -s FileTakenSize, --filetakensize FileTakenSize\n\
108                         FileTakenSize specifies the size of the required\n\
109                         space that the input file is placed in Fvimage.\n\
110                         It is specified together with the input file.\n");
111   fprintf (stdout, "  -r Address, --baseaddr Address\n\
112                         Address is the rebase start address for drivers that\n\
113                         run in Flash. It supports DEC or HEX digital format.\n\
114                         If it is set to zero, no rebase action will be taken\n");
115   fprintf (stdout, "  -F ForceRebase, --force-rebase ForceRebase\n\
116                         If value is TRUE, will always take rebase action\n\
117                         If value is FALSE, will always not take reabse action\n\
118                         If not specified, will take rebase action if rebase address greater than zero, \n\
119                         will not take rebase action if rebase address is zero.\n");
120   fprintf (stdout, "  -a AddressFile, --addrfile AddressFile\n\
121                         AddressFile is one file used to record the child\n\
122                         FV base address when current FV base address is set.\n");
123   fprintf (stdout, "  -m logfile, --map logfile\n\
124                         Logfile is the output fv map file name. if it is not\n\
125                         given, the FvName.map will be the default map file name\n");
126   fprintf (stdout, "  -g Guid, --guid Guid\n\
127                         GuidValue is one specific capsule guid value\n\
128                         or fv file system guid value.\n\
129                         Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
130   fprintf (stdout, "  --FvNameGuid Guid     Guid is used to specify Fv Name.\n\
131                         Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
132   fprintf (stdout, "  --capflag CapFlag     Capsule Reset Flag can be PersistAcrossReset,\n\
133                         or PopulateSystemTable or InitiateReset or not set\n");
134   fprintf (stdout, "  --capoemflag CapOEMFlag\n\
135                         Capsule OEM Flag is an integer between 0x0000 and 0xffff\n");
136   fprintf (stdout, "  --capheadsize HeadSize\n\
137                         HeadSize is one HEX or DEC format value\n\
138                         HeadSize is required by Capsule Image.\n");
139   fprintf (stdout, "  -c, --capsule         Create Capsule Image.\n");
140   fprintf (stdout, "  -p, --dump            Dump Capsule Image header.\n");
141   fprintf (stdout, "  -v, --verbose         Turn on verbose output with informational messages.\n");
142   fprintf (stdout, "  -q, --quiet           Disable all messages except key message and fatal error\n");
143   fprintf (stdout, "  -d, --debug level     Enable debug messages, at input debug level.\n");
144   fprintf (stdout, "  --version             Show program's version number and exit.\n");
145   fprintf (stdout, "  -h, --help            Show this help message and exit.\n");
146 }
147 
148 UINT32 mFvTotalSize;
149 UINT32 mFvTakenSize;
150 
151 int
main(IN int argc,IN char ** argv)152 main (
153   IN int   argc,
154   IN char  **argv
155   )
156 /*++
157 
158 Routine Description:
159 
160   This utility uses GenFvImage.Lib to build a firmware volume image.
161 
162 Arguments:
163 
164   FvInfFileName      The name of an FV image description file or Capsule Image.
165 
166   Arguments come in pair in any order.
167     -I FvInfFileName
168 
169 Returns:
170 
171   EFI_SUCCESS            No error conditions detected.
172   EFI_INVALID_PARAMETER  One or more of the input parameters is invalid.
173   EFI_OUT_OF_RESOURCES   A resource required by the utility was unavailable.
174                          Most commonly this will be memory allocation
175                          or file creation.
176   EFI_LOAD_ERROR         GenFvImage.lib could not be loaded.
177   EFI_ABORTED            Error executing the GenFvImage lib.
178 
179 --*/
180 {
181   EFI_STATUS            Status;
182   CHAR8                 *InfFileName;
183   CHAR8                 *AddrFileName;
184   CHAR8                 *MapFileName;
185   CHAR8                 *InfFileImage;
186   UINT32                InfFileSize;
187   CHAR8                 *OutFileName;
188   BOOLEAN               CapsuleFlag;
189   BOOLEAN               DumpCapsule;
190   FILE                  *FpFile;
191   EFI_CAPSULE_HEADER    *CapsuleHeader;
192   UINT64                LogLevel, TempNumber;
193   UINT32                Index;
194 
195   InfFileName   = NULL;
196   AddrFileName  = NULL;
197   InfFileImage  = NULL;
198   OutFileName   = NULL;
199   MapFileName   = NULL;
200   InfFileSize   = 0;
201   CapsuleFlag   = FALSE;
202   DumpCapsule   = FALSE;
203   FpFile        = NULL;
204   CapsuleHeader = NULL;
205   LogLevel      = 0;
206   TempNumber    = 0;
207   Index         = 0;
208   mFvTotalSize  = 0;
209   mFvTakenSize  = 0;
210   Status        = EFI_SUCCESS;
211 
212   SetUtilityName (UTILITY_NAME);
213 
214   if (argc == 1) {
215     Error (NULL, 0, 1001, "Missing options", "No input options specified.");
216     Usage ();
217     return STATUS_ERROR;
218   }
219 
220   //
221   // Init global data to Zero
222   //
223   memset (&mFvDataInfo, 0, sizeof (FV_INFO));
224   memset (&mCapDataInfo, 0, sizeof (CAP_INFO));
225   //
226   // Set the default FvGuid
227   //
228   memcpy (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid, sizeof (EFI_GUID));
229   mFvDataInfo.ForceRebase = -1;
230 
231   //
232   // Parse command line
233   //
234   argc --;
235   argv ++;
236 
237   if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
238     Version ();
239     Usage ();
240     return STATUS_SUCCESS;
241   }
242 
243   if (stricmp (argv[0], "--version") == 0) {
244     Version ();
245     return STATUS_SUCCESS;
246   }
247 
248   while (argc > 0) {
249     if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--inputfile") == 0)) {
250       InfFileName = argv[1];
251       if (InfFileName == NULL) {
252         Error (NULL, 0, 1003, "Invalid option value", "Input file can't be null");
253         return STATUS_ERROR;
254       }
255       argc -= 2;
256       argv += 2;
257       continue;
258     }
259 
260     if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--addrfile") == 0)) {
261       AddrFileName = argv[1];
262       if (AddrFileName == NULL) {
263         Error (NULL, 0, 1003, "Invalid option value", "Address file can't be null");
264         return STATUS_ERROR;
265       }
266       argc -= 2;
267       argv += 2;
268       continue;
269     }
270 
271     if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
272       OutFileName = argv[1];
273       if (OutFileName == NULL) {
274         Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null");
275         return STATUS_ERROR;
276       }
277       argc -= 2;
278       argv += 2;
279       continue;
280     }
281 
282     if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) {
283       Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber);
284       if (EFI_ERROR (Status)) {
285         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
286         return STATUS_ERROR;
287       }
288       mFvDataInfo.BaseAddress    = TempNumber;
289       mFvDataInfo.BaseAddressSet = TRUE;
290       argc -= 2;
291       argv += 2;
292       continue;
293     }
294 
295     if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--blocksize") == 0)) {
296       Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber);
297       if (EFI_ERROR (Status)) {
298         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
299         return STATUS_ERROR;
300       }
301       if (TempNumber == 0) {
302         Error (NULL, 0, 1003, "Invalid option value", "Fv block size can't be be set to zero");
303         return STATUS_ERROR;
304       }
305       mFvDataInfo.FvBlocks[0].Length = (UINT32) TempNumber;
306       DebugMsg (NULL, 0, 9, "FV Block Size", "%s = 0x%llx", EFI_BLOCK_SIZE_STRING, (unsigned long long) TempNumber);
307       argc -= 2;
308       argv += 2;
309       continue;
310     }
311 
312     if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--numberblock") == 0)) {
313       Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber);
314       if (EFI_ERROR (Status)) {
315         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
316         return STATUS_ERROR;
317       }
318       if (TempNumber == 0) {
319         Error (NULL, 0, 1003, "Invalid option value", "Fv block number can't be set to zero");
320         return STATUS_ERROR;
321       }
322       mFvDataInfo.FvBlocks[0].NumBlocks = (UINT32) TempNumber;
323       DebugMsg (NULL, 0, 9, "FV Number Block", "%s = 0x%llx", EFI_NUM_BLOCKS_STRING, (unsigned long long) TempNumber);
324       argc -= 2;
325       argv += 2;
326       continue;
327     }
328 
329     if ((strcmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--ffsfile") == 0)) {
330       if (argv[1] == NULL) {
331         Error (NULL, 0, 1003, "Invalid option value", "Input Ffsfile can't be null");
332         return STATUS_ERROR;
333       }
334       if (strlen (argv[1]) > MAX_LONG_FILE_PATH - 1) {
335         Error (NULL, 0, 1003, "Invalid option value", "Input Ffsfile name %s is too long!", argv[1]);
336         return STATUS_ERROR;
337       }
338       strncpy (mFvDataInfo.FvFiles[Index], argv[1], MAX_LONG_FILE_PATH - 1);
339       mFvDataInfo.FvFiles[Index][MAX_LONG_FILE_PATH - 1] = 0;
340       DebugMsg (NULL, 0, 9, "FV component file", "the %uth name is %s", (unsigned) Index + 1, argv[1]);
341       argc -= 2;
342       argv += 2;
343 
344       if (argc > 0) {
345         if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--filetakensize") == 0)) {
346           if (argv[1] == NULL) {
347             Error (NULL, 0, 1003, "Invalid option value", "Ffsfile Size can't be null");
348             return STATUS_ERROR;
349           }
350           Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber);
351           if (EFI_ERROR (Status)) {
352             Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
353             return STATUS_ERROR;
354           }
355           mFvDataInfo.SizeofFvFiles[Index] = (UINT32) TempNumber;
356           DebugMsg (NULL, 0, 9, "FV component file size", "the %uth size is %s", (unsigned) Index + 1, argv[1]);
357           argc -= 2;
358           argv += 2;
359         }
360       }
361       Index ++;
362       continue;
363     }
364 
365     if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--filetakensize") == 0)) {
366       Error (NULL, 0, 1003, "Invalid option", "It must be specified together with -f option to specify the file size.");
367       return STATUS_ERROR;
368     }
369 
370     if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--capsule") == 0)) {
371       CapsuleFlag = TRUE;
372       argc --;
373       argv ++;
374       continue;
375     }
376 
377     if ((strcmp (argv[0], "-F") == 0) || (stricmp (argv[0], "--force-rebase") == 0)) {
378       if (argv[1] == NULL) {
379         Error (NULL, 0, 1003, "Invalid option value", "Froce rebase flag can't be null");
380         return STATUS_ERROR;
381       }
382 
383       if (stricmp (argv[1], "TRUE") == 0) {
384         mFvDataInfo.ForceRebase = 1;
385       } else if (stricmp (argv[1], "FALSE") == 0) {
386         mFvDataInfo.ForceRebase = 0;
387       } else {
388         Error (NULL, 0, 1003, "Invalid option value", "froce rebase flag value must be \"TRUE\" or \"FALSE\"");
389         return STATUS_ERROR;
390       }
391 
392       argc -= 2;
393       argv += 2;
394       continue;
395     }
396 
397     if (stricmp (argv[0], "--capheadsize") == 0) {
398       //
399       // Get Capsule Image Header Size
400       //
401       Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber);
402       if (EFI_ERROR (Status)) {
403         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
404         return STATUS_ERROR;
405       }
406       mCapDataInfo.HeaderSize = (UINT32) TempNumber;
407       DebugMsg (NULL, 0, 9, "Capsule Header size", "%s = 0x%llx", EFI_CAPSULE_HEADER_SIZE_STRING, (unsigned long long) TempNumber);
408       argc -= 2;
409       argv += 2;
410       continue;
411     }
412 
413     if (stricmp (argv[0], "--capflag") == 0) {
414       //
415       // Get Capsule Header
416       //
417       if (argv[1] == NULL) {
418         Error (NULL, 0, 1003, "Option value is not set", "%s = %s", argv[0], argv[1]);
419         return STATUS_ERROR;
420       }
421       if (strcmp (argv[1], "PopulateSystemTable") == 0) {
422         mCapDataInfo.Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE;
423       } else if (strcmp (argv[1], "PersistAcrossReset") == 0) {
424         mCapDataInfo.Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET;
425       } else if (strcmp (argv[1], "InitiateReset") == 0) {
426         mCapDataInfo.Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET;
427       } else {
428         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
429         return STATUS_ERROR;
430       }
431       DebugMsg (NULL, 0, 9, "Capsule Flag", argv[1]);
432       argc -= 2;
433       argv += 2;
434       continue;
435     }
436 
437     if (stricmp (argv[0], "--capoemflag") == 0) {
438       if (argv[1] == NULL) {
439         Error (NULL, 0, 1003, "Invalid option value", "Capsule OEM flag can't be null");
440       }
441       Status = AsciiStringToUint64(argv[1], FALSE, &TempNumber);
442       if (EFI_ERROR (Status) || TempNumber > 0xffff) {
443         Error (NULL, 0, 1003, "Invalid option value", "Capsule OEM flag value must be integer value between 0x0000 and 0xffff");
444         return STATUS_ERROR;
445       }
446       mCapDataInfo.Flags |= TempNumber;
447       DebugMsg( NULL, 0, 9, "Capsule OEM Flags", argv[1]);
448       argc -= 2;
449       argv += 2;
450       continue;
451     }
452 
453     if (stricmp (argv[0], "--capguid") == 0) {
454       //
455       // Get the Capsule Guid
456       //
457       Status = StringToGuid (argv[1], &mCapDataInfo.CapGuid);
458       if (EFI_ERROR (Status)) {
459         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]);
460         return STATUS_ERROR;
461       }
462       DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]);
463       argc -= 2;
464       argv += 2;
465       continue;
466     }
467 
468     if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--guid") == 0)) {
469       //
470       // Get the Capsule or Fv Guid
471       //
472       Status = StringToGuid (argv[1], &mCapDataInfo.CapGuid);
473       if (EFI_ERROR (Status)) {
474         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_GUID_STRING, argv[1]);
475         return STATUS_ERROR;
476       }
477       memcpy (&mFvDataInfo.FvFileSystemGuid, &mCapDataInfo.CapGuid, sizeof (EFI_GUID));
478       mFvDataInfo.FvFileSystemGuidSet = TRUE;
479       DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]);
480       DebugMsg (NULL, 0, 9, "FV Guid", "%s = %s", EFI_FV_FILESYSTEMGUID_STRING, argv[1]);
481       argc -= 2;
482       argv += 2;
483       continue;
484     }
485 
486     if (stricmp (argv[0], "--FvNameGuid") == 0) {
487       //
488       // Get Fv Name Guid
489       //
490       Status = StringToGuid (argv[1], &mFvDataInfo.FvNameGuid);
491       if (EFI_ERROR (Status)) {
492         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_GUID_STRING, argv[1]);
493         return STATUS_ERROR;
494       }
495       mFvDataInfo.FvNameGuidSet = TRUE;
496       DebugMsg (NULL, 0, 9, "FV Name Guid", "%s = %s", EFI_FV_NAMEGUID_STRING, argv[1]);
497       argc -= 2;
498       argv += 2;
499       continue;
500     }
501 
502     if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--dump") == 0)) {
503       DumpCapsule = TRUE;
504       argc --;
505       argv ++;
506       continue;
507     }
508 
509     if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--map") == 0)) {
510       MapFileName = argv[1];
511       if (MapFileName == NULL) {
512         Error (NULL, 0, 1003, "Invalid option value", "Map file can't be null");
513         return STATUS_ERROR;
514       }
515       argc -= 2;
516       argv += 2;
517       continue;
518     }
519 
520     if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
521       SetPrintLevel (VERBOSE_LOG_LEVEL);
522       VerboseMsg ("Verbose output Mode Set!");
523       argc --;
524       argv ++;
525       continue;
526     }
527 
528     if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
529       SetPrintLevel (KEY_LOG_LEVEL);
530       KeyMsg ("Quiet output Mode Set!");
531       argc --;
532       argv ++;
533       continue;
534     }
535 
536     if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
537       Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
538       if (EFI_ERROR (Status)) {
539         Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
540         return STATUS_ERROR;
541       }
542       if (LogLevel > 9) {
543         Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);
544         return STATUS_ERROR;
545       }
546       SetPrintLevel (LogLevel);
547       DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
548       argc -= 2;
549       argv += 2;
550       continue;
551     }
552 
553     //
554     // Don't recognize the parameter.
555     //
556     Error (NULL, 0, 1000, "Unknown option", "%s", argv[0]);
557     return STATUS_ERROR;
558   }
559 
560   VerboseMsg ("%s tool start.", UTILITY_NAME);
561 
562   //
563   // check input parameter, InfFileName can be NULL
564   //
565   if (InfFileName == NULL && DumpCapsule) {
566     Error (NULL, 0, 1001, "Missing option", "Input Capsule Image");
567     return STATUS_ERROR;
568   }
569   VerboseMsg ("the input FvInf or CapInf file name is %s", InfFileName);
570 
571   if (!DumpCapsule && OutFileName == NULL) {
572     Error (NULL, 0, 1001, "Missing option", "Output File");
573     return STATUS_ERROR;
574   }
575   if (OutFileName != NULL) {
576     VerboseMsg ("the output file name is %s", OutFileName);
577   }
578 
579   //
580   // Read the INF file image
581   //
582   if (InfFileName != NULL) {
583     Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize);
584     if (EFI_ERROR (Status)) {
585       return STATUS_ERROR;
586     }
587   }
588 
589   if (DumpCapsule) {
590     VerboseMsg ("Dump the capsule header information for the input capsule image %s", InfFileName);
591     //
592     // Dump Capsule Image Header Information
593     //
594     CapsuleHeader = (EFI_CAPSULE_HEADER *) InfFileImage;
595     if (OutFileName == NULL) {
596       FpFile = stdout;
597     } else {
598       FpFile = fopen (LongFilePath (OutFileName), "w");
599       if (FpFile == NULL) {
600         Error (NULL, 0, 0001, "Error opening file", OutFileName);
601         return STATUS_ERROR;
602       }
603     }
604     if (FpFile != NULL) {
605       fprintf (FpFile, "Capsule %s Image Header Information\n", InfFileName);
606       fprintf (FpFile, "  GUID                  %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
607                       (unsigned) CapsuleHeader->CapsuleGuid.Data1,
608                       (unsigned) CapsuleHeader->CapsuleGuid.Data2,
609                       (unsigned) CapsuleHeader->CapsuleGuid.Data3,
610                       (unsigned) CapsuleHeader->CapsuleGuid.Data4[0],
611                       (unsigned) CapsuleHeader->CapsuleGuid.Data4[1],
612                       (unsigned) CapsuleHeader->CapsuleGuid.Data4[2],
613                       (unsigned) CapsuleHeader->CapsuleGuid.Data4[3],
614                       (unsigned) CapsuleHeader->CapsuleGuid.Data4[4],
615                       (unsigned) CapsuleHeader->CapsuleGuid.Data4[5],
616                       (unsigned) CapsuleHeader->CapsuleGuid.Data4[6],
617                       (unsigned) CapsuleHeader->CapsuleGuid.Data4[7]);
618       fprintf (FpFile, "  Header size           0x%08X\n", (unsigned) CapsuleHeader->HeaderSize);
619       fprintf (FpFile, "  Flags                 0x%08X\n", (unsigned) CapsuleHeader->Flags);
620       fprintf (FpFile, "  Capsule image size    0x%08X\n", (unsigned) CapsuleHeader->CapsuleImageSize);
621       fclose (FpFile);
622     }
623   } else if (CapsuleFlag) {
624     VerboseMsg ("Create capsule image");
625     //
626     // Call the GenerateCapImage to generate Capsule Image
627     //
628     for (Index = 0; mFvDataInfo.FvFiles[Index][0] != '\0'; Index ++) {
629       strcpy (mCapDataInfo.CapFiles[Index], mFvDataInfo.FvFiles[Index]);
630     }
631 
632     Status = GenerateCapImage (
633               InfFileImage,
634               InfFileSize,
635               OutFileName
636               );
637   } else {
638     VerboseMsg ("Create Fv image and its map file");
639     //
640     // Will take rebase action at below situation:
641     // 1. ForceRebase Flag specified to TRUE;
642     // 2. ForceRebase Flag not specified, BaseAddress greater than zero.
643     //
644     if (((mFvDataInfo.BaseAddress > 0) && (mFvDataInfo.ForceRebase == -1)) || (mFvDataInfo.ForceRebase == 1)) {
645       VerboseMsg ("FvImage Rebase Address is 0x%llX", (unsigned long long) mFvDataInfo.BaseAddress);
646     }
647     //
648     // Call the GenerateFvImage to generate Fv Image
649     //
650     Status = GenerateFvImage (
651               InfFileImage,
652               InfFileSize,
653               OutFileName,
654               MapFileName
655               );
656   }
657 
658   //
659   // free InfFileImage memory
660   //
661   if (InfFileImage != NULL) {
662     free (InfFileImage);
663   }
664 
665   //
666   //  update boot driver address and runtime driver address in address file
667   //
668   if (Status == EFI_SUCCESS && AddrFileName != NULL && mFvBaseAddressNumber > 0) {
669     FpFile = fopen (LongFilePath (AddrFileName), "w");
670     if (FpFile == NULL) {
671       Error (NULL, 0, 0001, "Error opening file", AddrFileName);
672       return STATUS_ERROR;
673     }
674     fprintf (FpFile, FV_BASE_ADDRESS_STRING);
675     fprintf (FpFile, "\n");
676     for (Index = 0; Index < mFvBaseAddressNumber; Index ++) {
677       fprintf (
678         FpFile,
679         "0x%llx\n",
680         (unsigned long long)mFvBaseAddress[Index]
681         );
682     }
683     fflush (FpFile);
684     fclose (FpFile);
685   }
686 
687   if (Status == EFI_SUCCESS) {
688     DebugMsg (NULL, 0, 9, "The Total Fv Size", "%s = 0x%x", EFI_FV_TOTAL_SIZE_STRING, (unsigned) mFvTotalSize);
689     DebugMsg (NULL, 0, 9, "The used Fv Size", "%s = 0x%x", EFI_FV_TAKEN_SIZE_STRING, (unsigned) mFvTakenSize);
690     DebugMsg (NULL, 0, 9, "The space Fv size", "%s = 0x%x", EFI_FV_SPACE_SIZE_STRING, (unsigned) (mFvTotalSize - mFvTakenSize));
691   }
692 
693   VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
694 
695   return GetUtilityStatus ();
696 }
697