3 Copyright (c) 2004 - 2013, 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 file contains functions required to generate a Firmware File System
27 #include <Common/UefiBaseTypes.h>
28 #include <Common/PiFirmwareFile.h>
29 #include <IndustryStandard/PeImage.h>
31 #include "CommonLib.h"
33 #include "EfiUtilityMsgs.h"
35 #define UTILITY_NAME "GenFfs"
36 #define UTILITY_MAJOR_VERSION 0
37 #define UTILITY_MINOR_VERSION 1
39 STATIC CHAR8
*mFfsFileType
[] = {
41 "EFI_FV_FILETYPE_RAW", // 0x01
42 "EFI_FV_FILETYPE_FREEFORM", // 0x02
43 "EFI_FV_FILETYPE_SECURITY_CORE", // 0x03
44 "EFI_FV_FILETYPE_PEI_CORE", // 0x04
45 "EFI_FV_FILETYPE_DXE_CORE", // 0x05
46 "EFI_FV_FILETYPE_PEIM", // 0x06
47 "EFI_FV_FILETYPE_DRIVER", // 0x07
48 "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER", // 0x08
49 "EFI_FV_FILETYPE_APPLICATION", // 0x09
50 "EFI_FV_FILETYPE_SMM", // 0x0A
51 "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B
52 "EFI_FV_FILETYPE_COMBINED_SMM_DXE", // 0x0C
53 "EFI_FV_FILETYPE_SMM_CORE" // 0x0D
56 STATIC CHAR8
*mAlignName
[] = {
57 "1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
58 "1K", "2K", "4K", "8K", "16K", "32K", "64K"
61 STATIC CHAR8
*mFfsValidAlignName
[] = {
62 "8", "16", "128", "512", "1K", "4K", "32K", "64K"
65 STATIC UINT32 mFfsValidAlign
[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536};
67 STATIC EFI_GUID mZeroGuid
= {0};
78 Print out version information for this utility.
90 fprintf (stdout
, "%s Version %d.%d %s \n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_VERSION
, __BUILD_VERSION
);
102 Print Error / Help message.
117 fprintf (stdout
, "\nUsage: %s [options]\n\n", UTILITY_NAME
);
120 // Copyright declaration
122 fprintf (stdout
, "Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.\n\n");
127 fprintf (stdout
, "Options:\n");
128 fprintf (stdout
, " -o FileName, --outputfile FileName\n\
129 File is FFS file to be created.\n");
130 fprintf (stdout
, " -t Type, --filetype Type\n\
131 Type is one FV file type defined in PI spec, which is\n\
132 EFI_FV_FILETYPE_RAW, EFI_FV_FILETYPE_FREEFORM,\n\
133 EFI_FV_FILETYPE_SECURITY_CORE, EFI_FV_FILETYPE_PEIM,\n\
134 EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,\n\
135 EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION,\n\
136 EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\n\
137 EFI_FV_FILETYPE_SMM, EFI_FV_FILETYPE_SMM_CORE,\n\
138 EFI_FV_FILETYPE_COMBINED_SMM_DXE, \n\
139 EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n");
140 fprintf (stdout
, " -g FileGuid, --fileguid FileGuid\n\
141 FileGuid is one module guid.\n\
142 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
143 fprintf (stdout
, " -x, --fixed Indicates that the file may not be moved\n\
144 from its present location.\n");
145 fprintf (stdout
, " -s, --checksum Indicates to calculate file checksum.\n");
146 fprintf (stdout
, " -a FileAlign, --align FileAlign\n\
147 FileAlign points to file alignment, which only support\n\
148 the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n");
149 fprintf (stdout
, " -i SectionFile, --sectionfile SectionFile\n\
150 Section file will be contained in this FFS file.\n");
151 fprintf (stdout
, " -n SectionAlign, --sectionalign SectionAlign\n\
152 SectionAlign points to section alignment, which support\n\
153 the alignment scope 1~64K. It is specified together\n\
154 with sectionfile to point its alignment in FFS file.\n");
155 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
156 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
157 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
158 fprintf (stdout
, " --version Show program's version number and exit.\n");
159 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
165 IN CHAR8
*AlignBuffer
,
166 OUT UINT32
*AlignNumber
172 Converts Align String to align value (1~64K).
176 AlignBuffer - Pointer to Align string.
177 AlignNumber - Pointer to Align value.
181 EFI_SUCCESS Successfully convert align string to align value.
182 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
190 if (AlignBuffer
== NULL
) {
191 return EFI_INVALID_PARAMETER
;
193 for (Index
= 0; Index
< sizeof (mAlignName
) / sizeof (CHAR8
*); Index
++) {
194 if (stricmp (AlignBuffer
, mAlignName
[Index
]) == 0) {
195 *AlignNumber
= 1 << Index
;
199 return EFI_INVALID_PARAMETER
;
211 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
212 unrecognized file type was specified.
216 String - File type string
226 if (String
== NULL
) {
227 return EFI_FV_FILETYPE_ALL
;
230 for (Index
= 0; Index
< sizeof (mFfsFileType
) / sizeof (CHAR8
*); Index
++) {
231 if (mFfsFileType
[Index
] != NULL
&& (stricmp (String
, mFfsFileType
[Index
]) == 0)) {
235 return EFI_FV_FILETYPE_ALL
;
241 IN CHAR8
**InputFileName
,
242 IN UINT32
*InputFileAlign
,
243 IN UINT32 InputFileNum
,
244 OUT UINT8
*FileBuffer
,
245 OUT UINT32
*BufferLength
,
246 OUT UINT32
*MaxAlignment
,
247 OUT UINT8
*PESectionNum
253 Get the contents of all section files specified in InputFileName
258 InputFileName - Name of the input file.
260 InputFileAlign - Alignment required by the input file data.
262 InputFileNum - Number of input files. Should be at least 1.
264 FileBuffer - Output buffer to contain data
266 BufferLength - On input, this is size of the FileBuffer.
267 On output, this is the actual length of the data.
269 MaxAlignment - The max alignment required by all the input file datas.
271 PeSectionNum - Calculate the number of Pe/Te Section in this FFS file.
275 EFI_SUCCESS on successful return
276 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
277 EFI_ABORTED if unable to open input file.
278 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
286 EFI_COMMON_SECTION_HEADER
*SectHeader
;
287 EFI_COMMON_SECTION_HEADER2 TempSectHeader
;
288 EFI_TE_IMAGE_HEADER TeHeader
;
290 EFI_GUID_DEFINED_SECTION GuidSectHeader
;
291 EFI_GUID_DEFINED_SECTION2 GuidSectHeader2
;
299 // Go through our array of file names and copy their contents
300 // to the output buffer.
302 for (Index
= 0; Index
< InputFileNum
; Index
++) {
304 // make sure section ends on a DWORD boundary
306 while ((Size
& 0x03) != 0) {
311 // Get the Max alignment of all input file datas
313 if (*MaxAlignment
< InputFileAlign
[Index
]) {
314 *MaxAlignment
= InputFileAlign
[Index
];
318 // Open file and read contents
320 InFile
= fopen (InputFileName
[Index
], "rb");
321 if (InFile
== NULL
) {
322 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
326 fseek (InFile
, 0, SEEK_END
);
327 FileSize
= ftell (InFile
);
328 fseek (InFile
, 0, SEEK_SET
);
329 DebugMsg (NULL
, 0, 9, "Input section files",
330 "the input section name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
333 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
336 if (FileSize
>= MAX_FFS_SIZE
) {
337 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER2
);
339 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
341 fread (&TempSectHeader
, 1, HeaderSize
, InFile
);
342 if (TempSectHeader
.Type
== EFI_SECTION_TE
) {
344 fread (&TeHeader
, 1, sizeof (TeHeader
), InFile
);
345 if (TeHeader
.Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
346 TeOffset
= TeHeader
.StrippedSize
- sizeof (TeHeader
);
348 } else if (TempSectHeader
.Type
== EFI_SECTION_PE32
) {
350 } else if (TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
) {
351 fseek (InFile
, 0, SEEK_SET
);
352 if (FileSize
>= MAX_SECTION_SIZE
) {
353 fread (&GuidSectHeader2
, 1, sizeof (GuidSectHeader2
), InFile
);
354 if ((GuidSectHeader2
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
355 HeaderSize
= GuidSectHeader2
.DataOffset
;
358 fread (&GuidSectHeader
, 1, sizeof (GuidSectHeader
), InFile
);
359 if ((GuidSectHeader
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
360 HeaderSize
= GuidSectHeader
.DataOffset
;
364 } else if (TempSectHeader
.Type
== EFI_SECTION_COMPRESSION
||
365 TempSectHeader
.Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
367 // for the encapsulated section, assume it contains Pe/Te section
372 fseek (InFile
, 0, SEEK_SET
);
375 // Revert TeOffset to the converse value relative to Alignment
376 // This is to assure the original PeImage Header at Alignment.
378 if ((TeOffset
!= 0) && (InputFileAlign
[Index
] != 0)) {
379 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
380 TeOffset
= TeOffset
% InputFileAlign
[Index
];
384 // make sure section data meet its alignment requirement by adding one raw pad section.
385 // But the different sections have the different section header. Necessary or not?
386 // Based on section type to adjust offset? Todo
388 if ((InputFileAlign
[Index
] != 0) && (((Size
+ HeaderSize
+ TeOffset
) % InputFileAlign
[Index
]) != 0)) {
389 Offset
= (Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + HeaderSize
+ TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
390 Offset
= Offset
- Size
- HeaderSize
- TeOffset
;
392 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
394 // The maximal alignment is 64K, the raw section size must be less than 0xffffff
396 memset (FileBuffer
+ Size
, 0, Offset
);
397 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
398 SectHeader
->Type
= EFI_SECTION_RAW
;
399 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
400 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
401 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
403 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment",
404 "Pad Raw section size is %u", (unsigned) Offset
);
406 Size
= Size
+ Offset
;
410 // Now read the contents of the file into the buffer
411 // Buffer must be enough to contain the file content.
413 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
414 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
415 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
426 // Set the actual length of the data.
428 if (Size
> *BufferLength
) {
429 *BufferLength
= Size
;
430 return EFI_BUFFER_TOO_SMALL
;
432 *BufferLength
= Size
;
450 argc - Number of command line parameters.
451 argv - Array of pointers to parameter strings.
454 STATUS_SUCCESS - Utility exits successfully.
455 STATUS_ERROR - Some error occurred during execution.
460 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
462 EFI_FV_FILETYPE FfsFiletype
;
463 CHAR8
*OutputFileName
;
464 EFI_GUID FileGuid
= {0};
466 UINT32
*InputFileAlign
;
467 CHAR8
**InputFileName
;
471 EFI_FFS_FILE_HEADER2 FfsFileHeader
;
479 // Init local variables
485 FfsFiletype
= EFI_FV_FILETYPE_ALL
;
486 OutputFileName
= NULL
;
488 InputFileName
= NULL
;
489 InputFileAlign
= NULL
;
494 Status
= EFI_SUCCESS
;
497 SetUtilityName (UTILITY_NAME
);
500 Error (NULL
, 0, 1001, "Missing options", "no options input");
506 // Parse command line
511 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
514 return STATUS_SUCCESS
;
517 if (stricmp (argv
[0], "--version") == 0) {
519 return STATUS_SUCCESS
;
523 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--filetype") == 0)) {
524 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
525 Error (NULL
, 0, 1003, "Invalid option value", "file type is missing for -t option");
528 FfsFiletype
= StringToType (argv
[1]);
529 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
530 Error (NULL
, 0, 1003, "Invalid option value", "%s is not a valid file type", argv
[1]);
538 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
539 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
540 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
543 OutputFileName
= argv
[1];
549 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--fileguid") == 0)) {
550 Status
= StringToGuid (argv
[1], &FileGuid
);
551 if (EFI_ERROR (Status
)) {
552 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
560 if ((stricmp (argv
[0], "-x") == 0) || (stricmp (argv
[0], "--fixed") == 0)) {
561 FfsAttrib
|= FFS_ATTRIB_FIXED
;
567 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--checksum") == 0)) {
568 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
574 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
575 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
576 Error (NULL
, 0, 1003, "Invalid option value", "Align value is missing for -a option");
579 for (Index
= 0; Index
< sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*); Index
++) {
580 if (stricmp (argv
[1], mFfsValidAlignName
[Index
]) == 0) {
584 if (Index
== sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*)) {
585 if ((stricmp (argv
[1], "1") == 0) || (stricmp (argv
[1], "2") == 0) || (stricmp (argv
[1], "4") == 0)) {
587 // 1, 2, 4 byte alignment same to 8 byte alignment
591 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
601 if ((stricmp (argv
[0], "-i") == 0) || (stricmp (argv
[0], "--sectionfile") == 0)) {
603 // Get Input file name and its alignment
605 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
606 Error (NULL
, 0, 1003, "Invalid option value", "input section file is missing for -i option");
611 // Allocate Input file name buffer and its alignment buffer.
613 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
614 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
615 if (InputFileName
== NULL
) {
616 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
619 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
621 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
622 if (InputFileAlign
== NULL
) {
623 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
624 free (InputFileName
);
627 memset (InputFileAlign
, 0, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
628 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
630 // InputFileName and alignment buffer too small, need to realloc
632 InputFileName
= (CHAR8
**) realloc (
634 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
637 if (InputFileName
== NULL
) {
638 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
639 free (InputFileAlign
);
642 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
644 InputFileAlign
= (UINT32
*) realloc (
646 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
649 if (InputFileAlign
== NULL
) {
650 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
651 free (InputFileName
);
654 memset (&(InputFileAlign
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
657 InputFileName
[InputFileNum
] = argv
[1];
667 // Section File alignment requirement
669 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
670 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileNum
]));
671 if (EFI_ERROR (Status
)) {
672 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
682 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
683 Error (NULL
, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file.");
687 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
688 SetPrintLevel (VERBOSE_LOG_LEVEL
);
689 VerboseMsg ("Verbose output Mode Set!");
695 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
696 SetPrintLevel (KEY_LOG_LEVEL
);
697 KeyMsg ("Quiet output Mode Set!");
703 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
704 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
705 if (EFI_ERROR (Status
)) {
706 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
710 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
713 SetPrintLevel (LogLevel
);
714 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
720 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
724 VerboseMsg ("%s tool start.", UTILITY_NAME
);
727 // Check the complete input paramters.
729 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
730 Error (NULL
, 0, 1001, "Missing option", "filetype");
734 if (CompareGuid (&FileGuid
, &mZeroGuid
) == 0) {
735 Error (NULL
, 0, 1001, "Missing option", "fileguid");
739 if (InputFileNum
== 0) {
740 Error (NULL
, 0, 1001, "Missing option", "Input files");
745 // Output input parameter information
747 VerboseMsg ("Fv File type is %s", mFfsFileType
[FfsFiletype
]);
748 VerboseMsg ("Output file name is %s", OutputFileName
);
749 VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
750 (unsigned) FileGuid
.Data1
,
761 if ((FfsAttrib
& FFS_ATTRIB_FIXED
) != 0) {
762 VerboseMsg ("FFS File has the fixed file attribute");
764 if ((FfsAttrib
& FFS_ATTRIB_CHECKSUM
) != 0) {
765 VerboseMsg ("FFS File requires the checksum of the whole file");
767 VerboseMsg ("FFS file alignment is %s", mFfsValidAlignName
[FfsAlign
]);
768 for (Index
= 0; Index
< InputFileNum
; Index
++) {
769 if (InputFileAlign
[Index
] == 0) {
771 // Minimum alignment is 1 byte.
773 InputFileAlign
[Index
] = 1;
775 VerboseMsg ("the %dth input section name is %s and section alignment is %u", Index
, InputFileName
[Index
], (unsigned) InputFileAlign
[Index
]);
779 // Calculate the size of all input section files.
781 Status
= GetSectionContents (
791 if ((FfsFiletype
== EFI_FV_FILETYPE_SECURITY_CORE
||
792 FfsFiletype
== EFI_FV_FILETYPE_PEI_CORE
||
793 FfsFiletype
== EFI_FV_FILETYPE_DXE_CORE
) && (PeSectionNum
!= 1)) {
794 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
);
798 if ((FfsFiletype
== EFI_FV_FILETYPE_PEIM
||
799 FfsFiletype
== EFI_FV_FILETYPE_DRIVER
||
800 FfsFiletype
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
||
801 FfsFiletype
== EFI_FV_FILETYPE_APPLICATION
) && (PeSectionNum
< 1)) {
802 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
]);
806 if (Status
== EFI_BUFFER_TOO_SMALL
) {
807 FileBuffer
= (UINT8
*) malloc (FileSize
);
808 if (FileBuffer
== NULL
) {
809 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
812 memset (FileBuffer
, 0, FileSize
);
815 // read all input file contents into a buffer
817 Status
= GetSectionContents (
828 if (EFI_ERROR (Status
)) {
833 // Create Ffs file header.
835 memset (&FfsFileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER2
));
836 memcpy (&FfsFileHeader
.Name
, &FileGuid
, sizeof (EFI_GUID
));
837 FfsFileHeader
.Type
= FfsFiletype
;
839 // Update FFS Alignment based on the max alignment required by input section files
841 VerboseMsg ("the max alignment of all input sections is %u", (unsigned) MaxAlignment
);
842 for (Index
= 0; Index
< sizeof (mFfsValidAlign
) / sizeof (UINT32
) - 1; Index
++) {
843 if ((MaxAlignment
> mFfsValidAlign
[Index
]) && (MaxAlignment
<= mFfsValidAlign
[Index
+ 1])) {
847 if (FfsAlign
< Index
) {
850 VerboseMsg ("the alignment of the generated FFS file is %u", (unsigned) mFfsValidAlign
[FfsAlign
+ 1]);
853 // Now FileSize includes the EFI_FFS_FILE_HEADER
855 if (FileSize
+ sizeof (EFI_FFS_FILE_HEADER
) >= MAX_FFS_SIZE
) {
856 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER2
);
857 FileSize
+= sizeof (EFI_FFS_FILE_HEADER2
);
858 FfsFileHeader
.ExtendedSize
= FileSize
;
859 memset(FfsFileHeader
.Size
, 0, sizeof (UINT8
) * 3);
860 FfsAttrib
|= FFS_ATTRIB_LARGE_FILE
;
862 HeaderSize
= sizeof (EFI_FFS_FILE_HEADER
);
863 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
864 FfsFileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
865 FfsFileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
866 FfsFileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
868 VerboseMsg ("the size of the generated FFS file is %u bytes", (unsigned) FileSize
);
870 FfsFileHeader
.Attributes
= (EFI_FFS_FILE_ATTRIBUTES
) (FfsAttrib
| (FfsAlign
<< 3));
873 // Fill in checksums and state, these must be zero for checksumming
875 // FileHeader.IntegrityCheck.Checksum.Header = 0;
876 // FileHeader.IntegrityCheck.Checksum.File = 0;
877 // FileHeader.State = 0;
879 FfsFileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
880 (UINT8
*) &FfsFileHeader
,
884 if (FfsFileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
886 // Ffs header checksum = zero, so only need to calculate ffs body.
888 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
890 FileSize
- HeaderSize
893 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
896 FfsFileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
899 // Open output file to write ffs data.
901 remove(OutputFileName
);
902 FfsFile
= fopen (OutputFileName
, "wb");
903 if (FfsFile
== NULL
) {
904 Error (NULL
, 0, 0001, "Error opening file", OutputFileName
);
910 fwrite (&FfsFileHeader
, 1, HeaderSize
, FfsFile
);
914 fwrite (FileBuffer
, 1, FileSize
- HeaderSize
, FfsFile
);
919 if (InputFileName
!= NULL
) {
920 free (InputFileName
);
922 if (InputFileAlign
!= NULL
) {
923 free (InputFileAlign
);
925 if (FileBuffer
!= NULL
) {
929 // If any errors were reported via the standard error reporting
930 // routines, then the status has been saved. Get the value and
931 // return it to the caller.
933 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
935 return GetUtilityStatus ();