1. Do not use tab characters 2. No trailing white space in one line 3. All files must end with CRLF Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Liming Gao <liming.gao@intel.com> Cc: Yonghong Zhu <yonghong.zhu@intel.com> Reviewed-by: Yonghong Zhu <yonghong.zhu@intel.com>
		
			
				
	
	
		
			1719 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1719 lines
		
	
	
		
			50 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
| Utility program to create an EFI option ROM image from binary and EFI PE32 files.
 | |
| 
 | |
| Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
| 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.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "EfiUtilityMsgs.h"
 | |
| #include "ParseInf.h"
 | |
| #include "EfiRom.h"
 | |
| 
 | |
| UINT64  DebugLevel = 0;
 | |
| 
 | |
| int
 | |
| 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
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   CHAR8     *Ext;
 | |
|   FILE      *FptrOut;
 | |
|   UINT32    Status;
 | |
|   FILE_LIST *FList;
 | |
|   UINT32    TotalSize;
 | |
|   UINT32    Size;
 | |
|   CHAR8     *Ptr0;
 | |
| 
 | |
|   SetUtilityName(UTILITY_NAME);
 | |
| 
 | |
|   Status  = STATUS_SUCCESS;
 | |
|   FptrOut = NULL;
 | |
| 
 | |
|   //
 | |
|   // Parse the command line arguments
 | |
|   //
 | |
