]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/EfiRom/EfiRom.c
BaseTools: Various typo
[mirror_edk2.git] / BaseTools / Source / C / EfiRom / EfiRom.c
index 9f71b19323e9eea951bf984691e5cc73aa97c2bd..0c52eb74845947de772bbfd2ebf41e5073d81ab3 100644 (file)
@@ -1,23 +1,15 @@
 /** @file\r
 /** @file\r
+Utility program to create an EFI option ROM image from binary and EFI PE32 files.\r
 \r
 \r
-Copyright (c) 1999 - 2010, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials are licensed and made available \r
-under the terms and conditions of the BSD License which accompanies this \r
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials are licensed and made available\r
+under the terms and conditions of the BSD License which accompanies this\r
 distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
 \r
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
 distribution.  The full text of the license may be found at\r
 http://opensource.org/licenses/bsd-license.php\r
 \r
 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
 \r
-Module Name:\r
-\r
-  EfiRom.c\r
-  \r
-Abstract:\r
-\r
-  Utility program to create an EFI option ROM image from binary and \r
-  EFI PE32 files.\r
-\r
 **/\r
 \r
 #include "EfiUtilityMsgs.h"\r
 **/\r
 \r
 #include "EfiUtilityMsgs.h"\r
@@ -34,8 +26,8 @@ main (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
-  Given an EFI image filename, create a ROM-able image by creating an option \r
+\r
+  Given an EFI image filename, create a ROM-able image by creating an option\r
   ROM header and PCI data structure, filling them in, and then writing the\r
   option ROM header + PCI data structure + EFI image out to the output file.\r
 \r
   ROM header and PCI data structure, filling them in, and then writing the\r
   option ROM header + PCI data structure + EFI image out to the output file.\r
 \r
@@ -79,11 +71,11 @@ Returns:
   } else if (mOptions.Debug) {\r
     SetPrintLevel(DebugLevel);\r
   }\r
   } else if (mOptions.Debug) {\r
     SetPrintLevel(DebugLevel);\r
   }\r
-  \r
+\r
   if (mOptions.Verbose) {\r
     VerboseMsg("%s tool start.\n", UTILITY_NAME);\r
   }\r
   if (mOptions.Verbose) {\r
     VerboseMsg("%s tool start.\n", UTILITY_NAME);\r
   }\r
-  \r
+\r
   //\r
   // If dumping an image, then do that and quit\r
   //\r
   //\r
   // If dumping an image, then do that and quit\r
   //\r
@@ -103,24 +95,34 @@ Returns:
   // the command line, or the first input filename with a different extension.\r
   //\r
   if (!mOptions.OutFileName[0]) {\r
   // the command line, or the first input filename with a different extension.\r
   //\r
   if (!mOptions.OutFileName[0]) {\r
-    strcpy (mOptions.OutFileName, mOptions.FileList->FileName);\r
-    //\r
-    // Find the last . on the line and replace the filename extension with\r
-    // the default\r
-    //\r
-    for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
-         (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');\r
-         Ext--\r
-        )\r
-      ;\r
-    //\r
-    // If dot here, then insert extension here, otherwise append\r
-    //\r
-    if (*Ext != '.') {\r
-      Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);\r
-    }\r
+    if (mOptions.FileList != NULL) {\r
+      if (strlen (mOptions.FileList->FileName) >= MAX_PATH) {\r
+        Status = STATUS_ERROR;\r
+        Error (NULL, 0, 2000, "Invalid parameter", "Input file name is too long - %s.", mOptions.FileList->FileName);\r
+        goto BailOut;\r
+      }\r
+      strncpy (mOptions.OutFileName, mOptions.FileList->FileName, MAX_PATH - 1);\r
+      mOptions.OutFileName[MAX_PATH - 1] = 0;\r
+      //\r
+      // Find the last . on the line and replace the filename extension with\r
+      // the default\r
+      //\r
+      Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
+      while (Ext >= mOptions.OutFileName) {\r
+        if ((*Ext == '.') || (*Ext == '\\')) {\r
+          break;\r
+        }\r
+        Ext--;\r
+      }\r
+      //\r
+      // If dot here, then insert extension here, otherwise append\r
+      //\r
+      if (*Ext != '.') {\r
+        Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);\r
+      }\r
 \r
 \r
-    strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);\r
+      strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);\r
+    }\r
   }\r
   //\r
   // Make sure we don't have the same filename for input and output files\r
   }\r
   //\r
   // Make sure we don't have the same filename for input and output files\r
@@ -128,14 +130,14 @@ Returns:
   for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {\r
     if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {\r
       Status = STATUS_ERROR;\r
   for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {\r
     if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {\r
       Status = STATUS_ERROR;\r
-      Error (NULL, 0, 1002, "Invalid input paramter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName);\r
+      Error (NULL, 0, 1002, "Invalid input parameter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName);\r
       goto BailOut;\r
     }\r
   }\r
   //\r
   // Now open our output file\r
   //\r
       goto BailOut;\r
     }\r
   }\r
   //\r
   // Now open our output file\r
   //\r
-  if ((FptrOut = fopen (mOptions.OutFileName, "wb")) == NULL) {\r
+  if ((FptrOut = fopen (LongFilePath (mOptions.OutFileName), "wb")) == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", mOptions.OutFileName);\r
     goto BailOut;\r
   }\r
     Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", mOptions.OutFileName);\r
     goto BailOut;\r
   }\r
@@ -150,7 +152,7 @@ Returns:
         VerboseMsg("Processing EFI file    %s\n", FList->FileName);\r
       }\r
 \r
         VerboseMsg("Processing EFI file    %s\n", FList->FileName);\r
       }\r
 \r
