/** @file\r
+Utility program to create an EFI option ROM image from binary and EFI PE32 files.\r
\r
-Copyright (c) 1999-2008 Intel Corporation. All rights reserved\r
-This program and the accompanying materials are licensed and made available \r
-under the terms and conditions of the BSD License which accompanies this \r
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available\r
+under the terms and conditions of the BSD License which accompanies this\r
distribution. The full text of the license may be found at\r
http://opensource.org/licenses/bsd-license.php\r
\r
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
-Module Name:\r
-\r
- EfiRom.c\r
- \r
-Abstract:\r
-\r
- Utility program to create an EFI option ROM image from binary and \r
- EFI PE32 files.\r
-\r
**/\r
\r
#include "EfiUtilityMsgs.h"\r
/*++\r
\r
Routine Description:\r
- \r
- Given an EFI image filename, create a ROM-able image by creating an option \r
+\r
+ Given an EFI image filename, create a ROM-able image by creating an option\r
ROM header and PCI data structure, filling them in, and then writing the\r
option ROM header + PCI data structure + EFI image out to the output file.\r
\r
} else if (mOptions.Debug) {\r
SetPrintLevel(DebugLevel);\r
}\r
- \r
+\r
if (mOptions.Verbose) {\r
VerboseMsg("%s tool start.\n", UTILITY_NAME);\r
}\r
- \r
+\r
//\r
// If dumping an image, then do that and quit\r
//\r
// the command line, or the first input filename with a different extension.\r
//\r
if (!mOptions.OutFileName[0]) {\r
- strcpy (mOptions.OutFileName, mOptions.FileList->FileName);\r
- //\r
- // Find the last . on the line and replace the filename extension with\r
- // the default\r
- //\r
- for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
- (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');\r
- Ext--\r
- )\r
- ;\r
- //\r
- // If dot here, then insert extension here, otherwise append\r
- //\r
- if (*Ext != '.') {\r
- Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);\r
- }\r
+ if (mOptions.FileList != NULL) {\r
+ if (strlen (mOptions.FileList->FileName) >= MAX_PATH) {\r
+ Status = STATUS_ERROR;\r
+ Error (NULL, 0, 2000, "Invalid parameter", "Input file name is too long - %s.", mOptions.FileList->FileName);\r
+ goto BailOut;\r
+ }\r
+ strncpy (mOptions.OutFileName, mOptions.FileList->FileName, MAX_PATH - 1);\r
+ mOptions.OutFileName[MAX_PATH - 1] = 0;\r
+ //\r
+ // Find the last . on the line and replace the filename extension with\r
+ // the default\r
+ //\r
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
+ while (Ext >= mOptions.OutFileName) {\r
+ if ((*Ext == '.') || (*Ext == '\\')) {\r
+ break;\r
+ }\r
+ Ext--;\r
+ }\r
+ //\r
+ // If dot here, then insert extension here, otherwise append\r
+ //\r
+ if (*Ext != '.') {\r
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);\r
+ }\r
\r
- strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);\r
+ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);\r
+ }\r
}\r
//\r
// Make sure we don't have the same filename for input and output files\r
for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {\r
if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {\r
Status = STATUS_ERROR;\r
- Error (NULL, 0, 1002, "Invalid input paramter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName);\r
+ Error (NULL, 0, 1002, "Invalid input parameter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName);\r
goto BailOut;\r
}\r
}\r
//\r
// Now open our output file\r
//\r
- if ((FptrOut = fopen (mOptions.OutFileName, "wb")) == NULL) {\r
+ if ((FptrOut = fopen (LongFilePath (mOptions.OutFileName), "wb")) == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", mOptions.OutFileName);\r
goto BailOut;\r
}\r
VerboseMsg("Processing EFI file %s\n", FList->FileName);\r
}\r
\r
- Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);\r
+ Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevIdList[0], &Size);\r
} else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) {\r
if (mOptions.Verbose) {\r
VerboseMsg("Processing binary file %s\n", FList->FileName);\r
// Check total size\r
//\r
if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
- Error (NULL, 0, 2000, "Invalid paramter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE);\r
+ Error (NULL, 0, 2000, "Invalid parameter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE);\r
Status = STATUS_ERROR;\r
}\r
\r
BailOut:\r
if (Status == STATUS_SUCCESS) {\r
- if (FptrOut != NULL) {\r
- fclose (FptrOut);\r
- }\r
//\r
// Clean up our file list\r
//\r
free (mOptions.FileList);\r
mOptions.FileList = FList;\r
}\r
+\r
+ //\r
+ // Clean up device ID list\r
+ //\r
+ if (mOptions.DevIdList != NULL) {\r
+ free (mOptions.DevIdList);\r
+ }\r
+ }\r
+ if (FptrOut != NULL) {\r
+ fclose (FptrOut);\r
}\r
\r
if (mOptions.Verbose) {\r
VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());\r
}\r
\r
- return GetUtilityStatus (); \r
+ return GetUtilityStatus ();\r
}\r
\r
static\r
/*++\r
\r
Routine Description:\r
- \r
+\r
Process a binary input file.\r
\r
Arguments:\r
PCI_3_0_DATA_STRUCTURE *PciDs30;\r
UINT32 Index;\r
UINT8 ByteCheckSum;\r
- \r
+ UINT16 CodeType;\r
+\r
PciDs23 = NULL;\r
PciDs30 = NULL;\r
Status = STATUS_SUCCESS;\r
//\r
// Try to open the input file\r
//\r
- if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
- Error (NULL, 0, 0001, "Error opening file", InFile->FileName);\r
+ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {\r
+ Error (NULL, 0, 0001, "Error opening file", "%s", InFile->FileName);\r
return STATUS_ERROR;\r
}\r
//\r
//\r
if (mOptions.Pci23 == 1) {\r
PciDs23->ImageLength = (UINT16) (TotalSize / 512);\r
+ CodeType = PciDs23->CodeType;\r
} else {\r
PciDs30->ImageLength = (UINT16) (TotalSize / 512);\r
- }\r
+ CodeType = PciDs30->CodeType;\r
+ }\r
\r
//\r
// If this is the last image, then set the LAST bit unless requested not\r
PciDs23->Indicator = INDICATOR_LAST;\r
} else {\r
PciDs30->Indicator = INDICATOR_LAST;\r
- }\r
+ }\r
} else {\r
if (mOptions.Pci23 == 1) {\r
PciDs23->Indicator = 0;\r
} else {\r
PciDs30->Indicator = 0;\r
- }\r
+ }\r
}\r
\r
- ByteCheckSum = 0;\r
- for (Index = 0; Index < FileSize - 1; Index++) {\r
- ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);\r
- }\r
+ if (CodeType != PCI_CODE_TYPE_EFI_IMAGE) {\r
+ ByteCheckSum = 0;\r
+ for (Index = 0; Index < FileSize - 1; Index++) {\r
+ ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);\r
+ }\r
\r
- Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);\r
- if (mOptions.Verbose) {\r
- VerboseMsg(" Checksum = %02x\n\n", Buffer[FileSize - 1]);\r
+ Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);\r
+ if (mOptions.Verbose) {\r
+ VerboseMsg(" Checksum = %02x\n\n", Buffer[FileSize - 1]);\r
+ }\r
}\r
\r
//\r
/*++\r
\r
Routine Description:\r
- \r
+\r
Process a PE32 EFI file.\r
\r
Arguments:\r
UINT16 MachineType;\r
UINT16 SubSystem;\r
UINT32 HeaderPadBytes;\r
+ UINT32 PadBytesBeforeImage;\r
+ UINT32 PadBytesAfterImage;\r
+ UINT32 DevIdListSize;\r
\r
//\r
// Try to open the input file\r
//\r
- if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {\r
Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", InFile->FileName);\r
return STATUS_ERROR;\r
}\r
} else {\r
HeaderPadBytes = 0;\r
}\r
- \r
+\r
//\r
// For Pci3.0 to use the different data structure.\r
//\r
if (mOptions.Pci23 == 1) {\r
HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
} else {\r
- HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
+ if (mOptions.DevIdCount > 1) {\r
+ //\r
+ // Write device ID list when more than one device ID is specified.\r
+ // Leave space for list plus terminator.\r
+ //\r
+ DevIdListSize = (mOptions.DevIdCount + 1) * sizeof (UINT16);\r
+ } else {\r
+ DevIdListSize = 0;\r
+ }\r
+ HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + DevIdListSize + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
}\r
\r
if (mOptions.Verbose) {\r
TotalSize = (TotalSize + 0x200) &~0x1ff;\r
}\r
//\r
+ // Workaround:\r
+ // If compressed, put the pad bytes after the image,\r
+ // else put the pad bytes before the image.\r
+ //\r
+ if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) {\r
+ PadBytesBeforeImage = 0;\r
+ PadBytesAfterImage = TotalSize - (FileSize + HeaderSize);\r
+ } else {\r
+ PadBytesBeforeImage = TotalSize - (FileSize + HeaderSize);\r
+ PadBytesAfterImage = 0;\r
+ }\r
+ //\r
// Check size\r
//\r
if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
- Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE); \r
+ Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);\r
Status = STATUS_ERROR;\r
goto BailOut;\r
}\r
RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;\r
RomHdr.EfiSubsystem = SubSystem;\r
RomHdr.EfiMachineType = MachineType;\r
- RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize;\r
+ RomHdr.EfiImageHeaderOffset = (UINT16) (HeaderSize + PadBytesBeforeImage);\r
RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);\r
//\r
// Set image as compressed or not\r
PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE;\r
PciDs30.VendorId = VendId;\r
PciDs30.DeviceId = DevId;\r
- PciDs30.DeviceListOffset = 0; // to be fixed\r
+ if (mOptions.DevIdCount > 1) {\r
+ //\r
+ // Place device list immediately after PCI structure\r
+ //\r
+ PciDs30.DeviceListOffset = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);\r
+ } else {\r
+ PciDs30.DeviceListOffset = 0;\r
+ }\r
PciDs30.Length = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);\r
PciDs30.Revision = 0x3;\r
//\r
if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
if (mOptions.Pci23 == 1) {\r
PciDs23.Indicator = INDICATOR_LAST;\r
- } else {\r
+ } else {\r
PciDs30.Indicator = INDICATOR_LAST;}\r
} else {\r
if (mOptions.Pci23 == 1) {\r
PciDs23.Indicator = 0;\r
- } else {\r
+ } else {\r
PciDs30.Indicator = 0;\r
}\r
}\r
Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);\r
Status = STATUS_ERROR;\r
goto BailOut;\r
- } \r
+ }\r
} else {\r
if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) {\r
Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);\r
Status = STATUS_ERROR;\r
goto BailOut;\r
- } \r
+ }\r
}\r
+\r
//\r
- // Keep track of how many bytes left to write\r
+ // Write the Device ID list to the output file\r
//\r
- TotalSize -= HeaderSize;\r
+ if (mOptions.DevIdCount > 1) {\r
+ if (fwrite (mOptions.DevIdList, sizeof (UINT16), mOptions.DevIdCount, OutFptr) != mOptions.DevIdCount) {\r
+ Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL);\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ //\r
+ // Write two-byte terminating 0 at the end of the device list\r
+ //\r
+ if (putc (0, OutFptr) == EOF || putc (0, OutFptr) == EOF) {\r
+ Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL);\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ }\r
\r
+\r
+ //\r
+ // Pad head to make it a multiple of 512 bytes\r
+ //\r
+ while (PadBytesBeforeImage > 0) {\r
+ if (putc (~0, OutFptr) == EOF) {\r
+ Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+ PadBytesBeforeImage--;\r
+ }\r
//\r
// Now dump the input file's contents to the output file\r
//\r
goto BailOut;\r
}\r
\r
- TotalSize -= FileSize;\r
//\r
// Pad the rest of the image to make it a multiple of 512 bytes\r
//\r
- while (TotalSize > 0) {\r
+ while (PadBytesAfterImage > 0) {\r
if (putc (~0, OutFptr) == EOF) {\r
Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);\r
Status = STATUS_ERROR;\r
goto BailOut;\r
}\r
\r
- TotalSize--;\r
+ PadBytesAfterImage--;\r
}\r
\r
BailOut:\r
/*++\r
\r
Routine Description:\r
- \r
+\r
Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
PE32 image file, and then return the machine type in the supplied pointer.\r
\r
/*++\r
\r
Routine Description:\r
- \r
+\r
Given the Argc/Argv program arguments, and a pointer to an options structure,\r
parse the command-line options and check their validity.\r
\r
UINT32 ClassCode;\r
UINT32 CodeRevision;\r
EFI_STATUS Status;\r
+ INTN ReturnStatus;\r
BOOLEAN EfiRomFlag;\r
UINT64 TempValue;\r
+ char *OptionName;\r
+ UINT16 *DevIdList;\r
\r
+ ReturnStatus = 0;\r
FileFlags = 0;\r
EfiRomFlag = FALSE;\r
\r
//\r
FileList = PrevFileList = NULL;\r
\r
+ Options->DevIdList = NULL;\r
+ Options->DevIdCount = 0;\r
+\r
ClassCode = 0;\r
CodeRevision = 0;\r
//\r
Usage ();\r
return STATUS_ERROR;\r
}\r
- \r
+\r
if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) {\r
Usage();\r
return STATUS_ERROR;\r
}\r
- \r
+\r
if ((stricmp(Argv[0], "--version") == 0)) {\r
Version();\r
return STATUS_ERROR;\r
Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
if (EFI_ERROR (Status)) {\r
Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
- return 1;\r
+ ReturnStatus = 1;\r
+ goto Done;\r
}\r
if (TempValue >= 0x10000) {\r
Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]);\r
- return 1;\r
+ ReturnStatus = 1;\r
+ goto Done;\r
}\r
Options->VendId = (UINT16) TempValue;\r
Options->VendIdValid = 1;\r
Argv++;\r
Argc--;\r
} else if (stricmp (Argv[0], "-i") == 0) {\r
+\r
+ OptionName = Argv[0];\r
+\r
//\r
- // Device ID specified with -i\r
- // Make sure there's another parameter\r
+ // Device IDs specified with -i\r
+ // Make sure there's at least one more parameter\r
//\r
- Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
- if (EFI_ERROR (Status)) {\r
- Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
- return 1;\r
+ if (Argc < 1) {\r
+ Error (NULL, 0, 2000, "Invalid parameter", "Missing Device Id with %s option!", OptionName);\r
+ ReturnStatus = 1;\r
+ goto Done;\r
}\r
- if (TempValue >= 0x10000) {\r
- Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);\r
- return 1;\r
+\r
+ //\r
+ // Process until another dash-argument parameter or the end of the list\r
+ //\r
+ while (Argc > 1 && Argv[1][0] != '-') {\r
+ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
+ if (EFI_ERROR (Status)) {\r
+ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", OptionName, Argv[1]);\r
+ ReturnStatus = 1;\r
+ goto Done;\r
+ }\r
+ //\r
+ // Don't allow device IDs greater than 16 bits\r
+ // Don't allow 0, since it is used as a list terminator\r
+ //\r
+ if (TempValue >= 0x10000 || TempValue == 0) {\r
+ Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);\r
+ ReturnStatus = 1;\r
+ goto Done;\r
+ }\r
+\r
+ DevIdList = (UINT16*) realloc (Options->DevIdList, (Options->DevIdCount + 1) * sizeof (UINT16));\r
+ if (DevIdList == NULL) {\r
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);\r
+ ReturnStatus = 1;\r
+ goto Done;\r
+ }\r
+ Options->DevIdList = DevIdList;\r
+\r
+ Options->DevIdList[Options->DevIdCount++] = (UINT16) TempValue;\r
+\r
+ Argv++;\r
+ Argc--;\r
}\r
- Options->DevId = (UINT16) TempValue;\r
- Options->DevIdValid = 1;\r
\r
- Argv++;\r
- Argc--;\r
} else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) {\r
//\r
// Output filename specified with -o\r
//\r
if (Argv[1] == NULL || Argv[1][0] == '-') {\r
Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]);\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
}\r
- strcpy (Options->OutFileName, Argv[1]);\r
+ if (strlen (Argv[1]) > MAX_PATH - 1) {\r
+ Error (NULL, 0, 2000, "Invalid parameter", "Output file name %s is too long!", Argv[1]);\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
+ }\r
+ strncpy (Options->OutFileName, Argv[1], MAX_PATH - 1);\r
+ Options->OutFileName[MAX_PATH - 1] = 0;\r
\r
Argv++;\r
Argc--;\r
// Help option\r
//\r
Usage ();\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
} else if (stricmp (Argv[0], "-b") == 0) {\r
//\r
// Specify binary files with -b\r
Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel);\r
if (EFI_ERROR (Status)) {\r
Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
- return 1;\r
+ ReturnStatus = 1;\r
+ goto Done;\r
}\r
if (DebugLevel > 9) {\r
Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]);\r
- return 1;\r
+ ReturnStatus = 1;\r
+ goto Done;\r
}\r
if (DebugLevel>=5 && DebugLevel<=9) {\r
Options->Debug = TRUE;\r
Options->DumpOption = 1;\r
\r
Options->VendIdValid = 1;\r
- Options->DevIdValid = 1;\r
+ Options->DevIdCount = 1;\r
FileFlags = FILE_FLAG_BINARY;\r
} else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) {\r
//\r
Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
if (EFI_ERROR (Status)) {\r
Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
- return 1;\r
+ ReturnStatus = 1;\r
+ goto Done;\r
}\r
ClassCode = (UINT32) TempValue;\r
if (ClassCode & 0xFF000000) {\r
Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]);\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
}\r
if (FileList != NULL && FileList->ClassCode == 0) {\r
FileList->ClassCode = ClassCode;\r
Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
if (EFI_ERROR (Status)) {\r
Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
- return 1;\r
+ ReturnStatus = 1;\r
+ goto Done;\r
}\r
CodeRevision = (UINT32) TempValue;\r
if (CodeRevision & 0xFFFF0000) {\r
Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]);\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
}\r
if (FileList != NULL && FileList->CodeRevision == 0) {\r
FileList->CodeRevision = (UINT16) CodeRevision;\r
mOptions.Pci23 = 1;\r
} else {\r
Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]);\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
}\r
} else {\r
//\r
//\r
if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {\r
Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]);\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
}\r
//\r
// Check Efi Option RomImage\r
FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
if (FileList == NULL) {\r
Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
}\r
- \r
+\r
//\r
// set flag and class code for this image.\r
//\r
} else {\r
if (PrevFileList == NULL) {\r
PrevFileList = FileList;\r
- } else { \r
+ } else {\r
PrevFileList->Next = FileList;\r
}\r
}\r
//\r
if (Options->FileList == NULL) {\r
Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!");\r
+ //\r
+ // No memory allocation, return directly.\r
+ //\r
return STATUS_ERROR;\r
}\r
\r
if (EfiRomFlag) {\r
if (!Options->VendIdValid) {\r
Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL);\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
}\r
- \r
- if (!Options->DevIdValid) {\r
+\r
+ if (!Options->DevIdCount) {\r
Error (NULL, 0, 2000, "Missing Device ID in command line", NULL);\r
- return STATUS_ERROR;\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
}\r
}\r
\r
- return 0;\r
+ if (Options->DevIdCount > 1 && Options->Pci23) {\r
+ Error (NULL, 0, 2000, "Invalid parameter", "PCI 3.0 is required when specifying multiple Device IDs");\r
+ ReturnStatus = STATUS_ERROR;\r
+ goto Done;\r
+ }\r
+\r
+Done:\r
+ if (ReturnStatus != 0) {\r
+ while (Options->FileList != NULL) {\r
+ FileList = Options->FileList->Next;\r
+ free (Options->FileList);\r
+ Options->FileList = FileList;\r
+ }\r
+ }\r
+\r
+ return ReturnStatus;\r
}\r
\r
static\r
/*++\r
\r
Routine Description:\r
- \r
+\r
Print version information for this utility.\r
\r
Arguments:\r
Nothing.\r
--*/\r
{\r
- fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);\r
+ fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
}\r
- \r
+\r
static\r
void\r
Usage (\r
/*++\r
\r
Routine Description:\r
- \r
+\r
Print usage information for this utility.\r
\r
Arguments:\r
//\r
// Summary usage\r
//\r
- fprintf (stdout, "Usage: %s [options] [file name<s>] \n\n", UTILITY_NAME);\r
- \r
+ fprintf (stdout, "Usage: %s -f VendorId -i DeviceId [options] [file name<s>] \n\n", UTILITY_NAME);\r
+\r
//\r
// Copyright declaration\r
- // \r
- fprintf (stdout, "Copyright (c) 2007 - 2009, Intel Corporation. All rights reserved.\n\n");\r
+ //\r
+ fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");\r
\r
//\r
// Details Option\r
//\r
fprintf (stdout, "Options:\n");\r
fprintf (stdout, " -o FileName, --output FileName\n\\r
- File will be created to store the ouput content.\n");\r
+ File will be created to store the output content.\n");\r
fprintf (stdout, " -e EfiFileName\n\\r
EFI PE32 image files.\n");\r
fprintf (stdout, " -ec EfiFileName\n\\r
fprintf (stdout, " -r Rev Hex Revision in the PCI data structure header.\n");\r
fprintf (stdout, " -n Not to automatically set the LAST bit in the last file.\n");\r
fprintf (stdout, " -f VendorId\n\\r
- Hex PCI Vendor ID for the device OpROM.\n");\r
+ Hex PCI Vendor ID for the device OpROM, must be specified\n");\r
fprintf (stdout, " -i DeviceId\n\\r
- Hex PCI Device ID for the device OpROM.\n");\r
+ One or more hex PCI Device IDs for the device OpROM, must be specified\n");\r
fprintf (stdout, " -p, --pci23\n\\r
Default layout meets PCI 3.0 specifications\n\\r
specifying this flag will for a PCI 2.3 layout.\n");\r
fprintf (stdout, " -q, --quiet\n\\r
Disable all messages except FATAL ERRORS.\n");\r
fprintf (stdout, " --debug [#,0-9]\n\\r
- Enable debug messages at level #.\n"); \r
+ Enable debug messages at level #.\n");\r
}\r
\r
static\r
EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr;\r
PCI_DATA_STRUCTURE PciDs23;\r
PCI_3_0_DATA_STRUCTURE PciDs30;\r
+ UINT16 DevId;\r
\r
//\r
// Open the input file\r
//\r
- if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {\r
Error (NULL, 0, 0001, "Error opening file", InFile->FileName);\r
return ;\r
}\r
ImageCount = 0;\r
for (;;) {\r
//\r
- // Save our postition in the file, since offsets in the headers\r
+ // Save our position in the file, since offsets in the headers\r
// are relative to the particular image.\r
//\r
ImageStart = ftell (InFptr);\r
fprintf (stdout, " Device ID 0x%04X\n", PciDs30.DeviceId);\r
fprintf (stdout, " Length 0x%04X\n", PciDs30.Length);\r
fprintf (stdout, " Revision 0x%04X\n", PciDs30.Revision);\r
- fprintf (stdout, " DeviceListOffset 0x%02X\n", PciDs30.DeviceListOffset); \r
+ fprintf (stdout, " DeviceListOffset 0x%02X\n", PciDs30.DeviceListOffset);\r
+ if (PciDs30.DeviceListOffset) {\r
+ //\r
+ // Print device ID list\r
+ //\r
+ fprintf (stdout, " Device list contents\n");\r
+ if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset + PciDs30.DeviceListOffset, SEEK_SET)) {\r
+ Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI device ID list!");\r
+ goto BailOut;\r
+ }\r
+\r
+ //\r
+ // Loop until terminating 0\r
+ //\r
+ do {\r
+ if (fread (&DevId, sizeof (DevId), 1, InFptr) != 1) {\r
+ Error (NULL, 0, 3001, "Not supported", "Failed to read PCI device ID list from file %s!", InFile->FileName);\r
+ goto BailOut;\r
+ }\r
+ if (DevId) {\r
+ fprintf (stdout, " 0x%04X\n", DevId);\r
+ }\r
+ } while (DevId);\r
+\r
+ }\r
fprintf (\r
stdout,\r
" Class Code 0x%06X\n",\r
fprintf (stdout, " Code revision: 0x%04X\n", PciDs30.CodeRevision);\r
fprintf (stdout, " MaxRuntimeImageLength 0x%02X\n", PciDs30.MaxRuntimeImageLength);\r
fprintf (stdout, " ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset);\r
- fprintf (stdout, " DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset); \r
- fprintf (stdout, " Indicator 0x%02X", PciDs30.Indicator); \r
+ fprintf (stdout, " DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset);\r
+ fprintf (stdout, " Indicator 0x%02X", PciDs30.Indicator);\r
}\r
//\r
// Print the indicator, used to flag the last image\r
if (mOptions.Pci23 == 1) {\r
fprintf (stdout, " Code type 0x%02X", PciDs23.CodeType);\r
} else {\r
- fprintf (stdout, " Code type 0x%02X", PciDs30.CodeType); \r
+ fprintf (stdout, " Code type 0x%02X", PciDs30.CodeType);\r
}\r
if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
fprintf (stdout, " (EFI image)\n");\r