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