-      Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);\r
+      Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevIdList[0], &Size);\r
     } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) {\r
       if (mOptions.Verbose) {\r
         VerboseMsg("Processing binary file %s\n", FList->FileName);\r
     } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) {\r
       if (mOptions.Verbose) {\r
         VerboseMsg("Processing binary file %s\n", FList->FileName);\r
@@ -176,15 +178,12 @@ Returns:
   // Check total size\r
   //\r
   if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
   // Check total size\r
   //\r
   if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
-    Error (NULL, 0, 2000, "Invalid paramter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE);\r
+    Error (NULL, 0, 2000, "Invalid parameter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE);\r
     Status = STATUS_ERROR;\r
   }\r
 \r
 BailOut:\r
   if (Status == STATUS_SUCCESS) {\r
     Status = STATUS_ERROR;\r
   }\r
 \r
 BailOut:\r
   if (Status == STATUS_SUCCESS) {\r
-    if (FptrOut != NULL) {\r
-      fclose (FptrOut);\r
-    }\r
     //\r
     // Clean up our file list\r
     //\r
     //\r
     // Clean up our file list\r
     //\r
@@ -193,13 +192,23 @@ BailOut:
       free (mOptions.FileList);\r
       mOptions.FileList = FList;\r
     }\r
       free (mOptions.FileList);\r
       mOptions.FileList = FList;\r
     }\r
+\r
+    //\r
+    // Clean up device ID list\r
+    //\r
+    if (mOptions.DevIdList != NULL) {\r
+      free (mOptions.DevIdList);\r
+    }\r
+  }\r
+  if (FptrOut != NULL) {\r
+    fclose (FptrOut);\r
   }\r
 \r
   if (mOptions.Verbose) {\r
     VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());\r
   }\r
 \r
   }\r
 \r
   if (mOptions.Verbose) {\r
     VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());\r
   }\r
 \r
-  return GetUtilityStatus (); \r
+  return GetUtilityStatus ();\r
 }\r
 \r
 static\r
 }\r
 \r
 static\r
@@ -212,7 +221,7 @@ ProcessBinFile (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   Process a binary input file.\r
 \r
 Arguments:\r
   Process a binary input file.\r
 \r
 Arguments:\r
@@ -237,7 +246,8 @@ Returns:
   PCI_3_0_DATA_STRUCTURE    *PciDs30;\r
   UINT32                    Index;\r
   UINT8                     ByteCheckSum;\r
   PCI_3_0_DATA_STRUCTURE    *PciDs30;\r
   UINT32                    Index;\r
   UINT8                     ByteCheckSum;\r
\r
+  UINT16                    CodeType;\r
+\r
   PciDs23 = NULL;\r
   PciDs30 = NULL;\r
   Status = STATUS_SUCCESS;\r
   PciDs23 = NULL;\r
   PciDs30 = NULL;\r
   Status = STATUS_SUCCESS;\r
@@ -245,8 +255,8 @@ Returns:
   //\r
   // Try to open the input file\r
   //\r
   //\r
   // Try to open the input file\r
   //\r
-  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
-    Error (NULL, 0, 0001, "Error opening file", InFile->FileName);\r
+  if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {\r
+    Error (NULL, 0, 0001, "Error opening file", "%s", InFile->FileName);\r
     return STATUS_ERROR;\r
   }\r
   //\r
     return STATUS_ERROR;\r
   }\r
   //\r
@@ -337,9 +347,11 @@ Returns:
   //\r
   if (mOptions.Pci23 == 1) {\r
     PciDs23->ImageLength = (UINT16) (TotalSize / 512);\r
   //\r
   if (mOptions.Pci23 == 1) {\r
     PciDs23->ImageLength = (UINT16) (TotalSize / 512);\r
+    CodeType = PciDs23->CodeType;\r
   } else {\r
     PciDs30->ImageLength = (UINT16) (TotalSize / 512);\r
   } else {\r
     PciDs30->ImageLength = (UINT16) (TotalSize / 512);\r
-       }\r
+    CodeType = PciDs30->CodeType;\r
+  }\r
 \r
   //\r
   // If this is the last image, then set the LAST bit unless requested not\r
 \r
   //\r
   // If this is the last image, then set the LAST bit unless requested not\r
@@ -350,23 +362,25 @@ Returns:
       PciDs23->Indicator = INDICATOR_LAST;\r
     } else {\r
       PciDs30->Indicator = INDICATOR_LAST;\r
       PciDs23->Indicator = INDICATOR_LAST;\r
     } else {\r
       PciDs30->Indicator = INDICATOR_LAST;\r
-               }\r
+    }\r
   } else {\r
     if (mOptions.Pci23 == 1) {\r
       PciDs23->Indicator = 0;\r
     } else {\r
       PciDs30->Indicator = 0;\r
   } else {\r
     if (mOptions.Pci23 == 1) {\r
       PciDs23->Indicator = 0;\r
     } else {\r
       PciDs30->Indicator = 0;\r
-               }\r
+    }\r
   }\r
 \r
   }\r
 \r