|   if (ParseCommandLine (Argc, Argv, &mOptions)) {
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (mOptions.Quiet) {
 | |
|     SetPrintLevel(40);
 | |
|   } else if (mOptions.Verbose) {
 | |
|     SetPrintLevel(15);
 | |
|   } else if (mOptions.Debug) {
 | |
|     SetPrintLevel(DebugLevel);
 | |
|   }
 | |
| 
 | |
|   if (mOptions.Verbose) {
 | |
|     VerboseMsg("%s tool start.\n", UTILITY_NAME);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If dumping an image, then do that and quit
 | |
|   //
 | |
|   if (mOptions.DumpOption == 1) {
 | |
|     if (mOptions.FileList != NULL) {
 | |
|       if ((Ptr0 = strstr ((CONST CHAR8 *) mOptions.FileList->FileName, DEFAULT_OUTPUT_EXTENSION)) != NULL) {
 | |
|         DumpImage (mOptions.FileList);
 | |
|         goto BailOut;
 | |
|       } else {
 | |
|         Error (NULL, 0, 1002, "No PciRom input file", "No *.rom input file");
 | |
|         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]) {
 | |
|     if (mOptions.FileList != NULL) {
 | |
|       if (strlen (mOptions.FileList->FileName) >= MAX_PATH) {
 | |
|         Status = STATUS_ERROR;
 | |
|         Error (NULL, 0, 2000, "Invalid parameter", "Input file name is too long - %s.", mOptions.FileList->FileName);
 | |
|         goto BailOut;
 | |
|       }
 | |
|       strncpy (mOptions.OutFileName, mOptions.FileList->FileName, MAX_PATH - 1);
 | |
|       mOptions.OutFileName[MAX_PATH - 1] = 0;
 | |
|       //
 | |
|       // Find the last . on the line and replace the filename extension with
 | |
|       // the default
 | |
|       //
 | |
|       Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
 | |
|       while (Ext >= mOptions.OutFileName) {
 | |
|         if ((*Ext == '.') || (*Ext == '\\')) {
 | |
|           break;
 | |
|         }
 | |
|         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;
 | |
|       Error (NULL, 0, 1002, "Invalid input parameter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName);
 | |
|       goto BailOut;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Now open our output file
 | |
|   //
 | |
|   if ((FptrOut = fopen (LongFilePath (mOptions.OutFileName), "wb")) == NULL) {
 | |
|     Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", 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) != 0) {
 | |
|       if (mOptions.Verbose) {
 | |
|         VerboseMsg("Processing EFI file    %s\n", FList->FileName);
 | |
|       }
 | |
| 
 | |
|       Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevIdList[0], &Size);
 | |
|     } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) {
 | |
|       if (mOptions.Verbose) {
 | |
|         VerboseMsg("Processing binary file %s\n", FList->FileName);
 | |
|       }
 | |
| 
 | |
|       Status = ProcessBinFile (FptrOut, FList, &Size);
 | |
|     } else {
 | |
|       Error (NULL, 0, 2000, "Invalid parameter", "File type not specified, it must be either an EFI or binary file: %s.", FList->FileName);
 | |
|       Status = STATUS_ERROR;
 | |
|     }
 | |
| 
 | |
|     if (mOptions.Verbose) {
 | |
|       VerboseMsg("  Output size = 0x%X\n", (unsigned) Size);
 | |
|     }
 | |
| 
 | |
|     if (Status != STATUS_SUCCESS) {
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     TotalSize += Size;
 | |
|   }
 | |
|   //
 | |
|   // Check total size
 | |
|   //
 | |
|   if (TotalSize > MAX_OPTION_ROM_SIZE) {
 | |
|     Error (NULL, 0, 2000, "Invalid parameter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE);
 | |
|     Status = STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
| BailOut:
 | |
|   if (Status == STATUS_SUCCESS) {
 | |
|     //
 | |
|     // Clean up our file list
 | |
|     //
 | |
|     while (mOptions.FileList != NULL) {
 | |
|       FList = mOptions.FileList->Next;
 | |
|       free (mOptions.FileList);
 | |
|       mOptions.FileList = FList;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Clean up device ID list
 | |
|     //
 | |
|     if (mOptions.DevIdList != NULL) {
 | |
|       free (mOptions.DevIdList);
 | |
|     }
 | |
|   }
 | |
|   if (FptrOut != NULL) {
 | |
|     fclose (FptrOut);
 | |
|   }
 | |
| 
 | |
|   if (mOptions.Verbose) {
 | |
|     VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
 | |
|   }
 | |
| 
 | |
|   return GetUtilityStatus ();
 | |
| }
 | |
| 
 | |
| 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        *PciDs23;
 | |
|   PCI_3_0_DATA_STRUCTURE    *PciDs30;
 | |
|   UINT32                    Index;
 | |
|   UINT8                     ByteCheckSum;
 | |
|   UINT16                    CodeType;
 | |
| 
 | |
|   PciDs23 = NULL;
 | |
|   PciDs30 = NULL;
 | |
|   Status = STATUS_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   // Try to open the input file
 | |
|   //
 | |
|   if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
 | |
|     Error (NULL, 0, 0001, "Error opening file", "%s", 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) {
 | |
|     VerboseMsg("  File size   = 0x%X\n", (unsigned) FileSize);
 | |
|   }
 | |
| 
 | |
|   fseek (InFptr, 0, SEEK_SET);
 | |
|   Buffer = (UINT8 *) malloc (FileSize);
 | |
|   if (Buffer == NULL) {
 | |
|     Error (NULL, 0, 4003, "Resource", "memory cannot be allocated!");
 | |
|     Status = STATUS_ERROR;
 | |
|     goto BailOut;
 | |
|   }
 | |
| 
 | |
|   if (fread (Buffer, FileSize, 1, InFptr) != 1) {
 | |
|     Error (NULL, 0, 2000, "Invalid", "Failed to read all bytes from input file.");
 | |
|     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) {
 | |
|     Error (NULL, 0, 3001, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", 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) {
 | |
|     Error (NULL, 0, 2000, "Invalid parameter", "ROM image file has an invalid ROM signature.");
 | |
|     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)) {
 | |
|     Error (NULL, 0, 2000, "Invalid parameter", "Invalid PCI data structure offset.");
 | |
|     Status = STATUS_ERROR;
 | |
|     goto BailOut;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Check the header is conform to PCI2.3 or PCI3.0
 | |
|   //
 | |
|   if (mOptions.Pci23 == 1) {
 | |
|     PciDs23 = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);
 | |
|     if (PciDs23->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
 | |
|       Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature.");
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // Default setting is PCI3.0 header
 | |
|     //
 | |
|     PciDs30 = (PCI_3_0_DATA_STRUCTURE *)(Buffer + RomHdr->PcirOffset);
 | |
|     if (PciDs30->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
 | |
|       Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature.");
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // ReSet Option Rom size
 | |
|   //
 | |
|   if (mOptions.Pci23 == 1) {
 | |
|     PciDs23->ImageLength = (UINT16) (TotalSize / 512);
 | |
|     CodeType = PciDs23->CodeType;
 | |
|   } else {
 | |
|     PciDs30->ImageLength = (UINT16) (TotalSize / 512);
 | |
|     CodeType = PciDs30->CodeType;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If this is the last image, then set the LAST bit unless requested not
 | |
|   // to via the command-line -n argument. Otherwise, make sure you clear it.
 | |
|   //
 | |
|   if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
 | |
|     if (mOptions.Pci23 == 1) {
 | |
|       PciDs23->Indicator = INDICATOR_LAST;
 | |
|     } else {
 | |
|       PciDs30->Indicator = INDICATOR_LAST;
 | |
|     }
 | |
|   } else {
 | |
|     if (mOptions.Pci23 == 1) {
 | |
|       PciDs23->Indicator = 0;
 | |
|     } else {
 | |
|       PciDs30->Indicator = 0;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (CodeType != PCI_CODE_TYPE_EFI_IMAGE) {
 | |
|     ByteCheckSum = 0;
 | |
|     for (Index = 0; Index < FileSize - 1; Index++) {
 | |
|       ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);
 | |
|     }
 | |
| 
 | |
|     Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);
 | |
|     if (mOptions.Verbose) {
 | |
|       VerboseMsg("  Checksum = %02x\n\n", Buffer[FileSize - 1]);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Now copy the input file contents out to the output file
 | |
|   //
 | |
|   if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
 | |
|     Error (NULL, 0, 0005, "Failed to write all file bytes to output file.", NULL);
 | |
|     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) {
 | |
|     Error (NULL, 0, 0003, "Error", "Error parsing file: %s", 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            PciDs23;
 | |
|   PCI_3_0_DATA_STRUCTURE        PciDs30;
 | |
|   UINT32                        FileSize;
 | |
|   UINT32                        CompressedFileSize;
 | |
|   UINT8                         *Buffer;
 | |
|   UINT8                         *CompressedBuffer;
 | |
|   UINT8                         *TempBufferPtr;
 | |
|   UINT32                        TotalSize;
 | |
|   UINT32                        HeaderSize;
 | |
|   UINT16                        MachineType;
 | |
|   UINT16                        SubSystem;
 | |
|   UINT32                        HeaderPadBytes;
 | |
|   UINT32                        PadBytesBeforeImage;
 | |
|   UINT32                        PadBytesAfterImage;
 | |
|   UINT32                        DevIdListSize;
 | |
| 
 | |
|   //
 | |
|   // Try to open the input file
 | |
|   //
 | |
|   if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
 | |
|     Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", 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;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // For Pci3.0 to use the different data structure.
 | |
|   //
 | |
|   if (mOptions.Pci23 == 1) {
 | |
|     HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
 | |
|   } else {
 | |
|     if (mOptions.DevIdCount > 1) {
 | |
|       //
 | |
|       // Write device ID list when more than one device ID is specified.
 | |
|       // Leave space for list plus terminator.
 | |
|       //
 | |
|       DevIdListSize = (mOptions.DevIdCount + 1) * sizeof (UINT16);
 | |
|     } else {
 | |
|       DevIdListSize = 0;
 | |
|     }
 | |
|     HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + DevIdListSize + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
 | |
|   }
 | |
| 
 | |
|   if (mOptions.Verbose) {
 | |
|     VerboseMsg("  File size   = 0x%X\n", (unsigned) 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 = (UINT8 *) malloc (FileSize);
 | |
|   if (Buffer == NULL) {
 | |
|     Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|     Status = STATUS_ERROR;
 | |
|     goto BailOut;
 | |
|   }
 | |
| 
 | |
|   fseek (InFptr, 0, SEEK_SET);
 | |
|   if (fread (Buffer, FileSize, 1, InFptr) != 1) {
 | |
|     Error (NULL, 0, 0004, "Error reading file", "File %s", InFile->FileName);
 | |
|     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) != 0) {
 | |
|     //
 | |
|     // Allocate a buffer into which we can compress the image, compress it,
 | |
|     // and use that size as the new size.
 | |
|     //
 | |
|     CompressedBuffer = (UINT8 *) malloc (FileSize);
 | |
|     if (CompressedBuffer == NULL) {
 | |
|       Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
| 
 | |
|     CompressedFileSize  = FileSize;
 | |
|     Status              = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);
 | |
|     if (Status != STATUS_SUCCESS) {
 | |
|       Error (NULL, 0, 0007, "Error compressing file!", NULL);
 | |
|       goto BailOut;
 | |
|     }
 | |
|     //
 | |
|     // Now compute the size, then swap buffer pointers.
 | |
|     //
 | |
|     if (mOptions.Verbose) {
 | |
|       VerboseMsg("  Comp size   = 0x%X\n", (unsigned) 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;
 | |
|   }
 | |
|   //
 | |
|   // Workaround:
 | |
|   //   If compressed, put the pad bytes after the image,
 | |
|   //   else put the pad bytes before the image.
 | |
|   //
 | |
|   if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) {
 | |
|     PadBytesBeforeImage = 0;
 | |
|     PadBytesAfterImage = TotalSize - (FileSize + HeaderSize);
 | |
|   } else {
 | |
|     PadBytesBeforeImage = TotalSize - (FileSize + HeaderSize);
 | |
|     PadBytesAfterImage = 0;
 | |
|   }
 | |
|   //
 | |
|   // Check size
 | |
|   //
 | |
|   if (TotalSize > MAX_OPTION_ROM_SIZE) {
 | |
|     Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", 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 + PadBytesBeforeImage);
 | |
|   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
 | |
|   //
 | |
|   if (mOptions.Pci23 == 1) {
 | |
|     memset (&PciDs23, 0, sizeof (PCI_DATA_STRUCTURE));
 | |
|   } else {
 | |
|     memset (&PciDs30, 0, sizeof (PCI_3_0_DATA_STRUCTURE));
 | |
|   }
 | |
| 
 | |
|   if (mOptions.Pci23 == 1) {
 | |
|     PciDs23.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
 | |
|     PciDs23.VendorId  = VendId;
 | |
|     PciDs23.DeviceId  = DevId;
 | |
|     PciDs23.Length    = (UINT16) sizeof (PCI_DATA_STRUCTURE);
 | |
|     PciDs23.Revision  = 0;
 | |
|     //
 | |
|     // Class code and code revision from the command line (optional)
 | |
|     //
 | |
|     PciDs23.ClassCode[0]  = (UINT8) InFile->ClassCode;
 | |
|     PciDs23.ClassCode[1]  = (UINT8) (InFile->ClassCode >> 8);
 | |
|     PciDs23.ClassCode[2]  = (UINT8) (InFile->ClassCode >> 16);
 | |
|     PciDs23.ImageLength   = RomHdr.InitializationSize;
 | |
|     PciDs23.CodeRevision  = InFile->CodeRevision;
 | |
|     PciDs23.CodeType      = PCI_CODE_TYPE_EFI_IMAGE;
 | |
|   } else {
 | |
|     PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
 | |
|     PciDs30.VendorId  = VendId;
 | |
|     PciDs30.DeviceId  = DevId;
 | |
|     if (mOptions.DevIdCount > 1) {
 | |
|       //
 | |
|       // Place device list immediately after PCI structure
 | |
|       //
 | |
|       PciDs30.DeviceListOffset = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);
 | |
|     } else {
 | |
|       PciDs30.DeviceListOffset = 0;
 | |
|     }
 | |
|     PciDs30.Length    = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);
 | |
|     PciDs30.Revision  = 0x3;
 | |
|     //
 | |
|     // Class code and code revision from the command line (optional)
 | |
|     //
 | |
|     PciDs30.ClassCode[0]  = (UINT8) InFile->ClassCode;
 | |
|     PciDs30.ClassCode[1]  = (UINT8) (InFile->ClassCode >> 8);
 | |
|     PciDs30.ClassCode[2]  = (UINT8) (InFile->ClassCode >> 16);
 | |
|     PciDs30.ImageLength   = RomHdr.InitializationSize;
 | |
|     PciDs30.CodeRevision  = InFile->CodeRevision;
 | |
|     PciDs30.CodeType      = PCI_CODE_TYPE_EFI_IMAGE;
 | |
|     PciDs30.MaxRuntimeImageLength = 0; // to be fixed
 | |
|     PciDs30.ConfigUtilityCodeHeaderOffset = 0; // to be fixed
 | |
|     PciDs30.DMTFCLPEntryPointOffset = 0; // to be fixed
 | |
|   }
 | |
|   //
 | |
|   // If this is the last image, then set the LAST bit unless requested not
 | |
|   // to via the command-line -n argument.
 | |
|   //
 | |
|   if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
 | |
|     if (mOptions.Pci23 == 1) {
 | |
|       PciDs23.Indicator = INDICATOR_LAST;
 | |
|     } else {
 | |
|     PciDs30.Indicator = INDICATOR_LAST;}
 | |
|   } else {
 | |
|     if (mOptions.Pci23 == 1) {
 | |
|       PciDs23.Indicator = 0;
 | |
|   } else {
 | |
|       PciDs30.Indicator = 0;
 | |
|     }
 | |
|   }
 | |
|   //
 | |
|   // Write the ROM header to the output file
 | |
|   //
 | |
|   if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {
 | |
|     Error (NULL, 0, 0002, "Failed to write ROM header to output file!", NULL);
 | |
|     Status = STATUS_ERROR;
 | |
|     goto BailOut;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Write pad bytes to align the PciDs
 | |
|   //
 | |
|   while (HeaderPadBytes > 0) {
 | |
|     if (putc (0, OutFptr) == EOF) {
 | |
|       Error (NULL, 0, 0002, "Failed to write ROM header pad bytes to output file!", NULL);
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
| 
 | |
|     HeaderPadBytes--;
 | |
|   }
 | |
|   //
 | |
|   // Write the PCI data structure header to the output file
 | |
|   //
 | |
|   if (mOptions.Pci23 == 1) {
 | |
|     if (fwrite (&PciDs23, sizeof (PciDs23), 1, OutFptr) != 1) {
 | |
|       Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
|   } else {
 | |
|     if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) {
 | |
|       Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Write the Device ID list to the output file
 | |
|   //
 | |
|   if (mOptions.DevIdCount > 1) {
 | |
|     if (fwrite (mOptions.DevIdList, sizeof (UINT16), mOptions.DevIdCount, OutFptr) != mOptions.DevIdCount) {
 | |
|       Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL);
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
|     //
 | |
|     // Write two-byte terminating 0 at the end of the device list
 | |
|     //
 | |
|     if (putc (0, OutFptr) == EOF || putc (0, OutFptr) == EOF) {
 | |
|       Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL);
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| 
 | |
|   //
 | |
|   // Pad head to make it a multiple of 512 bytes
 | |
|   //
 | |
|   while (PadBytesBeforeImage > 0) {
 | |
|     if (putc (~0, OutFptr) == EOF) {
 | |
|       Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
|     PadBytesBeforeImage--;
 | |
|   }
 | |
|   //
 | |
|   // Now dump the input file's contents to the output file
 | |
|   //
 | |
|   if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
 | |
|     Error (NULL, 0, 0002, "Failed to write all file bytes to output file!", NULL);
 | |
|     Status = STATUS_ERROR;
 | |
|     goto BailOut;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Pad the rest of the image to make it a multiple of 512 bytes
 | |
|   //
 | |
|   while (PadBytesAfterImage > 0) {
 | |
|     if (putc (~0, OutFptr) == EOF) {
 | |
|       Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);
 | |
|       Status = STATUS_ERROR;
 | |
|       goto BailOut;
 | |
|     }
 | |
| 
 | |
|     PadBytesAfterImage--;
 | |
|   }
 | |
| 
 | |
| 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) {
 | |
|     Error (NULL, 0, 0003, "Error parsing", "Error parsing file: %s", InFile->FileName);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| static
 | |
| int
 | |
| CheckPE32File (
 | |
|   FILE      *Fptr,
 | |
|   UINT16    *MachineType,
 | |
|   UINT16    *SubSystem
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| 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_OPTIONAL_HEADER_UNION PeHdr;
 | |
| 
 | |
|   //
 | |
|   // Position to the start of the file
 | |
|   //
 | |
|   fseek (Fptr, 0, SEEK_SET);
 | |
| 
 | |
|   //
 | |
|   // Read the DOS header
 | |
|   //
 | |
|   if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
 | |
|     Error (NULL, 0, 0004, "Failed to read the DOS stub from the input file!", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Check the magic number (0x5A4D)
 | |
|   //
 | |
|   if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
 | |
|     Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (magic number)!");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
|   //
 | |
|   // Position into the file and check the PE signature
 | |
|   //
 | |
|   fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
 | |
| 
 | |
|   //
 | |
|   // Read PE headers
 | |
|   //
 | |
|   if (fread (&PeHdr, sizeof (PeHdr), 1, Fptr) != 1) {
 | |
|     Error (NULL, 0, 0004, "Failed to read PE/COFF headers from input file!", NULL);
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   //
 | |
|   // Check the PE signature in the header "PE\0\0"
 | |
|   //
 | |
|   if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
 | |
|     Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (signature)!");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   memcpy ((char *) MachineType, &PeHdr.Pe32.FileHeader.Machine, 2);
 | |
| 
 | |
|   if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
 | |
|     *SubSystem = PeHdr.Pe32.OptionalHeader.Subsystem;
 | |
|   } else if (PeHdr.Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
 | |
|     *SubSystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem;
 | |
|   } else {
 | |
|     Error (NULL, 0, 2000, "Invalid parameter", "Unable to find subsystem type!");
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   if (mOptions.Verbose) {
 | |
|     VerboseMsg("  Got subsystem = 0x%X from image\n", *SubSystem);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // File was successfully identified as a PE32
 | |
|   //
 | |
|   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;
 | |
|   EFI_STATUS Status;
 | |
|   INTN       ReturnStatus;
 | |
|   BOOLEAN    EfiRomFlag;
 | |
|   UINT64     TempValue;
 | |
|   char       *OptionName;
 | |
|   UINT16     *DevIdList;
 | |
| 
 | |
|   ReturnStatus = 0;
 | |
|   FileFlags = 0;
 | |
|   EfiRomFlag = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Clear out the options
 | |
|   //
 | |
|   memset ((char *) Options, 0, sizeof (OPTIONS));
 | |
| 
 | |
|   //
 | |
|   // To avoid compile warnings
 | |
|   //
 | |
|   FileList                = PrevFileList = NULL;
 | |
| 
 | |
|   Options->DevIdList      = NULL;
 | |
|   Options->DevIdCount     = 0;
 | |
| 
 | |
|   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;
 | |
|   }
 | |
| 
 | |
|   if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) {
 | |
|     Usage();
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   if ((stricmp(Argv[0], "--version") == 0)) {
 | |
|     Version();
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Process until no more arguments
 | |
|   //
 | |
|   while (Argc > 0) {
 | |
|     if (Argv[0][0] == '-') {
 | |
|       //
 | |
|       // Vendor ID specified with -f
 | |
|       //
 | |
|       if (stricmp (Argv[0], "-f") == 0) {
 | |
|         //
 | |
|         // Make sure there's another parameter
 | |
|         //
 | |
|         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
 | |
|           ReturnStatus = 1;
 | |
|           goto Done;
 | |
|         }
 | |
|         if (TempValue >= 0x10000) {
 | |
|           Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]);
 | |
|           ReturnStatus = 1;
 | |
|           goto Done;
 | |
|         }
 | |
|         Options->VendId       = (UINT16) TempValue;
 | |
|         Options->VendIdValid  = 1;
 | |
| 
 | |
|         Argv++;
 | |
|         Argc--;
 | |
|       } else if (stricmp (Argv[0], "-i") == 0) {
 | |
| 
 | |
|         OptionName = Argv[0];
 | |
| 
 | |
|         //
 | |
|         // Device IDs specified with -i
 | |
|         // Make sure there's at least one more parameter
 | |
|         //
 | |
|         if (Argc < 1) {
 | |
|           Error (NULL, 0, 2000, "Invalid parameter", "Missing Device Id with %s option!", OptionName);
 | |
|           ReturnStatus = 1;
 | |
|           goto Done;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // Process until another dash-argument parameter or the end of the list
 | |
|         //
 | |
|         while (Argc > 1 && Argv[1][0] != '-') {
 | |
|           Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
 | |
|           if (EFI_ERROR (Status)) {
 | |
|             Error (NULL, 0, 2000, "Invalid option value", "%s = %s", OptionName, Argv[1]);
 | |
|             ReturnStatus = 1;
 | |
|             goto Done;
 | |
|           }
 | |
|           //
 | |
|           // Don't allow device IDs greater than 16 bits
 | |
|           // Don't allow 0, since it is used as a list terminator
 | |
|           //
 | |
|           if (TempValue >= 0x10000 || TempValue == 0) {
 | |
|             Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);
 | |
|             ReturnStatus = 1;
 | |
|             goto Done;
 | |
|           }
 | |
| 
 | |
|           DevIdList = (UINT16*) realloc (Options->DevIdList, (Options->DevIdCount + 1) * sizeof (UINT16));
 | |
|           if (DevIdList == NULL) {
 | |
|             Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);
 | |
|             ReturnStatus = 1;
 | |
|             goto Done;
 | |
|           }
 | |
|           Options->DevIdList = DevIdList;
 | |
| 
 | |
|           Options->DevIdList[Options->DevIdCount++] = (UINT16) TempValue;
 | |
| 
 | |
|           Argv++;
 | |
|           Argc--;
 | |
|         }
 | |
| 
 | |
|       } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) {
 | |
|         //
 | |
|         // Output filename specified with -o
 | |
|         // Make sure there's another parameter
 | |
|         //
 | |
|         if (Argv[1] == NULL || Argv[1][0] == '-') {
 | |
|           Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]);
 | |
|           ReturnStatus = STATUS_ERROR;
 | |
|           goto Done;
 | |
|         }
 | |
|         if (strlen (Argv[1]) > MAX_PATH - 1) {
 | |
|           Error (NULL, 0, 2000, "Invalid parameter", "Output file name %s is too long!", Argv[1]);
 | |
|           ReturnStatus = STATUS_ERROR;
 | |
|           goto Done;
 | |
|         }
 | |
|         strncpy (Options->OutFileName, Argv[1], MAX_PATH - 1);
 | |
|         Options->OutFileName[MAX_PATH - 1] = 0;
 | |
| 
 | |
|         Argv++;
 | |
|         Argc--;
 | |
|       } else if ((stricmp (Argv[0], "-h") == 0) || (stricmp (Argv[0], "--help") == 0)) {
 | |
|         //
 | |
|         // Help option
 | |
|         //
 | |
|         Usage ();
 | |
|         ReturnStatus = STATUS_ERROR;
 | |
|         goto Done;
 | |
|       } else if (stricmp (Argv[0], "-b") == 0) {
 | |
|         //
 | |
|         // Specify binary files with -b
 | |
|         //
 | |
|         FileFlags = FILE_FLAG_BINARY;
 | |
|       } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {
 | |
|         //
 | |
|         // Specify EFI files with -e. Specify EFI-compressed with -c.
 | |
|         //
 | |
|         FileFlags = 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 -n
 | |
|         //
 | |
|       } else if (stricmp (Argv[0], "-n") == 0) {
 | |
|         Options->NoLast = 1;
 | |
|       } else if (((stricmp (Argv[0], "-v") == 0)) || ((stricmp (Argv[0], "--verbose") == 0))) {
 | |
|         //
 | |
|         // -v for verbose
 | |
|         //
 | |
|         Options->Verbose = 1;
 | |
|       } else if (stricmp (Argv[0], "--debug") == 0) {
 | |
|         Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
 | |
|           ReturnStatus = 1;
 | |
|           goto Done;
 | |
|         }
 | |
|         if (DebugLevel > 9)  {
 | |
|           Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]);
 | |
|           ReturnStatus = 1;
 | |
|           goto Done;
 | |
|         }
 | |
|         if (DebugLevel>=5 && DebugLevel<=9) {
 | |
|           Options->Debug = TRUE;
 | |
|         } else {
 | |
|           Options->Debug = FALSE;
 | |
|         }
 | |
|         Argv++;
 | |
|         Argc--;
 | |
|       } else if ((stricmp (Argv[0], "--quiet") == 0) || (stricmp (Argv[0], "-q") == 0)) {
 | |
|         Options->Quiet = TRUE;
 | |
|       } else if ((stricmp (Argv[0], "--dump") == 0) || (stricmp (Argv[0], "-d") == 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->DevIdCount   = 1;
 | |
|         FileFlags             = FILE_FLAG_BINARY;
 | |
|       } else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) {
 | |
|         //
 | |
|         // Class code value for the next file in the list.
 | |
|         // Make sure there's another parameter
 | |
|         //
 | |
|         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
 | |
|           ReturnStatus = 1;
 | |
|           goto Done;
 | |
|         }
 | |
|         ClassCode = (UINT32) TempValue;
 | |
|         if (ClassCode & 0xFF000000) {
 | |
|           Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]);
 | |
|           ReturnStatus = STATUS_ERROR;
 | |
|           goto Done;
 | |
|         }
 | |
|         if (FileList != NULL && FileList->ClassCode == 0) {
 | |
|           FileList->ClassCode = ClassCode;
 | |
|         }
 | |
|         Argv++;
 | |
|         Argc--;
 | |
|       } else if ((stricmp (Argv[0], "-r") == 0) || (stricmp (Argv[0], "--Revision") == 0)) {
 | |
|         //
 | |
|         // Code revision in the PCI data structure. The value is for the next
 | |
|         // file in the list.
 | |
|         // Make sure there's another parameter
 | |
|         //
 | |
|         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
 | |
|         if (EFI_ERROR (Status)) {
 | |
|           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
 | |
|           ReturnStatus = 1;
 | |
|           goto Done;
 | |
|         }
 | |
|         CodeRevision = (UINT32) TempValue;
 | |
|         if (CodeRevision & 0xFFFF0000) {
 | |
|           Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]);
 | |
|           ReturnStatus = STATUS_ERROR;
 | |
|           goto Done;
 | |
|         }
 | |
|         if (FileList != NULL && FileList->CodeRevision == 0) {
 | |
|           FileList->CodeRevision = (UINT16) CodeRevision;
 | |
|         }
 | |
|         Argv++;
 | |
|         Argc--;
 | |
|       } else if ((stricmp (Argv[0], "-p") == 0) || (stricmp (Argv[0], "--pci23") == 0)) {
 | |
|         //
 | |
|         // Default layout meets PCI 3.0 specifications, specifying this flag will for a PCI 2.3 layout.
 | |
|         //
 | |
|         mOptions.Pci23 = 1;
 | |
|       } else {
 | |
|         Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]);
 | |
|         ReturnStatus = STATUS_ERROR;
 | |
|         goto Done;
 | |
|       }
 | |
|     } 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) {
 | |
|         Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]);
 | |
|         ReturnStatus = STATUS_ERROR;
 | |
|         goto Done;
 | |
|       }
 | |
|       //
 | |
|       // Check Efi Option RomImage
 | |
|       //
 | |
|       if ((FileFlags & FILE_FLAG_EFI) == FILE_FLAG_EFI) {
 | |
|         EfiRomFlag = TRUE;
 | |
|       }
 | |
|       //
 | |
|       // Create a new file structure
 | |
|       //
 | |
|       FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));
 | |
|       if (FileList == NULL) {
 | |
|         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);
 | |
|         ReturnStatus = STATUS_ERROR;
 | |
|         goto Done;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // set flag and class code for this image.
 | |
|       //
 | |
|       memset ((char *) FileList, 0, sizeof (FILE_LIST));
 | |
|       FileList->FileName      = Argv[0];
 | |
|       FileList->FileFlags     = FileFlags;
 | |
|       FileList->ClassCode     = ClassCode;
 | |
|       FileList->CodeRevision  = (UINT16) CodeRevision;
 | |
|       ClassCode               = 0;
 | |
|       CodeRevision            = 0;
 | |
| 
 | |
|       if (Options->FileList == NULL) {
 | |
|         Options->FileList = FileList;
 | |
|       } else {
 | |
|         if (PrevFileList == NULL) {
 | |
|           PrevFileList = FileList;
 | |
|         } else {
 | |
|           PrevFileList->Next = FileList;
 | |
|         }
 | |
|       }
 | |
| 
 | |
|       PrevFileList = FileList;
 | |
|     }
 | |
