]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/HiiPack/HiiPack.c
EdkCompatibilityPkg: Fix some typos of "according"
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / HiiPack / HiiPack.c
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 }