3 Copyright (c) 1999 - 2002 Intel Corporation. All rights reserved
4 This software and associated documentation (if any) is furnished
5 under a license and may only be used or copied in accordance
6 with the terms of the license. Except as permitted by such
7 license, no part of this software or documentation may be
8 reproduced, stored in a retrieval system, or transmitted in any
9 form or by any means without the express written consent of
18 Utility program to create an EFI option ROM image from binary and
29 // Includes for EFI 1.1 build
31 // #include "Tiano.h" // required defines for Compress.h
32 // #include "EfiImage.h" // for PE32 structure definitions
33 // #include "Compress.h" // for compression function
34 // Includes for Tiano build
36 #include "TianoCommon.h"
37 #include "EfiImage.h" // for PE32 structure definitions
38 #include "EfiCompress.h"
41 // END include differences
43 #include "Pci22.h" // for option ROM header structures
45 // Version of this utility
47 #define UTILITY_VERSION "v2.5"
50 // Define some status return values
52 #define STATUS_SUCCESS 0
53 #define STATUS_WARNING 1
54 #define STATUS_ERROR 2
57 // Define the max length of a filename
61 #define DEFAULT_OUTPUT_EXTENSION ".rom"
64 // Max size for an option ROM image
66 #define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB
68 // Values for the indicator field in the PCI data structure
70 #define INDICATOR_LAST 0x80 // last file in series of files
72 // Masks for the FILE_LIST.FileFlags field
74 #define FILE_FLAG_BINARY 0x01
75 #define FILE_FLAG_EFI 0x02
76 #define FILE_FLAG_COMPRESS 0x04
79 // Use this linked list structure to keep track of all the filenames
80 // specified on the command line.
82 typedef struct _FILE_LIST
{
83 struct _FILE_LIST
*Next
;
91 // Use this to track our command-line options
94 INT8 OutFileName
[MAX_PATH
];
106 // Make a global structure to keep track of command-line options
108 static OPTIONS mOptions
;
111 // Use these to convert from machine type value to a named type
118 static STRING_LOOKUP mMachineTypes
[] = {
119 EFI_IMAGE_MACHINE_IA32
,
121 EFI_IMAGE_MACHINE_IA64
,
123 EFI_IMAGE_MACHINE_EBC
,
129 static STRING_LOOKUP mSubsystemTypes
[] = {
130 EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
,
132 EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
,
133 "EFI boot service driver",
134 EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
,
135 "EFI runtime driver",
140 // Function prototypes
195 GetSubsystemTypeStr (
207 Given an EFI image filename, create a ROM-able image by creating an option
208 ROM header and PCI data structure, filling them in, and then writing the
209 option ROM header + PCI data structure + EFI image out to the output file.
213 Argc - standard C main() argument count
215 Argv - standard C main() argument list
223 // GC_TODO: ] - add argument and description to function comment
232 Status
= STATUS_SUCCESS
;
236 // Parse the command line arguments
238 if (ParseCommandLine (Argc
, Argv
, &mOptions
)) {
242 // If dumping an image, then do that and quit
244 if (mOptions
.DumpOption
) {
245 DumpImage (mOptions
.FileList
);
249 // Determine the output filename. Either what they specified on
250 // the command line, or the first input filename with a different extension.
252 if (!mOptions
.OutFileName
[0]) {
253 strcpy (mOptions
.OutFileName
, mOptions
.FileList
->FileName
);
255 // Find the last . on the line and replace the filename extension with
258 for (Ext
= mOptions
.OutFileName
+ strlen (mOptions
.OutFileName
) - 1;
259 (Ext
>= mOptions
.OutFileName
) && (*Ext
!= '.') && (*Ext
!= '\\');
264 // If dot here, then insert extension here, otherwise append
267 Ext
= mOptions
.OutFileName
+ strlen (mOptions
.OutFileName
);
270 strcpy (Ext
, DEFAULT_OUTPUT_EXTENSION
);
273 // Make sure we don't have the same filename for input and output files
275 for (FList
= mOptions
.FileList
; FList
!= NULL
; FList
= FList
->Next
) {
276 if (stricmp (mOptions
.OutFileName
, FList
->FileName
) == 0) {
277 Status
= STATUS_ERROR
;
280 "ERROR: Input and output file names must be different - %s = %s\n",
288 // Now open our output file
290 if ((FptrOut
= fopen (mOptions
.OutFileName
, "w+b")) == NULL
) {
291 fprintf (stdout
, "ERROR: Failed to open output file %s\n", mOptions
.OutFileName
);
295 // Process all our files
298 for (FList
= mOptions
.FileList
; FList
!= NULL
; FList
= FList
->Next
) {
300 if (FList
->FileFlags
& FILE_FLAG_EFI
) {
301 if (mOptions
.Verbose
) {
302 fprintf (stdout
, "Processing EFI file %s\n", FList
->FileName
);
305 Status
= ProcessEfiFile (FptrOut
, FList
, mOptions
.VendId
, mOptions
.DevId
, &Size
);
306 } else if (FList
->FileFlags
& FILE_FLAG_BINARY
) {
307 if (mOptions
.Verbose
) {
308 fprintf (stdout
, "Processing binary file %s\n", FList
->FileName
);
311 Status
= ProcessBinFile (FptrOut
, FList
, &Size
);
313 fprintf (stdout
, "ERROR: File not specified as EFI or binary: %s\n", FList
->FileName
);
314 Status
= STATUS_ERROR
;
317 if (mOptions
.Verbose
) {
318 fprintf (stdout
, " Output size = 0x%X\n", Size
);
321 if (Status
!= STATUS_SUCCESS
) {
330 if (TotalSize
> MAX_OPTION_ROM_SIZE
) {
333 "ERROR: Option ROM image size exceeds limit 0x%X bytes\n",
336 Status
= STATUS_ERROR
;
340 if (FptrOut
!= NULL
) {
344 // Clean up our file list
346 while (mOptions
.FileList
!= NULL
) {
347 FList
= mOptions
.FileList
->Next
;
348 free (mOptions
.FileList
);
349 mOptions
.FileList
= FList
;
366 Process a binary input file.
370 OutFptr - file pointer to output binary ROM image file we're creating
371 InFile - structure contains information on the binary file to process
372 Size - pointer to where to return the size added to the output file
385 PCI_EXPANSION_ROM_HEADER
*RomHdr
;
386 PCI_DATA_STRUCTURE
*PciDs
;
390 Status
= STATUS_SUCCESS
;
393 // Try to open the input file
395 if ((InFptr
= fopen (InFile
->FileName
, "rb")) == NULL
) {
396 fprintf (stdout
, "ERROR: Failed to open input file %s\n", InFile
->FileName
);
400 // Seek to the end of the input file and get the file size. Then allocate
401 // a buffer to read it in to.
403 fseek (InFptr
, 0, SEEK_END
);
404 FileSize
= ftell (InFptr
);
405 if (mOptions
.Verbose
) {
406 fprintf (stdout
, " File size = 0x%X\n", FileSize
);
409 fseek (InFptr
, 0, SEEK_SET
);
410 Buffer
= (INT8
*) malloc (FileSize
);
411 if (Buffer
== NULL
) {
412 fprintf (stdout
, "ERROR: Memory allocation failed\n");
413 Status
= STATUS_ERROR
;
417 if (fread (Buffer
, FileSize
, 1, InFptr
) != 1) {
418 fprintf (stdout
, "ERROR: Failed to read all bytes from input file\n");
419 Status
= STATUS_ERROR
;
423 // Total size must be an even multiple of 512 bytes, and can't exceed
424 // the option ROM image size.
426 TotalSize
= FileSize
;
427 if (TotalSize
& 0x1FF) {
428 TotalSize
= (TotalSize
+ 0x200) &~0x1ff;
431 if (TotalSize
> MAX_OPTION_ROM_SIZE
) {
434 "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",
438 Status
= STATUS_ERROR
;
442 // Return the size to the caller so they can keep track of the running total.
447 // Crude check to make sure it's a legitimate ROM image
449 RomHdr
= (PCI_EXPANSION_ROM_HEADER
*) Buffer
;
450 if (RomHdr
->Signature
!= PCI_EXPANSION_ROM_HEADER_SIGNATURE
) {
451 fprintf (stdout
, "ERROR: ROM image file has invalid ROM signature\n");
452 Status
= STATUS_ERROR
;
456 // Make sure the pointer to the PCI data structure is within the size of the image.
457 // Then check it for valid signature.
459 if ((RomHdr
->PcirOffset
> FileSize
) || (RomHdr
->PcirOffset
== 0)) {
460 fprintf (stdout
, "ERROR: Invalid PCI data structure offset\n");
461 Status
= STATUS_ERROR
;
465 PciDs
= (PCI_DATA_STRUCTURE
*) (Buffer
+ RomHdr
->PcirOffset
);
466 if (PciDs
->Signature
!= PCI_DATA_STRUCTURE_SIGNATURE
) {
467 fprintf (stdout
, "ERROR: PCI data structure has invalid signature\n");
468 Status
= STATUS_ERROR
;
472 // If this is the last image, then set the LAST bit unless requested not
473 // to via the command-line -l argument. Otherwise, make sure you clear it.
475 if ((InFile
->Next
== NULL
) && (mOptions
.NoLast
== 0)) {
476 PciDs
->Indicator
= INDICATOR_LAST
;
478 PciDs
->Indicator
= 0;
482 for (Index
= 0; Index
< FileSize
- 1; Index
++) {
483 ByteCheckSum
= (UINT8
) (ByteCheckSum
+ Buffer
[Index
]);
486 Buffer
[FileSize
- 1] = (UINT8
) ((~ByteCheckSum
) + 1);
487 fprintf (stdout
, "CheckSUm = %02x\n", (UINT32
) Buffer
[FileSize
- 1]);
490 // Now copy the input file contents out to the output file
492 if (fwrite (Buffer
, FileSize
, 1, OutFptr
) != 1) {
493 fprintf (stdout
, "ERROR: Failed to write all file bytes to output file\n");
494 Status
= STATUS_ERROR
;
498 TotalSize
-= FileSize
;
500 // Pad the rest of the image to make it a multiple of 512 bytes
502 while (TotalSize
> 0) {
508 if (InFptr
!= NULL
) {
512 if (Buffer
!= NULL
) {
516 // Print the file name if errors occurred
518 if (Status
!= STATUS_SUCCESS
) {
519 fprintf (stdout
, "Error processing binary file %s\n", InFile
->FileName
);
538 Process a PE32 EFI file.
542 OutFptr - file pointer to output binary ROM image file we're creating
543 InFile - structure contains information on the PE32 file to process
544 VendId - vendor ID as required in the option ROM header
545 DevId - device ID as required in the option ROM header
546 Size - pointer to where to return the size added to the output file
556 EFI_PCI_EXPANSION_ROM_HEADER RomHdr
;
557 PCI_DATA_STRUCTURE PciDs
;
559 UINT32 CompressedFileSize
;
561 UINT8
*CompressedBuffer
;
562 UINT8
*TempBufferPtr
;
567 UINT32 HeaderPadBytes
;
570 // Try to open the input file
572 if ((InFptr
= fopen (InFile
->FileName
, "rb")) == NULL
) {
573 fprintf (stdout
, "ERROR: Failed to open input file %s\n", InFile
->FileName
);
577 // Initialize our buffer pointers to null.
580 CompressedBuffer
= NULL
;
583 // Double-check the file to make sure it's what we expect it to be
585 Status
= CheckPE32File (InFptr
, &MachineType
, &SubSystem
);
586 if (Status
!= STATUS_SUCCESS
) {
590 // Seek to the end of the input file and get the file size
592 fseek (InFptr
, 0, SEEK_END
);
593 FileSize
= ftell (InFptr
);
596 // Get the size of the headers we're going to put in front of the image. The
597 // EFI header must be aligned on a 4-byte boundary, so pad accordingly.
599 if (sizeof (RomHdr
) & 0x03) {
600 HeaderPadBytes
= 4 - (sizeof (RomHdr
) & 0x03);
605 HeaderSize
= sizeof (PCI_DATA_STRUCTURE
) + HeaderPadBytes
+ sizeof (EFI_PCI_EXPANSION_ROM_HEADER
);
606 if (mOptions
.Verbose
) {
607 fprintf (stdout
, " File size = 0x%X\n", FileSize
);
610 // Allocate memory for the entire file (in case we have to compress), then
611 // seek back to the beginning of the file and read it into our buffer.
613 Buffer
= (INT8
*) malloc (FileSize
);
614 if (Buffer
== NULL
) {
615 fprintf (stdout
, "ERROR: Memory allocation failed\n");
616 Status
= STATUS_ERROR
;
620 fseek (InFptr
, 0, SEEK_SET
);
621 if (fread (Buffer
, FileSize
, 1, InFptr
) != 1) {
622 fprintf (stdout
, "ERROR: Failed to read all bytes from input file\n");
623 Status
= STATUS_ERROR
;
627 // Now determine the size of the final output file. It's either the header size
628 // plus the file's size, or the header size plus the compressed file size.
630 if (InFile
->FileFlags
& FILE_FLAG_COMPRESS
) {
632 // Allocate a buffer into which we can compress the image, compress it,
633 // and use that size as the new size.
635 CompressedBuffer
= (INT8
*) malloc (FileSize
);
636 if (CompressedBuffer
== NULL
) {
637 fprintf (stdout
, "ERROR: Memory allocation failed\n");
638 Status
= STATUS_ERROR
;
642 CompressedFileSize
= FileSize
;
643 Status
= Compress (Buffer
, FileSize
, CompressedBuffer
, &CompressedFileSize
);
644 if (Status
!= STATUS_SUCCESS
) {
645 fprintf (stdout
, "ERROR: Compression failed\n");
649 // Now compute the size, then swap buffer pointers.
651 if (mOptions
.Verbose
) {
652 fprintf (stdout
, " Comp size = 0x%X\n", CompressedFileSize
);
655 TotalSize
= CompressedFileSize
+ HeaderSize
;
656 FileSize
= CompressedFileSize
;
657 TempBufferPtr
= Buffer
;
658 Buffer
= CompressedBuffer
;
659 CompressedBuffer
= TempBufferPtr
;
661 TotalSize
= FileSize
+ HeaderSize
;
664 // Total size must be an even multiple of 512 bytes
666 if (TotalSize
& 0x1FF) {
667 TotalSize
= (TotalSize
+ 0x200) &~0x1ff;
672 if (TotalSize
> MAX_OPTION_ROM_SIZE
) {
675 "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",
679 Status
= STATUS_ERROR
;
683 // Return the size to the caller so they can keep track of the running total.
688 // Now fill in the ROM header. These values come from chapter 18 of the
689 // EFI 1.02 specification.
691 memset (&RomHdr
, 0, sizeof (RomHdr
));
692 RomHdr
.Signature
= PCI_EXPANSION_ROM_HEADER_SIGNATURE
;
693 RomHdr
.InitializationSize
= (UINT16
) (TotalSize
/ 512);
694 RomHdr
.EfiSignature
= EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE
;
695 RomHdr
.EfiSubsystem
= SubSystem
;
696 RomHdr
.EfiMachineType
= MachineType
;
697 RomHdr
.EfiImageHeaderOffset
= (UINT16
) HeaderSize
;
698 RomHdr
.PcirOffset
= (UINT16
) (sizeof (RomHdr
) + HeaderPadBytes
);
700 // Set image as compressed or not
702 if (InFile
->FileFlags
& FILE_FLAG_COMPRESS
) {
703 RomHdr
.CompressionType
= EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
;
706 // Fill in the PCI data structure
708 memset (&PciDs
, 0, sizeof (PCI_DATA_STRUCTURE
));
710 PciDs
.Signature
= PCI_DATA_STRUCTURE_SIGNATURE
;
711 PciDs
.VendorId
= VendId
;
712 PciDs
.DeviceId
= DevId
;
713 PciDs
.Length
= (UINT16
) sizeof (PCI_DATA_STRUCTURE
);
716 // Class code and code revision from the command line (optional)
718 PciDs
.ClassCode
[0] = (UINT8
) InFile
->ClassCode
;
719 PciDs
.ClassCode
[1] = (UINT8
) (InFile
->ClassCode
>> 8);
720 PciDs
.ClassCode
[2] = (UINT8
) (InFile
->ClassCode
>> 16);
721 PciDs
.ImageLength
= RomHdr
.InitializationSize
;
722 PciDs
.CodeRevision
= InFile
->CodeRevision
;
723 PciDs
.CodeType
= PCI_CODE_TYPE_EFI_IMAGE
;
726 // If this is the last image, then set the LAST bit unless requested not
727 // to via the command-line -l argument.
729 if ((InFile
->Next
== NULL
) && (mOptions
.NoLast
== 0)) {
730 PciDs
.Indicator
= INDICATOR_LAST
;
733 // Write the ROM header to the output file
735 if (fwrite (&RomHdr
, sizeof (RomHdr
), 1, OutFptr
) != 1) {
736 fprintf (stdout
, "ERROR: Failed to write ROM header to output file\n");
737 Status
= STATUS_ERROR
;
742 // Write pad bytes to align the PciDs
744 while (HeaderPadBytes
> 0) {
745 if (putc (0, OutFptr
) == EOF
) {
746 fprintf (stdout
, "ERROR: Failed to write ROM header pad bytes to output file\n");
747 Status
= STATUS_ERROR
;
754 // Write the PCI data structure header to the output file
756 if (fwrite (&PciDs
, sizeof (PciDs
), 1, OutFptr
) != 1) {
757 fprintf (stdout
, "ERROR: Failed to write PCI ROM header to output file\n");
758 Status
= STATUS_ERROR
;
762 // Keep track of how many bytes left to write
764 TotalSize
-= HeaderSize
;
767 // Now dump the input file's contents to the output file
769 if (fwrite (Buffer
, FileSize
, 1, OutFptr
) != 1) {
770 fprintf (stdout
, "ERROR: Failed to write all file bytes to output file\n");
771 Status
= STATUS_ERROR
;
775 TotalSize
-= FileSize
;
777 // Pad the rest of the image to make it a multiple of 512 bytes
779 while (TotalSize
> 0) {
780 if (putc (~0, OutFptr
) == EOF
) {
781 fprintf (stdout
, "ERROR: Failed to write trailing pad bytes output file\n");
782 Status
= STATUS_ERROR
;
790 if (InFptr
!= NULL
) {
795 // Free up our buffers
797 if (Buffer
!= NULL
) {
801 if (CompressedBuffer
!= NULL
) {
802 free (CompressedBuffer
);
805 // Print the file name if errors occurred
807 if (Status
!= STATUS_SUCCESS
) {
808 fprintf (stdout
, "Error processing EFI file %s\n", InFile
->FileName
);
825 GC_TODO: Add function description
829 Fptr - GC_TODO: add argument description
830 MachineType - GC_TODO: add argument description
831 SubSystem - GC_TODO: add argument description
835 GC_TODO: add return values
843 Given a file pointer to a supposed PE32 image file, verify that it is indeed a
844 PE32 image file, and then return the machine type in the supplied pointer.
848 Fptr File pointer to the already-opened PE32 file
849 MachineType Location to stuff the machine type of the PE32 file. This is needed
850 because the image may be Itanium-based, IA32, or EBC.
858 EFI_IMAGE_DOS_HEADER DosHeader
;
859 EFI_IMAGE_FILE_HEADER FileHdr
;
860 EFI_IMAGE_OPTIONAL_HEADER OptionalHdr
;
864 // Position to the start of the file
866 fseek (Fptr
, 0, SEEK_SET
);
869 // Read the DOS header
871 if (fread (&DosHeader
, sizeof (DosHeader
), 1, Fptr
) != 1) {
872 fprintf (stdout
, "ERROR: Failed to read the DOS stub from the input file\n");
876 // Check the magic number (0x5A4D)
878 if (DosHeader
.e_magic
!= EFI_IMAGE_DOS_SIGNATURE
) {
879 fprintf (stdout
, "ERROR: Input file does not appear to be a PE32 image (magic number)\n");
883 // Position into the file and check the PE signature
885 fseek (Fptr
, (long) DosHeader
.e_lfanew
, SEEK_SET
);
886 if (fread (&PESig
, sizeof (PESig
), 1, Fptr
) != 1) {
887 fprintf (stdout
, "ERROR: Failed to read PE signature bytes from input file\n");
891 // Check the PE signature in the header "PE\0\0"
893 if (PESig
!= EFI_IMAGE_NT_SIGNATURE
) {
894 fprintf (stdout
, "ERROR: Input file does not appear to be a PE32 image (signature)\n");
898 // Read the file header and stuff their MachineType
900 if (fread (&FileHdr
, sizeof (FileHdr
), 1, Fptr
) != 1) {
901 fprintf (stdout
, "ERROR: Failed to read PE file header from input file\n");
905 memcpy ((char *) MachineType
, &FileHdr
.Machine
, 2);
908 // Read the optional header so we can get the subsystem
910 if (fread (&OptionalHdr
, sizeof (OptionalHdr
), 1, Fptr
) != 1) {
911 fprintf (stdout
, "ERROR: Failed to read COFF optional header from input file\n");
915 *SubSystem
= OptionalHdr
.Subsystem
;
916 if (mOptions
.Verbose
) {
917 fprintf (stdout
, " Got subsystem = 0x%X from image\n", (int) *SubSystem
);
922 return STATUS_SUCCESS
;
936 Given the Argc/Argv program arguments, and a pointer to an options structure,
937 parse the command-line options and check their validity.
942 Argc - standard C main() argument count
943 Argv[] - standard C main() argument list
944 Options - pointer to a structure to store the options in
948 STATUS_SUCCESS success
956 FILE_LIST
*PrevFileList
;
964 // Clear out the options
966 memset ((char *) Options
, 0, sizeof (OPTIONS
));
969 // To avoid compile warnings
971 FileList
= PrevFileList
= NULL
;
976 // Skip over the program name
982 // If no arguments, assume they want usage info
989 // Process until no more arguments
992 if ((Argv
[0][0] == '-') || (Argv
[0][0] == '/')) {
994 // To simplify string comparisons, replace slashes with dashes
999 // Vendor ID specified with -v
1001 if (stricmp (Argv
[0], "-v") == 0) {
1003 // Make sure there's another parameter
1006 Options
->VendId
= (UINT16
) strtol (Argv
[1], NULL
, 16);
1007 Options
->VendIdValid
= 1;
1011 "ERROR: Missing Vendor ID with %s\n\n",
1015 return STATUS_ERROR
;
1020 } else if (stricmp (Argv
[0], "-d") == 0) {
1022 // Device ID specified with -d
1023 // Make sure there's another parameter
1026 Options
->DevId
= (UINT16
) strtol (Argv
[1], NULL
, 16);
1027 Options
->DevIdValid
= 1;
1031 "ERROR: Missing Device ID with %s\n\n",
1035 return STATUS_ERROR
;
1040 } else if (stricmp (Argv
[0], "-o") == 0) {
1042 // Output filename specified with -o
1043 // Make sure there's another parameter
1046 strcpy (Options
->OutFileName
, Argv
[1]);
1050 "ERROR: Missing output file name with %s\n\n",
1054 return STATUS_ERROR
;
1059 } else if ((stricmp (Argv
[0], "-h") == 0) || (strcmp (Argv
[0], "-?") == 0)) {
1064 return STATUS_ERROR
;
1065 } else if (stricmp (Argv
[0], "-b") == 0) {
1067 // Specify binary files with -b
1069 FileFlags
= (FileFlags
&~FILE_FLAG_EFI
) | FILE_FLAG_BINARY
;
1070 } else if ((stricmp (Argv
[0], "-e") == 0) || (stricmp (Argv
[0], "-ec") == 0)) {
1072 // Specify EFI files with -e. Specify EFI-compressed with -ec.
1074 FileFlags
= (FileFlags
&~FILE_FLAG_BINARY
) | FILE_FLAG_EFI
;
1075 if ((Argv
[0][2] == 'c') || (Argv
[0][2] == 'C')) {
1076 FileFlags
|= FILE_FLAG_COMPRESS
;
1079 // Specify not to set the LAST bit in the last file with -l
1081 } else if (stricmp (Argv
[0], "-l") == 0) {
1082 Options
->NoLast
= 1;
1083 } else if (stricmp (Argv
[0], "-p") == 0) {
1085 // -v for verbose would have been nicer, but it's already used. Let's use
1086 // -p for prolix (wordy) output
1088 Options
->Verbose
= 1;
1089 } else if (stricmp (Argv
[0], "-dump") == 0) {
1091 // -dump for dumping a ROM image. In this case, say that the device id
1092 // and vendor id are valid so we don't have to specify bogus ones on the
1095 Options
->DumpOption
= 1;
1097 Options
->VendIdValid
= 1;
1098 Options
->DevIdValid
= 1;
1099 FileFlags
= FILE_FLAG_BINARY
;
1100 } else if (stricmp (Argv
[0], "-cc") == 0) {
1102 // Class code value for the next file in the list.
1103 // Make sure there's another parameter
1107 // No error checking on the return value. Could check for LONG_MAX,
1108 // LONG_MIN, or 0 class code value if desired. Check range (3 bytes)
1111 ClassCode
= (UINT32
) strtol (Argv
[1], NULL
, 16);
1112 if (ClassCode
& 0xFF000000) {
1113 fprintf (stdout
, "ERROR: Class code %s out of range\n", Argv
[1]);
1114 return STATUS_ERROR
;
1119 "ERROR: Missing class code value with %s\n\n",
1123 return STATUS_ERROR
;
1128 } else if (stricmp (Argv
[0], "-rev") == 0) {
1130 // Code revision in the PCI data structure. The value is for the next
1131 // file in the list.
1132 // Make sure there's another parameter
1136 // No error checking on the return value. Could check for LONG_MAX,
1137 // LONG_MIN, or 0 value if desired. Check range (2 bytes)
1140 CodeRevision
= (UINT32
) strtol (Argv
[1], NULL
, 16);
1141 if (CodeRevision
& 0xFFFF0000) {
1142 fprintf (stdout
, "ERROR: Code revision %s out of range\n", Argv
[1]);
1143 return STATUS_ERROR
;
1148 "ERROR: Missing code revision value with %s\n\n",
1152 return STATUS_ERROR
;
1158 fprintf (stdout
, "ERROR: Invalid option specified: %s\n\n", Argv
[0]);
1160 return STATUS_ERROR
;
1164 // Not a slash-option argument. Must be a file name. Make sure they've specified
1165 // -e or -b already.
1167 if ((FileFlags
& (FILE_FLAG_BINARY
| FILE_FLAG_EFI
)) == 0) {
1168 fprintf (stdout
, "ERROR: Missing -e or -b with input file %s\n", Argv
[0]);
1169 return STATUS_ERROR
;
1172 // Create a new file structure
1174 FileList
= (FILE_LIST
*) malloc (sizeof (FILE_LIST
));
1175 if (FileList
== NULL
) {
1176 fprintf (stdout
, "ERROR: Memory allocation failure\n");
1177 return STATUS_ERROR
;
1180 memset ((char *) FileList
, 0, sizeof (FILE_LIST
));
1181 FileList
->FileName
= Argv
[0];
1182 FileList
->FileFlags
= FileFlags
;
1183 if (Options
->FileList
== NULL
) {
1184 Options
->FileList
= FileList
;
1186 if (PrevFileList
== NULL
) {
1187 PrevFileList
= FileList
;
1189 PrevFileList
->Next
= FileList
;
1193 PrevFileList
= FileList
;
1195 // Set the class code and code revision for this file, then reset the values.
1197 FileList
->ClassCode
= ClassCode
;
1198 FileList
->CodeRevision
= (UINT16
) CodeRevision
;
1209 // Make sure they specified a device ID and vendor ID
1211 if (!Options
->VendIdValid
) {
1212 fprintf (stdout
, "ERROR: Missing Vendor ID on command line\n\n");
1214 return STATUS_ERROR
;
1217 if (!Options
->DevIdValid
) {
1218 fprintf (stdout
, "ERROR: Missing Device ID on command line\n\n");
1220 return STATUS_ERROR
;
1223 // Must have specified some files
1225 if (Options
->FileList
== NULL
) {
1226 fprintf (stdout
, "ERROR: Missing input file name\n");
1228 return STATUS_ERROR
;
1241 Routine Description:
1243 Print usage information for this utility.
1256 static const char *Msg
[] = {
1257 "EfiRom "UTILITY_VERSION
" - Intel EFI Make Option ROM utility",
1258 " Copyright (C), 1999-2002 Intel Coproration\n",
1259 " Create an option ROM image from a list of input files",
1260 " Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ",
1261 " [-e|-b] [FileName(s)]",
1263 " VendorId - required hex PCI Vendor ID for the device",
1264 " DeviceId - required hex PCI Device ID for the device",
1265 " OutFileName - optional output file name. Default is the first input",
1266 " file name with a "DEFAULT_OUTPUT_EXTENSION
" file extension",
1267 " FileNames - input PE32 or binary file name(s)",
1268 " BinFileName - input binary file name(s)",
1269 " -p - for verbose output",
1270 " -l - to not automatically set the LAST bit on the last file",
1271 " -b - following FileNames are binary files",
1272 " -e - following FileNames are EFI PE32 image files",
1273 " -ec - following FileNames are EFI PE32 image files, and should",
1274 " be compressed by this utility",
1275 " -cc ClassCode - to use hex ClassCode in the PCI data structure header for",
1276 " the following FileName",
1277 " -rev Revision - to use hex Revision in the PCI data structure header for",
1278 " the following FileName",
1279 " -dump - to dump the headers of an existing option ROM image",
1281 "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ",
1286 for (Index
= 0; Msg
[Index
] != NULL
; Index
++) {
1287 fprintf (stdout
, "%s\n", Msg
[Index
]);
1298 Routine Description:
1300 GC_TODO: Add function description
1304 InFile - GC_TODO: add argument description
1308 GC_TODO: add return values
1312 PCI_EXPANSION_ROM_HEADER PciRomHdr
;
1316 EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr
;
1317 PCI_DATA_STRUCTURE PciDs
;
1320 // Open the input file
1322 if ((InFptr
= fopen (InFile
->FileName
, "rb")) == NULL
) {
1325 "ERROR: Could not open input file %s\n",
1331 // Go through the image and dump the header stuff for each
1336 // Save our postition in the file, since offsets in the headers
1337 // are relative to the particular image.
1339 ImageStart
= ftell (InFptr
);
1343 // Read the option ROM header. Have to assume a raw binary image for now.
1345 if (fread (&PciRomHdr
, sizeof (PciRomHdr
), 1, InFptr
) != 1) {
1346 fprintf (stdout
, "ERROR: Failed to read PCI ROM header from file\n");
1351 // Dump the contents of the header
1353 fprintf (stdout
, "Image %d -- Offset 0x%X\n", ImageCount
, ImageStart
);
1354 fprintf (stdout
, " ROM header contents\n");
1355 fprintf (stdout
, " Signature 0x%04X\n", (UINT32
) PciRomHdr
.Signature
);
1356 fprintf (stdout
, " PCIR offset 0x%04X\n", (UINT32
) PciRomHdr
.PcirOffset
);
1358 // Find PCI data structure
1360 if (fseek (InFptr
, ImageStart
+ PciRomHdr
.PcirOffset
, SEEK_SET
)) {
1361 fprintf (stdout
, "ERROR: Failed to seek to PCI data structure\n");
1365 // Read and dump the PCI data structure
1367 if (fread (&PciDs
, sizeof (PciDs
), 1, InFptr
) != 1) {
1368 fprintf (stdout
, "ERROR: Failed to read PCI data structure from file\n");
1372 fprintf (stdout
, " PCI Data Structure\n");
1375 " Signature %c%c%c%c\n",
1376 (char) PciDs
.Signature
,
1377 (char) (PciDs
.Signature
>> 8),
1378 (char) (PciDs
.Signature
>> 16),
1379 (char) (PciDs
.Signature
>> 24)
1381 fprintf (stdout
, " Vendor ID 0x%04X\n", PciDs
.VendorId
);
1382 fprintf (stdout
, " Device ID 0x%04X\n", PciDs
.DeviceId
);
1385 " Class Code 0x%06X\n",
1386 (UINT32
) (PciDs
.ClassCode
[0] | (PciDs
.ClassCode
[1] << 8) | (PciDs
.ClassCode
[2] << 16))
1388 fprintf (stdout
, " Image size 0x%X\n", PciDs
.ImageLength
* 512);
1389 fprintf (stdout
, " Code revision: 0x%04X\n", PciDs
.CodeRevision
);
1390 fprintf (stdout
, " Indicator 0x%02X", (UINT32
) PciDs
.Indicator
);
1392 // Print the indicator, used to flag the last image
1394 if (PciDs
.Indicator
== INDICATOR_LAST
) {
1395 fprintf (stdout
, " (last image)\n");
1397 fprintf (stdout
, "\n");
1400 // Print the code type. If EFI code, then we can provide more info.
1402 fprintf (stdout
, " Code type 0x%02X", (UINT32
) PciDs
.CodeType
);
1403 if (PciDs
.CodeType
== PCI_CODE_TYPE_EFI_IMAGE
) {
1404 fprintf (stdout
, " (EFI image)\n");
1406 // Re-read the header as an EFI ROM header, then dump more info
1408 fprintf (stdout
, " EFI ROM header contents\n");
1409 if (fseek (InFptr
, ImageStart
, SEEK_SET
)) {
1410 fprintf (stdout
, "ERROR: Failed to re-seek to ROM header structure\n");
1414 if (fread (&EfiRomHdr
, sizeof (EfiRomHdr
), 1, InFptr
) != 1) {
1415 fprintf (stdout
, "ERROR: Failed to read EFI PCI ROM header from file\n");
1419 // Now dump more info
1421 fprintf (stdout
, " EFI Signature 0x%04X\n", EfiRomHdr
.EfiSignature
);
1424 " Compression Type 0x%04X ",
1425 (UINT32
) EfiRomHdr
.CompressionType
1427 if (EfiRomHdr
.CompressionType
== EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED
) {
1428 fprintf (stdout
, "(compressed)\n");
1430 fprintf (stdout
, "(not compressed)\n");
1435 " Machine type 0x%04X (%s)\n",
1436 EfiRomHdr
.EfiMachineType
,
1437 GetMachineTypeStr (EfiRomHdr
.EfiMachineType
)
1441 " Subsystem 0x%04X (%s)\n",
1442 EfiRomHdr
.EfiSubsystem
,
1443 GetSubsystemTypeStr (EfiRomHdr
.EfiSubsystem
)
1447 " EFI image offset 0x%04X (@0x%X)\n",
1448 (UINT32
) EfiRomHdr
.EfiImageHeaderOffset
,
1449 (UINT32
) (EfiRomHdr
.EfiImageHeaderOffset
+ ImageStart
)
1456 fprintf (stdout
, "\n");
1459 // If code type is EFI image, then dump it as well?
1461 // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
1464 // If last image, then we're done
1466 if (PciDs
.Indicator
== INDICATOR_LAST
) {
1470 // Seek to the start of the next image
1472 if (fseek (InFptr
, ImageStart
+ (PciDs
.ImageLength
* 512), SEEK_SET
)) {
1473 fprintf (stdout
, "ERROR: Failed to seek to next image\n");
1488 Routine Description:
1490 GC_TODO: Add function description
1494 MachineType - GC_TODO: add argument description
1498 GC_TODO: add return values
1504 for (Index
= 0; mMachineTypes
[Index
].Name
!= NULL
; Index
++) {
1505 if (mMachineTypes
[Index
].Value
== MachineType
) {
1506 return mMachineTypes
[Index
].Name
;
1515 GetSubsystemTypeStr (
1516 UINT16 SubsystemType
1520 Routine Description:
1522 GC_TODO: Add function description
1526 SubsystemType - GC_TODO: add argument description
1530 GC_TODO: add return values
1536 for (Index
= 0; mSubsystemTypes
[Index
].Name
!= NULL
; Index
++) {
1537 if (mSubsystemTypes
[Index
].Value
== SubsystemType
) {
1538 return mSubsystemTypes
[Index
].Name
;