Check In tool source code based on Build tool project revision r1655.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8964 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
897
BaseTools/Source/C/GenFfs/GenFfs.c
Normal file
897
BaseTools/Source/C/GenFfs/GenFfs.c
Normal file
@@ -0,0 +1,897 @@
|
||||
/**
|
||||
|
||||
Copyright (c) 2004-2008, Intel Corporation
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
Module Name:
|
||||
|
||||
GenFfs.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains functions required to generate a Firmware File System
|
||||
file.
|
||||
|
||||
**/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <Common/UefiBaseTypes.h>
|
||||
#include <Common/PiFirmwareFile.h>
|
||||
#include <IndustryStandard/PeImage.h>
|
||||
|
||||
#include "CommonLib.h"
|
||||
#include "ParseInf.h"
|
||||
#include "EfiUtilityMsgs.h"
|
||||
|
||||
#define UTILITY_NAME "GenFfs"
|
||||
#define UTILITY_MAJOR_VERSION 0
|
||||
#define UTILITY_MINOR_VERSION 1
|
||||
|
||||
STATIC CHAR8 *mFfsFileType[] = {
|
||||
NULL, // 0x00
|
||||
"EFI_FV_FILETYPE_RAW", // 0x01
|
||||
"EFI_FV_FILETYPE_FREEFORM", // 0x02
|
||||
"EFI_FV_FILETYPE_SECURITY_CORE", // 0x03
|
||||
"EFI_FV_FILETYPE_PEI_CORE", // 0x04
|
||||
"EFI_FV_FILETYPE_DXE_CORE", // 0x05
|
||||
"EFI_FV_FILETYPE_PEIM", // 0x06
|
||||
"EFI_FV_FILETYPE_DRIVER", // 0x07
|
||||
"EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER", // 0x08
|
||||
"EFI_FV_FILETYPE_APPLICATION", // 0x09
|
||||
"EFI_FV_FILETYPE_SMM", // 0x0A
|
||||
"EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B
|
||||
"EFI_FV_FILETYPE_COMBINED_SMM_DXE", // 0x0C
|
||||
"EFI_FV_FILETYPE_SMM_CORE" // 0x0D
|
||||
};
|
||||
|
||||
STATIC CHAR8 *mAlignName[] = {
|
||||
"1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
|
||||
"1K", "2K", "4K", "8K", "16K", "32K", "64K"
|
||||
};
|
||||
|
||||
STATIC CHAR8 *mFfsValidAlignName[] = {
|
||||
"8", "16", "128", "512", "1K", "4K", "32K", "64K"
|
||||
};
|
||||
|
||||
STATIC UINT32 mFfsValidAlign[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536};
|
||||
|
||||
STATIC EFI_GUID mZeroGuid = {0};
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
Version (
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Print out version information for this utility.
|
||||
|
||||
Arguments:
|
||||
|
||||
None
|
||||
|
||||
Returns:
|
||||
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
|
||||
}
|
||||
|
||||
STATIC
|
||||
VOID
|
||||
Usage (
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Print Error / Help message.
|
||||
|
||||
Arguments:
|
||||
|
||||
VOID
|
||||
|
||||
Returns:
|
||||
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Summary usage
|
||||
//
|
||||
fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME);
|
||||
|
||||
//
|
||||
// Copyright declaration
|
||||
//
|
||||
fprintf (stdout, "Copyright (c) 2007, Intel Corporation. All rights reserved.\n\n");
|
||||
|
||||
//
|
||||
// Details Option
|
||||
//
|
||||
fprintf (stdout, "Options:\n");
|
||||
fprintf (stdout, " -o FileName, --outputfile FileName\n\
|
||||
File is FFS file to be created.\n");
|
||||
fprintf (stdout, " -t Type, --filetype Type\n\
|
||||
Type is one FV file type defined in PI spec, which is\n\
|
||||
EFI_FV_FILETYPE_RAW, EFI_FV_FILETYPE_FREEFORM,\n\
|
||||
EFI_FV_FILETYPE_SECURITY_CORE, EFI_FV_FILETYPE_PEIM,\n\
|
||||
EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,\n\
|
||||
EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION,\n\
|
||||
EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\n\
|
||||
EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n");
|
||||
fprintf (stdout, " -g FileGuid, --fileguid FileGuid\n\
|
||||
FileGuid is one module guid.\n\
|
||||
Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
|
||||
fprintf (stdout, " -x, --fixed Indicates that the file may not be moved\n\
|
||||
from its present location.\n");
|
||||
fprintf (stdout, " -s, --checksum Indicates to calculate file checksum.\n");
|
||||
fprintf (stdout, " -a FileAlign, --align FileAlign\n\
|
||||
FileAlign points to file alignment, which only support\n\
|
||||
the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n");
|
||||
fprintf (stdout, " -i SectionFile, --sectionfile SectionFile\n\
|
||||
Section file will be contained in this FFS file.\n");
|
||||
fprintf (stdout, " -n SectionAlign, --sectionalign SectionAlign\n\
|
||||
SectionAlign points to section alignment, which support\n\
|
||||
the alignment scope 1~64K. It is specified together\n\
|
||||
with sectionfile to point its alignment in FFS file.\n");
|
||||
fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n");
|
||||
fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n");
|
||||
fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n");
|
||||
fprintf (stdout, " --version Show program's version number and exit.\n");
|
||||
fprintf (stdout, " -h, --help Show this help message and exit.\n");
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
StringtoAlignment (
|
||||
IN CHAR8 *AlignBuffer,
|
||||
OUT UINT32 *AlignNumber
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Converts Align String to align value (1~64K).
|
||||
|
||||
Arguments:
|
||||
|
||||
AlignBuffer - Pointer to Align string.
|
||||
AlignNumber - Pointer to Align value.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS Successfully convert align string to align value.
|
||||
EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope.
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT32 Index = 0;
|
||||
//
|
||||
// Check AlignBuffer
|
||||
//
|
||||
if (AlignBuffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) {
|
||||
if (stricmp (AlignBuffer, mAlignName [Index]) == 0) {
|
||||
*AlignNumber = 1 << Index;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
STATIC
|
||||
UINT8
|
||||
StringToType (
|
||||
IN CHAR8 *String
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an
|
||||
unrecognized file type was specified.
|
||||
|
||||
Arguments:
|
||||
|
||||
String - File type string
|
||||
|
||||
Returns:
|
||||
|
||||
File Type Value
|
||||
|
||||
--*/
|
||||
{
|
||||
UINT8 Index = 0;
|
||||
|
||||
if (String == NULL) {
|
||||
return EFI_FV_FILETYPE_ALL;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < sizeof (mFfsFileType) / sizeof (CHAR8 *); Index ++) {
|
||||
if (mFfsFileType [Index] != NULL && (stricmp (String, mFfsFileType [Index]) == 0)) {
|
||||
return Index;
|
||||
}
|
||||
}
|
||||
return EFI_FV_FILETYPE_ALL;
|
||||
}
|
||||
|
||||
STATIC
|
||||
EFI_STATUS
|
||||
GetSectionContents (
|
||||
IN CHAR8 **InputFileName,
|
||||
IN UINT32 *InputFileAlign,
|
||||
IN UINT32 InputFileNum,
|
||||
OUT UINT8 *FileBuffer,
|
||||
OUT UINT32 *BufferLength,
|
||||
OUT UINT32 *MaxAlignment,
|
||||
OUT UINT8 *PESectionNum
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Get the contents of all section files specified in InputFileName
|
||||
into FileBuffer.
|
||||
|
||||
Arguments:
|
||||
|
||||
InputFileName - Name of the input file.
|
||||
|
||||
InputFileAlign - Alignment required by the input file data.
|
||||
|
||||
InputFileNum - Number of input files. Should be at least 1.
|
||||
|
||||
FileBuffer - Output buffer to contain data
|
||||
|
||||
BufferLength - On input, this is size of the FileBuffer.
|
||||
On output, this is the actual length of the data.
|
||||
|
||||
MaxAlignment - The max alignment required by all the input file datas.
|
||||
|
||||
PeSectionNum - Calculate the number of Pe/Te Section in this FFS file.
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS on successful return
|
||||
EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL.
|
||||
EFI_ABORTED if unable to open input file.
|
||||
EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data.
|
||||
--*/
|
||||
{
|
||||
UINT32 Size;
|
||||
UINT32 Offset;
|
||||
UINT32 FileSize;
|
||||
UINT32 Index;
|
||||
FILE *InFile;
|
||||
EFI_COMMON_SECTION_HEADER *SectHeader;
|
||||
EFI_COMMON_SECTION_HEADER TempSectHeader;
|
||||
EFI_TE_IMAGE_HEADER TeHeader;
|
||||
UINT32 TeOffset;
|
||||
|
||||
Size = 0;
|
||||
Offset = 0;
|
||||
TeOffset = 0;
|
||||
|
||||
//
|
||||
// Go through our array of file names and copy their contents
|
||||
// to the output buffer.
|
||||
//
|
||||
for (Index = 0; Index < InputFileNum; Index++) {
|
||||
//
|
||||
// make sure section ends on a DWORD boundary
|
||||
//
|
||||
while ((Size & 0x03) != 0) {
|
||||
Size++;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the Max alignment of all input file datas
|
||||
//
|
||||
if (*MaxAlignment < InputFileAlign [Index]) {
|
||||
*MaxAlignment = InputFileAlign [Index];
|
||||
}
|
||||
|
||||
//
|
||||
// Open file and read contents
|
||||
//
|
||||
InFile = fopen (InputFileName[Index], "rb");
|
||||
if (InFile == NULL) {
|
||||
Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
fseek (InFile, 0, SEEK_END);
|
||||
FileSize = ftell (InFile);
|
||||
fseek (InFile, 0, SEEK_SET);
|
||||
DebugMsg (NULL, 0, 9, "Input section files",
|
||||
"the input section name is %s and the size is %d bytes", InputFileName[Index], FileSize);
|
||||
|
||||
//
|
||||
// Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section.
|
||||
//
|
||||
TeOffset = 0;
|
||||
fread (&TempSectHeader, 1, sizeof (TempSectHeader), InFile);
|
||||
if (TempSectHeader.Type == EFI_SECTION_TE) {
|
||||
(*PESectionNum) ++;
|
||||
fread (&TeHeader, 1, sizeof (TeHeader), InFile);
|
||||
if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
|
||||
TeOffset = TeHeader.StrippedSize - sizeof (TeHeader);
|
||||
}
|
||||
} else if (TempSectHeader.Type == EFI_SECTION_PE32) {
|
||||
(*PESectionNum) ++;
|
||||
} else if (TempSectHeader.Type == EFI_SECTION_COMPRESSION ||
|
||||
TempSectHeader.Type == EFI_SECTION_GUID_DEFINED ||
|
||||
TempSectHeader.Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) {
|
||||
//
|
||||
// for the encapsulated section, assume it contains Pe/Te section
|
||||
//
|
||||
(*PESectionNum) ++;
|
||||
}
|
||||
|
||||
fseek (InFile, 0, SEEK_SET);
|
||||
|
||||
//
|
||||
// Revert TeOffset to the converse value relative to Alignment
|
||||
// This is to assure the original PeImage Header at Alignment.
|
||||
//
|
||||
if ((TeOffset != 0) && (InputFileAlign [Index] != 0)) {
|
||||
TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]);
|
||||
TeOffset = TeOffset % InputFileAlign [Index];
|
||||
}
|
||||
|
||||
//
|
||||
// make sure section data meet its alignment requirement by adding one raw pad section.
|
||||
// But the different sections have the different section header. Necessary or not?
|
||||
// Based on section type to adjust offset? Todo
|
||||
//
|
||||
if ((InputFileAlign [Index] != 0) && (((Size + sizeof (EFI_COMMON_SECTION_HEADER) + TeOffset) % InputFileAlign [Index]) != 0)) {
|
||||
Offset = (Size + 2 * sizeof (EFI_COMMON_SECTION_HEADER) + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);
|
||||
Offset = Offset - Size - sizeof (EFI_COMMON_SECTION_HEADER) - TeOffset;
|
||||
|
||||
if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) {
|
||||
SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size);
|
||||
SectHeader->Type = EFI_SECTION_RAW;
|
||||
SectHeader->Size[0] = (UINT8) (Offset & 0xff);
|
||||
SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8);
|
||||
SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16);
|
||||
}
|
||||
DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment",
|
||||
"Pad Raw section size is %d", Offset);
|
||||
|
||||
Size = Size + Offset;
|
||||
}
|
||||
|
||||
//
|
||||
// Now read the contents of the file into the buffer
|
||||
// Buffer must be enough to contain the file content.
|
||||
//
|
||||
if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) {
|
||||
if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
|
||||
Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]);
|
||||
fclose (InFile);
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
fclose (InFile);
|
||||
Size += FileSize;
|
||||
}
|
||||
|
||||
//
|
||||
// Set the actual length of the data.
|
||||
//
|
||||
if (Size > *BufferLength) {
|
||||
*BufferLength = Size;
|
||||
return EFI_BUFFER_TOO_SMALL;
|
||||
} else {
|
||||
*BufferLength = Size;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (
|
||||
INT32 argc,
|
||||
CHAR8 *argv[]
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Main function.
|
||||
|
||||
Arguments:
|
||||
|
||||
argc - Number of command line parameters.
|
||||
argv - Array of pointers to parameter strings.
|
||||
|
||||
Returns:
|
||||
STATUS_SUCCESS - Utility exits successfully.
|
||||
STATUS_ERROR - Some error occurred during execution.
|
||||
|
||||
--*/
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_FFS_FILE_ATTRIBUTES FfsAttrib;
|
||||
UINT32 FfsAlign;
|
||||
EFI_FV_FILETYPE FfsFiletype;
|
||||
CHAR8 *OutputFileName;
|
||||
EFI_GUID FileGuid = {0};
|
||||
UINT32 InputFileNum;
|
||||
UINT32 *InputFileAlign;
|
||||
CHAR8 **InputFileName;
|
||||
UINT8 *FileBuffer;
|
||||
UINT32 FileSize;
|
||||
UINT32 MaxAlignment;
|
||||
EFI_FFS_FILE_HEADER FfsFileHeader;
|
||||
FILE *FfsFile;
|
||||
UINT32 Index;
|
||||
UINT64 LogLevel;
|
||||
UINT8 PeSectionNum;
|
||||
|
||||
//
|
||||
// Init local variables
|
||||
//
|
||||
LogLevel = 0;
|
||||
Index = 0;
|
||||
FfsAttrib = 0;
|
||||
FfsAlign = 0;
|
||||
FfsFiletype = EFI_FV_FILETYPE_ALL;
|
||||
OutputFileName = NULL;
|
||||
InputFileNum = 0;
|
||||
InputFileName = NULL;
|
||||
InputFileAlign = NULL;
|
||||
FileBuffer = NULL;
|
||||
FileSize = 0;
|
||||
MaxAlignment = 1;
|
||||
FfsFile = NULL;
|
||||
Status = EFI_SUCCESS;
|
||||
PeSectionNum = 0;
|
||||
|
||||
SetUtilityName (UTILITY_NAME);
|
||||
|
||||
if (argc == 1) {
|
||||
Error (NULL, 0, 1001, "Missing options", "no options input");
|
||||
Usage ();
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
//
|
||||
// Parse command line
|
||||
//
|
||||
argc --;
|
||||
argv ++;
|
||||
|
||||
if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) {
|
||||
Version ();
|
||||
Usage ();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (stricmp (argv[0], "--version") == 0) {
|
||||
Version ();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
while (argc > 0) {
|
||||
if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--filetype") == 0)) {
|
||||
if (argv[1] == NULL || argv[1][0] == '-') {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "file type is missing for -t option");
|
||||
goto Finish;
|
||||
}
|
||||
FfsFiletype = StringToType (argv[1]);
|
||||
if (FfsFiletype == EFI_FV_FILETYPE_ALL) {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "%s is not a valid file type", argv[1]);
|
||||
goto Finish;
|
||||
}
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) {
|
||||
if (argv[1] == NULL || argv[1][0] == '-') {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option");
|
||||
goto Finish;
|
||||
}
|
||||
OutputFileName = argv[1];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--fileguid") == 0)) {
|
||||
Status = StringToGuid (argv[1], &FileGuid);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
|
||||
goto Finish;
|
||||
}
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-x") == 0) || (stricmp (argv[0], "--fixed") == 0)) {
|
||||
FfsAttrib |= FFS_ATTRIB_FIXED;
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--checksum") == 0)) {
|
||||
FfsAttrib |= FFS_ATTRIB_CHECKSUM;
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) {
|
||||
if (argv[1] == NULL || argv[1][0] == '-') {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "Align value is missing for -a option");
|
||||
goto Finish;
|
||||
}
|
||||
for (Index = 0; Index < sizeof (mFfsValidAlignName) / sizeof (CHAR8 *); Index ++) {
|
||||
if (stricmp (argv[1], mFfsValidAlignName[Index]) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Index == sizeof (mFfsValidAlignName) / sizeof (CHAR8 *)) {
|
||||
if ((stricmp (argv[1], "1") == 0) || (stricmp (argv[1], "2") == 0) || (stricmp (argv[1], "4") == 0)) {
|
||||
//
|
||||
// 1, 2, 4 byte alignment same to 8 byte alignment
|
||||
//
|
||||
Index = 0;
|
||||
} else {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
|
||||
goto Finish;
|
||||
}
|
||||
}
|
||||
FfsAlign = Index;
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--sectionfile") == 0)) {
|
||||
//
|
||||
// Get Input file name and its alignment
|
||||
//
|
||||
if (argv[1] == NULL || argv[1][0] == '-') {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "input section file is missing for -i option");
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate Input file name buffer and its alignment buffer.
|
||||
//
|
||||
if ((InputFileNum == 0) && (InputFileName == NULL)) {
|
||||
InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *));
|
||||
if (InputFileName == NULL) {
|
||||
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
|
||||
|
||||
InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
|
||||
if (InputFileAlign == NULL) {
|
||||
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
|
||||
free (InputFileName);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
memset (InputFileAlign, 0, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32));
|
||||
} else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
|
||||
//
|
||||
// InputFileName and alignment buffer too small, need to realloc
|
||||
//
|
||||
InputFileName = (CHAR8 **) realloc (
|
||||
InputFileName,
|
||||
(InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *)
|
||||
);
|
||||
|
||||
if (InputFileName == NULL) {
|
||||
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
|
||||
free (InputFileAlign);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)));
|
||||
|
||||
InputFileAlign = (UINT32 *) realloc (
|
||||
InputFileAlign,
|
||||
(InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32)
|
||||
);
|
||||
|
||||
if (InputFileAlign == NULL) {
|
||||
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
|
||||
free (InputFileName);
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
memset (&(InputFileAlign[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)));
|
||||
}
|
||||
|
||||
InputFileName[InputFileNum] = argv[1];
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
|
||||
if (argc <= 0) {
|
||||
InputFileNum ++;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Section File alignment requirement
|
||||
//
|
||||
if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) {
|
||||
Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileNum]));
|
||||
if (EFI_ERROR (Status)) {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
|
||||
goto Finish;
|
||||
}
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
}
|
||||
InputFileNum ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) {
|
||||
Error (NULL, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file.");
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) {
|
||||
SetPrintLevel (VERBOSE_LOG_LEVEL);
|
||||
VerboseMsg ("Verbose output Mode Set!");
|
||||
argc --;
|
||||
argv ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
|
||||
SetPrintLevel (KEY_LOG_LEVEL);
|
||||
KeyMsg ("Quiet output Mode Set!");
|
||||
argc --;
|
||||
argv ++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) {
|
||||
Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]);
|
||||
goto Finish;
|
||||
}
|
||||
if (LogLevel > 9) {
|
||||
Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", LogLevel);
|
||||
goto Finish;
|
||||
}
|
||||
SetPrintLevel (LogLevel);
|
||||
DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]);
|
||||
argc -= 2;
|
||||
argv += 2;
|
||||
continue;
|
||||
}
|
||||
|
||||
Error (NULL, 0, 1000, "Unknown option", argv[0]);
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
VerboseMsg ("%s tool start.", UTILITY_NAME);
|
||||
|
||||
//
|
||||
// Check the complete input paramters.
|
||||
//
|
||||
if (FfsFiletype == EFI_FV_FILETYPE_ALL) {
|
||||
Error (NULL, 0, 1001, "Missing option", "filetype");
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
if (CompareGuid (&FileGuid, &mZeroGuid) == 0) {
|
||||
Error (NULL, 0, 1001, "Missing option", "fileguid");
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
if (InputFileNum == 0) {
|
||||
Error (NULL, 0, 1001, "Missing option", "Input files");
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
//
|
||||
// Output input parameter information
|
||||
//
|
||||
VerboseMsg ("Fv File type is %s", mFfsFileType [FfsFiletype]);
|
||||
VerboseMsg ("Output file name is %s", OutputFileName);
|
||||
VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||||
FileGuid.Data1,
|
||||
FileGuid.Data2,
|
||||
FileGuid.Data3,
|
||||
FileGuid.Data4[0],
|
||||
FileGuid.Data4[1],
|
||||
FileGuid.Data4[2],
|
||||
FileGuid.Data4[3],
|
||||
FileGuid.Data4[4],
|
||||
FileGuid.Data4[5],
|
||||
FileGuid.Data4[6],
|
||||
FileGuid.Data4[7]);
|
||||
if ((FfsAttrib & FFS_ATTRIB_FIXED) != 0) {
|
||||
VerboseMsg ("FFS File has the fixed file attribute");
|
||||
}
|
||||
if ((FfsAttrib & FFS_ATTRIB_CHECKSUM) != 0) {
|
||||
VerboseMsg ("FFS File requires the checksum of the whole file");
|
||||
}
|
||||
VerboseMsg ("FFS file alignment is %s", mFfsValidAlignName[FfsAlign]);
|
||||
for (Index = 0; Index < InputFileNum; Index ++) {
|
||||
if (InputFileAlign[Index] == 0) {
|
||||
//
|
||||
// Minimum alignment is 1 byte.
|
||||
//
|
||||
InputFileAlign[Index] = 1;
|
||||
}
|
||||
VerboseMsg ("the %dth input section name is %s and section alignment is %d", Index, InputFileName[Index], InputFileAlign[Index]);
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate the size of all input section files.
|
||||
//
|
||||
Status = GetSectionContents (
|
||||
InputFileName,
|
||||
InputFileAlign,
|
||||
InputFileNum,
|
||||
FileBuffer,
|
||||
&FileSize,
|
||||
&MaxAlignment,
|
||||
&PeSectionNum
|
||||
);
|
||||
|
||||
if ((FfsFiletype == EFI_FV_FILETYPE_SECURITY_CORE ||
|
||||
FfsFiletype == EFI_FV_FILETYPE_PEI_CORE ||
|
||||
FfsFiletype == EFI_FV_FILETYPE_DXE_CORE) && (PeSectionNum != 1)) {
|
||||
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);
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
if ((FfsFiletype == EFI_FV_FILETYPE_PEIM ||
|
||||
FfsFiletype == EFI_FV_FILETYPE_DRIVER ||
|
||||
FfsFiletype == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER ||
|
||||
FfsFiletype == EFI_FV_FILETYPE_APPLICATION) && (PeSectionNum < 1)) {
|
||||
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]);
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
FileBuffer = (UINT8 *) malloc (FileSize);
|
||||
if (FileBuffer == NULL) {
|
||||
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
|
||||
goto Finish;
|
||||
}
|
||||
memset (FileBuffer, 0, FileSize);
|
||||
|
||||
//
|
||||
// read all input file contents into a buffer
|
||||
//
|
||||
Status = GetSectionContents (
|
||||
InputFileName,
|
||||
InputFileAlign,
|
||||
InputFileNum,
|
||||
FileBuffer,
|
||||
&FileSize,
|
||||
&MaxAlignment,
|
||||
&PeSectionNum
|
||||
);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Finish;
|
||||
}
|
||||
|
||||
//
|
||||
// Create Ffs file header.
|
||||
//
|
||||
memset (&FfsFileHeader, 0, sizeof (EFI_FFS_FILE_HEADER));
|
||||
memcpy (&FfsFileHeader.Name, &FileGuid, sizeof (EFI_GUID));
|
||||
FfsFileHeader.Type = FfsFiletype;
|
||||
//
|
||||
// Update FFS Alignment based on the max alignment required by input section files
|
||||
//
|
||||
VerboseMsg ("the max alignment of all input sections is %d", MaxAlignment);
|
||||
for (Index = 0; Index < sizeof (mFfsValidAlign) / sizeof (UINT32) - 1; Index ++) {
|
||||
if ((MaxAlignment > mFfsValidAlign [Index]) && (MaxAlignment <= mFfsValidAlign [Index + 1])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (FfsAlign < Index) {
|
||||
FfsAlign = Index;
|
||||
}
|
||||
VerboseMsg ("the alignment of the genreated FFS file is %d", mFfsValidAlign [FfsAlign + 1]);
|
||||
FfsFileHeader.Attributes = FfsAttrib | (FfsAlign << 3);
|
||||
|
||||
//
|
||||
// Now FileSize includes the EFI_FFS_FILE_HEADER
|
||||
//
|
||||
FileSize += sizeof (EFI_FFS_FILE_HEADER);
|
||||
VerboseMsg ("the size of the genreated FFS file is %d bytes", FileSize);
|
||||
FfsFileHeader.Size[0] = (UINT8) (FileSize & 0xFF);
|
||||
FfsFileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8);
|
||||
FfsFileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16);
|
||||
//
|
||||
// Fill in checksums and state, these must be zero for checksumming
|
||||
//
|
||||
// FileHeader.IntegrityCheck.Checksum.Header = 0;
|
||||
// FileHeader.IntegrityCheck.Checksum.File = 0;
|
||||
// FileHeader.State = 0;
|
||||
//
|
||||
FfsFileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 (
|
||||
(UINT8 *) &FfsFileHeader,
|
||||
sizeof (EFI_FFS_FILE_HEADER)
|
||||
);
|
||||
|
||||
if (FfsFileHeader.Attributes & FFS_ATTRIB_CHECKSUM) {
|
||||
//
|
||||
// Ffs header checksum = zero, so only need to calculate ffs body.
|
||||
//
|
||||
FfsFileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 (
|
||||
FileBuffer,
|
||||
FileSize - sizeof (EFI_FFS_FILE_HEADER)
|
||||
);
|
||||
} else {
|
||||
FfsFileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM;
|
||||
}
|
||||
|
||||
FfsFileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID;
|
||||
|
||||
//
|
||||
// Open output file to write ffs data.
|
||||
//
|
||||
remove(OutputFileName);
|
||||
FfsFile = fopen (OutputFileName, "wb");
|
||||
if (FfsFile == NULL) {
|
||||
Error (NULL, 0, 0001, "Error opening file", OutputFileName);
|
||||
goto Finish;
|
||||
}
|
||||
//
|
||||
// write header
|
||||
//
|
||||
fwrite (&FfsFileHeader, 1, sizeof (FfsFileHeader), FfsFile);
|
||||
//
|
||||
// write data
|
||||
//
|
||||
fwrite (FileBuffer, 1, FileSize - sizeof (EFI_FFS_FILE_HEADER), FfsFile);
|
||||
|
||||
fclose (FfsFile);
|
||||
|
||||
Finish:
|
||||
if (InputFileName != NULL) {
|
||||
free (InputFileName);
|
||||
}
|
||||
if (InputFileAlign != NULL) {
|
||||
free (InputFileAlign);
|
||||
}
|
||||
if (FileBuffer != NULL) {
|
||||
free (FileBuffer);
|
||||
}
|
||||
//
|
||||
// If any errors were reported via the standard error reporting
|
||||
// routines, then the status has been saved. Get the value and
|
||||
// return it to the caller.
|
||||
//
|
||||
VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ());
|
||||
|
||||
return GetUtilityStatus ();
|
||||
}
|
Reference in New Issue
Block a user