-  ByteCheckSum = 0;\r
-  for (Index = 0; Index < FileSize - 1; Index++) {\r
-    ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);\r
-  }\r
+  if (CodeType != PCI_CODE_TYPE_EFI_IMAGE) {\r
+    ByteCheckSum = 0;\r
+    for (Index = 0; Index < FileSize - 1; Index++) {\r
+      ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);\r
+    }\r
 \r
 \r
-  Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);\r
-  if (mOptions.Verbose) {\r
-    VerboseMsg("  Checksum = %02x\n\n", Buffer[FileSize - 1]);\r
+    Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);\r
+    if (mOptions.Verbose) {\r
+      VerboseMsg("  Checksum = %02x\n\n", Buffer[FileSize - 1]);\r
+    }\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -417,7 +431,7 @@ ProcessEfiFile (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   Process a PE32 EFI file.\r
 \r
 Arguments:\r
   Process a PE32 EFI file.\r
 \r
 Arguments:\r
@@ -449,11 +463,14 @@ Returns:
   UINT16                        MachineType;\r
   UINT16                        SubSystem;\r
   UINT32                        HeaderPadBytes;\r
   UINT16                        MachineType;\r
   UINT16                        SubSystem;\r
   UINT32                        HeaderPadBytes;\r
+  UINT32                        PadBytesBeforeImage;\r
+  UINT32                        PadBytesAfterImage;\r
+  UINT32                        DevIdListSize;\r
 \r
   //\r
   // Try to open the input file\r
   //\r
 \r
   //\r
   // Try to open the input file\r
   //\r
-  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+  if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {\r
     Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", InFile->FileName);\r
     return STATUS_ERROR;\r
   }\r
     Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", InFile->FileName);\r
     return STATUS_ERROR;\r
   }\r
@@ -485,14 +502,23 @@ Returns:
   } else {\r
     HeaderPadBytes = 0;\r
   }\r
   } else {\r
     HeaderPadBytes = 0;\r
   }\r
-  \r
+\r
   //\r
   // For Pci3.0 to use the different data structure.\r
   //\r
   if (mOptions.Pci23 == 1) {\r
     HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
   } else {\r
   //\r
   // For Pci3.0 to use the different data structure.\r
   //\r
   if (mOptions.Pci23 == 1) {\r
     HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
   } else {\r
-    HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
+    if (mOptions.DevIdCount > 1) {\r
+      //\r
+      // Write device ID list when more than one device ID is specified.\r
+      // Leave space for list plus terminator.\r
+      //\r
+      DevIdListSize = (mOptions.DevIdCount + 1) * sizeof (UINT16);\r
+    } else {\r
+      DevIdListSize = 0;\r
+    }\r
+    HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + DevIdListSize + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);\r
   }\r
 \r
   if (mOptions.Verbose) {\r
   }\r
 \r
   if (mOptions.Verbose) {\r
@@ -559,10 +585,22 @@ Returns:
     TotalSize = (TotalSize + 0x200) &~0x1ff;\r
   }\r
   //\r
     TotalSize = (TotalSize + 0x200) &~0x1ff;\r
   }\r
   //\r
+  // Workaround:\r
+  //   If compressed, put the pad bytes after the image,\r
+  //   else put the pad bytes before the image.\r
+  //\r
+  if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) {\r
+    PadBytesBeforeImage = 0;\r
+    PadBytesAfterImage = TotalSize - (FileSize + HeaderSize);\r
+  } else {\r
+    PadBytesBeforeImage = TotalSize - (FileSize + HeaderSize);\r
+    PadBytesAfterImage = 0;\r
+  }\r
+  //\r
   // Check size\r
   //\r
   if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
   // Check size\r
   //\r
   if (TotalSize > MAX_OPTION_ROM_SIZE) {\r
-    Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);  \r
+    Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);\r
     Status = STATUS_ERROR;\r
     goto BailOut;\r
   }\r
     Status = STATUS_ERROR;\r
     goto BailOut;\r
   }\r
@@ -581,7 +619,7 @@ Returns:
   RomHdr.EfiSignature         = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;\r
   RomHdr.EfiSubsystem         = SubSystem;\r
   RomHdr.EfiMachineType       = MachineType;\r
   RomHdr.EfiSignature         = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;\r
   RomHdr.EfiSubsystem         = SubSystem;\r
   RomHdr.EfiMachineType       = MachineType;\r
-  RomHdr.EfiImageHeaderOffset = (UINT16) HeaderSize;\r
+  RomHdr.EfiImageHeaderOffset = (UINT16) (HeaderSize + PadBytesBeforeImage);\r
   RomHdr.PcirOffset           = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);\r
   //\r
   // Set image as compressed or not\r
   RomHdr.PcirOffset           = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);\r
   //\r
   // Set image as compressed or not\r
@@ -617,7 +655,14 @@ Returns:
     PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE;\r
     PciDs30.VendorId  = VendId;\r
     PciDs30.DeviceId  = DevId;\r
     PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE;\r
     PciDs30.VendorId  = VendId;\r
     PciDs30.DeviceId  = DevId;\r
-    PciDs30.DeviceListOffset = 0; // to be fixed\r
+    if (mOptions.DevIdCount > 1) {\r
+      //\r
+      // Place device list immediately after PCI structure\r
+      //\r
+      PciDs30.DeviceListOffset = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);\r
+    } else {\r
+      PciDs30.DeviceListOffset = 0;\r
+    }\r
     PciDs30.Length    = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);\r
     PciDs30.Revision  = 0x3;\r
     //\r
     PciDs30.Length    = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);\r
     PciDs30.Revision  = 0x3;\r
     //\r
