3 Copyright (c) 2004 - 2010, 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 - 2010, 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_HEADER TempSectHeader
;
288 EFI_TE_IMAGE_HEADER TeHeader
;
290 EFI_GUID_DEFINED_SECTION GuidSectHeader
;
298 // Go through our array of file names and copy their contents
299 // to the output buffer.
301 for (Index
= 0; Index
< InputFileNum
; Index
++) {
303 // make sure section ends on a DWORD boundary
305 while ((Size
& 0x03) != 0) {
310 // Get the Max alignment of all input file datas
312 if (*MaxAlignment
< InputFileAlign
[Index
]) {
313 *MaxAlignment
= InputFileAlign
[Index
];
317 // Open file and read contents
319 InFile
= fopen (InputFileName
[Index
], "rb");
320 if (InFile
== NULL
) {
321 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
325 fseek (InFile
, 0, SEEK_END
);
326 FileSize
= ftell (InFile
);
327 fseek (InFile
, 0, SEEK_SET
);
328 DebugMsg (NULL
, 0, 9, "Input section files",
329 "the input section name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
332 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
335 HeaderSize
= sizeof (EFI_COMMON_SECTION_HEADER
);
336 fread (&TempSectHeader
, 1, sizeof (TempSectHeader
), InFile
);
337 if (TempSectHeader
.Type
== EFI_SECTION_TE
) {
339 fread (&TeHeader
, 1, sizeof (TeHeader
), InFile
);
340 if (TeHeader
.Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
341 TeOffset
= TeHeader
.StrippedSize
- sizeof (TeHeader
);
343 } else if (TempSectHeader
.Type
== EFI_SECTION_PE32
) {
345 } else if (TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
) {
346 fseek (InFile
, 0, SEEK_SET
);
347 fread (&GuidSectHeader
, 1, sizeof (GuidSectHeader
), InFile
);
348 if ((GuidSectHeader
.Attributes
& EFI_GUIDED_SECTION_PROCESSING_REQUIRED
) == 0) {
349 HeaderSize
= GuidSectHeader
.DataOffset
;
352 } else if (TempSectHeader
.Type
== EFI_SECTION_COMPRESSION
||
353 TempSectHeader
.Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
355 // for the encapsulated section, assume it contains Pe/Te section
360 fseek (InFile
, 0, SEEK_SET
);
363 // Revert TeOffset to the converse value relative to Alignment
364 // This is to assure the original PeImage Header at Alignment.
366 if ((TeOffset
!= 0) && (InputFileAlign
[Index
] != 0)) {
367 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
368 TeOffset
= TeOffset
% InputFileAlign
[Index
];
372 // make sure section data meet its alignment requirement by adding one raw pad section.
373 // But the different sections have the different section header. Necessary or not?
374 // Based on section type to adjust offset? Todo
376 if ((InputFileAlign
[Index
] != 0) && (((Size
+ HeaderSize
+ TeOffset
) % InputFileAlign
[Index
]) != 0)) {
377 Offset
= (Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + HeaderSize
+ TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
378 Offset
= Offset
- Size
- HeaderSize
- TeOffset
;
380 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
381 memset (FileBuffer
+ Size
, 0, Offset
);
382 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
383 SectHeader
->Type
= EFI_SECTION_RAW
;
384 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
385 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
386 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
388 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment",
389 "Pad Raw section size is %u", (unsigned) Offset
);
391 Size
= Size
+ Offset
;
395 // Now read the contents of the file into the buffer
396 // Buffer must be enough to contain the file content.
398 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
399 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
400 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
411 // Set the actual length of the data.
413 if (Size
> *BufferLength
) {
414 *BufferLength
= Size
;
415 return EFI_BUFFER_TOO_SMALL
;
417 *BufferLength
= Size
;
435 argc - Number of command line parameters.
436 argv - Array of pointers to parameter strings.
439 STATUS_SUCCESS - Utility exits successfully.
440 STATUS_ERROR - Some error occurred during execution.
445 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
447 EFI_FV_FILETYPE FfsFiletype
;
448 CHAR8
*OutputFileName
;
449 EFI_GUID FileGuid
= {0};
451 UINT32
*InputFileAlign
;
452 CHAR8
**InputFileName
;
456 EFI_FFS_FILE_HEADER FfsFileHeader
;
463 // Init local variables
469 FfsFiletype
= EFI_FV_FILETYPE_ALL
;
470 OutputFileName
= NULL
;
472 InputFileName
= NULL
;
473 InputFileAlign
= NULL
;
478 Status
= EFI_SUCCESS
;
481 SetUtilityName (UTILITY_NAME
);
484 Error (NULL
, 0, 1001, "Missing options", "no options input");
490 // Parse command line
495 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
498 return STATUS_SUCCESS
;
501 if (stricmp (argv
[0], "--version") == 0) {
503 return STATUS_SUCCESS
;
507 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--filetype") == 0)) {
508 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
509 Error (NULL
, 0, 1003, "Invalid option value", "file type is missing for -t option");
512 FfsFiletype
= StringToType (argv
[1]);
513 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
514 Error (NULL
, 0, 1003, "Invalid option value", "%s is not a valid file type", argv
[1]);
522 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
523 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
524 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
527 OutputFileName
= argv
[1];
533 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--fileguid") == 0)) {
534 Status
= StringToGuid (argv
[1], &FileGuid
);
535 if (EFI_ERROR (Status
)) {
536 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
544 if ((stricmp (argv
[0], "-x") == 0) || (stricmp (argv
[0], "--fixed") == 0)) {
545 FfsAttrib
|= FFS_ATTRIB_FIXED
;
551 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--checksum") == 0)) {
552 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
558 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
559 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
560 Error (NULL
, 0, 1003, "Invalid option value", "Align value is missing for -a option");
563 for (Index
= 0; Index
< sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*); Index
++) {
564 if (stricmp (argv
[1], mFfsValidAlignName
[Index
]) == 0) {
568 if (Index
== sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*)) {
569 if ((stricmp (argv
[1], "1") == 0) || (stricmp (argv
[1], "2") == 0) || (stricmp (argv
[1], "4") == 0)) {
571 // 1, 2, 4 byte alignment same to 8 byte alignment
575 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
585 if ((stricmp (argv
[0], "-i") == 0) || (stricmp (argv
[0], "--sectionfile") == 0)) {
587 // Get Input file name and its alignment
589 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
590 Error (NULL
, 0, 1003, "Invalid option value", "input section file is missing for -i option");
595 // Allocate Input file name buffer and its alignment buffer.
597 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
598 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
599 if (InputFileName
== NULL
) {
600 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
603 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
605 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
606 if (InputFileAlign
== NULL
) {
607 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
608 free (InputFileName
);
611 memset (InputFileAlign
, 0, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
612 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
614 // InputFileName and alignment buffer too small, need to realloc
616 InputFileName
= (CHAR8
**) realloc (
618 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
621 if (InputFileName
== NULL
) {
622 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
623 free (InputFileAlign
);
626 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
628 InputFileAlign
= (UINT32
*) realloc (
630 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
633 if (InputFileAlign
== NULL
) {
634 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
635 free (InputFileName
);
638 memset (&(InputFileAlign
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
641 InputFileName
[InputFileNum
] = argv
[1];
651 // Section File alignment requirement
653 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
654 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileNum
]));
655 if (EFI_ERROR (Status
)) {
656 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
666 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
667 Error (NULL
, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file.");
671 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
672 SetPrintLevel (VERBOSE_LOG_LEVEL
);
673 VerboseMsg ("Verbose output Mode Set!");
679 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
680 SetPrintLevel (KEY_LOG_LEVEL
);
681 KeyMsg ("Quiet output Mode Set!");
687 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
688 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
689 if (EFI_ERROR (Status
)) {
690 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
694 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
697 SetPrintLevel (LogLevel
);
698 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
704 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
708 VerboseMsg ("%s tool start.", UTILITY_NAME
);
711 // Check the complete input paramters.
713 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
714 Error (NULL
, 0, 1001, "Missing option", "filetype");
718 if (CompareGuid (&FileGuid
, &mZeroGuid
) == 0) {
719 Error (NULL
, 0, 1001, "Missing option", "fileguid");
723 if (InputFileNum
== 0) {
724 Error (NULL
, 0, 1001, "Missing option", "Input files");
729 // Output input parameter information
731 VerboseMsg ("Fv File type is %s", mFfsFileType
[FfsFiletype
]);
732 VerboseMsg ("Output file name is %s", OutputFileName
);
733 VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
734 (unsigned) FileGuid
.Data1
,
745 if ((FfsAttrib
& FFS_ATTRIB_FIXED
) != 0) {
746 VerboseMsg ("FFS File has the fixed file attribute");
748 if ((FfsAttrib
& FFS_ATTRIB_CHECKSUM
) != 0) {
749 VerboseMsg ("FFS File requires the checksum of the whole file");
751 VerboseMsg ("FFS file alignment is %s", mFfsValidAlignName
[FfsAlign
]);
752 for (Index
= 0; Index
< InputFileNum
; Index
++) {
753 if (InputFileAlign
[Index
] == 0) {
755 // Minimum alignment is 1 byte.
757 InputFileAlign
[Index
] = 1;
759 VerboseMsg ("the %dth input section name is %s and section alignment is %u", Index
, InputFileName
[Index
], (unsigned) InputFileAlign
[Index
]);
763 // Calculate the size of all input section files.
765 Status
= GetSectionContents (
775 if ((FfsFiletype
== EFI_FV_FILETYPE_SECURITY_CORE
||
776 FfsFiletype
== EFI_FV_FILETYPE_PEI_CORE
||
777 FfsFiletype
== EFI_FV_FILETYPE_DXE_CORE
) && (PeSectionNum
!= 1)) {
778 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
);
782 if ((FfsFiletype
== EFI_FV_FILETYPE_PEIM
||
783 FfsFiletype
== EFI_FV_FILETYPE_DRIVER
||
784 FfsFiletype
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
||
785 FfsFiletype
== EFI_FV_FILETYPE_APPLICATION
) && (PeSectionNum
< 1)) {
786 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
]);
790 if (Status
== EFI_BUFFER_TOO_SMALL
) {
791 FileBuffer
= (UINT8
*) malloc (FileSize
);
792 if (FileBuffer
== NULL
) {
793 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
796 memset (FileBuffer
, 0, FileSize
);
799 // read all input file contents into a buffer
801 Status
= GetSectionContents (
812 if (EFI_ERROR (Status
)) {
817 // Create Ffs file header.
819 memset (&FfsFileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
820 memcpy (&FfsFileHeader
.Name
, &FileGuid
, sizeof (EFI_GUID
));
821 FfsFileHeader
.Type
= FfsFiletype
;
823 // Update FFS Alignment based on the max alignment required by input section files
825 VerboseMsg ("the max alignment of all input sections is %u", (unsigned) MaxAlignment
);
826 for (Index
= 0; Index
< sizeof (mFfsValidAlign
) / sizeof (UINT32
) - 1; Index
++) {
827 if ((MaxAlignment
> mFfsValidAlign
[Index
]) && (MaxAlignment
<= mFfsValidAlign
[Index
+ 1])) {
831 if (FfsAlign
< Index
) {
834 VerboseMsg ("the alignment of the generated FFS file is %u", (unsigned) mFfsValidAlign
[FfsAlign
+ 1]);
835 FfsFileHeader
.Attributes
= (EFI_FFS_FILE_ATTRIBUTES
) (FfsAttrib
| (FfsAlign
<< 3));
838 // Now FileSize includes the EFI_FFS_FILE_HEADER
840 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
841 VerboseMsg ("the size of the generated FFS file is %u bytes", (unsigned) FileSize
);
842 FfsFileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
843 FfsFileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
844 FfsFileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
846 // Fill in checksums and state, these must be zero for checksumming
848 // FileHeader.IntegrityCheck.Checksum.Header = 0;
849 // FileHeader.IntegrityCheck.Checksum.File = 0;
850 // FileHeader.State = 0;
852 FfsFileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
853 (UINT8
*) &FfsFileHeader
,
854 sizeof (EFI_FFS_FILE_HEADER
)
857 if (FfsFileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
859 // Ffs header checksum = zero, so only need to calculate ffs body.
861 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
863 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
866 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
869 FfsFileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
872 // Open output file to write ffs data.
874 remove(OutputFileName
);
875 FfsFile
= fopen (OutputFileName
, "wb");
876 if (FfsFile
== NULL
) {
877 Error (NULL
, 0, 0001, "Error opening file", OutputFileName
);
883 fwrite (&FfsFileHeader
, 1, sizeof (FfsFileHeader
), FfsFile
);
887 fwrite (FileBuffer
, 1, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), FfsFile
);
892 if (InputFileName
!= NULL
) {
893 free (InputFileName
);
895 if (InputFileAlign
!= NULL
) {
896 free (InputFileAlign
);
898 if (FileBuffer
!= NULL
) {
902 // If any errors were reported via the standard error reporting
903 // routines, then the status has been saved. Get the value and
904 // return it to the caller.
906 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
908 return GetUtilityStatus ();