]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/EfiRom.c
Sync all bug fixes between EDK1.04 and EDK1.06 into EdkCompatibilityPkg.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / EfiRom / EfiRom.c
index 06a858166995fe833d40e0fcb6babf8978d77f11..cf8efc86e1b4855b9e64416a7f4daec2d3f67afa 100644 (file)
@@ -1,7 +1,7 @@
 /*++\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
@@ -41,11 +41,12 @@ Abstract:
 //\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
@@ -137,6 +138,15 @@ static STRING_LOOKUP  mSubsystemTypes[] = {
   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
@@ -353,6 +363,45 @@ BailOut:
 \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
@@ -382,11 +431,12 @@ Returns:
   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
@@ -421,34 +471,14 @@ Returns:
     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
@@ -464,47 +494,76 @@ Returns:
     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
@@ -665,9 +724,8 @@ Returns:
   //\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
@@ -729,7 +787,7 @@ Returns:
   // 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
@@ -1068,7 +1126,7 @@ Returns:
         //\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
@@ -1254,39 +1312,42 @@ Returns:
 \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
@@ -1315,8 +1376,9 @@ Returns:
   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
@@ -1382,41 +1444,35 @@ Returns:
       );\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
@@ -1450,22 +1506,45 @@ Returns:
         (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
@@ -1543,3 +1622,4 @@ Returns:
 \r
   return "unknown";\r
 }\r
+\r