@@ -640,12 +685,12 @@ Returns:
   if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
     if (mOptions.Pci23 == 1) {\r
       PciDs23.Indicator = INDICATOR_LAST;\r
   if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {\r
     if (mOptions.Pci23 == 1) {\r
       PciDs23.Indicator = INDICATOR_LAST;\r
-         } else {\r
+    } else {\r
     PciDs30.Indicator = INDICATOR_LAST;}\r
   } else {\r
     if (mOptions.Pci23 == 1) {\r
       PciDs23.Indicator = 0;\r
     PciDs30.Indicator = INDICATOR_LAST;}\r
   } else {\r
     if (mOptions.Pci23 == 1) {\r
       PciDs23.Indicator = 0;\r
-       } else {\r
+  } else {\r
       PciDs30.Indicator = 0;\r
     }\r
   }\r
       PciDs30.Indicator = 0;\r
     }\r
   }\r
@@ -678,19 +723,46 @@ Returns:
       Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);\r
       Status = STATUS_ERROR;\r
       goto BailOut;\r
       Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);\r
       Status = STATUS_ERROR;\r
       goto BailOut;\r
-    } \r
+    }\r
   } else {\r
     if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) {\r
       Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);\r
       Status = STATUS_ERROR;\r
       goto BailOut;\r
   } else {\r
     if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) {\r
       Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);\r
       Status = STATUS_ERROR;\r
       goto BailOut;\r
-    } \r
+    }\r
   }\r
   }\r
+\r
   //\r
   //\r
-  // Keep track of how many bytes left to write\r
+  // Write the Device ID list to the output file\r
   //\r
   //\r
-  TotalSize -= HeaderSize;\r
+  if (mOptions.DevIdCount > 1) {\r
+    if (fwrite (mOptions.DevIdList, sizeof (UINT16), mOptions.DevIdCount, OutFptr) != mOptions.DevIdCount) {\r
+      Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL);\r
+      Status = STATUS_ERROR;\r
+      goto BailOut;\r
+    }\r
+    //\r
+    // Write two-byte terminating 0 at the end of the device list\r
+    //\r
+    if (putc (0, OutFptr) == EOF || putc (0, OutFptr) == EOF) {\r
+      Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL);\r
+      Status = STATUS_ERROR;\r
+      goto BailOut;\r
+    }\r
+  }\r
 \r
 \r
+\r
+  //\r
+  // Pad head to make it a multiple of 512 bytes\r
+  //\r
+  while (PadBytesBeforeImage > 0) {\r
+    if (putc (~0, OutFptr) == EOF) {\r
+      Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);\r
+      Status = STATUS_ERROR;\r
+      goto BailOut;\r
+    }\r
+    PadBytesBeforeImage--;\r
+  }\r
   //\r
   // Now dump the input file's contents to the output file\r
   //\r
   //\r
   // Now dump the input file's contents to the output file\r
   //\r
@@ -700,18 +772,17 @@ Returns:
     goto BailOut;\r
   }\r
 \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
   //\r
   // Pad the rest of the image to make it a multiple of 512 bytes\r
   //\r
-  while (TotalSize > 0) {\r
+  while (PadBytesAfterImage > 0) {\r
     if (putc (~0, OutFptr) == EOF) {\r
       Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);\r
       Status = STATUS_ERROR;\r
       goto BailOut;\r
     }\r
 \r
     if (putc (~0, OutFptr) == EOF) {\r
       Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);\r
       Status = STATUS_ERROR;\r
       goto BailOut;\r
     }\r
 \r
-    TotalSize--;\r
+    PadBytesAfterImage--;\r
   }\r
 \r
 BailOut:\r
   }\r
 \r
 BailOut:\r
@@ -748,7 +819,7 @@ CheckPE32File (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
   PE32 image file, and then return the machine type in the supplied pointer.\r
 \r
   Given a file pointer to a supposed PE32 image file, verify that it is indeed a\r
   PE32 image file, and then return the machine type in the supplied pointer.\r
 \r
@@ -840,7 +911,7 @@ ParseCommandLine (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   Given the Argc/Argv program arguments, and a pointer to an options structure,\r
   parse the command-line options and check their validity.\r
 \r
   Given the Argc/Argv program arguments, and a pointer to an options structure,\r
   parse the command-line options and check their validity.\r
 \r
@@ -864,9 +935,13 @@ Returns:
   UINT32    ClassCode;\r
   UINT32    CodeRevision;\r
   EFI_STATUS Status;\r
   UINT32    ClassCode;\r
   UINT32    CodeRevision;\r
   EFI_STATUS Status;\r
+  INTN       ReturnStatus;\r
   BOOLEAN    EfiRomFlag;\r
   UINT64     TempValue;\r
   BOOLEAN    EfiRomFlag;\r
   UINT64     TempValue;\r
+  char       *OptionName;\r
+  UINT16     *DevIdList;\r
 \r
 \r
+  ReturnStatus = 0;\r
   FileFlags = 0;\r
   EfiRomFlag = FALSE;\r
 \r
   FileFlags = 0;\r
   EfiRomFlag = FALSE;\r
 \r
@@ -880,6 +955,9 @@ Returns:
   //\r
   FileList                = PrevFileList = NULL;\r
 \r
   //\r
   FileList                = PrevFileList = NULL;\r
 \r
+  Options->DevIdList      = NULL;\r
+  Options->DevIdCount     = 0;\r
+\r
   ClassCode               = 0;\r
   CodeRevision            = 0;\r
   //\r
   ClassCode               = 0;\r
   CodeRevision            = 0;\r
   //\r
@@ -895,12 +973,12 @@ Returns:
     Usage ();\r
     return STATUS_ERROR;\r
   }\r
     Usage ();\r
     return STATUS_ERROR;\r
   }\r