|     //
 | |
|     // Next argument
 | |
|     //
 | |
|     Argv++;
 | |
|     Argc--;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Must have specified some files
 | |
|   //
 | |
|   if (Options->FileList == NULL) {
 | |
|     Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!");
 | |
|     //
 | |
|     // No memory allocation, return directly.
 | |
|     //
 | |
|     return STATUS_ERROR;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // For EFI OptionRom image, Make sure a device ID and vendor ID are both specified.
 | |
|   //
 | |
|   if (EfiRomFlag) {
 | |
|     if (!Options->VendIdValid) {
 | |
|       Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL);
 | |
|       ReturnStatus = STATUS_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (!Options->DevIdCount) {
 | |
|       Error (NULL, 0, 2000, "Missing Device ID in command line", NULL);
 | |
|       ReturnStatus = STATUS_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|    if (Options->DevIdCount > 1 && Options->Pci23) {
 | |
|      Error (NULL, 0, 2000, "Invalid parameter", "PCI 3.0 is required when specifying multiple Device IDs");
 | |
|      ReturnStatus = STATUS_ERROR;
 | |
|      goto Done;
 | |
|    }
 | |
| 
 | |
| Done:
 | |
|   if (ReturnStatus != 0) {
 | |
|     while (Options->FileList != NULL) {
 | |
|       FileList = Options->FileList->Next;
 | |
|       free (Options->FileList);
 | |
|       Options->FileList = FileList;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return ReturnStatus;
 | |
| }
 | |
| 
 | |
| static
 | |
| void
 | |
| Version (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Print version information for this utility.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   None.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   Nothing.
 | |
| --*/
 | |
| {
 | |
|  fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
 | |
| }
 | |
| 
 | |
| static
 | |
| void
 | |
| Usage (
 | |
|   VOID
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Print usage information for this utility.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   None.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   Nothing.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   //
 | |
|   // Summary usage
 | |
|   //
 | |
|   fprintf (stdout, "Usage: %s -f VendorId -i DeviceId [options] [file name<s>] \n\n", UTILITY_NAME);
 | |
| 
 | |
|   //
 | |
|   // Copyright declaration
 | |
|   //
 | |
|   fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
 | |
| 
 | |
|   //
 | |
|   // Details Option
 | |
|   //
 | |
|   fprintf (stdout, "Options:\n");
 | |
|   fprintf (stdout, "  -o FileName, --output FileName\n\
 | |
|             File will be created to store the output content.\n");
 | |
|   fprintf (stdout, "  -e EfiFileName\n\
 | |
|             EFI PE32 image files.\n");
 | |
|   fprintf (stdout, "  -ec EfiFileName\n\
 | |
|             EFI PE32 image files and will be compressed.\n");
 | |
|   fprintf (stdout, "  -b BinFileName\n\
 | |
|             Legacy binary files.\n");
 | |
|   fprintf (stdout, "  -l ClassCode\n\
 | |
|             Hex ClassCode in the PCI data structure header.\n");
 | |
|   fprintf (stdout, "  -r Rev    Hex Revision in the PCI data structure header.\n");
 | |
|   fprintf (stdout, "  -n        Not to automatically set the LAST bit in the last file.\n");
 | |
|   fprintf (stdout, "  -f VendorId\n\
 | |
|             Hex PCI Vendor ID for the device OpROM, must be specified\n");
 | |
|   fprintf (stdout, "  -i DeviceId\n\
 | |
|             One or more hex PCI Device IDs for the device OpROM, must be specified\n");
 | |
|   fprintf (stdout, "  -p, --pci23\n\
 | |
|             Default layout meets PCI 3.0 specifications\n\
 | |
|             specifying this flag will for a PCI 2.3 layout.\n");
 | |
|   fprintf (stdout, "  -d, --dump\n\
 | |
|             Dump the headers of an existing option ROM image.\n");
 | |
|   fprintf (stdout, "  -v, --verbose\n\
 | |
|             Turn on verbose output with informational messages.\n");
 | |
|   fprintf (stdout, "  --version Show program's version number and exit.\n");
 | |
|   fprintf (stdout, "  -h, --help\n\
 | |
|             Show this help message and exit.\n");
 | |
|   fprintf (stdout, "  -q, --quiet\n\
 | |
|             Disable all messages except FATAL ERRORS.\n");
 | |
|   fprintf (stdout, "  --debug [#,0-9]\n\
 | |
|             Enable debug messages at level #.\n");
 | |
| }
 | |
| 
 | |
| static
 | |
| void
 | |
| DumpImage (
 | |
|   FILE_LIST *InFile
 | |
|   )
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Dump the headers of an existing option ROM image
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   InFile  - the file name of an existing option ROM image
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   none
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   PCI_EXPANSION_ROM_HEADER      PciRomHdr;
 | |
|   FILE                          *InFptr;
 | |
|   UINT32                        ImageStart;
 | |
|   UINT32                        ImageCount;
 | |
|   EFI_PCI_EXPANSION_ROM_HEADER  EfiRomHdr;
 | |
|   PCI_DATA_STRUCTURE            PciDs23;
 | |
|   PCI_3_0_DATA_STRUCTURE        PciDs30;
 | |
|   UINT16                        DevId;
 | |
| 
 | |
|   //
 | |
|   // Open the input file
 | |
|   //
 | |
|   if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
 | |
|     Error (NULL, 0, 0001, "Error opening file", 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) {
 | |
|       Error (NULL, 0, 3001, "Not supported", "Failed to read PCI ROM header from file!");
 | |
|       goto BailOut;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Dump the contents of the header
 | |
|     //
 | |
|     fprintf (stdout, "Image %u -- Offset 0x%X\n", (unsigned) ImageCount, (unsigned) ImageStart);
 | |
|     fprintf (stdout, "  ROM header contents\n");
 | |
|     fprintf (stdout, "    Signature              0x%04X\n", PciRomHdr.Signature);
 | |
|     fprintf (stdout, "    PCIR offset            0x%04X\n", PciRomHdr.PcirOffset);
 | |
|     //
 | |
|     // Find PCI data structure
 | |
|     //
 | |
|     if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {
 | |
|       Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI data structure!");
 | |
|       goto BailOut;
 | |
|     }
 | |
|     //
 | |
|     // Read and dump the PCI data structure
 | |
|     //
 | |
|     memset (&PciDs23, 0, sizeof (PciDs23));
 | |
|     memset (&PciDs30, 0, sizeof (PciDs30));
 | |
|     if (mOptions.Pci23 == 1) {
 | |
|       if (fread (&PciDs23, sizeof (PciDs23), 1, InFptr) != 1) {
 | |
|         Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName);
 | |
|         goto BailOut;
 | |
|       }
 | |
|     } else {
 | |
|       if (fread (&PciDs30, sizeof (PciDs30), 1, InFptr) != 1) {
 | |
|         Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName);
 | |
|         goto BailOut;
 | |
|       }
 | |
|     }
 | |
|     if (mOptions.Verbose) {
 | |
|       VerboseMsg("Read PCI data structure from file %s", InFile->FileName);
 | |
|     }
 | |
| 
 | |
|     //fprintf (stdout, "  PCI Data Structure\n");
 | |
|     if (mOptions.Pci23 == 1) {
 | |
|     fprintf (
 | |
|       stdout,
 | |
|       "    Signature              %c%c%c%c\n",
 | |
|       (char) PciDs23.Signature,
 | |
|       (char) (PciDs23.Signature >> 8),
 | |
|       (char) (PciDs23.Signature >> 16),
 | |
|       (char) (PciDs23.Signature >> 24)
 | |
|       );
 | |
|     fprintf (stdout, "    Vendor ID              0x%04X\n", PciDs23.VendorId);
 | |
|     fprintf (stdout, "    Device ID              0x%04X\n", PciDs23.DeviceId);
 | |
|     fprintf (stdout, "    Length                 0x%04X\n", PciDs23.Length);
 | |
|     fprintf (stdout, "    Revision               0x%04X\n", PciDs23.Revision);
 | |
|     fprintf (
 | |
|       stdout,
 | |
|       "    Class Code             0x%06X\n",
 | |
|       (unsigned) (PciDs23.ClassCode[0] | (PciDs23.ClassCode[1] << 8) | (PciDs23.ClassCode[2] << 16))
 | |
|       );
 | |
|     fprintf (stdout, "    Image size             0x%X\n", (unsigned) PciDs23.ImageLength * 512);
 | |
|     fprintf (stdout, "    Code revision:         0x%04X\n", PciDs23.CodeRevision);
 | |
|     fprintf (stdout, "    Indicator              0x%02X", PciDs23.Indicator);
 | |
|     } else {
 | |
|     fprintf (
 | |
|       stdout,
 | |
|       "    Signature               %c%c%c%c\n",
 | |
|       (char) PciDs30.Signature,
 | |
|       (char) (PciDs30.Signature >> 8),
 | |
|       (char) (PciDs30.Signature >> 16),
 | |
|       (char) (PciDs30.Signature >> 24)
 | |
|       );
 | |
|     fprintf (stdout, "    Vendor ID               0x%04X\n", PciDs30.VendorId);
 | |
|     fprintf (stdout, "    Device ID               0x%04X\n", PciDs30.DeviceId);
 | |
|     fprintf (stdout, "    Length                  0x%04X\n", PciDs30.Length);
 | |
|     fprintf (stdout, "    Revision                0x%04X\n", PciDs30.Revision);
 | |
|     fprintf (stdout, "    DeviceListOffset        0x%02X\n", PciDs30.DeviceListOffset);
 | |
|     if (PciDs30.DeviceListOffset) {
 | |
|       //
 | |
|       // Print device ID list
 | |
|       //
 | |
|       fprintf (stdout, "    Device list contents\n");
 | |
|       if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset + PciDs30.DeviceListOffset, SEEK_SET)) {
 | |
|         Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI device ID list!");
 | |
|         goto BailOut;
 | |
|       }
 | |
| 
 | |
|       //
 | |
|       // Loop until terminating 0
 | |
|       //
 | |
|       do {
 | |
|         if (fread (&DevId, sizeof (DevId), 1, InFptr) != 1) {
 | |
|           Error (NULL, 0, 3001, "Not supported", "Failed to read PCI device ID list from file %s!", InFile->FileName);
 | |
|           goto BailOut;
 | |
|         }
 | |
|         if (DevId) {
 | |
|           fprintf (stdout, "      0x%04X\n", DevId);
 | |
|         }
 | |
|       } while (DevId);
 | |
| 
 | |
|     }
 | |
|     fprintf (
 | |
|       stdout,
 | |
|       "    Class Code              0x%06X\n",
 | |
|       (unsigned) (PciDs30.ClassCode[0] | (PciDs30.ClassCode[1] << 8) | (PciDs30.ClassCode[2] << 16))
 | |
|       );
 | |
|     fprintf (stdout, "    Image size              0x%X\n", (unsigned) PciDs30.ImageLength * 512);
 | |
|     fprintf (stdout, "    Code revision:          0x%04X\n", PciDs30.CodeRevision);
 | |
|     fprintf (stdout, "    MaxRuntimeImageLength   0x%02X\n", PciDs30.MaxRuntimeImageLength);
 | |
|     fprintf (stdout, "    ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset);
 | |
|     fprintf (stdout, "    DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset);
 | |
|     fprintf (stdout, "    Indicator               0x%02X", PciDs30.Indicator);
 | |
|     }
 | |
|     //
 | |
|     // Print the indicator, used to flag the last image
 | |
|     //
 | |
|     if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.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.
 | |
|     //
 | |
|     if (mOptions.Pci23 == 1) {
 | |
|       fprintf (stdout, "    Code type              0x%02X", PciDs23.CodeType);
 | |
|     } else {
 | |
|       fprintf (stdout, "    Code type               0x%02X", PciDs30.CodeType);
 | |
|     }
 | |
|     if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.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)) {
 | |
|         Error (NULL, 0, 5001, "Failed to re-seek to ROM header structure!", NULL);
 | |
|         goto BailOut;
 | |
|       }
 | |
| 
 | |
|       if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {
 | |
|         Error (NULL, 0, 5001, "Failed to read EFI PCI ROM header from file!", NULL);
 | |
|         goto BailOut;
 | |
|       }
 | |
|       //
 | |
|       // Now dump more info
 | |
|       //
 | |
|       fprintf (stdout, "    EFI Signature          0x%04X\n", (unsigned) EfiRomHdr.EfiSignature);
 | |
|       fprintf (
 | |
|         stdout,
 | |
|         "    Compression Type       0x%04X ",
 | |
|         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",
 | |
|         EfiRomHdr.EfiImageHeaderOffset,
 | |
|         EfiRomHdr.EfiImageHeaderOffset + (unsigned) 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 (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) {
 | |
|       goto BailOut;
 | |
|     }
 | |
|     //
 | |
|     // Seek to the start of the next image
 | |
|     //
 | |
|     if (mOptions.Pci23 == 1) {
 | |
|       if (fseek (InFptr, ImageStart + (PciDs23.ImageLength * 512), SEEK_SET)) {
 | |
|         Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!");
 | |
|         goto BailOut;
 | |
|       }
 | |
|     } else {
 | |
|       if (fseek (InFptr, ImageStart + (PciDs30.ImageLength * 512), SEEK_SET)) {
 | |
|         Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!");
 | |
|         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";
 | |
| }
 |