1 /*++ 2 3 Copyright (c) 2007 - 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 13 Module Name: 14 15 EfiRom.c 16 17 Abstract: 18 19 Utility program to create an EFI option ROM image from binary and 20 EFI PE32 files. 21 22 23 --*/ 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <stdlib.h> 28 29 // 30 // Includes for EFI 1.1 build 31 // 32 // #include "Tiano.h" // required defines for Compress.h 33 // #include "EfiImage.h" // for PE32 structure definitions 34 // #include "Compress.h" // for compression function 35 // Includes for Tiano build 36 // 37 #include "TianoCommon.h" 38 #include "EfiImage.h" // for PE32 structure definitions 39 #include "Compress.h" 40 41 // 42 // END include differences 43 // 44 #include "Pci.h" // for option ROM header structures 45 // 46 // Version of this utility 47 // 48 #define UTILITY_NAME "EfiRom" 49 #define UTILITY_VERSION "v2.7" 50 51 // 52 // Define some status return values 53 // 54 #define STATUS_SUCCESS 0 55 #define STATUS_WARNING 1 56 #define STATUS_ERROR 2 57 58 // 59 // Define the max length of a filename 60 // 61 #define MAX_PATH 200 62 63 #define DEFAULT_OUTPUT_EXTENSION ".rom" 64 65 // 66 // Max size for an option ROM image 67 // 68 #define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB 69 // 70 // Values for the indicator field in the PCI data structure 71 // 72 #define INDICATOR_LAST 0x80 // last file in series of files 73 // 74 // Masks for the FILE_LIST.FileFlags field 75 // 76 #define FILE_FLAG_BINARY 0x01 77 #define FILE_FLAG_EFI 0x02 78 #define FILE_FLAG_COMPRESS 0x04 79 80 // 81 // Use this linked list structure to keep track of all the filenames 82 // specified on the command line. 83 // 84 typedef struct _FILE_LIST { 85 struct _FILE_LIST *Next; 86 INT8 *FileName; 87 UINT32 FileFlags; 88 UINT32 ClassCode; 89 UINT16 CodeRevision; 90 } FILE_LIST; 91 92 // 93 // Use this to track our command-line options 94 // 95 typedef struct { 96 INT8 OutFileName[MAX_PATH]; 97 INT8 NoLast; 98 INT8 Verbose; 99 INT8 DumpOption; 100 UINT8 DevIdValid; 101 UINT8 VendIdValid; 102 UINT16 VendId; 103 UINT16 DevId; 104 FILE_LIST *FileList; 105 } OPTIONS; 106 107 // 108 // Make a global structure to keep track of command-line options 109 // 110 static OPTIONS mOptions; 111 112 // 113 // Use these to convert from machine type value to a named type 114 // 115 typedef struct { 116 UINT16 Value; 117 char *Name; 118 } STRING_LOOKUP; 119 120 static STRING_LOOKUP mMachineTypes[] = { 121 EFI_IMAGE_MACHINE_IA32, 122 "IA32", 123 EFI_IMAGE_MACHINE_IA64, 124 "IA64", 125 EFI_IMAGE_MACHINE_EBC, 126 "EBC", 127 0, 128 NULL 129 }; 130 131 static STRING_LOOKUP mSubsystemTypes[] = { 132 EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION, 133 "EFI application", 134 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, 135 "EFI boot service driver", 136 EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, 137 "EFI runtime driver", 138 0, 139 NULL 140 }; 141 142 static char* mCodeTypeStr[] = { 143 "PCAT Image", 144 "Open Firmware Image", 145 "HP PA RISC Image", 146 "EFI Image", 147 "Undefined" 148 }; 149 150 // 151 // Function prototypes 152 // 153 static 154 void 155 Usage ( 156 VOID 157 ); 158 159 static 160 int 161 ParseCommandLine ( 162 int Argc, 163 char *Argv[], 164 OPTIONS *Options 165 ); 166 167 static 168 int 169 CheckPE32File ( 170 FILE *Fptr, 171 UINT16 *MachineType, 172 UINT16 *SubSystem 173 ); 174 175 static 176 int 177 ProcessEfiFile ( 178 FILE *OutFptr, 179 FILE_LIST *InFile, 180 UINT16 VendId, 181 UINT16 DevId, 182 UINT32 *Size 183 ); 184 185 static 186 int 187 ProcessBinFile ( 188 FILE *OutFptr, 189 FILE_LIST *InFile, 190 UINT32 *Size 191 ); 192 193 static 194 void 195 DumpImage ( 196 FILE_LIST *InFile 197 ); 198 199 char * 200 GetMachineTypeStr ( 201 UINT16 MachineType 202 ); 203 204 static 205 char * 206 GetSubsystemTypeStr ( 207 UINT16 SubsystemType 208 ); 209 210 int 211 main ( 212 int Argc, 213 char *Argv[] 214 ) 215 /*++ 216 217 Routine Description: 218 219 Given an EFI image filename, create a ROM-able image by creating an option 220 ROM header and PCI data structure, filling them in, and then writing the 221 option ROM header + PCI data structure + EFI image out to the output file. 222 223 Arguments: 224 225 Argc - standard C main() argument count 226 227 Argv - standard C main() argument list 228 229 Returns: 230 231 0 success 232 non-zero otherwise 233 234 --*/ 235 // GC_TODO: ] - add argument and description to function comment 236 { 237 INT8 *Ext; 238 FILE *FptrOut; 239 UINT32 Status; 240 FILE_LIST *FList; 241 UINT32 TotalSize; 242 UINT32 Size; 243 244 Status = STATUS_SUCCESS; 245 FptrOut = NULL; 246 247 // 248 // Parse the command line arguments 249 // 250 if (ParseCommandLine (Argc, Argv, &mOptions)) { 251 return STATUS_ERROR; 252 } 253 // 254 // If dumping an image, then do that and quit 255 // 256 if (mOptions.DumpOption) { 257 DumpImage (mOptions.FileList); 258 goto BailOut; 259 } 260 // 261 // Determine the output filename. Either what they specified on 262 // the command line, or the first input filename with a different extension. 263 // 264 if (!mOptions.OutFileName[0]) { 265 strcpy (mOptions.OutFileName, mOptions.FileList->FileName); 266 // 267 // Find the last . on the line and replace the filename extension with 268 // the default 269 // 270 for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1; 271 (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\'); 272 Ext-- 273 ) 274 ; 275 // 276 // If dot here, then insert extension here, otherwise append 277 // 278 if (*Ext != '.') { 279 Ext = mOptions.OutFileName + strlen (mOptions.OutFileName); 280 } 281 282 strcpy (Ext, DEFAULT_OUTPUT_EXTENSION); 283 } 284 // 285 // Make sure we don't have the same filename for input and output files 286 // 287 for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) { 288 if (_stricmp (mOptions.OutFileName, FList->FileName) == 0) { 289 Status = STATUS_ERROR; 290 fprintf ( 291 stdout, 292 "ERROR: Input and output file names must be different - %s = %s\n", 293 FList->FileName, 294 mOptions.OutFileName 295 ); 296 goto BailOut; 297 } 298 } 299 // 300 // Now open our output file 301 // 302 if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) { 303 fprintf (stdout, "ERROR: Failed to open output file %s\n", mOptions.OutFileName); 304 goto BailOut; 305 } 306 // 307 // Process all our files 308 // 309 TotalSize = 0; 310 for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) { 311 Size = 0; 312 if (FList->FileFlags & FILE_FLAG_EFI) { 313 if (mOptions.Verbose) { 314 fprintf (stdout, "Processing EFI file %s\n", FList->FileName); 315 } 316 317 Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size); 318 } else if (FList->FileFlags & FILE_FLAG_BINARY) { 319 if (mOptions.Verbose) { 320 fprintf (stdout, "Processing binary file %s\n", FList->FileName); 321 } 322 323 Status = ProcessBinFile (FptrOut, FList, &Size); 324 } else { 325 fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName); 326 Status = STATUS_ERROR; 327 } 328 329 if (mOptions.Verbose) { 330 fprintf (stdout, " Output size = 0x%X\n", Size); 331 } 332 333 if (Status != STATUS_SUCCESS) { 334 break; 335 } 336 337 TotalSize += Size; 338 } 339 // 340 // Check total size 341 // 342 if (TotalSize > MAX_OPTION_ROM_SIZE) { 343 fprintf ( 344 stdout, 345 "ERROR: Option ROM image size exceeds limit 0x%X bytes\n", 346 MAX_OPTION_ROM_SIZE 347 ); 348 Status = STATUS_ERROR; 349 } 350 351 BailOut: 352 if (FptrOut != NULL) { 353 fclose (FptrOut); 354 } 355 // 356 // Clean up our file list 357 // 358 while (mOptions.FileList != NULL) { 359 FList = mOptions.FileList->Next; 360 free (mOptions.FileList); 361 mOptions.FileList = FList; 362 } 363 364 return Status; 365 } 366 367 UINT8 368 CheckSum ( 369 UINT8 *Buffer, 370 UINT32 DataSize, 371 UINT32 PaddingSize 372 ) 373 /*++ 374 Routine Description: 375 Calculate checksum from DataSize of Buffer. 376 377 Arguments: 378 Buffer - pointer to data buffer 379 DataSize - size of data buffer in bytes 380 381 Return: 382 UINT8 - checksum 383 --*/ 384 { 385 UINT8 Checksum = 0; 386 while (DataSize-- != 0) { 387 Checksum = Checksum + Buffer[DataSize]; 388 } 389 while (PaddingSize-- != 0) { 390 Checksum = Checksum + 0xff; 391 } 392 return Checksum; 393 } 394 395 char * 396 GetCodeTypeStr ( 397 UINT8 CodeType 398 ) 399 { 400 if (CodeType >= ARRAY_SIZE (mCodeTypeStr)) { 401 CodeType = ARRAY_SIZE (mCodeTypeStr) - 1; 402 } 403 return mCodeTypeStr[CodeType]; 404 } 405 406 static 407 int 408 ProcessBinFile ( 409 FILE *OutFptr, 410 FILE_LIST *InFile, 411 UINT32 *Size 412 ) 413 /*++ 414 415 Routine Description: 416 417 Process a binary input file. 418 419 Arguments: 420 421 OutFptr - file pointer to output binary ROM image file we're creating 422 InFile - structure contains information on the binary file to process 423 Size - pointer to where to return the size added to the output file 424 425 Returns: 426 427 0 - successful 428 429 --*/ 430 { 431 FILE *InFptr; 432 UINT32 TotalSize; 433 UINT32 FileSize; 434 UINT32 DataSize; 435 UINT32 PaddingSize; 436 UINT8 *Buffer; 437 UINT32 Status; 438 PCI_EXPANSION_ROM_HEADER *RomHdr; 439 PCI_DATA_STRUCTURE *PciDs; 440 UINT8 ByteCheckSum; 441 442 Status = STATUS_SUCCESS; 443 444 // 445 // Try to open the input file 446 // 447 if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { 448 fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName); 449 return STATUS_ERROR; 450 } 451 // 452 // Seek to the end of the input file and get the file size. Then allocate 453 // a buffer to read it in to. 454 // 455 fseek (InFptr, 0, SEEK_END); 456 FileSize = ftell (InFptr); 457 if (mOptions.Verbose) { 458 fprintf (stdout, " File size = 0x%X\n", FileSize); 459 } 460 461 fseek (InFptr, 0, SEEK_SET); 462 Buffer = (INT8 *) malloc (FileSize); 463 if (Buffer == NULL) { 464 fprintf (stdout, "ERROR: Memory allocation failed\n"); 465 Status = STATUS_ERROR; 466 goto BailOut; 467 } 468 469 if (fread (Buffer, FileSize, 1, InFptr) != 1) { 470 fprintf (stdout, "ERROR: Failed to read all bytes from input file\n"); 471 Status = STATUS_ERROR; 472 goto BailOut; 473 } 474 475 476 RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer; 477 PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset); 478 479 // 480 // Crude check to make sure it's a legitimate ROM image 481 // 482 if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { 483 fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n"); 484 Status = STATUS_ERROR; 485 goto BailOut; 486 } 487 // 488 // Make sure the pointer to the PCI data structure is within the size of the image. 489 // Then check it for valid signature. 490 // 491 if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) { 492 fprintf (stdout, "ERROR: Invalid PCI data structure offset\n"); 493 Status = STATUS_ERROR; 494 goto BailOut; 495 } 496 497 if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { 498 fprintf (stdout, "ERROR: PCI data structure has invalid signature\n"); 499 Status = STATUS_ERROR; 500 goto BailOut; 501 } 502 503 if ((UINT32) (PciDs->ImageLength * 512) == FileSize) { 504 // 505 // ImageLength reflects the actual file size correctly. 506 // 507 DataSize = FileSize - 1; 508 PaddingSize = 0; 509 TotalSize = FileSize; 510 } else { 511 // 512 // ImageLength doesn't reflect the actual file size, 513 // 1). add additional 512 bytes if actual file size is multiple of 512 514 // 2). add additional X (X <= 512) bytes so that the result size is multiple of 512 515 // 516 fprintf (stdout, "WARNING: ImageLength in PCI data structure != Actual File Size\n" 517 " --> add additional padding bytes\n" 518 " --> adjust ImageLength\n" 519 ); 520 TotalSize = (FileSize + 0x200) & ~0x1ff; 521 DataSize = FileSize; 522 PaddingSize = TotalSize - DataSize - 1; 523 PciDs->ImageLength = (UINT16) (TotalSize / 512); 524 } 525 526 // 527 // Check size 528 // 529 if (TotalSize > MAX_OPTION_ROM_SIZE) { 530 fprintf ( 531 stdout, 532 "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n", 533 InFile->FileName, 534 MAX_OPTION_ROM_SIZE 535 ); 536 Status = STATUS_ERROR; 537 goto BailOut; 538 } 539 540 // 541 // Return the size to the caller so they can keep track of the running total. 542 // 543 *Size = TotalSize; 544 545 // 546 // If this is the last image, then set the LAST bit unless requested not 547 // to via the command-line -l argument. Otherwise, make sure you clear it. 548 // 549 if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { 550 PciDs->Indicator |= INDICATOR_LAST; 551 } else { 552 PciDs->Indicator &= ~INDICATOR_LAST; 553 } 554 555 ByteCheckSum = -CheckSum (Buffer, DataSize, PaddingSize); 556 557 if (fwrite (Buffer, DataSize, 1, OutFptr) != 1) { 558 fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n"); 559 Status = STATUS_ERROR; 560 goto BailOut; 561 } 562 563 while (PaddingSize-- != 0) { 564 putc (~0, OutFptr); 565 } 566 putc (ByteCheckSum, OutFptr); 567 568 BailOut: 569 if (InFptr != NULL) { 570 fclose (InFptr); 571 } 572 573 if (Buffer != NULL) { 574 free (Buffer); 575 } 576 // 577 // Print the file name if errors occurred 578 // 579 if (Status != STATUS_SUCCESS) { 580 fprintf (stdout, "Error processing binary file %s\n", InFile->FileName); 581 } 582 583 return Status; 584 } 585 586 static 587 int 588 ProcessEfiFile ( 589 FILE *OutFptr, 590 FILE_LIST *InFile, 591 UINT16 VendId, 592 UINT16 DevId, 593 UINT32 *Size 594 ) 595 /*++ 596 597 Routine Description: 598 599 Process a PE32 EFI file. 600 601 Arguments: 602 603 OutFptr - file pointer to output binary ROM image file we're creating 604 InFile - structure contains information on the PE32 file to process 605 VendId - vendor ID as required in the option ROM header 606 DevId - device ID as required in the option ROM header 607 Size - pointer to where to return the size added to the output file 608 609 Returns: 610 611 0 - successful 612 613 --*/ 614 { 615 UINT32 Status; 616 FILE *InFptr; 617 EFI_PCI_EXPANSION_ROM_HEADER RomHdr; 618 PCI_DATA_STRUCTURE PciDs; 619 UINT32 FileSize; 620 UINT32 CompressedFileSize; 621 UINT8 *Buffer; 622 UINT8 *CompressedBuffer; 623 UINT8 *TempBufferPtr; 624 UINT32 TotalSize; 625 UINT32 HeaderSize; 626 UINT16 MachineType; 627 UINT16 SubSystem; 628 UINT32 HeaderPadBytes; 629 630 // 631 // Try to open the input file 632 // 633 if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { 634 fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName); 635 return STATUS_ERROR; 636 } 637 // 638 // Initialize our buffer pointers to null. 639 // 640 Buffer = NULL; 641 CompressedBuffer = NULL; 642 643 // 644 // Double-check the file to make sure it's what we expect it to be 645 // 646 Status = CheckPE32File (InFptr, &MachineType, &SubSystem); 647 if (Status != STATUS_SUCCESS) { 648 goto BailOut; 649 } 650 // 651 // Seek to the end of the input file and get the file size 652 // 653 fseek (InFptr, 0, SEEK_END); 654 FileSize = ftell (InFptr); 655 656 // 657 // Get the size of the headers we're going to put in front of the image. The 658 // EFI header must be aligned on a 4-byte boundary, so pad accordingly. 659 // 660 if (sizeof (RomHdr) & 0x03) { 661 HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03); 662 } else { 663 HeaderPadBytes = 0; 664 } 665 666 HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); 667 if (mOptions.Verbose) { 668 fprintf (stdout, " File size = 0x%X\n", FileSize); 669 } 670 // 671 // Allocate memory for the entire file (in case we have to compress), then 672 // seek back to the beginning of the file and read it into our buffer. 673 // 674 Buffer = (INT8 *) malloc (FileSize); 675 if (Buffer == NULL) { 676 fprintf (stdout, "ERROR: Memory allocation failed\n"); 677 Status = STATUS_ERROR; 678 goto BailOut; 679 } 680 681 fseek (InFptr, 0, SEEK_SET); 682 if (fread (Buffer, FileSize, 1, InFptr) != 1) { 683 fprintf (stdout, "ERROR: Failed to read all bytes from input file\n"); 684 Status = STATUS_ERROR; 685 goto BailOut; 686 } 687 // 688 // Now determine the size of the final output file. It's either the header size 689 // plus the file's size, or the header size plus the compressed file size. 690 // 691 if (InFile->FileFlags & FILE_FLAG_COMPRESS) { 692 // 693 // Allocate a buffer into which we can compress the image, compress it, 694 // and use that size as the new size. 695 // 696 CompressedBuffer = (INT8 *) malloc (FileSize); 697 if (CompressedBuffer == NULL) { 698 fprintf (stdout, "ERROR: Memory allocation failed\n"); 699 Status = STATUS_ERROR; 700 goto BailOut; 701 } 702 703 CompressedFileSize = FileSize; 704 Status = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize); 705 if (Status != STATUS_SUCCESS) { 706 fprintf (stdout, "ERROR: Compression failed\n"); 707 goto BailOut; 708 } 709 // 710 // Now compute the size, then swap buffer pointers. 711 // 712 if (mOptions.Verbose) { 713 fprintf (stdout, " Comp size = 0x%X\n", CompressedFileSize); 714 } 715 716 TotalSize = CompressedFileSize + HeaderSize; 717 FileSize = CompressedFileSize; 718 TempBufferPtr = Buffer; 719 Buffer = CompressedBuffer; 720 CompressedBuffer = TempBufferPtr; 721 } else { 722 TotalSize = FileSize + HeaderSize; 723 } 724 // 725 // Total size must be an even multiple of 512 bytes 726 // 727 TotalSize = (TotalSize + 0x1ff) & ~0x1ff; 728 729 // 730 // Check size 731 // 732 if (TotalSize > MAX_OPTION_ROM_SIZE) { 733 fprintf ( 734 stdout, 735 "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n", 736 InFile->FileName, 737 MAX_OPTION_ROM_SIZE 738 ); 739 Status = STATUS_ERROR; 740 goto BailOut; 741 } 742 // 743 // Return the size to the caller so they can keep track of the running total. 744 // 745 *Size = TotalSize; 746 747 // 748 // Now fill in the ROM header. These values come from chapter 18 of the 749 // EFI 1.02 specification. 750 // 751 memset (&RomHdr, 0, sizeof (RomHdr)); 752 RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE; 753 RomHdr.InitializationSize = (UINT16) (TotalSize / 512); 754 RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE; 755 RomHdr.EfiSubsystem = SubSystem; 756 RomHdr.EfiMachineType = MachineType; 757 RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize; 758 RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes); 759 // 760 // Set image as compressed or not 761 // 762 if (InFile->FileFlags & FILE_FLAG_COMPRESS) { 763 RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED; 764 } 765 // 766 // Fill in the PCI data structure 767 // 768 memset (&PciDs, 0, sizeof (PCI_DATA_STRUCTURE)); 769 770 PciDs.Signature = PCI_DATA_STRUCTURE_SIGNATURE; 771 PciDs.VendorId = VendId; 772 PciDs.DeviceId = DevId; 773 PciDs.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE); 774 PciDs.Revision = 0; 775 // 776 // Class code and code revision from the command line (optional) 777 // 778 PciDs.ClassCode[0] = (UINT8) InFile->ClassCode; 779 PciDs.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); 780 PciDs.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); 781 PciDs.ImageLength = RomHdr.InitializationSize; 782 PciDs.CodeRevision = InFile->CodeRevision; 783 PciDs.CodeType = PCI_CODE_TYPE_EFI_IMAGE; 784 785 // 786 // If this is the last image, then set the LAST bit unless requested not 787 // to via the command-line -l argument. 788 // 789 if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { 790 PciDs.Indicator |= INDICATOR_LAST; 791 } 792 // 793 // Write the ROM header to the output file 794 // 795 if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) { 796 fprintf (stdout, "ERROR: Failed to write ROM header to output file\n"); 797 Status = STATUS_ERROR; 798 goto BailOut; 799 } 800 801 // 802 // Write pad bytes to align the PciDs 803 // 804 while (HeaderPadBytes > 0) { 805 if (putc (0, OutFptr) == EOF) { 806 fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n"); 807 Status = STATUS_ERROR; 808 goto BailOut; 809 } 810 811 HeaderPadBytes--; 812 } 813 // 814 // Write the PCI data structure header to the output file 815 // 816 if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) { 817 fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n"); 818 Status = STATUS_ERROR; 819 goto BailOut; 820 } 821 // 822 // Keep track of how many bytes left to write 823 // 824 TotalSize -= HeaderSize; 825 826 // 827 // Now dump the input file's contents to the output file 828 // 829 if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { 830 fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n"); 831 Status = STATUS_ERROR; 832 goto BailOut; 833 } 834 835 TotalSize -= FileSize; 836 // 837 // Pad the rest of the image to make it a multiple of 512 bytes 838 // 839 while (TotalSize > 0) { 840 if (putc (~0, OutFptr) == EOF) { 841 fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n"); 842 Status = STATUS_ERROR; 843 goto BailOut; 844 } 845 846 TotalSize--; 847 } 848 849 BailOut: 850 if (InFptr != NULL) { 851 fclose (InFptr); 852 } 853 854 // 855 // Free up our buffers 856 // 857 if (Buffer != NULL) { 858 free (Buffer); 859 } 860 861 if (CompressedBuffer != NULL) { 862 free (CompressedBuffer); 863 } 864 // 865 // Print the file name if errors occurred 866 // 867 if (Status != STATUS_SUCCESS) { 868 fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName); 869 } 870 871 return Status; 872 } 873 874 static 875 int 876 CheckPE32File ( 877 FILE *Fptr, 878 UINT16 *MachineType, 879 UINT16 *SubSystem 880 ) 881 /*++ 882 883 Routine Description: 884 885 GC_TODO: Add function description 886 887 Arguments: 888 889 Fptr - GC_TODO: add argument description 890 MachineType - GC_TODO: add argument description 891 SubSystem - GC_TODO: add argument description 892 893 Returns: 894 895 GC_TODO: add return values 896 897 --*/ 898 { 899 /*++ 900 901 Routine Description: 902 903 Given a file pointer to a supposed PE32 image file, verify that it is indeed a 904 PE32 image file, and then return the machine type in the supplied pointer. 905 906 Arguments: 907 908 Fptr File pointer to the already-opened PE32 file 909 MachineType Location to stuff the machine type of the PE32 file. This is needed 910 because the image may be Itanium-based, IA32, or EBC. 911 912 Returns: 913 914 0 success 915 non-zero otherwise 916 917 --*/ 918 EFI_IMAGE_DOS_HEADER DosHeader; 919 EFI_IMAGE_FILE_HEADER FileHdr; 920 EFI_IMAGE_OPTIONAL_HEADER OptionalHdr; 921 UINT32 PESig; 922 923 // 924 // Position to the start of the file 925 // 926 fseek (Fptr, 0, SEEK_SET); 927 928 // 929 // Read the DOS header 930 // 931 if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) { 932 fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n"); 933 return STATUS_ERROR; 934 } 935 // 936 // Check the magic number (0x5A4D) 937 // 938 if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) { 939 fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n"); 940 return STATUS_ERROR; 941 } 942 // 943 // Position into the file and check the PE signature 944 // 945 fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET); 946 if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) { 947 fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n"); 948 return STATUS_ERROR; 949 } 950 // 951 // Check the PE signature in the header "PE\0\0" 952 // 953 if (PESig != EFI_IMAGE_NT_SIGNATURE) { 954 fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n"); 955 return STATUS_ERROR; 956 } 957 // 958 // Read the file header and stuff their MachineType 959 // 960 if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) { 961 fprintf (stdout, "ERROR: Failed to read PE file header from input file\n"); 962 return STATUS_ERROR; 963 } 964 965 memcpy ((char *) MachineType, &FileHdr.Machine, 2); 966 967 // 968 // Read the optional header so we can get the subsystem 969 // 970 if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) { 971 fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n"); 972 return STATUS_ERROR; 973 } 974 975 *SubSystem = OptionalHdr.Subsystem; 976 if (mOptions.Verbose) { 977 fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem); 978 } 979 // 980 // Good to go 981 // 982 return STATUS_SUCCESS; 983 } 984 985 static 986 int 987 ParseCommandLine ( 988 int Argc, 989 char *Argv[], 990 OPTIONS *Options 991 ) 992 /*++ 993 994 Routine Description: 995 996 Given the Argc/Argv program arguments, and a pointer to an options structure, 997 parse the command-line options and check their validity. 998 999 1000 Arguments: 1001 1002 Argc - standard C main() argument count 1003 Argv[] - standard C main() argument list 1004 Options - pointer to a structure to store the options in 1005 1006 Returns: 1007 1008 STATUS_SUCCESS success 1009 non-zero otherwise 1010 1011 --*/ 1012 // 1013 { 1014 FILE_LIST *FileList; 1015 1016 FILE_LIST *PrevFileList; 1017 UINT32 FileFlags; 1018 UINT32 ClassCode; 1019 UINT32 CodeRevision; 1020 1021 FileFlags = 0; 1022 1023 // 1024 // Clear out the options 1025 // 1026 memset ((char *) Options, 0, sizeof (OPTIONS)); 1027 1028 // 1029 // To avoid compile warnings 1030 // 1031 FileList = PrevFileList = NULL; 1032 1033 ClassCode = 0; 1034 CodeRevision = 0; 1035 // 1036 // Skip over the program name 1037 // 1038 Argc--; 1039 Argv++; 1040 1041 // 1042 // If no arguments, assume they want usage info 1043 // 1044 if (Argc == 0) { 1045 Usage (); 1046 return STATUS_ERROR; 1047 } 1048 // 1049 // Process until no more arguments 1050 // 1051 while (Argc > 0) { 1052 if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) { 1053 // 1054 // To simplify string comparisons, replace slashes with dashes 1055 // 1056 Argv[0][0] = '-'; 1057 1058 // 1059 // Vendor ID specified with -v 1060 // 1061 if (_stricmp (Argv[0], "-v") == 0) { 1062 // 1063 // Make sure there's another parameter 1064 // 1065 if (Argc > 1) { 1066 Options->VendId = (UINT16) strtol (Argv[1], NULL, 16); 1067 Options->VendIdValid = 1; 1068 } else { 1069 fprintf ( 1070 stdout, 1071 "ERROR: Missing Vendor ID with %s\n\n", 1072 Argv[0] 1073 ); 1074 Usage (); 1075 return STATUS_ERROR; 1076 } 1077 1078 Argv++; 1079 Argc--; 1080 } else if (_stricmp (Argv[0], "-d") == 0) { 1081 // 1082 // Device ID specified with -d 1083 // Make sure there's another parameter 1084 // 1085 if (Argc > 1) { 1086 Options->DevId = (UINT16) strtol (Argv[1], NULL, 16); 1087 Options->DevIdValid = 1; 1088 } else { 1089 fprintf ( 1090 stdout, 1091 "ERROR: Missing Device ID with %s\n\n", 1092 Argv[0] 1093 ); 1094 Usage (); 1095 return STATUS_ERROR; 1096 } 1097 1098 Argv++; 1099 Argc--; 1100 } else if (_stricmp (Argv[0], "-o") == 0) { 1101 // 1102 // Output filename specified with -o 1103 // Make sure there's another parameter 1104 // 1105 if (Argc > 1) { 1106 strcpy (Options->OutFileName, Argv[1]); 1107 } else { 1108 fprintf ( 1109 stdout, 1110 "ERROR: Missing output file name with %s\n\n", 1111 Argv[0] 1112 ); 1113 Usage (); 1114 return STATUS_ERROR; 1115 } 1116 1117 Argv++; 1118 Argc--; 1119 } else if ((_stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) { 1120 // 1121 // Help option 1122 // 1123 Usage (); 1124 return STATUS_ERROR; 1125 } else if (_stricmp (Argv[0], "-b") == 0) { 1126 // 1127 // Specify binary files with -b 1128 // 1129 FileFlags = (FileFlags & ~FILE_FLAG_EFI) | FILE_FLAG_BINARY; 1130 } else if ((_stricmp (Argv[0], "-e") == 0) || (_stricmp (Argv[0], "-ec") == 0)) { 1131 // 1132 // Specify EFI files with -e. Specify EFI-compressed with -ec. 1133 // 1134 FileFlags = (FileFlags &~FILE_FLAG_BINARY) | FILE_FLAG_EFI; 1135 if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) { 1136 FileFlags |= FILE_FLAG_COMPRESS; 1137 } 1138 // 1139 // Specify not to set the LAST bit in the last file with -l 1140 // 1141 } else if (_stricmp (Argv[0], "-l") == 0) { 1142 Options->NoLast = 1; 1143 } else if (_stricmp (Argv[0], "-p") == 0) { 1144 // 1145 // -v for verbose would have been nicer, but it's already used. Let's use 1146 // -p for prolix (wordy) output 1147 // 1148 Options->Verbose = 1; 1149 } else if (_stricmp (Argv[0], "-dump") == 0) { 1150 // 1151 // -dump for dumping a ROM image. In this case, say that the device id 1152 // and vendor id are valid so we don't have to specify bogus ones on the 1153 // command line. 1154 // 1155 Options->DumpOption = 1; 1156 1157 Options->VendIdValid = 1; 1158 Options->DevIdValid = 1; 1159 FileFlags = FILE_FLAG_BINARY; 1160 } else if (_stricmp (Argv[0], "-cc") == 0) { 1161 // 1162 // Class code value for the next file in the list. 1163 // Make sure there's another parameter 1164 // 1165 if (Argc > 1) { 1166 // 1167 // No error checking on the return value. Could check for LONG_MAX, 1168 // LONG_MIN, or 0 class code value if desired. Check range (3 bytes) 1169 // at least. 1170 // 1171 ClassCode = (UINT32) strtol (Argv[1], NULL, 16); 1172 if (ClassCode & 0xFF000000) { 1173 fprintf (stdout, "ERROR: Class code %s out of range\n", Argv[1]); 1174 return STATUS_ERROR; 1175 } 1176 } else { 1177 fprintf ( 1178 stdout, 1179 "ERROR: Missing class code value with %s\n\n", 1180 Argv[0] 1181 ); 1182 Usage (); 1183 return STATUS_ERROR; 1184 } 1185 1186 Argv++; 1187 Argc--; 1188 } else if (_stricmp (Argv[0], "-rev") == 0) { 1189 // 1190 // Code revision in the PCI data structure. The value is for the next 1191 // file in the list. 1192 // Make sure there's another parameter 1193 // 1194 if (Argc > 1) { 1195 // 1196 // No error checking on the return value. Could check for LONG_MAX, 1197 // LONG_MIN, or 0 value if desired. Check range (2 bytes) 1198 // at least. 1199 // 1200 CodeRevision = (UINT32) strtol (Argv[1], NULL, 16); 1201 if (CodeRevision & 0xFFFF0000) { 1202 fprintf (stdout, "ERROR: Code revision %s out of range\n", Argv[1]); 1203 return STATUS_ERROR; 1204 } 1205 } else { 1206 fprintf ( 1207 stdout, 1208 "ERROR: Missing code revision value with %s\n\n", 1209 Argv[0] 1210 ); 1211 Usage (); 1212 return STATUS_ERROR; 1213 } 1214 1215 Argv++; 1216 Argc--; 1217 } else { 1218 fprintf (stdout, "ERROR: Invalid option specified: %s\n\n", Argv[0]); 1219 Usage (); 1220 return STATUS_ERROR; 1221 } 1222 } else { 1223 // 1224 // Not a slash-option argument. Must be a file name. Make sure they've specified 1225 // -e or -b already. 1226 // 1227 if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) { 1228 fprintf (stdout, "ERROR: Missing -e or -b with input file %s\n", Argv[0]); 1229 return STATUS_ERROR; 1230 } 1231 // 1232 // Create a new file structure 1233 // 1234 FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST)); 1235 if (FileList == NULL) { 1236 fprintf (stdout, "ERROR: Memory allocation failure\n"); 1237 return STATUS_ERROR; 1238 } 1239 1240 memset ((char *) FileList, 0, sizeof (FILE_LIST)); 1241 FileList->FileName = Argv[0]; 1242 FileList->FileFlags = FileFlags; 1243 if (Options->FileList == NULL) { 1244 Options->FileList = FileList; 1245 } else { 1246 if (PrevFileList == NULL) { 1247 PrevFileList = FileList; 1248 } else { 1249 PrevFileList->Next = FileList; 1250 } 1251 } 1252 1253 PrevFileList = FileList; 1254 // 1255 // Set the class code and code revision for this file, then reset the values. 1256 // 1257 FileList->ClassCode = ClassCode; 1258 FileList->CodeRevision = (UINT16) CodeRevision; 1259 ClassCode = 0; 1260 CodeRevision = 0; 1261 } 1262 // 1263 // Next argument 1264 // 1265 Argv++; 1266 Argc--; 1267 } 1268 // 1269 // Make sure they specified a device ID and vendor ID 1270 // 1271 if (!Options->VendIdValid) { 1272 fprintf (stdout, "ERROR: Missing Vendor ID on command line\n\n"); 1273 Usage (); 1274 return STATUS_ERROR; 1275 } 1276 1277 if (!Options->DevIdValid) { 1278 fprintf (stdout, "ERROR: Missing Device ID on command line\n\n"); 1279 Usage (); 1280 return STATUS_ERROR; 1281 } 1282 // 1283 // Must have specified some files 1284 // 1285 if (Options->FileList == NULL) { 1286 fprintf (stdout, "ERROR: Missing input file name\n"); 1287 Usage (); 1288 return STATUS_ERROR; 1289 } 1290 1291 return 0; 1292 } 1293 1294 static 1295 void 1296 Usage ( 1297 VOID 1298 ) 1299 /*++ 1300 1301 Routine Description: 1302 1303 Print usage information for this utility. 1304 1305 Arguments: 1306 1307 None. 1308 1309 Returns: 1310 1311 Nothing. 1312 1313 --*/ 1314 { 1315 int Index; 1316 const char *Str[] = { 1317 UTILITY_NAME" "UTILITY_VERSION" - Intel EFI Make Option ROM Utility", 1318 " Copyright (C), 1999 - 2008 Intel Coproration", 1319 1320 #if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) ) 1321 " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR, 1322 #endif 1323 1324 "", 1325 "Usage:", 1326 " "UTILITY_NAME" [OPTION]... SOURCE ...", 1327 "Description:", 1328 " Create an option ROM image from a list of input files", 1329 "Options:", 1330 " -v VendorId - required hex PCI Vendor ID for the device", 1331 " -d DeviceId - required hex PCI Device ID for the device", 1332 " -o OutFileName - optional output file name. Default is the first input", 1333 " file name with a "DEFAULT_OUTPUT_EXTENSION" file extension", 1334 " -e SOURCE ... - input are EFI PE32 image file(s)", 1335 " -b SOURCE ... - input are Legacy binary file(s)", 1336 " -ec SOURCE ... - input are EFI PE32 image file(s) and should be compressed", 1337 " -p - for verbose output", 1338 " -l - to not automatically set the LAST bit on the last file", 1339 " -cc ClassCode - to use hex ClassCode in the PCI data structure header for", 1340 " the following SOURCE(s)", 1341 " -rev Revision - to use hex Revision in the PCI data structure header for", 1342 " the following one SOURCE", 1343 " -dump - to dump the headers of an existing option ROM image", 1344 "Example Usage:", 1345 " EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi", 1346 NULL 1347 }; 1348 1349 for (Index = 0; Str[Index] != NULL; Index++) { 1350 fprintf (stdout, "%s\n", Str[Index]); 1351 } 1352 } 1353 1354 static 1355 void 1356 DumpImage ( 1357 FILE_LIST *InFile 1358 ) 1359 /*++ 1360 1361 Routine Description: 1362 1363 GC_TODO: Add function description 1364 1365 Arguments: 1366 1367 InFile - GC_TODO: add argument description 1368 1369 Returns: 1370 1371 GC_TODO: add return values 1372 1373 --*/ 1374 { 1375 PCI_EXPANSION_ROM_HEADER PciRomHdr; 1376 FILE *InFptr; 1377 UINT32 ImageStart; 1378 UINT32 ImageCount; 1379 UINT16 DeviceId; 1380 EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr; 1381 PCI_3_0_DATA_STRUCTURE PciDs; 1382 1383 // 1384 // Open the input file 1385 // 1386 if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { 1387 fprintf ( 1388 stdout, 1389 "ERROR: Could not open input file %s\n", 1390 InFile->FileName 1391 ); 1392 return ; 1393 } 1394 // 1395 // Go through the image and dump the header stuff for each 1396 // 1397 ImageCount = 0; 1398 for (;;) { 1399 // 1400 // Save our postition in the file, since offsets in the headers 1401 // are relative to the particular image. 1402 // 1403 ImageStart = ftell (InFptr); 1404 ImageCount++; 1405 1406 // 1407 // Read the option ROM header. Have to assume a raw binary image for now. 1408 // 1409 if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) { 1410 fprintf (stdout, "ERROR: Failed to read PCI ROM header from file\n"); 1411 goto BailOut; 1412 } 1413 1414 // 1415 // Dump the contents of the header 1416 // 1417 fprintf (stdout, "Image %d -- Offset 0x%X\n", ImageCount, ImageStart); 1418 fprintf (stdout, " ROM header contents\n"); 1419 fprintf (stdout, " Signature 0x%04X\n", (UINT32) PciRomHdr.Signature); 1420 fprintf (stdout, " PCIR offset 0x%04X\n", (UINT32) PciRomHdr.PcirOffset); 1421 // 1422 // Find PCI data structure 1423 // 1424 if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) { 1425 fprintf (stdout, "ERROR: Failed to seek to PCI data structure\n"); 1426 goto BailOut; 1427 } 1428 // 1429 // Read and dump the PCI data structure 1430 // 1431 if (fread (&PciDs, sizeof (PciDs), 1, InFptr) != 1) { 1432 fprintf (stdout, "ERROR: Failed to read PCI data structure from file\n"); 1433 goto BailOut; 1434 } 1435 1436 fprintf (stdout, " PCI Data Structure\n"); 1437 fprintf ( 1438 stdout, 1439 " Signature %c%c%c%c\n", 1440 (char) PciDs.Signature, 1441 (char) (PciDs.Signature >> 8), 1442 (char) (PciDs.Signature >> 16), 1443 (char) (PciDs.Signature >> 24) 1444 ); 1445 fprintf (stdout, " Vendor ID 0x%04X\n", PciDs.VendorId); 1446 fprintf (stdout, " Device ID 0x%04X\n", PciDs.DeviceId); 1447 fprintf (stdout, " Structure Length 0x%04X\n", PciDs.Length); 1448 fprintf (stdout, " PCI Revision 0x%02X\n", PciDs.Revision); 1449 fprintf ( 1450 stdout, 1451 " Class Code 0x%06X\n", 1452 (UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16)) 1453 ); 1454 fprintf (stdout, " Image size 0x%X\n", PciDs.ImageLength * 512); 1455 fprintf (stdout, " Code revision 0x%04X\n", PciDs.CodeRevision); 1456 fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs.Indicator); 1457 // 1458 // Print the indicator, used to flag the last image 1459 // 1460 if ((PciDs.Indicator & INDICATOR_LAST) == INDICATOR_LAST) { 1461 fprintf (stdout, " (last image)\n"); 1462 } else { 1463 fprintf (stdout, "\n"); 1464 } 1465 1466 // 1467 // Print the code type. If EFI code, then we can provide more info. 1468 // 1469 fprintf (stdout, " Code type 0x%02X (%s)\n", (UINT32) PciDs.CodeType, GetCodeTypeStr (PciDs.CodeType)); 1470 if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) { 1471 // 1472 // Re-read the header as an EFI ROM header, then dump more info 1473 // 1474 fprintf (stdout, " EFI ROM header contents\n"); 1475 memcpy (&EfiRomHdr, &PciRomHdr, sizeof (EfiRomHdr)); 1476 // 1477 // Now dump more info 1478 // 1479 fprintf (stdout, " EFI Signature 0x%04X\n", EfiRomHdr.EfiSignature); 1480 fprintf ( 1481 stdout, 1482 " Compression Type 0x%04X ", 1483 (UINT32) EfiRomHdr.CompressionType 1484 ); 1485 if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { 1486 fprintf (stdout, "(compressed)\n"); 1487 } else { 1488 fprintf (stdout, "(not compressed)\n"); 1489 } 1490 1491 fprintf ( 1492 stdout, 1493 " Machine type 0x%04X (%s)\n", 1494 EfiRomHdr.EfiMachineType, 1495 GetMachineTypeStr (EfiRomHdr.EfiMachineType) 1496 ); 1497 fprintf ( 1498 stdout, 1499 " Subsystem 0x%04X (%s)\n", 1500 EfiRomHdr.EfiSubsystem, 1501 GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem) 1502 ); 1503 fprintf ( 1504 stdout, 1505 " EFI image offset 0x%04X (@0x%X)\n", 1506 (UINT32) EfiRomHdr.EfiImageHeaderOffset, 1507 (UINT32) (EfiRomHdr.EfiImageHeaderOffset + ImageStart) 1508 ); 1509 } 1510 1511 // 1512 // Dump additional information for PCI 3.0 OpROM 1513 // 1514 if (PciDs.Revision >= 3) { 1515 fprintf (stdout, " Extended for PCI 3.0\n"); 1516 1517 if (PciDs.DeviceListOffset != 0) { 1518 if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset + PciDs.DeviceListOffset, SEEK_SET)) { 1519 fprintf (stdout, "ERROR: Failed to seek to supported Device List\n"); 1520 goto BailOut; 1521 } 1522 fprintf (stdout, " Device ID List "); 1523 while (TRUE) { 1524 if (fread (&DeviceId, sizeof (DeviceId), 1, InFptr) != 1) { 1525 fprintf (stdout, "ERROR: Failed to read supported DeviceId from DeviceId List\n"); 1526 goto BailOut; 1527 } 1528 if (DeviceId == 0) { 1529 break; 1530 } 1531 fprintf (stdout, "0x%04X ", DeviceId); 1532 } 1533 fprintf (stdout, "\n"); 1534 } 1535 fprintf (stdout, " Max Runtime Image Length 0x%08X\n", PciDs.MaxRuntimeImageLength * 512); 1536 if (PciDs.Length == sizeof (PCI_3_0_DATA_STRUCTURE)) { 1537 fprintf (stdout, " Config Utility Header 0x%04X\n", PciDs.ConfigUtilityCodeHeaderOffset); 1538 fprintf (stdout, " DMTF CLP Entry Point 0x%04X\n", PciDs.DMTFCLPEntryPointOffset); 1539 } else { 1540 fprintf (stdout, "WARNING: Oprom declars 3.0 revision with wrong structure length 0x%04X\n", PciDs.Length); 1541 } 1542 } 1543 1544 // 1545 // If last image, then we're done 1546 // 1547 if ((PciDs.Indicator & INDICATOR_LAST) == INDICATOR_LAST) { 1548 goto BailOut; 1549 } 1550 // 1551 // Seek to the start of the next image 1552 // 1553 if (fseek (InFptr, ImageStart + (PciDs.ImageLength * 512), SEEK_SET)) { 1554 fprintf (stdout, "ERROR: Failed to seek to next image\n"); 1555 goto BailOut; 1556 } 1557 } 1558 1559 BailOut: 1560 fclose (InFptr); 1561 } 1562 1563 char * 1564 GetMachineTypeStr ( 1565 UINT16 MachineType 1566 ) 1567 /*++ 1568 1569 Routine Description: 1570 1571 GC_TODO: Add function description 1572 1573 Arguments: 1574 1575 MachineType - GC_TODO: add argument description 1576 1577 Returns: 1578 1579 GC_TODO: add return values 1580 1581 --*/ 1582 { 1583 int Index; 1584 1585 for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) { 1586 if (mMachineTypes[Index].Value == MachineType) { 1587 return mMachineTypes[Index].Name; 1588 } 1589 } 1590 1591 return "unknown"; 1592 } 1593 1594 static 1595 char * 1596 GetSubsystemTypeStr ( 1597 UINT16 SubsystemType 1598 ) 1599 /*++ 1600 1601 Routine Description: 1602 1603 GC_TODO: Add function description 1604 1605 Arguments: 1606 1607 SubsystemType - GC_TODO: add argument description 1608 1609 Returns: 1610 1611 GC_TODO: add return values 1612 1613 --*/ 1614 { 1615 int Index; 1616 1617 for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) { 1618 if (mSubsystemTypes[Index].Value == SubsystemType) { 1619 return mSubsystemTypes[Index].Name; 1620 } 1621 } 1622 1623 return "unknown"; 1624 } 1625 1626