mirror of https://github.com/acidanthera/audk.git
2562 lines
76 KiB
C
2562 lines
76 KiB
C
|
/*++
|
||
|
|
||
|
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
|
||
|
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:
|
||
|
|
||
|
HiiPack.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
Process HII export and pack files and create HII export files,
|
||
|
dumps, or variable defaults packs.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <ctype.h>
|
||
|
|
||
|
#include "Tiano.h"
|
||
|
#include "EfiUtilityMsgs.h"
|
||
|
#include "ParseInf.h"
|
||
|
#include "EfiInternalFormRepresentation.h"
|
||
|
#include "HiiPack.h"
|
||
|
#include "Hii.h"
|
||
|
#include "IfrParse.h"
|
||
|
#include "StringParse.h"
|
||
|
|
||
|
#define UTILITY_VERSION "v1.0"
|
||
|
#define UTILITY_NAME "HiiPack"
|
||
|
#define MAX_PATH 260
|
||
|
|
||
|
//
|
||
|
// We may have to create an empty IFR formset to provide a GUID for an HII
|
||
|
// export pack. Create a structure definition to make it easier.
|
||
|
//
|
||
|
#pragma pack(1)
|
||
|
|
||
|
typedef struct {
|
||
|
EFI_HII_IFR_PACK PackHeader;
|
||
|
EFI_IFR_FORM_SET Formset;
|
||
|
EFI_IFR_END_FORM_SET EndFormset;
|
||
|
} EMPTY_FORMSET_PACK;
|
||
|
|
||
|
#pragma pack()
|
||
|
//
|
||
|
// We'll store lists of file names from the command line in
|
||
|
// a linked list of these
|
||
|
//
|
||
|
typedef struct _FILE_NAME_LIST {
|
||
|
struct _FILE_NAME_LIST *Next;
|
||
|
UINT8 FileName[MAX_PATH];
|
||
|
int Tag; // used for whatever
|
||
|
} FILE_NAME_LIST;
|
||
|
|
||
|
//
|
||
|
// When merging HII export packs, we save HII data table headers in a linked
|
||
|
// list of these.
|
||
|
//
|
||
|
typedef struct _DATA_TABLE_HEADER_LIST {
|
||
|
struct _DATA_TABLE_HEADER_LIST *Next;
|
||
|
EFI_HII_DATA_TABLE DataTableHeader;
|
||
|
} DATA_TABLE_HEADER_LIST;
|
||
|
//
|
||
|
// Create some defines for the different operation modes supported by this utility
|
||
|
//
|
||
|
#define MODE_CREATE_HII_EXPORT 1
|
||
|
#define MODE_MERGE_HII_EXPORTS 2
|
||
|
#define MODE_EMIT_DEFAULTS 3
|
||
|
#define MODE_DUMP_HII_EXPORT 4
|
||
|
//
|
||
|
// Here's all our globals.
|
||
|
//
|
||
|
static struct {
|
||
|
FILE_NAME_LIST *PackFileNames; // Input HII pack file names
|
||
|
FILE_NAME_LIST *HiiExportFileNames; // Input files when merging
|
||
|
CHAR8 OutputFileName[MAX_PATH]; // Output dump file
|
||
|
BOOLEAN MfgFlag; // From -mfg command line arg
|
||
|
BOOLEAN NoEmptyVarPacks; // From -noemptyvarpacks command line arg
|
||
|
BOOLEAN NoVarPacks; // From -novarpacks command line arg
|
||
|
EFI_GUID Guid; // Guid specified on command line
|
||
|
BOOLEAN GuidSpecified;
|
||
|
BOOLEAN DumpStrings; // In dump mode, dump string data
|
||
|
int Verbose;
|
||
|
int Mode; // Mode this utility is operating in
|
||
|
} mGlobals;
|
||
|
|
||
|
static
|
||
|
void
|
||
|
Usage (
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
ProcessArgs (
|
||
|
int Argc,
|
||
|
char *Argv[]
|
||
|
);
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
DumpHiiExportFile (
|
||
|
char *HiiExportFileName,
|
||
|
char *OutputFileName
|
||
|
);
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpString (
|
||
|
FILE *OutFptr,
|
||
|
int StringIndex,
|
||
|
CHAR16 *Str,
|
||
|
int Indent
|
||
|
);
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpStringPack (
|
||
|
FILE *OutFptr,
|
||
|
EFI_HII_STRING_PACK *Pack,
|
||
|
int BaseOffset,
|
||
|
int Indent
|
||
|
);
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpVariablePacks (
|
||
|
FILE *OutFptr,
|
||
|
EFI_HII_VARIABLE_PACK *Pack,
|
||
|
int NumPacks,
|
||
|
int BaseOffset,
|
||
|
int Indent
|
||
|
);
|
||
|
|
||
|
static
|
||
|
void
|
||
|
TestDumpHiiPack (
|
||
|
FILE *OutFptr,
|
||
|
char *BufferStart,
|
||
|
int BufferSize
|
||
|
);
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpRawBytes (
|
||
|
FILE *OutFptr,
|
||
|
char *Buffer,
|
||
|
int Count,
|
||
|
int BaseOffset,
|
||
|
int Indent
|
||
|
);
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpIfrPack (
|
||
|
FILE *OutFptr,
|
||
|
EFI_HII_IFR_PACK *Pack,
|
||
|
int BaseOffset,
|
||
|
int Indent
|
||
|
);
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FreeGlobals (
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
AddStringPack (
|
||
|
EFI_HII_STRING_PACK *PackHeader
|
||
|
);
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
ProcessHiiExportFile (
|
||
|
char *FileName,
|
||
|
int MfgDefaults
|
||
|
);
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
ProcessIfrFiles (
|
||
|
FILE_NAME_LIST *FileName
|
||
|
);
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
EmitDefaults (
|
||
|
FILE_NAME_LIST *HiiExportFiles,
|
||
|
int MfgDefaults,
|
||
|
int NoEmptyVarPacks
|
||
|
);
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
MergeHiiExports (
|
||
|
FILE_NAME_LIST *HiiExportFiles,
|
||
|
char *OutputFileName,
|
||
|
int MfgDefaults,
|
||
|
int NoEmptyVarPacks
|
||
|
);
|
||
|
|
||
|
void
|
||
|
GuidToString (
|
||
|
EFI_GUID *Guid,
|
||
|
char *Str
|
||
|
);
|
||
|
|
||
|
static
|
||
|
CHAR16 *
|
||
|
AsciiToWchar (
|
||
|
CHAR8 *Str
|
||
|
);
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
CreateHiiExport (
|
||
|
char *OutputFileName,
|
||
|
EFI_GUID *DummyFormsetGuid,
|
||
|
FILE_NAME_LIST *PackFiles,
|
||
|
int MfgDefaults
|
||
|
);
|
||
|
|
||
|
int
|
||
|
main (
|
||
|
int Argc,
|
||
|
char *Argv[]
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Call the routine to parse the command-line options, then process the file.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Standard C main() argc and argv.
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
0 if successful
|
||
|
nonzero otherwise
|
||
|
|
||
|
--*/
|
||
|
// GC_TODO: Argc - add argument and description to function comment
|
||
|
// GC_TODO: ] - add argument and description to function comment
|
||
|
{
|
||
|
STATUS Status;
|
||
|
//
|
||
|
// Set the utility name for error reporting purposes
|
||
|
//
|
||
|
SetUtilityName (UTILITY_NAME);
|
||
|
//
|
||
|
// Process the command-line arguments
|
||
|
//
|
||
|
Status = ProcessArgs (Argc, Argv);
|
||
|
if (Status != STATUS_SUCCESS) {
|
||
|
return Status;
|
||
|
}
|
||
|
//
|
||
|
// Switch based on whether we're dumping, merging, etc.
|
||
|
//
|
||
|
if (mGlobals.Mode == MODE_DUMP_HII_EXPORT) {
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "Dumping HII export file %s => %s\n", mGlobals.HiiExportFileNames, mGlobals.OutputFileName);
|
||
|
}
|
||
|
|
||
|
DumpHiiExportFile (mGlobals.HiiExportFileNames->FileName, mGlobals.OutputFileName);
|
||
|
} else if (mGlobals.Mode == MODE_CREATE_HII_EXPORT) {
|
||
|
CreateHiiExport (mGlobals.OutputFileName, &mGlobals.Guid, mGlobals.PackFileNames, mGlobals.MfgFlag);
|
||
|
} else if (mGlobals.Mode == MODE_MERGE_HII_EXPORTS) {
|
||
|
MergeHiiExports (mGlobals.HiiExportFileNames, mGlobals.OutputFileName, mGlobals.MfgFlag, mGlobals.NoEmptyVarPacks);
|
||
|
} else if (mGlobals.Mode == MODE_EMIT_DEFAULTS) {
|
||
|
EmitDefaults (mGlobals.HiiExportFileNames, mGlobals.MfgFlag, mGlobals.NoEmptyVarPacks);
|
||
|
}
|
||
|
//
|
||
|
//
|
||
|
FreeGlobals ();
|
||
|
IfrParseEnd ();
|
||
|
StringEnd ();
|
||
|
return GetUtilityStatus ();
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|
||
|
static
|
||
|
STATUS
|
||
|
MergeHiiExports (
|
||
|
FILE_NAME_LIST *HiiExportFiles,
|
||
|
char *OutputFileName,
|
||
|
int MfgDefaults,
|
||
|
int NoEmptyVarPacks
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given a linked list of input HII export pack files, read in the contents
|
||
|
of each and create a single HII export pack that contains the contents
|
||
|
of all the input files.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
HiiExportFiles - pointer to linked list of input HII export pack file names
|
||
|
OutputFileName - name of output (merged) HII export file
|
||
|
MfgDefaults - non-zero to emit manufacturing defaults in output file
|
||
|
NoEmptyVarPacks - non-zero to not emit 0-length variable packs to the output file
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
STATUS_SUCCESS - if successful
|
||
|
STATUS_ERROR - otherwise
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_HII_HANDLE HiiHandle;
|
||
|
FILE *OutFptr;
|
||
|
FILE *InFptr;
|
||
|
STATUS Status;
|
||
|
CHAR8 *Buffer;
|
||
|
int FileSize;
|
||
|
int DataTableIndex;
|
||
|
int Count;
|
||
|
int NumDataTables;
|
||
|
EFI_HII_EXPORT_TABLE *HiiExportTableHeader;
|
||
|
EFI_HII_EXPORT_TABLE TempHiiExportTableHeader;
|
||
|
EFI_HII_DATA_TABLE *DataTableHeader;
|
||
|
EFI_HII_STRING_PACK *StringPack;
|
||
|
EFI_HII_VARIABLE_PACK *VarPack;
|
||
|
EFI_HII_IFR_PACK *IfrPack;
|
||
|
EFI_GUID HiiExportRevisionGuid = EFI_HII_PROTOCOL_GUID;
|
||
|
EFI_GUID PackageGuid;
|
||
|
EFI_GUID FormsetGuid;
|
||
|
long DataTableHeaderOffset;
|
||
|
DATA_TABLE_HEADER_LIST *DataTableList;
|
||
|
DATA_TABLE_HEADER_LIST *LastDataTable;
|
||
|
DATA_TABLE_HEADER_LIST *TempDataTable;
|
||
|
//
|
||
|
// Init locals
|
||
|
//
|
||
|
HiiHandle = FIRST_HII_PACK_HANDLE;
|
||
|
Buffer = NULL;
|
||
|
InFptr = NULL;
|
||
|
OutFptr = NULL;
|
||
|
Status = STATUS_ERROR;
|
||
|
DataTableList = NULL;
|
||
|
LastDataTable = NULL;
|
||
|
//
|
||
|
// Initialize our IFR parser and string routines
|
||
|
//
|
||
|
IfrParseInit ();
|
||
|
StringInit ();
|
||
|
//
|
||
|
// Process each input HII export file
|
||
|
//
|
||
|
NumDataTables = 0;
|
||
|
while (HiiExportFiles != NULL) {
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "Processing file %s\n", HiiExportFiles->FileName);
|
||
|
}
|
||
|
//
|
||
|
// Read in the entire file contents
|
||
|
//
|
||
|
if ((InFptr = fopen (HiiExportFiles->FileName, "rb")) == NULL) {
|
||
|
Error (NULL, 0, 0, HiiExportFiles->FileName, "failed to open HII export file for reading");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fseek (InFptr, 0, SEEK_END);
|
||
|
FileSize = (int) ftell (InFptr);
|
||
|
fseek (InFptr, 0, SEEK_SET);
|
||
|
Buffer = (CHAR8 *) malloc (FileSize);
|
||
|
if (Buffer == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (fread (Buffer, FileSize, 1, InFptr) != 1) {
|
||
|
Error (NULL, 0, 0, HiiExportFiles->FileName, "failed to read file contents");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fclose (InFptr);
|
||
|
InFptr = NULL;
|
||
|
HiiExportTableHeader = (EFI_HII_EXPORT_TABLE *) Buffer;
|
||
|
//
|
||
|
// Walk all the data tables
|
||
|
//
|
||
|
DataTableHeader = (EFI_HII_DATA_TABLE *) (HiiExportTableHeader + 1);
|
||
|
for (DataTableIndex = 0; DataTableIndex < (int) HiiExportTableHeader->NumberOfHiiDataTables; DataTableIndex++) {
|
||
|
NumDataTables++;
|
||
|
//
|
||
|
// Make sure we're still pointing into our buffer
|
||
|
//
|
||
|
if (((char *) DataTableHeader < Buffer) || ((char *) DataTableHeader > Buffer + FileSize)) {
|
||
|
Error (NULL, 0, 0, "bad data table size in input file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Save a copy of the data table header
|
||
|
//
|
||
|
TempDataTable = (DATA_TABLE_HEADER_LIST *) malloc (sizeof (DATA_TABLE_HEADER_LIST));
|
||
|
if (TempDataTable == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
memset ((void *) TempDataTable, 0, sizeof (DATA_TABLE_HEADER_LIST));
|
||
|
memcpy (&TempDataTable->DataTableHeader, DataTableHeader, sizeof (EFI_HII_DATA_TABLE));
|
||
|
if (DataTableList == NULL) {
|
||
|
DataTableList = TempDataTable;
|
||
|
} else {
|
||
|
LastDataTable->Next = TempDataTable;
|
||
|
}
|
||
|
|
||
|
LastDataTable = TempDataTable;
|
||
|
//
|
||
|
// If there is an IFR pack, parse it
|
||
|
//
|
||
|
if (DataTableHeader->IfrDataOffset != 0) {
|
||
|
if (IfrParsePack (
|
||
|
HiiHandle,
|
||
|
(EFI_HII_IFR_PACK *) ((char *) DataTableHeader + DataTableHeader->IfrDataOffset),
|
||
|
&DataTableHeader->PackageGuid
|
||
|
) != STATUS_SUCCESS
|
||
|
) {
|
||
|
goto Done;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// If there is string data, save it
|
||
|
//
|
||
|
if (DataTableHeader->StringDataOffset != 0) {
|
||
|
Status = StringParsePack (
|
||
|
HiiHandle,
|
||
|
(EFI_HII_STRING_PACK *) ((char *) DataTableHeader + DataTableHeader->StringDataOffset),
|
||
|
NULL,
|
||
|
&DataTableHeader->PackageGuid
|
||
|
);
|
||
|
if (Status != STATUS_SUCCESS) {
|
||
|
goto Done;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// If there is device path data, process it
|
||
|
//
|
||
|
if (DataTableHeader->DevicePathOffset != 0) {
|
||
|
Error (NULL, 0, 0, "application error", "%s contains unsupported device path data", HiiExportFiles->FileName);
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Next data pack
|
||
|
//
|
||
|
DataTableHeader = (EFI_HII_DATA_TABLE *) ((char *) DataTableHeader + DataTableHeader->DataTableSize);
|
||
|
HiiHandle++;
|
||
|
}
|
||
|
|
||
|
free (Buffer);
|
||
|
Buffer = NULL;
|
||
|
//
|
||
|
// Next input file
|
||
|
//
|
||
|
HiiExportFiles = HiiExportFiles->Next;
|
||
|
}
|
||
|
//
|
||
|
// Now create defaults
|
||
|
//
|
||
|
if (IfrSetDefaults (MfgDefaults) != STATUS_SUCCESS) {
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Create and write the output HII export header
|
||
|
//
|
||
|
if ((OutFptr = fopen (OutputFileName, "wb")) == NULL) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
memset ((void *) &TempHiiExportTableHeader, 0, sizeof (EFI_HII_EXPORT_TABLE));
|
||
|
TempHiiExportTableHeader.NumberOfHiiDataTables = HiiHandle - FIRST_HII_PACK_HANDLE;
|
||
|
memcpy (&TempHiiExportTableHeader.Revision, &HiiExportRevisionGuid, sizeof (EFI_GUID));
|
||
|
if (fwrite ((void *) &TempHiiExportTableHeader, sizeof (EFI_HII_EXPORT_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write HII export table header to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Now go back through all the handles and create new data packs for each, writing out
|
||
|
// the contents as we go.
|
||
|
//
|
||
|
HiiHandle = FIRST_HII_PACK_HANDLE;
|
||
|
for (TempDataTable = DataTableList; TempDataTable != NULL; TempDataTable = TempDataTable->Next) {
|
||
|
//
|
||
|
// Write a data table header to the output file. We'll rewind the file and
|
||
|
// write an updated one when we're done with this data set
|
||
|
//
|
||
|
DataTableHeaderOffset = ftell (OutFptr);
|
||
|
TempDataTable->DataTableHeader.HiiHandle = HiiHandle;
|
||
|
TempDataTable->DataTableHeader.DataTableSize = sizeof (EFI_HII_DATA_TABLE);
|
||
|
//
|
||
|
// We may change the number of variable data when merging export files, so init to 0
|
||
|
//
|
||
|
TempDataTable->DataTableHeader.NumberOfVariableData = 0;
|
||
|
if (fwrite ((void *) &TempDataTable->DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write HII data table header to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Get the string pack if any
|
||
|
//
|
||
|
Status = StringGetPack (HiiHandle, &StringPack, &FileSize, &Count, &FormsetGuid, &PackageGuid);
|
||
|
if (Status == STATUS_SUCCESS) {
|
||
|
TempDataTable->DataTableHeader.StringDataOffset = TempDataTable->DataTableHeader.DataTableSize;
|
||
|
TempDataTable->DataTableHeader.DataTableSize += FileSize;
|
||
|
//
|
||
|
// TempDataTable->DataTableHeader.NumberOfLanguages should be unchanged
|
||
|
//
|
||
|
if (fwrite ((void *) StringPack, FileSize, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write string pack to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Get the IFR pack
|
||
|
//
|
||
|
Status = IfrGetIfrPack (HiiHandle, &IfrPack, &FormsetGuid);
|
||
|
if (Status == STATUS_SUCCESS) {
|
||
|
//
|
||
|
// Write the IFR pack, followed by the variable packs
|
||
|
//
|
||
|
TempDataTable->DataTableHeader.IfrDataOffset = TempDataTable->DataTableHeader.DataTableSize;
|
||
|
TempDataTable->DataTableHeader.DataTableSize += IfrPack->Header.Length;
|
||
|
if (fwrite ((void *) IfrPack, IfrPack->Header.Length, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write IFR pack to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// If this is just a formset stub, then don't write the variable packs
|
||
|
//
|
||
|
if (IfrPack->Header.Length != sizeof (EMPTY_FORMSET_PACK)) {
|
||
|
//
|
||
|
// Go through all the variable packs and see if they're referenced by this IFR
|
||
|
//
|
||
|
Count = 0;
|
||
|
do {
|
||
|
Status = IfrGetVarPack (Count, &VarPack);
|
||
|
if (Status == STATUS_SUCCESS) {
|
||
|
//
|
||
|
// Check for variable data length of 0
|
||
|
//
|
||
|
if ((NoEmptyVarPacks == 0) ||
|
||
|
((VarPack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - VarPack->VariableNameLength) != 0)
|
||
|
) {
|
||
|
//
|
||
|
// See if it's referenced by this IFR
|
||
|
//
|
||
|
if (IfrReferencesVarPack (HiiHandle, VarPack) == STATUS_SUCCESS) {
|
||
|
if (TempDataTable->DataTableHeader.VariableDataOffset == 0) {
|
||
|
TempDataTable->DataTableHeader.VariableDataOffset = TempDataTable->DataTableHeader.DataTableSize;
|
||
|
}
|
||
|
|
||
|
TempDataTable->DataTableHeader.DataTableSize += VarPack->Header.Length;
|
||
|
TempDataTable->DataTableHeader.NumberOfVariableData++;
|
||
|
if (fwrite ((void *) VarPack, VarPack->Header.Length, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write variable pack to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Count++;
|
||
|
} while (Status == STATUS_SUCCESS);
|
||
|
}
|
||
|
|
||
|
Status = STATUS_SUCCESS;
|
||
|
}
|
||
|
//
|
||
|
// Get the device path pack
|
||
|
//
|
||
|
//
|
||
|
// Rewind the file and write the updated data table header.
|
||
|
//
|
||
|
fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
|
||
|
if (fwrite ((void *) &TempDataTable->DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write HII data table header to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fseek (OutFptr, 0, SEEK_END);
|
||
|
HiiHandle++;
|
||
|
}
|
||
|
|
||
|
Status = STATUS_SUCCESS;
|
||
|
Done:
|
||
|
IfrParseEnd ();
|
||
|
StringEnd ();
|
||
|
if (Buffer != NULL) {
|
||
|
free (Buffer);
|
||
|
}
|
||
|
|
||
|
if (InFptr != NULL) {
|
||
|
fclose (InFptr);
|
||
|
}
|
||
|
|
||
|
if (OutFptr != NULL) {
|
||
|
fclose (OutFptr);
|
||
|
}
|
||
|
|
||
|
while (DataTableList != NULL) {
|
||
|
TempDataTable = DataTableList->Next;
|
||
|
free (DataTableList);
|
||
|
DataTableList = TempDataTable;
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|
||
|
static
|
||
|
STATUS
|
||
|
CreateHiiExport (
|
||
|
char *OutputFileName,
|
||
|
EFI_GUID *DummyFormsetGuid,
|
||
|
FILE_NAME_LIST *PackFiles,
|
||
|
int MfgDefaults
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given a linked list of HII pack file names, walk the list to
|
||
|
process them and create a single HII export file.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OutputFileName - name of output HII export file to create
|
||
|
DummyFormsetGuid - IFR formsets contain a GUID which is used in many
|
||
|
places while processing data tables. If we were not
|
||
|
given an IFR pack, then we'll create a stub IFR
|
||
|
pack using this GUID as the formset GUID.
|
||
|
PackFiles - linked list of HII pack files to process
|
||
|
MfgDefaults - when creating variable packs (via IFR pack processing),
|
||
|
use manufacturing defaults rather than standard defaults
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
STATUS_SUCCESS - if successful
|
||
|
STATUS_ERROR - otherwise
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
STATUS Status;
|
||
|
EMPTY_FORMSET_PACK EmptyFormset;
|
||
|
EFI_HII_DATA_TABLE DataTableHeader;
|
||
|
EFI_HII_EXPORT_TABLE ExportTableHeader;
|
||
|
long DataTableHeaderOffset;
|
||
|
long FileSize;
|
||
|
FILE *OutFptr;
|
||
|
FILE *InFptr;
|
||
|
FILE_NAME_LIST *TempFile;
|
||
|
EFI_GUID HiiExportRevisionGuid = EFI_HII_PROTOCOL_GUID;
|
||
|
EFI_GUID TempGuid;
|
||
|
EFI_GUID PackageGuid;
|
||
|
char *Buffer;
|
||
|
EFI_HII_VARIABLE_PACK *VarPack;
|
||
|
EFI_HII_IFR_PACK *IfrPack;
|
||
|
EFI_HII_STRING_PACK_HEADER *StringPack;
|
||
|
EFI_HII_STRING_PACK_HEADER TerminatorStringPack;
|
||
|
int NumIfr;
|
||
|
int NumStrings;
|
||
|
int Index;
|
||
|
int VarPackIndex;
|
||
|
//
|
||
|
// If no input HII pack files, then why are we here? Should have been caught when
|
||
|
// args were processed though.
|
||
|
//
|
||
|
if (PackFiles == NULL) {
|
||
|
Error (NULL, 0, 0, "no input pack files specified", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
InFptr = NULL;
|
||
|
Status = STATUS_ERROR;
|
||
|
Buffer = NULL;
|
||
|
//
|
||
|
// Open the output file for writing
|
||
|
//
|
||
|
if ((OutFptr = fopen (OutputFileName, "wb")) == NULL) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Figure out how many data tables we are going to need. We'll create one
|
||
|
// data table if no more than one IFR, or we'll create one data table per IFR,
|
||
|
// and then one for strings if multiple IFR
|
||
|
//
|
||
|
NumIfr = 0;
|
||
|
NumStrings = 0;
|
||
|
for (TempFile = PackFiles; TempFile != NULL; TempFile = TempFile->Next) {
|
||
|
if (TempFile->Tag == EFI_HII_IFR) {
|
||
|
NumIfr++;
|
||
|
} else if (TempFile->Tag == EFI_HII_STRING) {
|
||
|
NumStrings++;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Three possibilities:
|
||
|
// 1) No IFR, so create one data table that contains only strings and an empty formset
|
||
|
// 2) Only 1 IFR, so create an export table with one data table that contains the IFR
|
||
|
// and all the strings
|
||
|
// 3) Multiple IFR, so create a data table for each IFR and another data table with
|
||
|
// all the strings.
|
||
|
//
|
||
|
// Initialize the export table header and write it out
|
||
|
//
|
||
|
memset ((void *) &ExportTableHeader, 0, sizeof (EFI_HII_EXPORT_TABLE));
|
||
|
if (NumIfr < 2) {
|
||
|
ExportTableHeader.NumberOfHiiDataTables = 1;
|
||
|
} else {
|
||
|
//
|
||
|
// One data table per IFR, plus one for strings (if any).
|
||
|
//
|
||
|
ExportTableHeader.NumberOfHiiDataTables = (UINT16) NumIfr;
|
||
|
if (NumStrings != 0) {
|
||
|
ExportTableHeader.NumberOfHiiDataTables++;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Init the GUID in the HII export table header
|
||
|
//
|
||
|
memcpy (&ExportTableHeader.Revision, &HiiExportRevisionGuid, sizeof (EFI_GUID));
|
||
|
if (fwrite ((void *) &ExportTableHeader, sizeof (EFI_HII_EXPORT_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write HII export table header to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// *****************************************************************************************
|
||
|
//
|
||
|
// CASE 1 - No IFR => one data table that contains only strings and an empty formset.
|
||
|
// No variable data.
|
||
|
//
|
||
|
// CASE 2 - Only 1 IFR => create an export table with one data table that contains the IFR
|
||
|
// and all the strings plus variable data
|
||
|
//
|
||
|
// CASE 3 - Multiple IFR => create a data table for each IFR and another data table with
|
||
|
// all the strings. Each IFR data table has variable data if applicable.
|
||
|
//
|
||
|
// *****************************************************************************************
|
||
|
//
|
||
|
// If the user did not give us an IFR file, then we'll have to create an empty formset
|
||
|
// and emit it to the output file. In this case, we need a formset GUID on the command
|
||
|
// line.
|
||
|
//
|
||
|
if ((NumIfr == 0) && (mGlobals.GuidSpecified == 0)) {
|
||
|
//
|
||
|
// Warning (NULL, 0, 0, "using NULL GUID for empty formset", "specify -g GUID on the command line if desired");
|
||
|
//
|
||
|
memset ((void *) &PackageGuid, 0, sizeof (EFI_GUID));
|
||
|
} else if (mGlobals.GuidSpecified) {
|
||
|
//
|
||
|
// Use it for the package GUID
|
||
|
//
|
||
|
memcpy (&PackageGuid, &mGlobals.Guid, sizeof (EFI_GUID));
|
||
|
}
|
||
|
//
|
||
|
// Init the data table header.
|
||
|
// Write out the blank data table header. Save the offset so we can
|
||
|
// write an updated version at the end of processing.
|
||
|
//
|
||
|
memset ((void *) &DataTableHeader, 0, sizeof (EFI_HII_DATA_TABLE));
|
||
|
DataTableHeaderOffset = ftell (OutFptr);
|
||
|
DataTableHeader.HiiHandle = FIRST_HII_PACK_HANDLE;
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "writing data table (first time) to offset 0x%X\n", ftell (OutFptr));
|
||
|
}
|
||
|
|
||
|
if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Set the data table size, then write out all the string packs
|
||
|
//
|
||
|
DataTableHeader.DataTableSize = sizeof (EFI_HII_DATA_TABLE);
|
||
|
//
|
||
|
// Write out the string files to a single data record
|
||
|
//
|
||
|
for (TempFile = PackFiles; TempFile != NULL; TempFile = TempFile->Next) {
|
||
|
//
|
||
|
// Continue to next file if it's not a string pack file
|
||
|
//
|
||
|
if (TempFile->Tag != EFI_HII_STRING) {
|
||
|
continue;
|
||
|
}
|
||
|
//
|
||
|
// Set the offset in the header if this is the first string pack
|
||
|
//
|
||
|
if (DataTableHeader.StringDataOffset == 0) {
|
||
|
DataTableHeader.StringDataOffset = DataTableHeader.DataTableSize;
|
||
|
}
|
||
|
|
||
|
if ((InFptr = fopen (TempFile->FileName, "rb")) == NULL) {
|
||
|
Error (NULL, 0, 0, TempFile->FileName, "failed to open input string pack file for reading");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Get the file size, then read it into a buffer
|
||
|
//
|
||
|
fseek (InFptr, 0, SEEK_END);
|
||
|
FileSize = ftell (InFptr);
|
||
|
fseek (InFptr, 0, SEEK_SET);
|
||
|
Buffer = (char *) malloc (FileSize);
|
||
|
if (Buffer == NULL) {
|
||
|
Error (NULL, 0, 0, TempFile->FileName, "memory allocation failure reading in file contents");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (fread (Buffer, FileSize, 1, InFptr) != 1) {
|
||
|
Error (NULL, 0, 0, TempFile->FileName, "failed to read file contents");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fclose (InFptr);
|
||
|
InFptr = NULL;
|
||
|
//
|
||
|
// Verify that it's actually a string pack
|
||
|
//
|
||
|
StringPack = (EFI_HII_STRING_PACK_HEADER *) Buffer;
|
||
|
while ((char *) StringPack < Buffer + FileSize) {
|
||
|
if (StringPack->Header.Type != EFI_HII_STRING) {
|
||
|
Error (NULL, 0, 0, TempFile->FileName, "file does not consist entirely of string packs");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (StringPack->Header.Length == 0) {
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
DataTableHeader.NumberOfLanguages++;
|
||
|
DataTableHeader.DataTableSize += StringPack->Header.Length;
|
||
|
//
|
||
|
// Write the string pack to the output file
|
||
|
//
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "writing string pack to offset 0x%X\n", ftell (OutFptr));
|
||
|
}
|
||
|
|
||
|
if (fwrite (StringPack, StringPack->Header.Length, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, TempFile->FileName, "failed to write string pack to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Sanity check that adding the length advances us (no wrap)
|
||
|
//
|
||
|
if ((char *) StringPack + StringPack->Header.Length <= (char *) StringPack) {
|
||
|
Error (NULL, 0, 0, TempFile->FileName, "invalid pack size in file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
StringPack = (EFI_HII_STRING_PACK_HEADER *) ((char *) StringPack + StringPack->Header.Length);
|
||
|
}
|
||
|
//
|
||
|
// Free up buffer, go to next input string pack file
|
||
|
//
|
||
|
free (Buffer);
|
||
|
Buffer = NULL;
|
||
|
}
|
||
|
//
|
||
|
// Write a null-terminator string pack if we had any string packs at all
|
||
|
//
|
||
|
if (DataTableHeader.StringDataOffset != 0) {
|
||
|
memset (&TerminatorStringPack, 0, sizeof (EFI_HII_STRING_PACK_HEADER));
|
||
|
TerminatorStringPack.Header.Length = 0;
|
||
|
TerminatorStringPack.Header.Type = EFI_HII_STRING;
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "writing terminator string pack to offset 0x%X\n", ftell (OutFptr));
|
||
|
}
|
||
|
|
||
|
if (fwrite (&TerminatorStringPack, sizeof (EFI_HII_STRING_PACK_HEADER), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write string pack terminator to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
DataTableHeader.DataTableSize += sizeof (EFI_HII_STRING_PACK_HEADER);
|
||
|
}
|
||
|
//
|
||
|
// Parse all the IFR packs, then get the GUID from the first
|
||
|
// one so we can use it for the package GUID if necessary.
|
||
|
//
|
||
|
memcpy (&PackageGuid, &mGlobals.Guid, sizeof (EFI_GUID));
|
||
|
if (NumIfr != 0) {
|
||
|
IfrParseInit ();
|
||
|
if (ProcessIfrFiles (PackFiles) != STATUS_SUCCESS) {
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Set variable defaults in all variable packs
|
||
|
//
|
||
|
IfrSetDefaults (MfgDefaults);
|
||
|
//
|
||
|
// Get the GUID from the first IFR pack if the user did not specify a GUID on
|
||
|
// the command line.
|
||
|
//
|
||
|
if (mGlobals.GuidSpecified == 0) {
|
||
|
if (IfrGetIfrPack (FIRST_HII_PACK_HANDLE, &IfrPack, &PackageGuid) != STATUS_SUCCESS) {
|
||
|
Error (NULL, 0, 0, "internal application error", "failed to retrieve IFR pack after parsing");
|
||
|
goto Done;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Set the package GUID in the data table header.
|
||
|
//
|
||
|
memcpy (&DataTableHeader.PackageGuid, &PackageGuid, sizeof (EFI_GUID));
|
||
|
//
|
||
|
// If no IFR, then create and write the empty formset. Otherwise
|
||
|
// parse the IFR and emit it and the variable data for it.
|
||
|
//
|
||
|
if (NumIfr == 0) {
|
||
|
memset ((void *) &EmptyFormset, 0, sizeof (EMPTY_FORMSET_PACK));
|
||
|
EmptyFormset.PackHeader.Header.Type = EFI_HII_IFR;
|
||
|
EmptyFormset.PackHeader.Header.Length = sizeof (EMPTY_FORMSET_PACK);
|
||
|
//
|
||
|
// Formset Opcode
|
||
|
//
|
||
|
EmptyFormset.Formset.Header.OpCode = EFI_IFR_FORM_SET_OP;
|
||
|
EmptyFormset.Formset.Header.Length = (UINT8) sizeof (EFI_IFR_FORM_SET);
|
||
|
memcpy (&EmptyFormset.Formset.Guid, &PackageGuid, sizeof (EFI_GUID));
|
||
|
//
|
||
|
// EndFormset Opcode
|
||
|
//
|
||
|
EmptyFormset.EndFormset.Header.OpCode = EFI_IFR_END_FORM_SET_OP;
|
||
|
EmptyFormset.EndFormset.Header.Length = (UINT8) sizeof (EFI_IFR_END_FORM_SET);
|
||
|
DataTableHeader.IfrDataOffset = DataTableHeader.DataTableSize;
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "writing stub IFR formset to to offset 0x%X\n", ftell (OutFptr));
|
||
|
}
|
||
|
|
||
|
if (fwrite (&EmptyFormset, sizeof (EMPTY_FORMSET_PACK), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write formset stub to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
DataTableHeader.DataTableSize += sizeof (EMPTY_FORMSET_PACK);
|
||
|
//
|
||
|
// Go back and re-write the data table header, reposition to the end, then return.
|
||
|
//
|
||
|
fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "writing data table (second time) to offset 0x%X\n", ftell (OutFptr));
|
||
|
}
|
||
|
|
||
|
if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fseek (OutFptr, 0, SEEK_END);
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (
|
||
|
stdout,
|
||
|
"final file offset=0x%X DataTableHeader.DataTableSize=0x%X\n",
|
||
|
ftell (OutFptr),
|
||
|
DataTableHeader.DataTableSize
|
||
|
);
|
||
|
}
|
||
|
} else if (NumIfr == 1) {
|
||
|
//
|
||
|
// They gave us one input IFR file. We parsed it above, so get each one
|
||
|
// and emit the IFR and each variable pack it references.
|
||
|
// Update the data pack header for the IFR pack, then write the IFR pack data
|
||
|
//
|
||
|
DataTableHeader.IfrDataOffset = DataTableHeader.DataTableSize;
|
||
|
if (IfrGetIfrPack (FIRST_HII_PACK_HANDLE, &IfrPack, &TempGuid) != STATUS_SUCCESS) {
|
||
|
Error (NULL, 0, 0, "internal application error", "failed to retrieve IFR pack after parsing");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "writing IFR pack to 0x%X\n", ftell (OutFptr));
|
||
|
}
|
||
|
|
||
|
if (fwrite (IfrPack, IfrPack->Header.Length, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write IFR pack to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
DataTableHeader.DataTableSize += IfrPack->Header.Length;
|
||
|
//
|
||
|
// Now go through all the variable packs discovered during IFR processing
|
||
|
// and write them to the output file
|
||
|
//
|
||
|
if (mGlobals.NoVarPacks == 0) {
|
||
|
Index = 0;
|
||
|
do {
|
||
|
Status = IfrGetVarPack (Index, &VarPack);
|
||
|
if (Status == STATUS_SUCCESS) {
|
||
|
//
|
||
|
// If this is the first variable pack, then update the "offset
|
||
|
// to variable data" in the data table header
|
||
|
//
|
||
|
if (Index == 0) {
|
||
|
DataTableHeader.VariableDataOffset = DataTableHeader.DataTableSize;
|
||
|
}
|
||
|
|
||
|
DataTableHeader.DataTableSize += VarPack->Header.Length;
|
||
|
DataTableHeader.NumberOfVariableData++;
|
||
|
if (fwrite ((void *) VarPack, VarPack->Header.Length, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write variable pack to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
Index++;
|
||
|
}
|
||
|
} while (Status == STATUS_SUCCESS);
|
||
|
}
|
||
|
//
|
||
|
// Reposition in the output file and write the updated data table header
|
||
|
//
|
||
|
fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
|
||
|
if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fseek (OutFptr, 0, SEEK_END);
|
||
|
} else {
|
||
|
//
|
||
|
// Multiple IFR input files. Close out the current data table (strings)
|
||
|
// if applicable. Then retrieve each parsed IFR pack and create a data pack
|
||
|
// that contains the IFR (one per data set) and the variable packs that
|
||
|
// the given IFR form references.
|
||
|
//
|
||
|
if (NumStrings != 0) {
|
||
|
fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
|
||
|
if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fseek (OutFptr, 0, SEEK_END);
|
||
|
} else {
|
||
|
//
|
||
|
// No strings, so back up over the data table header we wrote because we assumed
|
||
|
// at least one string pack.
|
||
|
//
|
||
|
fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
|
||
|
}
|
||
|
//
|
||
|
// Now go through all the IFR packs and write them out, along with variable
|
||
|
// data referenced by each. Note that multiple IFR forms can refer to the
|
||
|
// same variables, so the same variable data could be duplicated in multiple
|
||
|
// data packs.
|
||
|
//
|
||
|
Index = FIRST_HII_PACK_HANDLE;
|
||
|
while (IfrGetIfrPack (Index, &IfrPack, &TempGuid) == STATUS_SUCCESS) {
|
||
|
//
|
||
|
// Initialize the data table header
|
||
|
//
|
||
|
memset (&DataTableHeader, 0, sizeof (EFI_HII_DATA_TABLE));
|
||
|
memcpy (&DataTableHeader.PackageGuid, &PackageGuid, sizeof (EFI_GUID));
|
||
|
//
|
||
|
// If we didn't have strings, then the HiiHandle should be just Index,
|
||
|
// rather than Index+1. But since the HiiHandle is not required to start
|
||
|
// with 1, we'll let it be Index+1.
|
||
|
//
|
||
|
DataTableHeader.HiiHandle = (EFI_HII_HANDLE) (Index + 1);
|
||
|
DataTableHeader.DataTableSize = sizeof (EFI_HII_DATA_TABLE);
|
||
|
//
|
||
|
// Save the file offset of the data table header so we can write an updated
|
||
|
// version later.
|
||
|
//
|
||
|
DataTableHeaderOffset = ftell (OutFptr);
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "writing data table header to 0x%X\n", ftell (OutFptr));
|
||
|
}
|
||
|
|
||
|
if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
DataTableHeader.IfrDataOffset = DataTableHeader.DataTableSize;
|
||
|
if (fwrite (IfrPack, IfrPack->Header.Length, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write IFR pack to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
DataTableHeader.DataTableSize += IfrPack->Header.Length;
|
||
|
//
|
||
|
// Go through all the variable packs and see if this IFR references each. If the
|
||
|
// IFR does reference it, then add the variable pack to the output.
|
||
|
//
|
||
|
if (mGlobals.NoVarPacks == 0) {
|
||
|
VarPackIndex = 0;
|
||
|
while (IfrGetVarPack (VarPackIndex, &VarPack) == STATUS_SUCCESS) {
|
||
|
//
|
||
|
// See if the IFR references this variable pack
|
||
|
//
|
||
|
if (IfrReferencesVarPack (Index, VarPack) == STATUS_SUCCESS) {
|
||
|
//
|
||
|
// If this is the first variable pack, then set the offset in
|
||
|
// the data table header.
|
||
|
//
|
||
|
if (DataTableHeader.VariableDataOffset == 0) {
|
||
|
DataTableHeader.VariableDataOffset = DataTableHeader.DataTableSize;
|
||
|
}
|
||
|
//
|
||
|
// Write the variable pack
|
||
|
//
|
||
|
if (fwrite (VarPack, VarPack->Header.Length, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to write variable pack to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
DataTableHeader.NumberOfVariableData++;
|
||
|
DataTableHeader.DataTableSize += VarPack->Header.Length;
|
||
|
}
|
||
|
|
||
|
VarPackIndex++;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Write the updated data table header
|
||
|
//
|
||
|
fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
|
||
|
if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fseek (OutFptr, 0, SEEK_END);
|
||
|
//
|
||
|
// Next IFR pack
|
||
|
//
|
||
|
Index++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Status = STATUS_SUCCESS;
|
||
|
Done:
|
||
|
IfrParseEnd ();
|
||
|
StringEnd ();
|
||
|
if (Buffer != NULL) {
|
||
|
free (Buffer);
|
||
|
}
|
||
|
|
||
|
if (InFptr != NULL) {
|
||
|
fclose (InFptr);
|
||
|
}
|
||
|
|
||
|
if (OutFptr != NULL) {
|
||
|
fclose (OutFptr);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
/******************************************************************************/
|
||
|
static
|
||
|
STATUS
|
||
|
ProcessIfrFiles (
|
||
|
FILE_NAME_LIST *FileName
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given a linked list of pack file names, read in each IFR pack file
|
||
|
and process the contents.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
FileName - pointer to linked list of input pack file names
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
STATUS_SUCCESS - if successful
|
||
|
STATUS_ERROR - otherwise
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
FILE *InFptr;
|
||
|
char *Buffer;
|
||
|
long BufferSize;
|
||
|
STATUS Status;
|
||
|
STATUS IfrStatus;
|
||
|
int Handle;
|
||
|
EFI_GUID FormsetGuid;
|
||
|
EFI_HII_PACK_HEADER *PackHeader;
|
||
|
//
|
||
|
// Process each input IFR file
|
||
|
//
|
||
|
Status = STATUS_ERROR;
|
||
|
Handle = 1;
|
||
|
InFptr = NULL;
|
||
|
Buffer = NULL;
|
||
|
while (FileName != NULL) {
|
||
|
//
|
||
|
// Only process IFR pack files
|
||
|
//
|
||
|
if (FileName->Tag != EFI_HII_IFR) {
|
||
|
FileName = FileName->Next;
|
||
|
continue;
|
||
|
}
|
||
|
//
|
||
|
// Open the input file, then read the contents
|
||
|
//
|
||
|
if ((InFptr = fopen (FileName->FileName, "rb")) == NULL) {
|
||
|
Error (NULL, 0, 0, FileName->FileName, "failed to open input IFR file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fseek (InFptr, 0, SEEK_END);
|
||
|
BufferSize = ftell (InFptr);
|
||
|
fseek (InFptr, 0, SEEK_SET);
|
||
|
Buffer = (char *) malloc (BufferSize);
|
||
|
if (Buffer == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (fread (Buffer, BufferSize, 1, InFptr) != 1) {
|
||
|
Error (NULL, 0, 0, FileName->FileName, "failed to read file contents");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fclose (InFptr);
|
||
|
InFptr = NULL;
|
||
|
//
|
||
|
// Check the buffer contents -- better be an IFR pack
|
||
|
//
|
||
|
if (BufferSize < sizeof (EFI_HII_PACK_HEADER)) {
|
||
|
Error (NULL, 0, 0, FileName->FileName, "file is not large enough to contain an IFR pack");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
PackHeader = (EFI_HII_PACK_HEADER *) Buffer;
|
||
|
if (PackHeader->Type != EFI_HII_IFR) {
|
||
|
Error (NULL, 0, 0, FileName->FileName, "file does not appear to be an IFR pack");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Process the contents
|
||
|
//
|
||
|
memset ((void *) &FormsetGuid, 0, sizeof (EFI_GUID));
|
||
|
IfrStatus = IfrParsePack (Handle, (EFI_HII_IFR_PACK *) PackHeader, &FormsetGuid);
|
||
|
if (IfrStatus != STATUS_SUCCESS) {
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
Handle++;
|
||
|
free (Buffer);
|
||
|
Buffer = NULL;
|
||
|
FileName = FileName->Next;
|
||
|
}
|
||
|
|
||
|
Status = STATUS_SUCCESS;
|
||
|
Done:
|
||
|
if (InFptr != NULL) {
|
||
|
fclose (InFptr);
|
||
|
}
|
||
|
|
||
|
if (Buffer != NULL) {
|
||
|
free (Buffer);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
EmitDefaults (
|
||
|
FILE_NAME_LIST *HiiExportFiles,
|
||
|
int MfgDefaults,
|
||
|
int NoEmptyVarPacks
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given a linked list of HII export files, read in each file,
|
||
|
process the contents, and then emit variable packs.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
HiiExportFiles - linked list of HII export files to process
|
||
|
MfgDefaults - emit manufacturing defaults
|
||
|
NoEmptyVarPacks - don't emit variable packs if they are 0-length
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
STATUS_SUCCESS - if successful
|
||
|
STATUS_ERROR - otherwise
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
int HiiHandle;
|
||
|
FILE *OutFptr;
|
||
|
FILE *InFptr;
|
||
|
EFI_HII_VARIABLE_PACK *VarPack;
|
||
|
CHAR8 OutFileName[MAX_PATH];
|
||
|
CHAR8 GuidString[100];
|
||
|
STATUS Status;
|
||
|
CHAR8 *Buffer;
|
||
|
int FileSize;
|
||
|
int DataTableIndex;
|
||
|
EFI_HII_EXPORT_TABLE *HiiExportTableHeader;
|
||
|
EFI_HII_DATA_TABLE *DataTableHeader;
|
||
|
//
|
||
|
// Init locals
|
||
|
//
|
||
|
HiiHandle = FIRST_HII_PACK_HANDLE;
|
||
|
Buffer = NULL;
|
||
|
InFptr = NULL;
|
||
|
OutFptr = NULL;
|
||
|
Status = STATUS_ERROR;
|
||
|
//
|
||
|
// Initialize our IFR parser
|
||
|
//
|
||
|
IfrParseInit ();
|
||
|
//
|
||
|
// Process each input HII export file
|
||
|
//
|
||
|
while (HiiExportFiles != NULL) {
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (stdout, "Processing file %s\n", HiiExportFiles->FileName);
|
||
|
}
|
||
|
//
|
||
|
// Read in the entire file contents
|
||
|
//
|
||
|
if ((InFptr = fopen (HiiExportFiles->FileName, "rb")) == NULL) {
|
||
|
Error (NULL, 0, 0, HiiExportFiles->FileName, "failed to open HII export file for reading");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fseek (InFptr, 0, SEEK_END);
|
||
|
FileSize = (int) ftell (InFptr);
|
||
|
fseek (InFptr, 0, SEEK_SET);
|
||
|
Buffer = (CHAR8 *) malloc (FileSize);
|
||
|
if (Buffer == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (fread (Buffer, FileSize, 1, InFptr) != 1) {
|
||
|
Error (NULL, 0, 0, HiiExportFiles->FileName, "failed to read file contents");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fclose (InFptr);
|
||
|
InFptr = NULL;
|
||
|
HiiExportTableHeader = (EFI_HII_EXPORT_TABLE *) Buffer;
|
||
|
//
|
||
|
// Walk all the data tables
|
||
|
//
|
||
|
DataTableHeader = (EFI_HII_DATA_TABLE *) (HiiExportTableHeader + 1);
|
||
|
for (DataTableIndex = 0; DataTableIndex < (int) HiiExportTableHeader->NumberOfHiiDataTables; DataTableIndex++) {
|
||
|
//
|
||
|
// Make sure we're still pointing into our buffer
|
||
|
//
|
||
|
if (((char *) DataTableHeader < Buffer) || ((char *) DataTableHeader > Buffer + FileSize)) {
|
||
|
Error (NULL, 0, 0, "bad data table size in input file", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// If there is an IFR pack, parse it
|
||
|
//
|
||
|
HiiHandle++;
|
||
|
if (DataTableHeader->IfrDataOffset != 0) {
|
||
|
if (IfrParsePack (
|
||
|
HiiHandle,
|
||
|
(EFI_HII_IFR_PACK *) ((char *) DataTableHeader + DataTableHeader->IfrDataOffset),
|
||
|
&DataTableHeader->PackageGuid
|
||
|
) != STATUS_SUCCESS
|
||
|
) {
|
||
|
goto Done;
|
||
|
}
|
||
|
}
|
||
|
//
|
||
|
// Next data pack
|
||
|
//
|
||
|
DataTableHeader = (EFI_HII_DATA_TABLE *) ((char *) DataTableHeader + DataTableHeader->DataTableSize);
|
||
|
}
|
||
|
|
||
|
free (Buffer);
|
||
|
Buffer = NULL;
|
||
|
//
|
||
|
// Next input file
|
||
|
//
|
||
|
HiiExportFiles = HiiExportFiles->Next;
|
||
|
}
|
||
|
//
|
||
|
// Now create defaults
|
||
|
//
|
||
|
if (IfrSetDefaults (MfgDefaults) != STATUS_SUCCESS) {
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Now retrieve each variable pack and write it out to a GUID-VarName.hpk file
|
||
|
//
|
||
|
HiiHandle = 0;
|
||
|
do {
|
||
|
Status = IfrGetVarPack (HiiHandle, &VarPack);
|
||
|
if (Status == STATUS_SUCCESS) {
|
||
|
//
|
||
|
// Check for variable data length of 0
|
||
|
//
|
||
|
if ((NoEmptyVarPacks == 0) ||
|
||
|
((VarPack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - VarPack->VariableNameLength) != 0)
|
||
|
) {
|
||
|
//
|
||
|
// Open the output file and write the variable pack
|
||
|
//
|
||
|
GuidToString (&VarPack->VariableGuid, GuidString);
|
||
|
if (MfgDefaults) {
|
||
|
sprintf (
|
||
|
OutFileName,
|
||
|
"%s-%S-MfgDefaults%s",
|
||
|
GuidString,
|
||
|
(CHAR16 *) (VarPack + 1),
|
||
|
DEFAULT_HII_PACK_FILENAME_EXTENSION
|
||
|
);
|
||
|
} else {
|
||
|
sprintf (
|
||
|
OutFileName,
|
||
|
"%s-%S-Defaults%s",
|
||
|
GuidString,
|
||
|
(CHAR16 *) (VarPack + 1),
|
||
|
DEFAULT_HII_PACK_FILENAME_EXTENSION
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if (mGlobals.Verbose) {
|
||
|
fprintf (
|
||
|
stdout,
|
||
|
"Creating %svariable defaults pack file %s\n",
|
||
|
MfgDefaults ? "manufacturing " : "",
|
||
|
OutFileName
|
||
|
);
|
||
|
}
|
||
|
|
||
|
if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
|
||
|
Error (NULL, 0, 0, OutFileName, "failed to open output file for writing", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (fwrite ((void *) VarPack, VarPack->Header.Length, 1, OutFptr) != 1) {
|
||
|
Error (NULL, 0, 0, OutFileName, "failed to write defaults to output file");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fclose (OutFptr);
|
||
|
OutFptr = NULL;
|
||
|
} else {
|
||
|
//
|
||
|
// Print a message that we skipped one if in verbose mode
|
||
|
//
|
||
|
if (mGlobals.Verbose) {
|
||
|
GuidToString (&VarPack->VariableGuid, GuidString);
|
||
|
if (MfgDefaults) {
|
||
|
sprintf (
|
||
|
OutFileName,
|
||
|
"%s-%S-MfgDefaults%s",
|
||
|
GuidString,
|
||
|
(CHAR16 *) (VarPack + 1),
|
||
|
DEFAULT_HII_PACK_FILENAME_EXTENSION
|
||
|
);
|
||
|
} else {
|
||
|
sprintf (
|
||
|
OutFileName,
|
||
|
"%s-%S-Defaults%s",
|
||
|
GuidString,
|
||
|
(CHAR16 *) (VarPack + 1),
|
||
|
DEFAULT_HII_PACK_FILENAME_EXTENSION
|
||
|
);
|
||
|
}
|
||
|
|
||
|
fprintf (
|
||
|
stdout,
|
||
|
"Skipping 0-length %svariable defaults pack file %s\n",
|
||
|
MfgDefaults ? "manufacturing " : "",
|
||
|
OutFileName
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
HiiHandle++;
|
||
|
} while (Status == STATUS_SUCCESS);
|
||
|
Status = STATUS_SUCCESS;
|
||
|
Done:
|
||
|
IfrParseEnd ();
|
||
|
if (Buffer != NULL) {
|
||
|
free (Buffer);
|
||
|
}
|
||
|
|
||
|
if (InFptr != NULL) {
|
||
|
fclose (InFptr);
|
||
|
}
|
||
|
|
||
|
if (OutFptr != NULL) {
|
||
|
fclose (OutFptr);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
FreeGlobals (
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Free up an memory we allocated so we can exit cleanly
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Returns: NA
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
FILE_NAME_LIST *Next;
|
||
|
//
|
||
|
// Free up input pack file names
|
||
|
//
|
||
|
while (mGlobals.PackFileNames != NULL) {
|
||
|
Next = mGlobals.PackFileNames->Next;
|
||
|
free (mGlobals.PackFileNames);
|
||
|
mGlobals.PackFileNames = Next;
|
||
|
}
|
||
|
//
|
||
|
// Free up input HII export file names
|
||
|
//
|
||
|
while (mGlobals.HiiExportFileNames != NULL) {
|
||
|
Next = mGlobals.HiiExportFileNames->Next;
|
||
|
free (mGlobals.HiiExportFileNames);
|
||
|
mGlobals.HiiExportFileNames = Next;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
DumpHiiExportFile (
|
||
|
char *HiiExportFileName,
|
||
|
char *OutputFileName
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Dump the contents of an HII export file for debug purposes
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
HiiExportFileName - name of input HII export file
|
||
|
OutputFileName - name of output file to dump contents
|
||
|
|
||
|
Returns:
|
||
|
STATUS_SUCCESS - no problems
|
||
|
STATUS_ERROR - problems encountered processing the file
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
FILE *InFptr;
|
||
|
|
||
|
FILE *OutFptr;
|
||
|
char *Buffer;
|
||
|
char *BufferStart;
|
||
|
char *BufferEnd;
|
||
|
int BufferSize;
|
||
|
STATUS Status;
|
||
|
char GuidString[100];
|
||
|
int Counter;
|
||
|
int NumberOfTables;
|
||
|
EFI_HII_DATA_TABLE *DataTableHeader;
|
||
|
EFI_GUID HiiExportRevisionGuid = EFI_HII_PROTOCOL_GUID;
|
||
|
//
|
||
|
// Init locals
|
||
|
//
|
||
|
InFptr = NULL;
|
||
|
OutFptr = NULL;
|
||
|
BufferStart = NULL;
|
||
|
Status = STATUS_ERROR;
|
||
|
//
|
||
|
// Open the input file
|
||
|
//
|
||
|
if ((InFptr = fopen (HiiExportFileName, "rb")) == NULL) {
|
||
|
Error (NULL, 0, 0, HiiExportFileName, "failed to open input HII export file for reading");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Open the output file
|
||
|
//
|
||
|
if ((OutFptr = fopen (OutputFileName, "w")) == NULL) {
|
||
|
Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Get the file size, then allocate a buffer and read in the file contents.
|
||
|
//
|
||
|
fseek (InFptr, 0, SEEK_END);
|
||
|
BufferSize = (int) ftell (InFptr);
|
||
|
fseek (InFptr, 0, SEEK_SET);
|
||
|
BufferStart = (char *) malloc (BufferSize);
|
||
|
if (BufferStart == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (fread (BufferStart, BufferSize, 1, InFptr) != 1) {
|
||
|
Error (NULL, 0, 0, HiiExportFileName, "error reading file contents");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
fclose (InFptr);
|
||
|
InFptr = NULL;
|
||
|
//
|
||
|
// Crude check of the input data -- check the size and GUID
|
||
|
//
|
||
|
if (BufferSize < sizeof (EFI_HII_EXPORT_TABLE)) {
|
||
|
Error (NULL, 0, 0, HiiExportFileName, "files not large enough to contain an HII export table header");
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
if (memcmp (&((EFI_HII_EXPORT_TABLE *) BufferStart)->Revision, &HiiExportRevisionGuid, sizeof (EFI_GUID)) != 0) {
|
||
|
Error (NULL, 0, 0, HiiExportFileName, "invalid HII export revision GUID -- is this an HII export file?");
|
||
|
//
|
||
|
// See if it's a HII pack file
|
||
|
//
|
||
|
TestDumpHiiPack (OutFptr, BufferStart, BufferSize);
|
||
|
goto Done;
|
||
|
}
|
||
|
//
|
||
|
// Now walk the export data
|
||
|
//
|
||
|
Buffer = BufferStart;
|
||
|
BufferEnd = BufferStart + BufferSize;
|
||
|
//
|
||
|
// Dump the header
|
||
|
//
|
||
|
fprintf (OutFptr, "HII dump of file %s\n\n", HiiExportFileName);
|
||
|
NumberOfTables = ((EFI_HII_EXPORT_TABLE *) Buffer)->NumberOfHiiDataTables;
|
||
|
fprintf (OutFptr, "Number of data tables: %d\n", NumberOfTables);
|
||
|
GuidToString (&((EFI_HII_EXPORT_TABLE *) Buffer)->Revision, GuidString);
|
||
|
fprintf (OutFptr, "HII export revision: %s\n", GuidString);
|
||
|
//
|
||
|
// Now walk the data tables
|
||
|
//
|
||
|
Buffer += sizeof (EFI_HII_EXPORT_TABLE);
|
||
|
for (Counter = 0; Counter < NumberOfTables; Counter++) {
|
||
|
DataTableHeader = (EFI_HII_DATA_TABLE *) Buffer;
|
||
|
fprintf (OutFptr, "----------------------------------------------------------\n");
|
||
|
fprintf (OutFptr, " DataTable at offset 0x%08X\n", (int) Buffer - (int) BufferStart);
|
||
|
fprintf (OutFptr, " HII Handle: 0x%08X\n", DataTableHeader->HiiHandle);
|
||
|
GuidToString (&DataTableHeader->PackageGuid, GuidString);
|
||
|
fprintf (OutFptr, " Package GUID: %s\n", GuidString);
|
||
|
fprintf (OutFptr, " Data table size: 0x%08X\n", DataTableHeader->DataTableSize);
|
||
|
fprintf (OutFptr, " IFR data offset: 0x%08X\n", DataTableHeader->IfrDataOffset);
|
||
|
fprintf (OutFptr, " String data offset: 0x%08X\n", DataTableHeader->StringDataOffset);
|
||
|
fprintf (OutFptr, " Variable data offset: 0x%08X\n", DataTableHeader->VariableDataOffset);
|
||
|
fprintf (OutFptr, " Device path offset: 0x%08X\n", DataTableHeader->DevicePathOffset);
|
||
|
fprintf (OutFptr, " Number of variable data: 0x%08X\n", DataTableHeader->NumberOfVariableData);
|
||
|
fprintf (OutFptr, " Number of languages: 0x%08X\n", DataTableHeader->NumberOfLanguages);
|
||
|
//
|
||
|
// Dump strings
|
||
|
//
|
||
|
if (DataTableHeader->StringDataOffset != 0) {
|
||
|
DumpStringPack (
|
||
|
OutFptr,
|
||
|
(EFI_HII_STRING_PACK *) ((char *) DataTableHeader + DataTableHeader->StringDataOffset),
|
||
|
DataTableHeader->StringDataOffset,
|
||
|
6
|
||
|
);
|
||
|
}
|
||
|
//
|
||
|
// Dump IFR
|
||
|
//
|
||
|
if (DataTableHeader->IfrDataOffset != 0) {
|
||
|
DumpIfrPack (
|
||
|
OutFptr,
|
||
|
(EFI_HII_IFR_PACK *) ((char *) DataTableHeader + DataTableHeader->IfrDataOffset),
|
||
|
DataTableHeader->IfrDataOffset,
|
||
|
6
|
||
|
);
|
||
|
}
|
||
|
//
|
||
|
// Dump variables
|
||
|
//
|
||
|
if (DataTableHeader->VariableDataOffset != 0) {
|
||
|
DumpVariablePacks (
|
||
|
OutFptr,
|
||
|
(EFI_HII_VARIABLE_PACK *) ((char *) DataTableHeader + DataTableHeader->VariableDataOffset),
|
||
|
DataTableHeader->NumberOfVariableData,
|
||
|
DataTableHeader->VariableDataOffset,
|
||
|
6
|
||
|
);
|
||
|
}
|
||
|
//
|
||
|
// Dump device path
|
||
|
//
|
||
|
//
|
||
|
// Check position before advancing
|
||
|
//
|
||
|
if ((Buffer + DataTableHeader->DataTableSize < Buffer) || (Buffer + DataTableHeader->DataTableSize > BufferEnd)) {
|
||
|
Error (NULL, 0, 0, HiiExportFileName, "bad data table size at offset 0x%X", (int) Buffer - (int) BufferStart);
|
||
|
goto Done;
|
||
|
}
|
||
|
|
||
|
Buffer += DataTableHeader->DataTableSize;
|
||
|
}
|
||
|
|
||
|
Status = STATUS_SUCCESS;
|
||
|
Done:
|
||
|
if (OutFptr != NULL) {
|
||
|
fclose (OutFptr);
|
||
|
}
|
||
|
|
||
|
if (InFptr != NULL) {
|
||
|
fclose (InFptr);
|
||
|
}
|
||
|
|
||
|
if (BufferStart != NULL) {
|
||
|
free (BufferStart);
|
||
|
}
|
||
|
|
||
|
return Status;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpIfrPack (
|
||
|
FILE *OutFptr,
|
||
|
EFI_HII_IFR_PACK *Pack,
|
||
|
int BaseOffset,
|
||
|
int Indent
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Dump the contents of an IFR pack for debug purposes
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OutFptr - file pointer to which to dump the output
|
||
|
Pack - pointer to IFR pack to dump
|
||
|
BaseOffset - offset from which Pack starts in its parent data table
|
||
|
Indent - indent this many spaces when printing text to OutFptr
|
||
|
|
||
|
Returns:
|
||
|
NA
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_IFR_FORM_SET *IfrFormSet;
|
||
|
char GuidString[100];
|
||
|
if (Pack->Header.Type != EFI_HII_IFR) {
|
||
|
Error (NULL, 0, 0, "found non-IFR pack type at IFR data offset", NULL);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
fprintf (OutFptr, "%*cIFR pack at offset 0x%08X\n", Indent, ' ', BaseOffset);
|
||
|
fprintf (OutFptr, "%*c Length 0x%08X\n", Indent, ' ', Pack->Header.Length);
|
||
|
//
|
||
|
// Get the GUID from the formset
|
||
|
//
|
||
|
IfrFormSet = (EFI_IFR_FORM_SET *) (Pack + 1);
|
||
|
GuidToString (&IfrFormSet->Guid, GuidString);
|
||
|
fprintf (OutFptr, "%*c Variable GUID %s\n", Indent, ' ', GuidString);
|
||
|
//
|
||
|
// Print the IFR formset size, with a note indicating if it's a min (likely stub)
|
||
|
// formset
|
||
|
//
|
||
|
if (Pack->Header.Length == sizeof (EMPTY_FORMSET_PACK)) {
|
||
|
fprintf (
|
||
|
OutFptr,
|
||
|
"%*c IFR formset size 0x%08X (empty formset)\n",
|
||
|
Indent,
|
||
|
' ',
|
||
|
Pack->Header.Length - sizeof (EFI_HII_IFR_PACK)
|
||
|
);
|
||
|
} else {
|
||
|
fprintf (
|
||
|
OutFptr,
|
||
|
"%*c IFR formset size 0x%08X\n",
|
||
|
Indent,
|
||
|
' ',
|
||
|
Pack->Header.Length - sizeof (EFI_HII_IFR_PACK)
|
||
|
);
|
||
|
}
|
||
|
//
|
||
|
// Dump raw bytes -- not much use
|
||
|
//
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpVariablePacks (
|
||
|
FILE *OutFptr,
|
||
|
EFI_HII_VARIABLE_PACK *Pack,
|
||
|
int NumPacks,
|
||
|
int BaseOffset,
|
||
|
int Indent
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Dump the contents of an IFR pack for debug purposes
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OutFptr - file pointer to which to dump the output
|
||
|
Pack - pointer to variable pack to dump
|
||
|
NumPacks - number of packs in Pack[] array
|
||
|
BaseOffset - offset from which Pack starts in its parent data table
|
||
|
Indent - indent this many spaces when printing text to OutFptr
|
||
|
|
||
|
Returns:
|
||
|
NA
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
int Count;
|
||
|
|
||
|
int Len;
|
||
|
char GuidString[100];
|
||
|
|
||
|
for (Count = 0; Count < NumPacks; Count++) {
|
||
|
if (Pack->Header.Type != EFI_HII_VARIABLE) {
|
||
|
Error (NULL, 0, 0, "found non-variable pack type in variable pack array", NULL);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
fprintf (OutFptr, "%*cVariable pack at offset 0x%08X\n", Indent, ' ', BaseOffset);
|
||
|
fprintf (OutFptr, "%*c Length 0x%08X\n", Indent, ' ', Pack->Header.Length);
|
||
|
GuidToString (&Pack->VariableGuid, GuidString);
|
||
|
fprintf (OutFptr, "%*c Variable GUID %s\n", Indent, ' ', GuidString);
|
||
|
fprintf (OutFptr, "%*c Variable Name %S\n", Indent, ' ', (CHAR16 *) (Pack + 1));
|
||
|
Len = sizeof (EFI_HII_VARIABLE_PACK) + Pack->VariableNameLength;
|
||
|
fprintf (OutFptr, "%*c Variable Size 0x%08X\n", Indent, ' ', Pack->Header.Length - Len);
|
||
|
//
|
||
|
// Dump raw bytes
|
||
|
//
|
||
|
DumpRawBytes (OutFptr, (char *) Pack + Len, Pack->Header.Length - Len, Len, Indent + 2);
|
||
|
BaseOffset += Pack->Header.Length;
|
||
|
Pack = (EFI_HII_VARIABLE_PACK *) ((char *) Pack + Pack->Header.Length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpStringPack (
|
||
|
FILE *OutFptr,
|
||
|
EFI_HII_STRING_PACK *Pack,
|
||
|
int BaseOffset,
|
||
|
int Indent
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Dump the contents of a string pack array for debug purposes
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OutFptr - file pointer to which to dump the output
|
||
|
Pack - pointer to string pack array to dump
|
||
|
BaseOffset - offset from which Pack starts in its parent data table
|
||
|
Indent - indent this many spaces when printing text to OutFptr
|
||
|
|
||
|
Returns:
|
||
|
NA
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
int Count;
|
||
|
int *IndexPtr;
|
||
|
CHAR16 *WCPtr;
|
||
|
//
|
||
|
// String pack array is terminated with a zero-length string pack
|
||
|
//
|
||
|
while (Pack->Header.Length > 0) {
|
||
|
if (Pack->Header.Type != EFI_HII_STRING) {
|
||
|
Error (NULL, 0, 0, "found non-string pack type in string pack array", NULL);
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
fprintf (OutFptr, "%*cString pack at offset 0x%08X\n", Indent, ' ', BaseOffset);
|
||
|
fprintf (OutFptr, "%*c Length 0x%08X\n", Indent, ' ', Pack->Header.Length);
|
||
|
fprintf (
|
||
|
OutFptr,
|
||
|
"%*c Language %S\n",
|
||
|
Indent,
|
||
|
' ',
|
||
|
(CHAR16 *) ((char *) Pack + Pack->LanguageNameString)
|
||
|
);
|
||
|
fprintf (
|
||
|
OutFptr,
|
||
|
"%*c Printable Language %S\n",
|
||
|
Indent,
|
||
|
' ',
|
||
|
(CHAR16 *) ((char *) Pack + Pack->PrintableLanguageName)
|
||
|
);
|
||
|
fprintf (OutFptr, "%*c Number of strings 0x%08X\n", Indent, ' ', Pack->NumStringPointers);
|
||
|
fprintf (OutFptr, "%*c Attributes 0x%08X\n", Indent, ' ', Pack->Attributes);
|
||
|
IndexPtr = (int *) (Pack + 1);
|
||
|
//
|
||
|
// Dump string data
|
||
|
//
|
||
|
if (mGlobals.DumpStrings) {
|
||
|
for (Count = 0; Count < (int) Pack->NumStringPointers; Count++) {
|
||
|
fprintf (OutFptr, "%*c String 0x%04X: ", Indent, ' ', Count);
|
||
|
//
|
||
|
// Print raw hex bytes
|
||
|
//
|
||
|
for (WCPtr = (CHAR16 *) ((char *) Pack +*IndexPtr); *WCPtr != 0; WCPtr++) {
|
||
|
fprintf (OutFptr, "%02X ", (unsigned int) *WCPtr);
|
||
|
}
|
||
|
|
||
|
fprintf (OutFptr, "00\n");
|
||
|
IndexPtr++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
BaseOffset += Pack->Header.Length;
|
||
|
Pack = (EFI_HII_STRING_PACK *) ((char *) Pack + Pack->Header.Length);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
TestDumpHiiPack (
|
||
|
FILE *OutFptr,
|
||
|
char *Buffer,
|
||
|
int BufferSize
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
GC_TODO: Add function description
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OutFptr - GC_TODO: add argument description
|
||
|
Buffer - GC_TODO: add argument description
|
||
|
BufferSize - GC_TODO: add argument description
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
GC_TODO: add return values
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_HII_PACK_HEADER *PackHeader;
|
||
|
|
||
|
PackHeader = (EFI_HII_PACK_HEADER *) Buffer;
|
||
|
//
|
||
|
// Check size match
|
||
|
//
|
||
|
if (PackHeader->Length != (unsigned int) BufferSize) {
|
||
|
return ;
|
||
|
}
|
||
|
//
|
||
|
// Check type
|
||
|
//
|
||
|
switch (PackHeader->Type) {
|
||
|
case EFI_HII_STRING:
|
||
|
fprintf (stdout, "Dumping as string pack\n");
|
||
|
DumpStringPack (OutFptr, (EFI_HII_STRING_PACK *) Buffer, 0, 2);
|
||
|
break;
|
||
|
|
||
|
case EFI_HII_IFR:
|
||
|
fprintf (stdout, "Dumping as IFR pack\n");
|
||
|
DumpIfrPack (OutFptr, (EFI_HII_IFR_PACK *) Buffer, 0, 2);
|
||
|
break;
|
||
|
|
||
|
case EFI_HII_VARIABLE:
|
||
|
fprintf (stdout, "Dumping as IFR pack\n");
|
||
|
DumpVariablePacks (OutFptr, (EFI_HII_VARIABLE_PACK *) Buffer, 1, 0, 2);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
DumpRawBytes (
|
||
|
FILE *OutFptr,
|
||
|
char *Buffer,
|
||
|
int Count,
|
||
|
int BaseOffset,
|
||
|
int Indent
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
GC_TODO: Add function description
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
OutFptr - GC_TODO: add argument description
|
||
|
Buffer - GC_TODO: add argument description
|
||
|
Count - GC_TODO: add argument description
|
||
|
BaseOffset - GC_TODO: add argument description
|
||
|
Indent - GC_TODO: add argument description
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
GC_TODO: add return values
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
int Counter;
|
||
|
|
||
|
for (Counter = 0; Counter < Count; Counter++) {
|
||
|
if ((Counter & 0xF) == 0) {
|
||
|
if (Counter != 0) {
|
||
|
fprintf (OutFptr, "\n%*c%08X ", Indent, ' ', Counter);
|
||
|
} else {
|
||
|
fprintf (OutFptr, "\n%*c%08X ", Indent, ' ', Counter);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fprintf (OutFptr, "%02X ", (unsigned int) (unsigned char) *Buffer);
|
||
|
Buffer++;
|
||
|
}
|
||
|
|
||
|
fprintf (OutFptr, "\n");
|
||
|
}
|
||
|
|
||
|
void
|
||
|
GuidToString (
|
||
|
EFI_GUID *Guid,
|
||
|
char *Str
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Given a pointer to a GUID, sprint the value into a string
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Guid - pointer to input GUID
|
||
|
Str - pointer to outgoing printed GUID value
|
||
|
|
||
|
Returns:
|
||
|
NA
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
sprintf (
|
||
|
Str,
|
||
|
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
|
||
|
Guid->Data1,
|
||
|
Guid->Data2,
|
||
|
Guid->Data3,
|
||
|
Guid->Data4[0],
|
||
|
Guid->Data4[1],
|
||
|
Guid->Data4[2],
|
||
|
Guid->Data4[3],
|
||
|
Guid->Data4[4],
|
||
|
Guid->Data4[5],
|
||
|
Guid->Data4[6],
|
||
|
Guid->Data4[7]
|
||
|
);
|
||
|
}
|
||
|
|
||
|
int
|
||
|
FindFilesCallback (
|
||
|
char *FoundFileName
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Callback function used to get files matching a file mask. This
|
||
|
function is called when the command-line arguments to this utility
|
||
|
are parsed and the user specified "-s Path FileMask" to process
|
||
|
all HII export files in Path and its subdirectories that match
|
||
|
FileMask.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
FoundFileName - name of file found.
|
||
|
|
||
|
Returns:
|
||
|
non-zero - caller should halt processing
|
||
|
zero - no problems while processing FoundFileName
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
FILE_NAME_LIST *FileName;
|
||
|
|
||
|
FILE_NAME_LIST *TempFileName;
|
||
|
|
||
|
FileName = (FILE_NAME_LIST *) malloc (sizeof (FILE_NAME_LIST));
|
||
|
if (FileName == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
memset ((void *) FileName, 0, sizeof (FILE_NAME_LIST));
|
||
|
strcpy (FileName->FileName, FoundFileName);
|
||
|
if (mGlobals.HiiExportFileNames == NULL) {
|
||
|
mGlobals.HiiExportFileNames = FileName;
|
||
|
} else {
|
||
|
//
|
||
|
// Add to the end of the list
|
||
|
//
|
||
|
for (TempFileName = mGlobals.HiiExportFileNames; TempFileName->Next != NULL; TempFileName = TempFileName->Next)
|
||
|
;
|
||
|
TempFileName->Next = FileName;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
STATUS
|
||
|
ProcessArgs (
|
||
|
int Argc,
|
||
|
char *Argv[]
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Process the command line arguments
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
As per standard C main()
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
STATUS_SUCCESS - if successful
|
||
|
STATUS_ERROR - otherwise
|
||
|
|
||
|
--*/
|
||
|
// GC_TODO: Argc - add argument and description to function comment
|
||
|
// GC_TODO: ] - add argument and description to function comment
|
||
|
{
|
||
|
FILE_NAME_LIST *FileName;
|
||
|
|
||
|
FILE_NAME_LIST *TempFileName;
|
||
|
FILE *InFptr;
|
||
|
EFI_HII_PACK_HEADER PackHeader;
|
||
|
|
||
|
memset ((void *) &mGlobals, 0, sizeof (mGlobals));
|
||
|
//
|
||
|
// Skip program name
|
||
|
//
|
||
|
Argc--;
|
||
|
Argv++;
|
||
|
|
||
|
if (Argc == 0) {
|
||
|
Usage ();
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
//
|
||
|
// First arg must be one of create, merge, defaults, or dump
|
||
|
//
|
||
|
if (_stricmp (Argv[0], "create") == 0) {
|
||
|
mGlobals.Mode = MODE_CREATE_HII_EXPORT;
|
||
|
} else if (_stricmp (Argv[0], "merge") == 0) {
|
||
|
mGlobals.Mode = MODE_MERGE_HII_EXPORTS;
|
||
|
} else if (_stricmp (Argv[0], "defaults") == 0) {
|
||
|
mGlobals.Mode = MODE_EMIT_DEFAULTS;
|
||
|
} else if (_stricmp (Argv[0], "dump") == 0) {
|
||
|
mGlobals.Mode = MODE_DUMP_HII_EXPORT;
|
||
|
} else if (strcmp (Argv[0], "-?") == 0) {
|
||
|
Usage ();
|
||
|
return STATUS_ERROR;
|
||
|
} else {
|
||
|
Error (NULL, 0, 0, Argv[0], "unrecognized mode");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
Argv++;
|
||
|
Argc--;
|
||
|
//
|
||
|
// Process until no more args.
|
||
|
//
|
||
|
while (Argc > 0) {
|
||
|
if (_stricmp (Argv[0], "-o") == 0) {
|
||
|
//
|
||
|
// -o option to specify the output file
|
||
|
//
|
||
|
if ((Argc <= 1) || (Argv[1][0] == '-')) {
|
||
|
Error (UTILITY_NAME, 0, 0, Argv[0], "missing output file name");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
if (mGlobals.OutputFileName[0] == 0) {
|
||
|
mGlobals.OutputFileName[MAX_PATH - 1] = 0;
|
||
|
strncpy (mGlobals.OutputFileName, Argv[1], MAX_PATH - 1);
|
||
|
} else {
|
||
|
Error (UTILITY_NAME, 0, 0, Argv[1], "-o option already specified with '%s'", mGlobals.OutputFileName);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
Argv++;
|
||
|
Argc--;
|
||
|
} else if (_stricmp (Argv[0], "-mfg") == 0) {
|
||
|
mGlobals.MfgFlag = 1;
|
||
|
} else if (_stricmp (Argv[0], "-g") == 0) {
|
||
|
//
|
||
|
// -g option to specify the guid
|
||
|
//
|
||
|
if ((Argc <= 1) || (Argv[1][0] == '-')) {
|
||
|
Error (UTILITY_NAME, 0, 0, Argv[0], "missing GUID");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
StringToGuid (Argv[1], &mGlobals.Guid);
|
||
|
mGlobals.GuidSpecified = 1;
|
||
|
Argv++;
|
||
|
Argc--;
|
||
|
} else if (_stricmp (Argv[0], "-v") == 0) {
|
||
|
mGlobals.Verbose = 1;
|
||
|
} else if (_stricmp (Argv[0], "-p") == 0) {
|
||
|
//
|
||
|
// -p option to specify an input pack file. Only valid for 'create' mode
|
||
|
//
|
||
|
if (mGlobals.Mode != MODE_CREATE_HII_EXPORT) {
|
||
|
Error (NULL, 0, 0, Argv[0], "option only valid in 'create' mode");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
if ((Argc <= 1) || (Argv[1][0] == '-')) {
|
||
|
Error (UTILITY_NAME, 0, 0, Argv[0], "missing pack file name");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
//
|
||
|
// Consume arguments until next -arg or end
|
||
|
//
|
||
|
do {
|
||
|
Argv++;
|
||
|
Argc--;
|
||
|
//
|
||
|
// Open the file, read the pack header, and figure out what type of
|
||
|
// HII pack it is.
|
||
|
//
|
||
|
if ((InFptr = fopen (Argv[0], "rb")) == NULL) {
|
||
|
Error (NULL, 0, 0, Argv[0], "failed to open input HII pack file for reading");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
if (fread (&PackHeader, sizeof (EFI_HII_PACK_HEADER), 1, InFptr) != 1) {
|
||
|
Error (NULL, 0, 0, Argv[0], "failed to read pack header from input HII pack file");
|
||
|
fclose (InFptr);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
fclose (InFptr);
|
||
|
if ((PackHeader.Type != EFI_HII_STRING) &&
|
||
|
(PackHeader.Type != EFI_HII_IFR) &&
|
||
|
(PackHeader.Type != EFI_HII_VARIABLE)
|
||
|
) {
|
||
|
Error (NULL, 0, 0, Argv[0], "unsupported HII pack type 0x%X", (unsigned int) PackHeader.Type);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
//
|
||
|
// Add this file name to our list of pack files
|
||
|
//
|
||
|
FileName = (FILE_NAME_LIST *) malloc (sizeof (FILE_NAME_LIST));
|
||
|
if (FileName == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
memset ((void *) FileName, 0, sizeof (FILE_NAME_LIST));
|
||
|
FileName->Tag = (int) PackHeader.Type;
|
||
|
strcpy (FileName->FileName, Argv[0]);
|
||
|
if (mGlobals.PackFileNames == NULL) {
|
||
|
mGlobals.PackFileNames = FileName;
|
||
|
} else {
|
||
|
//
|
||
|
// Add to the end of the list
|
||
|
//
|
||
|
for (TempFileName = mGlobals.PackFileNames; TempFileName->Next != NULL; TempFileName = TempFileName->Next)
|
||
|
;
|
||
|
TempFileName->Next = FileName;
|
||
|
}
|
||
|
} while ((Argc > 1) && (Argv[1][0] != '-'));
|
||
|
} else if (_stricmp (Argv[0], "-noemptyvarpacks") == 0) {
|
||
|
mGlobals.NoEmptyVarPacks = 1;
|
||
|
} else if (_stricmp (Argv[0], "-novarpacks") == 0) {
|
||
|
mGlobals.NoVarPacks = 1;
|
||
|
} else if (_stricmp (Argv[0], "-x") == 0) {
|
||
|
//
|
||
|
// -x option to specify an input HII export file name. Not valid for 'create' mode
|
||
|
//
|
||
|
if (mGlobals.Mode == MODE_CREATE_HII_EXPORT) {
|
||
|
Error (NULL, 0, 0, Argv[0], "option is not valid in 'create' mode");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
if ((Argc <= 1) || (Argv[1][0] == '-')) {
|
||
|
Error (UTILITY_NAME, 0, 0, Argv[0], "missing HII export input file name");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
//
|
||
|
// Consume arguments until next -arg or end
|
||
|
//
|
||
|
do {
|
||
|
Argv++;
|
||
|
Argc--;
|
||
|
//
|
||
|
// Add this file name to our list of export files
|
||
|
//
|
||
|
FileName = (FILE_NAME_LIST *) malloc (sizeof (FILE_NAME_LIST));
|
||
|
if (FileName == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
memset ((void *) FileName, 0, sizeof (FILE_NAME_LIST));
|
||
|
strcpy (FileName->FileName, Argv[0]);
|
||
|
if (mGlobals.HiiExportFileNames == NULL) {
|
||
|
mGlobals.HiiExportFileNames = FileName;
|
||
|
} else {
|
||
|
//
|
||
|
// Add to the end of the list
|
||
|
//
|
||
|
for (TempFileName = mGlobals.HiiExportFileNames;
|
||
|
TempFileName->Next != NULL;
|
||
|
TempFileName = TempFileName->Next
|
||
|
)
|
||
|
;
|
||
|
TempFileName->Next = FileName;
|
||
|
}
|
||
|
} while ((Argc > 1) && (Argv[1][0] != '-'));
|
||
|
} else if (_stricmp (Argv[0], "-dumpstrings") == 0) {
|
||
|
mGlobals.DumpStrings = 1;
|
||
|
} else if (_stricmp (Argv[0], "-s") == 0) {
|
||
|
//
|
||
|
// -s option to specify input HII export files using a path and file mask.
|
||
|
// Only valid in merge mode
|
||
|
//
|
||
|
if (mGlobals.Mode != MODE_MERGE_HII_EXPORTS) {
|
||
|
Error (NULL, 0, 0, Argv[0], "option only valid in 'merge' mode");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
if ((Argc <= 1) || (Argv[1][0] == '-')) {
|
||
|
Error (UTILITY_NAME, 0, 0, Argv[0], "missing root directory name");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
if ((Argc <= 2) || (Argv[2][0] == '-')) {
|
||
|
Error (UTILITY_NAME, 0, 0, Argv[0], "missing file mask");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
//
|
||
|
// Call our function to process the directory and file mask. If
|
||
|
// the directory does not start with c:\, then prepend cwd to it.
|
||
|
//
|
||
|
if (FindFiles (Argv[1], Argv[2], FindFilesCallback)) {
|
||
|
Error (NULL, 0, 0, "failed to process matching files", "%s\\%s", Argv[1], Argv[2]);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
Argv += 2;
|
||
|
Argc -= 2;
|
||
|
} else if (_stricmp (Argv[0], "-p") == 0) {
|
||
|
//
|
||
|
// -p option to specify an input pack file. Only valid for 'create' mode
|
||
|
//
|
||
|
if (mGlobals.Mode != MODE_CREATE_HII_EXPORT) {
|
||
|
Error (NULL, 0, 0, Argv[0], "option only valid in 'create' mode");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
if ((Argc <= 1) || (Argv[1][0] == '-')) {
|
||
|
Error (UTILITY_NAME, 0, 0, Argv[0], "missing pack file name");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
//
|
||
|
// Consume arguments until next -arg or end
|
||
|
//
|
||
|
do {
|
||
|
Argv++;
|
||
|
Argc--;
|
||
|
//
|
||
|
// Open the file, read the pack header, and figure out what type of
|
||
|
// HII pack it is.
|
||
|
//
|
||
|
if ((InFptr = fopen (Argv[0], "rb")) == NULL) {
|
||
|
Error (NULL, 0, 0, Argv[0], "failed to open input HII pack file for reading");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
if (fread (&PackHeader, sizeof (EFI_HII_PACK_HEADER), 1, InFptr) != 1) {
|
||
|
Error (NULL, 0, 0, Argv[0], "failed to read pack header from input HII pack file");
|
||
|
fclose (InFptr);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
fclose (InFptr);
|
||
|
if ((PackHeader.Type != EFI_HII_STRING) &&
|
||
|
(PackHeader.Type != EFI_HII_IFR) &&
|
||
|
(PackHeader.Type != EFI_HII_VARIABLE)
|
||
|
) {
|
||
|
Error (NULL, 0, 0, Argv[0], "unsupported HII pack type 0x%X", (unsigned int) PackHeader.Type);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
//
|
||
|
// Add this file name to our list of pack files
|
||
|
//
|
||
|
FileName = (FILE_NAME_LIST *) malloc (sizeof (FILE_NAME_LIST));
|
||
|
if (FileName == NULL) {
|
||
|
Error (NULL, 0, 0, "memory allocation failure", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
memset ((void *) FileName, 0, sizeof (FILE_NAME_LIST));
|
||
|
FileName->Tag = (int) PackHeader.Type;
|
||
|
strcpy (FileName->FileName, Argv[0]);
|
||
|
if (mGlobals.PackFileNames == NULL) {
|
||
|
mGlobals.PackFileNames = FileName;
|
||
|
} else {
|
||
|
//
|
||
|
// Add to the end of the list
|
||
|
//
|
||
|
for (TempFileName = mGlobals.PackFileNames; TempFileName->Next != NULL; TempFileName = TempFileName->Next)
|
||
|
;
|
||
|
TempFileName->Next = FileName;
|
||
|
}
|
||
|
} while ((Argc > 1) && (Argv[1][0] != '-'));
|
||
|
} else {
|
||
|
Error (NULL, 0, 0, Argv[0], "unrecognized option");
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
|
||
|
Argv++;
|
||
|
Argc--;
|
||
|
}
|
||
|
//
|
||
|
// All modes except 'defaults' requires an output file name
|
||
|
//
|
||
|
if (mGlobals.Mode != MODE_EMIT_DEFAULTS) {
|
||
|
if (mGlobals.OutputFileName[0] == 0) {
|
||
|
Error (NULL, 0, 0, "must specify '-o OutputFileName'", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
//
|
||
|
// If merging, then you have to specify at least one HII export files.
|
||
|
// We support specifying only one file in case you want to take an export file
|
||
|
// and emit a copy with different (for example, manufacturing) defaults.
|
||
|
//
|
||
|
if (mGlobals.Mode == MODE_MERGE_HII_EXPORTS) {
|
||
|
if (mGlobals.HiiExportFileNames == NULL) {
|
||
|
Error (NULL, 0, 0, "must specify at least one HII export file in 'merge' mode", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
} else if (mGlobals.Mode == MODE_CREATE_HII_EXPORT) {
|
||
|
//
|
||
|
// Must have specified at least one HII pack file
|
||
|
//
|
||
|
if (mGlobals.PackFileNames == NULL) {
|
||
|
Error (NULL, 0, 0, "must specify at least one input HII pack file in 'create' mode", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// Must have specified an input HII export file name
|
||
|
//
|
||
|
if (mGlobals.HiiExportFileNames == NULL) {
|
||
|
Error (NULL, 0, 0, "must specify at least one '-x HiiExportFileName'", NULL);
|
||
|
return STATUS_ERROR;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
static
|
||
|
void
|
||
|
Usage (
|
||
|
VOID
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Print usage information for this utility.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
Nothing.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
int Index;
|
||
|
const char *Str[] = {
|
||
|
UTILITY_NAME" "UTILITY_VERSION" - Create/Dump HII Database Files Utility",
|
||
|
" Copyright (C), 2004 - 2008 Intel Corporation",
|
||
|
#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
|
||
|
" Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
|
||
|
#endif
|
||
|
"",
|
||
|
"Usage:",
|
||
|
" "UTILITY_NAME " [MODE] [OPTION]",
|
||
|
"Modes:",
|
||
|
" create create an HII export file from one or more HII pack files",
|
||
|
" merge merge two or more HII export files into one HII export file",
|
||
|
" defaults emit variable defaults from an input HII export file",
|
||
|
" dump ASCII dump the contents of an HII export file",
|
||
|
"Options for all modes:",
|
||
|
" -o FileName write output to FileName",
|
||
|
" -mfg use manufacturing defaults from IFR rather than standard defaults",
|
||
|
" -g GUID use GUID for a package GUID in the data tables where applicable",
|
||
|
" -v verbose operation",
|
||
|
"Options for 'create' mode:",
|
||
|
" -p PackFileName(s) include contents of HII pack file PackFileName",
|
||
|
" in the output file",
|
||
|
" -novarpacks don't emit variable packs to the output file",
|
||
|
"Options for 'merge' mode:",
|
||
|
" -x HiiExportFileName(s) include contents of HII export file",
|
||
|
" HiiExportFileName in the output file",
|
||
|
" -s Path FileMask include all matching HII export files in Path",
|
||
|
" and its subdirectories in the output file.",
|
||
|
" If Path does not begin with the form C:\\, then",
|
||
|
" it is assumed to be relative to the current working",
|
||
|
" directory. FileMask may contain wildcard characters.",
|
||
|
"Options for 'defaults' mode:",
|
||
|
" -x HiiExportFileName emit defaults from all variables referenced",
|
||
|
" in input file HiiExportFileName",
|
||
|
" -noemptyvarpacks don't emit variable packs for 0-length variables",
|
||
|
"Options for 'dump' mode:",
|
||
|
" -x HiiExportFileName dump contents of input file HiiExportFileName",
|
||
|
" -dumpstrings dump string data",
|
||
|
NULL
|
||
|
};
|
||
|
for (Index = 0; Str[Index] != NULL; Index++) {
|
||
|
fprintf (stdout, "%s\n", Str[Index]);
|
||
|
}
|
||
|
}
|