2 This file contains functions required to generate a Firmware File System file.
4 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #include <Common/UefiBaseTypes.h>
20 #include <Common/PiFirmwareFile.h>
21 #include <IndustryStandard/PeImage.h>
23 #include "CommonLib.h"
25 #include "EfiUtilityMsgs.h"
27 #define UTILITY_NAME "GenFfs"
28 #define UTILITY_MAJOR_VERSION 0
29 #define UTILITY_MINOR_VERSION 1
31 STATIC CHAR8
*mFfsFileType
[] = {
33 "EFI_FV_FILETYPE_RAW", // 0x01
34 "EFI_FV_FILETYPE_FREEFORM", // 0x02
35 "EFI_FV_FILETYPE_SECURITY_CORE", // 0x03
36 "EFI_FV_FILETYPE_PEI_CORE", // 0x04
37 "EFI_FV_FILETYPE_DXE_CORE", // 0x05
38 "EFI_FV_FILETYPE_PEIM", // 0x06
39 "EFI_FV_FILETYPE_DRIVER", // 0x07
40 "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER", // 0x08
41 "EFI_FV_FILETYPE_APPLICATION", // 0x09
42 "EFI_FV_FILETYPE_SMM", // 0x0A
43 "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B
44 "EFI_FV_FILETYPE_COMBINED_SMM_DXE", // 0x0C
45 "EFI_FV_FILETYPE_SMM_CORE" // 0x0D
48 STATIC CHAR8
*mAlignName
[] = {
49 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
50 "1K", "2K", "4K", "8K", "16K", "32K", "64K"
53 STATIC CHAR8
*mFfsValidAlignName
[] = {
54 "8", "16", "128", "512", "1K", "4K", "32K", "64K"
57 STATIC UINT32 mFfsValidAlign
[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536};
59 STATIC EFI_GUID mZeroGuid
= {0};
70 Print out version information for this utility.
82 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
94 Print Error / Help message.
109 fprintf (stdout
, "\nUsage: %s [options]\n\n", UTILITY_NAME
);
112 // Copyright declaration
114 fprintf (stdout
, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
119 fprintf (stdout
, "Options:\n");
120 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
121 File is FFS file to be created.\n");
122 fprintf (stdout
, " -t Type, --filetype Type\n\
123 Type is one FV file type defined in PI spec, which is\n\
124 EFI_FV_FILETYPE_RAW, EFI_FV_FILETYPE_FREEFORM,\n\
125 EFI_FV_FILETYPE_SECURITY_CORE, EFI_FV_FILETYPE_PEIM,\n\
126 EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,\n\
127 EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION,\n\
128 EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\n\
129 EFI_FV_FILETYPE_SMM, EFI_FV_FILETYPE_SMM_CORE,\n\
130 EFI_FV_FILETYPE_COMBINED_SMM_DXE, \n\
131 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n");
132 fprintf (stdout
, " -g FileGuid, --fileguid FileGuid\n\
133 FileGuid is one module guid.\n\
134 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
135 fprintf (stdout
, " -x, --fixed Indicates that the file may not be moved\n\
136 from its present location.\n");
137 fprintf (stdout
, " -s, --checksum Indicates to calculate file checksum.\n");
138 fprintf (stdout
, " -a FileAlign, --align FileAlign\n\
139 FileAlign points to file alignment, which only support\n\
140 the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n");
141 fprintf (stdout
, " -i SectionFile, --sectionfile SectionFile\n\
142 Section file will be contained in this FFS file.\n");
143 fprintf (stdout
, " -n SectionAlign, --sectionalign SectionAlign\n\
144 SectionAlign points to section alignment, which support\n\
145 the alignment scope 1~64K. It is specified together\n\
146 with sectionfile to point its alignment in FFS file.\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");
157 IN CHAR8
*AlignBuffer
,
158 OUT UINT32
*AlignNumber
164 Converts Align String to align value (1~64K).
168 AlignBuffer - Pointer to Align string.
169 AlignNumber - Pointer to Align value.
173 EFI_SUCCESS Successfully convert align string to align value.
174 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
182 if (AlignBuffer
== NULL
) {
183 return EFI_INVALID_PARAMETER
;
185 for (Index
= 0; Index
< sizeof (mAlignName
) / sizeof (CHAR8
*); Index
++) {
186 if (stricmp (AlignBuffer
, mAlignName
[Index
]) == 0) {
187 *AlignNumber
= 1 << Index
;
191 return EFI_INVALID_PARAMETER
;
203 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
204 unrecognized file type was specified.
208 String - File type string
218 if (String
== NULL
) {
219 return EFI_FV_FILETYPE_ALL
;
222 for (Index
= 0; Index
< sizeof (mFfsFileType
) / sizeof (CHAR8
*); Index
++) {
223 if (mFfsFileType
[Index
] != NULL
&& (stricmp (String
, mFfsFileType
[Index
]) == 0)) {
227 return EFI_FV_FILETYPE_ALL
;
233 IN CHAR8
**InputFileName
,
234 IN UINT32
*InputFileAlign
,
235 IN UINT32 InputFileNum
,
236 OUT UINT8
*FileBuffer
,
237 OUT UINT32
*BufferLength
,
238 OUT UINT32
*MaxAlignment
,
239 OUT UINT8
*PESectionNum
245 Get the contents of all section files specified in InputFileName
250 InputFileName - Name of the input file.
252 InputFileAlign - Alignment required by the input file data.
254 InputFileNum - Number of input files. Should be at least 1.
256 FileBuffer - Output buffer to contain data
258 BufferLength - On input, this is size of the FileBuffer.
259 On output, this is the actual length of the data.
261 MaxAlignment - The max alignment required by all the input file datas.
263 PeSectionNum - Calculate the number of Pe/Te Section in this FFS file.
267 EFI_SUCCESS on successful return
268 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
269 EFI_ABORTED if unable to open input file.
270 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
278 EFI_COMMON_SECTION_HEADER
*SectHeader
;
279 EFI_COMMON_SECTION_HEADER2 TempSectHeader
;
280 EFI_TE_IMAGE_HEADER TeHeader
;
282 EFI_GUID_DEFINED_SECTION GuidSectHeader
;
283 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2
;
291 // Go through our array of file names and copy their contents
292 // to the output buffer.
294 for (Index
= 0; Index
< InputFileNum
; Index
++) {
296 // make sure section ends on a DWORD boundary
298 while ((Size
& 0x03) != 0) {
303 // Get the Max alignment of all input file datas
305 if (*MaxAlignment
< InputFileAlign
[Index
]) {
306 *MaxAlignment
= InputFileAlign
[Index
];
310 // Open file and read contents
312 InFile
= fopen (LongFilePath (InputFileName
[Index
]), "rb");
313 if (InFile
== NULL
) {
314 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
318 fseek (InFile
, 0, SEEK_END
);
319 FileSize
= ftell (InFile
);
320 fseek (InFile
, 0, SEEK_SET
);
321 DebugMsg (NULL
, 0, 9, "Input section files",
322 "the input section name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
325 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
328 if (FileSize
>= MAX_FFS_SIZE
) {
329 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER2
);
331 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
333 fread (&TempSectHeader
, 1, HeaderSize
, InFile
);
334 if (TempSectHeader
.Type
== EFI_SECTION_TE
) {
336 fread (&TeHeader
, 1, sizeof (TeHeader
), InFile
);
337 if (TeHeader
.Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
338 TeOffset
= TeHeader
.StrippedSize
- sizeof (TeHeader
);
340 } else if (TempSectHeader
.Type
== EFI_SECTION_PE32
) {
342 } else if (TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
) {
343 fseek (InFile
, 0, SEEK_SET
);
344 if (FileSize
>= MAX_SECTION_SIZE
) {
345 fread (&GuidSectHeader2
, 1, sizeof (GuidSectHeader2
), InFile
);
346 if ((GuidSectHeader2
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
347 HeaderSize
= GuidSectHeader2
.DataOffset
;
350 fread (&GuidSectHeader
, 1, sizeof (GuidSectHeader
), InFile
);
351 if ((GuidSectHeader
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
352 HeaderSize
= GuidSectHeader
.DataOffset
;
356 } else if (TempSectHeader
.Type
== EFI_SECTION_COMPRESSION
||
357 TempSectHeader
.Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
359 // for the encapsulated section, assume it contains Pe/Te section
364 fseek (InFile
, 0, SEEK_SET
);
367 // Revert TeOffset to the converse value relative to Alignment
368 // This is to assure the original PeImage Header at Alignment.
370 if ((TeOffset
!= 0) && (InputFileAlign
[Index
] != 0)) {
371 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
372 TeOffset
= TeOffset
% InputFileAlign
[Index
];
376 // make sure section data meet its alignment requirement by adding one raw pad section.
377 // But the different sections have the different section header. Necessary or not?
378 // Based on section type to adjust offset? Todo
380 if ((InputFileAlign
[Index
] != 0) && (((Size
+ HeaderSize
+ TeOffset
) % InputFileAlign
[Index
]) != 0)) {
381 Offset
= (Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + HeaderSize
+ TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
382 Offset
= Offset
- Size
- HeaderSize
- TeOffset
;
384 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
386 // The maximal alignment is 64K, the raw section size must be less than 0xffffff
388 memset (FileBuffer
+ Size
, 0, Offset
);
389 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
390 SectHeader
->Type
= EFI_SECTION_RAW
;
391 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
392 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
393 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
395 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment",
396 "Pad Raw section size is %u", (unsigned) Offset
);
398 Size
= Size
+ Offset
;
402 // Now read the contents of the file into the buffer
403 // Buffer must be enough to contain the file content.
405 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
406 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
407 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
418 // Set the actual length of the data.
420 if (Size
> *BufferLength
) {
421 *BufferLength
= Size
;
422 return EFI_BUFFER_TOO_SMALL
;
424 *BufferLength
= Size
;
442 argc - Number of command line parameters.
443 argv - Array of pointers to parameter strings.
446 STATUS_SUCCESS - Utility exits successfully.
447 STATUS_ERROR - Some error occurred during execution.
452 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
454 EFI_FV_FILETYPE FfsFiletype
;
455 CHAR8
*OutputFileName
;
456 EFI_GUID FileGuid
= {0};
458 UINT32
*InputFileAlign
;
459 CHAR8
**InputFileName
;
463 EFI_FFS_FILE_HEADER2 FfsFileHeader
;
471 // Init local variables
477 FfsFiletype
= EFI_FV_FILETYPE_ALL
;
478 OutputFileName
= NULL
;
480 InputFileName
= NULL
;
481 InputFileAlign
= NULL
;
486 Status
= EFI_SUCCESS
;
489 SetUtilityName (UTILITY_NAME
);
492 Error (NULL
, 0, 1001, "Missing options", "no options input");
498 // Parse command line
503 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
506 return STATUS_SUCCESS
;
509 if (stricmp (argv
[0], "--version") == 0) {
511 return STATUS_SUCCESS
;
515 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--filetype") == 0)) {
516 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
517 Error (NULL
, 0, 1003, "Invalid option value", "file type is missing for -t option");
520 FfsFiletype
= StringToType (argv
[1]);
521 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
522 Error (NULL
, 0, 1003, "Invalid option value", "%s is not a valid file type", argv
[1]);
530 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
531 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
532 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
535 OutputFileName
= argv
[1];
541 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--fileguid") == 0)) {
542 Status
= StringToGuid (argv
[1], &FileGuid
);
543 if (EFI_ERROR (Status
)) {
544 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
552 if ((stricmp (argv
[0], "-x") == 0) || (stricmp (argv
[0], "--fixed") == 0)) {
553 FfsAttrib
|= FFS_ATTRIB_FIXED
;
559 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--checksum") == 0)) {
560 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
566 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
567 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
568 Error (NULL
, 0, 1003, "Invalid option value", "Align value is missing for -a option");
571 for (Index
= 0; Index
< sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*); Index
++) {
572 if (stricmp (argv
[1], mFfsValidAlignName
[Index
]) == 0) {
576 if (Index
== sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*)) {
577 if ((stricmp (argv
[1], "1") == 0) || (stricmp (argv
[1], "2") == 0) || (stricmp (argv
[1], "4") == 0)) {
579 // 1, 2, 4 byte alignment same to 8 byte alignment
583 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
593 if ((stricmp (argv
[0], "-i") == 0) || (stricmp (argv
[0], "--sectionfile") == 0)) {
595 // Get Input file name and its alignment
597 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
598 Error (NULL
, 0, 1003, "Invalid option value", "input section file is missing for -i option");
603 // Allocate Input file name buffer and its alignment buffer.
605 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
606 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
607 if (InputFileName
== NULL
) {
608 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
611 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
613 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
614 if (InputFileAlign
== NULL
) {
615 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
616 free (InputFileName
);
619 memset (InputFileAlign
, 0, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
620 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
622 // InputFileName and alignment buffer too small, need to realloc
624 InputFileName
= (CHAR8
**) realloc (
626 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
629 if (InputFileName
== NULL
) {
630 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
631 free (InputFileAlign
);
634 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
636 InputFileAlign
= (UINT32
*) realloc (
638 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
641 if (InputFileAlign
== NULL
) {
642 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
643 free (InputFileName
);
646 memset (&(InputFileAlign
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
649 InputFileName
[InputFileNum
] = argv
[1];
659 // Section File alignment requirement
661 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
662 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileNum
]));
663 if (EFI_ERROR (Status
)) {
664 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
674 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
675 Error (NULL
, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file.");
679 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
680 SetPrintLevel (VERBOSE_LOG_LEVEL
);
681 VerboseMsg ("Verbose output Mode Set!");
687 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
688 SetPrintLevel (KEY_LOG_LEVEL
);
689 KeyMsg ("Quiet output Mode Set!");
695 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
696 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
697 if (EFI_ERROR (Status
)) {
698 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
702 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
705 SetPrintLevel (LogLevel
);
706 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
712 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
716 VerboseMsg ("%s tool start.", UTILITY_NAME
);
719 // Check the complete input paramters.
721 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
722 Error (NULL
, 0, 1001, "Missing option", "filetype");
726 if (CompareGuid (&FileGuid
, &mZeroGuid
) == 0) {
727 Error (NULL
, 0, 1001, "Missing option", "fileguid");
731 if (InputFileNum
== 0) {
732 Error (NULL
, 0, 1001, "Missing option", "Input files");
737 // Output input parameter information
739 VerboseMsg ("Fv File type is %s", mFfsFileType
[FfsFiletype
]);
740 VerboseMsg ("Output file name is %s", OutputFileName
);
741 VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
742 (unsigned) FileGuid
.Data1
,
753 if ((FfsAttrib
& FFS_ATTRIB_FIXED
) != 0) {
754 VerboseMsg ("FFS File has the fixed file attribute");
756 if ((FfsAttrib
& FFS_ATTRIB_CHECKSUM
) != 0) {
757 VerboseMsg ("FFS File requires the checksum of the whole file");
759 VerboseMsg ("FFS file alignment is %s", mFfsValidAlignName
[FfsAlign
]);
760 for (Index
= 0; Index
< InputFileNum
; Index
++) {
761 if (InputFileAlign
[Index
] == 0) {
763 // Minimum alignment is 1 byte.
765 InputFileAlign
[Index
] = 1;
767 VerboseMsg ("the %dth input section name is %s and section alignment is %u", Index
, InputFileName
[Index
], (unsigned) InputFileAlign
[Index
]);
771 // Calculate the size of all input section files.
773 Status
= GetSectionContents (
783 if ((FfsFiletype
== EFI_FV_FILETYPE_SECURITY_CORE
||
784 FfsFiletype
== EFI_FV_FILETYPE_PEI_CORE
||
785 FfsFiletype
== EFI_FV_FILETYPE_DXE_CORE
) && (PeSectionNum
!= 1)) {
786 Error (NULL
, 0, 2000, "Invalid parameter", "Fv File type %s must have one and only one Pe or Te section, but %u Pe/Te section are input", mFfsFileType
[FfsFiletype
], PeSectionNum
);
790 if ((FfsFiletype
== EFI_FV_FILETYPE_PEIM
||
791 FfsFiletype
== EFI_FV_FILETYPE_DRIVER
||
792 FfsFiletype
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
||
793 FfsFiletype
== EFI_FV_FILETYPE_APPLICATION
) && (PeSectionNum
< 1)) {
794 Error (NULL
, 0, 2000, "Invalid parameter", "Fv File type %s must have at least one Pe or Te section, but no Pe/Te section is input", mFfsFileType
[FfsFiletype
]);
798 if (Status
== EFI_BUFFER_TOO_SMALL
) {
799 FileBuffer
= (UINT8
*) malloc (FileSize
);
800 if (FileBuffer
== NULL
) {
801 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
804 memset (FileBuffer
, 0, FileSize
);
807 // read all input file contents into a buffer
809 Status
= GetSectionContents (
820 if (EFI_ERROR (Status
)) {
825 // Create Ffs file header.
827 memset (&FfsFileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER2
));
828 memcpy (&FfsFileHeader
.Name
, &FileGuid
, sizeof (EFI_GUID
));
829 FfsFileHeader
.Type
= FfsFiletype
;
831 // Update FFS Alignment based on the max alignment required by input section files
833 VerboseMsg ("the max alignment of all input sections is %u", (unsigned) MaxAlignment
);
834 for (Index
= 0; Index
< sizeof (mFfsValidAlign
) / sizeof (UINT32
) - 1; Index
++) {
835 if ((MaxAlignment
> mFfsValidAlign
[Index
]) && (MaxAlignment
<= mFfsValidAlign
[Index
+ 1])) {
839 if (FfsAlign
< Index
) {
842 VerboseMsg ("the alignment of the generated FFS file is %u", (unsigned) mFfsValidAlign
[FfsAlign
+ 1]);
845 // Now FileSize includes the EFI_FFS_FILE_HEADER
847 if (FileSize
+ sizeof (EFI_FFS_FILE_HEADER
) >= MAX_FFS_SIZE
) {
848 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER2
);
849 FileSize
+= sizeof (EFI_FFS_FILE_HEADER2
);
850 FfsFileHeader
.ExtendedSize
= FileSize
;
851 memset(FfsFileHeader
.Size
, 0, sizeof (UINT8
) * 3);
852 FfsAttrib
|= FFS_ATTRIB_LARGE_FILE
;
854 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER
);
855 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
856 FfsFileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
857 FfsFileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
858 FfsFileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
860 VerboseMsg ("the size of the generated FFS file is %u bytes", (unsigned) FileSize
);
862 FfsFileHeader
.Attributes
= (EFI_FFS_FILE_ATTRIBUTES
) (FfsAttrib
| (FfsAlign
<< 3));
865 // Fill in checksums and state, these must be zero for checksumming
867 // FileHeader.IntegrityCheck.Checksum.Header = 0;
868 // FileHeader.IntegrityCheck.Checksum.File = 0;
869 // FileHeader.State = 0;
871 FfsFileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
872 (UINT8
*) &FfsFileHeader
,
876 if (FfsFileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
878 // Ffs header checksum = zero, so only need to calculate ffs body.
880 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
882 FileSize
- HeaderSize
885 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
888 FfsFileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
891 // Open output file to write ffs data.
893 remove(OutputFileName
);
894 FfsFile
= fopen (LongFilePath (OutputFileName
), "wb");
895 if (FfsFile
== NULL
) {
896 Error (NULL
, 0, 0001, "Error opening file", OutputFileName
);
902 fwrite (&FfsFileHeader
, 1, HeaderSize
, FfsFile
);
906 fwrite (FileBuffer
, 1, FileSize
- HeaderSize
, FfsFile
);
911 if (InputFileName
!= NULL
) {
912 free (InputFileName
);
914 if (InputFileAlign
!= NULL
) {
915 free (InputFileAlign
);
917 if (FileBuffer
!= NULL
) {
921 // If any errors were reported via the standard error reporting
922 // routines, then the status has been saved. Get the value and
923 // return it to the caller.
925 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
927 return GetUtilityStatus ();