-  \r
+\r
   if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) {\r
     Usage();\r
     return STATUS_ERROR;\r
   }\r
   if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) {\r
     Usage();\r
     return STATUS_ERROR;\r
   }\r
-  \r
+\r
   if ((stricmp(Argv[0], "--version") == 0)) {\r
     Version();\r
     return STATUS_ERROR;\r
   if ((stricmp(Argv[0], "--version") == 0)) {\r
     Version();\r
     return STATUS_ERROR;\r
@@ -921,11 +999,13 @@ Returns:
         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
-          return 1;\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         if (TempValue >= 0x10000) {\r
           Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]);\r
         }\r
         if (TempValue >= 0x10000) {\r
           Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]);\r
-          return 1;\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         Options->VendId       = (UINT16) TempValue;\r
         Options->VendIdValid  = 1;\r
         }\r
         Options->VendId       = (UINT16) TempValue;\r
         Options->VendIdValid  = 1;\r
@@ -933,24 +1013,53 @@ Returns:
         Argv++;\r
         Argc--;\r
       } else if (stricmp (Argv[0], "-i") == 0) {\r
         Argv++;\r
         Argc--;\r
       } else if (stricmp (Argv[0], "-i") == 0) {\r
+\r
+        OptionName = Argv[0];\r
+\r
         //\r
         //\r
-        // Device ID specified with -i\r
-        // Make sure there's another parameter\r
+        // Device IDs specified with -i\r
+        // Make sure there's at least one more parameter\r
         //\r
         //\r
-        Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
-        if (EFI_ERROR (Status)) {\r
-          Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
-          return 1;\r
+        if (Argc < 1) {\r
+          Error (NULL, 0, 2000, "Invalid parameter", "Missing Device Id with %s option!", OptionName);\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         }\r
-        if (TempValue >= 0x10000) {\r
-          Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);\r
-          return 1;\r
+\r
+        //\r
+        // Process until another dash-argument parameter or the end of the list\r
+        //\r
+        while (Argc > 1 && Argv[1][0] != '-') {\r
+          Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
+          if (EFI_ERROR (Status)) {\r
+            Error (NULL, 0, 2000, "Invalid option value", "%s = %s", OptionName, Argv[1]);\r
+            ReturnStatus = 1;\r
+            goto Done;\r
+          }\r
+          //\r
+          // Don't allow device IDs greater than 16 bits\r
+          // Don't allow 0, since it is used as a list terminator\r
+          //\r
+          if (TempValue >= 0x10000 || TempValue == 0) {\r
+            Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);\r
+            ReturnStatus = 1;\r
+            goto Done;\r
+          }\r
+\r
+          DevIdList = (UINT16*) realloc (Options->DevIdList, (Options->DevIdCount + 1) * sizeof (UINT16));\r
+          if (DevIdList == NULL) {\r
+            Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);\r
+            ReturnStatus = 1;\r
+            goto Done;\r
+          }\r
+          Options->DevIdList = DevIdList;\r
+\r
+          Options->DevIdList[Options->DevIdCount++] = (UINT16) TempValue;\r
+\r
+          Argv++;\r
+          Argc--;\r
         }\r
         }\r
-        Options->DevId      = (UINT16) TempValue;\r
-        Options->DevIdValid = 1;\r
 \r
 \r
-        Argv++;\r
-        Argc--;\r
       } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) {\r
         //\r
         // Output filename specified with -o\r
       } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) {\r
         //\r
         // Output filename specified with -o\r
@@ -958,9 +1067,16 @@ Returns:
         //\r
         if (Argv[1] == NULL || Argv[1][0] == '-') {\r
           Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]);\r
         //\r
         if (Argv[1] == NULL || Argv[1][0] == '-') {\r
           Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]);\r
-          return STATUS_ERROR;\r
+          ReturnStatus = STATUS_ERROR;\r
+          goto Done;\r
         }\r
         }\r
-        strcpy (Options->OutFileName, Argv[1]);\r
+        if (strlen (Argv[1]) > MAX_PATH - 1) {\r
+          Error (NULL, 0, 2000, "Invalid parameter", "Output file name %s is too long!", Argv[1]);\r
+          ReturnStatus = STATUS_ERROR;\r
+          goto Done;\r
+        }\r
+        strncpy (Options->OutFileName, Argv[1], MAX_PATH - 1);\r
+        Options->OutFileName[MAX_PATH - 1] = 0;\r
 \r
         Argv++;\r
         Argc--;\r
 \r
         Argv++;\r
         Argc--;\r
@@ -969,7 +1085,8 @@ Returns:
         // Help option\r
         //\r
         Usage ();\r
         // Help option\r
         //\r
         Usage ();\r
