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