X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=BaseTools%2FSource%2FC%2FEfiRom%2FEfiRom.c;h=0c52eb74845947de772bbfd2ebf41e5073d81ab3;hp=2e513156001298ce3516d4d32e4c84aa99e7d744;hb=fb0b35e05f772bd415fe264267bbbcde2e0accda;hpb=fb4ea38c46cf28d46efe82a000af9c4421b6cb39
diff --git a/BaseTools/Source/C/EfiRom/EfiRom.c b/BaseTools/Source/C/EfiRom/EfiRom.c
index 2e51315600..0c52eb7484 100644
--- a/BaseTools/Source/C/EfiRom/EfiRom.c
+++ b/BaseTools/Source/C/EfiRom/EfiRom.c
@@ -1,9 +1,9 @@
/** @file
Utility program to create an EFI option ROM image from binary and EFI PE32 files.
-Copyright (c) 1999 - 2016, 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
+Copyright (c) 1999 - 2018, 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
@@ -26,8 +26,8 @@ main (
/*++
Routine Description:
-
- Given an EFI image filename, create a ROM-able image by creating an option
+
+ 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.
@@ -71,11 +71,11 @@ Returns:
} 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
//
@@ -96,16 +96,24 @@ Returns:
//
if (!mOptions.OutFileName[0]) {
if (mOptions.FileList != NULL) {
- strcpy (mOptions.OutFileName, mOptions.FileList->FileName);
+ 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
//
- for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
- (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');
- Ext--
- )
- ;
+ 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
//
@@ -144,7 +152,7 @@ Returns:
VerboseMsg("Processing EFI file %s\n", FList->FileName);
}
- Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);
+ 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);
@@ -176,9 +184,6 @@ Returns:
BailOut:
if (Status == STATUS_SUCCESS) {
- if (FptrOut != NULL) {
- fclose (FptrOut);
- }
//
// Clean up our file list
//
@@ -187,13 +192,23 @@ BailOut:
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 ();
+ return GetUtilityStatus ();
}
static
@@ -206,7 +221,7 @@ ProcessBinFile (
/*++
Routine Description:
-
+
Process a binary input file.
Arguments:
@@ -232,7 +247,7 @@ Returns:
UINT32 Index;
UINT8 ByteCheckSum;
UINT16 CodeType;
-
+
PciDs23 = NULL;
PciDs30 = NULL;
Status = STATUS_SUCCESS;
@@ -241,7 +256,7 @@ Returns:
// Try to open the input file
//
if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
- Error (NULL, 0, 0001, "Error opening file", InFile->FileName);
+ Error (NULL, 0, 0001, "Error opening file", "%s", InFile->FileName);
return STATUS_ERROR;
}
//
@@ -336,7 +351,7 @@ Returns:
} else {
PciDs30->ImageLength = (UINT16) (TotalSize / 512);
CodeType = PciDs30->CodeType;
- }
+ }
//
// If this is the last image, then set the LAST bit unless requested not
@@ -347,13 +362,13 @@ Returns:
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) {
@@ -416,7 +431,7 @@ ProcessEfiFile (
/*++
Routine Description:
-
+
Process a PE32 EFI file.
Arguments:
@@ -450,6 +465,7 @@ Returns:
UINT32 HeaderPadBytes;
UINT32 PadBytesBeforeImage;
UINT32 PadBytesAfterImage;
+ UINT32 DevIdListSize;
//
// Try to open the input file
@@ -486,14 +502,23 @@ Returns:
} 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 {
- HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
+ 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) {
@@ -575,7 +600,7 @@ Returns:
// 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);
+ 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;
}
@@ -630,7 +655,14 @@ Returns:
PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
PciDs30.VendorId = VendId;
PciDs30.DeviceId = DevId;
- PciDs30.DeviceListOffset = 0; // to be fixed
+ 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;
//
@@ -653,12 +685,12 @@ Returns:
if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
if (mOptions.Pci23 == 1) {
PciDs23.Indicator = INDICATOR_LAST;
- } else {
+ } else {
PciDs30.Indicator = INDICATOR_LAST;}
} else {
if (mOptions.Pci23 == 1) {
PciDs23.Indicator = 0;
- } else {
+ } else {
PciDs30.Indicator = 0;
}
}
@@ -691,15 +723,35 @@ Returns:
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
//
@@ -767,7 +819,7 @@ CheckPE32File (
/*++
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.
@@ -859,7 +911,7 @@ ParseCommandLine (
/*++
Routine Description:
-
+
Given the Argc/Argv program arguments, and a pointer to an options structure,
parse the command-line options and check their validity.
@@ -886,6 +938,8 @@ Returns:
INTN ReturnStatus;
BOOLEAN EfiRomFlag;
UINT64 TempValue;
+ char *OptionName;
+ UINT16 *DevIdList;
ReturnStatus = 0;
FileFlags = 0;
@@ -901,6 +955,9 @@ Returns:
//
FileList = PrevFileList = NULL;
+ Options->DevIdList = NULL;
+ Options->DevIdCount = 0;
+
ClassCode = 0;
CodeRevision = 0;
//
@@ -916,12 +973,12 @@ Returns:
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;
@@ -956,26 +1013,53 @@ Returns:
Argv++;
Argc--;
} else if (stricmp (Argv[0], "-i") == 0) {
+
+ OptionName = Argv[0];
+
//
- // Device ID specified with -i
- // Make sure there's another parameter
+ // Device IDs specified with -i
+ // Make sure there's at least one more parameter
//
- Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
- if (EFI_ERROR (Status)) {
- Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
+ if (Argc < 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Missing Device Id with %s option!", OptionName);
ReturnStatus = 1;
goto Done;
}
- if (TempValue >= 0x10000) {
- Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);
- 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--;
}
- Options->DevId = (UINT16) TempValue;
- Options->DevIdValid = 1;
- Argv++;
- Argc--;
} else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) {
//
// Output filename specified with -o
@@ -1056,7 +1140,7 @@ Returns:
Options->DumpOption = 1;
Options->VendIdValid = 1;
- Options->DevIdValid = 1;
+ Options->DevIdCount = 1;
FileFlags = FILE_FLAG_BINARY;
} else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) {
//
@@ -1138,7 +1222,7 @@ Returns:
ReturnStatus = STATUS_ERROR;
goto Done;
}
-
+
//
// set flag and class code for this image.
//
@@ -1155,7 +1239,7 @@ Returns:
} else {
if (PrevFileList == NULL) {
PrevFileList = FileList;
- } else {
+ } else {
PrevFileList->Next = FileList;
}
}
@@ -1189,14 +1273,20 @@ Returns:
ReturnStatus = STATUS_ERROR;
goto Done;
}
-
- if (!Options->DevIdValid) {
+
+ 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) {
@@ -1217,7 +1307,7 @@ Version (
/*++
Routine Description:
-
+
Print version information for this utility.
Arguments:
@@ -1231,7 +1321,7 @@ Returns:
{
fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
}
-
+
static
void
Usage (
@@ -1240,7 +1330,7 @@ Usage (
/*++
Routine Description:
-
+
Print usage information for this utility.
Arguments:
@@ -1257,11 +1347,11 @@ Returns:
// Summary usage
//
fprintf (stdout, "Usage: %s -f VendorId -i DeviceId [options] [file name] \n\n", UTILITY_NAME);
-
+
//
// Copyright declaration
- //
- fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
+ //
+ fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
//
// Details Option
@@ -1282,7 +1372,7 @@ Returns:
fprintf (stdout, " -f VendorId\n\
Hex PCI Vendor ID for the device OpROM, must be specified\n");
fprintf (stdout, " -i DeviceId\n\
- Hex PCI Device ID for the device OpROM, must be specified\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");
@@ -1296,7 +1386,7 @@ Returns:
fprintf (stdout, " -q, --quiet\n\
Disable all messages except FATAL ERRORS.\n");
fprintf (stdout, " --debug [#,0-9]\n\
- Enable debug messages at level #.\n");
+ Enable debug messages at level #.\n");
}
static
@@ -1327,6 +1417,7 @@ Returns:
EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr;
PCI_DATA_STRUCTURE PciDs23;
PCI_3_0_DATA_STRUCTURE PciDs30;
+ UINT16 DevId;
//
// Open the input file
@@ -1341,7 +1432,7 @@ Returns:
ImageCount = 0;
for (;;) {
//
- // Save our postition in the file, since offsets in the headers
+ // Save our position in the file, since offsets in the headers
// are relative to the particular image.
//
ImageStart = ftell (InFptr);
@@ -1424,7 +1515,31 @@ Returns:
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);
+ 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",
@@ -1434,8 +1549,8 @@ Returns:
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);
+ fprintf (stdout, " DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset);
+ fprintf (stdout, " Indicator 0x%02X", PciDs30.Indicator);
}
//
// Print the indicator, used to flag the last image
@@ -1451,7 +1566,7 @@ Returns:
if (mOptions.Pci23 == 1) {
fprintf (stdout, " Code type 0x%02X", PciDs23.CodeType);
} else {
- fprintf (stdout, " Code type 0x%02X", PciDs30.CodeType);
+ 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");