-        return STATUS_ERROR;\r
+        ReturnStatus = STATUS_ERROR;\r
+        goto Done;\r
       } else if (stricmp (Argv[0], "-b") == 0) {\r
         //\r
         // Specify binary files with -b\r
       } else if (stricmp (Argv[0], "-b") == 0) {\r
         //\r
         // Specify binary files with -b\r
@@ -997,11 +1114,13 @@ Returns:
         Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
         Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
-          return 1;\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         if (DebugLevel > 9)  {\r
           Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]);\r
         }\r
         if (DebugLevel > 9)  {\r
           Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]);\r
-          return 1;\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         if (DebugLevel>=5 && DebugLevel<=9) {\r
           Options->Debug = TRUE;\r
         }\r
         if (DebugLevel>=5 && DebugLevel<=9) {\r
           Options->Debug = TRUE;\r
@@ -1021,7 +1140,7 @@ Returns:
         Options->DumpOption   = 1;\r
 \r
         Options->VendIdValid  = 1;\r
         Options->DumpOption   = 1;\r
 \r
         Options->VendIdValid  = 1;\r
-        Options->DevIdValid   = 1;\r
+        Options->DevIdCount   = 1;\r
         FileFlags             = FILE_FLAG_BINARY;\r
       } else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) {\r
         //\r
         FileFlags             = FILE_FLAG_BINARY;\r
       } else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) {\r
         //\r
@@ -1031,12 +1150,14 @@ Returns:
         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
-          return 1;\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         ClassCode = (UINT32) TempValue;\r
         if (ClassCode & 0xFF000000) {\r
           Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]);\r
         }\r
         ClassCode = (UINT32) TempValue;\r
         if (ClassCode & 0xFF000000) {\r
           Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]);\r
-          return STATUS_ERROR;\r
+          ReturnStatus = STATUS_ERROR;\r
+          goto Done;\r
         }\r
         if (FileList != NULL && FileList->ClassCode == 0) {\r
           FileList->ClassCode = ClassCode;\r
         }\r
         if (FileList != NULL && FileList->ClassCode == 0) {\r
           FileList->ClassCode = ClassCode;\r
@@ -1052,12 +1173,14 @@ Returns:
         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
         Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);\r
         if (EFI_ERROR (Status)) {\r
           Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);\r
-          return 1;\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         CodeRevision = (UINT32) TempValue;\r
         if (CodeRevision & 0xFFFF0000) {\r
           Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]);\r
         }\r
         CodeRevision = (UINT32) TempValue;\r
         if (CodeRevision & 0xFFFF0000) {\r
           Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]);\r
-          return STATUS_ERROR;\r
+          ReturnStatus = STATUS_ERROR;\r
+          goto Done;\r
         }\r
         if (FileList != NULL && FileList->CodeRevision == 0) {\r
           FileList->CodeRevision = (UINT16) CodeRevision;\r
         }\r
         if (FileList != NULL && FileList->CodeRevision == 0) {\r
           FileList->CodeRevision = (UINT16) CodeRevision;\r
@@ -1071,7 +1194,8 @@ Returns:
         mOptions.Pci23 = 1;\r
       } else {\r
         Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]);\r
         mOptions.Pci23 = 1;\r
       } else {\r
         Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]);\r
-        return STATUS_ERROR;\r
+        ReturnStatus = STATUS_ERROR;\r
+        goto Done;\r
       }\r
     } else {\r
       //\r
       }\r
     } else {\r
       //\r
@@ -1080,7 +1204,8 @@ Returns:
       //\r
       if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {\r
         Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]);\r
       //\r
       if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {\r
         Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]);\r
-        return STATUS_ERROR;\r
+        ReturnStatus = STATUS_ERROR;\r
+        goto Done;\r
       }\r
       //\r
       // Check Efi Option RomImage\r
       }\r
       //\r
       // Check Efi Option RomImage\r
@@ -1094,9 +1219,10 @@ Returns:
       FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
       if (FileList == NULL) {\r
         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);\r
       FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));\r
       if (FileList == NULL) {\r
         Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);\r
-        return STATUS_ERROR;\r
+        ReturnStatus = STATUS_ERROR;\r
+        goto Done;\r
       }\r
       }\r
-      \r
+\r
       //\r
       // set flag and class code for this image.\r
       //\r
       //\r
       // set flag and class code for this image.\r
       //\r
@@ -1113,7 +1239,7 @@ Returns:
       } else {\r
         if (PrevFileList == NULL) {\r
           PrevFileList = FileList;\r
       } else {\r
         if (PrevFileList == NULL) {\r
           PrevFileList = FileList;\r
-        } else {          \r
+        } else {\r
           PrevFileList->Next = FileList;\r
         }\r
       }\r
           PrevFileList->Next = FileList;\r
         }\r
       }\r
@@ -1132,6 +1258,9 @@ Returns:
   //\r
   if (Options->FileList == NULL) {\r
     Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!");\r
   //\r
   if (Options->FileList == NULL) {\r
     Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!");\r
+    //\r
+    // No memory allocation, return directly.\r
+    //\r
     return STATUS_ERROR;\r
   }\r
 \r
     return STATUS_ERROR;\r
   }\r
 \r
@@ -1141,16 +1270,33 @@ Returns:
   if (EfiRomFlag) {\r
     if (!Options->VendIdValid) {\r
       Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL);\r
   if (EfiRomFlag) {\r
     if (!Options->VendIdValid) {\r
       Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL);\r
-      return STATUS_ERROR;\r
+      ReturnStatus = STATUS_ERROR;\r
+      goto Done;\r
     }\r
     }\r
