]> git.proxmox.com Git - mirror_edk2.git/blobdiff - BaseTools/Source/C/EfiRom/EfiRom.c
BaseTools: Replace StandardError with Expression
[mirror_edk2.git] / BaseTools / Source / C / EfiRom / EfiRom.c
index 622a12f04d89bda05630f2be433d59450cb99d2e..fc3b5ad277a60db17bd7b3fda5a8a2bbf39932ee 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Utility program to create an EFI option ROM image from binary and EFI PE32 files.\r
 \r
-Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 1999 - 2017, 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
@@ -96,16 +96,24 @@ Returns:
   //\r
   if (!mOptions.OutFileName[0]) {\r
     if (mOptions.FileList != NULL) {\r
-      strcpy (mOptions.OutFileName, mOptions.FileList->FileName);\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
-      for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;\r
-           (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');\r
-           Ext--\r
-          )\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
@@ -144,7 +152,7 @@ Returns:
         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
@@ -176,9 +184,6 @@ Returns:
 \r
 BailOut:\r
   if (Status == STATUS_SUCCESS) {\r
-    if (FptrOut != NULL) {\r
-      fclose (FptrOut);\r
-    }\r
     //\r
     // Clean up our file list\r
     //\r
@@ -187,6 +192,16 @@ BailOut:
       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
@@ -241,7 +256,7 @@ Returns:
   // Try to open the input file\r
   //\r
   if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {\r
-    Error (NULL, 0, 0001, "Error opening file", InFile->FileName);\r
+    Error (NULL, 0, 0001, "Error opening file", "%s", InFile->FileName);\r
     return STATUS_ERROR;\r
   }\r
   //\r
@@ -450,6 +465,7 @@ Returns:
   UINT32                        HeaderPadBytes;\r
   UINT32                        PadBytesBeforeImage;\r
   UINT32                        PadBytesAfterImage;\r
+  UINT32                        DevIdListSize;\r
 \r
   //\r
   // Try to open the input file\r
@@ -493,7 +509,16 @@ Returns:
   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
@@ -630,7 +655,14 @@ Returns:
     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
@@ -700,6 +732,26 @@ Returns:
     } \r
   }\r
 \r
+  //\r
+  // Write the Device ID list to the output file\r
+  //\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
   // Pad head to make it a multiple of 512 bytes\r
   //\r
@@ -883,9 +935,13 @@ Returns:
   UINT32    ClassCode;\r
   UINT32    CodeRevision;\r
   EFI_STATUS Status;\r
+  INTN       ReturnStatus;\r
   BOOLEAN    EfiRomFlag;\r
   UINT64     TempValue;\r
+  char       *OptionName;\r
+  UINT16     *DevIdList;\r
 \r
+  ReturnStatus = 0;\r
   FileFlags = 0;\r
   EfiRomFlag = FALSE;\r
 \r
@@ -899,6 +955,9 @@ Returns:
   //\r
   FileList                = PrevFileList = NULL;\r
 \r
+  Options->DevIdList      = NULL;\r
+  Options->DevIdCount     = 0;\r
+\r
   ClassCode               = 0;\r
   CodeRevision            = 0;\r
   //\r
@@ -940,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
-          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
-          return 1;\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         Options->VendId       = (UINT16) TempValue;\r
         Options->VendIdValid  = 1;\r
@@ -952,24 +1013,53 @@ Returns:
         Argv++;\r
         Argc--;\r
       } else if (stricmp (Argv[0], "-i") == 0) {\r
+\r
+        OptionName = Argv[0];\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
-        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
-        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
-        Options->DevId      = (UINT16) TempValue;\r
-        Options->DevIdValid = 1;\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
@@ -977,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
-          return STATUS_ERROR;\r
+          ReturnStatus = STATUS_ERROR;\r
+          goto Done;\r
+        }\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
-        strcpy (Options->OutFileName, Argv[1]);\r
+        strncpy (Options->OutFileName, Argv[1], MAX_PATH - 1);\r
+        Options->OutFileName[MAX_PATH - 1] = 0;\r
 \r
         Argv++;\r
         Argc--;\r
@@ -988,7 +1085,8 @@ Returns:
         // 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
@@ -1016,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
-          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
-          return 1;\r
+          ReturnStatus = 1;\r
+          goto Done;\r
         }\r
         if (DebugLevel>=5 && DebugLevel<=9) {\r
           Options->Debug = TRUE;\r
@@ -1040,7 +1140,7 @@ Returns:
         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
@@ -1050,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
-          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
-          return STATUS_ERROR;\r
+          ReturnStatus = STATUS_ERROR;\r
+          goto Done;\r
         }\r
         if (FileList != NULL && FileList->ClassCode == 0) {\r
           FileList->ClassCode = ClassCode;\r
@@ -1071,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
-          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
-          return STATUS_ERROR;\r
+          ReturnStatus = STATUS_ERROR;\r
+          goto Done;\r
         }\r
         if (FileList != NULL && FileList->CodeRevision == 0) {\r
           FileList->CodeRevision = (UINT16) CodeRevision;\r
@@ -1090,7 +1194,8 @@ Returns:
         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
@@ -1099,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
-        return STATUS_ERROR;\r
+        ReturnStatus = STATUS_ERROR;\r
+        goto Done;\r
       }\r
       //\r
       // Check Efi Option RomImage\r
@@ -1113,7 +1219,8 @@ Returns:
       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
@@ -1151,6 +1258,9 @@ Returns:
   //\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
@@ -1160,16 +1270,33 @@ Returns:
   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
-    if (!Options->DevIdValid) {\r
+    if (!Options->DevIdCount) {\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
-  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
@@ -1224,7 +1351,7 @@ Returns:
   //\r
   // Copyright declaration\r
   // \r
-  fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");\r
+  fprintf (stdout, "Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.\n\n");\r
 \r
   //\r
   // Details Option\r
@@ -1245,7 +1372,7 @@ Returns:
   fprintf (stdout, "  -f VendorId\n\\r
             Hex PCI Vendor ID for the device OpROM, must be specified\n");\r
   fprintf (stdout, "  -i DeviceId\n\\r
-            Hex PCI Device ID for the device OpROM, must be specified\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
@@ -1290,6 +1417,7 @@ Returns:
   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
@@ -1388,6 +1516,30 @@ Returns:
     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
+    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