X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=Tools%2FSource%2FTianoTools%2FEfiRom%2FEfiRom.c;fp=Tools%2FSource%2FTianoTools%2FEfiRom%2FEfiRom.c;h=0000000000000000000000000000000000000000;hp=2cc478b119225441208c591f10a64089e3518565;hb=feccee87a78e68d575dbdf44b34ca0cb5a21ea8d;hpb=214b0d1914b48d651b25e58f321ddb77a46903b8 diff --git a/Tools/Source/TianoTools/EfiRom/EfiRom.c b/Tools/Source/TianoTools/EfiRom/EfiRom.c deleted file mode 100644 index 2cc478b119..0000000000 --- a/Tools/Source/TianoTools/EfiRom/EfiRom.c +++ /dev/null @@ -1,1536 +0,0 @@ -/*++ - -Copyright (c) 1999-2006 Intel Corporation. All rights reserved -This program and the accompanying materials are licensed and made available -under the terms and conditions of the BSD License which accompanies this -distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - - EfiRom.c - -Abstract: - - Utility program to create an EFI option ROM image from binary and - EFI PE32 files. - - ---*/ - -#include -#include -#include - -#include -#include // for PE32 structure definitions -#include - -#include // for option ROM header structures - -#include "EfiCompress.h" -#include "CommonLib.h" - -// -// Version of this utility -// -#define UTILITY_VERSION "v2.5" - -// -// Define some status return values -// -#define STATUS_SUCCESS 0 -#define STATUS_WARNING 1 -#define STATUS_ERROR 2 - -// -// Define the max length of a filename -// -#define MAX_PATH 200 - -#define DEFAULT_OUTPUT_EXTENSION ".rom" - -// -// Max size for an option ROM image -// -#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB -// -// Values for the indicator field in the PCI data structure -// -#define INDICATOR_LAST 0x80 // last file in series of files -// -// Masks for the FILE_LIST.FileFlags field -// -#define FILE_FLAG_BINARY 0x01 -#define FILE_FLAG_EFI 0x02 -#define FILE_FLAG_COMPRESS 0x04 - -// -// Use this linked list structure to keep track of all the filenames -// specified on the command line. -// -typedef struct _FILE_LIST { - struct _FILE_LIST *Next; - INT8 *FileName; - UINT32 FileFlags; - UINT32 ClassCode; - UINT16 CodeRevision; -} FILE_LIST; - -// -// Use this to track our command-line options -// -typedef struct { - INT8 OutFileName[MAX_PATH]; - INT8 NoLast; - INT8 Verbose; - INT8 DumpOption; - UINT8 DevIdValid; - UINT8 VendIdValid; - UINT16 VendId; - UINT16 DevId; - FILE_LIST *FileList; -} OPTIONS; - -// -// Make a global structure to keep track of command-line options -// -static OPTIONS mOptions; - -// -// Use these to convert from machine type value to a named type -// -typedef struct { - UINT16 Value; - char *Name; -} STRING_LOOKUP; - -static STRING_LOOKUP mMachineTypes[] = { - EFI_IMAGE_MACHINE_IA32, - "IA32", - EFI_IMAGE_MACHINE_IA64, - "IA64", - EFI_IMAGE_MACHINE_EBC, - "EBC", - 0, - NULL -}; - -static STRING_LOOKUP mSubsystemTypes[] = { - EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION, - "EFI application", - EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, - "EFI boot service driver", - EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, - "EFI runtime driver", - 0, - NULL -}; -// -// Function prototypes -// -static -void -Usage ( - VOID - ); - -static -int -ParseCommandLine ( - int Argc, - char *Argv[], - OPTIONS *Options - ); - -static -int -CheckPE32File ( - FILE *Fptr, - UINT16 *MachineType, - UINT16 *SubSystem - ); - -static -int -ProcessEfiFile ( - FILE *OutFptr, - FILE_LIST *InFile, - UINT16 VendId, - UINT16 DevId, - UINT32 *Size - ); - -static -int -ProcessBinFile ( - FILE *OutFptr, - FILE_LIST *InFile, - UINT32 *Size - ); - -static -void -DumpImage ( - FILE_LIST *InFile - ); - -char * -GetMachineTypeStr ( - UINT16 MachineType - ); - -static -char * -GetSubsystemTypeStr ( - UINT16 SubsystemType - ); - -main ( - int Argc, - char *Argv[] - ) -/*++ - -Routine Description: - - Given an EFI image filename, create a ROM-able image by creating an option - ROM header and PCI data structure, filling them in, and then writing the - option ROM header + PCI data structure + EFI image out to the output file. - -Arguments: - - Argc - standard C main() argument count - - Argv - standard C main() argument list - -Returns: - - 0 success - non-zero otherwise - ---*/ -// GC_TODO: ] - add argument and description to function comment -{ - INT8 *Ext; - FILE *FptrOut; - UINT32 Status; - FILE_LIST *FList; - UINT32 TotalSize; - UINT32 Size; - - Status = STATUS_SUCCESS; - FptrOut = NULL; - - // - // Parse the command line arguments - // - if (ParseCommandLine (Argc, Argv, &mOptions)) { - return STATUS_ERROR; - } - // - // If dumping an image, then do that and quit - // - if (mOptions.DumpOption) { - DumpImage (mOptions.FileList); - goto BailOut; - } - // - // Determine the output filename. Either what they specified on - // the command line, or the first input filename with a different extension. - // - if (!mOptions.OutFileName[0]) { - strcpy (mOptions.OutFileName, mOptions.FileList->FileName); - // - // Find the last . on the line and replace the filename extension with - // the default - // - for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1; - (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\'); - Ext-- - ) - ; - // - // If dot here, then insert extension here, otherwise append - // - if (*Ext != '.') { - Ext = mOptions.OutFileName + strlen (mOptions.OutFileName); - } - - strcpy (Ext, DEFAULT_OUTPUT_EXTENSION); - } - // - // Make sure we don't have the same filename for input and output files - // - for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) { - if (stricmp (mOptions.OutFileName, FList->FileName) == 0) { - Status = STATUS_ERROR; - fprintf ( - stdout, - "ERROR: Input and output file names must be different - %s = %s\n", - FList->FileName, - mOptions.OutFileName - ); - goto BailOut; - } - } - // - // Now open our output file - // - if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) { - fprintf (stdout, "ERROR: Failed to open output file %s\n", mOptions.OutFileName); - goto BailOut; - } - // - // Process all our files - // - TotalSize = 0; - for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) { - Size = 0; - if (FList->FileFlags & FILE_FLAG_EFI) { - if (mOptions.Verbose) { - fprintf (stdout, "Processing EFI file %s\n", FList->FileName); - } - - Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size); - } else if (FList->FileFlags & FILE_FLAG_BINARY) { - if (mOptions.Verbose) { - fprintf (stdout, "Processing binary file %s\n", FList->FileName); - } - - Status = ProcessBinFile (FptrOut, FList, &Size); - } else { - fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName); - Status = STATUS_ERROR; - } - - if (mOptions.Verbose) { - fprintf (stdout, " Output size = 0x%X\n", Size); - } - - if (Status != STATUS_SUCCESS) { - break; - } - - TotalSize += Size; - } - // - // Check total size - // - if (TotalSize > MAX_OPTION_ROM_SIZE) { - fprintf ( - stdout, - "ERROR: Option ROM image size exceeds limit 0x%X bytes\n", - MAX_OPTION_ROM_SIZE - ); - Status = STATUS_ERROR; - } - -BailOut: - if (FptrOut != NULL) { - fclose (FptrOut); - } - // - // Clean up our file list - // - while (mOptions.FileList != NULL) { - FList = mOptions.FileList->Next; - free (mOptions.FileList); - mOptions.FileList = FList; - } - - return Status; -} - -static -int -ProcessBinFile ( - FILE *OutFptr, - FILE_LIST *InFile, - UINT32 *Size - ) -/*++ - -Routine Description: - - Process a binary input file. - -Arguments: - - OutFptr - file pointer to output binary ROM image file we're creating - InFile - structure contains information on the binary file to process - Size - pointer to where to return the size added to the output file - -Returns: - - 0 - successful - ---*/ -{ - FILE *InFptr; - UINT32 TotalSize; - UINT32 FileSize; - UINT8 *Buffer; - UINT32 Status; - PCI_EXPANSION_ROM_HEADER *RomHdr; - PCI_DATA_STRUCTURE *PciDs; - UINT32 Index; - UINT8 ByteCheckSum; - - Status = STATUS_SUCCESS; - - // - // Try to open the input file - // - if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { - fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName); - return STATUS_ERROR; - } - // - // Seek to the end of the input file and get the file size. Then allocate - // a buffer to read it in to. - // - fseek (InFptr, 0, SEEK_END); - FileSize = ftell (InFptr); - if (mOptions.Verbose) { - fprintf (stdout, " File size = 0x%X\n", FileSize); - } - - fseek (InFptr, 0, SEEK_SET); - Buffer = (INT8 *) malloc (FileSize); - if (Buffer == NULL) { - fprintf (stdout, "ERROR: Memory allocation failed\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - if (fread (Buffer, FileSize, 1, InFptr) != 1) { - fprintf (stdout, "ERROR: Failed to read all bytes from input file\n"); - Status = STATUS_ERROR; - goto BailOut; - } - // - // Total size must be an even multiple of 512 bytes, and can't exceed - // the option ROM image size. - // - TotalSize = FileSize; - if (TotalSize & 0x1FF) { - TotalSize = (TotalSize + 0x200) &~0x1ff; - } - - if (TotalSize > MAX_OPTION_ROM_SIZE) { - fprintf ( - stdout, - "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n", - InFile->FileName, - MAX_OPTION_ROM_SIZE - ); - Status = STATUS_ERROR; - goto BailOut; - } - // - // Return the size to the caller so they can keep track of the running total. - // - *Size = TotalSize; - - // - // Crude check to make sure it's a legitimate ROM image - // - RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer; - if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { - fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n"); - Status = STATUS_ERROR; - goto BailOut; - } - // - // Make sure the pointer to the PCI data structure is within the size of the image. - // Then check it for valid signature. - // - if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) { - fprintf (stdout, "ERROR: Invalid PCI data structure offset\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset); - if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { - fprintf (stdout, "ERROR: PCI data structure has invalid signature\n"); - Status = STATUS_ERROR; - goto BailOut; - } - // - // If this is the last image, then set the LAST bit unless requested not - // to via the command-line -l argument. Otherwise, make sure you clear it. - // - if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { - PciDs->Indicator = INDICATOR_LAST; - } else { - PciDs->Indicator = 0; - } - - ByteCheckSum = 0; - for (Index = 0; Index < FileSize - 1; Index++) { - ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]); - } - - Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1); - fprintf (stdout, "CheckSUm = %02x\n", (UINT32) Buffer[FileSize - 1]); - - // - // Now copy the input file contents out to the output file - // - if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { - fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - TotalSize -= FileSize; - // - // Pad the rest of the image to make it a multiple of 512 bytes - // - while (TotalSize > 0) { - putc (~0, OutFptr); - TotalSize--; - } - -BailOut: - if (InFptr != NULL) { - fclose (InFptr); - } - - if (Buffer != NULL) { - free (Buffer); - } - // - // Print the file name if errors occurred - // - if (Status != STATUS_SUCCESS) { - fprintf (stdout, "Error processing binary file %s\n", InFile->FileName); - } - - return Status; -} - -static -int -ProcessEfiFile ( - FILE *OutFptr, - FILE_LIST *InFile, - UINT16 VendId, - UINT16 DevId, - UINT32 *Size - ) -/*++ - -Routine Description: - - Process a PE32 EFI file. - -Arguments: - - OutFptr - file pointer to output binary ROM image file we're creating - InFile - structure contains information on the PE32 file to process - VendId - vendor ID as required in the option ROM header - DevId - device ID as required in the option ROM header - Size - pointer to where to return the size added to the output file - -Returns: - - 0 - successful - ---*/ -{ - UINT32 Status; - FILE *InFptr; - EFI_PCI_EXPANSION_ROM_HEADER RomHdr; - PCI_DATA_STRUCTURE PciDs; - UINT32 FileSize; - UINT32 CompressedFileSize; - UINT8 *Buffer; - UINT8 *CompressedBuffer; - UINT8 *TempBufferPtr; - UINT32 TotalSize; - UINT32 HeaderSize; - UINT16 MachineType; - UINT16 SubSystem; - UINT32 HeaderPadBytes; - - // - // Try to open the input file - // - if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { - fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName); - return STATUS_ERROR; - } - // - // Initialize our buffer pointers to null. - // - Buffer = NULL; - CompressedBuffer = NULL; - - // - // Double-check the file to make sure it's what we expect it to be - // - Status = CheckPE32File (InFptr, &MachineType, &SubSystem); - if (Status != STATUS_SUCCESS) { - goto BailOut; - } - // - // Seek to the end of the input file and get the file size - // - fseek (InFptr, 0, SEEK_END); - FileSize = ftell (InFptr); - - // - // Get the size of the headers we're going to put in front of the image. The - // EFI header must be aligned on a 4-byte boundary, so pad accordingly. - // - if (sizeof (RomHdr) & 0x03) { - HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03); - } else { - HeaderPadBytes = 0; - } - - HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); - if (mOptions.Verbose) { - fprintf (stdout, " File size = 0x%X\n", FileSize); - } - // - // Allocate memory for the entire file (in case we have to compress), then - // seek back to the beginning of the file and read it into our buffer. - // - Buffer = (INT8 *) malloc (FileSize); - if (Buffer == NULL) { - fprintf (stdout, "ERROR: Memory allocation failed\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - fseek (InFptr, 0, SEEK_SET); - if (fread (Buffer, FileSize, 1, InFptr) != 1) { - fprintf (stdout, "ERROR: Failed to read all bytes from input file\n"); - Status = STATUS_ERROR; - goto BailOut; - } - // - // Now determine the size of the final output file. It's either the header size - // plus the file's size, or the header size plus the compressed file size. - // - if (InFile->FileFlags & FILE_FLAG_COMPRESS) { - // - // Allocate a buffer into which we can compress the image, compress it, - // and use that size as the new size. - // - CompressedBuffer = (INT8 *) malloc (FileSize); - if (CompressedBuffer == NULL) { - fprintf (stdout, "ERROR: Memory allocation failed\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - CompressedFileSize = FileSize; - Status = Compress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize); - if (Status != STATUS_SUCCESS) { - fprintf (stdout, "ERROR: Compression failed\n"); - goto BailOut; - } - // - // Now compute the size, then swap buffer pointers. - // - if (mOptions.Verbose) { - fprintf (stdout, " Comp size = 0x%X\n", CompressedFileSize); - } - - TotalSize = CompressedFileSize + HeaderSize; - FileSize = CompressedFileSize; - TempBufferPtr = Buffer; - Buffer = CompressedBuffer; - CompressedBuffer = TempBufferPtr; - } else { - TotalSize = FileSize + HeaderSize; - } - // - // Total size must be an even multiple of 512 bytes - // - if (TotalSize & 0x1FF) { - TotalSize = (TotalSize + 0x200) &~0x1ff; - } - // - // Check size - // - if (TotalSize > MAX_OPTION_ROM_SIZE) { - fprintf ( - stdout, - "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n", - InFile->FileName, - MAX_OPTION_ROM_SIZE - ); - Status = STATUS_ERROR; - goto BailOut; - } - // - // Return the size to the caller so they can keep track of the running total. - // - *Size = TotalSize; - - // - // Now fill in the ROM header. These values come from chapter 18 of the - // EFI 1.02 specification. - // - memset (&RomHdr, 0, sizeof (RomHdr)); - RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE; - RomHdr.InitializationSize = (UINT16) (TotalSize / 512); - RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE; - RomHdr.EfiSubsystem = SubSystem; - RomHdr.EfiMachineType = MachineType; - RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize; - RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes); - // - // Set image as compressed or not - // - if (InFile->FileFlags & FILE_FLAG_COMPRESS) { - RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED; - } - // - // Fill in the PCI data structure - // - memset (&PciDs, 0, sizeof (PCI_DATA_STRUCTURE)); - - PciDs.Signature = PCI_DATA_STRUCTURE_SIGNATURE; - PciDs.VendorId = VendId; - PciDs.DeviceId = DevId; - PciDs.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE); - PciDs.Revision = 0; - // - // Class code and code revision from the command line (optional) - // - PciDs.ClassCode[0] = (UINT8) InFile->ClassCode; - PciDs.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); - PciDs.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); - PciDs.ImageLength = RomHdr.InitializationSize; - PciDs.CodeRevision = InFile->CodeRevision; - PciDs.CodeType = PCI_CODE_TYPE_EFI_IMAGE; - - // - // If this is the last image, then set the LAST bit unless requested not - // to via the command-line -l argument. - // - if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { - PciDs.Indicator = INDICATOR_LAST; - } - // - // Write the ROM header to the output file - // - if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) { - fprintf (stdout, "ERROR: Failed to write ROM header to output file\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - // - // Write pad bytes to align the PciDs - // - while (HeaderPadBytes > 0) { - if (putc (0, OutFptr) == EOF) { - fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - HeaderPadBytes--; - } - // - // Write the PCI data structure header to the output file - // - if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) { - fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n"); - Status = STATUS_ERROR; - goto BailOut; - } - // - // Keep track of how many bytes left to write - // - TotalSize -= HeaderSize; - - // - // Now dump the input file's contents to the output file - // - if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { - fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - TotalSize -= FileSize; - // - // Pad the rest of the image to make it a multiple of 512 bytes - // - while (TotalSize > 0) { - if (putc (~0, OutFptr) == EOF) { - fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n"); - Status = STATUS_ERROR; - goto BailOut; - } - - TotalSize--; - } - -BailOut: - if (InFptr != NULL) { - fclose (InFptr); - } - - // - // Free up our buffers - // - if (Buffer != NULL) { - free (Buffer); - } - - if (CompressedBuffer != NULL) { - free (CompressedBuffer); - } - // - // Print the file name if errors occurred - // - if (Status != STATUS_SUCCESS) { - fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName); - } - - return Status; -} - -static -int -CheckPE32File ( - FILE *Fptr, - UINT16 *MachineType, - UINT16 *SubSystem - ) -/*++ - -Routine Description: - - GC_TODO: Add function description - -Arguments: - - Fptr - GC_TODO: add argument description - MachineType - GC_TODO: add argument description - SubSystem - GC_TODO: add argument description - -Returns: - - GC_TODO: add return values - ---*/ -{ - /*++ - -Routine Description: - - Given a file pointer to a supposed PE32 image file, verify that it is indeed a - PE32 image file, and then return the machine type in the supplied pointer. - -Arguments: - - Fptr File pointer to the already-opened PE32 file - MachineType Location to stuff the machine type of the PE32 file. This is needed - because the image may be Itanium-based, IA32, or EBC. - -Returns: - - 0 success - non-zero otherwise - ---*/ - EFI_IMAGE_DOS_HEADER DosHeader; - EFI_IMAGE_FILE_HEADER FileHdr; - EFI_IMAGE_OPTIONAL_HEADER OptionalHdr; - UINT32 PESig; - - // - // Position to the start of the file - // - fseek (Fptr, 0, SEEK_SET); - - // - // Read the DOS header - // - if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) { - fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n"); - return STATUS_ERROR; - } - // - // Check the magic number (0x5A4D) - // - if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) { - fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n"); - return STATUS_ERROR; - } - // - // Position into the file and check the PE signature - // - fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET); - if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) { - fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n"); - return STATUS_ERROR; - } - // - // Check the PE signature in the header "PE\0\0" - // - if (PESig != EFI_IMAGE_NT_SIGNATURE) { - fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n"); - return STATUS_ERROR; - } - // - // Read the file header and stuff their MachineType - // - if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) { - fprintf (stdout, "ERROR: Failed to read PE file header from input file\n"); - return STATUS_ERROR; - } - - memcpy ((char *) MachineType, &FileHdr.Machine, 2); - - // - // Read the optional header so we can get the subsystem - // - if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) { - fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n"); - return STATUS_ERROR; - } - - *SubSystem = OptionalHdr.Subsystem; - if (mOptions.Verbose) { - fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem); - } - // - // Good to go - // - return STATUS_SUCCESS; -} - -static -int -ParseCommandLine ( - int Argc, - char *Argv[], - OPTIONS *Options - ) -/*++ - -Routine Description: - - Given the Argc/Argv program arguments, and a pointer to an options structure, - parse the command-line options and check their validity. - - -Arguments: - - Argc - standard C main() argument count - Argv[] - standard C main() argument list - Options - pointer to a structure to store the options in - -Returns: - - STATUS_SUCCESS success - non-zero otherwise - ---*/ -// -{ - FILE_LIST *FileList; - - FILE_LIST *PrevFileList; - UINT32 FileFlags; - UINT32 ClassCode; - UINT32 CodeRevision; - - FileFlags = 0; - - // - // Clear out the options - // - memset ((char *) Options, 0, sizeof (OPTIONS)); - - // - // To avoid compile warnings - // - FileList = PrevFileList = NULL; - - ClassCode = 0; - CodeRevision = 0; - // - // Skip over the program name - // - Argc--; - Argv++; - - // - // If no arguments, assume they want usage info - // - if (Argc == 0) { - Usage (); - return STATUS_ERROR; - } - // - // Process until no more arguments - // - while (Argc > 0) { - if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) { - // - // To simplify string comparisons, replace slashes with dashes - // - Argv[0][0] = '-'; - - // - // Vendor ID specified with -v - // - if (stricmp (Argv[0], "-v") == 0) { - // - // Make sure there's another parameter - // - if (Argc > 1) { - Options->VendId = (UINT16) strtol (Argv[1], NULL, 16); - Options->VendIdValid = 1; - } else { - fprintf ( - stdout, - "ERROR: Missing Vendor ID with %s\n\n", - Argv[0] - ); - Usage (); - return STATUS_ERROR; - } - - Argv++; - Argc--; - } else if (stricmp (Argv[0], "-d") == 0) { - // - // Device ID specified with -d - // Make sure there's another parameter - // - if (Argc > 1) { - Options->DevId = (UINT16) strtol (Argv[1], NULL, 16); - Options->DevIdValid = 1; - } else { - fprintf ( - stdout, - "ERROR: Missing Device ID with %s\n\n", - Argv[0] - ); - Usage (); - return STATUS_ERROR; - } - - Argv++; - Argc--; - } else if (stricmp (Argv[0], "-o") == 0) { - // - // Output filename specified with -o - // Make sure there's another parameter - // - if (Argc > 1) { - strcpy (Options->OutFileName, Argv[1]); - } else { - fprintf ( - stdout, - "ERROR: Missing output file name with %s\n\n", - Argv[0] - ); - Usage (); - return STATUS_ERROR; - } - - Argv++; - Argc--; - } else if ((stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) { - // - // Help option - // - Usage (); - return STATUS_ERROR; - } else if (stricmp (Argv[0], "-b") == 0) { - // - // Specify binary files with -b - // - FileFlags = (FileFlags &~FILE_FLAG_EFI) | FILE_FLAG_BINARY; - } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) { - // - // Specify EFI files with -e. Specify EFI-compressed with -ec. - // - FileFlags = (FileFlags &~FILE_FLAG_BINARY) | FILE_FLAG_EFI; - if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) { - FileFlags |= FILE_FLAG_COMPRESS; - } - // - // Specify not to set the LAST bit in the last file with -l - // - } else if (stricmp (Argv[0], "-l") == 0) { - Options->NoLast = 1; - } else if (stricmp (Argv[0], "-p") == 0) { - // - // -v for verbose would have been nicer, but it's already used. Let's use - // -p for prolix (wordy) output - // - Options->Verbose = 1; - } else if (stricmp (Argv[0], "-dump") == 0) { - // - // -dump for dumping a ROM image. In this case, say that the device id - // and vendor id are valid so we don't have to specify bogus ones on the - // command line. - // - Options->DumpOption = 1; - - Options->VendIdValid = 1; - Options->DevIdValid = 1; - FileFlags = FILE_FLAG_BINARY; - } else if (stricmp (Argv[0], "-cc") == 0) { - // - // Class code value for the next file in the list. - // Make sure there's another parameter - // - if (Argc > 1) { - // - // No error checking on the return value. Could check for LONG_MAX, - // LONG_MIN, or 0 class code value if desired. Check range (3 bytes) - // at least. - // - ClassCode = (UINT32) strtol (Argv[1], NULL, 16); - if (ClassCode & 0xFF000000) { - fprintf (stdout, "ERROR: Class code %s out of range\n", Argv[1]); - return STATUS_ERROR; - } - } else { - fprintf ( - stdout, - "ERROR: Missing class code value with %s\n\n", - Argv[0] - ); - Usage (); - return STATUS_ERROR; - } - - Argv++; - Argc--; - } else if (stricmp (Argv[0], "-rev") == 0) { - // - // Code revision in the PCI data structure. The value is for the next - // file in the list. - // Make sure there's another parameter - // - if (Argc > 1) { - // - // No error checking on the return value. Could check for LONG_MAX, - // LONG_MIN, or 0 value if desired. Check range (2 bytes) - // at least. - // - CodeRevision = (UINT32) strtol (Argv[1], NULL, 16); - if (CodeRevision & 0xFFFF0000) { - fprintf (stdout, "ERROR: Code revision %s out of range\n", Argv[1]); - return STATUS_ERROR; - } - } else { - fprintf ( - stdout, - "ERROR: Missing code revision value with %s\n\n", - Argv[0] - ); - Usage (); - return STATUS_ERROR; - } - - Argv++; - Argc--; - } else { - fprintf (stdout, "ERROR: Invalid option specified: %s\n\n", Argv[0]); - Usage (); - return STATUS_ERROR; - } - } else { - // - // Not a slash-option argument. Must be a file name. Make sure they've specified - // -e or -b already. - // - if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) { - fprintf (stdout, "ERROR: Missing -e or -b with input file %s\n", Argv[0]); - return STATUS_ERROR; - } - // - // Create a new file structure - // - FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST)); - if (FileList == NULL) { - fprintf (stdout, "ERROR: Memory allocation failure\n"); - return STATUS_ERROR; - } - - memset ((char *) FileList, 0, sizeof (FILE_LIST)); - FileList->FileName = Argv[0]; - FileList->FileFlags = FileFlags; - if (Options->FileList == NULL) { - Options->FileList = FileList; - } else { - if (PrevFileList == NULL) { - PrevFileList = FileList; - } else { - PrevFileList->Next = FileList; - } - } - - PrevFileList = FileList; - // - // Set the class code and code revision for this file, then reset the values. - // - FileList->ClassCode = ClassCode; - FileList->CodeRevision = (UINT16) CodeRevision; - ClassCode = 0; - CodeRevision = 0; - } - // - // Next argument - // - Argv++; - Argc--; - } - // - // Make sure they specified a device ID and vendor ID - // - if (!Options->VendIdValid) { - fprintf (stdout, "ERROR: Missing Vendor ID on command line\n\n"); - Usage (); - return STATUS_ERROR; - } - - if (!Options->DevIdValid) { - fprintf (stdout, "ERROR: Missing Device ID on command line\n\n"); - Usage (); - return STATUS_ERROR; - } - // - // Must have specified some files - // - if (Options->FileList == NULL) { - fprintf (stdout, "ERROR: Missing input file name\n"); - Usage (); - return STATUS_ERROR; - } - - return 0; -} - -static -void -Usage ( - VOID - ) -/*++ - -Routine Description: - - Print usage information for this utility. - -Arguments: - - None. - -Returns: - - Nothing. - ---*/ -{ - int Index; - static const char *Msg[] = { - "EfiRom "UTILITY_VERSION " - Intel EFI Make Option ROM utility", - " Copyright (C), 1999-2002 Intel Coproration\n", - " Create an option ROM image from a list of input files", - " Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ", - " [-e|-b] [FileName(s)]", - " where:", - " VendorId - required hex PCI Vendor ID for the device", - " DeviceId - required hex PCI Device ID for the device", - " OutFileName - optional output file name. Default is the first input", - " file name with a "DEFAULT_OUTPUT_EXTENSION " file extension", - " FileNames - input PE32 or binary file name(s)", - " BinFileName - input binary file name(s)", - " -p - for verbose output", - " -l - to not automatically set the LAST bit on the last file", - " -b - following FileNames are binary files", - " -e - following FileNames are EFI PE32 image files", - " -ec - following FileNames are EFI PE32 image files, and should", - " be compressed by this utility", - " -cc ClassCode - to use hex ClassCode in the PCI data structure header for", - " the following FileName", - " -rev Revision - to use hex Revision in the PCI data structure header for", - " the following FileName", - " -dump - to dump the headers of an existing option ROM image", - "", - "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ", - "", - NULL - }; - - for (Index = 0; Msg[Index] != NULL; Index++) { - fprintf (stdout, "%s\n", Msg[Index]); - } -} - -static -void -DumpImage ( - FILE_LIST *InFile - ) -/*++ - -Routine Description: - - GC_TODO: Add function description - -Arguments: - - InFile - GC_TODO: add argument description - -Returns: - - GC_TODO: add return values - ---*/ -{ - PCI_EXPANSION_ROM_HEADER PciRomHdr; - FILE *InFptr; - UINT32 ImageStart; - UINT32 ImageCount; - EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr; - PCI_DATA_STRUCTURE PciDs; - - // - // Open the input file - // - if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { - fprintf ( - stdout, - "ERROR: Could not open input file %s\n", - InFile->FileName - ); - return ; - } - // - // Go through the image and dump the header stuff for each - // - ImageCount = 0; - for (;;) { - // - // Save our postition in the file, since offsets in the headers - // are relative to the particular image. - // - ImageStart = ftell (InFptr); - ImageCount++; - - // - // Read the option ROM header. Have to assume a raw binary image for now. - // - if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) { - fprintf (stdout, "ERROR: Failed to read PCI ROM header from file\n"); - goto BailOut; - } - - // - // Dump the contents of the header - // - fprintf (stdout, "Image %d -- Offset 0x%X\n", ImageCount, ImageStart); - fprintf (stdout, " ROM header contents\n"); - fprintf (stdout, " Signature 0x%04X\n", (UINT32) PciRomHdr.Signature); - fprintf (stdout, " PCIR offset 0x%04X\n", (UINT32) PciRomHdr.PcirOffset); - // - // Find PCI data structure - // - if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) { - fprintf (stdout, "ERROR: Failed to seek to PCI data structure\n"); - goto BailOut; - } - // - // Read and dump the PCI data structure - // - if (fread (&PciDs, sizeof (PciDs), 1, InFptr) != 1) { - fprintf (stdout, "ERROR: Failed to read PCI data structure from file\n"); - goto BailOut; - } - - fprintf (stdout, " PCI Data Structure\n"); - fprintf ( - stdout, - " Signature %c%c%c%c\n", - (char) PciDs.Signature, - (char) (PciDs.Signature >> 8), - (char) (PciDs.Signature >> 16), - (char) (PciDs.Signature >> 24) - ); - fprintf (stdout, " Vendor ID 0x%04X\n", PciDs.VendorId); - fprintf (stdout, " Device ID 0x%04X\n", PciDs.DeviceId); - fprintf ( - stdout, - " Class Code 0x%06X\n", - (UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16)) - ); - fprintf (stdout, " Image size 0x%X\n", PciDs.ImageLength * 512); - fprintf (stdout, " Code revision: 0x%04X\n", PciDs.CodeRevision); - fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs.Indicator); - // - // Print the indicator, used to flag the last image - // - if (PciDs.Indicator == INDICATOR_LAST) { - fprintf (stdout, " (last image)\n"); - } else { - fprintf (stdout, "\n"); - } - // - // Print the code type. If EFI code, then we can provide more info. - // - fprintf (stdout, " Code type 0x%02X", (UINT32) PciDs.CodeType); - if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) { - fprintf (stdout, " (EFI image)\n"); - // - // Re-read the header as an EFI ROM header, then dump more info - // - fprintf (stdout, " EFI ROM header contents\n"); - if (fseek (InFptr, ImageStart, SEEK_SET)) { - fprintf (stdout, "ERROR: Failed to re-seek to ROM header structure\n"); - goto BailOut; - } - - if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) { - fprintf (stdout, "ERROR: Failed to read EFI PCI ROM header from file\n"); - goto BailOut; - } - // - // Now dump more info - // - fprintf (stdout, " EFI Signature 0x%04X\n", EfiRomHdr.EfiSignature); - fprintf ( - stdout, - " Compression Type 0x%04X ", - (UINT32) EfiRomHdr.CompressionType - ); - if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { - fprintf (stdout, "(compressed)\n"); - } else { - fprintf (stdout, "(not compressed)\n"); - } - - fprintf ( - stdout, - " Machine type 0x%04X (%s)\n", - EfiRomHdr.EfiMachineType, - GetMachineTypeStr (EfiRomHdr.EfiMachineType) - ); - fprintf ( - stdout, - " Subsystem 0x%04X (%s)\n", - EfiRomHdr.EfiSubsystem, - GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem) - ); - fprintf ( - stdout, - " EFI image offset 0x%04X (@0x%X)\n", - (UINT32) EfiRomHdr.EfiImageHeaderOffset, - (UINT32) (EfiRomHdr.EfiImageHeaderOffset + ImageStart) - ); - - } else { - // - // Not an EFI image - // - fprintf (stdout, "\n"); - } - // - // If code type is EFI image, then dump it as well? - // - // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) { - // } - // - // If last image, then we're done - // - if (PciDs.Indicator == INDICATOR_LAST) { - goto BailOut; - } - // - // Seek to the start of the next image - // - if (fseek (InFptr, ImageStart + (PciDs.ImageLength * 512), SEEK_SET)) { - fprintf (stdout, "ERROR: Failed to seek to next image\n"); - goto BailOut; - } - } - -BailOut: - fclose (InFptr); -} - -char * -GetMachineTypeStr ( - UINT16 MachineType - ) -/*++ - -Routine Description: - - GC_TODO: Add function description - -Arguments: - - MachineType - GC_TODO: add argument description - -Returns: - - GC_TODO: add return values - ---*/ -{ - int Index; - - for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) { - if (mMachineTypes[Index].Value == MachineType) { - return mMachineTypes[Index].Name; - } - } - - return "unknown"; -} - -static -char * -GetSubsystemTypeStr ( - UINT16 SubsystemType - ) -/*++ - -Routine Description: - - GC_TODO: Add function description - -Arguments: - - SubsystemType - GC_TODO: add argument description - -Returns: - - GC_TODO: add return values - ---*/ -{ - int Index; - - for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) { - if (mSubsystemTypes[Index].Value == SubsystemType) { - return mSubsystemTypes[Index].Name; - } - } - - return "unknown"; -}