-  \r
-    if (!Options->DevIdValid) {\r
+\r
+    if (!Options->DevIdCount) {\r
       Error (NULL, 0, 2000, "Missing Device ID in command line", NULL);\r
       Error (NULL, 0, 2000, "Missing Device ID in command line", NULL);\r
-      return STATUS_ERROR;\r
+      ReturnStatus = STATUS_ERROR;\r
+      goto Done;\r
     }\r
   }\r
 \r
     }\r
   }\r
 \r
-  return 0;\r
+   if (Options->DevIdCount > 1 && Options->Pci23) {\r
+     Error (NULL, 0, 2000, "Invalid parameter", "PCI 3.0 is required when specifying multiple Device IDs");\r
+     ReturnStatus = STATUS_ERROR;\r
+     goto Done;\r
+   }\r
+\r
+Done:\r
+  if (ReturnStatus != 0) {\r
+    while (Options->FileList != NULL) {\r
+      FileList = Options->FileList->Next;\r
+      free (Options->FileList);\r
+      Options->FileList = FileList;\r
+    }\r
+  }\r
+\r
+  return ReturnStatus;\r
 }\r
 \r
 static\r
 }\r
 \r
 static\r
@@ -1161,7 +1307,7 @@ Version (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   Print version information for this utility.\r
 \r
 Arguments:\r
   Print version information for this utility.\r
 \r
 Arguments:\r
@@ -1175,7 +1321,7 @@ Returns:
 {\r
  fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
 }\r
 {\r
  fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);\r
 }\r
