/**
Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
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
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:
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_MAJOR_VERSION 0
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
};
"1", "2", "4", "8", "16", "32", "64", "128", "256", "512",
"1K", "2K", "4K", "8K", "16K", "32K", "64K"
};
"8", "16", "128", "512", "1K", "4K", "32K", "64K"
};
Version (
)
/*++
Routine Description:
Print out version information for this utility.
Arguments:
None
Returns:
None
--*/
{
fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
}
Usage (
)
/*++
Routine Description:
Print Error / Help message.
Arguments:
VOID
Returns:
None
--*/
{
//
// Summary usage
//
//
// Copyright declaration
//
//
// Details Option
//
File is FFS file to be created.\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_SMM, EFI_FV_FILETYPE_SMM_CORE,\n\
EFI_FV_FILETYPE_COMBINED_SMM_DXE, \n\
EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n");
FileGuid is one module guid.\n\
Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n");
from its present location.\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");
Section file will be contained in this FFS file.\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");
}
)
/*++
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.
--*/
{
//
// Check AlignBuffer
//
if (AlignBuffer == NULL) {
return EFI_INVALID_PARAMETER;
}
return EFI_SUCCESS;
}
}
return EFI_INVALID_PARAMETER;
}
)
/*++
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
--*/
{
return EFI_FV_FILETYPE_ALL;
}
return Index;
}
}
return EFI_FV_FILETYPE_ALL;
}
)
/*++
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.
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.
--*/
{
Size = 0;
Offset = 0;
TeOffset = 0;
//
// Go through our array of file names and copy their contents
// to the output buffer.
//
//
// make sure section ends on a DWORD boundary
//
while ((Size & 0x03) != 0) {
Size++;
}
//
// Get the Max alignment of all input file datas
//
}
//
// Open file and read contents
//
return EFI_ABORTED;
}
"the input section name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize);
//
//
TeOffset = 0;
HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER);
(*PESectionNum) ++;
}
(*PESectionNum) ++;
}
(*PESectionNum) ++;
//
//
(*PESectionNum) ++;
}
//
// Revert TeOffset to the converse value relative to Alignment
// This is to assure the original PeImage Header at Alignment.
//
}
//
// 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 + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) {
Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1);
}
"Pad Raw section size is %u", (unsigned) Offset);
}
//
// Now read the contents of the file into the buffer
// Buffer must be enough to contain the file content.
//
return EFI_ABORTED;
}
}
}
//
// 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 (
int argc,
)
/*++
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.
--*/
{
//
// Init local variables
//
LogLevel = 0;
Index = 0;
FfsAttrib = 0;
FfsAlign = 0;
InputFileNum = 0;
FileBuffer = NULL;
FileSize = 0;
MaxAlignment = 1;
PeSectionNum = 0;
if (argc == 1) {
Usage ();
return STATUS_ERROR;
}
//
// Parse command line
//
argc --;
argv ++;
Version ();
Usage ();
return STATUS_SUCCESS;
}
Version ();
return STATUS_SUCCESS;
}
while (argc > 0) {
goto Finish;
}
if (FfsFiletype == EFI_FV_FILETYPE_ALL) {
goto Finish;
}
argc -= 2;
argv += 2;
continue;
}
goto Finish;
}
argc -= 2;
argv += 2;
continue;
}
goto Finish;
}
argc -= 2;
argv += 2;
continue;
}
argc -= 1;
argv += 1;
continue;
}
argc -= 1;
argv += 1;
continue;
}
goto Finish;
}
break;
}
}
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 {
goto Finish;
}
}
argc -= 2;
argv += 2;
continue;
}
//
// Get Input file name and its alignment
//
goto Finish;
}
//
// Allocate Input file name buffer and its alignment buffer.
//
if (InputFileName == NULL) {
return STATUS_ERROR;
}
if (InputFileAlign == NULL) {
return STATUS_ERROR;
}
} else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) {
//
// InputFileName and alignment buffer too small, need to realloc
//
);
if (InputFileName == NULL) {
return STATUS_ERROR;
}
);
if (InputFileAlign == NULL) {
return STATUS_ERROR;
}
}
argc -= 2;
argv += 2;
if (argc <= 0) {
InputFileNum ++;
break;
}
//
// Section File alignment requirement
//
goto Finish;
}
argc -= 2;
argv += 2;
}
InputFileNum ++;
continue;
}
Error (NULL, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file.");
goto Finish;
}
VerboseMsg ("Verbose output Mode Set!");
argc --;
argv ++;
continue;
}
KeyMsg ("Quiet output Mode Set!");
argc --;
argv ++;
continue;
}
goto Finish;
}
if (LogLevel > 9) {
Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel);
goto Finish;
}
argc -= 2;
argv += 2;
continue;
}
goto Finish;
}
//
// Check the complete input paramters.
//
if (FfsFiletype == EFI_FV_FILETYPE_ALL) {
goto Finish;
}
goto Finish;
}
if (InputFileNum == 0) {
goto Finish;
}
//
// Output input parameter information
//
VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
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");
}
if (InputFileAlign[Index] == 0) {
//
// Minimum alignment is 1 byte.
//
}
VerboseMsg ("the %dth input section name is %s and section alignment is %u", Index, InputFileName[Index], (unsigned) InputFileAlign[Index]);
}
//
// Calculate the size of all input section files.
//
&FileSize,
);
if ((FfsFiletype == EFI_FV_FILETYPE_SECURITY_CORE ||
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);
goto Finish;
}
if ((FfsFiletype == EFI_FV_FILETYPE_PEIM ||
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) {
if (FileBuffer == NULL) {
goto Finish;
}
//
// read all input file contents into a buffer
//
&FileSize,
);
}
goto Finish;
}
//
// Create Ffs file header.
//
//
// Update FFS Alignment based on the max alignment required by input section files
//
break;
}
}
}
VerboseMsg ("the alignment of the generated FFS file is %u", (unsigned) mFfsValidAlign [FfsAlign + 1]);
//
// Now FileSize includes the EFI_FFS_FILE_HEADER
//
FileSize += sizeof (EFI_FFS_FILE_HEADER);
//
// Fill in checksums and state, these must be zero for checksumming
//
// FileHeader.IntegrityCheck.Checksum.Header = 0;
// FileHeader.IntegrityCheck.Checksum.File = 0;
// FileHeader.State = 0;
//
(UINT8 *) &FfsFileHeader,
sizeof (EFI_FFS_FILE_HEADER)
);
//
// Ffs header checksum = zero, so only need to calculate ffs body.
//
FileSize - sizeof (EFI_FFS_FILE_HEADER)
);
} else {
}
//
// Open output file to write ffs data.
//
goto Finish;
}
//
// write header
//
//
// write data
//
if (InputFileName != NULL) {
}
if (InputFileAlign != NULL) {
}
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.
//
return GetUtilityStatus ();
}