3 Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This contains all code necessary to build the GenFvImage.exe utility.
19 This utility relies heavily on the GenFvImage Lib. Definitions for both
20 can be found in the Tiano Firmware Volume Generation Utility
21 Specification, review draft.
26 // File included in build
31 #include "GenFvInternalLib.h"
36 #define UTILITY_NAME "GenFv"
39 // Utility version information
41 #define UTILITY_MAJOR_VERSION 0
42 #define UTILITY_MINOR_VERSION 1
44 EFI_GUID mEfiFirmwareFileSystem2Guid
= EFI_FIRMWARE_FILE_SYSTEM2_GUID
;
45 EFI_GUID mEfiFirmwareFileSystem3Guid
= EFI_FIRMWARE_FILE_SYSTEM3_GUID
;
56 Displays the standard utility information to SDTOUT
68 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
80 Displays the utility usage syntax to STDOUT
95 fprintf (stdout
, "\nUsage: %s [options]\n\n", UTILITY_NAME
);
98 // Copyright declaration
100 fprintf (stdout
, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
105 fprintf (stdout
, "Options:\n");
106 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
107 File is the FvImage or CapImage to be created.\n");
108 fprintf (stdout
, " -i FileName, --inputfile FileName\n\
109 File is the input FV.inf or Cap.inf to specify\n\
110 how to construct FvImage or CapImage.\n");
111 fprintf (stdout
, " -b BlockSize, --blocksize BlockSize\n\
112 BlockSize is one HEX or DEC format value\n\
113 BlockSize is required by Fv Image.\n");
114 fprintf (stdout
, " -n NumberBlock, --numberblock NumberBlock\n\
115 NumberBlock is one HEX or DEC format value\n\
116 NumberBlock is one optional parameter.\n");
117 fprintf (stdout
, " -f FfsFile, --ffsfile FfsFile\n\
118 FfsFile is placed into Fv Image\n\
119 multi files can input one by one\n");
120 fprintf (stdout
, " -s FileTakenSize, --filetakensize FileTakenSize\n\
121 FileTakenSize specifies the size of the required\n\
122 space that the input file is placed in Fvimage.\n\
123 It is specified together with the input file.\n");
124 fprintf (stdout
, " -r Address, --baseaddr Address\n\
125 Address is the rebase start address for drivers that\n\
126 run in Flash. It supports DEC or HEX digital format.\n\
127 If it is set to zero, no rebase action will be taken\n");
128 fprintf (stdout
, " -F ForceRebase, --force-rebase ForceRebase\n\
129 If value is TRUE, will always take rebase action\n\
130 If value is FALSE, will always not take reabse action\n\
131 If not specified, will take rebase action if rebase address greater than zero, \n\
132 will not take rebase action if rebase address is zero.\n");
133 fprintf (stdout
, " -a AddressFile, --addrfile AddressFile\n\
134 AddressFile is one file used to record the child\n\
135 FV base address when current FV base address is set.\n");
136 fprintf (stdout
, " -m logfile, --map logfile\n\
137 Logfile is the output fv map file name. if it is not\n\
138 given, the FvName.map will be the default map file name\n");
139 fprintf (stdout
, " -g Guid, --guid Guid\n\
140 GuidValue is one specific capsule guid value\n\
141 or fv file system guid value.\n\
142 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
143 fprintf (stdout
, " --FvNameGuid Guid Guid is used to specify Fv Name.\n\
144 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
145 fprintf (stdout
, " --capflag CapFlag Capsule Reset Flag can be PersistAcrossReset,\n\
146 or PopulateSystemTable or InitiateReset or not set\n");
147 fprintf (stdout
, " --capoemflag CapOEMFlag\n\
148 Capsule OEM Flag is an integer between 0x0000 and 0xffff\n");
149 fprintf (stdout
, " --capheadsize HeadSize\n\
150 HeadSize is one HEX or DEC format value\n\
151 HeadSize is required by Capsule Image.\n");
152 fprintf (stdout
, " -c, --capsule Create Capsule Image.\n");
153 fprintf (stdout
, " -p, --dump Dump Capsule Image header.\n");
154 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
155 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
156 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
157 fprintf (stdout
, " --version Show program's version number and exit.\n");
158 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
173 This utility uses GenFvImage.Lib to build a firmware volume image.
177 FvInfFileName The name of an FV image description file or Capsule Image.
179 Arguments come in pair in any order.
184 EFI_SUCCESS No error conditions detected.
185 EFI_INVALID_PARAMETER One or more of the input parameters is invalid.
186 EFI_OUT_OF_RESOURCES A resource required by the utility was unavailable.
187 Most commonly this will be memory allocation
189 EFI_LOAD_ERROR GenFvImage.lib could not be loaded.
190 EFI_ABORTED Error executing the GenFvImage lib.
204 EFI_CAPSULE_HEADER
*CapsuleHeader
;
205 UINT64 LogLevel
, TempNumber
;
217 CapsuleHeader
= NULL
;
223 Status
= EFI_SUCCESS
;
225 SetUtilityName (UTILITY_NAME
);
228 Error (NULL
, 0, 1001, "Missing options", "No input options specified.");
234 // Init global data to Zero
236 memset (&mFvDataInfo
, 0, sizeof (FV_INFO
));
237 memset (&mCapDataInfo
, 0, sizeof (CAP_INFO
));
239 // Set the default FvGuid
241 memcpy (&mFvDataInfo
.FvFileSystemGuid
, &mEfiFirmwareFileSystem2Guid
, sizeof (EFI_GUID
));
242 mFvDataInfo
.ForceRebase
= -1;
245 // Parse command line
250 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
253 return STATUS_SUCCESS
;
256 if (stricmp (argv
[0], "--version") == 0) {
258 return STATUS_SUCCESS
;
262 if ((stricmp (argv
[0], "-i") == 0) || (stricmp (argv
[0], "--inputfile") == 0)) {
263 InfFileName
= argv
[1];
264 if (InfFileName
== NULL
) {
265 Error (NULL
, 0, 1003, "Invalid option value", "Input file can't be null");
273 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--addrfile") == 0)) {
274 AddrFileName
= argv
[1];
275 if (AddrFileName
== NULL
) {
276 Error (NULL
, 0, 1003, "Invalid option value", "Address file can't be null");
284 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
285 OutFileName
= argv
[1];
286 if (OutFileName
== NULL
) {
287 Error (NULL
, 0, 1003, "Invalid option value", "Output file can't be null");
295 if ((stricmp (argv
[0], "-r") == 0) || (stricmp (argv
[0], "--baseaddr") == 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 mFvDataInfo
.BaseAddress
= TempNumber
;
302 mFvDataInfo
.BaseAddressSet
= TRUE
;
308 if ((stricmp (argv
[0], "-b") == 0) || (stricmp (argv
[0], "--blocksize") == 0)) {
309 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempNumber
);
310 if (EFI_ERROR (Status
)) {
311 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
314 if (TempNumber
== 0) {
315 Error (NULL
, 0, 1003, "Invalid option value", "Fv block size can't be be set to zero");
318 mFvDataInfo
.FvBlocks
[0].Length
= (UINT32
) TempNumber
;
319 DebugMsg (NULL
, 0, 9, "FV Block Size", "%s = 0x%llx", EFI_BLOCK_SIZE_STRING
, (unsigned long long) TempNumber
);
325 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--numberblock") == 0)) {
326 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempNumber
);
327 if (EFI_ERROR (Status
)) {
328 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
331 if (TempNumber
== 0) {
332 Error (NULL
, 0, 1003, "Invalid option value", "Fv block number can't be set to zero");
335 mFvDataInfo
.FvBlocks
[0].NumBlocks
= (UINT32
) TempNumber
;
336 DebugMsg (NULL
, 0, 9, "FV Number Block", "%s = 0x%llx", EFI_NUM_BLOCKS_STRING
, (unsigned long long) TempNumber
);
342 if ((strcmp (argv
[0], "-f") == 0) || (stricmp (argv
[0], "--ffsfile") == 0)) {
343 if (argv
[1] == NULL
) {
344 Error (NULL
, 0, 1003, "Invalid option value", "Input Ffsfile can't be null");
347 strcpy (mFvDataInfo
.FvFiles
[Index
], argv
[1]);
348 DebugMsg (NULL
, 0, 9, "FV component file", "the %uth name is %s", (unsigned) Index
+ 1, argv
[1]);
353 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--filetakensize") == 0)) {
354 if (argv
[1] == NULL
) {
355 Error (NULL
, 0, 1003, "Invalid option value", "Ffsfile Size can't be null");
358 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempNumber
);
359 if (EFI_ERROR (Status
)) {
360 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
363 mFvDataInfo
.SizeofFvFiles
[Index
] = (UINT32
) TempNumber
;
364 DebugMsg (NULL
, 0, 9, "FV component file size", "the %uth size is %s", (unsigned) Index
+ 1, argv
[1]);
373 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--filetakensize") == 0)) {
374 Error (NULL
, 0, 1003, "Invalid option", "It must be specified together with -f option to specify the file size.");
378 if ((stricmp (argv
[0], "-c") == 0) || (stricmp (argv
[0], "--capsule") == 0)) {
385 if ((strcmp (argv
[0], "-F") == 0) || (stricmp (argv
[0], "--force-rebase") == 0)) {
386 if (argv
[1] == NULL
) {
387 Error (NULL
, 0, 1003, "Invalid option value", "Froce rebase flag can't be null");
391 if (stricmp (argv
[1], "TRUE") == 0) {
392 mFvDataInfo
.ForceRebase
= 1;
393 } else if (stricmp (argv
[1], "FALSE") == 0) {
394 mFvDataInfo
.ForceRebase
= 0;
396 Error (NULL
, 0, 1003, "Invalid option value", "froce rebase flag value must be \"TRUE\" or \"FALSE\"");
405 if (stricmp (argv
[0], "--capheadsize") == 0) {
407 // Get Capsule Image Header Size
409 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &TempNumber
);
410 if (EFI_ERROR (Status
)) {
411 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
414 mCapDataInfo
.HeaderSize
= (UINT32
) TempNumber
;
415 DebugMsg (NULL
, 0, 9, "Capsule Header size", "%s = 0x%llx", EFI_CAPSULE_HEADER_SIZE_STRING
, (unsigned long long) TempNumber
);
421 if (stricmp (argv
[0], "--capflag") == 0) {
423 // Get Capsule Header
425 if (argv
[1] == NULL
) {
426 Error (NULL
, 0, 1003, "Option value is not set", "%s = %s", argv
[0], argv
[1]);
429 if (strcmp (argv
[1], "PopulateSystemTable") == 0) {
430 mCapDataInfo
.Flags
|= CAPSULE_FLAGS_PERSIST_ACROSS_RESET
| CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE
;
431 } else if (strcmp (argv
[1], "PersistAcrossReset") == 0) {
432 mCapDataInfo
.Flags
|= CAPSULE_FLAGS_PERSIST_ACROSS_RESET
;
433 } else if (strcmp (argv
[1], "InitiateReset") == 0) {
434 mCapDataInfo
.Flags
|= CAPSULE_FLAGS_PERSIST_ACROSS_RESET
| CAPSULE_FLAGS_INITIATE_RESET
;
436 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
439 DebugMsg (NULL
, 0, 9, "Capsule Flag", argv
[1]);
445 if (stricmp (argv
[0], "--capoemflag") == 0) {
446 if (argv
[1] == NULL
) {
447 Error (NULL
, 0, 1003, "Invalid option value", "Capsule OEM flag can't be null");
449 Status
= AsciiStringToUint64(argv
[1], FALSE
, &TempNumber
);
450 if (EFI_ERROR (Status
) || TempNumber
> 0xffff) {
451 Error (NULL
, 0, 1003, "Invalid option value", "Capsule OEM flag value must be integer value between 0x0000 and 0xffff");
454 mCapDataInfo
.Flags
|= TempNumber
;
455 DebugMsg( NULL
, 0, 9, "Capsule OEM Flags", argv
[1]);
461 if (stricmp (argv
[0], "--capguid") == 0) {
463 // Get the Capsule Guid
465 Status
= StringToGuid (argv
[1], &mCapDataInfo
.CapGuid
);
466 if (EFI_ERROR (Status
)) {
467 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", EFI_CAPSULE_GUID_STRING
, argv
[1]);
470 DebugMsg (NULL
, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING
, argv
[1]);
476 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--guid") == 0)) {
478 // Get the Capsule or Fv Guid
480 Status
= StringToGuid (argv
[1], &mCapDataInfo
.CapGuid
);
481 if (EFI_ERROR (Status
)) {
482 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", EFI_GUID_STRING
, argv
[1]);
485 memcpy (&mFvDataInfo
.FvFileSystemGuid
, &mCapDataInfo
.CapGuid
, sizeof (EFI_GUID
));
486 mFvDataInfo
.FvFileSystemGuidSet
= TRUE
;
487 DebugMsg (NULL
, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING
, argv
[1]);
488 DebugMsg (NULL
, 0, 9, "FV Guid", "%s = %s", EFI_FV_FILESYSTEMGUID_STRING
, argv
[1]);
494 if (stricmp (argv
[0], "--FvNameGuid") == 0) {
498 Status
= StringToGuid (argv
[1], &mFvDataInfo
.FvNameGuid
);
499 if (EFI_ERROR (Status
)) {
500 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", EFI_GUID_STRING
, argv
[1]);
503 mFvDataInfo
.FvNameGuidSet
= TRUE
;
504 DebugMsg (NULL
, 0, 9, "FV Name Guid", "%s = %s", EFI_FV_NAMEGUID_STRING
, argv
[1]);
510 if ((stricmp (argv
[0], "-p") == 0) || (stricmp (argv
[0], "--dump") == 0)) {
517 if ((stricmp (argv
[0], "-m") == 0) || (stricmp (argv
[0], "--map") == 0)) {
518 MapFileName
= argv
[1];
519 if (MapFileName
== NULL
) {
520 Error (NULL
, 0, 1003, "Invalid option value", "Map file can't be null");
528 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
529 SetPrintLevel (VERBOSE_LOG_LEVEL
);
530 VerboseMsg ("Verbose output Mode Set!");
536 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
537 SetPrintLevel (KEY_LOG_LEVEL
);
538 KeyMsg ("Quiet output Mode Set!");
544 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
545 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
546 if (EFI_ERROR (Status
)) {
547 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
551 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
554 SetPrintLevel (LogLevel
);
555 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
562 // Don't recognize the parameter.
564 Error (NULL
, 0, 1000, "Unknown option", "%s", argv
[0]);
568 VerboseMsg ("%s tool start.", UTILITY_NAME
);
571 // check input parameter, InfFileName can be NULL
573 if (InfFileName
== NULL
&& DumpCapsule
) {
574 Error (NULL
, 0, 1001, "Missing option", "Input Capsule Image");
577 VerboseMsg ("the input FvInf or CapInf file name is %s", InfFileName
);
579 if (!DumpCapsule
&& OutFileName
== NULL
) {
580 Error (NULL
, 0, 1001, "Missing option", "Output File");
583 if (OutFileName
!= NULL
) {
584 VerboseMsg ("the output file name is %s", OutFileName
);
588 // Read the INF file image
590 if (InfFileName
!= NULL
) {
591 Status
= GetFileImage (InfFileName
, &InfFileImage
, &InfFileSize
);
592 if (EFI_ERROR (Status
)) {
598 VerboseMsg ("Dump the capsule header information for the input capsule image %s", InfFileName
);
600 // Dump Capsule Image Header Information
602 CapsuleHeader
= (EFI_CAPSULE_HEADER
*) InfFileImage
;
603 if (OutFileName
== NULL
) {
606 FpFile
= fopen (LongFilePath (OutFileName
), "w");
607 if (FpFile
== NULL
) {
608 Error (NULL
, 0, 0001, "Error opening file", OutFileName
);
612 fprintf (FpFile
, "Capsule %s Image Header Information\n", InfFileName
);
613 fprintf (FpFile
, " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n",
614 (unsigned) CapsuleHeader
->CapsuleGuid
.Data1
,
615 (unsigned) CapsuleHeader
->CapsuleGuid
.Data2
,
616 (unsigned) CapsuleHeader
->CapsuleGuid
.Data3
,
617 (unsigned) CapsuleHeader
->CapsuleGuid
.Data4
[0],
618 (unsigned) CapsuleHeader
->CapsuleGuid
.Data4
[1],
619 (unsigned) CapsuleHeader
->CapsuleGuid
.Data4
[2],
620 (unsigned) CapsuleHeader
->CapsuleGuid
.Data4
[3],
621 (unsigned) CapsuleHeader
->CapsuleGuid
.Data4
[4],
622 (unsigned) CapsuleHeader
->CapsuleGuid
.Data4
[5],
623 (unsigned) CapsuleHeader
->CapsuleGuid
.Data4
[6],
624 (unsigned) CapsuleHeader
->CapsuleGuid
.Data4
[7]);
625 fprintf (FpFile
, " Header size 0x%08X\n", (unsigned) CapsuleHeader
->HeaderSize
);
626 fprintf (FpFile
, " Flags 0x%08X\n", (unsigned) CapsuleHeader
->Flags
);
627 fprintf (FpFile
, " Capsule image size 0x%08X\n", (unsigned) CapsuleHeader
->CapsuleImageSize
);
629 } else if (CapsuleFlag
) {
630 VerboseMsg ("Create capsule image");
632 // Call the GenerateCapImage to generate Capsule Image
634 for (Index
= 0; mFvDataInfo
.FvFiles
[Index
][0] != '\0'; Index
++) {
635 strcpy (mCapDataInfo
.CapFiles
[Index
], mFvDataInfo
.FvFiles
[Index
]);
638 Status
= GenerateCapImage (
644 VerboseMsg ("Create Fv image and its map file");
646 // Will take rebase action at below situation:
647 // 1. ForceRebase Flag specified to TRUE;
648 // 2. ForceRebase Flag not specified, BaseAddress greater than zero.
650 if (((mFvDataInfo
.BaseAddress
> 0) && (mFvDataInfo
.ForceRebase
== -1)) || (mFvDataInfo
.ForceRebase
== 1)) {
651 VerboseMsg ("FvImage Rebase Address is 0x%llX", (unsigned long long) mFvDataInfo
.BaseAddress
);
654 // Call the GenerateFvImage to generate Fv Image
656 Status
= GenerateFvImage (
665 // free InfFileImage memory
667 if (InfFileImage
!= NULL
) {
672 // update boot driver address and runtime driver address in address file
674 if (Status
== EFI_SUCCESS
&& AddrFileName
!= NULL
&& mFvBaseAddressNumber
> 0) {
675 FpFile
= fopen (LongFilePath (AddrFileName
), "w");
676 if (FpFile
== NULL
) {
677 Error (NULL
, 0, 0001, "Error opening file", AddrFileName
);
680 fprintf (FpFile
, FV_BASE_ADDRESS_STRING
);
681 fprintf (FpFile
, "\n");
682 for (Index
= 0; Index
< mFvBaseAddressNumber
; Index
++) {
686 (unsigned long long)mFvBaseAddress
[Index
]
693 if (Status
== EFI_SUCCESS
) {
694 DebugMsg (NULL
, 0, 9, "The Total Fv Size", "%s = 0x%x", EFI_FV_TOTAL_SIZE_STRING
, (unsigned) mFvTotalSize
);
695 DebugMsg (NULL
, 0, 9, "The used Fv Size", "%s = 0x%x", EFI_FV_TAKEN_SIZE_STRING
, (unsigned) mFvTakenSize
);
696 DebugMsg (NULL
, 0, 9, "The space Fv size", "%s = 0x%x", EFI_FV_SPACE_SIZE_STRING
, (unsigned) (mFvTotalSize
- mFvTakenSize
));
699 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
701 return GetUtilityStatus ();