-   \r
+\r
 static\r
 void\r
 Usage (\r
 static\r
 void\r
 Usage (\r
@@ -1184,7 +1330,7 @@ Usage (
 /*++\r
 \r
 Routine Description:\r
 /*++\r
 \r
 Routine Description:\r
-  \r
+\r
   Print usage information for this utility.\r
 \r
 Arguments:\r
   Print usage information for this utility.\r
 \r
 Arguments:\r
@@ -1200,19 +1346,19 @@ Returns:
   //\r
   // Summary usage\r
   //\r
   //\r
   // Summary usage\r
   //\r
-  fprintf (stdout, "Usage: %s [options] [file name<s>] \n\n", UTILITY_NAME);\r
-  \r
+  fprintf (stdout, "Usage: %s -f VendorId -i DeviceId [options] [file name<s>] \n\n", UTILITY_NAME);\r
+\r
   //\r
   // Copyright declaration\r
   //\r
   // Copyright declaration\r
-  // \r
-  fprintf (stdout, "Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.\n\n");\r
+  //\r
+  fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");\r
 \r
   //\r
   // Details Option\r
   //\r
   fprintf (stdout, "Options:\n");\r
   fprintf (stdout, "  -o FileName, --output FileName\n\\r
 \r
   //\r
   // Details Option\r
   //\r
   fprintf (stdout, "Options:\n");\r
   fprintf (stdout, "  -o FileName, --output FileName\n\\r
-            File will be created to store the ouput content.\n");\r
+            File will be created to store the output content.\n");\r
   fprintf (stdout, "  -e EfiFileName\n\\r
             EFI PE32 image files.\n");\r
   fprintf (stdout, "  -ec EfiFileName\n\\r
   fprintf (stdout, "  -e EfiFileName\n\\r
             EFI PE32 image files.\n");\r
   fprintf (stdout, "  -ec EfiFileName\n\\r
@@ -1224,9 +1370,9 @@ Returns:
   fprintf (stdout, "  -r Rev    Hex Revision in the PCI data structure header.\n");\r
   fprintf (stdout, "  -n        Not to automatically set the LAST bit in the last file.\n");\r
   fprintf (stdout, "  -f VendorId\n\\r
   fprintf (stdout, "  -r Rev    Hex Revision in the PCI data structure header.\n");\r
   fprintf (stdout, "  -n        Not to automatically set the LAST bit in the last file.\n");\r
   fprintf (stdout, "  -f VendorId\n\\r
-            Hex PCI Vendor ID for the device OpROM.\n");\r
+            Hex PCI Vendor ID for the device OpROM, must be specified\n");\r
   fprintf (stdout, "  -i DeviceId\n\\r
   fprintf (stdout, "  -i DeviceId\n\\r
-            Hex PCI Device ID for the device OpROM.\n");\r
+            One or more hex PCI Device IDs for the device OpROM, must be specified\n");\r
   fprintf (stdout, "  -p, --pci23\n\\r
             Default layout meets PCI 3.0 specifications\n\\r
             specifying this flag will for a PCI 2.3 layout.\n");\r
   fprintf (stdout, "  -p, --pci23\n\\r
             Default layout meets PCI 3.0 specifications\n\\r
             specifying this flag will for a PCI 2.3 layout.\n");\r
@@ -1240,7 +1386,7 @@ Returns:
   fprintf (stdout, "  -q, --quiet\n\\r
             Disable all messages except FATAL ERRORS.\n");\r
   fprintf (stdout, "  --debug [#,0-9]\n\\r
   fprintf (stdout, "  -q, --quiet\n\\r
             Disable all messages except FATAL ERRORS.\n");\r
   fprintf (stdout, "  --debug [#,0-9]\n\\r
-            Enable debug messages at level #.\n");  \r
+            Enable debug messages at level #.\n");\r
 }\r
 \r
 static\r
 }\r
 \r
 static\r
@@ -1271,11 +1417,12 @@ Returns:
   EFI_PCI_EXPANSION_ROM_HEADER  EfiRomHdr;\r
   PCI_DATA_STRUCTURE            PciDs23;\r
   PCI_3_0_DATA_STRUCTURE        PciDs30;\r
   EFI_PCI_EXPANSION_ROM_HEADER  EfiRomHdr;\r
   PCI_DATA_STRUCTURE            PciDs23;\r
   PCI_3_0_DATA_STRUCTURE        PciDs30;\r
+  UINT16                        DevId;\r
 \r
   //\r
   // Open the input file\r
   //\r
 \r
   //\r
   // Open the input file\r
   //\r
-  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {\r
+  if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {\r
     Error (NULL, 0, 0001, "Error opening file", InFile->FileName);\r
     return ;\r
   }\r
     Error (NULL, 0, 0001, "Error opening file", InFile->FileName);\r
     return ;\r
   }\r
@@ -1285,7 +1432,7 @@ Returns:
   ImageCount = 0;\r
   for (;;) {\r
     //\r
   ImageCount = 0;\r
   for (;;) {\r
     //\r
-    // Save our postition in the file, since offsets in the headers\r
+    // Save our position in the file, since offsets in the headers\r
     // are relative to the particular image.\r
     //\r
     ImageStart = ftell (InFptr);\r
     // are relative to the particular image.\r
     //\r
     ImageStart = ftell (InFptr);\r
@@ -1368,7 +1515,31 @@ Returns:
     fprintf (stdout, "    Device ID               0x%04X\n", PciDs30.DeviceId);\r
     fprintf (stdout, "    Length                  0x%04X\n", PciDs30.Length);\r
     fprintf (stdout, "    Revision                0x%04X\n", PciDs30.Revision);\r
     fprintf (stdout, "    Device ID               0x%04X\n", PciDs30.DeviceId);\r
     fprintf (stdout, "    Length                  0x%04X\n", PciDs30.Length);\r
     fprintf (stdout, "    Revision                0x%04X\n", PciDs30.Revision);\r
-    fprintf (stdout, "    DeviceListOffset        0x%02X\n", PciDs30.DeviceListOffset);    \r
+    fprintf (stdout, "    DeviceListOffset        0x%02X\n", PciDs30.DeviceListOffset);\r
+    if (PciDs30.DeviceListOffset) {\r
+      //\r
+      // Print device ID list\r
+      //\r
+      fprintf (stdout, "    Device list contents\n");\r
+      if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset + PciDs30.DeviceListOffset, SEEK_SET)) {\r
+        Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI device ID list!");\r
+        goto BailOut;\r
+      }\r
+\r
+      //\r
+      // Loop until terminating 0\r
+      //\r
+      do {\r
+        if (fread (&DevId, sizeof (DevId), 1, InFptr) != 1) {\r
+          Error (NULL, 0, 3001, "Not supported", "Failed to read PCI device ID list from file %s!", InFile->FileName);\r
+          goto BailOut;\r
+        }\r
+        if (DevId) {\r
+          fprintf (stdout, "      0x%04X\n", DevId);\r
+        }\r
+      } while (DevId);\r
+\r
+    }\r
     fprintf (\r
       stdout,\r
       "    Class Code              0x%06X\n",\r
     fprintf (\r
       stdout,\r
       "    Class Code              0x%06X\n",\r
@@ -1378,8 +1549,8 @@ Returns:
     fprintf (stdout, "    Code revision:          0x%04X\n", PciDs30.CodeRevision);\r
     fprintf (stdout, "    MaxRuntimeImageLength   0x%02X\n", PciDs30.MaxRuntimeImageLength);\r
     fprintf (stdout, "    ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset);\r
     fprintf (stdout, "    Code revision:          0x%04X\n", PciDs30.CodeRevision);\r
     fprintf (stdout, "    MaxRuntimeImageLength   0x%02X\n", PciDs30.MaxRuntimeImageLength);\r
     fprintf (stdout, "    ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset);\r
-    fprintf (stdout, "    DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset);   \r
-    fprintf (stdout, "    Indicator               0x%02X", PciDs30.Indicator);    \r
+    fprintf (stdout, "    DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset);\r
+    fprintf (stdout, "    Indicator               0x%02X", PciDs30.Indicator);\r
     }\r
     //\r
     // Print the indicator, used to flag the last image\r
     }\r
     //\r
     // Print the indicator, used to flag the last image\r
@@ -1395,7 +1566,7 @@ Returns:
     if (mOptions.Pci23 == 1) {\r
       fprintf (stdout, "    Code type              0x%02X", PciDs23.CodeType);\r
     } else {\r
     if (mOptions.Pci23 == 1) {\r
       fprintf (stdout, "    Code type              0x%02X", PciDs23.CodeType);\r
     } else {\r
-      fprintf (stdout, "    Code type               0x%02X", PciDs30.CodeType); \r
+      fprintf (stdout, "    Code type               0x%02X", PciDs30.CodeType);\r
     }\r
     if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
       fprintf (stdout, "   (EFI image)\n");\r
     }\r
     if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {\r
       fprintf (stdout, "   (EFI image)\n");\r