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");