-/**\r
+/** @file\r
+This file contains functions required to generate a Firmware File System file.\r
\r
-Copyright (c) 2004-2008, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
+Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
are licensed and made available under the terms and conditions of the BSD License \r
which accompanies this distribution. The full text of the license may be found at \r
http://opensource.org/licenses/bsd-license.php \r
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
\r
-Module Name:\r
-\r
- GenFfs.c\r
-\r
-Abstract:\r
-\r
- This file contains functions required to generate a Firmware File System\r
- file.\r
-\r
**/\r
\r
+#ifndef __GNUC__\r
+#include <windows.h>\r
+#include <io.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#endif\r
+\r
#include <stdio.h>\r
#include <stdlib.h>\r
#include <string.h>\r
#include <Common/UefiBaseTypes.h>\r
#include <Common/PiFirmwareFile.h>\r
#include <IndustryStandard/PeImage.h>\r
+#include <Guid/FfsSectionAlignmentPadding.h>\r
\r
#include "CommonLib.h"\r
#include "ParseInf.h"\r
#include "EfiUtilityMsgs.h"\r
+#include "FvLib.h"\r
+#include "PeCoffLib.h"\r
\r
#define UTILITY_NAME "GenFfs"\r
#define UTILITY_MAJOR_VERSION 0\r
"EFI_FV_FILETYPE_SMM", // 0x0A\r
"EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B\r
"EFI_FV_FILETYPE_COMBINED_SMM_DXE", // 0x0C\r
- "EFI_FV_FILETYPE_SMM_CORE" // 0x0D\r
- };\r
+ "EFI_FV_FILETYPE_SMM_CORE", // 0x0D\r
+ "EFI_FV_FILETYPE_MM_STANDALONE", // 0x0E\r
+ "EFI_FV_FILETYPE_MM_CORE_STANDALONE" // 0x0F\r
+};\r
\r
STATIC CHAR8 *mAlignName[] = {\r
"1", "2", "4", "8", "16", "32", "64", "128", "256", "512",\r
- "1K", "2K", "4K", "8K", "16K", "32K", "64K"\r
+ "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K",\r
+ "512K", "1M", "2M", "4M", "8M", "16M"\r
};\r
\r
STATIC CHAR8 *mFfsValidAlignName[] = {\r
- "8", "16", "128", "512", "1K", "4K", "32K", "64K"\r
+ "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K","256K",\r
+ "512K", "1M", "2M", "4M", "8M", "16M"\r
};\r
\r
-STATIC UINT32 mFfsValidAlign[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536};\r
+STATIC UINT32 mFfsValidAlign[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536, 131072, 262144,\r
+ 524288, 1048576, 2097152, 4194304, 8388608, 16777216};\r
\r
STATIC EFI_GUID mZeroGuid = {0};\r
\r
+STATIC EFI_GUID mEfiFfsSectionAlignmentPaddingGuid = EFI_FFS_SECTION_ALIGNMENT_PADDING_GUID;\r
+\r
STATIC\r
VOID \r
Version (\r
\r
--*/ \r
{\r
- fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
+ fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
}\r
\r
STATIC\r
//\r
// Copyright declaration\r
// \r
- fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");\r
+ fprintf (stdout, "Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.\n\n");\r
\r
//\r
// Details Option\r
EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,\n\\r
EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION,\n\\r
EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\n\\r
+ EFI_FV_FILETYPE_SMM, EFI_FV_FILETYPE_SMM_CORE,\n\\r
+ EFI_FV_FILETYPE_MM_STANDALONE,\n\\r
+ EFI_FV_FILETYPE_MM_CORE_STANDALONE,\n\\r
+ EFI_FV_FILETYPE_COMBINED_SMM_DXE, \n\\r
EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n");\r
fprintf (stdout, " -g FileGuid, --fileguid FileGuid\n\\r
FileGuid is one module guid.\n\\r
fprintf (stdout, " -s, --checksum Indicates to calculate file checksum.\n");\r
fprintf (stdout, " -a FileAlign, --align FileAlign\n\\r
FileAlign points to file alignment, which only support\n\\r
- the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n");\r
+ the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n\\r
+ 128K,256K,512K,1M,2M,4M,8M,16M\n");\r
fprintf (stdout, " -i SectionFile, --sectionfile SectionFile\n\\r
Section file will be contained in this FFS file.\n");\r
fprintf (stdout, " -n SectionAlign, --sectionalign SectionAlign\n\\r
SectionAlign points to section alignment, which support\n\\r
- the alignment scope 1~64K. It is specified together\n\\r
- with sectionfile to point its alignment in FFS file.\n");\r
+ the alignment scope 0~16M. If SectionAlign is specified\n\\r
+ as 0, tool get alignment value from SectionFile. It is\n\\r
+ specified together with sectionfile to point its\n\\r
+ alignment in FFS file.\n");\r
fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");\r
fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");\r
fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");\r
\r
Routine Description:\r
\r
- Converts Align String to align value (1~64K). \r
+ Converts Align String to align value (1~16M).\r
\r
Arguments:\r
\r
STATIC\r
EFI_STATUS\r
GetSectionContents (\r
- IN CHAR8 **InputFileName,\r
- IN UINT32 *InputFileAlign,\r
- IN UINT32 InputFileNum,\r
- OUT UINT8 *FileBuffer,\r
- OUT UINT32 *BufferLength,\r
- OUT UINT32 *MaxAlignment,\r
- OUT UINT8 *PESectionNum\r
+ IN CHAR8 **InputFileName,\r
+ IN UINT32 *InputFileAlign,\r
+ IN UINT32 InputFileNum,\r
+ IN EFI_FFS_FILE_ATTRIBUTES FfsAttrib,\r
+ OUT UINT8 *FileBuffer,\r
+ OUT UINT32 *BufferLength,\r
+ OUT UINT32 *MaxAlignment,\r
+ OUT UINT8 *PESectionNum\r
)\r
/*++\r
\r
EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.\r
--*/\r
{\r
- UINT32 Size;\r
- UINT32 Offset;\r
- UINT32 FileSize;\r
- UINT32 Index;\r
- FILE *InFile;\r
- EFI_COMMON_SECTION_HEADER *SectHeader;\r
- EFI_COMMON_SECTION_HEADER TempSectHeader;\r
- EFI_TE_IMAGE_HEADER TeHeader;\r
- UINT32 TeOffset;\r
-\r
- Size = 0;\r
- Offset = 0;\r
- TeOffset = 0;\r
+ UINT32 Size;\r
+ UINT32 Offset;\r
+ UINT32 FileSize;\r
+ UINT32 Index;\r
+ FILE *InFile;\r
+ EFI_FREEFORM_SUBTYPE_GUID_SECTION *SectHeader;\r
+ EFI_COMMON_SECTION_HEADER2 TempSectHeader;\r
+ EFI_TE_IMAGE_HEADER TeHeader;\r
+ UINT32 TeOffset;\r
+ EFI_GUID_DEFINED_SECTION GuidSectHeader;\r
+ EFI_GUID_DEFINED_SECTION2 GuidSectHeader2;\r
+ UINT32 HeaderSize;\r
+ UINT32 MaxEncounteredAlignment;\r
+\r
+ Size = 0;\r
+ Offset = 0;\r
+ TeOffset = 0;\r
+ MaxEncounteredAlignment = 1;\r
\r
//\r
// Go through our array of file names and copy their contents\r
Size++;\r
}\r
\r
- //\r
- // Get the Max alignment of all input file datas\r
- //\r
- if (*MaxAlignment < InputFileAlign [Index]) {\r
- *MaxAlignment = InputFileAlign [Index];\r
- }\r
-\r
// \r
// Open file and read contents\r
//\r
- InFile = fopen (InputFileName[Index], "rb");\r
+ InFile = fopen (LongFilePath (InputFileName[Index]), "rb");\r
if (InFile == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);\r
return EFI_ABORTED;\r
FileSize = ftell (InFile);\r
fseek (InFile, 0, SEEK_SET);\r
DebugMsg (NULL, 0, 9, "Input section files", \r
- "the input section name is %s and the size is %d bytes", InputFileName[Index], FileSize); \r
+ "the input section name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize); \r
\r
//\r
// Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.\r
//\r
TeOffset = 0;\r
- fread (&TempSectHeader, 1, sizeof (TempSectHeader), InFile);\r
+ if (FileSize >= MAX_FFS_SIZE) {\r
+ HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2);\r
+ } else {\r
+ HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);\r
+ }\r
+ fread (&TempSectHeader, 1, HeaderSize, InFile);\r
if (TempSectHeader.Type == EFI_SECTION_TE) {\r
(*PESectionNum) ++;\r
fread (&TeHeader, 1, sizeof (TeHeader), InFile);\r
}\r
} else if (TempSectHeader.Type == EFI_SECTION_PE32) {\r
(*PESectionNum) ++;\r
+ } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) {\r
+ fseek (InFile, 0, SEEK_SET);\r
+ if (FileSize >= MAX_SECTION_SIZE) {\r
+ fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile);\r
+ if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
+ HeaderSize = GuidSectHeader2.DataOffset;\r
+ }\r
+ } else {\r
+ fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile);\r
+ if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) {\r
+ HeaderSize = GuidSectHeader.DataOffset;\r
+ }\r
+ }\r
+ (*PESectionNum) ++;\r
} else if (TempSectHeader.Type == EFI_SECTION_COMPRESSION || \r
- TempSectHeader.Type == EFI_SECTION_GUID_DEFINED ||\r
TempSectHeader.Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {\r
//\r
// for the encapsulated section, assume it contains Pe/Te section \r
TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);\r
TeOffset = TeOffset % InputFileAlign [Index];\r
}\r
- \r
+\r
//\r
- // make sure section data meet its alignment requirement by adding one raw pad section.\r
+ // make sure section data meet its alignment requirement by adding one pad section.\r
// But the different sections have the different section header. Necessary or not?\r
// Based on section type to adjust offset? Todo\r
//\r
- if ((InputFileAlign [Index] != 0) && (((Size + sizeof (EFI_COMMON_SECTION_HEADER) + TeOffset) % InputFileAlign [Index]) != 0)) {\r
- Offset = (Size + 2 * sizeof (EFI_COMMON_SECTION_HEADER) + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);\r
- Offset = Offset - Size - sizeof (EFI_COMMON_SECTION_HEADER) - TeOffset;\r
+ if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {\r
+ Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);\r
+ Offset = Offset - Size - HeaderSize - TeOffset;\r
\r
if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {\r
- SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);\r
- SectHeader->Type = EFI_SECTION_RAW;\r
- SectHeader->Size[0] = (UINT8) (Offset & 0xff);\r
- SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);\r
- SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);\r
+ //\r
+ // The maximal alignment is 64K, the raw section size must be less than 0xffffff\r
+ //\r
+ memset (FileBuffer + Size, 0, Offset);\r
+ SectHeader = (EFI_FREEFORM_SUBTYPE_GUID_SECTION *) (FileBuffer + Size);\r
+ SectHeader->CommonHeader.Size[0] = (UINT8) (Offset & 0xff);\r
+ SectHeader->CommonHeader.Size[1] = (UINT8) ((Offset & 0xff00) >> 8);\r
+ SectHeader->CommonHeader.Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);\r
+\r
+ //\r
+ // Only add a special reducible padding section if\r
+ // - this FFS has the FFS_ATTRIB_FIXED attribute,\r
+ // - none of the preceding sections have alignment requirements,\r
+ // - the size of the padding is sufficient for the\r
+ // EFI_SECTION_FREEFORM_SUBTYPE_GUID header.\r
+ //\r
+ if ((FfsAttrib & FFS_ATTRIB_FIXED) != 0 &&\r
+ MaxEncounteredAlignment <= 1 &&\r
+ Offset >= sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION)) {\r
+ SectHeader->CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID;\r
+ SectHeader->SubTypeGuid = mEfiFfsSectionAlignmentPaddingGuid;\r
+ } else {\r
+ SectHeader->CommonHeader.Type = EFI_SECTION_RAW;\r
+ }\r
}\r
DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", \r
- "Pad Raw section size is %d", Offset);\r
+ "Pad Raw section size is %u", (unsigned) Offset);\r
\r
Size = Size + Offset;\r
}\r
\r
+ //\r
+ // Get the Max alignment of all input file datas\r
+ //\r
+ if (MaxEncounteredAlignment < InputFileAlign [Index]) {\r
+ MaxEncounteredAlignment = InputFileAlign [Index];\r
+ }\r
+\r
//\r
// Now read the contents of the file into the buffer\r
// Buffer must be enough to contain the file content.\r
fclose (InFile);\r
Size += FileSize;\r
}\r
- \r
+\r
+ *MaxAlignment = MaxEncounteredAlignment;\r
+\r
//\r
// Set the actual length of the data.\r
//\r
}\r
}\r
\r
+EFI_STATUS\r
+FfsRebaseImageRead (\r
+ IN VOID *FileHandle,\r
+ IN UINTN FileOffset,\r
+ IN OUT UINT32 *ReadSize,\r
+ OUT VOID *Buffer\r
+ )\r
+ /*++\r
+\r
+ Routine Description:\r
+\r
+ Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file\r
+\r
+ Arguments:\r
+\r
+ FileHandle - The handle to the PE/COFF file\r
+\r
+ FileOffset - The offset, in bytes, into the file to read\r
+\r
+ ReadSize - The number of bytes to read from the file starting at FileOffset\r
+\r
+ Buffer - A pointer to the buffer to read the data into.\r
+\r
+ Returns:\r
+\r
+ EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset\r
+\r
+ --*/\r
+{\r
+ CHAR8 *Destination8;\r
+ CHAR8 *Source8;\r
+ UINT32 Length;\r
+\r
+ Destination8 = Buffer;\r
+ Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset);\r
+ Length = *ReadSize;\r
+ while (Length--) {\r
+ *(Destination8++) = *(Source8++);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+GetAlignmentFromFile(char *InFile, UINT32 *Alignment)\r
+ /*++\r
+ InFile is input file for getting alignment\r
+ return the alignment\r
+ --*/\r
+{\r
+ FILE *InFileHandle;\r
+ UINT8 *PeFileBuffer;\r
+ UINTN PeFileSize;\r
+ UINT32 CurSecHdrSize;\r
+ PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;\r
+ EFI_COMMON_SECTION_HEADER *CommonHeader;\r
+ EFI_STATUS Status;\r
+\r
+ InFileHandle = NULL;\r
+ PeFileBuffer = NULL;\r
+ *Alignment = 0;\r
+\r
+ memset (&ImageContext, 0, sizeof (ImageContext));\r
+\r
+ InFileHandle = fopen(LongFilePath(InFile), "rb");\r
+ if (InFileHandle == NULL){\r
+ Error (NULL, 0, 0001, "Error opening file", InFile);\r
+ return EFI_ABORTED;\r
+ }\r
+ PeFileSize = _filelength (fileno(InFileHandle));\r
+ PeFileBuffer = (UINT8 *) malloc (PeFileSize);\r
+ if (PeFileBuffer == NULL) {\r
+ fclose (InFileHandle);\r
+ Error(NULL, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle);\r
+ fclose (InFileHandle);\r
+ CommonHeader = (EFI_COMMON_SECTION_HEADER *) PeFileBuffer;\r
+ CurSecHdrSize = GetSectionHeaderLength(CommonHeader);\r
+ ImageContext.Handle = (VOID *) ((UINTN)PeFileBuffer + CurSecHdrSize);\r
+ ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)FfsRebaseImageRead;\r
+ Status = PeCoffLoaderGetImageInfo(&ImageContext);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile, (int) Status);\r
+ return Status;\r
+ }\r
+ *Alignment = ImageContext.SectionAlignment;\r
+ // Free the allocated memory resource\r
+ if (PeFileBuffer != NULL) {\r
+ free (PeFileBuffer);\r
+ PeFileBuffer = NULL;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
int\r
main (\r
- INT32 argc,\r
+ int argc,\r
CHAR8 *argv[]\r
)\r
/*++\r
UINT8 *FileBuffer;\r
UINT32 FileSize;\r
UINT32 MaxAlignment;\r
- EFI_FFS_FILE_HEADER FfsFileHeader;\r
+ EFI_FFS_FILE_HEADER2 FfsFileHeader;\r
FILE *FfsFile;\r
UINT32 Index;\r
UINT64 LogLevel;\r
UINT8 PeSectionNum;\r
+ UINT32 HeaderSize;\r
+ UINT32 Alignment;\r
+ //\r
+ // Workaround for static code checkers.\r
+ // Ensures the size of 'AlignmentBuffer' can hold all the digits of an\r
+ // unsigned 32-bit integer plus the size unit character.\r
+ //\r
+ CHAR8 AlignmentBuffer[16];\r
\r
//\r
// Init local variables\r
// Section File alignment requirement\r
//\r
if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) {\r
- Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileNum]));\r
+ if ((argv[1] != NULL) && (stricmp("0", argv[1]) == 0)) {\r
+ Status = GetAlignmentFromFile(InputFileName[InputFileNum], &Alignment);\r
+ if (EFI_ERROR(Status)) {\r
+ Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]);\r
+ goto Finish;\r
+ }\r
+ if (Alignment < 0x400){\r
+ sprintf (AlignmentBuffer, "%d", Alignment);\r
+ }\r
+ else if (Alignment >= 0x400) {\r
+ if (Alignment >= 0x100000) {\r
+ sprintf (AlignmentBuffer, "%dM", Alignment/0x100000);\r
+ } else {\r
+ sprintf (AlignmentBuffer, "%dK", Alignment/0x400);\r
+ }\r
+ }\r
+ Status = StringtoAlignment (AlignmentBuffer, &(InputFileAlign[InputFileNum]));\r
+ }\r
+ else {\r
+ Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileNum]));\r
+ }\r
if (EFI_ERROR (Status)) {\r
Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);\r
goto Finish;\r
goto Finish;\r
}\r
if (LogLevel > 9) {\r
- Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", LogLevel);\r
+ Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);\r
goto Finish;\r
}\r
SetPrintLevel (LogLevel);\r
continue;\r
}\r
\r
- Error (NULL, 0, 1000, "Unknown option", argv[0]);\r
+ Error (NULL, 0, 1000, "Unknown option", "%s", argv[0]);\r
goto Finish;\r
}\r
\r
VerboseMsg ("%s tool start.", UTILITY_NAME);\r
\r
//\r
- // Check the complete input paramters.\r
+ // Check the complete input parameters.\r
//\r
if (FfsFiletype == EFI_FV_FILETYPE_ALL) {\r
Error (NULL, 0, 1001, "Missing option", "filetype");\r
VerboseMsg ("Fv File type is %s", mFfsFileType [FfsFiletype]);\r
VerboseMsg ("Output file name is %s", OutputFileName);\r
VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", \r
- FileGuid.Data1,\r
+ (unsigned) FileGuid.Data1,\r
FileGuid.Data2,\r
FileGuid.Data3,\r
FileGuid.Data4[0],\r
//\r
InputFileAlign[Index] = 1;\r
}\r
- VerboseMsg ("the %dth input section name is %s and section alignment is %d", Index, InputFileName[Index], InputFileAlign[Index]);\r
+ VerboseMsg ("the %dth input section name is %s and section alignment is %u", Index, InputFileName[Index], (unsigned) InputFileAlign[Index]);\r
}\r
\r
//\r
InputFileName,\r
InputFileAlign,\r
InputFileNum,\r
+ FfsAttrib,\r
FileBuffer,\r
&FileSize,\r
&MaxAlignment,\r
if ((FfsFiletype == EFI_FV_FILETYPE_SECURITY_CORE || \r
FfsFiletype == EFI_FV_FILETYPE_PEI_CORE ||\r
FfsFiletype == EFI_FV_FILETYPE_DXE_CORE) && (PeSectionNum != 1)) {\r
- Error (NULL, 0, 2000, "Invalid parameter", "Fv File type %s must have one and only one Pe or Te section, but %d Pe/Te section are input", mFfsFileType [FfsFiletype], PeSectionNum);\r
+ 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);\r
goto Finish;\r
}\r
\r
InputFileName,\r
InputFileAlign,\r
InputFileNum,\r
+ FfsAttrib,\r
FileBuffer,\r
&FileSize,\r
&MaxAlignment,\r
if (EFI_ERROR (Status)) {\r
goto Finish;\r
}\r
+\r
+ if (FileBuffer == NULL && FileSize != 0) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");\r
+ goto Finish;\r
+ }\r
\r
//\r
// Create Ffs file header.\r
//\r
- memset (&FfsFileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));\r
+ memset (&FfsFileHeader, 0, sizeof (EFI_FFS_FILE_HEADER2));\r
memcpy (&FfsFileHeader.Name, &FileGuid, sizeof (EFI_GUID));\r
FfsFileHeader.Type = FfsFiletype;\r
//\r
// Update FFS Alignment based on the max alignment required by input section files \r
//\r
- VerboseMsg ("the max alignment of all input sections is %d", MaxAlignment); \r
+ VerboseMsg ("the max alignment of all input sections is %u", (unsigned) MaxAlignment); \r
for (Index = 0; Index < sizeof (mFfsValidAlign) / sizeof (UINT32) - 1; Index ++) {\r
if ((MaxAlignment > mFfsValidAlign [Index]) && (MaxAlignment <= mFfsValidAlign [Index + 1])) {\r
break;\r
if (FfsAlign < Index) {\r
FfsAlign = Index;\r
}\r
- VerboseMsg ("the alignment of the genreated FFS file is %d", mFfsValidAlign [FfsAlign + 1]); \r
- FfsFileHeader.Attributes = FfsAttrib | (FfsAlign << 3);\r
+ VerboseMsg ("the alignment of the generated FFS file is %u", (unsigned) mFfsValidAlign [FfsAlign + 1]); \r
\r
//\r
// Now FileSize includes the EFI_FFS_FILE_HEADER\r
//\r
- FileSize += sizeof (EFI_FFS_FILE_HEADER);\r
- VerboseMsg ("the size of the genreated FFS file is %d bytes", FileSize);\r
- FfsFileHeader.Size[0] = (UINT8) (FileSize & 0xFF);\r
- FfsFileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);\r
- FfsFileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);\r
+ if (FileSize + sizeof (EFI_FFS_FILE_HEADER) >= MAX_FFS_SIZE) {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER2);\r
+ FileSize += sizeof (EFI_FFS_FILE_HEADER2);\r
+ FfsFileHeader.ExtendedSize = FileSize;\r
+ memset(FfsFileHeader.Size, 0, sizeof (UINT8) * 3);\r
+ FfsAttrib |= FFS_ATTRIB_LARGE_FILE;\r
+ } else {\r
+ HeaderSize = sizeof (EFI_FFS_FILE_HEADER);\r
+ FileSize += sizeof (EFI_FFS_FILE_HEADER);\r
+ FfsFileHeader.Size[0] = (UINT8) (FileSize & 0xFF);\r
+ FfsFileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);\r
+ FfsFileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);\r
+ }\r
+ VerboseMsg ("the size of the generated FFS file is %u bytes", (unsigned) FileSize);\r
+\r
+ //FfsAlign larger than 7, set FFS_ATTRIB_DATA_ALIGNMENT2\r
+ if (FfsAlign < 8) {\r
+ FfsFileHeader.Attributes = (EFI_FFS_FILE_ATTRIBUTES) (FfsAttrib | (FfsAlign << 3));\r
+ } else {\r
+ FfsFileHeader.Attributes = (EFI_FFS_FILE_ATTRIBUTES) (FfsAttrib | ((FfsAlign & 0x7) << 3) | FFS_ATTRIB_DATA_ALIGNMENT2);\r
+ }\r
+\r
//\r
// Fill in checksums and state, these must be zero for checksumming\r
//\r
//\r
FfsFileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (\r
(UINT8 *) &FfsFileHeader,\r
- sizeof (EFI_FFS_FILE_HEADER)\r
+ HeaderSize\r
);\r
\r
if (FfsFileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {\r
//\r
FfsFileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (\r
FileBuffer, \r
- FileSize - sizeof (EFI_FFS_FILE_HEADER)\r
+ FileSize - HeaderSize\r
); \r
} else {\r
FfsFileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;\r
//\r
// Open output file to write ffs data.\r
//\r
- remove(OutputFileName);\r
- FfsFile = fopen (OutputFileName, "wb");\r
- if (FfsFile == NULL) {\r
- Error (NULL, 0, 0001, "Error opening file", OutputFileName);\r
- goto Finish;\r
- }\r
- //\r
- // write header\r
- //\r
- fwrite (&FfsFileHeader, 1, sizeof (FfsFileHeader), FfsFile);\r
- //\r
- // write data\r
- //\r
- fwrite (FileBuffer, 1, FileSize - sizeof (EFI_FFS_FILE_HEADER), FfsFile);\r
+ if (OutputFileName != NULL) {\r
+ remove(OutputFileName);\r
+ FfsFile = fopen (LongFilePath (OutputFileName), "wb");\r
+ if (FfsFile == NULL) {\r
+ Error (NULL, 0, 0001, "Error opening file", OutputFileName);\r
+ goto Finish;\r
+ }\r
+ //\r
+ // write header\r
+ //\r
+ fwrite (&FfsFileHeader, 1, HeaderSize, FfsFile);\r
+ //\r
+ // write data\r
+ //\r
+ if (FileBuffer != NULL) {\r
+ fwrite (FileBuffer, 1, FileSize - HeaderSize, FfsFile);\r
+ }\r
\r
- fclose (FfsFile);\r
+ fclose (FfsFile);\r
+ }\r
\r
Finish:\r
if (InputFileName != NULL) {\r