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.
7 Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
13 // File included in build
18 #include "GenFvInternalLib.h"
23 #define UTILITY_NAME "GenFv"
26 // Utility version information
28 #define UTILITY_MAJOR_VERSION 0
29 #define UTILITY_MINOR_VERSION 1
31 EFI_GUID mEfiFirmwareFileSystem2Guid
= EFI_FIRMWARE_FILE_SYSTEM2_GUID
;
32 EFI_GUID mEfiFirmwareFileSystem3Guid
= EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
43 Displays the standard utility information to SDTOUT
55 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
67 Displays the utility usage syntax to STDOUT
82 fprintf (stdout
, "\nUsage: %s [options]\n\n", UTILITY_NAME
);
85 // Copyright declaration
87 fprintf (stdout
, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
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");
160 This utility uses GenFvImage.Lib to build a firmware volume image.
164 FvInfFileName The name of an FV image description file or Capsule Image.
166 Arguments come in pair in any order.
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
176 EFI_LOAD_ERROR GenFvImage.lib could not be loaded.
177 EFI_ABORTED Error executing the GenFvImage lib.
191 EFI_CAPSULE_HEADER
*CapsuleHeader
;
192 UINT64 LogLevel
, TempNumber
;
204 CapsuleHeader
= NULL
;
210 Status
= EFI_SUCCESS
;
212 SetUtilityName (UTILITY_NAME
);
215 Error (NULL
, 0, 1001, "Missing options", "No input options specified.");
221 // Init global data to Zero
223 memset (&mFvDataInfo
, 0, sizeof (FV_INFO
));
224 memset (&mCapDataInfo
, 0, sizeof (CAP_INFO
));
226 // Set the default FvGuid
228 memcpy (&mFvDataInfo
.FvFileSystemGuid
, &mEfiFirmwareFileSystem2Guid
, sizeof (EFI_GUID
));
229 mFvDataInfo
.ForceRebase
= -1;
232 // Parse command line
237 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
240 return STATUS_SUCCESS
;
243 if (stricmp (argv
[0], "--version") == 0) {
245 return STATUS_SUCCESS
;
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");
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");
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");
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]);
288 mFvDataInfo
.BaseAddress
= TempNumber
;
289 mFvDataInfo
.BaseAddressSet
= TRUE
;
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]);
301 if (TempNumber
== 0) {
302 Error (NULL
, 0, 1003, "Invalid option value", "Fv block size can't be set to zero");
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
);
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]);
318 if (TempNumber
== 0) {
319 Error (NULL
, 0, 1003, "Invalid option value", "Fv block number can't be set to zero");
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
);
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");
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]);
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]);
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");
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]);
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]);
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.");
370 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--capsule") == 0)) {
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");
383 if (stricmp (argv
[1], "TRUE") == 0) {
384 mFvDataInfo
.ForceRebase
= 1;
385 } else if (stricmp (argv
[1], "FALSE") == 0) {
386 mFvDataInfo
.ForceRebase
= 0;
388 Error (NULL
, 0, 1003, "Invalid option value", "froce rebase flag value must be \"TRUE\" or \"FALSE\"");
397 if (stricmp (argv
[0], "--capheadsize") == 0) {
399 // Get Capsule Image Header Size
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]);
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
);
413 if (stricmp (argv
[0], "--capflag") == 0) {
415 // Get Capsule Header
417 if (argv
[1] == NULL
) {
418 Error (NULL
, 0, 1003, "Option value is not set", "%s = %s", argv
[0], argv
[1]);
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
;
428 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
431 DebugMsg (NULL
, 0, 9, "Capsule Flag", argv
[1]);
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");
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");
446 mCapDataInfo
.Flags
|= TempNumber
;
447 DebugMsg( NULL
, 0, 9, "Capsule OEM Flags", argv
[1]);
453 if (stricmp (argv
[0], "--capguid") == 0) {
455 // Get the Capsule Guid
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]);
462 DebugMsg (NULL
, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING
, argv
[1]);
468 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--guid") == 0)) {
470 // Get the Capsule or Fv Guid
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]);
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]);
486 if (stricmp (argv
[0], "--FvNameGuid") == 0) {
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]);
495 mFvDataInfo
.FvNameGuidSet
= TRUE
;
496 DebugMsg (NULL
, 0, 9, "FV Name Guid", "%s = %s", EFI_FV_NAMEGUID_STRING
, argv
[1]);
502 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
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");
520 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
521 SetPrintLevel (VERBOSE_LOG_LEVEL
);
522 VerboseMsg ("Verbose output Mode Set!");
528 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
529 SetPrintLevel (KEY_LOG_LEVEL
);
530 KeyMsg ("Quiet output Mode Set!");
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]);
543 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
546 SetPrintLevel (LogLevel
);
547 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
554 // Don't recognize the parameter.
556 Error (NULL
, 0, 1000, "Unknown option", "%s", argv
[0]);
560 VerboseMsg ("%s tool start.", UTILITY_NAME
);
563 // check input parameter, InfFileName can be NULL
565 if (InfFileName
== NULL
&& DumpCapsule
) {
566 Error (NULL
, 0, 1001, "Missing option", "Input Capsule Image");
569 VerboseMsg ("the input FvInf or CapInf file name is %s", InfFileName
);
571 if (!DumpCapsule
&& OutFileName
== NULL
) {
572 Error (NULL
, 0, 1001, "Missing option", "Output File");
575 if (OutFileName
!= NULL
) {
576 VerboseMsg ("the output file name is %s", OutFileName
);
580 // Read the INF file image
582 if (InfFileName
!= NULL
) {
583 Status
= GetFileImage (InfFileName
, &InfFileImage
, &InfFileSize
);
584 if (EFI_ERROR (Status
)) {
590 VerboseMsg ("Dump the capsule header information for the input capsule image %s", InfFileName
);
592 // Dump Capsule Image Header Information
594 CapsuleHeader
= (EFI_CAPSULE_HEADER
*) InfFileImage
;
595 if (OutFileName
== NULL
) {
598 FpFile
= fopen (LongFilePath (OutFileName
), "w");
599 if (FpFile
== NULL
) {
600 Error (NULL
, 0, 0001, "Error opening file", OutFileName
);
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
);
623 } else if (CapsuleFlag
) {
624 VerboseMsg ("Create capsule image");
626 // Call the GenerateCapImage to generate Capsule Image
628 for (Index
= 0; mFvDataInfo
.FvFiles
[Index
][0] != '\0'; Index
++) {
629 strcpy (mCapDataInfo
.CapFiles
[Index
], mFvDataInfo
.FvFiles
[Index
]);
632 Status
= GenerateCapImage (
638 VerboseMsg ("Create Fv image and its map file");
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.
644 if (((mFvDataInfo
.BaseAddress
> 0) && (mFvDataInfo
.ForceRebase
== -1)) || (mFvDataInfo
.ForceRebase
== 1)) {
645 VerboseMsg ("FvImage Rebase Address is 0x%llX", (unsigned long long) mFvDataInfo
.BaseAddress
);
648 // Call the GenerateFvImage to generate Fv Image
650 Status
= GenerateFvImage (
659 // free InfFileImage memory
661 if (InfFileImage
!= NULL
) {
666 // update boot driver address and runtime driver address in address file
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
);
674 fprintf (FpFile
, FV_BASE_ADDRESS_STRING
);
675 fprintf (FpFile
, "\n");
676 for (Index
= 0; Index
< mFvBaseAddressNumber
; Index
++) {
680 (unsigned long long)mFvBaseAddress
[Index
]
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
));
693 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
695 return GetUtilityStatus ();