/*++\r
\r
-Copyright (c) 2007, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
+Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials \r
are licensed and made available under the terms and conditions of the BSD License \r
which accompanies this distribution. The full text of the license may be found at \r
http://opensource.org/licenses/bsd-license.php \r
//\r
// END include differences\r
//\r
-#include "Pci22.h" // for option ROM header structures\r
+#include "Pci.h" // for option ROM header structures\r
//\r
// Version of this utility\r
//\r
-#define UTILITY_VERSION "v2.5"\r
+#define UTILITY_NAME "EfiRom"\r
+#define UTILITY_VERSION "v2.7"\r
\r
//\r
// Define some status return values\r
0,\r
NULL\r
};\r
+\r
+static char* mCodeTypeStr[] = {\r
+ "PCAT Image",\r
+ "Open Firmware Image",\r
+ "HP PA RISC Image",\r
+ "EFI Image",\r
+ "Undefined"\r
+};\r
+\r
//\r
// Function prototypes\r
//\r
\r
return Status;\r
}\r
+ \r
+UINT8\r
+CheckSum (\r
+ UINT8 *Buffer, \r
+ UINT32 DataSize,\r
+ UINT32 PaddingSize\r
+ )\r
+/*++\r
+Routine Description:\r
+ Calculate checksum from DataSize of Buffer.\r
+\r
+Arguments:\r
+ Buffer - pointer to data buffer\r
+ DataSize - size of data buffer in bytes\r
+\r
+Return:\r
+ UINT8 - checksum\r
+--*/\r
+{\r
+ UINT8 Checksum = 0;\r
+ while (DataSize-- != 0) {\r
+ Checksum = Checksum + Buffer[DataSize];\r
+ }\r
+ while (PaddingSize-- != 0) {\r
+ Checksum = Checksum + 0xff;\r
+ }\r
+ return Checksum;\r
+}\r
+\r
+char *\r
+GetCodeTypeStr (\r
+ UINT8 CodeType\r
+ )\r
+{\r
+ if (CodeType >= sizeof (mCodeTypeStr) / sizeof (*mCodeTypeStr)) {\r
+ CodeType = sizeof (mCodeTypeStr) / sizeof (*mCodeTypeStr) - 1;\r
+ }\r
+ return mCodeTypeStr[CodeType];\r
+}\r
\r
static\r
int\r
FILE *InFptr;\r
UINT32 TotalSize;\r
UINT32 FileSize;\r
+ UINT32 DataSize;\r
+ UINT32 PaddingSize;\r
UINT8 *Buffer;\r
UINT32 Status;\r
PCI_EXPANSION_ROM_HEADER *RomHdr;\r
PCI_DATA_STRUCTURE *PciDs;\r
- UINT32 Index;\r
UINT8 ByteCheckSum;\r
\r
Status = STATUS_SUCCESS;\r
Status = STATUS_ERROR;\r
goto BailOut;\r
}\r
- //\r
- // Total size must be an even multiple of 512 bytes, and can't exceed\r
- // the option ROM image size.\r
- //\r
- TotalSize = FileSize;\r
- if (TotalSize & 0x1FF) {\r
- TotalSize = (TotalSize + 0x200) &~0x1ff;\r
- }\r
\r
- if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
- fprintf (\r
- stdout,\r
- "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",\r
- InFile->FileName,\r
- MAX_OPTION_ROM_SIZE\r
- );\r
- Status = STATUS_ERROR;\r
- goto BailOut;\r
- }\r
- //\r
- // Return the size to the caller so they can keep track of the running total.\r
- //\r
- *Size = TotalSize;\r
+ \r
+ RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;\r
+ PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);\r
\r
//\r
// Crude check to make sure it's a legitimate ROM image\r
//\r
- RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;\r
if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {\r
fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n");\r
Status = STATUS_ERROR;\r
goto BailOut;\r
}\r
\r
- PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);\r
if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {\r
fprintf (stdout, "ERROR: PCI data structure has invalid signature\n");\r
Status = STATUS_ERROR;\r
goto BailOut;\r
}\r
+\r
+ if ((UINT32) (PciDs->ImageLength * 512) == FileSize) {\r
+ //\r
+ // ImageLength reflects the actual file size correctly.\r
+ //\r
+ DataSize = FileSize - 1;\r
+ PaddingSize = 0;\r
+ TotalSize = FileSize;\r
+ } else {\r
+ //\r
+ // ImageLength doesn't reflect the actual file size,\r
+ // 1). add additional 512 bytes if actual file size is multiple of 512\r
+ // 2). add additional X (X <= 512) bytes so that the result size is multiple of 512\r
+ //\r
+ fprintf (stdout, "WARNING: ImageLength in PCI data structure != Actual File Size\n"\r
+ " --> add additional padding bytes\n"\r
+ " --> adjust ImageLength\n"\r
+ );\r
+ TotalSize = (FileSize + 0x200) & ~0x1ff;\r
+ DataSize = FileSize;\r
+ PaddingSize = TotalSize - DataSize - 1;\r
+ PciDs->ImageLength = (UINT16) (TotalSize / 512);\r
+ }\r
+\r
+ //\r
+ // Check size\r
+ //\r
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
+ fprintf (\r
+ stdout,\r
+ "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n",\r
+ InFile->FileName,\r
+ MAX_OPTION_ROM_SIZE\r
+ );\r
+ Status = STATUS_ERROR;\r
+ goto BailOut;\r
+ }\r
+\r
+ //\r
+ // Return the size to the caller so they can keep track of the running total.\r
+ //\r
+ *Size = TotalSize;\r
+\r
//\r
// If this is the last image, then set the LAST bit unless requested not\r
// to via the command-line -l argument. Otherwise, make sure you clear it.\r
//\r
if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
- PciDs->Indicator = INDICATOR_LAST;\r
+ PciDs->Indicator |= INDICATOR_LAST;\r
} else {\r
- PciDs->Indicator = 0;\r
- }\r
-\r
- ByteCheckSum = 0;\r
- for (Index = 0; Index < FileSize - 1; Index++) {\r
- ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);\r
+ PciDs->Indicator &= ~INDICATOR_LAST;\r
}\r
\r
- Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);\r
- fprintf (stdout, "CheckSUm = %02x\n", (UINT32) Buffer[FileSize - 1]);\r
+ ByteCheckSum = -CheckSum (Buffer, DataSize, PaddingSize);\r
\r
- //\r
- // Now copy the input file contents out to the output file\r
- //\r
- if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {\r
+ if (fwrite (Buffer, DataSize, 1, OutFptr) != 1) {\r
fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n");\r
Status = STATUS_ERROR;\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 (PaddingSize-- != 0) {\r
putc (~0, OutFptr);\r
- TotalSize--;\r
}\r
+ putc (ByteCheckSum, OutFptr);\r
\r
BailOut:\r
if (InFptr != NULL) {\r
//\r
// Total size must be an even multiple of 512 bytes\r
//\r
- if (TotalSize & 0x1FF) {\r
- TotalSize = (TotalSize + 0x200) &~0x1ff;\r
- }\r
+ TotalSize = (TotalSize + 0x1ff) & ~0x1ff;\r
+\r
//\r
// Check size\r
//\r
// to via the command-line -l argument.\r
//\r
if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
- PciDs.Indicator = INDICATOR_LAST;\r
+ PciDs.Indicator |= INDICATOR_LAST;\r
}\r
//\r
// Write the ROM header to the output file\r
//\r
// Specify binary files with -b\r
//\r
- FileFlags = (FileFlags &~FILE_FLAG_EFI) | FILE_FLAG_BINARY;\r
+ FileFlags = (FileFlags & ~FILE_FLAG_EFI) | FILE_FLAG_BINARY;\r
} else if ((_stricmp (Argv[0], "-e") == 0) || (_stricmp (Argv[0], "-ec") == 0)) {\r
//\r
// Specify EFI files with -e. Specify EFI-compressed with -ec.\r
\r
--*/\r
{\r
- int Index;\r
- static const char *Msg[] = {\r
- "EfiRom "UTILITY_VERSION" - Intel EFI Make Option ROM utility",\r
- " Copyright (C), 1999 - 2002 Intel Coproration\n",\r
- " Create an option ROM image from a list of input files",\r
- " Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ",\r
- " [-e|-b] [FileName(s)]",\r
- " where:",\r
- " VendorId - required hex PCI Vendor ID for the device",\r
- " DeviceId - required hex PCI Device ID for the device",\r
- " OutFileName - optional output file name. Default is the first input",\r
- " file name with a "DEFAULT_OUTPUT_EXTENSION" file extension",\r
- " FileNames - input PE32 or binary file name(s)",\r
- " BinFileName - input binary file name(s)",\r
- " -p - for verbose output",\r
- " -l - to not automatically set the LAST bit on the last file",\r
- " -b - following FileNames are binary files",\r
- " -e - following FileNames are EFI PE32 image files",\r
- " -ec - following FileNames are EFI PE32 image files, and should",\r
- " be compressed by this utility",\r
- " -cc ClassCode - to use hex ClassCode in the PCI data structure header for",\r
- " the following FileName",\r
- " -rev Revision - to use hex Revision in the PCI data structure header for",\r
- " the following FileName",\r
- " -dump - to dump the headers of an existing option ROM image",\r
- "",\r
- "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ",\r
+ int Index;\r
+ const char *Str[] = {\r
+ UTILITY_NAME" "UTILITY_VERSION" - Intel EFI Make Option ROM Utility",\r
+ " Copyright (C), 1999 - 2008 Intel Coproration",\r
+\r
+#if ( defined(UTILITY_BUILD) && defined(UTILITY_VENDOR) )\r
+ " Built from "UTILITY_BUILD", project of "UTILITY_VENDOR,\r
+#endif\r
+\r
"",\r
+ "Usage:",\r
+ " "UTILITY_NAME" [OPTION]... SOURCE ...",\r
+ "Description:",\r
+ " Create an option ROM image from a list of input files",\r
+ "Options:",\r
+ " -v VendorId - required hex PCI Vendor ID for the device",\r
+ " -d DeviceId - required hex PCI Device ID for the device",\r
+ " -o OutFileName - optional output file name. Default is the first input",\r
+ " file name with a "DEFAULT_OUTPUT_EXTENSION" file extension",\r
+ " -e SOURCE ... - input are EFI PE32 image file(s)",\r
+ " -b SOURCE ... - input are Legacy binary file(s)",\r
+ " -ec SOURCE ... - input are EFI PE32 image file(s) and should be compressed",\r
+ " -p - for verbose output",\r
+ " -l - to not automatically set the LAST bit on the last file",\r
+ " -cc ClassCode - to use hex ClassCode in the PCI data structure header for",\r
+ " the following SOURCE(s)",\r
+ " -rev Revision - to use hex Revision in the PCI data structure header for",\r
+ " the following one SOURCE",\r
+ " -dump - to dump the headers of an existing option ROM image",\r
+ "Example Usage:",\r
+ " EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi",\r
NULL\r
};\r
\r
- for (Index = 0; Msg[Index] != NULL; Index++) {\r
- fprintf (stdout, "%s\n", Msg[Index]);\r
+ for (Index = 0; Str[Index] != NULL; Index++) {\r
+ fprintf (stdout, "%s\n", Str[Index]);\r
}\r
}\r
\r
FILE *InFptr;\r
UINT32 ImageStart;\r
UINT32 ImageCount;\r
+ UINT16 DeviceId;\r
EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr;\r
- PCI_DATA_STRUCTURE PciDs;\r
+ PCI_3_0_DATA_STRUCTURE PciDs;\r
\r
//\r
// Open the input file\r
);\r
fprintf (stdout, " Vendor ID 0x%04X\n", PciDs.VendorId);\r
fprintf (stdout, " Device ID 0x%04X\n", PciDs.DeviceId);\r
+ fprintf (stdout, " Structure Length 0x%04X\n", PciDs.Length);\r
+ fprintf (stdout, " PCI Revision 0x%02X\n", PciDs.Revision);\r
fprintf (\r
stdout,\r
" Class Code 0x%06X\n",\r
(UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16))\r
);\r
fprintf (stdout, " Image size 0x%X\n", PciDs.ImageLength * 512);\r
- fprintf (stdout, " Code revision: 0x%04X\n", PciDs.CodeRevision);\r
+ fprintf (stdout, " Code revision 0x%04X\n", PciDs.CodeRevision);\r
fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs.Indicator);\r
//\r
// Print the indicator, used to flag the last image\r
//\r
- if (PciDs.Indicator == INDICATOR_LAST) {\r
+ if ((PciDs.Indicator & INDICATOR_LAST) == INDICATOR_LAST) {\r
fprintf (stdout, " (last image)\n");\r
} else {\r
fprintf (stdout, "\n");\r
}\r
+\r
//\r
// Print the code type. If EFI code, then we can provide more info.\r
//\r
- fprintf (stdout, " Code type 0x%02X", (UINT32) PciDs.CodeType);\r
+ fprintf (stdout, " Code type 0x%02X (%s)\n", (UINT32) PciDs.CodeType, GetCodeTypeStr (PciDs.CodeType));\r
if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
- fprintf (stdout, " (EFI image)\n");\r
//\r
// Re-read the header as an EFI ROM header, then dump more info\r
//\r
fprintf (stdout, " EFI ROM header contents\n");\r
- if (fseek (InFptr, ImageStart, SEEK_SET)) {\r
- fprintf (stdout, "ERROR: Failed to re-seek to ROM header structure\n");\r
- goto BailOut;\r
- }\r
-\r
- if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {\r
- fprintf (stdout, "ERROR: Failed to read EFI PCI ROM header from file\n");\r
- goto BailOut;\r
- }\r
+ memcpy (&EfiRomHdr, &PciRomHdr, sizeof (EfiRomHdr));\r
//\r
// Now dump more info\r
//\r
(UINT32) EfiRomHdr.EfiImageHeaderOffset,\r
(UINT32) (EfiRomHdr.EfiImageHeaderOffset + ImageStart)\r
);\r
-\r
- } else {\r
- //\r
- // Not an EFI image\r
- //\r
- fprintf (stdout, "\n");\r
}\r
+\r
//\r
- // If code type is EFI image, then dump it as well?\r
+ // Dump additional information for PCI 3.0 OpROM\r
//\r
- // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
- // }\r
+ if (PciDs.Revision >= 3) {\r
+ fprintf (stdout, " Extended for PCI 3.0\n");\r
+ \r
+ if (PciDs.DeviceListOffset != 0) {\r
+ if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset + PciDs.DeviceListOffset, SEEK_SET)) {\r
+ fprintf (stdout, "ERROR: Failed to seek to supported Device List\n");\r
+ goto BailOut;\r
+ }\r
+ fprintf (stdout, " Device ID List ");\r
+ while (TRUE) {\r
+ if (fread (&DeviceId, sizeof (DeviceId), 1, InFptr) != 1) {\r
+ fprintf (stdout, "ERROR: Failed to read supported DeviceId from DeviceId List\n");\r
+ goto BailOut;\r
+ }\r
+ if (DeviceId == 0) {\r
+ break;\r
+ }\r
+ fprintf (stdout, "0x%04X ", DeviceId);\r
+ }\r
+ fprintf (stdout, "\n");\r
+ }\r
+ fprintf (stdout, " Max Runtime Image Length 0x%08X\n", PciDs.MaxRuntimeImageLength * 512);\r
+ if (PciDs.Length == sizeof (PCI_3_0_DATA_STRUCTURE)) {\r
+ fprintf (stdout, " Config Utility Header 0x%04X\n", PciDs.ConfigUtilityCodeHeaderOffset);\r
+ fprintf (stdout, " DMTF CLP Entry Point 0x%04X\n", PciDs.DMTFCLPEntryPointOffset);\r
+ } else {\r
+ fprintf (stdout, "WARNING: Oprom declars 3.0 revision with wrong structure length 0x%04X\n", PciDs.Length);\r
+ }\r
+ }\r
+\r
//\r
// If last image, then we're done\r
//\r
- if (PciDs.Indicator == INDICATOR_LAST) {\r
+ if ((PciDs.Indicator & INDICATOR_LAST) == INDICATOR_LAST) {\r
goto BailOut;\r
}\r
//\r
\r
return "unknown";\r
}\r
+\r