Home | History | Annotate | Download | only in HiiPack
      1 /*++
      2 
      3 Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   HiiPack.c
     15 
     16 Abstract:
     17 
     18   Process HII export and pack files and create HII export files,
     19   dumps, or variable defaults packs.
     20 
     21 --*/
     22 
     23 #include <stdio.h>
     24 #include <string.h>
     25 #include <stdlib.h>
     26 #include <ctype.h>
     27 
     28 #include "Tiano.h"
     29 #include "EfiUtilityMsgs.h"
     30 #include "ParseInf.h"
     31 #include "EfiInternalFormRepresentation.h"
     32 #include "HiiPack.h"
     33 #include "Hii.h"
     34 #include "IfrParse.h"
     35 #include "StringParse.h"
     36 
     37 #define UTILITY_VERSION "v1.0"
     38 #define UTILITY_NAME    "HiiPack"
     39 #define MAX_PATH        260
     40 
     41 //
     42 // We may have to create an empty IFR formset to provide a GUID for an HII
     43 // export pack. Create a structure definition to make it easier.
     44 //
     45 #pragma pack(1)
     46 
     47 typedef struct {
     48   EFI_HII_IFR_PACK      PackHeader;
     49   EFI_IFR_FORM_SET      Formset;
     50   EFI_IFR_END_FORM_SET  EndFormset;
     51 } EMPTY_FORMSET_PACK;
     52 
     53 #pragma pack()
     54 //
     55 // We'll store lists of file names from the command line in
     56 // a linked list of these
     57 //
     58 typedef struct _FILE_NAME_LIST {
     59   struct _FILE_NAME_LIST  *Next;
     60   UINT8                   FileName[MAX_PATH];
     61   int                     Tag;  // used for whatever
     62 } FILE_NAME_LIST;
     63 
     64 //
     65 // When merging HII export packs, we save HII data table headers in a linked
     66 // list of these.
     67 //
     68 typedef struct _DATA_TABLE_HEADER_LIST {
     69   struct _DATA_TABLE_HEADER_LIST  *Next;
     70   EFI_HII_DATA_TABLE              DataTableHeader;
     71 } DATA_TABLE_HEADER_LIST;
     72 //
     73 // Create some defines for the different operation modes supported by this utility
     74 //
     75 #define MODE_CREATE_HII_EXPORT  1
     76 #define MODE_MERGE_HII_EXPORTS  2
     77 #define MODE_EMIT_DEFAULTS      3
     78 #define MODE_DUMP_HII_EXPORT    4
     79 //
     80 // Here's all our globals.
     81 //
     82 static struct {
     83   FILE_NAME_LIST  *PackFileNames;           // Input HII pack file names
     84   FILE_NAME_LIST  *HiiExportFileNames;      // Input files when merging
     85   CHAR8           OutputFileName[MAX_PATH]; // Output dump file
     86   BOOLEAN         MfgFlag;                  // From -mfg command line arg
     87   BOOLEAN         NoEmptyVarPacks;          // From -noemptyvarpacks command line arg
     88   BOOLEAN         NoVarPacks;               // From -novarpacks command line arg
     89   EFI_GUID        Guid;                     // Guid specified on command line
     90   BOOLEAN         GuidSpecified;
     91   BOOLEAN         DumpStrings;              // In dump mode, dump string data
     92   int             Verbose;
     93   int             Mode;                     // Mode this utility is operating in
     94 } mGlobals;
     95 
     96 static
     97 void
     98 Usage (
     99   VOID
    100   );
    101 
    102 static
    103 STATUS
    104 ProcessArgs (
    105   int   Argc,
    106   char  *Argv[]
    107   );
    108 
    109 static
    110 STATUS
    111 DumpHiiExportFile (
    112   char    *HiiExportFileName,
    113   char    *OutputFileName
    114   );
    115 
    116 static
    117 void
    118 DumpString (
    119   FILE    *OutFptr,
    120   int     StringIndex,
    121   CHAR16  *Str,
    122   int     Indent
    123   );
    124 
    125 static
    126 void
    127 DumpStringPack (
    128   FILE                  *OutFptr,
    129   EFI_HII_STRING_PACK   *Pack,
    130   int                   BaseOffset,
    131   int                   Indent
    132   );
    133 
    134 static
    135 void
    136 DumpVariablePacks (
    137   FILE                  *OutFptr,
    138   EFI_HII_VARIABLE_PACK *Pack,
    139   int                   NumPacks,
    140   int                   BaseOffset,
    141   int                   Indent
    142   );
    143 
    144 static
    145 void
    146 TestDumpHiiPack (
    147   FILE    *OutFptr,
    148   char    *BufferStart,
    149   int     BufferSize
    150   );
    151 
    152 static
    153 void
    154 DumpRawBytes (
    155   FILE                  *OutFptr,
    156   char                  *Buffer,
    157   int                   Count,
    158   int                   BaseOffset,
    159   int                   Indent
    160   );
    161 
    162 static
    163 void
    164 DumpIfrPack (
    165   FILE                  *OutFptr,
    166   EFI_HII_IFR_PACK      *Pack,
    167   int                   BaseOffset,
    168   int                   Indent
    169   );
    170 
    171 static
    172 void
    173 FreeGlobals (
    174   VOID
    175   );
    176 
    177 static
    178 STATUS
    179 AddStringPack (
    180   EFI_HII_STRING_PACK   *PackHeader
    181   );
    182 
    183 static
    184 STATUS
    185 ProcessHiiExportFile (
    186   char    *FileName,
    187   int     MfgDefaults
    188   );
    189 
    190 static
    191 STATUS
    192 ProcessIfrFiles (
    193   FILE_NAME_LIST *FileName
    194   );
    195 
    196 static
    197 STATUS
    198 EmitDefaults (
    199   FILE_NAME_LIST *HiiExportFiles,
    200   int            MfgDefaults,
    201   int            NoEmptyVarPacks
    202   );
    203 
    204 static
    205 STATUS
    206 MergeHiiExports (
    207   FILE_NAME_LIST *HiiExportFiles,
    208   char           *OutputFileName,
    209   int            MfgDefaults,
    210   int            NoEmptyVarPacks
    211   );
    212 
    213 void
    214 GuidToString (
    215   EFI_GUID   *Guid,
    216   char       *Str
    217   );
    218 
    219 static
    220 CHAR16  *
    221 AsciiToWchar (
    222   CHAR8 *Str
    223   );
    224 
    225 static
    226 STATUS
    227 CreateHiiExport (
    228   char              *OutputFileName,
    229   EFI_GUID          *DummyFormsetGuid,
    230   FILE_NAME_LIST    *PackFiles,
    231   int               MfgDefaults
    232   );
    233 
    234 int
    235 main (
    236   int   Argc,
    237   char  *Argv[]
    238   )
    239 /*++
    240 
    241 Routine Description:
    242 
    243   Call the routine to parse the command-line options, then process the file.
    244 
    245 Arguments:
    246 
    247   Standard C main() argc and argv.
    248 
    249 Returns:
    250 
    251   0       if successful
    252   nonzero otherwise
    253 
    254 --*/
    255 // GC_TODO:    Argc - add argument and description to function comment
    256 // GC_TODO:    ] - add argument and description to function comment
    257 {
    258   STATUS  Status;
    259   //
    260   // Set the utility name for error reporting purposes
    261   //
    262   SetUtilityName (UTILITY_NAME);
    263   //
    264   // Process the command-line arguments
    265   //
    266   Status = ProcessArgs (Argc, Argv);
    267   if (Status != STATUS_SUCCESS) {
    268     return Status;
    269   }
    270   //
    271   // Switch based on whether we're dumping, merging, etc.
    272   //
    273   if (mGlobals.Mode == MODE_DUMP_HII_EXPORT) {
    274     if (mGlobals.Verbose) {
    275       fprintf (stdout, "Dumping HII export file %s => %s\n", mGlobals.HiiExportFileNames, mGlobals.OutputFileName);
    276     }
    277 
    278     DumpHiiExportFile (mGlobals.HiiExportFileNames->FileName, mGlobals.OutputFileName);
    279   } else if (mGlobals.Mode == MODE_CREATE_HII_EXPORT) {
    280     CreateHiiExport (mGlobals.OutputFileName, &mGlobals.Guid, mGlobals.PackFileNames, mGlobals.MfgFlag);
    281   } else if (mGlobals.Mode == MODE_MERGE_HII_EXPORTS) {
    282     MergeHiiExports (mGlobals.HiiExportFileNames, mGlobals.OutputFileName, mGlobals.MfgFlag, mGlobals.NoEmptyVarPacks);
    283   } else if (mGlobals.Mode == MODE_EMIT_DEFAULTS) {
    284     EmitDefaults (mGlobals.HiiExportFileNames, mGlobals.MfgFlag, mGlobals.NoEmptyVarPacks);
    285   }
    286   //
    287   //
    288   FreeGlobals ();
    289   IfrParseEnd ();
    290   StringEnd ();
    291   return GetUtilityStatus ();
    292 }
    293 
    294 /******************************************************************************/
    295 static
    296 STATUS
    297 MergeHiiExports (
    298   FILE_NAME_LIST *HiiExportFiles,
    299   char           *OutputFileName,
    300   int            MfgDefaults,
    301   int            NoEmptyVarPacks
    302   )
    303 /*++
    304 
    305 Routine Description:
    306 
    307   Given a linked list of input HII export pack files, read in the contents
    308   of each and create a single HII export pack that contains the contents
    309   of all the input files.
    310 
    311 Arguments:
    312 
    313   HiiExportFiles    - pointer to linked list of input HII export pack file names
    314   OutputFileName    - name of output (merged) HII export file
    315   MfgDefaults       - non-zero to emit manufacturing defaults in output file
    316   NoEmptyVarPacks   - non-zero to not emit 0-length variable packs to the output file
    317 
    318 Returns:
    319 
    320   STATUS_SUCCESS    - if successful
    321   STATUS_ERROR      - otherwise
    322 
    323 --*/
    324 {
    325   EFI_HII_HANDLE          HiiHandle;
    326   FILE                    *OutFptr;
    327   FILE                    *InFptr;
    328   STATUS                  Status;
    329   CHAR8                   *Buffer;
    330   int                     FileSize;
    331   int                     DataTableIndex;
    332   int                     Count;
    333   int                     NumDataTables;
    334   EFI_HII_EXPORT_TABLE    *HiiExportTableHeader;
    335   EFI_HII_EXPORT_TABLE    TempHiiExportTableHeader;
    336   EFI_HII_DATA_TABLE      *DataTableHeader;
    337   EFI_HII_STRING_PACK     *StringPack;
    338   EFI_HII_VARIABLE_PACK   *VarPack;
    339   EFI_HII_IFR_PACK        *IfrPack;
    340   EFI_GUID                HiiExportRevisionGuid = EFI_HII_PROTOCOL_GUID;
    341   EFI_GUID                PackageGuid;
    342   EFI_GUID                FormsetGuid;
    343   long                    DataTableHeaderOffset;
    344   DATA_TABLE_HEADER_LIST  *DataTableList;
    345   DATA_TABLE_HEADER_LIST  *LastDataTable;
    346   DATA_TABLE_HEADER_LIST  *TempDataTable;
    347   //
    348   // Init locals
    349   //
    350   HiiHandle     = FIRST_HII_PACK_HANDLE;
    351   Buffer        = NULL;
    352   InFptr        = NULL;
    353   OutFptr       = NULL;
    354   Status        = STATUS_ERROR;
    355   DataTableList = NULL;
    356   LastDataTable = NULL;
    357   //
    358   // Initialize our IFR parser and string routines
    359   //
    360   IfrParseInit ();
    361   StringInit ();
    362   //
    363   // Process each input HII export file
    364   //
    365   NumDataTables = 0;
    366   while (HiiExportFiles != NULL) {
    367     if (mGlobals.Verbose) {
    368       fprintf (stdout, "Processing file %s\n", HiiExportFiles->FileName);
    369     }
    370     //
    371     // Read in the entire file contents
    372     //
    373     if ((InFptr = fopen (HiiExportFiles->FileName, "rb")) == NULL) {
    374       Error (NULL, 0, 0, HiiExportFiles->FileName, "failed to open HII export file for reading");
    375       goto Done;
    376     }
    377 
    378     fseek (InFptr, 0, SEEK_END);
    379     FileSize = (int) ftell (InFptr);
    380     fseek (InFptr, 0, SEEK_SET);
    381     Buffer = (CHAR8 *) malloc (FileSize);
    382     if (Buffer == NULL) {
    383       Error (NULL, 0, 0, "memory allocation failure", NULL);
    384       goto Done;
    385     }
    386 
    387     if (fread (Buffer, FileSize, 1, InFptr) != 1) {
    388       Error (NULL, 0, 0, HiiExportFiles->FileName, "failed to read file contents");
    389       goto Done;
    390     }
    391 
    392     fclose (InFptr);
    393     InFptr                = NULL;
    394     HiiExportTableHeader  = (EFI_HII_EXPORT_TABLE *) Buffer;
    395     //
    396     // Walk all the data tables
    397     //
    398     DataTableHeader = (EFI_HII_DATA_TABLE *) (HiiExportTableHeader + 1);
    399     for (DataTableIndex = 0; DataTableIndex < (int) HiiExportTableHeader->NumberOfHiiDataTables; DataTableIndex++) {
    400       NumDataTables++;
    401       //
    402       // Make sure we're still pointing into our buffer
    403       //
    404       if (((char *) DataTableHeader < Buffer) || ((char *) DataTableHeader > Buffer + FileSize)) {
    405         Error (NULL, 0, 0, "bad data table size in input file", NULL);
    406         goto Done;
    407       }
    408       //
    409       // Save a copy of the data table header
    410       //
    411       TempDataTable = (DATA_TABLE_HEADER_LIST *) malloc (sizeof (DATA_TABLE_HEADER_LIST));
    412       if (TempDataTable == NULL) {
    413         Error (NULL, 0, 0, "memory allocation failure", NULL);
    414         goto Done;
    415       }
    416 
    417       memset ((void *) TempDataTable, 0, sizeof (DATA_TABLE_HEADER_LIST));
    418       memcpy (&TempDataTable->DataTableHeader, DataTableHeader, sizeof (EFI_HII_DATA_TABLE));
    419       if (DataTableList == NULL) {
    420         DataTableList = TempDataTable;
    421       } else {
    422         LastDataTable->Next = TempDataTable;
    423       }
    424 
    425       LastDataTable = TempDataTable;
    426       //
    427       // If there is an IFR pack, parse it
    428       //
    429       if (DataTableHeader->IfrDataOffset != 0) {
    430         if (IfrParsePack (
    431             HiiHandle,
    432             (EFI_HII_IFR_PACK *) ((char *) DataTableHeader + DataTableHeader->IfrDataOffset),
    433             &DataTableHeader->PackageGuid
    434             ) != STATUS_SUCCESS
    435             ) {
    436           goto Done;
    437         }
    438       }
    439       //
    440       // If there is string data, save it
    441       //
    442       if (DataTableHeader->StringDataOffset != 0) {
    443         Status = StringParsePack (
    444                   HiiHandle,
    445                   (EFI_HII_STRING_PACK *) ((char *) DataTableHeader + DataTableHeader->StringDataOffset),
    446                   NULL,
    447                   &DataTableHeader->PackageGuid
    448                   );
    449         if (Status != STATUS_SUCCESS) {
    450           goto Done;
    451         }
    452       }
    453       //
    454       // If there is device path data, process it
    455       //
    456       if (DataTableHeader->DevicePathOffset != 0) {
    457         Error (NULL, 0, 0, "application error", "%s contains unsupported device path data", HiiExportFiles->FileName);
    458         goto Done;
    459       }
    460       //
    461       // Next data pack
    462       //
    463       DataTableHeader = (EFI_HII_DATA_TABLE *) ((char *) DataTableHeader + DataTableHeader->DataTableSize);
    464       HiiHandle++;
    465     }
    466 
    467     free (Buffer);
    468     Buffer = NULL;
    469     //
    470     // Next input file
    471     //
    472     HiiExportFiles = HiiExportFiles->Next;
    473   }
    474   //
    475   // Now create defaults
    476   //
    477   if (IfrSetDefaults (MfgDefaults) != STATUS_SUCCESS) {
    478     goto Done;
    479   }
    480   //
    481   // Create and write the output HII export header
    482   //
    483   if ((OutFptr = fopen (OutputFileName, "wb")) == NULL) {
    484     Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
    485     goto Done;
    486   }
    487 
    488   memset ((void *) &TempHiiExportTableHeader, 0, sizeof (EFI_HII_EXPORT_TABLE));
    489   TempHiiExportTableHeader.NumberOfHiiDataTables = HiiHandle - FIRST_HII_PACK_HANDLE;
    490   memcpy (&TempHiiExportTableHeader.Revision, &HiiExportRevisionGuid, sizeof (EFI_GUID));
    491   if (fwrite ((void *) &TempHiiExportTableHeader, sizeof (EFI_HII_EXPORT_TABLE), 1, OutFptr) != 1) {
    492     Error (NULL, 0, 0, OutputFileName, "failed to write HII export table header to output file");
    493     goto Done;
    494   }
    495   //
    496   // Now go back through all the handles and create new data packs for each, writing out
    497   // the contents as we go.
    498   //
    499   HiiHandle = FIRST_HII_PACK_HANDLE;
    500   for (TempDataTable = DataTableList; TempDataTable != NULL; TempDataTable = TempDataTable->Next) {
    501     //
    502     // Write a data table header to the output file. We'll rewind the file and
    503     // write an updated one when we're done with this data set
    504     //
    505     DataTableHeaderOffset                         = ftell (OutFptr);
    506     TempDataTable->DataTableHeader.HiiHandle      = HiiHandle;
    507     TempDataTable->DataTableHeader.DataTableSize  = sizeof (EFI_HII_DATA_TABLE);
    508     //
    509     // We may change the number of variable data when merging export files, so init to 0
    510     //
    511     TempDataTable->DataTableHeader.NumberOfVariableData = 0;
    512     if (fwrite ((void *) &TempDataTable->DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
    513       Error (NULL, 0, 0, OutputFileName, "failed to write HII data table header to output file");
    514       goto Done;
    515     }
    516     //
    517     // Get the string pack if any
    518     //
    519     Status = StringGetPack (HiiHandle, &StringPack, &FileSize, &Count, &FormsetGuid, &PackageGuid);
    520     if (Status == STATUS_SUCCESS) {
    521       TempDataTable->DataTableHeader.StringDataOffset = TempDataTable->DataTableHeader.DataTableSize;
    522       TempDataTable->DataTableHeader.DataTableSize += FileSize;
    523       //
    524       // TempDataTable->DataTableHeader.NumberOfLanguages should be unchanged
    525       //
    526       if (fwrite ((void *) StringPack, FileSize, 1, OutFptr) != 1) {
    527         Error (NULL, 0, 0, "failed to write string pack to output file", NULL);
    528         goto Done;
    529       }
    530     }
    531     //
    532     // Get the IFR pack
    533     //
    534     Status = IfrGetIfrPack (HiiHandle, &IfrPack, &FormsetGuid);
    535     if (Status == STATUS_SUCCESS) {
    536       //
    537       // Write the IFR pack, followed by the variable packs
    538       //
    539       TempDataTable->DataTableHeader.IfrDataOffset = TempDataTable->DataTableHeader.DataTableSize;
    540       TempDataTable->DataTableHeader.DataTableSize += IfrPack->Header.Length;
    541       if (fwrite ((void *) IfrPack, IfrPack->Header.Length, 1, OutFptr) != 1) {
    542         Error (NULL, 0, 0, "failed to write IFR pack to output file", NULL);
    543         goto Done;
    544       }
    545       //
    546       // If this is just a formset stub, then don't write the variable packs
    547       //
    548       if (IfrPack->Header.Length != sizeof (EMPTY_FORMSET_PACK)) {
    549         //
    550         // Go through all the variable packs and see if they're referenced by this IFR
    551         //
    552         Count = 0;
    553         do {
    554           Status = IfrGetVarPack (Count, &VarPack);
    555           if (Status == STATUS_SUCCESS) {
    556             //
    557             // Check for variable data length of 0
    558             //
    559             if ((NoEmptyVarPacks == 0) ||
    560                 ((VarPack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - VarPack->VariableNameLength) != 0)
    561                 ) {
    562               //
    563               // See if it's referenced by this IFR
    564               //
    565               if (IfrReferencesVarPack (HiiHandle, VarPack) == STATUS_SUCCESS) {
    566                 if (TempDataTable->DataTableHeader.VariableDataOffset == 0) {
    567                   TempDataTable->DataTableHeader.VariableDataOffset = TempDataTable->DataTableHeader.DataTableSize;
    568                 }
    569 
    570                 TempDataTable->DataTableHeader.DataTableSize += VarPack->Header.Length;
    571                 TempDataTable->DataTableHeader.NumberOfVariableData++;
    572                 if (fwrite ((void *) VarPack, VarPack->Header.Length, 1, OutFptr) != 1) {
    573                   Error (NULL, 0, 0, "failed to write variable pack to output file", NULL);
    574                   goto Done;
    575                 }
    576 
    577               }
    578             }
    579           }
    580 
    581           Count++;
    582         } while (Status == STATUS_SUCCESS);
    583       }
    584 
    585       Status = STATUS_SUCCESS;
    586     }
    587     //
    588     // Get the device path pack
    589     //
    590     //
    591     // Rewind the file and write the updated data table header.
    592     //
    593     fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
    594     if (fwrite ((void *) &TempDataTable->DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
    595       Error (NULL, 0, 0, OutputFileName, "failed to write HII data table header to output file");
    596       goto Done;
    597     }
    598 
    599     fseek (OutFptr, 0, SEEK_END);
    600     HiiHandle++;
    601   }
    602 
    603   Status = STATUS_SUCCESS;
    604 Done:
    605   IfrParseEnd ();
    606   StringEnd ();
    607   if (Buffer != NULL) {
    608     free (Buffer);
    609   }
    610 
    611   if (InFptr != NULL) {
    612     fclose (InFptr);
    613   }
    614 
    615   if (OutFptr != NULL) {
    616     fclose (OutFptr);
    617   }
    618 
    619   while (DataTableList != NULL) {
    620     TempDataTable = DataTableList->Next;
    621     free (DataTableList);
    622     DataTableList = TempDataTable;
    623   }
    624 
    625   return Status;
    626 }
    627 
    628 /******************************************************************************/
    629 static
    630 STATUS
    631 CreateHiiExport (
    632   char              *OutputFileName,
    633   EFI_GUID          *DummyFormsetGuid,
    634   FILE_NAME_LIST    *PackFiles,
    635   int               MfgDefaults
    636   )
    637 /*++
    638 
    639 Routine Description:
    640 
    641   Given a linked list of HII pack file names, walk the list to
    642   process them and create a single HII export file.
    643 
    644 Arguments:
    645 
    646   OutputFileName    - name of output HII export file to create
    647   DummyFormsetGuid  - IFR formsets contain a GUID which is used in many
    648                       places while processing data tables. If we were not
    649                       given an IFR pack, then we'll create a stub IFR
    650                       pack using this GUID as the formset GUID.
    651   PackFiles         - linked list of HII pack files to process
    652   MfgDefaults       - when creating variable packs (via IFR pack processing),
    653                       use manufacturing defaults rather than standard defaults
    654 
    655 Returns:
    656 
    657   STATUS_SUCCESS    - if successful
    658   STATUS_ERROR      - otherwise
    659 
    660 --*/
    661 {
    662   STATUS                      Status;
    663   EMPTY_FORMSET_PACK          EmptyFormset;
    664   EFI_HII_DATA_TABLE          DataTableHeader;
    665   EFI_HII_EXPORT_TABLE        ExportTableHeader;
    666   long                        DataTableHeaderOffset;
    667   long                        FileSize;
    668   FILE                        *OutFptr;
    669   FILE                        *InFptr;
    670   FILE_NAME_LIST              *TempFile;
    671   EFI_GUID                    HiiExportRevisionGuid = EFI_HII_PROTOCOL_GUID;
    672   EFI_GUID                    TempGuid;
    673   EFI_GUID                    PackageGuid;
    674   char                        *Buffer;
    675   EFI_HII_VARIABLE_PACK       *VarPack;
    676   EFI_HII_IFR_PACK            *IfrPack;
    677   EFI_HII_STRING_PACK_HEADER  *StringPack;
    678   EFI_HII_STRING_PACK_HEADER  TerminatorStringPack;
    679   int                         NumIfr;
    680   int                         NumStrings;
    681   int                         Index;
    682   int                         VarPackIndex;
    683   //
    684   // If no input HII pack files, then why are we here? Should have been caught when
    685   // args were processed though.
    686   //
    687   if (PackFiles == NULL) {
    688     Error (NULL, 0, 0, "no input pack files specified", NULL);
    689     return STATUS_ERROR;
    690   }
    691 
    692   InFptr  = NULL;
    693   Status  = STATUS_ERROR;
    694   Buffer  = NULL;
    695   //
    696   // Open the output file for writing
    697   //
    698   if ((OutFptr = fopen (OutputFileName, "wb")) == NULL) {
    699     Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
    700     goto Done;
    701   }
    702   //
    703   // Figure out how many data tables we are going to need. We'll create one
    704   // data table if no more than one IFR, or we'll create one data table per IFR,
    705   // and then one for strings if multiple IFR
    706   //
    707   NumIfr      = 0;
    708   NumStrings  = 0;
    709   for (TempFile = PackFiles; TempFile != NULL; TempFile = TempFile->Next) {
    710     if (TempFile->Tag == EFI_HII_IFR) {
    711       NumIfr++;
    712     } else if (TempFile->Tag == EFI_HII_STRING) {
    713       NumStrings++;
    714     }
    715   }
    716   //
    717   // Three possibilities:
    718   //  1) No IFR, so create one data table that contains only strings and an empty formset
    719   //  2) Only 1 IFR, so create an export table with one data table that contains the IFR
    720   //     and all the strings
    721   //  3) Multiple IFR, so create a data table for each IFR and another data table with
    722   //     all the strings.
    723   //
    724   // Initialize the export table header and write it out
    725   //
    726   memset ((void *) &ExportTableHeader, 0, sizeof (EFI_HII_EXPORT_TABLE));
    727   if (NumIfr < 2) {
    728     ExportTableHeader.NumberOfHiiDataTables = 1;
    729   } else {
    730     //
    731     // One data table per IFR, plus one for strings (if any).
    732     //
    733     ExportTableHeader.NumberOfHiiDataTables = (UINT16) NumIfr;
    734     if (NumStrings != 0) {
    735       ExportTableHeader.NumberOfHiiDataTables++;
    736     }
    737   }
    738   //
    739   // Init the GUID in the HII export table header
    740   //
    741   memcpy (&ExportTableHeader.Revision, &HiiExportRevisionGuid, sizeof (EFI_GUID));
    742   if (fwrite ((void *) &ExportTableHeader, sizeof (EFI_HII_EXPORT_TABLE), 1, OutFptr) != 1) {
    743     Error (NULL, 0, 0, OutputFileName, "failed to write HII export table header to output file");
    744     goto Done;
    745   }
    746   //
    747   // *****************************************************************************************
    748   //
    749   //  CASE 1 - No IFR => one data table that contains only strings and an empty formset.
    750   //           No variable data.
    751   //
    752   //  CASE 2 - Only 1 IFR => create an export table with one data table that contains the IFR
    753   //           and all the strings plus variable data
    754   //
    755   //  CASE 3 - Multiple IFR => create a data table for each IFR and another data table with
    756   //           all the strings. Each IFR data table has variable data if applicable.
    757   //
    758   // *****************************************************************************************
    759   //
    760   // If the user did not give us an IFR file, then we'll have to create an empty formset
    761   // and emit it to the output file. In this case, we need a formset GUID on the command
    762   // line.
    763   //
    764   if ((NumIfr == 0) && (mGlobals.GuidSpecified == 0)) {
    765     //
    766     //    Warning (NULL, 0, 0, "using NULL GUID for empty formset", "specify -g GUID on the command line if desired");
    767     //
    768     memset ((void *) &PackageGuid, 0, sizeof (EFI_GUID));
    769   } else if (mGlobals.GuidSpecified) {
    770     //
    771     // Use it for the package GUID
    772     //
    773     memcpy (&PackageGuid, &mGlobals.Guid, sizeof (EFI_GUID));
    774   }
    775   //
    776   // Init the data table header.
    777   // Write out the blank data table header. Save the offset so we can
    778   // write an updated version at the end of processing.
    779   //
    780   memset ((void *) &DataTableHeader, 0, sizeof (EFI_HII_DATA_TABLE));
    781   DataTableHeaderOffset     = ftell (OutFptr);
    782   DataTableHeader.HiiHandle = FIRST_HII_PACK_HANDLE;
    783   if (mGlobals.Verbose) {
    784     fprintf (stdout, "writing data table (first time) to offset 0x%X\n", ftell (OutFptr));
    785   }
    786 
    787   if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
    788     Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
    789     goto Done;
    790   }
    791   //
    792   // Set the data table size, then write out all the string packs
    793   //
    794   DataTableHeader.DataTableSize = sizeof (EFI_HII_DATA_TABLE);
    795   //
    796   // Write out the string files to a single data record
    797   //
    798   for (TempFile = PackFiles; TempFile != NULL; TempFile = TempFile->Next) {
    799     //
    800     // Continue to next file if it's not a string pack file
    801     //
    802     if (TempFile->Tag != EFI_HII_STRING) {
    803       continue;
    804     }
    805     //
    806     // Set the offset in the header if this is the first string pack
    807     //
    808     if (DataTableHeader.StringDataOffset == 0) {
    809       DataTableHeader.StringDataOffset = DataTableHeader.DataTableSize;
    810     }
    811 
    812     if ((InFptr = fopen (TempFile->FileName, "rb")) == NULL) {
    813       Error (NULL, 0, 0, TempFile->FileName, "failed to open input string pack file for reading");
    814       goto Done;
    815     }
    816     //
    817     // Get the file size, then read it into a buffer
    818     //
    819     fseek (InFptr, 0, SEEK_END);
    820     FileSize = ftell (InFptr);
    821     fseek (InFptr, 0, SEEK_SET);
    822     Buffer = (char *) malloc (FileSize);
    823     if (Buffer == NULL) {
    824       Error (NULL, 0, 0, TempFile->FileName, "memory allocation failure reading in file contents");
    825       goto Done;
    826     }
    827 
    828     if (fread (Buffer, FileSize, 1, InFptr) != 1) {
    829       Error (NULL, 0, 0, TempFile->FileName, "failed to read file contents");
    830       goto Done;
    831     }
    832 
    833     fclose (InFptr);
    834     InFptr = NULL;
    835     //
    836     // Verify that it's actually a string pack
    837     //
    838     StringPack = (EFI_HII_STRING_PACK_HEADER *) Buffer;
    839     while ((char *) StringPack < Buffer + FileSize) {
    840       if (StringPack->Header.Type != EFI_HII_STRING) {
    841         Error (NULL, 0, 0, TempFile->FileName, "file does not consist entirely of string packs");
    842         goto Done;
    843       }
    844 
    845       if (StringPack->Header.Length == 0) {
    846         break;
    847       }
    848 
    849       DataTableHeader.NumberOfLanguages++;
    850       DataTableHeader.DataTableSize += StringPack->Header.Length;
    851       //
    852       // Write the string pack to the output file
    853       //
    854       if (mGlobals.Verbose) {
    855         fprintf (stdout, "writing string pack to offset 0x%X\n", ftell (OutFptr));
    856       }
    857 
    858       if (fwrite (StringPack, StringPack->Header.Length, 1, OutFptr) != 1) {
    859         Error (NULL, 0, 0, TempFile->FileName, "failed to write string pack to output file");
    860         goto Done;
    861       }
    862       //
    863       // Sanity check that adding the length advances us (no wrap)
    864       //
    865       if ((char *) StringPack + StringPack->Header.Length <= (char *) StringPack) {
    866         Error (NULL, 0, 0, TempFile->FileName, "invalid pack size in file");
    867         goto Done;
    868       }
    869 
    870       StringPack = (EFI_HII_STRING_PACK_HEADER *) ((char *) StringPack + StringPack->Header.Length);
    871     }
    872     //
    873     // Free up buffer, go to next input string pack file
    874     //
    875     free (Buffer);
    876     Buffer = NULL;
    877   }
    878   //
    879   // Write a null-terminator string pack if we had any string packs at all
    880   //
    881   if (DataTableHeader.StringDataOffset != 0) {
    882     memset (&TerminatorStringPack, 0, sizeof (EFI_HII_STRING_PACK_HEADER));
    883     TerminatorStringPack.Header.Length  = 0;
    884     TerminatorStringPack.Header.Type    = EFI_HII_STRING;
    885     if (mGlobals.Verbose) {
    886       fprintf (stdout, "writing terminator string pack to offset 0x%X\n", ftell (OutFptr));
    887     }
    888 
    889     if (fwrite (&TerminatorStringPack, sizeof (EFI_HII_STRING_PACK_HEADER), 1, OutFptr) != 1) {
    890       Error (NULL, 0, 0, "failed to write string pack terminator to output file", NULL);
    891       goto Done;
    892     }
    893 
    894     DataTableHeader.DataTableSize += sizeof (EFI_HII_STRING_PACK_HEADER);
    895   }
    896   //
    897   // Parse all the IFR packs, then get the GUID from the first
    898   // one so we can use it for the package GUID if necessary.
    899   //
    900   memcpy (&PackageGuid, &mGlobals.Guid, sizeof (EFI_GUID));
    901   if (NumIfr != 0) {
    902     IfrParseInit ();
    903     if (ProcessIfrFiles (PackFiles) != STATUS_SUCCESS) {
    904       goto Done;
    905     }
    906     //
    907     // Set variable defaults in all variable packs
    908     //
    909     IfrSetDefaults (MfgDefaults);
    910     //
    911     // Get the GUID from the first IFR pack if the user did not specify a GUID on
    912     // the command line.
    913     //
    914     if (mGlobals.GuidSpecified == 0) {
    915       if (IfrGetIfrPack (FIRST_HII_PACK_HANDLE, &IfrPack, &PackageGuid) != STATUS_SUCCESS) {
    916         Error (NULL, 0, 0, "internal application error", "failed to retrieve IFR pack after parsing");
    917         goto Done;
    918       }
    919     }
    920   }
    921   //
    922   // Set the package GUID in the data table header.
    923   //
    924   memcpy (&DataTableHeader.PackageGuid, &PackageGuid, sizeof (EFI_GUID));
    925   //
    926   // If no IFR, then create and write the empty formset. Otherwise
    927   // parse the IFR and emit it and the variable data for it.
    928   //
    929   if (NumIfr == 0) {
    930     memset ((void *) &EmptyFormset, 0, sizeof (EMPTY_FORMSET_PACK));
    931     EmptyFormset.PackHeader.Header.Type   = EFI_HII_IFR;
    932     EmptyFormset.PackHeader.Header.Length = sizeof (EMPTY_FORMSET_PACK);
    933     //
    934     // Formset Opcode
    935     //
    936     EmptyFormset.Formset.Header.OpCode  = EFI_IFR_FORM_SET_OP;
    937     EmptyFormset.Formset.Header.Length  = (UINT8) sizeof (EFI_IFR_FORM_SET);
    938     memcpy (&EmptyFormset.Formset.Guid, &PackageGuid, sizeof (EFI_GUID));
    939     //
    940     // EndFormset Opcode
    941     //
    942     EmptyFormset.EndFormset.Header.OpCode = EFI_IFR_END_FORM_SET_OP;
    943     EmptyFormset.EndFormset.Header.Length = (UINT8) sizeof (EFI_IFR_END_FORM_SET);
    944     DataTableHeader.IfrDataOffset         = DataTableHeader.DataTableSize;
    945     if (mGlobals.Verbose) {
    946       fprintf (stdout, "writing stub IFR formset to to offset 0x%X\n", ftell (OutFptr));
    947     }
    948 
    949     if (fwrite (&EmptyFormset, sizeof (EMPTY_FORMSET_PACK), 1, OutFptr) != 1) {
    950       Error (NULL, 0, 0, OutputFileName, "failed to write formset stub to output file");
    951       goto Done;
    952     }
    953 
    954     DataTableHeader.DataTableSize += sizeof (EMPTY_FORMSET_PACK);
    955     //
    956     // Go back and re-write the data table header, reposition to the end, then return.
    957     //
    958     fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
    959     if (mGlobals.Verbose) {
    960       fprintf (stdout, "writing data table (second time) to offset 0x%X\n", ftell (OutFptr));
    961     }
    962 
    963     if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
    964       Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
    965       goto Done;
    966     }
    967 
    968     fseek (OutFptr, 0, SEEK_END);
    969     if (mGlobals.Verbose) {
    970       fprintf (
    971         stdout,
    972         "final file offset=0x%X DataTableHeader.DataTableSize=0x%X\n",
    973         ftell (OutFptr),
    974         DataTableHeader.DataTableSize
    975         );
    976     }
    977   } else if (NumIfr == 1) {
    978     //
    979     // They gave us one input IFR file. We parsed it above, so get each one
    980     // and emit the IFR and each variable pack it references.
    981     // Update the data pack header for the IFR pack, then write the IFR pack data
    982     //
    983     DataTableHeader.IfrDataOffset = DataTableHeader.DataTableSize;
    984     if (IfrGetIfrPack (FIRST_HII_PACK_HANDLE, &IfrPack, &TempGuid) != STATUS_SUCCESS) {
    985       Error (NULL, 0, 0, "internal application error", "failed to retrieve IFR pack after parsing");
    986       goto Done;
    987     }
    988 
    989     if (mGlobals.Verbose) {
    990       fprintf (stdout, "writing IFR pack to 0x%X\n", ftell (OutFptr));
    991     }
    992 
    993     if (fwrite (IfrPack, IfrPack->Header.Length, 1, OutFptr) != 1) {
    994       Error (NULL, 0, 0, OutputFileName, "failed to write IFR pack to output file");
    995       goto Done;
    996     }
    997 
    998     DataTableHeader.DataTableSize += IfrPack->Header.Length;
    999     //
   1000     // Now go through all the variable packs discovered during IFR processing
   1001     // and write them to the output file
   1002     //
   1003     if (mGlobals.NoVarPacks == 0) {
   1004       Index = 0;
   1005       do {
   1006         Status = IfrGetVarPack (Index, &VarPack);
   1007         if (Status == STATUS_SUCCESS) {
   1008           //
   1009           // If this is the first variable pack, then update the "offset
   1010           // to variable data" in the data table header
   1011           //
   1012           if (Index == 0) {
   1013             DataTableHeader.VariableDataOffset = DataTableHeader.DataTableSize;
   1014           }
   1015 
   1016           DataTableHeader.DataTableSize += VarPack->Header.Length;
   1017           DataTableHeader.NumberOfVariableData++;
   1018           if (fwrite ((void *) VarPack, VarPack->Header.Length, 1, OutFptr) != 1) {
   1019             Error (NULL, 0, 0, OutputFileName, "failed to write variable pack to output file");
   1020             goto Done;
   1021           }
   1022 
   1023           Index++;
   1024         }
   1025       } while (Status == STATUS_SUCCESS);
   1026     }
   1027     //
   1028     // Reposition in the output file and write the updated data table header
   1029     //
   1030     fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
   1031     if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
   1032       Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
   1033       goto Done;
   1034     }
   1035 
   1036     fseek (OutFptr, 0, SEEK_END);
   1037   } else {
   1038     //
   1039     // Multiple IFR input files. Close out the current data table (strings)
   1040     // if applicable. Then retrieve each parsed IFR pack and create a data pack
   1041     // that contains the IFR (one per data set) and the variable packs that
   1042     // the given IFR form references.
   1043     //
   1044     if (NumStrings != 0) {
   1045       fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
   1046       if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
   1047         Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
   1048         goto Done;
   1049       }
   1050 
   1051       fseek (OutFptr, 0, SEEK_END);
   1052     } else {
   1053       //
   1054       // No strings, so back up over the data table header we wrote because we assumed
   1055       // at least one string pack.
   1056       //
   1057       fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
   1058     }
   1059     //
   1060     // Now go through all the IFR packs and write them out, along with variable
   1061     // data referenced by each. Note that multiple IFR forms can refer to the
   1062     // same variables, so the same variable data could be duplicated in multiple
   1063     // data packs.
   1064     //
   1065     Index = FIRST_HII_PACK_HANDLE;
   1066     while (IfrGetIfrPack (Index, &IfrPack, &TempGuid) == STATUS_SUCCESS) {
   1067       //
   1068       // Initialize the data table header
   1069       //
   1070       memset (&DataTableHeader, 0, sizeof (EFI_HII_DATA_TABLE));
   1071       memcpy (&DataTableHeader.PackageGuid, &PackageGuid, sizeof (EFI_GUID));
   1072       //
   1073       // If we didn't have strings, then the HiiHandle should be just Index,
   1074       // rather than Index+1. But since the HiiHandle is not required to start
   1075       // with 1, we'll let it be Index+1.
   1076       //
   1077       DataTableHeader.HiiHandle     = (EFI_HII_HANDLE) (Index + 1);
   1078       DataTableHeader.DataTableSize = sizeof (EFI_HII_DATA_TABLE);
   1079       //
   1080       // Save the file offset of the data table header so we can write an updated
   1081       // version later.
   1082       //
   1083       DataTableHeaderOffset = ftell (OutFptr);
   1084       if (mGlobals.Verbose) {
   1085         fprintf (stdout, "writing data table header to 0x%X\n", ftell (OutFptr));
   1086       }
   1087 
   1088       if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
   1089         Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
   1090         goto Done;
   1091       }
   1092 
   1093       DataTableHeader.IfrDataOffset = DataTableHeader.DataTableSize;
   1094       if (fwrite (IfrPack, IfrPack->Header.Length, 1, OutFptr) != 1) {
   1095         Error (NULL, 0, 0, OutputFileName, "failed to write IFR pack to output file");
   1096         goto Done;
   1097       }
   1098 
   1099       DataTableHeader.DataTableSize += IfrPack->Header.Length;
   1100       //
   1101       // Go through all the variable packs and see if this IFR references each. If the
   1102       // IFR does reference it, then add the variable pack to the output.
   1103       //
   1104       if (mGlobals.NoVarPacks == 0) {
   1105         VarPackIndex = 0;
   1106         while (IfrGetVarPack (VarPackIndex, &VarPack) == STATUS_SUCCESS) {
   1107           //
   1108           // See if the IFR references this variable pack
   1109           //
   1110           if (IfrReferencesVarPack (Index, VarPack) == STATUS_SUCCESS) {
   1111             //
   1112             // If this is the first variable pack, then set the offset in
   1113             // the data table header.
   1114             //
   1115             if (DataTableHeader.VariableDataOffset == 0) {
   1116               DataTableHeader.VariableDataOffset = DataTableHeader.DataTableSize;
   1117             }
   1118             //
   1119             // Write the variable pack
   1120             //
   1121             if (fwrite (VarPack, VarPack->Header.Length, 1, OutFptr) != 1) {
   1122               Error (NULL, 0, 0, OutputFileName, "failed to write variable pack to output file");
   1123               goto Done;
   1124             }
   1125 
   1126             DataTableHeader.NumberOfVariableData++;
   1127             DataTableHeader.DataTableSize += VarPack->Header.Length;
   1128           }
   1129 
   1130           VarPackIndex++;
   1131         }
   1132       }
   1133       //
   1134       // Write the updated data table header
   1135       //
   1136       fseek (OutFptr, DataTableHeaderOffset, SEEK_SET);
   1137       if (fwrite ((void *) &DataTableHeader, sizeof (EFI_HII_DATA_TABLE), 1, OutFptr) != 1) {
   1138         Error (NULL, 0, 0, "failed to write Data Table Header to output file", NULL);
   1139         goto Done;
   1140       }
   1141 
   1142       fseek (OutFptr, 0, SEEK_END);
   1143       //
   1144       // Next IFR pack
   1145       //
   1146       Index++;
   1147     }
   1148   }
   1149 
   1150   Status = STATUS_SUCCESS;
   1151 Done:
   1152   IfrParseEnd ();
   1153   StringEnd ();
   1154   if (Buffer != NULL) {
   1155     free (Buffer);
   1156   }
   1157 
   1158   if (InFptr != NULL) {
   1159     fclose (InFptr);
   1160   }
   1161 
   1162   if (OutFptr != NULL) {
   1163     fclose (OutFptr);
   1164   }
   1165 
   1166   return Status;
   1167 }
   1168 
   1169 /******************************************************************************/
   1170 static
   1171 STATUS
   1172 ProcessIfrFiles (
   1173   FILE_NAME_LIST  *FileName
   1174   )
   1175 /*++
   1176 
   1177 Routine Description:
   1178 
   1179   Given a linked list of pack file names, read in each IFR pack file
   1180   and process the contents.
   1181 
   1182 Arguments:
   1183 
   1184   FileName    - pointer to linked list of input pack file names
   1185 
   1186 Returns:
   1187 
   1188   STATUS_SUCCESS    - if successful
   1189   STATUS_ERROR      - otherwise
   1190 
   1191 --*/
   1192 {
   1193   FILE                *InFptr;
   1194   char                *Buffer;
   1195   long                BufferSize;
   1196   STATUS              Status;
   1197   STATUS              IfrStatus;
   1198   int                 Handle;
   1199   EFI_GUID            FormsetGuid;
   1200   EFI_HII_PACK_HEADER *PackHeader;
   1201   //
   1202   // Process each input IFR file
   1203   //
   1204   Status  = STATUS_ERROR;
   1205   Handle  = 1;
   1206   InFptr  = NULL;
   1207   Buffer  = NULL;
   1208   while (FileName != NULL) {
   1209     //
   1210     // Only process IFR pack files
   1211     //
   1212     if (FileName->Tag != EFI_HII_IFR) {
   1213       FileName = FileName->Next;
   1214       continue;
   1215     }
   1216     //
   1217     // Open the input file, then read the contents
   1218     //
   1219     if ((InFptr = fopen (FileName->FileName, "rb")) == NULL) {
   1220       Error (NULL, 0, 0, FileName->FileName, "failed to open input IFR file");
   1221       goto Done;
   1222     }
   1223 
   1224     fseek (InFptr, 0, SEEK_END);
   1225     BufferSize = ftell (InFptr);
   1226     fseek (InFptr, 0, SEEK_SET);
   1227     Buffer = (char *) malloc (BufferSize);
   1228     if (Buffer == NULL) {
   1229       Error (NULL, 0, 0, "memory allocation failure", NULL);
   1230       goto Done;
   1231     }
   1232 
   1233     if (fread (Buffer, BufferSize, 1, InFptr) != 1) {
   1234       Error (NULL, 0, 0, FileName->FileName, "failed to read file contents");
   1235       goto Done;
   1236     }
   1237 
   1238     fclose (InFptr);
   1239     InFptr = NULL;
   1240     //
   1241     // Check the buffer contents -- better be an IFR pack
   1242     //
   1243     if (BufferSize < sizeof (EFI_HII_PACK_HEADER)) {
   1244       Error (NULL, 0, 0, FileName->FileName, "file is not large enough to contain an IFR pack");
   1245       goto Done;
   1246     }
   1247 
   1248     PackHeader = (EFI_HII_PACK_HEADER *) Buffer;
   1249     if (PackHeader->Type != EFI_HII_IFR) {
   1250       Error (NULL, 0, 0, FileName->FileName, "file does not appear to be an IFR pack");
   1251       goto Done;
   1252     }
   1253     //
   1254     // Process the contents
   1255     //
   1256     memset ((void *) &FormsetGuid, 0, sizeof (EFI_GUID));
   1257     IfrStatus = IfrParsePack (Handle, (EFI_HII_IFR_PACK *) PackHeader, &FormsetGuid);
   1258     if (IfrStatus != STATUS_SUCCESS) {
   1259       goto Done;
   1260     }
   1261 
   1262     Handle++;
   1263     free (Buffer);
   1264     Buffer    = NULL;
   1265     FileName  = FileName->Next;
   1266   }
   1267 
   1268   Status = STATUS_SUCCESS;
   1269 Done:
   1270   if (InFptr != NULL) {
   1271     fclose (InFptr);
   1272   }
   1273 
   1274   if (Buffer != NULL) {
   1275     free (Buffer);
   1276   }
   1277 
   1278   return Status;
   1279 }
   1280 
   1281 static
   1282 STATUS
   1283 EmitDefaults (
   1284   FILE_NAME_LIST  *HiiExportFiles,
   1285   int             MfgDefaults,
   1286   int             NoEmptyVarPacks
   1287   )
   1288 /*++
   1289 
   1290 Routine Description:
   1291 
   1292   Given a linked list of HII export files, read in each file,
   1293   process the contents, and then emit variable packs.
   1294 
   1295 Arguments:
   1296 
   1297   HiiExportFiles  - linked list of HII export files to process
   1298   MfgDefaults     - emit manufacturing defaults
   1299   NoEmptyVarPacks - don't emit variable packs if they are 0-length
   1300 
   1301 Returns:
   1302 
   1303   STATUS_SUCCESS    - if successful
   1304   STATUS_ERROR      - otherwise
   1305 
   1306 --*/
   1307 {
   1308   int                   HiiHandle;
   1309   FILE                  *OutFptr;
   1310   FILE                  *InFptr;
   1311   EFI_HII_VARIABLE_PACK *VarPack;
   1312   CHAR8                 OutFileName[MAX_PATH];
   1313   CHAR8                 GuidString[100];
   1314   STATUS                Status;
   1315   CHAR8                 *Buffer;
   1316   int                   FileSize;
   1317   int                   DataTableIndex;
   1318   EFI_HII_EXPORT_TABLE  *HiiExportTableHeader;
   1319   EFI_HII_DATA_TABLE    *DataTableHeader;
   1320   //
   1321   // Init locals
   1322   //
   1323   HiiHandle = FIRST_HII_PACK_HANDLE;
   1324   Buffer    = NULL;
   1325   InFptr    = NULL;
   1326   OutFptr   = NULL;
   1327   Status    = STATUS_ERROR;
   1328   //
   1329   // Initialize our IFR parser
   1330   //
   1331   IfrParseInit ();
   1332   //
   1333   // Process each input HII export file
   1334   //
   1335   while (HiiExportFiles != NULL) {
   1336     if (mGlobals.Verbose) {
   1337       fprintf (stdout, "Processing file %s\n", HiiExportFiles->FileName);
   1338     }
   1339     //
   1340     // Read in the entire file contents
   1341     //
   1342     if ((InFptr = fopen (HiiExportFiles->FileName, "rb")) == NULL) {
   1343       Error (NULL, 0, 0, HiiExportFiles->FileName, "failed to open HII export file for reading");
   1344       goto Done;
   1345     }
   1346 
   1347     fseek (InFptr, 0, SEEK_END);
   1348     FileSize = (int) ftell (InFptr);
   1349     fseek (InFptr, 0, SEEK_SET);
   1350     Buffer = (CHAR8 *) malloc (FileSize);
   1351     if (Buffer == NULL) {
   1352       Error (NULL, 0, 0, "memory allocation failure", NULL);
   1353       goto Done;
   1354     }
   1355 
   1356     if (fread (Buffer, FileSize, 1, InFptr) != 1) {
   1357       Error (NULL, 0, 0, HiiExportFiles->FileName, "failed to read file contents");
   1358       goto Done;
   1359     }
   1360 
   1361     fclose (InFptr);
   1362     InFptr                = NULL;
   1363     HiiExportTableHeader  = (EFI_HII_EXPORT_TABLE *) Buffer;
   1364     //
   1365     // Walk all the data tables
   1366     //
   1367     DataTableHeader = (EFI_HII_DATA_TABLE *) (HiiExportTableHeader + 1);
   1368     for (DataTableIndex = 0; DataTableIndex < (int) HiiExportTableHeader->NumberOfHiiDataTables; DataTableIndex++) {
   1369       //
   1370       // Make sure we're still pointing into our buffer
   1371       //
   1372       if (((char *) DataTableHeader < Buffer) || ((char *) DataTableHeader > Buffer + FileSize)) {
   1373         Error (NULL, 0, 0, "bad data table size in input file", NULL);
   1374         goto Done;
   1375       }
   1376       //
   1377       // If there is an IFR pack, parse it
   1378       //
   1379       HiiHandle++;
   1380       if (DataTableHeader->IfrDataOffset != 0) {
   1381         if (IfrParsePack (
   1382             HiiHandle,
   1383             (EFI_HII_IFR_PACK *) ((char *) DataTableHeader + DataTableHeader->IfrDataOffset),
   1384             &DataTableHeader->PackageGuid
   1385             ) != STATUS_SUCCESS
   1386             ) {
   1387           goto Done;
   1388         }
   1389       }
   1390       //
   1391       // Next data pack
   1392       //
   1393       DataTableHeader = (EFI_HII_DATA_TABLE *) ((char *) DataTableHeader + DataTableHeader->DataTableSize);
   1394     }
   1395 
   1396     free (Buffer);
   1397     Buffer = NULL;
   1398     //
   1399     // Next input file
   1400     //
   1401     HiiExportFiles = HiiExportFiles->Next;
   1402   }
   1403   //
   1404   // Now create defaults
   1405   //
   1406   if (IfrSetDefaults (MfgDefaults) != STATUS_SUCCESS) {
   1407     goto Done;
   1408   }
   1409   //
   1410   // Now retrieve each variable pack and write it out to a GUID-VarName.hpk file
   1411   //
   1412   HiiHandle = 0;
   1413   do {
   1414     Status = IfrGetVarPack (HiiHandle, &VarPack);
   1415     if (Status == STATUS_SUCCESS) {
   1416       //
   1417       // Check for variable data length of 0
   1418       //
   1419       if ((NoEmptyVarPacks == 0) ||
   1420           ((VarPack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - VarPack->VariableNameLength) != 0)
   1421           ) {
   1422         //
   1423         // Open the output file and write the variable pack
   1424         //
   1425         GuidToString (&VarPack->VariableGuid, GuidString);
   1426         if (MfgDefaults) {
   1427           sprintf (
   1428             OutFileName,
   1429             "%s-%S-MfgDefaults%s",
   1430             GuidString,
   1431             (CHAR16 *) (VarPack + 1),
   1432             DEFAULT_HII_PACK_FILENAME_EXTENSION
   1433             );
   1434         } else {
   1435           sprintf (
   1436             OutFileName,
   1437             "%s-%S-Defaults%s",
   1438             GuidString,
   1439             (CHAR16 *) (VarPack + 1),
   1440             DEFAULT_HII_PACK_FILENAME_EXTENSION
   1441             );
   1442         }
   1443 
   1444         if (mGlobals.Verbose) {
   1445           fprintf (
   1446             stdout,
   1447             "Creating %svariable defaults pack file %s\n",
   1448             MfgDefaults ? "manufacturing " : "",
   1449             OutFileName
   1450             );
   1451         }
   1452 
   1453         if ((OutFptr = fopen (OutFileName, "wb")) == NULL) {
   1454           Error (NULL, 0, 0, OutFileName, "failed to open output file for writing", NULL);
   1455           goto Done;
   1456         }
   1457 
   1458         if (fwrite ((void *) VarPack, VarPack->Header.Length, 1, OutFptr) != 1) {
   1459           Error (NULL, 0, 0, OutFileName, "failed to write defaults to output file");
   1460           goto Done;
   1461         }
   1462 
   1463         fclose (OutFptr);
   1464         OutFptr = NULL;
   1465       } else {
   1466         //
   1467         // Print a message that we skipped one if in verbose mode
   1468         //
   1469         if (mGlobals.Verbose) {
   1470           GuidToString (&VarPack->VariableGuid, GuidString);
   1471           if (MfgDefaults) {
   1472             sprintf (
   1473               OutFileName,
   1474               "%s-%S-MfgDefaults%s",
   1475               GuidString,
   1476               (CHAR16 *) (VarPack + 1),
   1477               DEFAULT_HII_PACK_FILENAME_EXTENSION
   1478               );
   1479           } else {
   1480             sprintf (
   1481               OutFileName,
   1482               "%s-%S-Defaults%s",
   1483               GuidString,
   1484               (CHAR16 *) (VarPack + 1),
   1485               DEFAULT_HII_PACK_FILENAME_EXTENSION
   1486               );
   1487           }
   1488 
   1489           fprintf (
   1490             stdout,
   1491             "Skipping 0-length %svariable defaults pack file %s\n",
   1492             MfgDefaults ? "manufacturing " : "",
   1493             OutFileName
   1494             );
   1495         }
   1496       }
   1497     }
   1498 
   1499     HiiHandle++;
   1500   } while (Status == STATUS_SUCCESS);
   1501   Status = STATUS_SUCCESS;
   1502 Done:
   1503   IfrParseEnd ();
   1504   if (Buffer != NULL) {
   1505     free (Buffer);
   1506   }
   1507 
   1508   if (InFptr != NULL) {
   1509     fclose (InFptr);
   1510   }
   1511 
   1512   if (OutFptr != NULL) {
   1513     fclose (OutFptr);
   1514   }
   1515 
   1516   return Status;
   1517 }
   1518 
   1519 static
   1520 void
   1521 FreeGlobals (
   1522   VOID
   1523   )
   1524 /*++
   1525 
   1526 Routine Description:
   1527 
   1528   Free up an memory we allocated so we can exit cleanly
   1529 
   1530 Arguments:
   1531 
   1532 Returns: NA
   1533 
   1534 --*/
   1535 {
   1536   FILE_NAME_LIST  *Next;
   1537   //
   1538   // Free up input pack file names
   1539   //
   1540   while (mGlobals.PackFileNames != NULL) {
   1541     Next = mGlobals.PackFileNames->Next;
   1542     free (mGlobals.PackFileNames);
   1543     mGlobals.PackFileNames = Next;
   1544   }
   1545   //
   1546   // Free up input HII export file names
   1547   //
   1548   while (mGlobals.HiiExportFileNames != NULL) {
   1549     Next = mGlobals.HiiExportFileNames->Next;
   1550     free (mGlobals.HiiExportFileNames);
   1551     mGlobals.HiiExportFileNames = Next;
   1552   }
   1553 }
   1554 
   1555 static
   1556 STATUS
   1557 DumpHiiExportFile (
   1558   char    *HiiExportFileName,
   1559   char    *OutputFileName
   1560   )
   1561 /*++
   1562 
   1563 Routine Description:
   1564 
   1565   Dump the contents of an HII export file for debug purposes
   1566 
   1567 Arguments:
   1568 
   1569   HiiExportFileName - name of input HII export file
   1570   OutputFileName    - name of output file to dump contents
   1571 
   1572 Returns:
   1573   STATUS_SUCCESS  - no problems
   1574   STATUS_ERROR    - problems encountered processing the file
   1575 
   1576 --*/
   1577 {
   1578   FILE                *InFptr;
   1579 
   1580   FILE                *OutFptr;
   1581   char                *Buffer;
   1582   char                *BufferStart;
   1583   char                *BufferEnd;
   1584   int                 BufferSize;
   1585   STATUS              Status;
   1586   char                GuidString[100];
   1587   int                 Counter;
   1588   int                 NumberOfTables;
   1589   EFI_HII_DATA_TABLE  *DataTableHeader;
   1590   EFI_GUID              HiiExportRevisionGuid = EFI_HII_PROTOCOL_GUID;
   1591   //
   1592   // Init locals
   1593   //
   1594   InFptr      = NULL;
   1595   OutFptr     = NULL;
   1596   BufferStart = NULL;
   1597   Status      = STATUS_ERROR;
   1598   //
   1599   // Open the input file
   1600   //
   1601   if ((InFptr = fopen (HiiExportFileName, "rb")) == NULL) {
   1602     Error (NULL, 0, 0, HiiExportFileName, "failed to open input HII export file for reading");
   1603     goto Done;
   1604   }
   1605   //
   1606   // Open the output file
   1607   //
   1608   if ((OutFptr = fopen (OutputFileName, "w")) == NULL) {
   1609     Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing");
   1610     goto Done;
   1611   }
   1612   //
   1613   // Get the file size, then allocate a buffer and read in the file contents.
   1614   //
   1615   fseek (InFptr, 0, SEEK_END);
   1616   BufferSize = (int) ftell (InFptr);
   1617   fseek (InFptr, 0, SEEK_SET);
   1618   BufferStart = (char *) malloc (BufferSize);
   1619   if (BufferStart == NULL) {
   1620     Error (NULL, 0, 0, "memory allocation failure", NULL);
   1621     goto Done;
   1622   }
   1623 
   1624   if (fread (BufferStart, BufferSize, 1, InFptr) != 1) {
   1625     Error (NULL, 0, 0, HiiExportFileName, "error reading file contents");
   1626     goto Done;
   1627   }
   1628 
   1629   fclose (InFptr);
   1630   InFptr = NULL;
   1631   //
   1632   // Crude check of the input data -- check the size and GUID
   1633   //
   1634   if (BufferSize < sizeof (EFI_HII_EXPORT_TABLE)) {
   1635     Error (NULL, 0, 0, HiiExportFileName, "files not large enough to contain an HII export table header");
   1636     goto Done;
   1637   }
   1638 
   1639   if (memcmp (&((EFI_HII_EXPORT_TABLE *) BufferStart)->Revision, &HiiExportRevisionGuid, sizeof (EFI_GUID)) != 0) {
   1640     Error (NULL, 0, 0, HiiExportFileName, "invalid HII export revision GUID -- is this an HII export file?");
   1641     //
   1642     // See if it's a HII pack file
   1643     //
   1644     TestDumpHiiPack (OutFptr, BufferStart, BufferSize);
   1645     goto Done;
   1646   }
   1647   //
   1648   // Now walk the export data
   1649   //
   1650   Buffer    = BufferStart;
   1651   BufferEnd = BufferStart + BufferSize;
   1652   //
   1653   // Dump the header
   1654   //
   1655   fprintf (OutFptr, "HII dump of file %s\n\n", HiiExportFileName);
   1656   NumberOfTables = ((EFI_HII_EXPORT_TABLE *) Buffer)->NumberOfHiiDataTables;
   1657   fprintf (OutFptr, "Number of data tables:  %d\n", NumberOfTables);
   1658   GuidToString (&((EFI_HII_EXPORT_TABLE *) Buffer)->Revision, GuidString);
   1659   fprintf (OutFptr, "HII export revision:    %s\n", GuidString);
   1660   //
   1661   // Now walk the data tables
   1662   //
   1663   Buffer += sizeof (EFI_HII_EXPORT_TABLE);
   1664   for (Counter = 0; Counter < NumberOfTables; Counter++) {
   1665     DataTableHeader = (EFI_HII_DATA_TABLE *) Buffer;
   1666     fprintf (OutFptr, "----------------------------------------------------------\n");
   1667     fprintf (OutFptr, "  DataTable at offset 0x%08X\n", (int) Buffer - (int) BufferStart);
   1668     fprintf (OutFptr, "    HII Handle:                            0x%08X\n", DataTableHeader->HiiHandle);
   1669     GuidToString (&DataTableHeader->PackageGuid, GuidString);
   1670     fprintf (OutFptr, "    Package GUID:                          %s\n", GuidString);
   1671     fprintf (OutFptr, "    Data table size:                       0x%08X\n", DataTableHeader->DataTableSize);
   1672     fprintf (OutFptr, "    IFR data offset:                       0x%08X\n", DataTableHeader->IfrDataOffset);
   1673     fprintf (OutFptr, "    String data offset:                    0x%08X\n", DataTableHeader->StringDataOffset);
   1674     fprintf (OutFptr, "    Variable data offset:                  0x%08X\n", DataTableHeader->VariableDataOffset);
   1675     fprintf (OutFptr, "    Device path offset:                    0x%08X\n", DataTableHeader->DevicePathOffset);
   1676     fprintf (OutFptr, "    Number of variable data:               0x%08X\n", DataTableHeader->NumberOfVariableData);
   1677     fprintf (OutFptr, "    Number of languages:                   0x%08X\n", DataTableHeader->NumberOfLanguages);
   1678     //
   1679     // Dump strings
   1680     //
   1681     if (DataTableHeader->StringDataOffset != 0) {
   1682       DumpStringPack (
   1683         OutFptr,
   1684         (EFI_HII_STRING_PACK *) ((char *) DataTableHeader + DataTableHeader->StringDataOffset),
   1685         DataTableHeader->StringDataOffset,
   1686         6
   1687         );
   1688     }
   1689     //
   1690     // Dump IFR
   1691     //
   1692     if (DataTableHeader->IfrDataOffset != 0) {
   1693       DumpIfrPack (
   1694         OutFptr,
   1695         (EFI_HII_IFR_PACK *) ((char *) DataTableHeader + DataTableHeader->IfrDataOffset),
   1696         DataTableHeader->IfrDataOffset,
   1697         6
   1698         );
   1699     }
   1700     //
   1701     // Dump variables
   1702     //
   1703     if (DataTableHeader->VariableDataOffset != 0) {
   1704       DumpVariablePacks (
   1705         OutFptr,
   1706         (EFI_HII_VARIABLE_PACK *) ((char *) DataTableHeader + DataTableHeader->VariableDataOffset),
   1707         DataTableHeader->NumberOfVariableData,
   1708         DataTableHeader->VariableDataOffset,
   1709         6
   1710         );
   1711     }
   1712     //
   1713     // Dump device path
   1714     //
   1715     //
   1716     // Check position before advancing
   1717     //
   1718     if ((Buffer + DataTableHeader->DataTableSize < Buffer) || (Buffer + DataTableHeader->DataTableSize > BufferEnd)) {
   1719       Error (NULL, 0, 0, HiiExportFileName, "bad data table size at offset 0x%X", (int) Buffer - (int) BufferStart);
   1720       goto Done;
   1721     }
   1722 
   1723     Buffer += DataTableHeader->DataTableSize;
   1724   }
   1725 
   1726   Status = STATUS_SUCCESS;
   1727 Done:
   1728   if (OutFptr != NULL) {
   1729     fclose (OutFptr);
   1730   }
   1731 
   1732   if (InFptr != NULL) {
   1733     fclose (InFptr);
   1734   }
   1735 
   1736   if (BufferStart != NULL) {
   1737     free (BufferStart);
   1738   }
   1739 
   1740   return Status;
   1741 }
   1742 
   1743 static
   1744 void
   1745 DumpIfrPack (
   1746   FILE                  *OutFptr,
   1747   EFI_HII_IFR_PACK      *Pack,
   1748   int                   BaseOffset,
   1749   int                   Indent
   1750   )
   1751 /*++
   1752 
   1753 Routine Description:
   1754 
   1755   Dump the contents of an IFR pack for debug purposes
   1756 
   1757 Arguments:
   1758 
   1759   OutFptr         - file pointer to which to dump the output
   1760   Pack            - pointer to IFR pack to dump
   1761   BaseOffset      - offset from which Pack starts in its parent data table
   1762   Indent          - indent this many spaces when printing text to OutFptr
   1763 
   1764 Returns:
   1765   NA
   1766 
   1767 --*/
   1768 {
   1769   EFI_IFR_FORM_SET  *IfrFormSet;
   1770   char              GuidString[100];
   1771   if (Pack->Header.Type != EFI_HII_IFR) {
   1772     Error (NULL, 0, 0, "found non-IFR pack type at IFR data offset", NULL);
   1773     return ;
   1774   }
   1775 
   1776   fprintf (OutFptr, "%*cIFR pack at offset      0x%08X\n", Indent, ' ', BaseOffset);
   1777   fprintf (OutFptr, "%*c  Length                0x%08X\n", Indent, ' ', Pack->Header.Length);
   1778   //
   1779   // Get the GUID from the formset
   1780   //
   1781   IfrFormSet = (EFI_IFR_FORM_SET *) (Pack + 1);
   1782   GuidToString (&IfrFormSet->Guid, GuidString);
   1783   fprintf (OutFptr, "%*c  Variable GUID         %s\n", Indent, ' ', GuidString);
   1784   //
   1785   // Print the IFR formset size, with a note indicating if it's a min (likely stub)
   1786   // formset
   1787   //
   1788   if (Pack->Header.Length == sizeof (EMPTY_FORMSET_PACK)) {
   1789     fprintf (
   1790       OutFptr,
   1791       "%*c  IFR formset size      0x%08X (empty formset)\n",
   1792       Indent,
   1793       ' ',
   1794       Pack->Header.Length - sizeof (EFI_HII_IFR_PACK)
   1795       );
   1796   } else {
   1797     fprintf (
   1798       OutFptr,
   1799       "%*c  IFR formset size      0x%08X\n",
   1800       Indent,
   1801       ' ',
   1802       Pack->Header.Length - sizeof (EFI_HII_IFR_PACK)
   1803       );
   1804   }
   1805   //
   1806   // Dump raw bytes -- not much use
   1807   //
   1808 }
   1809 
   1810 static
   1811 void
   1812 DumpVariablePacks (
   1813   FILE                  *OutFptr,
   1814   EFI_HII_VARIABLE_PACK *Pack,
   1815   int                   NumPacks,
   1816   int                   BaseOffset,
   1817   int                   Indent
   1818   )
   1819 /*++
   1820 
   1821 Routine Description:
   1822 
   1823   Dump the contents of an IFR pack for debug purposes
   1824 
   1825 Arguments:
   1826 
   1827   OutFptr         - file pointer to which to dump the output
   1828   Pack            - pointer to variable pack to dump
   1829   NumPacks        - number of packs in Pack[] array
   1830   BaseOffset      - offset from which Pack starts in its parent data table
   1831   Indent          - indent this many spaces when printing text to OutFptr
   1832 
   1833 Returns:
   1834   NA
   1835 
   1836 --*/
   1837 {
   1838   int   Count;
   1839 
   1840   int   Len;
   1841   char  GuidString[100];
   1842 
   1843   for (Count = 0; Count < NumPacks; Count++) {
   1844     if (Pack->Header.Type != EFI_HII_VARIABLE) {
   1845       Error (NULL, 0, 0, "found non-variable pack type in variable pack array", NULL);
   1846       return ;
   1847     }
   1848 
   1849     fprintf (OutFptr, "%*cVariable pack at offset 0x%08X\n", Indent, ' ', BaseOffset);
   1850     fprintf (OutFptr, "%*c  Length                0x%08X\n", Indent, ' ', Pack->Header.Length);
   1851     GuidToString (&Pack->VariableGuid, GuidString);
   1852     fprintf (OutFptr, "%*c  Variable GUID         %s\n", Indent, ' ', GuidString);
   1853     fprintf (OutFptr, "%*c  Variable Name         %S\n", Indent, ' ', (CHAR16 *) (Pack + 1));
   1854     Len = sizeof (EFI_HII_VARIABLE_PACK) + Pack->VariableNameLength;
   1855     fprintf (OutFptr, "%*c  Variable Size         0x%08X\n", Indent, ' ', Pack->Header.Length - Len);
   1856     //
   1857     // Dump raw bytes
   1858     //
   1859     DumpRawBytes (OutFptr, (char *) Pack + Len, Pack->Header.Length - Len, Len, Indent + 2);
   1860     BaseOffset += Pack->Header.Length;
   1861     Pack = (EFI_HII_VARIABLE_PACK *) ((char *) Pack + Pack->Header.Length);
   1862   }
   1863 }
   1864 
   1865 static
   1866 void
   1867 DumpStringPack (
   1868   FILE                  *OutFptr,
   1869   EFI_HII_STRING_PACK   *Pack,
   1870   int                   BaseOffset,
   1871   int                   Indent
   1872   )
   1873 /*++
   1874 
   1875 Routine Description:
   1876 
   1877   Dump the contents of a string pack array for debug purposes
   1878 
   1879 Arguments:
   1880 
   1881   OutFptr         - file pointer to which to dump the output
   1882   Pack            - pointer to string pack array to dump
   1883   BaseOffset      - offset from which Pack starts in its parent data table
   1884   Indent          - indent this many spaces when printing text to OutFptr
   1885 
   1886 Returns:
   1887   NA
   1888 
   1889 --*/
   1890 {
   1891   int     Count;
   1892   int     *IndexPtr;
   1893   CHAR16  *WCPtr;
   1894   //
   1895   // String pack array is terminated with a zero-length string pack
   1896   //
   1897   while (Pack->Header.Length > 0) {
   1898     if (Pack->Header.Type != EFI_HII_STRING) {
   1899       Error (NULL, 0, 0, "found non-string pack type in string pack array", NULL);
   1900       return ;
   1901     }
   1902 
   1903     fprintf (OutFptr, "%*cString pack at offset   0x%08X\n", Indent, ' ', BaseOffset);
   1904     fprintf (OutFptr, "%*c  Length                0x%08X\n", Indent, ' ', Pack->Header.Length);
   1905     fprintf (
   1906       OutFptr,
   1907       "%*c  Language              %S\n",
   1908       Indent,
   1909       ' ',
   1910       (CHAR16 *) ((char *) Pack + Pack->LanguageNameString)
   1911       );
   1912     fprintf (
   1913       OutFptr,
   1914       "%*c  Printable Language    %S\n",
   1915       Indent,
   1916       ' ',
   1917       (CHAR16 *) ((char *) Pack + Pack->PrintableLanguageName)
   1918       );
   1919     fprintf (OutFptr, "%*c  Number of strings     0x%08X\n", Indent, ' ', Pack->NumStringPointers);
   1920     fprintf (OutFptr, "%*c  Attributes            0x%08X\n", Indent, ' ', Pack->Attributes);
   1921     IndexPtr = (int *) (Pack + 1);
   1922     //
   1923     // Dump string data
   1924     //
   1925     if (mGlobals.DumpStrings) {
   1926       for (Count = 0; Count < (int) Pack->NumStringPointers; Count++) {
   1927         fprintf (OutFptr, "%*c    String 0x%04X: ", Indent, ' ', Count);
   1928         //
   1929         // Print raw hex bytes
   1930         //
   1931         for (WCPtr = (CHAR16 *) ((char *) Pack +*IndexPtr); *WCPtr != 0; WCPtr++) {
   1932           fprintf (OutFptr, "%02X ", (unsigned int) *WCPtr);
   1933         }
   1934 
   1935         fprintf (OutFptr, "00\n");
   1936         IndexPtr++;
   1937       }
   1938     }
   1939 
   1940     BaseOffset += Pack->Header.Length;
   1941     Pack = (EFI_HII_STRING_PACK *) ((char *) Pack + Pack->Header.Length);
   1942   }
   1943 }
   1944 
   1945 static
   1946 void
   1947 TestDumpHiiPack (
   1948   FILE    *OutFptr,
   1949   char    *Buffer,
   1950   int     BufferSize
   1951   )
   1952 /*++
   1953 
   1954 Routine Description:
   1955 
   1956   GC_TODO: Add function description
   1957 
   1958 Arguments:
   1959 
   1960   OutFptr     - GC_TODO: add argument description
   1961   Buffer      - GC_TODO: add argument description
   1962   BufferSize  - GC_TODO: add argument description
   1963 
   1964 Returns:
   1965 
   1966   GC_TODO: add return values
   1967 
   1968 --*/
   1969 {
   1970   EFI_HII_PACK_HEADER *PackHeader;
   1971 
   1972   PackHeader = (EFI_HII_PACK_HEADER *) Buffer;
   1973   //
   1974   // Check size match
   1975   //
   1976   if (PackHeader->Length != (unsigned int) BufferSize) {
   1977     return ;
   1978   }
   1979   //
   1980   // Check type
   1981   //
   1982   switch (PackHeader->Type) {
   1983   case EFI_HII_STRING:
   1984     fprintf (stdout, "Dumping as string pack\n");
   1985     DumpStringPack (OutFptr, (EFI_HII_STRING_PACK *) Buffer, 0, 2);
   1986     break;
   1987 
   1988   case EFI_HII_IFR:
   1989     fprintf (stdout, "Dumping as IFR pack\n");
   1990     DumpIfrPack (OutFptr, (EFI_HII_IFR_PACK *) Buffer, 0, 2);
   1991     break;
   1992 
   1993   case EFI_HII_VARIABLE:
   1994     fprintf (stdout, "Dumping as IFR pack\n");
   1995     DumpVariablePacks (OutFptr, (EFI_HII_VARIABLE_PACK *) Buffer, 1, 0, 2);
   1996     break;
   1997   }
   1998 }
   1999 
   2000 static
   2001 void
   2002 DumpRawBytes (
   2003   FILE                  *OutFptr,
   2004   char                  *Buffer,
   2005   int                   Count,
   2006   int                   BaseOffset,
   2007   int                   Indent
   2008   )
   2009 /*++
   2010 
   2011 Routine Description:
   2012 
   2013   GC_TODO: Add function description
   2014 
   2015 Arguments:
   2016 
   2017   OutFptr     - GC_TODO: add argument description
   2018   Buffer      - GC_TODO: add argument description
   2019   Count       - GC_TODO: add argument description
   2020   BaseOffset  - GC_TODO: add argument description
   2021   Indent      - GC_TODO: add argument description
   2022 
   2023 Returns:
   2024 
   2025   GC_TODO: add return values
   2026 
   2027 --*/
   2028 {
   2029   int Counter;
   2030 
   2031   for (Counter = 0; Counter < Count; Counter++) {
   2032     if ((Counter & 0xF) == 0) {
   2033       if (Counter != 0) {
   2034         fprintf (OutFptr, "\n%*c%08X ", Indent, ' ', Counter);
   2035       } else {
   2036         fprintf (OutFptr, "\n%*c%08X ", Indent, ' ', Counter);
   2037       }
   2038     }
   2039 
   2040     fprintf (OutFptr, "%02X ", (unsigned int) (unsigned char) *Buffer);
   2041     Buffer++;
   2042   }
   2043 
   2044   fprintf (OutFptr, "\n");
   2045 }
   2046 
   2047 void
   2048 GuidToString (
   2049   EFI_GUID   *Guid,
   2050   char       *Str
   2051   )
   2052 /*++
   2053 
   2054 Routine Description:
   2055 
   2056   Given a pointer to a GUID, sprint the value into a string
   2057 
   2058 Arguments:
   2059 
   2060   Guid   - pointer to input GUID
   2061   Str    - pointer to outgoing printed GUID value
   2062 
   2063 Returns:
   2064   NA
   2065 
   2066 --*/
   2067 {
   2068   sprintf (
   2069     Str,
   2070     "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X",
   2071     Guid->Data1,
   2072     Guid->Data2,
   2073     Guid->Data3,
   2074     Guid->Data4[0],
   2075     Guid->Data4[1],
   2076     Guid->Data4[2],
   2077     Guid->Data4[3],
   2078     Guid->Data4[4],
   2079     Guid->Data4[5],
   2080     Guid->Data4[6],
   2081     Guid->Data4[7]
   2082     );
   2083 }
   2084 
   2085 int
   2086 FindFilesCallback (
   2087   char *FoundFileName
   2088   )
   2089 /*++
   2090 
   2091 Routine Description:
   2092 
   2093   Callback function used to get files matching a file mask. This
   2094   function is called when the command-line arguments to this utility
   2095   are parsed and the user specified "-s Path FileMask" to process
   2096   all HII export files in Path and its subdirectories that match
   2097   FileMask.
   2098 
   2099 Arguments:
   2100 
   2101   FoundFileName - name of file found.
   2102 
   2103 Returns:
   2104   non-zero    - caller should halt processing
   2105   zero        - no problems while processing FoundFileName
   2106 
   2107 --*/
   2108 {
   2109   FILE_NAME_LIST  *FileName;
   2110 
   2111   FILE_NAME_LIST  *TempFileName;
   2112 
   2113   FileName = (FILE_NAME_LIST *) malloc (sizeof (FILE_NAME_LIST));
   2114   if (FileName == NULL) {
   2115     Error (NULL, 0, 0, "memory allocation failure", NULL);
   2116     return STATUS_ERROR;
   2117   }
   2118 
   2119   memset ((void *) FileName, 0, sizeof (FILE_NAME_LIST));
   2120   strcpy (FileName->FileName, FoundFileName);
   2121   if (mGlobals.HiiExportFileNames == NULL) {
   2122     mGlobals.HiiExportFileNames = FileName;
   2123   } else {
   2124     //
   2125     // Add to the end of the list
   2126     //
   2127     for (TempFileName = mGlobals.HiiExportFileNames; TempFileName->Next != NULL; TempFileName = TempFileName->Next)
   2128       ;
   2129     TempFileName->Next = FileName;
   2130   }
   2131 
   2132   return 0;
   2133 }
   2134 
   2135 static
   2136 STATUS
   2137 ProcessArgs (
   2138   int   Argc,
   2139   char  *Argv[]
   2140   )
   2141 /*++
   2142 
   2143 Routine Description:
   2144 
   2145   Process the command line arguments
   2146 
   2147 Arguments:
   2148 
   2149   As per standard C main()
   2150 
   2151 Returns:
   2152 
   2153   STATUS_SUCCESS    - if successful
   2154   STATUS_ERROR      - otherwise
   2155 
   2156 --*/
   2157 // GC_TODO:    Argc - add argument and description to function comment
   2158 // GC_TODO:    ] - add argument and description to function comment
   2159 {
   2160   FILE_NAME_LIST      *FileName;
   2161 
   2162   FILE_NAME_LIST      *TempFileName;
   2163   FILE                *InFptr;
   2164   EFI_HII_PACK_HEADER PackHeader;
   2165 
   2166   memset ((void *) &mGlobals, 0, sizeof (mGlobals));
   2167   //
   2168   // Skip program name
   2169   //
   2170   Argc--;
   2171   Argv++;
   2172 
   2173   if (Argc == 0) {
   2174     Usage ();
   2175     return STATUS_ERROR;
   2176   }
   2177   //
   2178   // First arg must be one of create, merge, defaults, or dump
   2179   //
   2180   if (_stricmp (Argv[0], "create") == 0) {
   2181     mGlobals.Mode = MODE_CREATE_HII_EXPORT;
   2182   } else if (_stricmp (Argv[0], "merge") == 0) {
   2183     mGlobals.Mode = MODE_MERGE_HII_EXPORTS;
   2184   } else if (_stricmp (Argv[0], "defaults") == 0) {
   2185     mGlobals.Mode = MODE_EMIT_DEFAULTS;
   2186   } else if (_stricmp (Argv[0], "dump") == 0) {
   2187     mGlobals.Mode = MODE_DUMP_HII_EXPORT;
   2188   } else if (strcmp (Argv[0], "-?") == 0) {
   2189     Usage ();
   2190     return STATUS_ERROR;
   2191   } else {
   2192     Error (NULL, 0, 0, Argv[0], "unrecognized mode");
   2193     return STATUS_ERROR;
   2194   }
   2195 
   2196   Argv++;
   2197   Argc--;
   2198   //
   2199   // Process until no more args.
   2200   //
   2201   while (Argc > 0) {
   2202     if (_stricmp (Argv[0], "-o") == 0) {
   2203       //
   2204       // -o option to specify the output file
   2205       //
   2206       if ((Argc <= 1) || (Argv[1][0] == '-')) {
   2207         Error (UTILITY_NAME, 0, 0, Argv[0], "missing output file name");
   2208         return STATUS_ERROR;
   2209       }
   2210 
   2211       if (mGlobals.OutputFileName[0] == 0) {
   2212         mGlobals.OutputFileName[MAX_PATH - 1] = 0;
   2213         strncpy (mGlobals.OutputFileName, Argv[1], MAX_PATH - 1);
   2214       } else {
   2215         Error (UTILITY_NAME, 0, 0, Argv[1], "-o option already specified with '%s'", mGlobals.OutputFileName);
   2216         return STATUS_ERROR;
   2217       }
   2218 
   2219       Argv++;
   2220       Argc--;
   2221     } else if (_stricmp (Argv[0], "-mfg") == 0) {
   2222       mGlobals.MfgFlag = 1;
   2223     } else if (_stricmp (Argv[0], "-g") == 0) {
   2224       //
   2225       // -g option to specify the guid
   2226       //
   2227       if ((Argc <= 1) || (Argv[1][0] == '-')) {
   2228         Error (UTILITY_NAME, 0, 0, Argv[0], "missing GUID");
   2229         return STATUS_ERROR;
   2230       }
   2231 
   2232       StringToGuid (Argv[1], &mGlobals.Guid);
   2233       mGlobals.GuidSpecified = 1;
   2234       Argv++;
   2235       Argc--;
   2236     } else if (_stricmp (Argv[0], "-v") == 0) {
   2237       mGlobals.Verbose = 1;
   2238     } else if (_stricmp (Argv[0], "-p") == 0) {
   2239       //
   2240       // -p option to specify an input pack file. Only valid for 'create' mode
   2241       //
   2242       if (mGlobals.Mode != MODE_CREATE_HII_EXPORT) {
   2243         Error (NULL, 0, 0, Argv[0], "option only valid in 'create' mode");
   2244         return STATUS_ERROR;
   2245       }
   2246 
   2247       if ((Argc <= 1) || (Argv[1][0] == '-')) {
   2248         Error (UTILITY_NAME, 0, 0, Argv[0], "missing pack file name");
   2249         return STATUS_ERROR;
   2250       }
   2251       //
   2252       // Consume arguments until next -arg or end
   2253       //
   2254       do {
   2255         Argv++;
   2256         Argc--;
   2257         //
   2258         // Open the file, read the pack header, and figure out what type of
   2259         // HII pack it is.
   2260         //
   2261         if ((InFptr = fopen (Argv[0], "rb")) == NULL) {
   2262           Error (NULL, 0, 0, Argv[0], "failed to open input HII pack file for reading");
   2263           return STATUS_ERROR;
   2264         }
   2265 
   2266         if (fread (&PackHeader, sizeof (EFI_HII_PACK_HEADER), 1, InFptr) != 1) {
   2267           Error (NULL, 0, 0, Argv[0], "failed to read pack header from input HII pack file");
   2268           fclose (InFptr);
   2269           return STATUS_ERROR;
   2270         }
   2271 
   2272         fclose (InFptr);
   2273         if ((PackHeader.Type != EFI_HII_STRING) &&
   2274             (PackHeader.Type != EFI_HII_IFR) &&
   2275             (PackHeader.Type != EFI_HII_VARIABLE)
   2276             ) {
   2277           Error (NULL, 0, 0, Argv[0], "unsupported HII pack type 0x%X", (unsigned int) PackHeader.Type);
   2278           return STATUS_ERROR;
   2279         }
   2280         //
   2281         // Add this file name to our list of pack files
   2282         //
   2283         FileName = (FILE_NAME_LIST *) malloc (sizeof (FILE_NAME_LIST));
   2284         if (FileName == NULL) {
   2285           Error (NULL, 0, 0, "memory allocation failure", NULL);
   2286           return STATUS_ERROR;
   2287         }
   2288 
   2289         memset ((void *) FileName, 0, sizeof (FILE_NAME_LIST));
   2290         FileName->Tag = (int) PackHeader.Type;
   2291         strcpy (FileName->FileName, Argv[0]);
   2292         if (mGlobals.PackFileNames == NULL) {
   2293           mGlobals.PackFileNames = FileName;
   2294         } else {
   2295           //
   2296           // Add to the end of the list
   2297           //
   2298           for (TempFileName = mGlobals.PackFileNames; TempFileName->Next != NULL; TempFileName = TempFileName->Next)
   2299             ;
   2300           TempFileName->Next = FileName;
   2301         }
   2302       } while ((Argc > 1) && (Argv[1][0] != '-'));
   2303     } else if (_stricmp (Argv[0], "-noemptyvarpacks") == 0) {
   2304       mGlobals.NoEmptyVarPacks = 1;
   2305     } else if (_stricmp (Argv[0], "-novarpacks") == 0) {
   2306       mGlobals.NoVarPacks = 1;
   2307     } else if (_stricmp (Argv[0], "-x") == 0) {
   2308       //
   2309       // -x option to specify an input HII export file name. Not valid for 'create' mode
   2310       //
   2311       if (mGlobals.Mode == MODE_CREATE_HII_EXPORT) {
   2312         Error (NULL, 0, 0, Argv[0], "option is not valid in 'create' mode");
   2313         return STATUS_ERROR;
   2314       }
   2315 
   2316       if ((Argc <= 1) || (Argv[1][0] == '-')) {
   2317         Error (UTILITY_NAME, 0, 0, Argv[0], "missing HII export input file name");
   2318         return STATUS_ERROR;
   2319       }
   2320       //
   2321       // Consume arguments until next -arg or end
   2322       //
   2323       do {
   2324         Argv++;
   2325         Argc--;
   2326         //
   2327         // Add this file name to our list of export files
   2328         //
   2329         FileName = (FILE_NAME_LIST *) malloc (sizeof (FILE_NAME_LIST));
   2330         if (FileName == NULL) {
   2331           Error (NULL, 0, 0, "memory allocation failure", NULL);
   2332           return STATUS_ERROR;
   2333         }
   2334 
   2335         memset ((void *) FileName, 0, sizeof (FILE_NAME_LIST));
   2336         strcpy (FileName->FileName, Argv[0]);
   2337         if (mGlobals.HiiExportFileNames == NULL) {
   2338           mGlobals.HiiExportFileNames = FileName;
   2339         } else {
   2340           //
   2341           // Add to the end of the list
   2342           //
   2343           for (TempFileName = mGlobals.HiiExportFileNames;
   2344                TempFileName->Next != NULL;
   2345                TempFileName = TempFileName->Next
   2346               )
   2347             ;
   2348           TempFileName->Next = FileName;
   2349         }
   2350       } while ((Argc > 1) && (Argv[1][0] != '-'));
   2351     } else if (_stricmp (Argv[0], "-dumpstrings") == 0) {
   2352       mGlobals.DumpStrings = 1;
   2353     } else if (_stricmp (Argv[0], "-s") == 0) {
   2354       //
   2355       // -s option to specify input HII export files using a path and file mask.
   2356       // Only valid in merge mode
   2357       //
   2358       if (mGlobals.Mode != MODE_MERGE_HII_EXPORTS) {
   2359         Error (NULL, 0, 0, Argv[0], "option only valid in 'merge' mode");
   2360         return STATUS_ERROR;
   2361       }
   2362 
   2363       if ((Argc <= 1) || (Argv[1][0] == '-')) {
   2364         Error (UTILITY_NAME, 0, 0, Argv[0], "missing root directory name");
   2365         return STATUS_ERROR;
   2366       }
   2367 
   2368       if ((Argc <= 2) || (Argv[2][0] == '-')) {
   2369         Error (UTILITY_NAME, 0, 0, Argv[0], "missing file mask");
   2370         return STATUS_ERROR;
   2371       }
   2372       //
   2373       // Call our function to process the directory and file mask. If
   2374       // the directory does not start with c:\, then prepend cwd to it.
   2375       //
   2376       if (FindFiles (Argv[1], Argv[2], FindFilesCallback)) {
   2377         Error (NULL, 0, 0, "failed to process matching files", "%s\\%s", Argv[1], Argv[2]);
   2378         return STATUS_ERROR;
   2379       }
   2380 
   2381       Argv += 2;
   2382       Argc -= 2;
   2383     } else if (_stricmp (Argv[0], "-p") == 0) {
   2384       //
   2385       // -p option to specify an input pack file. Only valid for 'create' mode
   2386       //
   2387       if (mGlobals.Mode != MODE_CREATE_HII_EXPORT) {
   2388         Error (NULL, 0, 0, Argv[0], "option only valid in 'create' mode");
   2389         return STATUS_ERROR;
   2390       }
   2391 
   2392       if ((Argc <= 1) || (Argv[1][0] == '-')) {
   2393         Error (UTILITY_NAME, 0, 0, Argv[0], "missing pack file name");
   2394         return STATUS_ERROR;
   2395       }
   2396       //
   2397       // Consume arguments until next -arg or end
   2398       //
   2399       do {
   2400         Argv++;
   2401         Argc--;
   2402         //
   2403         // Open the file, read the pack header, and figure out what type of
   2404         // HII pack it is.
   2405         //
   2406         if ((InFptr = fopen (Argv[0], "rb")) == NULL) {
   2407           Error (NULL, 0, 0, Argv[0], "failed to open input HII pack file for reading");
   2408           return STATUS_ERROR;
   2409         }
   2410 
   2411         if (fread (&PackHeader, sizeof (EFI_HII_PACK_HEADER), 1, InFptr) != 1) {
   2412           Error (NULL, 0, 0, Argv[0], "failed to read pack header from input HII pack file");
   2413           fclose (InFptr);
   2414           return STATUS_ERROR;
   2415         }
   2416 
   2417         fclose (InFptr);
   2418         if ((PackHeader.Type != EFI_HII_STRING) &&
   2419             (PackHeader.Type != EFI_HII_IFR) &&
   2420             (PackHeader.Type != EFI_HII_VARIABLE)
   2421             ) {
   2422           Error (NULL, 0, 0, Argv[0], "unsupported HII pack type 0x%X", (unsigned int) PackHeader.Type);
   2423           return STATUS_ERROR;
   2424         }
   2425         //
   2426         // Add this file name to our list of pack files
   2427         //
   2428         FileName = (FILE_NAME_LIST *) malloc (sizeof (FILE_NAME_LIST));
   2429         if (FileName == NULL) {
   2430           Error (NULL, 0, 0, "memory allocation failure", NULL);
   2431           return STATUS_ERROR;
   2432         }
   2433 
   2434         memset ((void *) FileName, 0, sizeof (FILE_NAME_LIST));
   2435         FileName->Tag = (int) PackHeader.Type;
   2436         strcpy (FileName->FileName, Argv[0]);
   2437         if (mGlobals.PackFileNames == NULL) {
   2438           mGlobals.PackFileNames = FileName;
   2439         } else {
   2440           //
   2441           // Add to the end of the list
   2442           //
   2443           for (TempFileName = mGlobals.PackFileNames; TempFileName->Next != NULL; TempFileName = TempFileName->Next)
   2444             ;
   2445           TempFileName->Next = FileName;
   2446         }
   2447       } while ((Argc > 1) && (Argv[1][0] != '-'));
   2448     } else {
   2449       Error (NULL, 0, 0, Argv[0], "unrecognized option");
   2450       return STATUS_ERROR;
   2451     }
   2452 
   2453     Argv++;
   2454     Argc--;
   2455   }
   2456   //
   2457   // All modes except 'defaults' requires an output file name
   2458   //
   2459   if (mGlobals.Mode != MODE_EMIT_DEFAULTS) {
   2460     if (mGlobals.OutputFileName[0] == 0) {
   2461       Error (NULL, 0, 0, "must specify '-o OutputFileName'", NULL);
   2462       return STATUS_ERROR;
   2463     }
   2464     //
   2465     // If merging, then you have to specify at least one HII export files.
   2466     // We support specifying only one file in case you want to take an export file
   2467     // and emit a copy with different (for example, manufacturing) defaults.
   2468     //
   2469     if (mGlobals.Mode == MODE_MERGE_HII_EXPORTS) {
   2470       if (mGlobals.HiiExportFileNames == NULL) {
   2471         Error (NULL, 0, 0, "must specify at least one HII export file in 'merge' mode", NULL);
   2472         return STATUS_ERROR;
   2473       }
   2474     } else if (mGlobals.Mode == MODE_CREATE_HII_EXPORT) {
   2475       //
   2476       // Must have specified at least one HII pack file
   2477       //
   2478       if (mGlobals.PackFileNames == NULL) {
   2479         Error (NULL, 0, 0, "must specify at least one input HII pack file in 'create' mode", NULL);
   2480         return STATUS_ERROR;
   2481       }
   2482     }
   2483   } else {
   2484     //
   2485     // Must have specified an input HII export file name
   2486     //
   2487     if (mGlobals.HiiExportFileNames == NULL) {
   2488       Error (NULL, 0, 0, "must specify at least one '-x HiiExportFileName'", NULL);
   2489       return STATUS_ERROR;
   2490     }
   2491   }
   2492 
   2493   return STATUS_SUCCESS;
   2494 }
   2495 
   2496 static
   2497 void
   2498 Usage (
   2499   VOID
   2500   )
   2501 /*++
   2502 
   2503 Routine Description:
   2504 
   2505   Print usage information for this utility.
   2506 
   2507 Arguments:
   2508 
   2509   None.
   2510 
   2511 Returns:
   2512 
   2513   Nothing.
   2514 
   2515 --*/
   2516 {
   2517   int          Index;
   2518   const char   *Str[] = {
   2519     UTILITY_NAME" "UTILITY_VERSION" - Create/Dump HII Database Files Utility",
   2520     "  Copyright (C), 2004 - 2008 Intel Corporation",
   2521 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )
   2522     "  Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,
   2523 #endif
   2524     "",
   2525     "Usage:",
   2526     "  "UTILITY_NAME " [MODE] [OPTION]",
   2527     "Modes:",
   2528     "  create     create an HII export file from one or more HII pack files",
   2529     "  merge      merge two or more HII export files into one HII export file",
   2530     "  defaults   emit variable defaults from an input HII export file",
   2531     "  dump       ASCII dump the contents of an HII export file",
   2532     "Options for all modes:",
   2533     "  -o FileName write output to FileName",
   2534     "  -mfg        use manufacturing defaults from IFR rather than standard defaults",
   2535     "  -g GUID     use GUID for a package GUID in the data tables where applicable",
   2536     "  -v          verbose operation",
   2537     "Options for 'create' mode:",
   2538     "  -p PackFileName(s)  include contents of HII pack file PackFileName",
   2539     "                      in the output file",
   2540     "  -novarpacks         don't emit variable packs to the output file",
   2541     "Options for 'merge' mode:",
   2542     "  -x HiiExportFileName(s)  include contents of HII export file",
   2543     "                           HiiExportFileName in the output file",
   2544     "  -s Path FileMask         include all matching HII export files in Path",
   2545     "                           and its subdirectories in the output file.",
   2546     "                           If Path does not begin with the form C:\\, then",
   2547     "                           it is assumed to be relative to the current working",
   2548     "                           directory. FileMask may contain wildcard characters.",
   2549     "Options for 'defaults' mode:",
   2550     "  -x HiiExportFileName     emit defaults from all variables referenced",
   2551     "                           in input file HiiExportFileName",
   2552     "  -noemptyvarpacks         don't emit variable packs for 0-length variables",
   2553     "Options for 'dump' mode:",
   2554     "  -x HiiExportFileName     dump contents of input file HiiExportFileName",
   2555     "  -dumpstrings             dump string data",
   2556     NULL
   2557   };
   2558   for (Index = 0; Str[Index] != NULL; Index++) {
   2559     fprintf (stdout, "%s\n", Str[Index]);
   2560   }
   2561 }
   2562