3 Copyright (c) 2004-2008, Intel Corporation
4 All rights reserved. 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\n", UTILITY_NAME
, UTILITY_MAJOR_VERSION
, UTILITY_MINOR_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, 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
;
296 // Go through our array of file names and copy their contents
297 // to the output buffer.
299 for (Index
= 0; Index
< InputFileNum
; Index
++) {
301 // make sure section ends on a DWORD boundary
303 while ((Size
& 0x03) != 0) {
308 // Get the Max alignment of all input file datas
310 if (*MaxAlignment
< InputFileAlign
[Index
]) {
311 *MaxAlignment
= InputFileAlign
[Index
];
315 // Open file and read contents
317 InFile
= fopen (InputFileName
[Index
], "rb");
318 if (InFile
== NULL
) {
319 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
323 fseek (InFile
, 0, SEEK_END
);
324 FileSize
= ftell (InFile
);
325 fseek (InFile
, 0, SEEK_SET
);
326 DebugMsg (NULL
, 0, 9, "Input section files",
327 "the input section name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
330 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
333 fread (&TempSectHeader
, 1, sizeof (TempSectHeader
), 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_COMPRESSION
||
343 TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
||
344 TempSectHeader
.Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
346 // for the encapsulated section, assume it contains Pe/Te section
351 fseek (InFile
, 0, SEEK_SET
);
354 // Revert TeOffset to the converse value relative to Alignment
355 // This is to assure the original PeImage Header at Alignment.
357 if ((TeOffset
!= 0) && (InputFileAlign
[Index
] != 0)) {
358 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
359 TeOffset
= TeOffset
% InputFileAlign
[Index
];
363 // make sure section data meet its alignment requirement by adding one raw pad section.
364 // But the different sections have the different section header. Necessary or not?
365 // Based on section type to adjust offset? Todo
367 if ((InputFileAlign
[Index
] != 0) && (((Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + TeOffset
) % InputFileAlign
[Index
]) != 0)) {
368 Offset
= (Size
+ 2 * sizeof (EFI_COMMON_SECTION_HEADER
) + TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
369 Offset
= Offset
- Size
- sizeof (EFI_COMMON_SECTION_HEADER
) - TeOffset
;
371 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
372 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
373 SectHeader
->Type
= EFI_SECTION_RAW
;
374 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
375 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
376 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
378 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment",
379 "Pad Raw section size is %u", (unsigned) Offset
);
381 Size
= Size
+ Offset
;
385 // Now read the contents of the file into the buffer
386 // Buffer must be enough to contain the file content.
388 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
389 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
390 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
401 // Set the actual length of the data.
403 if (Size
> *BufferLength
) {
404 *BufferLength
= Size
;
405 return EFI_BUFFER_TOO_SMALL
;
407 *BufferLength
= Size
;
425 argc - Number of command line parameters.
426 argv - Array of pointers to parameter strings.
429 STATUS_SUCCESS - Utility exits successfully.
430 STATUS_ERROR - Some error occurred during execution.
435 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
437 EFI_FV_FILETYPE FfsFiletype
;
438 CHAR8
*OutputFileName
;
439 EFI_GUID FileGuid
= {0};
441 UINT32
*InputFileAlign
;
442 CHAR8
**InputFileName
;
446 EFI_FFS_FILE_HEADER FfsFileHeader
;
453 // Init local variables
459 FfsFiletype
= EFI_FV_FILETYPE_ALL
;
460 OutputFileName
= NULL
;
462 InputFileName
= NULL
;
463 InputFileAlign
= NULL
;
468 Status
= EFI_SUCCESS
;
471 SetUtilityName (UTILITY_NAME
);
474 Error (NULL
, 0, 1001, "Missing options", "no options input");
480 // Parse command line
485 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
488 return STATUS_SUCCESS
;
491 if (stricmp (argv
[0], "--version") == 0) {
493 return STATUS_SUCCESS
;
497 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--filetype") == 0)) {
498 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
499 Error (NULL
, 0, 1003, "Invalid option value", "file type is missing for -t option");
502 FfsFiletype
= StringToType (argv
[1]);
503 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
504 Error (NULL
, 0, 1003, "Invalid option value", "%s is not a valid file type", argv
[1]);
512 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
513 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
514 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
517 OutputFileName
= argv
[1];
523 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--fileguid") == 0)) {
524 Status
= StringToGuid (argv
[1], &FileGuid
);
525 if (EFI_ERROR (Status
)) {
526 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
534 if ((stricmp (argv
[0], "-x") == 0) || (stricmp (argv
[0], "--fixed") == 0)) {
535 FfsAttrib
|= FFS_ATTRIB_FIXED
;
541 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--checksum") == 0)) {
542 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
548 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
549 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
550 Error (NULL
, 0, 1003, "Invalid option value", "Align value is missing for -a option");
553 for (Index
= 0; Index
< sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*); Index
++) {
554 if (stricmp (argv
[1], mFfsValidAlignName
[Index
]) == 0) {
558 if (Index
== sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*)) {
559 if ((stricmp (argv
[1], "1") == 0) || (stricmp (argv
[1], "2") == 0) || (stricmp (argv
[1], "4") == 0)) {
561 // 1, 2, 4 byte alignment same to 8 byte alignment
565 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
575 if ((stricmp (argv
[0], "-i") == 0) || (stricmp (argv
[0], "--sectionfile") == 0)) {
577 // Get Input file name and its alignment
579 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
580 Error (NULL
, 0, 1003, "Invalid option value", "input section file is missing for -i option");
585 // Allocate Input file name buffer and its alignment buffer.
587 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
588 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
589 if (InputFileName
== NULL
) {
590 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
593 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
595 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
596 if (InputFileAlign
== NULL
) {
597 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
598 free (InputFileName
);
601 memset (InputFileAlign
, 0, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
602 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
604 // InputFileName and alignment buffer too small, need to realloc
606 InputFileName
= (CHAR8
**) realloc (
608 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
611 if (InputFileName
== NULL
) {
612 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
613 free (InputFileAlign
);
616 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
618 InputFileAlign
= (UINT32
*) realloc (
620 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
623 if (InputFileAlign
== NULL
) {
624 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
625 free (InputFileName
);
628 memset (&(InputFileAlign
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
631 InputFileName
[InputFileNum
] = argv
[1];
641 // Section File alignment requirement
643 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
644 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileNum
]));
645 if (EFI_ERROR (Status
)) {
646 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
656 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
657 Error (NULL
, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file.");
661 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
662 SetPrintLevel (VERBOSE_LOG_LEVEL
);
663 VerboseMsg ("Verbose output Mode Set!");
669 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
670 SetPrintLevel (KEY_LOG_LEVEL
);
671 KeyMsg ("Quiet output Mode Set!");
677 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
678 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
679 if (EFI_ERROR (Status
)) {
680 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
684 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
687 SetPrintLevel (LogLevel
);
688 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
694 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
698 VerboseMsg ("%s tool start.", UTILITY_NAME
);
701 // Check the complete input paramters.
703 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
704 Error (NULL
, 0, 1001, "Missing option", "filetype");
708 if (CompareGuid (&FileGuid
, &mZeroGuid
) == 0) {
709 Error (NULL
, 0, 1001, "Missing option", "fileguid");
713 if (InputFileNum
== 0) {
714 Error (NULL
, 0, 1001, "Missing option", "Input files");
719 // Output input parameter information
721 VerboseMsg ("Fv File type is %s", mFfsFileType
[FfsFiletype
]);
722 VerboseMsg ("Output file name is %s", OutputFileName
);
723 VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
724 (unsigned) FileGuid
.Data1
,
735 if ((FfsAttrib
& FFS_ATTRIB_FIXED
) != 0) {
736 VerboseMsg ("FFS File has the fixed file attribute");
738 if ((FfsAttrib
& FFS_ATTRIB_CHECKSUM
) != 0) {
739 VerboseMsg ("FFS File requires the checksum of the whole file");
741 VerboseMsg ("FFS file alignment is %s", mFfsValidAlignName
[FfsAlign
]);
742 for (Index
= 0; Index
< InputFileNum
; Index
++) {
743 if (InputFileAlign
[Index
] == 0) {
745 // Minimum alignment is 1 byte.
747 InputFileAlign
[Index
] = 1;
749 VerboseMsg ("the %dth input section name is %s and section alignment is %u", Index
, InputFileName
[Index
], (unsigned) InputFileAlign
[Index
]);
753 // Calculate the size of all input section files.
755 Status
= GetSectionContents (
765 if ((FfsFiletype
== EFI_FV_FILETYPE_SECURITY_CORE
||
766 FfsFiletype
== EFI_FV_FILETYPE_PEI_CORE
||
767 FfsFiletype
== EFI_FV_FILETYPE_DXE_CORE
) && (PeSectionNum
!= 1)) {
768 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
);
772 if ((FfsFiletype
== EFI_FV_FILETYPE_PEIM
||
773 FfsFiletype
== EFI_FV_FILETYPE_DRIVER
||
774 FfsFiletype
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
||
775 FfsFiletype
== EFI_FV_FILETYPE_APPLICATION
) && (PeSectionNum
< 1)) {
776 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
]);
780 if (Status
== EFI_BUFFER_TOO_SMALL
) {
781 FileBuffer
= (UINT8
*) malloc (FileSize
);
782 if (FileBuffer
== NULL
) {
783 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
786 memset (FileBuffer
, 0, FileSize
);
789 // read all input file contents into a buffer
791 Status
= GetSectionContents (
802 if (EFI_ERROR (Status
)) {
807 // Create Ffs file header.
809 memset (&FfsFileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
810 memcpy (&FfsFileHeader
.Name
, &FileGuid
, sizeof (EFI_GUID
));
811 FfsFileHeader
.Type
= FfsFiletype
;
813 // Update FFS Alignment based on the max alignment required by input section files
815 VerboseMsg ("the max alignment of all input sections is %u", (unsigned) MaxAlignment
);
816 for (Index
= 0; Index
< sizeof (mFfsValidAlign
) / sizeof (UINT32
) - 1; Index
++) {
817 if ((MaxAlignment
> mFfsValidAlign
[Index
]) && (MaxAlignment
<= mFfsValidAlign
[Index
+ 1])) {
821 if (FfsAlign
< Index
) {
824 VerboseMsg ("the alignment of the generated FFS file is %u", (unsigned) mFfsValidAlign
[FfsAlign
+ 1]);
825 FfsFileHeader
.Attributes
= (EFI_FFS_FILE_ATTRIBUTES
) (FfsAttrib
| (FfsAlign
<< 3));
828 // Now FileSize includes the EFI_FFS_FILE_HEADER
830 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
831 VerboseMsg ("the size of the generated FFS file is %u bytes", (unsigned) FileSize
);
832 FfsFileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
833 FfsFileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
834 FfsFileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
836 // Fill in checksums and state, these must be zero for checksumming
838 // FileHeader.IntegrityCheck.Checksum.Header = 0;
839 // FileHeader.IntegrityCheck.Checksum.File = 0;
840 // FileHeader.State = 0;
842 FfsFileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
843 (UINT8
*) &FfsFileHeader
,
844 sizeof (EFI_FFS_FILE_HEADER
)
847 if (FfsFileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
849 // Ffs header checksum = zero, so only need to calculate ffs body.
851 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
853 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
856 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
859 FfsFileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
862 // Open output file to write ffs data.
864 remove(OutputFileName
);
865 FfsFile
= fopen (OutputFileName
, "wb");
866 if (FfsFile
== NULL
) {
867 Error (NULL
, 0, 0001, "Error opening file", OutputFileName
);
873 fwrite (&FfsFileHeader
, 1, sizeof (FfsFileHeader
), FfsFile
);
877 fwrite (FileBuffer
, 1, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), FfsFile
);
882 if (InputFileName
!= NULL
) {
883 free (InputFileName
);
885 if (InputFileAlign
!= NULL
) {
886 free (InputFileAlign
);
888 if (FileBuffer
!= NULL
) {
892 // If any errors were reported via the standard error reporting
893 // routines, then the status has been saved. Get the value and
894 // return it to the caller.
896 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
898 return GetUtilityStatus ();