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_FIRMWARE_VOLUME_IMAGE.\n");
138 fprintf (stdout
, " -g FileGuid, --fileguid FileGuid\n\
139 FileGuid is one module guid.\n\
140 Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
141 fprintf (stdout
, " -x, --fixed Indicates that the file may not be moved\n\
142 from its present location.\n");
143 fprintf (stdout
, " -s, --checksum Indicates to calculate file checksum.\n");
144 fprintf (stdout
, " -a FileAlign, --align FileAlign\n\
145 FileAlign points to file alignment, which only support\n\
146 the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n");
147 fprintf (stdout
, " -i SectionFile, --sectionfile SectionFile\n\
148 Section file will be contained in this FFS file.\n");
149 fprintf (stdout
, " -n SectionAlign, --sectionalign SectionAlign\n\
150 SectionAlign points to section alignment, which support\n\
151 the alignment scope 1~64K. It is specified together\n\
152 with sectionfile to point its alignment in FFS file.\n");
153 fprintf (stdout
, " -v, --verbose Turn on verbose output with informational messages.\n");
154 fprintf (stdout
, " -q, --quiet Disable all messages except key message and fatal error\n");
155 fprintf (stdout
, " -d, --debug level Enable debug messages, at input debug level.\n");
156 fprintf (stdout
, " --version Show program's version number and exit.\n");
157 fprintf (stdout
, " -h, --help Show this help message and exit.\n");
163 IN CHAR8
*AlignBuffer
,
164 OUT UINT32
*AlignNumber
170 Converts Align String to align value (1~64K).
174 AlignBuffer - Pointer to Align string.
175 AlignNumber - Pointer to Align value.
179 EFI_SUCCESS Successfully convert align string to align value.
180 EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
188 if (AlignBuffer
== NULL
) {
189 return EFI_INVALID_PARAMETER
;
191 for (Index
= 0; Index
< sizeof (mAlignName
) / sizeof (CHAR8
*); Index
++) {
192 if (stricmp (AlignBuffer
, mAlignName
[Index
]) == 0) {
193 *AlignNumber
= 1 << Index
;
197 return EFI_INVALID_PARAMETER
;
209 Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
210 unrecognized file type was specified.
214 String - File type string
224 if (String
== NULL
) {
225 return EFI_FV_FILETYPE_ALL
;
228 for (Index
= 0; Index
< sizeof (mFfsFileType
) / sizeof (CHAR8
*); Index
++) {
229 if (mFfsFileType
[Index
] != NULL
&& (stricmp (String
, mFfsFileType
[Index
]) == 0)) {
233 return EFI_FV_FILETYPE_ALL
;
239 IN CHAR8
**InputFileName
,
240 IN UINT32
*InputFileAlign
,
241 IN UINT32 InputFileNum
,
242 OUT UINT8
*FileBuffer
,
243 OUT UINT32
*BufferLength
,
244 OUT UINT32
*MaxAlignment
,
245 OUT UINT8
*PESectionNum
251 Get the contents of all section files specified in InputFileName
256 InputFileName - Name of the input file.
258 InputFileAlign - Alignment required by the input file data.
260 InputFileNum - Number of input files. Should be at least 1.
262 FileBuffer - Output buffer to contain data
264 BufferLength - On input, this is size of the FileBuffer.
265 On output, this is the actual length of the data.
267 MaxAlignment - The max alignment required by all the input file datas.
269 PeSectionNum - Calculate the number of Pe/Te Section in this FFS file.
273 EFI_SUCCESS on successful return
274 EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
275 EFI_ABORTED if unable to open input file.
276 EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
284 EFI_COMMON_SECTION_HEADER
*SectHeader
;
285 EFI_COMMON_SECTION_HEADER TempSectHeader
;
286 EFI_TE_IMAGE_HEADER TeHeader
;
294 // Go through our array of file names and copy their contents
295 // to the output buffer.
297 for (Index
= 0; Index
< InputFileNum
; Index
++) {
299 // make sure section ends on a DWORD boundary
301 while ((Size
& 0x03) != 0) {
306 // Get the Max alignment of all input file datas
308 if (*MaxAlignment
< InputFileAlign
[Index
]) {
309 *MaxAlignment
= InputFileAlign
[Index
];
313 // Open file and read contents
315 InFile
= fopen (InputFileName
[Index
], "rb");
316 if (InFile
== NULL
) {
317 Error (NULL
, 0, 0001, "Error opening file", InputFileName
[Index
]);
321 fseek (InFile
, 0, SEEK_END
);
322 FileSize
= ftell (InFile
);
323 fseek (InFile
, 0, SEEK_SET
);
324 DebugMsg (NULL
, 0, 9, "Input section files",
325 "the input section name is %s and the size is %u bytes", InputFileName
[Index
], (unsigned) FileSize
);
328 // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
331 fread (&TempSectHeader
, 1, sizeof (TempSectHeader
), InFile
);
332 if (TempSectHeader
.Type
== EFI_SECTION_TE
) {
334 fread (&TeHeader
, 1, sizeof (TeHeader
), InFile
);
335 if (TeHeader
.Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
336 TeOffset
= TeHeader
.StrippedSize
- sizeof (TeHeader
);
338 } else if (TempSectHeader
.Type
== EFI_SECTION_PE32
) {
340 } else if (TempSectHeader
.Type
== EFI_SECTION_COMPRESSION
||
341 TempSectHeader
.Type
== EFI_SECTION_GUID_DEFINED
||
342 TempSectHeader
.Type
== EFI_SECTION_FIRMWARE_VOLUME_IMAGE
) {
344 // for the encapsulated section, assume it contains Pe/Te section
349 fseek (InFile
, 0, SEEK_SET
);
352 // Revert TeOffset to the converse value relative to Alignment
353 // This is to assure the original PeImage Header at Alignment.
355 if ((TeOffset
!= 0) && (InputFileAlign
[Index
] != 0)) {
356 TeOffset
= InputFileAlign
[Index
] - (TeOffset
% InputFileAlign
[Index
]);
357 TeOffset
= TeOffset
% InputFileAlign
[Index
];
361 // make sure section data meet its alignment requirement by adding one raw pad section.
362 // But the different sections have the different section header. Necessary or not?
363 // Based on section type to adjust offset? Todo
365 if ((InputFileAlign
[Index
] != 0) && (((Size
+ sizeof (EFI_COMMON_SECTION_HEADER
) + TeOffset
) % InputFileAlign
[Index
]) != 0)) {
366 Offset
= (Size
+ 2 * sizeof (EFI_COMMON_SECTION_HEADER
) + TeOffset
+ InputFileAlign
[Index
] - 1) & ~(InputFileAlign
[Index
] - 1);
367 Offset
= Offset
- Size
- sizeof (EFI_COMMON_SECTION_HEADER
) - TeOffset
;
369 if (FileBuffer
!= NULL
&& ((Size
+ Offset
) < *BufferLength
)) {
370 SectHeader
= (EFI_COMMON_SECTION_HEADER
*) (FileBuffer
+ Size
);
371 SectHeader
->Type
= EFI_SECTION_RAW
;
372 SectHeader
->Size
[0] = (UINT8
) (Offset
& 0xff);
373 SectHeader
->Size
[1] = (UINT8
) ((Offset
& 0xff00) >> 8);
374 SectHeader
->Size
[2] = (UINT8
) ((Offset
& 0xff0000) >> 16);
376 DebugMsg (NULL
, 0, 9, "Pad raw section for section data alignment",
377 "Pad Raw section size is %u", (unsigned) Offset
);
379 Size
= Size
+ Offset
;
383 // Now read the contents of the file into the buffer
384 // Buffer must be enough to contain the file content.
386 if ((FileSize
> 0) && (FileBuffer
!= NULL
) && ((Size
+ FileSize
) <= *BufferLength
)) {
387 if (fread (FileBuffer
+ Size
, (size_t) FileSize
, 1, InFile
) != 1) {
388 Error (NULL
, 0, 0004, "Error reading file", InputFileName
[Index
]);
399 // Set the actual length of the data.
401 if (Size
> *BufferLength
) {
402 *BufferLength
= Size
;
403 return EFI_BUFFER_TOO_SMALL
;
405 *BufferLength
= Size
;
423 argc - Number of command line parameters.
424 argv - Array of pointers to parameter strings.
427 STATUS_SUCCESS - Utility exits successfully.
428 STATUS_ERROR - Some error occurred during execution.
433 EFI_FFS_FILE_ATTRIBUTES FfsAttrib
;
435 EFI_FV_FILETYPE FfsFiletype
;
436 CHAR8
*OutputFileName
;
437 EFI_GUID FileGuid
= {0};
439 UINT32
*InputFileAlign
;
440 CHAR8
**InputFileName
;
444 EFI_FFS_FILE_HEADER FfsFileHeader
;
451 // Init local variables
457 FfsFiletype
= EFI_FV_FILETYPE_ALL
;
458 OutputFileName
= NULL
;
460 InputFileName
= NULL
;
461 InputFileAlign
= NULL
;
466 Status
= EFI_SUCCESS
;
469 SetUtilityName (UTILITY_NAME
);
472 Error (NULL
, 0, 1001, "Missing options", "no options input");
478 // Parse command line
483 if ((stricmp (argv
[0], "-h") == 0) || (stricmp (argv
[0], "--help") == 0)) {
486 return STATUS_SUCCESS
;
489 if (stricmp (argv
[0], "--version") == 0) {
491 return STATUS_SUCCESS
;
495 if ((stricmp (argv
[0], "-t") == 0) || (stricmp (argv
[0], "--filetype") == 0)) {
496 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
497 Error (NULL
, 0, 1003, "Invalid option value", "file type is missing for -t option");
500 FfsFiletype
= StringToType (argv
[1]);
501 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
502 Error (NULL
, 0, 1003, "Invalid option value", "%s is not a valid file type", argv
[1]);
510 if ((stricmp (argv
[0], "-o") == 0) || (stricmp (argv
[0], "--outputfile") == 0)) {
511 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
512 Error (NULL
, 0, 1003, "Invalid option value", "Output file is missing for -o option");
515 OutputFileName
= argv
[1];
521 if ((stricmp (argv
[0], "-g") == 0) || (stricmp (argv
[0], "--fileguid") == 0)) {
522 Status
= StringToGuid (argv
[1], &FileGuid
);
523 if (EFI_ERROR (Status
)) {
524 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
532 if ((stricmp (argv
[0], "-x") == 0) || (stricmp (argv
[0], "--fixed") == 0)) {
533 FfsAttrib
|= FFS_ATTRIB_FIXED
;
539 if ((stricmp (argv
[0], "-s") == 0) || (stricmp (argv
[0], "--checksum") == 0)) {
540 FfsAttrib
|= FFS_ATTRIB_CHECKSUM
;
546 if ((stricmp (argv
[0], "-a") == 0) || (stricmp (argv
[0], "--align") == 0)) {
547 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
548 Error (NULL
, 0, 1003, "Invalid option value", "Align value is missing for -a option");
551 for (Index
= 0; Index
< sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*); Index
++) {
552 if (stricmp (argv
[1], mFfsValidAlignName
[Index
]) == 0) {
556 if (Index
== sizeof (mFfsValidAlignName
) / sizeof (CHAR8
*)) {
557 if ((stricmp (argv
[1], "1") == 0) || (stricmp (argv
[1], "2") == 0) || (stricmp (argv
[1], "4") == 0)) {
559 // 1, 2, 4 byte alignment same to 8 byte alignment
563 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
573 if ((stricmp (argv
[0], "-i") == 0) || (stricmp (argv
[0], "--sectionfile") == 0)) {
575 // Get Input file name and its alignment
577 if (argv
[1] == NULL
|| argv
[1][0] == '-') {
578 Error (NULL
, 0, 1003, "Invalid option value", "input section file is missing for -i option");
583 // Allocate Input file name buffer and its alignment buffer.
585 if ((InputFileNum
== 0) && (InputFileName
== NULL
)) {
586 InputFileName
= (CHAR8
**) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*));
587 if (InputFileName
== NULL
) {
588 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
591 memset (InputFileName
, 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
593 InputFileAlign
= (UINT32
*) malloc (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
594 if (InputFileAlign
== NULL
) {
595 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
596 free (InputFileName
);
599 memset (InputFileAlign
, 0, MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
));
600 } else if (InputFileNum
% MAXIMUM_INPUT_FILE_NUM
== 0) {
602 // InputFileName and alignment buffer too small, need to realloc
604 InputFileName
= (CHAR8
**) realloc (
606 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (CHAR8
*)
609 if (InputFileName
== NULL
) {
610 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
611 free (InputFileAlign
);
614 memset (&(InputFileName
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (CHAR8
*)));
616 InputFileAlign
= (UINT32
*) realloc (
618 (InputFileNum
+ MAXIMUM_INPUT_FILE_NUM
) * sizeof (UINT32
)
621 if (InputFileAlign
== NULL
) {
622 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
623 free (InputFileName
);
626 memset (&(InputFileAlign
[InputFileNum
]), 0, (MAXIMUM_INPUT_FILE_NUM
* sizeof (UINT32
)));
629 InputFileName
[InputFileNum
] = argv
[1];
639 // Section File alignment requirement
641 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
642 Status
= StringtoAlignment (argv
[1], &(InputFileAlign
[InputFileNum
]));
643 if (EFI_ERROR (Status
)) {
644 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
654 if ((stricmp (argv
[0], "-n") == 0) || (stricmp (argv
[0], "--sectionalign") == 0)) {
655 Error (NULL
, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file.");
659 if ((stricmp (argv
[0], "-v") == 0) || (stricmp (argv
[0], "--verbose") == 0)) {
660 SetPrintLevel (VERBOSE_LOG_LEVEL
);
661 VerboseMsg ("Verbose output Mode Set!");
667 if ((stricmp (argv
[0], "-q") == 0) || (stricmp (argv
[0], "--quiet") == 0)) {
668 SetPrintLevel (KEY_LOG_LEVEL
);
669 KeyMsg ("Quiet output Mode Set!");
675 if ((stricmp (argv
[0], "-d") == 0) || (stricmp (argv
[0], "--debug") == 0)) {
676 Status
= AsciiStringToUint64 (argv
[1], FALSE
, &LogLevel
);
677 if (EFI_ERROR (Status
)) {
678 Error (NULL
, 0, 1003, "Invalid option value", "%s = %s", argv
[0], argv
[1]);
682 Error (NULL
, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel
);
685 SetPrintLevel (LogLevel
);
686 DebugMsg (NULL
, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv
[1]);
692 Error (NULL
, 0, 1000, "Unknown option", argv
[0]);
696 VerboseMsg ("%s tool start.", UTILITY_NAME
);
699 // Check the complete input paramters.
701 if (FfsFiletype
== EFI_FV_FILETYPE_ALL
) {
702 Error (NULL
, 0, 1001, "Missing option", "filetype");
706 if (CompareGuid (&FileGuid
, &mZeroGuid
) == 0) {
707 Error (NULL
, 0, 1001, "Missing option", "fileguid");
711 if (InputFileNum
== 0) {
712 Error (NULL
, 0, 1001, "Missing option", "Input files");
717 // Output input parameter information
719 VerboseMsg ("Fv File type is %s", mFfsFileType
[FfsFiletype
]);
720 VerboseMsg ("Output file name is %s", OutputFileName
);
721 VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
722 (unsigned) FileGuid
.Data1
,
733 if ((FfsAttrib
& FFS_ATTRIB_FIXED
) != 0) {
734 VerboseMsg ("FFS File has the fixed file attribute");
736 if ((FfsAttrib
& FFS_ATTRIB_CHECKSUM
) != 0) {
737 VerboseMsg ("FFS File requires the checksum of the whole file");
739 VerboseMsg ("FFS file alignment is %s", mFfsValidAlignName
[FfsAlign
]);
740 for (Index
= 0; Index
< InputFileNum
; Index
++) {
741 if (InputFileAlign
[Index
] == 0) {
743 // Minimum alignment is 1 byte.
745 InputFileAlign
[Index
] = 1;
747 VerboseMsg ("the %dth input section name is %s and section alignment is %u", Index
, InputFileName
[Index
], (unsigned) InputFileAlign
[Index
]);
751 // Calculate the size of all input section files.
753 Status
= GetSectionContents (
763 if ((FfsFiletype
== EFI_FV_FILETYPE_SECURITY_CORE
||
764 FfsFiletype
== EFI_FV_FILETYPE_PEI_CORE
||
765 FfsFiletype
== EFI_FV_FILETYPE_DXE_CORE
) && (PeSectionNum
!= 1)) {
766 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
);
770 if ((FfsFiletype
== EFI_FV_FILETYPE_PEIM
||
771 FfsFiletype
== EFI_FV_FILETYPE_DRIVER
||
772 FfsFiletype
== EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER
||
773 FfsFiletype
== EFI_FV_FILETYPE_APPLICATION
) && (PeSectionNum
< 1)) {
774 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
]);
778 if (Status
== EFI_BUFFER_TOO_SMALL
) {
779 FileBuffer
= (UINT8
*) malloc (FileSize
);
780 if (FileBuffer
== NULL
) {
781 Error (NULL
, 0, 4001, "Resource", "memory cannot be allocated!");
784 memset (FileBuffer
, 0, FileSize
);
787 // read all input file contents into a buffer
789 Status
= GetSectionContents (
800 if (EFI_ERROR (Status
)) {
805 // Create Ffs file header.
807 memset (&FfsFileHeader
, 0, sizeof (EFI_FFS_FILE_HEADER
));
808 memcpy (&FfsFileHeader
.Name
, &FileGuid
, sizeof (EFI_GUID
));
809 FfsFileHeader
.Type
= FfsFiletype
;
811 // Update FFS Alignment based on the max alignment required by input section files
813 VerboseMsg ("the max alignment of all input sections is %u", (unsigned) MaxAlignment
);
814 for (Index
= 0; Index
< sizeof (mFfsValidAlign
) / sizeof (UINT32
) - 1; Index
++) {
815 if ((MaxAlignment
> mFfsValidAlign
[Index
]) && (MaxAlignment
<= mFfsValidAlign
[Index
+ 1])) {
819 if (FfsAlign
< Index
) {
822 VerboseMsg ("the alignment of the generated FFS file is %u", (unsigned) mFfsValidAlign
[FfsAlign
+ 1]);
823 FfsFileHeader
.Attributes
= (EFI_FFS_FILE_ATTRIBUTES
) (FfsAttrib
| (FfsAlign
<< 3));
826 // Now FileSize includes the EFI_FFS_FILE_HEADER
828 FileSize
+= sizeof (EFI_FFS_FILE_HEADER
);
829 VerboseMsg ("the size of the generated FFS file is %u bytes", (unsigned) FileSize
);
830 FfsFileHeader
.Size
[0] = (UINT8
) (FileSize
& 0xFF);
831 FfsFileHeader
.Size
[1] = (UINT8
) ((FileSize
& 0xFF00) >> 8);
832 FfsFileHeader
.Size
[2] = (UINT8
) ((FileSize
& 0xFF0000) >> 16);
834 // Fill in checksums and state, these must be zero for checksumming
836 // FileHeader.IntegrityCheck.Checksum.Header = 0;
837 // FileHeader.IntegrityCheck.Checksum.File = 0;
838 // FileHeader.State = 0;
840 FfsFileHeader
.IntegrityCheck
.Checksum
.Header
= CalculateChecksum8 (
841 (UINT8
*) &FfsFileHeader
,
842 sizeof (EFI_FFS_FILE_HEADER
)
845 if (FfsFileHeader
.Attributes
& FFS_ATTRIB_CHECKSUM
) {
847 // Ffs header checksum = zero, so only need to calculate ffs body.
849 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= CalculateChecksum8 (
851 FileSize
- sizeof (EFI_FFS_FILE_HEADER
)
854 FfsFileHeader
.IntegrityCheck
.Checksum
.File
= FFS_FIXED_CHECKSUM
;
857 FfsFileHeader
.State
= EFI_FILE_HEADER_CONSTRUCTION
| EFI_FILE_HEADER_VALID
| EFI_FILE_DATA_VALID
;
860 // Open output file to write ffs data.
862 remove(OutputFileName
);
863 FfsFile
= fopen (OutputFileName
, "wb");
864 if (FfsFile
== NULL
) {
865 Error (NULL
, 0, 0001, "Error opening file", OutputFileName
);
871 fwrite (&FfsFileHeader
, 1, sizeof (FfsFileHeader
), FfsFile
);
875 fwrite (FileBuffer
, 1, FileSize
- sizeof (EFI_FFS_FILE_HEADER
), FfsFile
);
880 if (InputFileName
!= NULL
) {
881 free (InputFileName
);
883 if (InputFileAlign
!= NULL
) {
884 free (InputFileAlign
);
886 if (FileBuffer
!= NULL
) {
890 // If any errors were reported via the standard error reporting
891 // routines, then the status has been saved. Get the value and
892 // return it to the caller.
894 VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME
, GetUtilityStatus ());
896 return GetUtilityStatus ();