]> git.proxmox.com Git - mirror_edk2.git/blobdiff - EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/EfiRom.c
1) Sync EdkCompatibilityPkg with EDK 1.04. The changes includes:
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / EfiRom / EfiRom.c
index 06a858166995fe833d40e0fcb6babf8978d77f11..f5ab9ff234af3858e490081d9bc9f4c6e1bf0ac9 100644 (file)
@@ -41,11 +41,11 @@ 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_VERSION "v2.6"\r
 \r
 //\r
 // Define some status return values\r
@@ -137,6 +137,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 +362,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 +430,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 +470,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 +493,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
+    PciDs->Indicator &= ~INDICATOR_LAST;\r
   }\r
 \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
-  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 +723,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 +786,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 +1125,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
@@ -1280,7 +1337,7 @@ Returns:
     "                       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
+    "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi",\r
     "",\r
     NULL\r
   };\r
@@ -1315,8 +1372,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 +1440,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 +1502,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 +1618,4 @@ Returns:
 \r
   return "unknown";\r
 }\r
+\r