summaryrefslogtreecommitdiff
path: root/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack
diff options
context:
space:
mode:
Diffstat (limited to 'EdkCompatibilityPkg/Sample/Tools/Source/HiiPack')
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/FindFiles.c208
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.c2561
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.h63
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/IfrParse.c2533
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/IfrParse.h267
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/Makefile103
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/StringParse.c244
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/StringParse.h125
8 files changed, 6104 insertions, 0 deletions
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/FindFiles.c b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/FindFiles.c
new file mode 100644
index 0000000000..b63a1f8347
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/FindFiles.c
@@ -0,0 +1,208 @@
+/*++
+
+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:
+
+ FindFiles.c
+
+Abstract:
+
+ OS-specific functions to assist in finding files in
+ subdirectories.
+
+--*/
+
+#include <windows.h>
+#include <direct.h>
+//
+// #include <io.h> // for _chmod()
+//
+#include <sys/stat.h>
+//
+// #include <errno.h> // for errno
+//
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#include "HiiPack.h"
+
+extern
+void
+Error (
+ char *Name,
+ UINT32 LineNumber,
+ UINT32 MessageCode,
+ char *Text,
+ char *MsgFmt,
+ ...
+ );
+
+static
+int
+ProcessDirectory (
+ char *RootDirectory,
+ char *FileMask,
+ FIND_FILE_CALLBACK Callback
+ );
+
+/*****************************************************************************/
+int
+FindFiles (
+ char *RootDirectory,
+ char *FileMask,
+ FIND_FILE_CALLBACK Callback
+ )
+/*++
+
+Routine Description:
+ Find files of a given name under a root directory
+
+Arguments:
+ RootDirectory - base directory -- look in this directory and
+ all its subdirectories for files matching FileMask.
+ FileMask - file mask of files to find
+ Callback - function to call for each file found
+
+Returns:
+
+--*/
+{
+ char FullPath[MAX_PATH];
+ //
+ // If RootDirectory is relative, then append to cwd.
+ //
+ if (isalpha (RootDirectory[0]) && (RootDirectory[1] == ':')) {
+ strcpy (FullPath, RootDirectory);
+ } else {
+ //
+ // Get current working directory
+ //
+ if (_getcwd (FullPath, sizeof (FullPath)) == NULL) {
+ Error (NULL, 0, 0, "failed to get current working directory", NULL);
+ return 1;
+ }
+ //
+ // Append the relative path they passed in
+ //
+ if (FullPath[strlen (FullPath) - 1] != '\\') {
+ strcat (FullPath, "\\");
+ }
+
+ strcat (FullPath, RootDirectory);
+ }
+
+ if (FullPath[strlen (FullPath) - 1] == '\\') {
+ FullPath[strlen (FullPath) - 1] = 0;
+ }
+ //
+ // Process the directory
+ //
+ return ProcessDirectory (FullPath, FileMask, Callback);
+}
+
+static
+int
+ProcessDirectory (
+ char *RootDirectory,
+ char *FileMask,
+ FIND_FILE_CALLBACK Callback
+ )
+/*++
+
+Routine Description:
+ Process a directory to find all files matching a given file mask
+
+Arguments:
+ RootDirectory - base directory -- look in this directory and
+ all its subdirectories for files matching FileMask.
+ FileMask - file mask of files to find
+ Callback - function to call for each file found
+
+Returns:
+
+--*/
+{
+ HANDLE Handle;
+ WIN32_FIND_DATA FindData;
+ char TempName[MAX_PATH];
+
+ Handle = INVALID_HANDLE_VALUE;
+ //
+ // Concatenate the filemask to the directory to create the full
+ // path\mask path name.
+ //
+ strcpy (TempName, RootDirectory);
+ strcat (TempName, "\\");
+ strcat (TempName, FileMask);
+ memset (&FindData, 0, sizeof (FindData));
+ Handle = FindFirstFile (TempName, &FindData);
+ if (Handle != INVALID_HANDLE_VALUE) {
+ do {
+ if ((FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+ strcpy (TempName, RootDirectory);
+ strcat (TempName, "\\");
+ strcat (TempName, FindData.cFileName);
+ if (Callback (TempName) != 0) {
+ goto Done;
+ }
+ }
+ } while (FindNextFile (Handle, &FindData));
+ }
+
+ if (Handle != INVALID_HANDLE_VALUE) {
+ FindClose (Handle);
+ Handle = INVALID_HANDLE_VALUE;
+ }
+ //
+ // Now create a *.* file mask to get all subdirectories and recursive call this
+ // function to handle each one found.
+ //
+ strcpy (TempName, RootDirectory);
+ strcat (TempName, "\\*.*");
+ memset (&FindData, 0, sizeof (FindData));
+ Handle = FindFirstFile (TempName, &FindData);
+ //
+ // Loop until no more files/directories
+ //
+ if (Handle != INVALID_HANDLE_VALUE) {
+ do {
+ if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+ //
+ // Make sure it's not "." or ".."
+ //
+ if ((strcmp (FindData.cFileName, ".") != 0) && (strcmp (FindData.cFileName, "..") != 0)) {
+ //
+ // Found a valid directory. Put it all together and make a recursive call
+ // to process it.
+ //
+ strcpy (TempName, RootDirectory);
+ strcat (TempName, "\\");
+ strcat (TempName, FindData.cFileName);
+ if (ProcessDirectory (TempName, FileMask, Callback) != 0) {
+ goto Done;
+ }
+ }
+ }
+ } while (FindNextFile (Handle, &FindData));
+ }
+
+Done:
+ //
+ // Free the handle
+ //
+ if (Handle != INVALID_HANDLE_VALUE) {
+ FindClose (Handle);
+ }
+
+ return 0;
+}
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.c b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.c
new file mode 100644
index 0000000000..70b88279d2
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.c
@@ -0,0 +1,2561 @@
+/*++
+
+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]);
+ }
+}
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.h b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.h
new file mode 100644
index 0000000000..e9fa66b759
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.h
@@ -0,0 +1,63 @@
+/*++
+
+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.h
+
+Abstract:
+
+ Common defines and prototypes for the HII pack tool.
+
+--*/
+
+#ifndef _HII_PACK_H_
+#define _HII_PACK_H_
+
+#define DEFAULT_VARIABLE_NAME_L L"Setup"
+#define DEFAULT_VARIABLE_NAME "Setup"
+
+#define MAX_VARIABLE_NAME 256
+#define FIRST_HII_PACK_HANDLE 1
+
+typedef
+int
+(*FIND_FILE_CALLBACK) (
+ char *FileName
+ );
+
+extern
+int
+FindFiles (
+ char *RootDirectory,
+ char *FileMask,
+ FIND_FILE_CALLBACK Callback
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ RootDirectory - GC_TODO: add argument description
+ FileMask - GC_TODO: add argument description
+ Callback - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif // #ifndef _HII_PACK_H_
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/IfrParse.c b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/IfrParse.c
new file mode 100644
index 0000000000..e69af5c259
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/IfrParse.c
@@ -0,0 +1,2533 @@
+/*++
+
+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:
+
+ IfrParse.c
+
+Abstract:
+
+ Routines for parsing and managing HII IFR packs.
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "Tiano.h"
+#include "EfiUtilityMsgs.h"
+#include "EfiInternalFormRepresentation.h"
+#include "Hii.h"
+#include "IfrParse.h"
+#include "HiiPack.h"
+
+typedef struct _VARIABLE_STORE_ENTRY {
+ struct _VARIABLE_STORE_ENTRY *Next;
+ CHAR8 VarName[MAX_VARIABLE_NAME];
+ char *VarBuffer;
+ int VarBufferSize;
+ EFI_HII_VARIABLE_PACK *VarPack;
+ int VarPackSize;
+} VARIABLE_STORE_ENTRY;
+
+typedef STATUS (*IFR_PARSE_FUNCTION) (IFR_PARSE_CONTEXT * Context);
+
+typedef struct {
+ INT8 *Name;
+ INT32 Size;
+ IFR_PARSE_FUNCTION Parse;
+} IFR_PARSE_TABLE_ENTRY;
+
+static
+STATUS
+IfrParse01 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse02 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse03 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse05 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse06 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse07 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse08 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse09 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse0A (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse0B (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse0C (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse0D (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse0E (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse0F (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse10 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse11 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse12 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse13 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse14 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse15 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse16 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse17 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse18 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse19 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse1A (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse1B (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse1C (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse1D (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse1E (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse1F (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse20 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse21 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse22 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse23 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse24 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse25 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse26 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse27 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse28 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse29 (
+ IFR_PARSE_CONTEXT *Context
+ );
+static
+STATUS
+IfrParse2A (
+ IFR_PARSE_CONTEXT *Context
+ );
+
+static const IFR_PARSE_TABLE_ENTRY mIfrParseTable[] = {
+ {
+ 0,
+ 0,
+ NULL
+ }, // invalid
+ {
+ "EFI_IFR_FORM",
+ sizeof (EFI_IFR_FORM),
+ IfrParse01
+ },
+ {
+ "EFI_IFR_SUBTITLE",
+ sizeof (EFI_IFR_SUBTITLE),
+ IfrParse02
+ },
+ {
+ "EFI_IFR_TEXT",
+ -6,
+ IfrParse03
+ }, // sizeof (EFI_IFR_TEXT) },
+ {
+ "unused 0x04 opcode",
+ 0,
+ NULL
+ }, // EFI_IFR_GRAPHIC_OP
+ {
+ "EFI_IFR_ONE_OF",
+ sizeof (EFI_IFR_ONE_OF),
+ IfrParse05
+ },
+ {
+ "EFI_IFR_CHECK_BOX",
+ sizeof (EFI_IFR_CHECK_BOX),
+ IfrParse06
+ },
+ {
+ "EFI_IFR_NUMERIC",
+ sizeof (EFI_IFR_NUMERIC),
+ IfrParse07
+ },
+ {
+ "EFI_IFR_PASSWORD",
+ sizeof (EFI_IFR_PASSWORD),
+ IfrParse08
+ },
+ {
+ "EFI_IFR_ONE_OF_OPTION",
+ sizeof (EFI_IFR_ONE_OF_OPTION),
+ IfrParse09
+ },
+ {
+ "EFI_IFR_SUPPRESS",
+ sizeof (EFI_IFR_SUPPRESS),
+ IfrParse0A
+ },
+ {
+ "EFI_IFR_END_FORM",
+ sizeof (EFI_IFR_END_FORM),
+ IfrParse0B
+ },
+ {
+ "EFI_IFR_HIDDEN",
+ sizeof (EFI_IFR_HIDDEN),
+ IfrParse0C
+ },
+ {
+ "EFI_IFR_END_FORM_SET",
+ sizeof (EFI_IFR_END_FORM_SET),
+ IfrParse0D
+ },
+ {
+ "EFI_IFR_FORM_SET",
+ sizeof (EFI_IFR_FORM_SET),
+ IfrParse0E
+ },
+ {
+ "EFI_IFR_REF",
+ sizeof (EFI_IFR_REF),
+ IfrParse0F
+ },
+ {
+ "EFI_IFR_END_ONE_OF",
+ sizeof (EFI_IFR_END_ONE_OF),
+ IfrParse10
+ },
+ {
+ "EFI_IFR_INCONSISTENT",
+ sizeof (EFI_IFR_INCONSISTENT),
+ IfrParse11
+ },
+ {
+ "EFI_IFR_EQ_ID_VAL",
+ sizeof (EFI_IFR_EQ_ID_VAL),
+ IfrParse12
+ },
+ {
+ "EFI_IFR_EQ_ID_ID",
+ sizeof (EFI_IFR_EQ_ID_ID),
+ IfrParse13
+ },
+ {
+ "EFI_IFR_EQ_ID_LIST",
+ -(int) (sizeof (EFI_IFR_EQ_ID_LIST)),
+ IfrParse14
+ },
+ {
+ "EFI_IFR_AND",
+ sizeof (EFI_IFR_AND),
+ IfrParse15
+ },
+ {
+ "EFI_IFR_OR",
+ sizeof (EFI_IFR_OR),
+ IfrParse16
+ },
+ {
+ "EFI_IFR_NOT",
+ sizeof (EFI_IFR_NOT),
+ IfrParse17
+ },
+ {
+ "EFI_IFR_END_IF",
+ sizeof (EFI_IFR_END_IF),
+ IfrParse18
+ },
+ {
+ "EFI_IFR_GRAYOUT",
+ sizeof (EFI_IFR_GRAYOUT),
+ IfrParse19
+ },
+ {
+ "EFI_IFR_DATE",
+ sizeof (EFI_IFR_DATE) / 3,
+ IfrParse1A
+ },
+ {
+ "EFI_IFR_TIME",
+ sizeof (EFI_IFR_TIME) / 3,
+ IfrParse1B
+ },
+ {
+ "EFI_IFR_STRING",
+ sizeof (EFI_IFR_STRING),
+ IfrParse1C
+ },
+ {
+ "EFI_IFR_LABEL",
+ sizeof (EFI_IFR_LABEL),
+ IfrParse1D
+ },
+ {
+ "EFI_IFR_SAVE_DEFAULTS",
+ sizeof (EFI_IFR_SAVE_DEFAULTS),
+ IfrParse1E
+ },
+ {
+ "EFI_IFR_RESTORE_DEFAULTS",
+ sizeof (EFI_IFR_RESTORE_DEFAULTS),
+ IfrParse1F
+ },
+ {
+ "EFI_IFR_BANNER",
+ sizeof (EFI_IFR_BANNER),
+ IfrParse20
+ },
+ {
+ "EFI_IFR_INVENTORY",
+ sizeof (EFI_IFR_INVENTORY),
+ IfrParse21
+ },
+ {
+ "EFI_IFR_EQ_VAR_VAL_OP",
+ sizeof (EFI_IFR_EQ_VAR_VAL),
+ IfrParse22
+ },
+ {
+ "EFI_IFR_ORDERED_LIST_OP",
+ sizeof (EFI_IFR_ORDERED_LIST),
+ IfrParse23
+ },
+ {
+ "EFI_IFR_VARSTORE_OP",
+ -(int) (sizeof (EFI_IFR_VARSTORE)),
+ IfrParse24
+ },
+ {
+ "EFI_IFR_VARSTORE_SELECT_OP",
+ sizeof (EFI_IFR_VARSTORE_SELECT),
+ IfrParse25
+ },
+ {
+ "EFI_IFR_VARSTORE_SELECT_PAIR_OP",
+ sizeof (EFI_IFR_VARSTORE_SELECT_PAIR),
+ IfrParse26
+ },
+ {
+ "EFI_IFR_TRUE",
+ sizeof (EFI_IFR_TRUE),
+ IfrParse27
+ },
+ {
+ "EFI_IFR_FALSE",
+ sizeof (EFI_IFR_FALSE),
+ IfrParse28
+ },
+ {
+ "EFI_IFR_GT",
+ sizeof (EFI_IFR_GT),
+ IfrParse29
+ },
+ {
+ "EFI_IFR_GE",
+ sizeof (EFI_IFR_GE),
+ IfrParse2A
+ },
+};
+#define PARSE_TABLE_ENTRIES (sizeof (mIfrParseTable) / sizeof (mIfrParseTable[0]))
+
+static
+STATUS
+GetVarStoreInfo (
+ IFR_PARSE_CONTEXT *Context,
+ UINT16 VarId,
+ EFI_GUID **VarStoreGuid,
+ char **VarStoreName
+ );
+
+static
+void
+FreeVarStores (
+ VOID
+ );
+
+static
+STATUS
+CreateVarStore (
+ EFI_GUID *VarGuid,
+ CHAR8 *VarName,
+ int VarStoreSize
+ );
+
+static
+STATUS
+SetDefaults (
+ IFR_PARSE_CONTEXT *Context,
+ UINT32 MfgDefaults
+ );
+
+//
+// Globals
+//
+static IFR_PARSE_CONTEXT *mParseContext = NULL;
+static VARIABLE_STORE_ENTRY *mVariableStores = NULL;
+static int BreakOnOpcodeTag = 0;
+static int OpcodeTag = 1;
+
+/*****************************************************************************/
+STATUS
+IfrParseCheck (
+ char *Buffer,
+ long BufferSize
+ )
+/*++
+
+Routine Description:
+
+ Check a buffer to ensure that is is parseable IFR
+
+Arguments:
+
+ Buffer - pointer to raw IFR bytes
+ BufferSize - size of IFR pointed to by Buffer
+
+Returns:
+
+ STATUS_SUCCESS if successful
+ STATUS_ERROR otherwise
+
+--*/
+{
+ char *Start;
+
+ char *End;
+
+ char *Pos;
+ EFI_IFR_OP_HEADER *OpHeader;
+ char *FileName;
+ FileName = "";
+ //
+ // Walk the list of IFR statements in the IFR pack
+ //
+ Start = Buffer;
+ Pos = Buffer;
+ End = Start + BufferSize;
+ while ((Pos >= Start) && (Pos < End)) {
+ OpHeader = (EFI_IFR_OP_HEADER *) Pos;
+ //
+ // Check range on size
+ //
+ if (Pos + OpHeader->Length > End) {
+ Error (NULL, 0, 0, FileName, "invalid IFR opcode size at offset 0x%X", (int) Pos - (int) Start);
+ return STATUS_ERROR;
+ }
+
+ if (OpHeader->Length == 0) {
+ Error (NULL, 0, 0, FileName, "IFR opcode size=0 at offset 0x%X", (int) Pos - (int) Start);
+ return STATUS_ERROR;
+ }
+ //
+ // See if it's the END_FORMSET opcode
+ //
+ if (OpHeader->OpCode == EFI_IFR_END_FORM_SET_OP) {
+ break;
+ }
+ //
+ // Advance to next IFR statement/opcode
+ //
+ Pos += OpHeader->Length;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+STATUS
+IfrParseInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Initialize this module for IFR pack parsing
+
+Arguments:
+
+Returns:
+
+ STATUS_SUCCESS always
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+STATUS
+IfrParseEnd (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Free up memory allocated during IFR pack parsing done by this module
+
+Arguments:
+ None
+
+Returns:
+
+ STATUS_SUCCESS always
+
+--*/
+{
+ IFR_PARSE_CONTEXT *NextContext;
+ IFR_PARSE_ENTRY *NextEntry;
+ //
+ // Free up the memory from our parse contexts
+ //
+ while (mParseContext != NULL) {
+ while (mParseContext->Ifr != NULL) {
+ NextEntry = mParseContext->Ifr->Next;
+ //
+ // We pointed directly into the user buffer, rather than make
+ // a copy, so don't free up the bytes.
+ //
+ free (mParseContext->Ifr);
+ mParseContext->Ifr = NextEntry;
+ }
+
+ NextContext = mParseContext->Next;
+ free (mParseContext->PackHeader);
+ free (mParseContext);
+ mParseContext = NextContext;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+void
+FreeVarStores (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ VARIABLE_STORE_ENTRY *NextVarStore;
+ //
+ // Free up memory from our variable stores
+ //
+ while (mVariableStores != NULL) {
+ if (mVariableStores->VarPack != NULL) {
+ free (mVariableStores->VarPack);
+ }
+
+ NextVarStore = mVariableStores->Next;
+ free (mVariableStores);
+ mVariableStores = NextVarStore;
+ }
+}
+
+/******************************************************************************
+ FUNCTION: IfrParsePack()
+
+ DESCRIPTION: Given a pointer to an IFR pack, parse it to create a linked
+ list of opcodes and relevant data required for later dumping.
+
+
+*******************************************************************************/
+STATUS
+IfrParsePack (
+ int Handle,
+ EFI_HII_IFR_PACK *PackHeader,
+ EFI_GUID *PackageGuid
+ )
+/*++
+
+Routine Description:
+
+ Given a pointer to an IFR pack, parse it to create a linked
+ list of opcodes and relevant data required for later dumping.
+
+Arguments:
+
+ Handle - the handle number associated with this IFR pack. It
+ can be used later to retrieve more info on the particular
+ pack
+ PackHeader - pointer to IFR pack to parse
+ PackageGuid - on input, it comes from the HII data table entry for this pack.
+ On output, we'll return the IFR formset GUID.
+
+Returns:
+
+ STATUS_SUCCESS always
+
+--*/
+{
+ EFI_IFR_OP_HEADER *OpHeader;
+ IFR_PARSE_CONTEXT *Context;
+ IFR_PARSE_CONTEXT *TempContext;
+ IFR_PARSE_ENTRY *IfrEntry;
+ //
+ // Initialize our context
+ //
+ Context = (IFR_PARSE_CONTEXT *) malloc (sizeof (IFR_PARSE_CONTEXT));
+ if (Context == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((void *) Context, 0, sizeof (IFR_PARSE_CONTEXT));
+ //
+ // Cache a copy of the input pack so the caller can free their copy
+ //
+ Context->PackHeader = (EFI_HII_IFR_PACK *) malloc (PackHeader->Header.Length);
+ if (Context->PackHeader == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ free (Context);
+ return STATUS_ERROR;
+ }
+
+ memcpy (Context->PackHeader, PackHeader, PackHeader->Header.Length);
+ Context->IfrBufferStart = (char *) (Context->PackHeader + 1);
+ Context->CurrentPos = Context->IfrBufferStart;
+ Context->IfrBufferLen = PackHeader->Header.Length - sizeof (EFI_HII_IFR_PACK);
+ Context->Handle = Handle;
+ Context->FormsetGuid = &Context->NullGuid;
+ Context->PackageGuid = *PackageGuid;
+ //
+ // Add it to the end of our list
+ //
+ if (mParseContext == NULL) {
+ mParseContext = Context;
+ } else {
+ TempContext = mParseContext;
+ while (TempContext->Next != NULL) {
+ TempContext = TempContext->Next;
+ }
+
+ TempContext->Next = Context;
+ }
+ //
+ // Walk the opcodes in the pack
+ //
+ while
+ (
+ (Context->CurrentPos >= Context->IfrBufferStart) &&
+ (Context->CurrentPos < Context->IfrBufferStart + Context->IfrBufferLen)
+ ) {
+ OpHeader = (EFI_IFR_OP_HEADER *) Context->CurrentPos;
+ //
+ // Allocate a new IFR entry to put in our linked list, then
+ // point directly to the caller's raw data.
+ //
+ IfrEntry = (IFR_PARSE_ENTRY *) malloc (sizeof (IFR_PARSE_ENTRY));
+ if (IfrEntry == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ free (Context->PackHeader);
+ free (Context);
+ return STATUS_ERROR;
+ }
+
+ memset ((void *) IfrEntry, 0, sizeof (IFR_PARSE_ENTRY));
+ IfrEntry->Tag = ++OpcodeTag;
+ if (OpcodeTag == BreakOnOpcodeTag) {
+ EFI_BREAKPOINT ();
+ }
+
+ IfrEntry->RawIfrHeader = (EFI_IFR_OP_HEADER *) (Context->CurrentPos);
+ //
+ // Add this entry to our linked list. If it's not the first, then
+ // forward the variable store settings from the previous entry.
+ //
+ if (Context->LastIfr != NULL) {
+ IfrEntry->VarStoreGuid1 = Context->LastIfr->VarStoreGuid1;
+ IfrEntry->VarStoreName1 = Context->LastIfr->VarStoreName1;
+ IfrEntry->VarStoreGuid2 = Context->LastIfr->VarStoreGuid2;
+ IfrEntry->VarStoreName2 = Context->LastIfr->VarStoreName2;
+ Context->LastIfr->Next = IfrEntry;
+ } else {
+ Context->Ifr = IfrEntry;
+ }
+
+ Context->LastIfr = IfrEntry;
+ //
+ // Switch on the opcode to parse it
+ //
+ if (OpHeader->OpCode < PARSE_TABLE_ENTRIES) {
+ if (mIfrParseTable[OpHeader->OpCode].Parse != NULL) {
+ mIfrParseTable[OpHeader->OpCode].Parse (Context);
+ }
+ } else {
+ Error (
+ NULL,
+ 0,
+ 0,
+ "invalid opcode found in IFR",
+ "offset=0x%X opcode=0x%02X",
+ (int) OpHeader - (int) Context->PackHeader,
+ (int) OpHeader->OpCode
+ );
+ free (IfrEntry);
+ free (Context->PackHeader);
+ free (Context);
+ return STATUS_ERROR;
+ }
+ //
+ // If it's the END_FORMSET opcode, then we're done
+ //
+ if (OpHeader->OpCode == EFI_IFR_END_FORM_SET_OP) {
+ break;
+ }
+ //
+ // Advance to next IFR statement/opcode
+ //
+ if (OpHeader->Length == 0) {
+ Error (NULL, 0, 0, "0-length IFR opcode encountered", NULL);
+ free (IfrEntry);
+ free (Context->PackHeader);
+ free (Context);
+ return STATUS_ERROR;
+ }
+
+ Context->CurrentPos += OpHeader->Length;
+ }
+ //
+ // Return the form GUID.
+ //
+ *PackageGuid = *Context->FormsetGuid;
+ return STATUS_SUCCESS;
+}
+
+/******************************************************************************
+ FUNCTION: GetVarStoreInfo()
+
+ DESCRIPTION: IFR contains VARSTORE opcodes to specify where variable data
+ for following opcodes is supposed to be stored. One VARSTORE statement
+ allows you to specify the variable store GUID and a key, and another
+ VARSTORE (select) allows you to specify the key of a VARSTORE statement.
+ Given the key from a VARSTORE_SELECT statement, go find the corresponding
+ VARSTORE statement with a matching key and return the varstore GUID and
+ name. If key == 0, then the variable store is FormsetGuid."Setup"
+*******************************************************************************/
+static
+STATUS
+GetVarStoreInfo (
+ IFR_PARSE_CONTEXT *Context,
+ UINT16 VarId,
+ EFI_GUID **VarStoreGuid,
+ char **VarStoreName
+ )
+/*++
+
+Routine Description:
+
+ Get variable store information from an IFR pack for a given variable store ID.
+
+Arguments:
+
+ Context - pointer to IFR parse context
+ VarId - variable store ID referenced by IFR being parsed
+ VarStoreGuid - outgoing GUID of the variable store corresponding to VarId
+ VarStoreName - outgoing variable name of variable store corresponding to VarId
+
+Returns:
+
+ STATUS_SUCCESS - variable store with matching VarId found, and outoing GUID/Name are valid
+ STATUS_ERROR - otherwise
+
+--*/
+{
+ IFR_PARSE_ENTRY *Ptr;
+ EFI_IFR_VARSTORE *VarStore;
+ if (Context == NULL) {
+ return STATUS_ERROR;
+ }
+
+ //
+ // Walk the entire IFR form and find a variable store opcode that
+ // has a matching variable store ID.
+ //
+ for (Ptr = Context->Ifr; Ptr != NULL; Ptr = Ptr->Next) {
+ if (Ptr->RawIfrHeader->OpCode == EFI_IFR_FORM_SET_OP) {
+ if (VarId == 0) {
+ *VarStoreGuid = &((EFI_IFR_FORM_SET *) (Ptr->RawIfrHeader))->Guid;
+ *VarStoreName = DEFAULT_VARIABLE_NAME;
+ return STATUS_SUCCESS;
+ }
+ } else if (Ptr->RawIfrHeader->OpCode == EFI_IFR_VARSTORE_OP) {
+ //
+ // See if it's a variable ID match
+ //
+ VarStore = (EFI_IFR_VARSTORE *) Ptr->RawIfrHeader;
+ if (VarStore->VarId == VarId) {
+ *VarStoreGuid = &VarStore->Guid;
+ *VarStoreName = (char *) (VarStore + 1);
+ return STATUS_SUCCESS;
+ }
+ }
+ }
+
+ return STATUS_ERROR;
+}
+
+STATUS
+IfrSetDefaults (
+ int MfgDefaults
+ )
+/*++
+
+Routine Description:
+
+ Go through all the IFR forms we've parsed so far and create and set variable
+ defaults.
+
+Arguments:
+
+ MfgDefaults - non-zero if manufacturing defaults are desired
+
+Returns:
+
+ STATUS_SUCCESS - always
+
+--*/
+{
+ IFR_PARSE_CONTEXT *Context;
+ //
+ // First free up any variable stores we've created so far.
+ //
+ FreeVarStores ();
+ for (Context = mParseContext; Context != NULL; Context = Context->Next) {
+ //
+ // Call our internal function to handle it
+ //
+ SetDefaults (Context, MfgDefaults);
+ }
+
+ return STATUS_SUCCESS;
+
+}
+
+/******************************************************************************/
+STATUS
+IfrGetIfrPack (
+ int Handle,
+ EFI_HII_IFR_PACK **PackHeader,
+ EFI_GUID *FormsetGuid
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Handle - GC_TODO: add argument description
+ PackHeader - GC_TODO: add argument description
+ FormsetGuid - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ IFR_PARSE_CONTEXT *Context;
+
+ for (Context = mParseContext; Context != NULL; Context = Context->Next) {
+ if (Context->Handle == Handle) {
+ *PackHeader = Context->PackHeader;
+ memcpy (FormsetGuid, Context->FormsetGuid, sizeof (EFI_GUID));
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_ERROR;
+}
+
+STATUS
+IfrReferencesVarPack (
+ int IfrHandle,
+ EFI_HII_VARIABLE_PACK *VarPack
+ )
+/*++
+
+Routine Description:
+
+ Given an HII handle number (which corrresponds to a handle number passed
+ in to IfrParsePack()), see if the IFR references the specified variable
+ pack.
+
+Arguments:
+
+ IfrHandle - handle number for the IFR pack to check (passed to IfrParsePack())
+ VarPack - variable pack to check to see if the IFR references
+
+Returns:
+
+ STATUS_SUCCESS if the IFR on the given handle references the variable pack
+ STATUS_WARNING the IFR does not reference the variable pack
+ STATUS_ERROR invalid IFR handle
+
+--*/
+{
+ IFR_PARSE_CONTEXT *Context;
+ char VarName[MAX_VARIABLE_NAME];
+ IFR_PARSE_ENTRY *ParseEntry;
+
+ for (Context = mParseContext; Context != NULL; Context = Context->Next) {
+ if (Context->Handle == IfrHandle) {
+ //
+ // Create an ASCII version of the variable name, since that's what is
+ // referenced in IFR.
+ //
+ sprintf (VarName, "%S", (CHAR16 *) (VarPack + 1));
+ //
+ // Walk all the opcodes and see if the IFR references this variable pack
+ //
+ for (ParseEntry = Context->Ifr; ParseEntry != NULL; ParseEntry = ParseEntry->Next) {
+ //
+ // Check for Name.Guid match for primary IFR variable store
+ //
+ if ((strcmp (VarName, ParseEntry->VarStoreName1) == 0) &&
+ (memcmp (&VarPack->VariableGuid, ParseEntry->VarStoreGuid1, sizeof (EFI_GUID)) == 0)
+ ) {
+ return STATUS_SUCCESS;
+ }
+ //
+ // Check for Name.Guid match for secondary IFR variable store
+ //
+ if ((ParseEntry->VarStoreName2 != NULL) &&
+ (strcmp (VarName, ParseEntry->VarStoreName2) == 0) &&
+ (memcmp (&VarPack->VariableGuid, ParseEntry->VarStoreGuid2, sizeof (EFI_GUID)) == 0)
+ ) {
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_WARNING;
+ }
+ }
+
+ return STATUS_ERROR;
+}
+
+STATUS
+IfrGetVarPack (
+ int VarIndex,
+ EFI_HII_VARIABLE_PACK **VarPack
+ )
+/*++
+
+Routine Description:
+
+ Get the variable defaults. It is expected that the caller
+ called IfrSetDefaults() previously to walk all the IFR forms we know about
+ and create and initialize default values.
+
+Arguments:
+
+ VarIndex - a 0-based index into all the variable stores we know about
+ VarPack - outgoing pointer to a variable pack
+
+Returns:
+
+ STATUS_ERROR - VarIndex exceeds the number of variable packs we know of
+ STATUS_SUCCESS - otherwise
+
+--*/
+{
+ VARIABLE_STORE_ENTRY *Entry;
+ //
+ // Initialize outgoing parameters
+ //
+ *VarPack = NULL;
+ for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) {
+ if (VarIndex == 0) {
+ *VarPack = Entry->VarPack;
+ return STATUS_SUCCESS;
+ }
+
+ VarIndex--;
+ }
+
+ return STATUS_ERROR;
+}
+
+static
+STATUS
+SetVariableValue (
+ EFI_GUID *VarGuid,
+ char *VarName,
+ int VarOffset,
+ int VarSize,
+ void *VarValue
+ )
+/*++
+
+Routine Description:
+
+ Given a variable GUID.Name, offset, size, and value, set the bytes in
+ the variable to the provided value.
+
+Arguments:
+ VarGuid - GUID of variable to set
+ VarName - name of variable to set
+ VarOffset - byte offset into the variable store
+ VarSize - size of the value in the variable store (in bytes)
+ VarValue - pointer to buffer containing the value to set
+
+Returns:
+
+
+--*/
+{
+ VARIABLE_STORE_ENTRY *Entry;
+ char *Src;
+ char *Dest;
+ //
+ // Go through our list of variable stores to find the match
+ //
+ for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) {
+ if (memcmp (VarGuid, &Entry->VarPack->VariableGuid, sizeof (EFI_GUID)) == 0) {
+ if (strcmp (VarName, Entry->VarName) == 0) {
+ //
+ // Found match -- check offset. If it's beyond the size of the variable store
+ // buffer, then return a warning. Note that date-time can be beyond the
+ // end of the varstore, which is ok.
+ //
+ if (VarOffset + VarSize <= Entry->VarBufferSize) {
+ //
+ // Stuff the data
+ //
+ Dest = Entry->VarBuffer + VarOffset;
+ Src = (char *) VarValue;
+ while (VarSize > 0) {
+ *Dest = *Src;
+ Src++;
+ Dest++;
+ VarSize--;
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_WARNING;
+ }
+ }
+ }
+
+ return STATUS_ERROR;
+}
+
+static
+STATUS
+SetDefaults (
+ IFR_PARSE_CONTEXT *Context,
+ UINT32 MfgDefaults
+ )
+/*++
+
+Routine Description:
+
+ Set variable defaults by walking a single IFR form.
+
+Arguments:
+
+ Context - Pointer to the IFR context.
+ MfgDefaults - Number of Mfg defaults
+
+Returns:
+
+ EFI_INVALID_PARAMETER - arguments to function are invalid
+ STATUS_SUCCESS - function executed successfully
+
+--*/
+{
+ int Size;
+ int CachedVarOffset;
+ int CachedVarSize;
+ int OrderedList;
+ IFR_PARSE_ENTRY *SavedParseEntry;
+ EFI_IFR_CHECK_BOX *IfrCheckBox;
+ EFI_IFR_ONE_OF_OPTION *IfrOneOfOption;
+ EFI_IFR_NUMERIC *IfrNumeric;
+ STATUS Status;
+ char ZeroByte;
+
+ //
+ // Walk the opcodes to set default values and stuff them into the variable stores
+ //
+
+ if (Context == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+ Status = STATUS_SUCCESS;
+ Context->CurrentIfr = Context->Ifr;
+ SavedParseEntry = NULL;
+ OrderedList = 0;
+ CachedVarOffset = 0;
+ CachedVarSize = 0;
+ ZeroByte = 0;
+
+ while (Context->CurrentIfr != NULL) {
+ if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_FORM_SET_OP) {
+ //
+ // Formset opcode -- create a variable pack
+ //
+ Status = CreateVarStore (
+ &((EFI_IFR_FORM_SET *) (Context->CurrentIfr->RawIfrHeader))->Guid,
+ DEFAULT_VARIABLE_NAME,
+ ((EFI_IFR_FORM_SET *) (Context->CurrentIfr->RawIfrHeader))->NvDataSize
+ );
+ } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_VARSTORE_OP) {
+ //
+ // Variable store opcode -- create a variable pack
+ //
+ Status = CreateVarStore (
+ &((EFI_IFR_VARSTORE *) (Context->CurrentIfr->RawIfrHeader))->Guid,
+ (char *) Context->CurrentIfr->RawIfrHeader + sizeof (EFI_IFR_VARSTORE),
+ ((EFI_IFR_VARSTORE *) (Context->CurrentIfr->RawIfrHeader))->Size
+ );
+ } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ONE_OF_OP) {
+ //
+ // Need this parse context later when we find the default ONE_OF_OPTION.
+ // Clear out the variable store first, so that we're covered if someone
+ // has two one-of opcode that operate on the same data.
+ // So "last one wins" is the behavior.
+ //
+ OrderedList = 0;
+ SavedParseEntry = Context->CurrentIfr;
+ CachedVarOffset = ((EFI_IFR_ONE_OF *) Context->CurrentIfr->RawIfrHeader)->QuestionId;
+ CachedVarSize = ((EFI_IFR_ONE_OF *) Context->CurrentIfr->RawIfrHeader)->Width;
+ } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ORDERED_LIST_OP) {
+ //
+ // Need this parse context later as we parse the ONE_OF_OP's in the ordered list
+ //
+ OrderedList = 1;
+ SavedParseEntry = Context->CurrentIfr;
+ CachedVarOffset = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->QuestionId;
+ CachedVarSize = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->MaxEntries;
+
+ while (CachedVarSize > 0) {
+ Status = SetVariableValue (
+ SavedParseEntry->VarStoreGuid1, // GUID of variable store to write
+ SavedParseEntry->VarStoreName1, // name of variable store to write
+ CachedVarOffset, // offset into variable store
+ 1, // variable data size
+ (void *) &ZeroByte
+ );
+ //
+ // variable value
+ //
+ CachedVarSize--;
+ CachedVarOffset++;
+ }
+
+ CachedVarOffset = ((EFI_IFR_ORDERED_LIST *) Context->CurrentIfr->RawIfrHeader)->QuestionId;
+ CachedVarSize = 1;
+ //
+ // ((EFI_IFR_ORDERED_LIST *)Context->CurrentIfr->RawIfrHeader)->Width;
+ //
+ } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_ONE_OF_OPTION_OP) {
+ IfrOneOfOption = (EFI_IFR_ONE_OF_OPTION *) Context->CurrentIfr->RawIfrHeader;
+ //
+ // If we're in an ordered list, then copy the value to the data store
+ //
+ if (OrderedList) {
+ Status = SetVariableValue (
+ SavedParseEntry->VarStoreGuid1, // GUID of variable store to write
+ SavedParseEntry->VarStoreName1, // name of variable store to write
+ CachedVarOffset, // offset into variable store
+ 1, // variable data size
+ (void *) &IfrOneOfOption->Value
+ );
+ //
+ // variable value
+ //
+ // Advance the offset for the next ordered list item
+ //
+ CachedVarOffset += CachedVarSize;
+ } else {
+ //
+ // ONE-OF list. See if the default flag is set (provided we're not doing mfg defaults)
+ //
+ if (!MfgDefaults) {
+ if (IfrOneOfOption->Flags & EFI_IFR_FLAG_DEFAULT) {
+ Status = SetVariableValue (
+ SavedParseEntry->VarStoreGuid1, // GUID of variable store to write
+ SavedParseEntry->VarStoreName1, // name of variable store to write
+ CachedVarOffset, // offset into variable store
+ CachedVarSize, // variable data size
+ &IfrOneOfOption->Value
+ );
+ //
+ // variable value
+ //
+ }
+ } else {
+ if (IfrOneOfOption->Flags & EFI_IFR_FLAG_MANUFACTURING) {
+ Status = SetVariableValue (
+ SavedParseEntry->VarStoreGuid1, // GUID of variable store to write
+ SavedParseEntry->VarStoreName1, // name of variable store to write
+ CachedVarOffset, // offset into variable store
+ CachedVarSize, // variable data size
+ &IfrOneOfOption->Value
+ );
+ //
+ // variable value
+ //
+ }
+ }
+ }
+ } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_CHECKBOX_OP) {
+ //
+ // If we're saving defaults, and the default flag is set, or we're saving
+ // manufacturing defaults and the manufacturing flag is set, then save a 1.
+ // By default the varstore buffer is cleared, so we don't need to save a 0 ever.
+ //
+ IfrCheckBox = (EFI_IFR_CHECK_BOX *) Context->CurrentIfr->RawIfrHeader;
+ if (((MfgDefaults == 0) && (IfrCheckBox->Flags & EFI_IFR_FLAG_DEFAULT)) ||
+ ((MfgDefaults != 0) && (IfrCheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING))
+ ) {
+ Size = 1;
+ Status = SetVariableValue (
+ Context->CurrentIfr->VarStoreGuid1, // GUID of variable store to write
+ Context->CurrentIfr->VarStoreName1, // name of variable store to write
+ IfrCheckBox->QuestionId, // offset into variable store
+ IfrCheckBox->Width, // variable data size
+ (void *) &Size
+ );
+ //
+ // variable value
+ //
+ }
+ } else if (Context->CurrentIfr->RawIfrHeader->OpCode == EFI_IFR_NUMERIC_OP) {
+ IfrNumeric = (EFI_IFR_NUMERIC *) Context->CurrentIfr->RawIfrHeader;
+ Status = SetVariableValue (
+ Context->CurrentIfr->VarStoreGuid1, // GUID of variable store to write
+ Context->CurrentIfr->VarStoreName1, // name of variable store to write
+ IfrNumeric->QuestionId, // offset into variable store
+ IfrNumeric->Width, // variable data size
+ (void *) &IfrNumeric->Default
+ );
+ //
+ // variable value
+ //
+ }
+
+ Context->CurrentIfr = Context->CurrentIfr->Next;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+CreateVarStore (
+ EFI_GUID *VarGuid,
+ CHAR8 *VarName,
+ int VarStoreSize
+ )
+/*++
+
+Routine Description:
+
+ Given a variable GUID.Name and the size of the variable store, allocate
+ storage for maintaining the variable value.
+
+Arguments:
+
+ VarGuid - GUID for a variable
+ VarName - Name of the variable
+ VarStoreSize - size of the variable store
+
+Returns:
+
+ STATUS_ERROR - problem with storage allocation
+ STATUS_SUCCESS - function executed successfully
+
+--*/
+{
+ VARIABLE_STORE_ENTRY *Entry;
+
+ VARIABLE_STORE_ENTRY *TempEntry;
+ int PackSize;
+ int VarNameLen;
+ //
+ // If the variable store size is zero, then do nothing. This could be valid
+ // if variable steering is used in the IFR such that FormsetGUID."Setup" variable
+ // store is never used.
+ //
+ // OPEN: What about a form that only has a time/date question? Then if some other
+ // function called SetDefaults(), attempting to set time/date would result in an
+ // error in the SetVarValue() function.
+ //
+ if (VarStoreSize == 0) {
+ return STATUS_SUCCESS;
+ }
+ //
+ // Go through our list of variable stores and see if we've already created one
+ // for this Guid.Name. If so, check the size and return. Otherwise create
+ // one and add it to the list.
+ //
+ for (Entry = mVariableStores; Entry != NULL; Entry = Entry->Next) {
+ if (memcmp (VarGuid, &Entry->VarPack->VariableGuid, sizeof (EFI_GUID)) == 0) {
+ if (strcmp (VarName, Entry->VarName) == 0) {
+ //
+ // Already have one. Check size.
+ //
+ if (Entry->VarBufferSize != VarStoreSize) {
+ Error (NULL, 0, 0, "mismatched variable store size between two formsets", VarName);
+ return STATUS_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+ }
+ }
+ }
+ //
+ // Create a new one.
+ //
+ Entry = (VARIABLE_STORE_ENTRY *) malloc (sizeof (VARIABLE_STORE_ENTRY));
+ if (Entry == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset ((void *) Entry, 0, sizeof (VARIABLE_STORE_ENTRY));
+ //
+ // Compute size of the varpack
+ //
+ VarNameLen = strlen (VarName) + 1;
+ PackSize = sizeof (EFI_HII_VARIABLE_PACK) + VarNameLen * sizeof (CHAR16) + VarStoreSize;
+ Entry->VarPack = (EFI_HII_VARIABLE_PACK *) malloc (PackSize);
+ if (Entry->VarPack == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ free (Entry);
+ return STATUS_ERROR;
+ }
+
+ Entry->VarPack->Header.Length = PackSize;
+ Entry->VarPack->Header.Type = EFI_HII_VARIABLE;
+ Entry->VarPack->VariableNameLength = VarNameLen * sizeof (CHAR16);
+ Entry->VarName[MAX_VARIABLE_NAME - 1] = 0;
+ strncpy (Entry->VarName, VarName, MAX_VARIABLE_NAME - 1);
+#ifdef USE_VC8
+ swprintf ((CHAR16 *) (Entry->VarPack + 1), (strlen (VarName) + 1) * sizeof (CHAR16), L"%S", VarName);
+#else
+ swprintf ((CHAR16 *) (Entry->VarPack + 1), L"%S", VarName);
+#endif
+ memcpy (&Entry->VarPack->VariableGuid, VarGuid, sizeof (EFI_GUID));
+ //
+ // Point VarBuffer into the allocated buffer (for convenience)
+ //
+ Entry->VarBuffer = (char *) Entry->VarPack + sizeof (EFI_HII_VARIABLE_PACK) + VarNameLen * sizeof (CHAR16);
+ memset ((void *) Entry->VarBuffer, 0, VarStoreSize);
+ Entry->VarBufferSize = VarStoreSize;
+ //
+ // Add this new varstore to our list
+ //
+ if (mVariableStores == NULL) {
+ mVariableStores = Entry;
+ } else {
+ for (TempEntry = mVariableStores; TempEntry->Next != NULL; TempEntry = TempEntry->Next)
+ ;
+ TempEntry->Next = Entry;
+ }
+ return STATUS_SUCCESS;
+}
+
+/******************************************************************************/
+
+/*++
+
+Routine Description:
+
+ The following IfrParseXX() functions are used to parse an IFR opcode numbered
+ XX via a dispatch table.
+
+Arguments:
+
+ Context - IFR parsing context into which pertinent data for the
+ current opcode can be saved. Context->LastIfr->RawIfrHeader points to
+ the raw IFR bytes currently being parsed.
+
+Returns:
+
+ STATUS_SUCCESS - always
+
+--*/
+
+/*******************************************************************************/
+static
+STATUS
+IfrParse01 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse02 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse03 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+//
+// Parse the IFR EFI_IFR_ONE_OF opcode.
+//
+static
+STATUS
+IfrParse05 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse06 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse07 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse08 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse09 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse0A (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse0B (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse0C (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse0D (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse0E (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ EFI_IFR_FORM_SET *Op;
+ Op = (EFI_IFR_FORM_SET *) Context->LastIfr->RawIfrHeader;
+ Context->LastIfr->VarStoreGuid1 = &Op->Guid;
+ Context->LastIfr->VarStoreName1 = "Setup";
+ Context->FormsetGuid = &Op->Guid;
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse0F (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse10 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse11 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse12 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse13 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse14 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse15 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse16 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse17 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse18 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse19 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse1A (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse1B (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse1C (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse1D (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse1E (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse1F (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse20 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse21 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse22 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+
+static
+STATUS
+IfrParse23 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+//
+// EFI_IFR_VARSTORE
+//
+static
+STATUS
+IfrParse24 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ EFI_IFR_VARSTORE *Op;
+ Op = (EFI_IFR_VARSTORE *) Context->LastIfr->RawIfrHeader;
+ return STATUS_SUCCESS;
+}
+//
+// VARSTORE_SELECT
+//
+static
+STATUS
+IfrParse25 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ STATUS Status;
+ EFI_IFR_VARSTORE_SELECT *Op;
+ Op = (EFI_IFR_VARSTORE_SELECT *) Context->LastIfr->RawIfrHeader;
+ Status = GetVarStoreInfo (Context, Op->VarId, &Context->LastIfr->VarStoreGuid1, &Context->LastIfr->VarStoreName1);
+ //
+ // VARSTORE_SELECT sets both
+ //
+ Context->LastIfr->VarStoreGuid2 = Context->LastIfr->VarStoreGuid1;
+ Context->LastIfr->VarStoreName2 = Context->LastIfr->VarStoreName1;
+ return Status;
+}
+//
+// VARSTORE_SELECT_PAIR
+//
+static
+STATUS
+IfrParse26 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ STATUS Status;
+ EFI_IFR_VARSTORE_SELECT_PAIR *Op;
+
+ Op = (EFI_IFR_VARSTORE_SELECT_PAIR *) Context->LastIfr->RawIfrHeader;
+ Status = GetVarStoreInfo (Context, Op->VarId, &Context->LastIfr->VarStoreGuid1, &Context->LastIfr->VarStoreName1);
+ Status = GetVarStoreInfo (
+ Context,
+ Op->SecondaryVarId,
+ &Context->LastIfr->VarStoreGuid2,
+ &Context->LastIfr->VarStoreName2
+ );
+ return Status;
+}
+//
+// TRUE
+//
+static
+STATUS
+IfrParse27 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+//
+// FALSe
+//
+static
+STATUS
+IfrParse28 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+static
+STATUS
+IfrParse29 (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
+static
+STATUS
+IfrParse2A (
+ IFR_PARSE_CONTEXT *Context
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Context - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ return STATUS_SUCCESS;
+}
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/IfrParse.h b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/IfrParse.h
new file mode 100644
index 0000000000..6a2a597b33
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/IfrParse.h
@@ -0,0 +1,267 @@
+/*++
+
+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:
+
+ IfrParse.h
+
+Abstract:
+
+ Prototypes and defines for the IFR parsing services.
+
+--*/
+
+#ifndef _IFR_PARSE_H_
+#define _IFR_PARSE_H_
+
+#define DEFAULT_HII_PACK_FILENAME_EXTENSION ".hpk"
+//
+// When we parse IFR, we'll keep the IFR in a linked list of
+// these.
+//
+typedef struct _IFR_PARSE_ENTRY {
+ struct _IFR_PARSE_ENTRY *Next;
+ int Tag; // for debugging
+ EFI_IFR_OP_HEADER *RawIfrHeader;
+ //
+ // GUIDs for variable storage
+ //
+ EFI_GUID *VarStoreGuid1;
+ char *VarStoreName1;
+ EFI_GUID *VarStoreGuid2;
+ char *VarStoreName2;
+} IFR_PARSE_ENTRY;
+
+typedef struct _IFR_PARSE_CONTEXT {
+ struct _IFR_PARSE_CONTEXT *Next;
+ EFI_HII_IFR_PACK *PackHeader;
+ char *IfrBufferStart;
+ char *CurrentPos;
+ long IfrBufferLen;
+ int Handle;
+ IFR_PARSE_ENTRY *Ifr;
+ IFR_PARSE_ENTRY *LastIfr;
+ IFR_PARSE_ENTRY *CurrentIfr;
+ FILE *OutFptr;
+ CHAR16 *Language;
+ EFI_GUID *FormsetGuid;
+ EFI_GUID NullGuid; // for use until we set the Guid field correctly
+ EFI_GUID PackageGuid; // from the PackageGuid in the HII data table
+} IFR_PARSE_CONTEXT;
+
+STATUS
+IfrGetVarPack (
+ int VarIndex,
+ EFI_HII_VARIABLE_PACK **VarPack
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ VarIndex - GC_TODO: add argument description
+ VarPack - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+IfrParsePack (
+ int Handle,
+ EFI_HII_IFR_PACK *PackHeader,
+ EFI_GUID *PackageGuid
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Handle - GC_TODO: add argument description
+ PackHeader - GC_TODO: add argument description
+ PackageGuid - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+IfrParseCheck (
+ char *Buffer,
+ long BufferSize
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Buffer - GC_TODO: add argument description
+ BufferSize - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+IfrParseInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+IfrParseEnd (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+IfrParseDump (
+ int Handle,
+ CHAR16 *Language,
+ FILE *OutFptr
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Handle - GC_TODO: add argument description
+ Language - GC_TODO: add argument description
+ OutFptr - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+IfrSetDefaults (
+ int MfgDefaults
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ MfgDefaults - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+IfrGetIfrPack (
+ int Handle,
+ EFI_HII_IFR_PACK **PackHeader,
+ EFI_GUID *FormsetGuid
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Handle - GC_TODO: add argument description
+ PackHeader - GC_TODO: add argument description
+ FormsetGuid - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+IfrReferencesVarPack (
+ int IfrHandle,
+ EFI_HII_VARIABLE_PACK *VarPack
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ IfrHandle - GC_TODO: add argument description
+ VarPack - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif // #ifndef _IFR_PARSE_H_
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/Makefile
new file mode 100644
index 0000000000..83f6ba7ff8
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/Makefile
@@ -0,0 +1,103 @@
+#/*++
+#
+# 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:
+#
+# Makefile
+#
+# Abstract:
+#
+# This file is used to build the HiiPack utility
+#
+#--*/
+
+#
+# Make sure environmental variable EDK_SOURCE is set
+#
+!IFNDEF EDK_SOURCE
+!ERROR EDK_SOURCE environmental variable not set
+!ENDIF
+
+#
+# Do this if you want to compile from this directory
+#
+!IFNDEF TOOLCHAIN
+TOOLCHAIN = TOOLCHAIN_MSVC
+!ENDIF
+
+!INCLUDE $(BUILD_DIR)\PlatformTools.env
+
+#
+# Target specific information
+#
+
+TARGET_NAME = HiiPack
+TARGET_SRC_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME)
+TARGET_EXE = $(EDK_TOOLS_OUTPUT)\HiiPack.exe
+
+#
+# Build targets
+#
+
+all: $(TARGET_EXE)
+
+INC = $(INC) -I "$(EDK_SOURCE)\Foundation\Framework\Protocol\Hii"
+
+INC_DEPS = "$(TARGET_SRC_DIR)\HiiPack.h" "$(TARGET_SRC_DIR)\IfrParse.h" "$(TARGET_SRC_DIR)\StringParse.h"
+
+LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib"
+
+OBJECTS = $(EDK_TOOLS_OUTPUT)\FindFiles.obj \
+ $(EDK_TOOLS_OUTPUT)\HiiPack.obj \
+ $(EDK_TOOLS_OUTPUT)\IfrParse.obj \
+ $(EDK_TOOLS_OUTPUT)\StringParse.obj
+
+#
+# Build EXE
+#
+
+$(EDK_TOOLS_OUTPUT)\FindFiles.obj : $(TARGET_SRC_DIR)\FindFiles.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\FindFiles.c /Fo$@
+
+$(EDK_TOOLS_OUTPUT)\HiiPack.obj : $(TARGET_SRC_DIR)\HiiPack.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\HiiPack.c /Fo$@
+
+$(EDK_TOOLS_OUTPUT)\IfrParse.obj : $(TARGET_SRC_DIR)\IfrParse.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\IfrParse.c /Fo$@
+
+$(EDK_TOOLS_OUTPUT)\StringParse.obj : $(TARGET_SRC_DIR)\StringParse.c $(INC_DEPS)
+ $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\StringParse.c /Fo$@
+
+#
+# Add Binary Build description for this tool.
+#
+
+!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe))
+$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe
+ copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y
+ if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \
+ copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y
+!ELSE
+$(TARGET_EXE) : $(OBJECTS) $(LIBS)
+ $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS)
+!IF ("$(EFI_BINARY_BUILD)" == "YES")
+ if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools
+ if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y
+ if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \
+ copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y
+!ENDIF
+!ENDIF
+
+clean:
+ @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL
+ @if exist $(EDK_TOOLS_OUTPUT)\FindFiles.* del $(EDK_TOOLS_OUTPUT)\FindFiles.* > NUL
+ @if exist $(EDK_TOOLS_OUTPUT)\IfrParse* del $(EDK_TOOLS_OUTPUT)\IfrParse.* > NUL
+ @if exist $(EDK_TOOLS_OUTPUT)\StringParse.* del $(EDK_TOOLS_OUTPUT)\StringParse.* > NUL
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/StringParse.c b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/StringParse.c
new file mode 100644
index 0000000000..8dd26e1529
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/StringParse.c
@@ -0,0 +1,244 @@
+/*++
+
+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:
+
+ StringParse.c
+
+Abstract:
+
+ Routines for parsing HII string packs
+
+--*/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "Tiano.h"
+#include "EfiUtilityMsgs.h"
+#include "EfiInternalFormRepresentation.h"
+#include "Hii.h"
+#include "StringParse.h"
+#include "HiiPack.h"
+
+typedef struct _STRING_PACK_RECORD {
+ struct _STRING_PACK_RECORD *Next;
+ int Handle;
+ EFI_GUID PackageGuid;
+ EFI_GUID FormsetGuid;
+ EFI_HII_STRING_PACK *StringPack;
+ int StringPackSize;
+ int NumStringPacks;
+} STRING_PACK_RECORD;
+
+static STRING_PACK_RECORD *mStringPacks = NULL;
+
+STATUS
+StringGetPack (
+ int Handle, // matches handle passed in with StringParsePack()
+ EFI_HII_STRING_PACK **StringPack, // returned pointer to string pack
+ int *StringPackSize, // sizeof buffer pointed to by StringPack
+ int *NumStringPacks, // in the array pointed to by StringPack
+ EFI_GUID *FormsetGuid,
+ EFI_GUID *PackageGuid
+ )
+/*++
+
+Routine Description:
+
+ Get a string pack given to us previously
+
+Arguments:
+ Handle - handle of string pack to get
+ StringPack - outgoing pointer to string pack on the given handle
+ StringPackSize - outgoing size of string pack pointed to by StringPack
+ NumStringPacks - outgoing number of string packs in StringPack[] array
+ FormsetGuid - outgoing GUID passed in with the string pack when it was parsed
+ PackageGuid - outgoing GUID passed in with the string pack when it was parsed
+
+Returns:
+
+ STATUS_SUCCESS - string pack with matching handle was found
+ STATUS_ERROR - otherwise
+
+--*/
+{
+ STRING_PACK_RECORD *Rec;
+
+ for (Rec = mStringPacks; Rec != NULL; Rec = Rec->Next) {
+ if (Rec->Handle == Handle) {
+ *StringPack = Rec->StringPack;
+ *StringPackSize = Rec->StringPackSize;
+ *NumStringPacks = Rec->NumStringPacks;
+ return STATUS_SUCCESS;
+ }
+ }
+
+ return STATUS_ERROR;
+}
+
+STATUS
+StringParsePack (
+ int Handle,
+ EFI_HII_STRING_PACK *StringPack,
+ EFI_GUID *FormsetGuid,
+ EFI_GUID *PackageGuid
+ )
+/*++
+
+Routine Description:
+
+ Parse a string pack, saving the information for later retrieval by the caller
+
+Arguments:
+ Handle - handle of string pack
+ StringPack - pointer to string pack array to parse
+ FormsetGuid - GUID of the string pack
+ PackageGuid - package GUID from the HII data table from which this string pack orginated
+
+Returns:
+
+ STATUS_SUCCESS - Stringpack processed successfully
+ STATUS_ERROR - otherwise
+
+--*/
+{
+ STRING_PACK_RECORD *Rec;
+
+ STRING_PACK_RECORD *TempRec;
+ int PackSize;
+ EFI_HII_STRING_PACK *TempPack;
+ //
+ // Allocate a new string pack record
+ //
+ Rec = (STRING_PACK_RECORD *) malloc (sizeof (STRING_PACK_RECORD));
+ if (Rec == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ return STATUS_ERROR;
+ }
+
+ memset (Rec, 0, sizeof (STRING_PACK_RECORD));
+ Rec->Handle = Handle;
+ if (PackageGuid != NULL) {
+ memcpy (&Rec->PackageGuid, PackageGuid, sizeof (EFI_GUID));
+ }
+
+ if (FormsetGuid != NULL) {
+ memcpy (&Rec->FormsetGuid, FormsetGuid, sizeof (EFI_GUID));
+ }
+ //
+ // Walk the string packs to find the terminator
+ //
+ TempPack = StringPack;
+ PackSize = 0;
+ while (TempPack->Header.Length > 0) {
+ if (TempPack->Header.Type != EFI_HII_STRING) {
+ Error (NULL, 0, 0, "found a non-string pack in the string pack array", NULL);
+ free (Rec);
+ return STATUS_ERROR;
+ }
+
+ PackSize += TempPack->Header.Length;
+ Rec->NumStringPacks++;
+ TempPack = (EFI_HII_STRING_PACK *) ((char *) TempPack + TempPack->Header.Length);
+ }
+ //
+ // Add space for the terminator
+ //
+ PackSize += sizeof (EFI_HII_STRING_PACK);
+ Rec->StringPackSize = PackSize;
+ //
+ // Make a copy of the incoming string pack
+ //
+ Rec->StringPack = (EFI_HII_STRING_PACK *) malloc (PackSize);
+ if (Rec->StringPack == NULL) {
+ Error (NULL, 0, 0, "memory allocation failure", NULL);
+ free (Rec);
+ return STATUS_ERROR;
+ }
+
+ memcpy ((void *) Rec->StringPack, StringPack, PackSize);
+ //
+ // Add this record to our list
+ //
+ if (mStringPacks == NULL) {
+ mStringPacks = Rec;
+ } else {
+ for (TempRec = mStringPacks; TempRec->Next != NULL; TempRec = TempRec->Next)
+ ;
+ TempRec->Next = Rec;
+ }
+ free (Rec->StringPack);
+ free (Rec);
+ return STATUS_SUCCESS;
+}
+
+STATUS
+StringInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ StringEnd ();
+ return STATUS_SUCCESS;
+}
+
+STATUS
+StringEnd (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ STRING_PACK_RECORD *Next;
+ //
+ // Free up all the memory we've allocated
+ //
+ while (mStringPacks != NULL) {
+ if (mStringPacks->StringPack != NULL) {
+ free (mStringPacks->StringPack);
+ }
+
+ Next = mStringPacks->Next;
+ free (mStringPacks);
+ mStringPacks = Next;
+ }
+
+ return STATUS_SUCCESS;
+}
diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/StringParse.h b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/StringParse.h
new file mode 100644
index 0000000000..a5df7d0ccb
--- /dev/null
+++ b/EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/StringParse.h
@@ -0,0 +1,125 @@
+/*++
+
+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:
+
+ StringParse.h
+
+Abstract:
+
+ Prototypes and defines for the string pack parsing services.
+
+--*/
+
+#ifndef _STRING_PARSE_H_
+#define _STRING_PARSE_H_
+
+STATUS
+StringGetPack (
+ int Handle, // matches handle passed in with StringParsePack()
+ EFI_HII_STRING_PACK **StringPack, // returned pointer to string pack
+ int *StringPackSize, // sizeof buffer pointed to by StringPack
+ int *NumStringPacks, // in the array pointed to by StringPack
+ EFI_GUID *FormsetGuid,
+ EFI_GUID *PackageGuid
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Handle - GC_TODO: add argument description
+ StringPack - GC_TODO: add argument description
+ StringPackSize - GC_TODO: add argument description
+ NumStringPacks - GC_TODO: add argument description
+ FormsetGuid - GC_TODO: add argument description
+ PackageGuid - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+StringParsePack (
+ int Handle,
+ EFI_HII_STRING_PACK *StringPack,
+ EFI_GUID *FormsetGuid,
+ EFI_GUID *PackageGuid
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ Handle - GC_TODO: add argument description
+ StringPack - GC_TODO: add argument description
+ FormsetGuid - GC_TODO: add argument description
+ PackageGuid - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+StringInit (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+STATUS
+StringEnd (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ None
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif // #ifndef _STRING_PARSE_H_