--- /dev/null
+/*++\r
+\r
+Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ HiiPack.c\r
+\r
+Abstract:\r
+\r
+ Process HII package files to generate HII package list binary file or PE/COFF\r
+ resource script file (i.e. .rc file).\r
+\r
+--*/\r
+\r
+#include <stdio.h>\r
+#include <string.h>\r
+\r
+#include "Tiano.h"\r
+#include "EfiHii.h"\r
+\r
+#include "EfiUtilityMsgs.h"\r
+#include "ParseInf.h"\r
+\r
+#define UTILITY_VERSION "v1.0"\r
+#define UTILITY_NAME "HiiPack"\r
+#define MAX_PATH 260\r
+\r
+//\r
+// Define HII resource section type and name\r
+//\r
+#define HII_RESOURCE_TYPE "HII"\r
+#define HII_RESOURCE_NAME 1\r
+\r
+//\r
+// We'll store lists of file names from the command line in\r
+// a linked list of these\r
+//\r
+typedef struct _FILE_NAME_LIST {\r
+ struct _FILE_NAME_LIST *Next;\r
+ UINT8 FileName[MAX_PATH];\r
+ UINT32 PackageType;\r
+ UINT32 Length;\r
+ UINT8 *Data;\r
+} FILE_NAME_LIST;\r
+\r
+//\r
+// Create some defines for the different operation modes supported by this utility\r
+//\r
+#define MODE_CREATE_HII_RESOURCE_FILE 0x0001\r
+#define MODE_CREATE_HII_PACKAGE_LIST 0x0002\r
+\r
+//\r
+// Here's all our globals.\r
+//\r
+static struct {\r
+ FILE_NAME_LIST *PackageFile; // all include paths to search\r
+ FILE_NAME_LIST *LastPackageFile;\r
+ UINT8 PackageListFileName[MAX_PATH]; // Output package list file name\r
+ UINT8 ResourceFileName[MAX_PATH]; // Output HII resource file name\r
+ EFI_GUID Guid; // Guid specified on command line\r
+ BOOLEAN GuidSpecified;\r
+ BOOLEAN Verbose;\r
+ UINT32 Mode; // Mode this utility is operating in\r
+} mGlobals;\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ );\r
+\r
+static\r
+STATUS\r
+ProcessArgs (\r
+ int Argc,\r
+ char *Argv[]\r
+ );\r
+\r
+static\r
+void\r
+FreeGlobals (\r
+ VOID\r
+ );\r
+\r
+static\r
+void\r
+DumpRawBytes (\r
+ FILE *OutFptr,\r
+ UINT8 *Buffer,\r
+ int Count,\r
+ int Indent\r
+ );\r
+\r
+static\r
+STATUS\r
+CreateResourceScript (\r
+ char *OutputFileName,\r
+ EFI_GUID *PackageListGuid,\r
+ FILE_NAME_LIST *PackageFiles\r
+ );\r
+\r
+static\r
+STATUS\r
+CreatePackageList (\r
+ char *OutputFileName,\r
+ EFI_GUID *PackageListGuid,\r
+ FILE_NAME_LIST *PackageFiles\r
+ );\r
+\r
+int\r
+main (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Call the routine to parse the command-line options, then process the file.\r
+\r
+Arguments:\r
+\r
+ Standard C main() argc and argv.\r
+\r
+Returns:\r
+\r
+ 0 if successful\r
+ nonzero otherwise\r
+\r
+--*/\r
+{\r
+ STATUS Status;\r
+\r
+ //\r
+ // Set the utility name for error reporting purposes\r
+ //\r
+ SetUtilityName (UTILITY_NAME);\r
+\r
+ //\r
+ // Process the command-line arguments\r
+ //\r
+ Status = ProcessArgs (Argc, Argv);\r
+ if (Status != STATUS_SUCCESS) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Switch based on args\r
+ //\r
+ if (mGlobals.Mode & MODE_CREATE_HII_RESOURCE_FILE) {\r
+ CreateResourceScript (mGlobals.ResourceFileName, &mGlobals.Guid, mGlobals.PackageFile);\r
+ }\r
+\r
+ if (mGlobals.Mode & MODE_CREATE_HII_PACKAGE_LIST) {\r
+ CreatePackageList (mGlobals.PackageListFileName, &mGlobals.Guid, mGlobals.PackageFile);\r
+ }\r
+\r
+ FreeGlobals ();\r
+\r
+ return GetUtilityStatus ();\r
+}\r
+\r
+/******************************************************************************/\r
+static const char *gRcFileHeader[] = {\r
+ "//",\r
+ "// DO NOT EDIT -- auto-generated file",\r
+ "//",\r
+ "// This file is generated by the hiipack utility",\r
+ "//",\r
+ NULL\r
+};\r
+\r
+static\r
+STATUS\r
+CreateResourceScript (\r
+ char *OutputFileName,\r
+ EFI_GUID *PackageListGuid,\r
+ FILE_NAME_LIST *PackageFiles\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Given a linked list of HII package files, walk the list to\r
+ process them and create a single HII resource script file.\r
+\r
+Arguments:\r
+\r
+ OutputFileName - name of output HII resource script file to create\r
+ PackageListGuid - the specified package list GUID\r
+ PackageFiles - linked list of HII package files to process\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - if successful\r
+ STATUS_ERROR - otherwise\r
+\r
+--*/\r
+{\r
+ STATUS Status;\r
+ UINT8 *PackageList;\r
+ UINT8 *Buffer;\r
+ UINT32 PackageListLen;\r
+ FILE *OutFptr;\r
+ UINTN Index;\r
+ FILE_NAME_LIST *Package;\r
+\r
+ //\r
+ // If no input HII pack files, then why are we here? Should have been caught when\r
+ // args were processed though.\r
+ //\r
+ if (PackageFiles == NULL) {\r
+ Error (NULL, 0, 0, "no input package file(s) specified", NULL);\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ OutFptr = NULL;\r
+ Status = STATUS_ERROR;\r
+\r
+ //\r
+ // Open the output file for writing\r
+ //\r
+ if ((OutFptr = fopen (OutputFileName, "w")) == NULL) {\r
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Write file header\r
+ //\r
+ for (Index = 0; gRcFileHeader[Index] != NULL; Index++) {\r
+ fprintf (OutFptr, "%s\n", gRcFileHeader[Index]);\r
+ }\r
+\r
+ //\r
+ // Write nameID and typeID\r
+ //\r
+ fprintf (OutFptr, "\n");\r
+ fprintf (OutFptr, "%d %s\n", HII_RESOURCE_NAME, HII_RESOURCE_TYPE);\r
+ fprintf (OutFptr, "{\n");\r
+\r
+ //\r
+ // Prepare package list\r
+ //\r
+ PackageListLen = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Package = PackageFiles;\r
+ while (Package != NULL) {\r
+ PackageListLen += Package->Length;\r
+ Package = Package->Next;\r
+ }\r
+ //\r
+ // Inlucde the length of EFI_HII_PACKAGE_END\r
+ //\r
+ PackageListLen += sizeof (EFI_HII_PACKAGE_HEADER);\r
+\r
+ Buffer = (UINT8 *) malloc (PackageListLen);\r
+ if (Buffer == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+ goto Done;\r
+ }\r
+ PackageList = Buffer;\r
+\r
+ memcpy (Buffer, PackageListGuid, sizeof (EFI_GUID));\r
+ Buffer += sizeof (EFI_GUID);\r
+ memcpy (Buffer, &PackageListLen, sizeof (UINT32));\r
+ Buffer += sizeof (UINT32);\r
+\r
+ Package = PackageFiles;\r
+ while (Package != NULL) {\r
+ memcpy (Buffer, Package->Data, Package->Length);\r
+ Buffer += Package->Length;\r
+ Package = Package->Next;\r
+ }\r
+ //\r
+ // Append EFI_HII_PACKAGE_END\r
+ //\r
+ ((EFI_HII_PACKAGE_HEADER *) Buffer)->Type = EFI_HII_PACKAGE_END;\r
+ ((EFI_HII_PACKAGE_HEADER *) Buffer)->Length = sizeof (EFI_HII_PACKAGE_HEADER);\r
+\r
+ //\r
+ // Dump package list\r
+ //\r
+ DumpRawBytes (OutFptr, PackageList, PackageListLen, 2);\r
+\r
+ //\r
+ // Write file tail\r
+ //\r
+ fprintf (OutFptr, "}\n");\r
+\r
+ Status = STATUS_SUCCESS;\r
+\r
+Done:\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+static\r
+STATUS\r
+CreatePackageList (\r
+ char *OutputFileName,\r
+ EFI_GUID *PackageListGuid,\r
+ FILE_NAME_LIST *PackageFiles\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Given a linked list of HII package files, walk the list to\r
+ process them and create a binary HII package list file.\r
+\r
+Arguments:\r
+\r
+ OutputFileName - name of output HII package list file to create\r
+ PackageListGuid - the specified package list GUID\r
+ PackageFiles - linked list of HII package files to process\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - if successful\r
+ STATUS_ERROR - otherwise\r
+\r
+--*/\r
+{\r
+ FILE *OutFptr;\r
+ UINT32 PackageListLen;\r
+ FILE_NAME_LIST *Package;\r
+\r
+ if (OutputFileName == NULL || PackageListGuid == NULL || PackageFiles == NULL) {\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ //\r
+ // Open the output file for writing\r
+ //\r
+ if ((OutFptr = fopen (OutputFileName, "wb")) == NULL) {\r
+ Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");\r
+ goto Done;\r
+ }\r
+\r
+ //\r
+ // Write package list header\r
+ //\r
+ PackageListLen = sizeof (EFI_HII_PACKAGE_LIST_HEADER);\r
+ Package = PackageFiles;\r
+ while (Package != NULL) {\r
+ PackageListLen += Package->Length;\r
+ Package = Package->Next;\r
+ }\r
+ fwrite (PackageListGuid, sizeof (UINT8), sizeof (EFI_GUID), OutFptr);\r
+ fwrite (&PackageListLen, sizeof (UINT8), sizeof (UINT32), OutFptr);\r
+\r
+ //\r
+ // Write packages\r
+ //\r
+ Package = PackageFiles;\r
+ while (Package != NULL) {\r
+ fwrite (Package->Data, sizeof (UINT8), Package->Length, OutFptr);\r
+ Package = Package->Next;\r
+ }\r
+\r
+Done:\r
+ if (OutFptr != NULL) {\r
+ fclose (OutFptr);\r
+ }\r
+\r
+ return STATUS_SUCCESS;\r
+}\r
+\r
+static\r
+void\r
+FreeGlobals (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Free up an memory we allocated so we can exit cleanly\r
+\r
+Arguments:\r
+\r
+Returns: NA\r
+\r
+--*/\r
+{\r
+ FILE_NAME_LIST *Next;\r
+\r
+ //\r
+ // Free up input package file names\r
+ //\r
+ while (mGlobals.PackageFile != NULL) {\r
+ Next = mGlobals.PackageFile->Next;\r
+ if (mGlobals.PackageFile->Data != NULL) {\r
+ free (mGlobals.PackageFile->Data);\r
+ }\r
+ free (mGlobals.PackageFile);\r
+ mGlobals.PackageFile = Next;\r
+ }\r
+}\r
+\r
+static\r
+void\r
+DumpRawBytes (\r
+ FILE *OutFptr,\r
+ UINT8 *Buffer,\r
+ int Count,\r
+ int Indent\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Dump buffer data into output file.\r
+\r
+Arguments:\r
+\r
+ OutFptr - FILE pointer to output file.\r
+ Buffer - the buffer to dump\r
+ Count - number of bytes to dump\r
+ Indent - indent at each line start\r
+\r
+Returns:\r
+\r
+ Nothing.\r
+\r
+--*/\r
+{\r
+ int Counter;\r
+ int Count2;\r
+ UINT16 *Ptr16;\r
+\r
+ Ptr16 = (UINT16 *) Buffer;\r
+ Count2 = Count - (Count & 0x1);\r
+\r
+ for (Counter = 0; Counter < Count2; Counter += 2) {\r
+ if ((Counter & 0xF) == 0) {\r
+ if (Counter == 0) {\r
+ fprintf (OutFptr, "%*c", Indent, ' ');\r
+ } else {\r
+ fprintf (OutFptr, "\n%*c", Indent, ' ');\r
+ }\r
+ }\r
+\r
+ fprintf (OutFptr, "0x%04X, ", (unsigned int) *Ptr16);\r
+ Ptr16++;\r
+ }\r
+\r
+ //\r
+ // Handle the last byte\r
+ //\r
+ if ((Count & 0x1) != 0) {\r
+ if ((Counter & 0xF) == 0) {\r
+ if (Counter == 0) {\r
+ fprintf (OutFptr, "%*c", Indent, ' ');\r
+ } else {\r
+ fprintf (OutFptr, "\n%*c", Indent, ' ');\r
+ }\r
+ }\r
+\r
+ fprintf (OutFptr, "0x%04X, ", (unsigned int) (*Ptr16 & 0xff));\r
+ }\r
+\r
+ fprintf (OutFptr, "\n");\r
+}\r
+\r
+static\r
+STATUS\r
+LoadPackage (\r
+ FILE_NAME_LIST *NameList\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Process the command line arguments\r
+\r
+Arguments:\r
+\r
+ NameList - the FILE_NAME_LIST linked list node\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - if successful\r
+ STATUS_ERROR - otherwise\r
+\r
+--*/\r
+{\r
+ STATUS Status;\r
+ FILE *InFptr;\r
+ UINT32 BufferSize;\r
+ UINT8 *Buffer;\r
+ EFI_HII_PACKAGE_HEADER *PackageHeader;\r
+ EFI_IFR_FORM_SET *FormSet;\r
+\r
+ Status = STATUS_SUCCESS;\r
+ if (NameList == NULL) {\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ //\r
+ // Try to open the package file\r
+ //\r
+ if ((InFptr = fopen (NameList->FileName, "rb")) == NULL) {\r
+ Error (NULL, 0, 0, NameList->FileName, "failed to open input file for read");\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ //\r
+ // Get the file size, then allocate a buffer and read in the file contents.\r
+ //\r
+ fseek (InFptr, 0, SEEK_END);\r
+ BufferSize = (UINT32) ftell (InFptr);\r
+ fseek (InFptr, 0, SEEK_SET);\r
+ Buffer = (UINT8 *) malloc (BufferSize);\r
+ if (Buffer == NULL) {\r
+ Error (NULL, 0, 0, "memory allocation failure", NULL);\r
+ goto Done;\r
+ }\r
+\r
+ if (fread (Buffer, sizeof (UINT8), BufferSize, InFptr) != BufferSize) {\r
+ Error (NULL, 0, 0, NameList->FileName, "error reading file contents");\r
+ Status = STATUS_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ NameList->Length = BufferSize;\r
+ NameList->Data = Buffer;\r
+\r
+ PackageHeader = (EFI_HII_PACKAGE_HEADER *) Buffer;\r
+ NameList->PackageType = PackageHeader->Type;\r
+\r
+ if (!mGlobals.GuidSpecified && NameList->PackageType == EFI_HII_PACKAGE_FORMS) {\r
+ FormSet = (EFI_IFR_FORM_SET *) (Buffer + sizeof (EFI_HII_PACKAGE_HEADER));\r
+ memcpy (&mGlobals.Guid, &FormSet->Guid, sizeof (EFI_GUID));\r
+ mGlobals.GuidSpecified = TRUE;\r
+ }\r
+\r
+Done:\r
+ fclose (InFptr);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+static\r
+STATUS\r
+ProcessArgs (\r
+ int Argc,\r
+ char *Argv[]\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Process the command line arguments\r
+\r
+Arguments:\r
+\r
+ As per standard C main()\r
+\r
+Returns:\r
+\r
+ STATUS_SUCCESS - if successful\r
+ STATUS_ERROR - otherwise\r
+\r
+--*/\r
+{\r
+ FILE_NAME_LIST *NewList;\r
+ STATUS Status;\r
+\r
+ Status = STATUS_SUCCESS;\r
+ memset ((void *) &mGlobals, 0, sizeof (mGlobals));\r
+\r
+ //\r
+ // Skip program name\r
+ //\r
+ Argc--;\r
+ Argv++;\r
+\r
+ if (Argc == 0) {\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ if (_stricmp (Argv[0], "-h") == 0 || _stricmp (Argv[0], "-?") == 0) {\r
+ Usage ();\r
+ return STATUS_ERROR;\r
+ }\r
+\r
+ //\r
+ // Process until no more args.\r
+ //\r
+ while (Argc > 0) {\r
+ if (_stricmp (Argv[0], "-rc") == 0) {\r
+ Argc--;\r
+ Argv++;\r
+\r
+ if (Argc == 0) {\r
+ Error (UTILITY_NAME, 0, 0, "mising HII resource file name", NULL);\r
+ Status = STATUS_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ strcpy (mGlobals.ResourceFileName, Argv[0]);\r
+ mGlobals.Mode |= MODE_CREATE_HII_RESOURCE_FILE;\r
+\r
+ } else if (_stricmp (Argv[0], "-hii") == 0) {\r
+ Argc--;\r
+ Argv++;\r
+\r
+ if (Argc == 0) {\r
+ Error (UTILITY_NAME, 0, 0, "mising HII package list file name", NULL);\r
+ Status = STATUS_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ strcpy (mGlobals.PackageListFileName, Argv[0]);\r
+ mGlobals.Mode |= MODE_CREATE_HII_PACKAGE_LIST;\r
+\r
+ } else if (_stricmp (Argv[0], "-g") == 0) {\r
+ Argc--;\r
+ Argv++;\r
+\r
+ if (Argc == 0) {\r
+ Error (UTILITY_NAME, 0, 0, "mising package list GUID", NULL);\r
+ Status = STATUS_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ Status = StringToGuid (Argv[0], &mGlobals.Guid);\r
+ if (Status != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ mGlobals.GuidSpecified = TRUE;\r
+\r
+ } else {\r
+ //\r
+ // This is a package file\r
+ //\r
+ NewList = malloc (sizeof (FILE_NAME_LIST));\r
+ if (NewList == NULL) {\r
+ Error (UTILITY_NAME, 0, 0, "memory allocation failure", NULL);\r
+ Status = STATUS_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+ memset (NewList, 0, sizeof (FILE_NAME_LIST));\r
+ strcpy (NewList->FileName, Argv[0]);\r
+\r
+ if (mGlobals.PackageFile == NULL) {\r
+ mGlobals.PackageFile = NewList;\r
+ } else {\r
+ mGlobals.LastPackageFile->Next = NewList;\r
+ }\r
+ mGlobals.LastPackageFile = NewList;\r
+\r
+ Status = LoadPackage (NewList);\r
+ if (Status != STATUS_SUCCESS) {\r
+ goto Done;\r
+ }\r
+ }\r
+\r
+ Argc--;\r
+ Argv++;\r
+ }\r
+\r
+ if (!mGlobals.GuidSpecified) {\r
+ Error (UTILITY_NAME, 0, 0, "please specify HII pakcage list GUID", NULL);\r
+ Status = STATUS_ERROR;\r
+ }\r
+\r
+Done:\r
+ if (Status != STATUS_SUCCESS) {\r
+ FreeGlobals ();\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+static\r
+void\r
+Usage (\r
+ VOID\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Print usage information for this utility.\r
+\r
+Arguments:\r
+\r
+ None.\r
+\r
+Returns:\r
+\r
+ Nothing.\r
+\r
+--*/\r
+{\r
+ int i;\r
+ const char *Str[] = {\r
+ UTILITY_NAME" "UTILITY_VERSION" - UEFI HII Package List Utility",\r
+ " Copyright (C), 2008 Intel Corporation",\r
+ \r
+#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )\r
+ " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,\r
+#endif\r
+ "",\r
+ "Usage:",\r
+ " "UTILITY_NAME" [OPTION] PACKAGE [PACKAGE [...]]",\r
+ "Description:",\r
+ " Merge HII package files into a single HII Package List.",\r
+ "Options:",\r
+ " -rc FileName write output to PE/COFF Resource Script file",\r
+ " -hii FileName write output to binary Package List file",\r
+ " -g GUID use GUID for the HII Package List Guid",\r
+ "",\r
+ "PACKAGE is the raw binary HII package file generated by StrGather or",\r
+ "VfrCompiler which named as *.hpk. For example, merge a Form package and",\r
+ "a String package into one HII package list:",\r
+ " \""UTILITY_NAME" -rc Sample.rc -hii Sample.hii \\",\r
+ " -g 12345678-1234-1234-1234-123456789abc Vfr.hpk Strings.hpk\"",\r
+ NULL\r
+ };\r
+ for (i = 0; Str[i] != NULL; i++) {\r
+ fprintf (stdout, "%s\n", Str[i]);\r
+ }\r
+}\r