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