audk/Tools/CCode/Source/GenSection/GenSection.c

939 lines
29 KiB
C

/*++
Copyright (c) 2004, 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:
GenSection.c
Abstract:
Creates output file that is a properly formed section per the FV spec.
--*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Common/UefiBaseTypes.h>
#include <Common/FirmwareVolumeImageFormat.h>
#include <Protocol/GuidedSectionExtraction.h>
#include "CommonLib.h"
#include "EfiCompress.h"
#include "EfiCustomizedCompress.h"
#include "Crc32.h"
#include "EfiUtilityMsgs.h"
#include "GenSection.h"
#define UTILITY_NAME "GenSection"
#define PARAMETER_NOT_SPECIFIED "Parameter not specified"
#define MAXIMUM_INPUT_FILE_NUM 10
char *SectionTypeName[] = {
NULL, // 0x00 - reserved
"EFI_SECTION_COMPRESSION", // 0x01
"EFI_SECTION_GUID_DEFINED", // 0x02
NULL, // 0x03 - reserved
NULL, // 0x04 - reserved
NULL, // 0x05 - reserved
NULL, // 0x06 - reserved
NULL, // 0x07 - reserved
NULL, // 0x08 - reserved
NULL, // 0x09 - reserved
NULL, // 0x0A - reserved
NULL, // 0x0B - reserved
NULL, // 0x0C - reserved
NULL, // 0x0D - reserved
NULL, // 0x0E - reserved
NULL, // 0x0F - reserved
"EFI_SECTION_PE32", // 0x10
"EFI_SECTION_PIC", // 0x11
"EFI_SECTION_TE", // 0x12
"EFI_SECTION_DXE_DEPEX", // 0x13
"EFI_SECTION_VERSION", // 0x14
"EFI_SECTION_USER_INTERFACE", // 0x15
"EFI_SECTION_COMPATIBILITY16", // 0x16
"EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17
"EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18
"EFI_SECTION_RAW", // 0x19
NULL, // 0x1A
"EFI_SECTION_PEI_DEPEX" // 0x1B
};
char *CompressionTypeName[] = { "NONE", "STANDARD" };
char *GUIDedSectionTypeName[] = { "CRC32" };
EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID;
static
VOID
PrintUsageMessage (
VOID
)
{
UINTN SectionType;
UINTN DisplayCount;
printf ("Usage: "UTILITY_NAME " -i InputFile -o OutputFile -s SectionType [SectionType params]\n\n");
printf (" Where SectionType is one of the following section types:\n\n");
DisplayCount = 0;
for (SectionType = 0; SectionType <= EFI_SECTION_LAST_SECTION_TYPE; SectionType++) {
if (SectionTypeName[SectionType] != NULL) {
printf (" %s\n", SectionTypeName[SectionType]);
}
}
printf ("\n and SectionType dependent parameters are as follows:\n\n");
printf (
" %s: -t < %s | %s >\n",
SectionTypeName[EFI_SECTION_COMPRESSION],
CompressionTypeName[EFI_NOT_COMPRESSED],
CompressionTypeName[EFI_STANDARD_COMPRESSION]
);
printf (
" %s: -t < %s >\n"" // Currently only CRC32 is supported\n\n",
SectionTypeName[EFI_SECTION_GUID_DEFINED],
GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]
);
printf (
" %s: -v VersionNumber\n"" [-a \"Version string\"]\n\n",
SectionTypeName[EFI_SECTION_VERSION]
);
printf (
" %s: -a \"Human readable name\"\n\n",
SectionTypeName[EFI_SECTION_USER_INTERFACE]
);
}
VOID
Ascii2UnicodeWriteString (
char *String,
FILE *OutFile,
BOOLEAN WriteLangCode
)
{
UINTN Index;
UINT8 AsciiNull;
//
// BUGBUG need to get correct language code...
//
char *EnglishLangCode = "eng";
AsciiNull = 0;
//
// first write the language code (english only)
//
if (WriteLangCode) {
fwrite (EnglishLangCode, 1, 4, OutFile);
}
//
// Next, write out the string... Convert ASCII to Unicode in the process.
//
Index = 0;
do {
fwrite (&String[Index], 1, 1, OutFile);
fwrite (&AsciiNull, 1, 1, OutFile);
} while (String[Index++] != 0);
}
STATUS
GenSectionCommonLeafSection (
char **InputFileName,
int InputFileNum,
UINTN SectionType,
FILE *OutFile
)
/*++
Routine Description:
Generate a leaf section of type other than EFI_SECTION_VERSION
and EFI_SECTION_USER_INTERFACE. Input file must be well formed.
The function won't validate the input file's contents. For
common leaf sections, the input file may be a binary file.
The utility will add section header to the file.
Arguments:
InputFileName - Name of the input file.
InputFileNum - Number of input files. Should be 1 for leaf section.
SectionType - A valid section type string
OutFile - Output file handle
Returns:
STATUS_ERROR - can't continue
STATUS_SUCCESS - successful return
--*/
{
UINT64 InputFileLength;
FILE *InFile;
UINT8 *Buffer;
INTN TotalLength;
EFI_COMMON_SECTION_HEADER CommonSect;
STATUS Status;
if (InputFileNum > 1) {
Error (NULL, 0, 0, "invalid parameter", "more than one input file specified");
return STATUS_ERROR;
} else if (InputFileNum < 1) {
Error (NULL, 0, 0, "no input file specified", NULL);
return STATUS_ERROR;
}
//
// Open the input file
//
InFile = fopen (InputFileName[0], "rb");
if (InFile == NULL) {
Error (NULL, 0, 0, InputFileName[0], "failed to open input file");
return STATUS_ERROR;
}
Status = STATUS_ERROR;
Buffer = NULL;
//
// Seek to the end of the input file so we can determine its size
//
fseek (InFile, 0, SEEK_END);
fgetpos (InFile, &InputFileLength);
fseek (InFile, 0, SEEK_SET);
//
// Fill in the fields in the local section header structure
//
CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
TotalLength = sizeof (CommonSect) + (INTN) InputFileLength;
//
// Size must fit in 3 bytes
//
if (TotalLength >= 0x1000000) {
Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit", TotalLength);
goto Done;
}
//
// Now copy the size into the section header and write out the section header
//
memcpy (&CommonSect.Size, &TotalLength, 3);
fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
//
// Allocate a buffer to read in the contents of the input file. Then
// read it in as one block and write it to the output file.
//
if (InputFileLength != 0) {
Buffer = (UINT8 *) malloc ((size_t) InputFileLength);
if (Buffer == NULL) {
Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL);
goto Done;
}
if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) {
Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file");
goto Done;
}
if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) {
Error (NULL, 0, 0, "failed to write to output file", NULL);
goto Done;
}
}
Status = STATUS_SUCCESS;
Done:
fclose (InFile);
if (Buffer != NULL) {
free (Buffer);
}
return Status;
}
EFI_STATUS
GetSectionContents (
char **InputFileName,
int InputFileNum,
UINT8 *FileBuffer,
UINTN *BufferLength
)
/*++
Routine Description:
Get the contents of all section files specified in InputFileName
into FileBuffer.
Arguments:
InputFileName - Name of the input file.
InputFileNum - Number of input files. Should be at least 1.
FileBuffer - Output buffer to contain data
BufferLength - Actual length of the data
Returns:
EFI_SUCCESS on successful return
EFI_INVALID_PARAMETER if InputFileNum is less than 1
EFI_ABORTED if unable to open input file.
--*/
{
UINTN Size;
UINTN FileSize;
INTN Index;
FILE *InFile;
if (InputFileNum < 1) {
Error (NULL, 0, 0, "must specify at least one input file", NULL);
return EFI_INVALID_PARAMETER;
}
Size = 0;
//
// Go through our array of file names and copy their contents
// to the output buffer.
//
for (Index = 0; Index < InputFileNum; Index++) {
InFile = fopen (InputFileName[Index], "rb");
if (InFile == NULL) {
Error (NULL, 0, 0, InputFileName[Index], "failed to open input file");
return EFI_ABORTED;
}
fseek (InFile, 0, SEEK_END);
FileSize = ftell (InFile);
fseek (InFile, 0, SEEK_SET);
//
// Now read the contents of the file into the buffer
//
if (FileSize > 0) {
if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) {
Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file");
fclose (InFile);
return EFI_ABORTED;
}
}
fclose (InFile);
Size += (UINTN) FileSize;
//
// make sure section ends on a DWORD boundary
//
while ((Size & 0x03) != 0) {
FileBuffer[Size] = 0;
Size++;
}
}
*BufferLength = Size;
return EFI_SUCCESS;
}
EFI_STATUS
GenSectionCompressionSection (
char **InputFileName,
int InputFileNum,
UINTN SectionType,
UINTN SectionSubType,
FILE *OutFile
)
/*++
Routine Description:
Generate an encapsulating section of type EFI_SECTION_COMPRESSION
Input file must be already sectioned. The function won't validate
the input files' contents. Caller should hand in files already
with section header.
Arguments:
InputFileName - Name of the input file.
InputFileNum - Number of input files. Should be at least 1.
SectionType - Section type to generate. Should be
EFI_SECTION_COMPRESSION
SectionSubType - Specify the compression algorithm requested.
OutFile - Output file handle
Returns:
EFI_SUCCESS on successful return
EFI_INVALID_PARAMETER if InputFileNum is less than 1
EFI_ABORTED if unable to open input file.
EFI_OUT_OF_RESOURCES No resource to complete the operation.
--*/
{
UINTN TotalLength;
UINTN InputLength;
UINTN CompressedLength;
UINT8 *FileBuffer;
UINT8 *OutputBuffer;
EFI_STATUS Status;
EFI_COMPRESSION_SECTION CompressionSect;
COMPRESS_FUNCTION CompressFunction;
if (SectionType != EFI_SECTION_COMPRESSION) {
Error (NULL, 0, 0, "parameter must be EFI_SECTION_COMPRESSION", NULL);
return EFI_INVALID_PARAMETER;
}
InputLength = 0;
FileBuffer = NULL;
OutputBuffer = NULL;
CompressedLength = 0;
FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
if (FileBuffer == NULL) {
Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
return EFI_OUT_OF_RESOURCES;
}
//
// read all input file contents into a buffer
//
Status = GetSectionContents (
InputFileName,
InputFileNum,
FileBuffer,
&InputLength
);
if (EFI_ERROR (Status)) {
free (FileBuffer);
return Status;
}
CompressFunction = NULL;
//
// Now data is in FileBuffer, compress the data
//
switch (SectionSubType) {
case EFI_NOT_COMPRESSED:
CompressedLength = InputLength;
break;
case EFI_STANDARD_COMPRESSION:
CompressFunction = (COMPRESS_FUNCTION) Compress;
break;
case EFI_CUSTOMIZED_COMPRESSION:
CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress;
break;
default:
Error (NULL, 0, 0, "unknown compression type", NULL);
free (FileBuffer);
return EFI_ABORTED;
}
if (CompressFunction != NULL) {
Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
if (Status == EFI_BUFFER_TOO_SMALL) {
OutputBuffer = malloc (CompressedLength);
if (!OutputBuffer) {
free (FileBuffer);
return EFI_OUT_OF_RESOURCES;
}
Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength);
}
free (FileBuffer);
FileBuffer = OutputBuffer;
if (EFI_ERROR (Status)) {
if (FileBuffer != NULL) {
free (FileBuffer);
}
return Status;
}
}
TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION);
//
// Add the section header for the compressed data
//
CompressionSect.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType;
CompressionSect.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
CompressionSect.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
CompressionSect.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
CompressionSect.CompressionType = (UINT8) SectionSubType;
CompressionSect.UncompressedLength = InputLength;
fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile);
fwrite (FileBuffer, CompressedLength, 1, OutFile);
free (FileBuffer);
return EFI_SUCCESS;
}
EFI_STATUS
GenSectionGuidDefinedSection (
char **InputFileName,
int InputFileNum,
UINTN SectionType,
UINTN SectionSubType,
FILE *OutFile
)
/*++
Routine Description:
Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED
Input file must be already sectioned. The function won't validate
the input files' contents. Caller should hand in files already
with section header.
Arguments:
InputFileName - Name of the input file.
InputFileNum - Number of input files. Should be at least 1.
SectionType - Section type to generate. Should be
EFI_SECTION_GUID_DEFINED
SectionSubType - Specify the authentication algorithm requested.
OutFile - Output file handle
Returns:
EFI_SUCCESS on successful return
EFI_INVALID_PARAMETER if InputFileNum is less than 1
EFI_ABORTED if unable to open input file.
EFI_OUT_OF_RESOURCES No resource to complete the operation.
--*/
{
INTN TotalLength;
INTN InputLength;
UINT8 *FileBuffer;
UINT32 Crc32Checksum;
EFI_STATUS Status;
CRC32_SECTION_HEADER Crc32GuidSect;
if (SectionType != EFI_SECTION_GUID_DEFINED) {
Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL);
return EFI_INVALID_PARAMETER;
}
InputLength = 0;
FileBuffer = NULL;
FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8));
if (FileBuffer == NULL) {
Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
return EFI_OUT_OF_RESOURCES;
}
//
// read all input file contents into a buffer
//
Status = GetSectionContents (
InputFileName,
InputFileNum,
FileBuffer,
&InputLength
);
if (EFI_ERROR (Status)) {
free (FileBuffer);
return Status;
}
//
// Now data is in FileBuffer, compress the data
//
switch (SectionSubType) {
case EFI_SECTION_CRC32_GUID_DEFINED:
Crc32Checksum = 0;
CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum);
if (EFI_ERROR (Status)) {
free (FileBuffer);
return Status;
}
TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE;
Crc32GuidSect.GuidSectionHeader.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType;
Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff);
Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8);
Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16);
memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID));
Crc32GuidSect.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID;
Crc32GuidSect.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE;
Crc32GuidSect.CRC32Checksum = Crc32Checksum;
break;
default:
Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type");
free (FileBuffer);
return EFI_ABORTED;
}
fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile);
fwrite (FileBuffer, InputLength, 1, OutFile);
free (FileBuffer);
return EFI_SUCCESS;
}
int
main (
int argc,
char *argv[]
)
/*++
Routine Description:
Main
Arguments:
command line parameters
Returns:
EFI_SUCCESS Section header successfully generated and section concatenated.
EFI_ABORTED Could not generate the section
EFI_OUT_OF_RESOURCES No resource to complete the operation.
--*/
{
INTN Index;
INTN VersionNumber;
UINTN SectionType;
UINTN SectionSubType;
BOOLEAN InputFileRequired;
BOOLEAN SubTypeRequired;
FILE *InFile;
FILE *OutFile;
INTN InputFileNum;
char **InputFileName;
char *OutputFileName;
char AuxString[500] = { 0 };
char *ParamSectionType;
char *ParamSectionSubType;
char *ParamLength;
char *ParamVersion;
char *ParamDigitalSignature;
EFI_STATUS Status;
EFI_COMMON_SECTION_HEADER CommonSect;
InputFileName = NULL;
OutputFileName = PARAMETER_NOT_SPECIFIED;
ParamSectionType = PARAMETER_NOT_SPECIFIED;
ParamSectionSubType = PARAMETER_NOT_SPECIFIED;
ParamLength = PARAMETER_NOT_SPECIFIED;
ParamVersion = PARAMETER_NOT_SPECIFIED;
ParamDigitalSignature = PARAMETER_NOT_SPECIFIED;
Status = EFI_SUCCESS;
VersionNumber = 0;
SectionType = 0;
SectionSubType = 0;
InputFileRequired = TRUE;
SubTypeRequired = FALSE;
InFile = NULL;
OutFile = NULL;
InputFileNum = 0;
Status = EFI_SUCCESS;
SetUtilityName (UTILITY_NAME);
if (argc == 1) {
PrintUsageMessage ();
return STATUS_ERROR;
}
//
// Parse command line
//
Index = 1;
while (Index < argc) {
if (strcmpi (argv[Index], "-i") == 0) {
//
// Input File found
//
Index++;
InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *));
if (InputFileName == NULL) {
Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
return EFI_OUT_OF_RESOURCES;
}
memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
InputFileName[InputFileNum] = argv[Index];
InputFileNum++;
Index++;
//
// Parse subsequent parameters until another switch is encountered
//
while ((Index < argc) && (argv[Index][0] != '-')) {
if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) {
//
// InputFileName buffer too small, need to realloc
//
InputFileName = (char **) realloc (
InputFileName,
(InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *)
);
if (InputFileName == NULL) {
Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory");
return EFI_OUT_OF_RESOURCES;
}
memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)));
}
InputFileName[InputFileNum] = argv[Index];
InputFileNum++;
Index++;
}
}
if (strcmpi (argv[Index], "-o") == 0) {
//
// Output file found
//
Index++;
OutputFileName = argv[Index];
} else if (strcmpi (argv[Index], "-s") == 0) {
//
// Section Type found
//
Index++;
ParamSectionType = argv[Index];
} else if (strcmpi (argv[Index], "-t") == 0) {
//
// Compression or Authentication type
//
Index++;
ParamSectionSubType = argv[Index];
} else if (strcmpi (argv[Index], "-l") == 0) {
//
// Length
//
Index++;
ParamLength = argv[Index];
} else if (strcmpi (argv[Index], "-v") == 0) {
//
// VersionNumber
//
Index++;
ParamVersion = argv[Index];
} else if (strcmpi (argv[Index], "-a") == 0) {
//
// Aux string
//
Index++;
//
// Note, the MSVC C-Start parses out and consolidates quoted strings from the command
// line. Quote characters are stripped. If this tool is ported to other environments
// this will need to be taken into account
//
strncpy (AuxString, argv[Index], 499);
} else if (strcmpi (argv[Index], "-d") == 0) {
//
// Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1)
//
Index++;
ParamDigitalSignature = argv[Index];
} else if (strcmpi (argv[Index], "-?") == 0) {
PrintUsageMessage ();
return STATUS_ERROR;
} else {
Error (NULL, 0, 0, argv[Index], "unknown option");
return GetUtilityStatus ();
}
Index++;
}
//
// At this point, all command line parameters are verified as not being totally
// bogus. Next verify the command line parameters are complete and make
// sense...
//
if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) {
SectionType = EFI_SECTION_COMPRESSION;
SubTypeRequired = TRUE;
if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) {
SectionSubType = EFI_NOT_COMPRESSED;
} else if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) {
SectionSubType = EFI_STANDARD_COMPRESSION;
} else {
Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type");
PrintUsageMessage ();
return GetUtilityStatus ();
}
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) {
SectionType = EFI_SECTION_GUID_DEFINED;
SubTypeRequired = TRUE;
if (stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) {
SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED;
} else {
Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType);
PrintUsageMessage ();
return GetUtilityStatus ();
}
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) {
SectionType = EFI_SECTION_PE32;
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) {
SectionType = EFI_SECTION_PIC;
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) {
SectionType = EFI_SECTION_TE;
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) {
SectionType = EFI_SECTION_DXE_DEPEX;
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) {
SectionType = EFI_SECTION_VERSION;
InputFileRequired = FALSE;
Index = sscanf (ParamVersion, "%d", &VersionNumber);
if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) {
Error (NULL, 0, 0, ParamVersion, "illegal version number");
PrintUsageMessage ();
return GetUtilityStatus ();
}
if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
AuxString[0] = 0;
}
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) {
SectionType = EFI_SECTION_USER_INTERFACE;
InputFileRequired = FALSE;
if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) {
Error (NULL, 0, 0, "user interface string not specified", NULL);
PrintUsageMessage ();
return GetUtilityStatus ();
}
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) {
SectionType = EFI_SECTION_COMPATIBILITY16;
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) {
SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE;
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) {
SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID;
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) {
SectionType = EFI_SECTION_RAW;
} else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) {
SectionType = EFI_SECTION_PEI_DEPEX;
} else {
Error (NULL, 0, 0, ParamSectionType, "unknown section type");
PrintUsageMessage ();
return GetUtilityStatus ();
}
//
// Open output file
//
OutFile = fopen (OutputFileName, "wb");
if (OutFile == NULL) {
Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
if (InFile != NULL) {
fclose (InFile);
}
return GetUtilityStatus ();
}
//
// At this point, we've fully validated the command line, and opened appropriate
// files, so let's go and do what we've been asked to do...
//
//
// Within this switch, build and write out the section header including any
// section type specific pieces. If there's an input file, it's tacked on later
//
switch (SectionType) {
case EFI_SECTION_COMPRESSION:
Status = GenSectionCompressionSection (
InputFileName,
InputFileNum,
SectionType,
SectionSubType,
OutFile
);
break;
case EFI_SECTION_GUID_DEFINED:
Status = GenSectionGuidDefinedSection (
InputFileName,
InputFileNum,
SectionType,
SectionSubType,
OutFile
);
break;
case EFI_SECTION_VERSION:
CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
Index = sizeof (CommonSect);
//
// 2 characters for the build number
//
Index += 2;
//
// Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
//
Index += (strlen (AuxString) * 2) + 2;
memcpy (&CommonSect.Size, &Index, 3);
fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
fwrite (&VersionNumber, 2, 1, OutFile);
Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
break;
case EFI_SECTION_USER_INTERFACE:
CommonSect.Type = (EFI_SECTION_TYPE) SectionType;
Index = sizeof (CommonSect);
//
// Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null.
//
Index += (strlen (AuxString) * 2) + 2;
memcpy (&CommonSect.Size, &Index, 3);
fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile);
Ascii2UnicodeWriteString (AuxString, OutFile, FALSE);
break;
default:
//
// All other section types are caught by default (they're all the same)
//
Status = GenSectionCommonLeafSection (
InputFileName,
InputFileNum,
SectionType,
OutFile
);
break;
}
if (InputFileName != NULL) {
free (InputFileName);
}
fclose (OutFile);
//
// If we had errors, then delete the output file
//
if (GetUtilityStatus () == STATUS_ERROR) {
remove (OutputFileName);
}
return GetUtilityStatus ();
}