summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom
parentInitial commit. (diff)
downloadvirtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz
virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom')
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c1712
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.h353
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/GNUmakefile15
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile16
-rw-r--r--src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile.kmk45
5 files changed, 2141 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c
new file mode 100644
index 00000000..61e47a6a
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c
@@ -0,0 +1,1712 @@
+/** @file
+Utility program to create an EFI option ROM image from binary and EFI PE32 files.
+
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "EfiUtilityMsgs.h"
+#include "ParseInf.h"
+#include "EfiRom.h"
+
+UINT64 DebugLevel = 0;
+
+int
+main (
+ int Argc,
+ char *Argv[]
+ )
+/*++
+
+Routine Description:
+
+ Given an EFI image filename, create a ROM-able image by creating an option
+ ROM header and PCI data structure, filling them in, and then writing the
+ option ROM header + PCI data structure + EFI image out to the output file.
+
+Arguments:
+
+ Argc - standard C main() argument count
+
+ Argv - standard C main() argument list
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+{
+ CHAR8 *Ext;
+ FILE *FptrOut;
+ UINT32 Status;
+ FILE_LIST *FList;
+ UINT32 TotalSize;
+ UINT32 Size;
+ CHAR8 *Ptr0;
+
+ SetUtilityName(UTILITY_NAME);
+
+ Status = STATUS_SUCCESS;
+ FptrOut = NULL;
+
+ //
+ // Parse the command line arguments
+ //
+ if (ParseCommandLine (Argc, Argv, &mOptions)) {
+ return STATUS_ERROR;
+ }
+
+ if (mOptions.Quiet) {
+ SetPrintLevel(40);
+ } else if (mOptions.Verbose) {
+ SetPrintLevel(15);
+ } else if (mOptions.Debug) {
+ SetPrintLevel(DebugLevel);
+ }
+
+ if (mOptions.Verbose) {
+ VerboseMsg("%s tool start.\n", UTILITY_NAME);
+ }
+
+ //
+ // If dumping an image, then do that and quit
+ //
+ if (mOptions.DumpOption == 1) {
+ if (mOptions.FileList != NULL) {
+ if ((Ptr0 = strstr ((CONST CHAR8 *) mOptions.FileList->FileName, DEFAULT_OUTPUT_EXTENSION)) != NULL) {
+ DumpImage (mOptions.FileList);
+ goto BailOut;
+ } else {
+ Error (NULL, 0, 1002, "No PciRom input file", "No *.rom input file");
+ goto BailOut;
+ }
+ }
+ }
+ //
+ // Determine the output filename. Either what they specified on
+ // the command line, or the first input filename with a different extension.
+ //
+ if (!mOptions.OutFileName[0]) {
+ if (mOptions.FileList != NULL) {
+ if (strlen (mOptions.FileList->FileName) >= MAX_PATH) {
+ Status = STATUS_ERROR;
+ Error (NULL, 0, 2000, "Invalid parameter", "Input file name is too long - %s.", mOptions.FileList->FileName);
+ goto BailOut;
+ }
+ strncpy (mOptions.OutFileName, mOptions.FileList->FileName, MAX_PATH - 1);
+ mOptions.OutFileName[MAX_PATH - 1] = 0;
+ //
+ // Find the last . on the line and replace the filename extension with
+ // the default
+ //
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
+ while (Ext >= mOptions.OutFileName) {
+ if ((*Ext == '.') || (*Ext == '\\')) {
+ break;
+ }
+ Ext--;
+ }
+ //
+ // If dot here, then insert extension here, otherwise append
+ //
+ if (*Ext != '.') {
+ Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
+ }
+
+ strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
+ }
+ }
+ //
+ // Make sure we don't have the same filename for input and output files
+ //
+ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
+ if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {
+ Status = STATUS_ERROR;
+ Error (NULL, 0, 1002, "Invalid input parameter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName);
+ goto BailOut;
+ }
+ }
+ //
+ // Now open our output file
+ //
+ if ((FptrOut = fopen (LongFilePath (mOptions.OutFileName), "wb")) == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", mOptions.OutFileName);
+ goto BailOut;
+ }
+ //
+ // Process all our files
+ //
+ TotalSize = 0;
+ for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
+ Size = 0;
+ if ((FList->FileFlags & FILE_FLAG_EFI) != 0) {
+ if (mOptions.Verbose) {
+ VerboseMsg("Processing EFI file %s\n", FList->FileName);
+ }
+
+ Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevIdList[0], &Size);
+ } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) {
+ if (mOptions.Verbose) {
+ VerboseMsg("Processing binary file %s\n", FList->FileName);
+ }
+
+ Status = ProcessBinFile (FptrOut, FList, &Size);
+ } else {
+ Error (NULL, 0, 2000, "Invalid parameter", "File type not specified, it must be either an EFI or binary file: %s.", FList->FileName);
+ Status = STATUS_ERROR;
+ }
+
+ if (mOptions.Verbose) {
+ VerboseMsg(" Output size = 0x%X\n", (unsigned) Size);
+ }
+
+ if (Status != STATUS_SUCCESS) {
+ break;
+ }
+
+ TotalSize += Size;
+ }
+ //
+ // Check total size
+ //
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE);
+ Status = STATUS_ERROR;
+ }
+
+BailOut:
+ if (Status == STATUS_SUCCESS) {
+ //
+ // Clean up our file list
+ //
+ while (mOptions.FileList != NULL) {
+ FList = mOptions.FileList->Next;
+ free (mOptions.FileList);
+ mOptions.FileList = FList;
+ }
+
+ //
+ // Clean up device ID list
+ //
+ if (mOptions.DevIdList != NULL) {
+ free (mOptions.DevIdList);
+ }
+ }
+ if (FptrOut != NULL) {
+ fclose (FptrOut);
+ }
+
+ if (mOptions.Verbose) {
+ VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
+ }
+
+ return GetUtilityStatus ();
+}
+
+static
+int
+ProcessBinFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Process a binary input file.
+
+Arguments:
+
+ OutFptr - file pointer to output binary ROM image file we're creating
+ InFile - structure contains information on the binary file to process
+ Size - pointer to where to return the size added to the output file
+
+Returns:
+
+ 0 - successful
+
+--*/
+{
+ FILE *InFptr;
+ UINT32 TotalSize;
+ UINT32 FileSize;
+ UINT8 *Buffer;
+ UINT32 Status;
+ PCI_EXPANSION_ROM_HEADER *RomHdr;
+ PCI_DATA_STRUCTURE *PciDs23;
+ PCI_3_0_DATA_STRUCTURE *PciDs30;
+ UINT32 Index;
+ UINT8 ByteCheckSum;
+ UINT16 CodeType;
+
+ PciDs23 = NULL;
+ PciDs30 = NULL;
+ Status = STATUS_SUCCESS;
+
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", "%s", InFile->FileName);
+ return STATUS_ERROR;
+ }
+ //
+ // Seek to the end of the input file and get the file size. Then allocate
+ // a buffer to read it in to.
+ //
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+ if (mOptions.Verbose) {
+ VerboseMsg(" File size = 0x%X\n", (unsigned) FileSize);
+ }
+
+ fseek (InFptr, 0, SEEK_SET);
+ Buffer = (UINT8 *) malloc (FileSize);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 4003, "Resource", "memory cannot be allocated!");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 2000, "Invalid", "Failed to read all bytes from input file.");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Total size must be an even multiple of 512 bytes, and can't exceed
+ // the option ROM image size.
+ //
+ TotalSize = FileSize;
+ if (TotalSize & 0x1FF) {
+ TotalSize = (TotalSize + 0x200) &~0x1ff;
+ }
+
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ Error (NULL, 0, 3001, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Return the size to the caller so they can keep track of the running total.
+ //
+ *Size = TotalSize;
+
+ //
+ // Crude check to make sure it's a legitimate ROM image
+ //
+ RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;
+ if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "ROM image file has an invalid ROM signature.");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Make sure the pointer to the PCI data structure is within the size of the image.
+ // Then check it for valid signature.
+ //
+ if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Invalid PCI data structure offset.");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ //
+ // Check the header is conform to PCI2.3 or PCI3.0
+ //
+ if (mOptions.Pci23 == 1) {
+ PciDs23 = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);
+ if (PciDs23->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature.");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ } else {
+ //
+ // Default setting is PCI3.0 header
+ //
+ PciDs30 = (PCI_3_0_DATA_STRUCTURE *)(Buffer + RomHdr->PcirOffset);
+ if (PciDs30->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature.");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ }
+
+ //
+ // ReSet Option Rom size
+ //
+ if (mOptions.Pci23 == 1) {
+ PciDs23->ImageLength = (UINT16) (TotalSize / 512);
+ CodeType = PciDs23->CodeType;
+ } else {
+ PciDs30->ImageLength = (UINT16) (TotalSize / 512);
+ CodeType = PciDs30->CodeType;
+ }
+
+ //
+ // If this is the last image, then set the LAST bit unless requested not
+ // to via the command-line -n argument. Otherwise, make sure you clear it.
+ //
+ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
+ if (mOptions.Pci23 == 1) {
+ PciDs23->Indicator = INDICATOR_LAST;
+ } else {
+ PciDs30->Indicator = INDICATOR_LAST;
+ }
+ } else {
+ if (mOptions.Pci23 == 1) {
+ PciDs23->Indicator = 0;
+ } else {
+ PciDs30->Indicator = 0;
+ }
+ }
+
+ if (CodeType != PCI_CODE_TYPE_EFI_IMAGE) {
+ ByteCheckSum = 0;
+ for (Index = 0; Index < FileSize - 1; Index++) {
+ ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);
+ }
+
+ Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);
+ if (mOptions.Verbose) {
+ VerboseMsg(" Checksum = %02x\n\n", Buffer[FileSize - 1]);
+ }
+ }
+
+ //
+ // Now copy the input file contents out to the output file
+ //
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0005, "Failed to write all file bytes to output file.", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ TotalSize -= FileSize;
+ //
+ // Pad the rest of the image to make it a multiple of 512 bytes
+ //
+ while (TotalSize > 0) {
+ putc (~0, OutFptr);
+ TotalSize--;
+ }
+
+BailOut:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+ //
+ // Print the file name if errors occurred
+ //
+ if (Status != STATUS_SUCCESS) {
+ Error (NULL, 0, 0003, "Error", "Error parsing file: %s", InFile->FileName);
+ }
+
+ return Status;
+}
+
+static
+int
+ProcessEfiFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT16 VendId,
+ UINT16 DevId,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Process a PE32 EFI file.
+
+Arguments:
+
+ OutFptr - file pointer to output binary ROM image file we're creating
+ InFile - structure contains information on the PE32 file to process
+ VendId - vendor ID as required in the option ROM header
+ DevId - device ID as required in the option ROM header
+ Size - pointer to where to return the size added to the output file
+
+Returns:
+
+ 0 - successful
+
+--*/
+{
+ UINT32 Status;
+ FILE *InFptr;
+ EFI_PCI_EXPANSION_ROM_HEADER RomHdr;
+ PCI_DATA_STRUCTURE PciDs23;
+ PCI_3_0_DATA_STRUCTURE PciDs30;
+ UINT32 FileSize;
+ UINT32 CompressedFileSize;
+ UINT8 *Buffer;
+ UINT8 *CompressedBuffer;
+ UINT8 *TempBufferPtr;
+ UINT32 TotalSize;
+ UINT32 HeaderSize;
+ UINT16 MachineType;
+ UINT16 SubSystem;
+ UINT32 HeaderPadBytes;
+ UINT32 PadBytesBeforeImage;
+ UINT32 PadBytesAfterImage;
+ UINT32 DevIdListSize;
+
+ //
+ // Try to open the input file
+ //
+ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
+ Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", InFile->FileName);
+ return STATUS_ERROR;
+ }
+ //
+ // Initialize our buffer pointers to null.
+ //
+ Buffer = NULL;
+ CompressedBuffer = NULL;
+
+ //
+ // Double-check the file to make sure it's what we expect it to be
+ //
+ Status = CheckPE32File (InFptr, &MachineType, &SubSystem);
+ if (Status != STATUS_SUCCESS) {
+ goto BailOut;
+ }
+ //
+ // Seek to the end of the input file and get the file size
+ //
+ fseek (InFptr, 0, SEEK_END);
+ FileSize = ftell (InFptr);
+
+ //
+ // Get the size of the headers we're going to put in front of the image. The
+ // EFI header must be aligned on a 4-byte boundary, so pad accordingly.
+ //
+ if (sizeof (RomHdr) & 0x03) {
+ HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);
+ } else {
+ HeaderPadBytes = 0;
+ }
+
+ //
+ // For Pci3.0 to use the different data structure.
+ //
+ if (mOptions.Pci23 == 1) {
+ HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
+ } else {
+ if (mOptions.DevIdCount > 1) {
+ //
+ // Write device ID list when more than one device ID is specified.
+ // Leave space for list plus terminator.
+ //
+ DevIdListSize = (mOptions.DevIdCount + 1) * sizeof (UINT16);
+ } else {
+ DevIdListSize = 0;
+ }
+ HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + DevIdListSize + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
+ }
+
+ if (mOptions.Verbose) {
+ VerboseMsg(" File size = 0x%X\n", (unsigned) FileSize);
+ }
+ //
+ // Allocate memory for the entire file (in case we have to compress), then
+ // seek back to the beginning of the file and read it into our buffer.
+ //
+ Buffer = (UINT8 *) malloc (FileSize);
+ if (Buffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ fseek (InFptr, 0, SEEK_SET);
+ if (fread (Buffer, FileSize, 1, InFptr) != 1) {
+ Error (NULL, 0, 0004, "Error reading file", "File %s", InFile->FileName);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Now determine the size of the final output file. It's either the header size
+ // plus the file's size, or the header size plus the compressed file size.
+ //
+ if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) {
+ //
+ // Allocate a buffer into which we can compress the image, compress it,
+ // and use that size as the new size.
+ //
+ CompressedBuffer = (UINT8 *) malloc (FileSize);
+ if (CompressedBuffer == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ CompressedFileSize = FileSize;
+ Status = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);
+ if (Status != STATUS_SUCCESS) {
+ Error (NULL, 0, 0007, "Error compressing file!", NULL);
+ goto BailOut;
+ }
+ //
+ // Now compute the size, then swap buffer pointers.
+ //
+ if (mOptions.Verbose) {
+ VerboseMsg(" Comp size = 0x%X\n", (unsigned) CompressedFileSize);
+ }
+
+ TotalSize = CompressedFileSize + HeaderSize;
+ FileSize = CompressedFileSize;
+ TempBufferPtr = Buffer;
+ Buffer = CompressedBuffer;
+ CompressedBuffer = TempBufferPtr;
+ } else {
+ TotalSize = FileSize + HeaderSize;
+ }
+ //
+ // Total size must be an even multiple of 512 bytes
+ //
+ if (TotalSize & 0x1FF) {
+ TotalSize = (TotalSize + 0x200) &~0x1ff;
+ }
+ //
+ // Workaround:
+ // If compressed, put the pad bytes after the image,
+ // else put the pad bytes before the image.
+ //
+ if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) {
+ PadBytesBeforeImage = 0;
+ PadBytesAfterImage = TotalSize - (FileSize + HeaderSize);
+ } else {
+ PadBytesBeforeImage = TotalSize - (FileSize + HeaderSize);
+ PadBytesAfterImage = 0;
+ }
+ //
+ // Check size
+ //
+ if (TotalSize > MAX_OPTION_ROM_SIZE) {
+ Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Return the size to the caller so they can keep track of the running total.
+ //
+ *Size = TotalSize;
+
+ //
+ // Now fill in the ROM header. These values come from chapter 18 of the
+ // EFI 1.02 specification.
+ //
+ memset (&RomHdr, 0, sizeof (RomHdr));
+ RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
+ RomHdr.InitializationSize = (UINT16) (TotalSize / 512);
+ RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
+ RomHdr.EfiSubsystem = SubSystem;
+ RomHdr.EfiMachineType = MachineType;
+ RomHdr.EfiImageHeaderOffset = (UINT16) (HeaderSize + PadBytesBeforeImage);
+ RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);
+ //
+ // Set image as compressed or not
+ //
+ if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
+ RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;
+ }
+ //
+ // Fill in the PCI data structure
+ //
+ if (mOptions.Pci23 == 1) {
+ memset (&PciDs23, 0, sizeof (PCI_DATA_STRUCTURE));
+ } else {
+ memset (&PciDs30, 0, sizeof (PCI_3_0_DATA_STRUCTURE));
+ }
+
+ if (mOptions.Pci23 == 1) {
+ PciDs23.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
+ PciDs23.VendorId = VendId;
+ PciDs23.DeviceId = DevId;
+ PciDs23.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE);
+ PciDs23.Revision = 0;
+ //
+ // Class code and code revision from the command line (optional)
+ //
+ PciDs23.ClassCode[0] = (UINT8) InFile->ClassCode;
+ PciDs23.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8);
+ PciDs23.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16);
+ PciDs23.ImageLength = RomHdr.InitializationSize;
+ PciDs23.CodeRevision = InFile->CodeRevision;
+ PciDs23.CodeType = PCI_CODE_TYPE_EFI_IMAGE;
+ } else {
+ PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
+ PciDs30.VendorId = VendId;
+ PciDs30.DeviceId = DevId;
+ if (mOptions.DevIdCount > 1) {
+ //
+ // Place device list immediately after PCI structure
+ //
+ PciDs30.DeviceListOffset = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);
+ } else {
+ PciDs30.DeviceListOffset = 0;
+ }
+ PciDs30.Length = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);
+ PciDs30.Revision = 0x3;
+ //
+ // Class code and code revision from the command line (optional)
+ //
+ PciDs30.ClassCode[0] = (UINT8) InFile->ClassCode;
+ PciDs30.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8);
+ PciDs30.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16);
+ PciDs30.ImageLength = RomHdr.InitializationSize;
+ PciDs30.CodeRevision = InFile->CodeRevision;
+ PciDs30.CodeType = PCI_CODE_TYPE_EFI_IMAGE;
+ PciDs30.MaxRuntimeImageLength = 0; // to be fixed
+ PciDs30.ConfigUtilityCodeHeaderOffset = 0; // to be fixed
+ PciDs30.DMTFCLPEntryPointOffset = 0; // to be fixed
+ }
+ //
+ // If this is the last image, then set the LAST bit unless requested not
+ // to via the command-line -n argument.
+ //
+ if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
+ if (mOptions.Pci23 == 1) {
+ PciDs23.Indicator = INDICATOR_LAST;
+ } else {
+ PciDs30.Indicator = INDICATOR_LAST;}
+ } else {
+ if (mOptions.Pci23 == 1) {
+ PciDs23.Indicator = 0;
+ } else {
+ PciDs30.Indicator = 0;
+ }
+ }
+ //
+ // Write the ROM header to the output file
+ //
+ if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0002, "Failed to write ROM header to output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ //
+ // Write pad bytes to align the PciDs
+ //
+ while (HeaderPadBytes > 0) {
+ if (putc (0, OutFptr) == EOF) {
+ Error (NULL, 0, 0002, "Failed to write ROM header pad bytes to output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ HeaderPadBytes--;
+ }
+ //
+ // Write the PCI data structure header to the output file
+ //
+ if (mOptions.Pci23 == 1) {
+ if (fwrite (&PciDs23, sizeof (PciDs23), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ } else {
+ if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) {
+ Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ }
+
+ //
+ // Write the Device ID list to the output file
+ //
+ if (mOptions.DevIdCount > 1) {
+ if (fwrite (mOptions.DevIdList, sizeof (UINT16), mOptions.DevIdCount, OutFptr) != mOptions.DevIdCount) {
+ Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ //
+ // Write two-byte terminating 0 at the end of the device list
+ //
+ if (putc (0, OutFptr) == EOF || putc (0, OutFptr) == EOF) {
+ Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ }
+
+
+ //
+ // Pad head to make it a multiple of 512 bytes
+ //
+ while (PadBytesBeforeImage > 0) {
+ if (putc (~0, OutFptr) == EOF) {
+ Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+ PadBytesBeforeImage--;
+ }
+ //
+ // Now dump the input file's contents to the output file
+ //
+ if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
+ Error (NULL, 0, 0002, "Failed to write all file bytes to output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ //
+ // Pad the rest of the image to make it a multiple of 512 bytes
+ //
+ while (PadBytesAfterImage > 0) {
+ if (putc (~0, OutFptr) == EOF) {
+ Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);
+ Status = STATUS_ERROR;
+ goto BailOut;
+ }
+
+ PadBytesAfterImage--;
+ }
+
+BailOut:
+ if (InFptr != NULL) {
+ fclose (InFptr);
+ }
+ //
+ // Free up our buffers
+ //
+ if (Buffer != NULL) {
+ free (Buffer);
+ }
+
+ if (CompressedBuffer != NULL) {
+ free (CompressedBuffer);
+ }
+ //
+ // Print the file name if errors occurred
+ //
+ if (Status != STATUS_SUCCESS) {
+ Error (NULL, 0, 0003, "Error parsing", "Error parsing file: %s", InFile->FileName);
+ }
+
+ return Status;
+}
+
+static
+int
+CheckPE32File (
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ )
+/*++
+
+Routine Description:
+
+ Given a file pointer to a supposed PE32 image file, verify that it is indeed a
+ PE32 image file, and then return the machine type in the supplied pointer.
+
+Arguments:
+
+ Fptr File pointer to the already-opened PE32 file
+ MachineType Location to stuff the machine type of the PE32 file. This is needed
+ because the image may be Itanium-based, IA32, or EBC.
+
+Returns:
+
+ 0 success
+ non-zero otherwise
+
+--*/
+{
+ EFI_IMAGE_DOS_HEADER DosHeader;
+ EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;
+
+ //
+ // Position to the start of the file
+ //
+ fseek (Fptr, 0, SEEK_SET);
+
+ //
+ // Read the DOS header
+ //
+ if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
+ Error (NULL, 0, 0004, "Failed to read the DOS stub from the input file!", NULL);
+ return STATUS_ERROR;
+ }
+ //
+ // Check the magic number (0x5A4D)
+ //
+ if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (magic number)!");
+ return STATUS_ERROR;
+ }
+ //
+ // Position into the file and check the PE signature
+ //
+ fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
+
+ //
+ // Read PE headers
+ //
+ if (fread (&PeHdr, sizeof (PeHdr), 1, Fptr) != 1) {
+ Error (NULL, 0, 0004, "Failed to read PE/COFF headers from input file!", NULL);
+ return STATUS_ERROR;
+ }
+
+
+ //
+ // Check the PE signature in the header "PE\0\0"
+ //
+ if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (signature)!");
+ return STATUS_ERROR;
+ }
+
+ memcpy ((char *) MachineType, &PeHdr.Pe32.FileHeader.Machine, 2);
+
+ if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ *SubSystem = PeHdr.Pe32.OptionalHeader.Subsystem;
+ } else if (PeHdr.Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+ *SubSystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem;
+ } else {
+ Error (NULL, 0, 2000, "Invalid parameter", "Unable to find subsystem type!");
+ return STATUS_ERROR;
+ }
+
+ if (mOptions.Verbose) {
+ VerboseMsg(" Got subsystem = 0x%X from image\n", *SubSystem);
+ }
+
+ //
+ // File was successfully identified as a PE32
+ //
+ return STATUS_SUCCESS;
+}
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[],
+ OPTIONS *Options
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv[] - standard C main() argument list
+ Options - pointer to a structure to store the options in
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+{
+ FILE_LIST *FileList;
+ FILE_LIST *PrevFileList;
+ UINT32 FileFlags;
+ UINT32 ClassCode;
+ UINT32 CodeRevision;
+ EFI_STATUS Status;
+ INTN ReturnStatus;
+ BOOLEAN EfiRomFlag;
+ UINT64 TempValue;
+ char *OptionName;
+ UINT16 *DevIdList;
+
+ ReturnStatus = 0;
+ FileFlags = 0;
+ EfiRomFlag = FALSE;
+
+ //
+ // Clear out the options
+ //
+ memset ((char *) Options, 0, sizeof (OPTIONS));
+
+ //
+ // To avoid compile warnings
+ //
+ FileList = PrevFileList = NULL;
+
+ Options->DevIdList = NULL;
+ Options->DevIdCount = 0;
+
+ ClassCode = 0;
+ CodeRevision = 0;
+ //
+ // Skip over the program name
+ //
+ Argc--;
+ Argv++;
+
+ //
+ // If no arguments, assume they want usage info
+ //
+ if (Argc == 0) {
+ Usage ();
+ return STATUS_ERROR;
+ }
+
+ if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) {
+ Usage();
+ return STATUS_ERROR;
+ }
+
+ if ((stricmp(Argv[0], "--version") == 0)) {
+ Version();
+ return STATUS_ERROR;
+ }
+
+ //
+ // Process until no more arguments
+ //
+ while (Argc > 0) {
+ if (Argv[0][0] == '-') {
+ //
+ // Vendor ID specified with -f
+ //
+ if (stricmp (Argv[0], "-f") == 0) {
+ //
+ // Make sure there's another parameter
+ //
+ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
+ ReturnStatus = 1;
+ goto Done;
+ }
+ if (TempValue >= 0x10000) {
+ Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]);
+ ReturnStatus = 1;
+ goto Done;
+ }
+ Options->VendId = (UINT16) TempValue;
+ Options->VendIdValid = 1;
+
+ Argv++;
+ Argc--;
+ } else if (stricmp (Argv[0], "-i") == 0) {
+
+ OptionName = Argv[0];
+
+ //
+ // Device IDs specified with -i
+ // Make sure there's at least one more parameter
+ //
+ if (Argc == 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Missing Device Id with %s option!", OptionName);
+ ReturnStatus = 1;
+ goto Done;
+ }
+
+ //
+ // Process until another dash-argument parameter or the end of the list
+ //
+ while (Argc > 1 && Argv[1][0] != '-') {
+ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", OptionName, Argv[1]);
+ ReturnStatus = 1;
+ goto Done;
+ }
+ //
+ // Don't allow device IDs greater than 16 bits
+ // Don't allow 0, since it is used as a list terminator
+ //
+ if (TempValue >= 0x10000 || TempValue == 0) {
+ Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);
+ ReturnStatus = 1;
+ goto Done;
+ }
+
+ DevIdList = (UINT16*) realloc (Options->DevIdList, (Options->DevIdCount + 1) * sizeof (UINT16));
+ if (DevIdList == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);
+ ReturnStatus = 1;
+ goto Done;
+ }
+ Options->DevIdList = DevIdList;
+
+ Options->DevIdList[Options->DevIdCount++] = (UINT16) TempValue;
+
+ Argv++;
+ Argc--;
+ }
+
+ } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) {
+ //
+ // Output filename specified with -o
+ // Make sure there's another parameter
+ //
+ if (Argv[1] == NULL || Argv[1][0] == '-') {
+ Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+ if (strlen (Argv[1]) > MAX_PATH - 1) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Output file name %s is too long!", Argv[1]);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+ strncpy (Options->OutFileName, Argv[1], MAX_PATH - 1);
+ Options->OutFileName[MAX_PATH - 1] = 0;
+
+ Argv++;
+ Argc--;
+ } else if ((stricmp (Argv[0], "-h") == 0) || (stricmp (Argv[0], "--help") == 0)) {
+ //
+ // Help option
+ //
+ Usage ();
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ } else if (stricmp (Argv[0], "-b") == 0) {
+ //
+ // Specify binary files with -b
+ //
+ FileFlags = FILE_FLAG_BINARY;
+ } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {
+ //
+ // Specify EFI files with -e. Specify EFI-compressed with -c.
+ //
+ FileFlags = FILE_FLAG_EFI;
+ if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) {
+ FileFlags |= FILE_FLAG_COMPRESS;
+ }
+ //
+ // Specify not to set the LAST bit in the last file with -n
+ //
+ } else if (stricmp (Argv[0], "-n") == 0) {
+ Options->NoLast = 1;
+ } else if (((stricmp (Argv[0], "-v") == 0)) || ((stricmp (Argv[0], "--verbose") == 0))) {
+ //
+ // -v for verbose
+ //
+ Options->Verbose = 1;
+ } else if (stricmp (Argv[0], "--debug") == 0) {
+ Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
+ ReturnStatus = 1;
+ goto Done;
+ }
+ if (DebugLevel > 9) {
+ Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]);
+ ReturnStatus = 1;
+ goto Done;
+ }
+ if (DebugLevel>=5 && DebugLevel<=9) {
+ Options->Debug = TRUE;
+ } else {
+ Options->Debug = FALSE;
+ }
+ Argv++;
+ Argc--;
+ } else if ((stricmp (Argv[0], "--quiet") == 0) || (stricmp (Argv[0], "-q") == 0)) {
+ Options->Quiet = TRUE;
+ } else if ((stricmp (Argv[0], "--dump") == 0) || (stricmp (Argv[0], "-d") == 0)) {
+ //
+ // -dump for dumping a ROM image. In this case, say that the device id
+ // and vendor id are valid so we don't have to specify bogus ones on the
+ // command line.
+ //
+ Options->DumpOption = 1;
+
+ Options->VendIdValid = 1;
+ Options->DevIdCount = 1;
+ FileFlags = FILE_FLAG_BINARY;
+ } else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) {
+ //
+ // Class code value for the next file in the list.
+ // Make sure there's another parameter
+ //
+ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
+ ReturnStatus = 1;
+ goto Done;
+ }
+ ClassCode = (UINT32) TempValue;
+ if (ClassCode & 0xFF000000) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+ if (FileList != NULL && FileList->ClassCode == 0) {
+ FileList->ClassCode = ClassCode;
+ }
+ Argv++;
+ Argc--;
+ } else if ((stricmp (Argv[0], "-r") == 0) || (stricmp (Argv[0], "--Revision") == 0)) {
+ //
+ // Code revision in the PCI data structure. The value is for the next
+ // file in the list.
+ // Make sure there's another parameter
+ //
+ Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
+ if (EFI_ERROR (Status)) {
+ Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
+ ReturnStatus = 1;
+ goto Done;
+ }
+ CodeRevision = (UINT32) TempValue;
+ if (CodeRevision & 0xFFFF0000) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+ if (FileList != NULL && FileList->CodeRevision == 0) {
+ FileList->CodeRevision = (UINT16) CodeRevision;
+ }
+ Argv++;
+ Argc--;
+ } else if ((stricmp (Argv[0], "-p") == 0) || (stricmp (Argv[0], "--pci23") == 0)) {
+ //
+ // Default layout meets PCI 3.0 specifications, specifying this flag will for a PCI 2.3 layout.
+ //
+ mOptions.Pci23 = 1;
+ } else {
+ Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+ } else {
+ //
+ // Not a slash-option argument. Must be a file name. Make sure they've specified
+ // -e or -b already.
+ //
+ if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+ //
+ // Check Efi Option RomImage
+ //
+ if ((FileFlags & FILE_FLAG_EFI) == FILE_FLAG_EFI) {
+ EfiRomFlag = TRUE;
+ }
+ //
+ // Create a new file structure
+ //
+ FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));
+ if (FileList == NULL) {
+ Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+
+ //
+ // set flag and class code for this image.
+ //
+ memset ((char *) FileList, 0, sizeof (FILE_LIST));
+ FileList->FileName = Argv[0];
+ FileList->FileFlags = FileFlags;
+ FileList->ClassCode = ClassCode;
+ FileList->CodeRevision = (UINT16) CodeRevision;
+ ClassCode = 0;
+ CodeRevision = 0;
+
+ if (Options->FileList == NULL) {
+ Options->FileList = FileList;
+ } else {
+ if (PrevFileList == NULL) {
+ PrevFileList = FileList;
+ } else {
+ PrevFileList->Next = FileList;
+ }
+ }
+
+ PrevFileList = FileList;
+ }
+ //
+ // Next argument
+ //
+ Argv++;
+ Argc--;
+ }
+
+ //
+ // Must have specified some files
+ //
+ if (Options->FileList == NULL) {
+ Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!");
+ //
+ // No memory allocation, return directly.
+ //
+ return STATUS_ERROR;
+ }
+
+ //
+ // For EFI OptionRom image, Make sure a device ID and vendor ID are both specified.
+ //
+ if (EfiRomFlag) {
+ if (!Options->VendIdValid) {
+ Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+
+ if (!Options->DevIdCount) {
+ Error (NULL, 0, 2000, "Missing Device ID in command line", NULL);
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+ }
+
+ if (Options->DevIdCount > 1 && Options->Pci23) {
+ Error (NULL, 0, 2000, "Invalid parameter", "PCI 3.0 is required when specifying multiple Device IDs");
+ ReturnStatus = STATUS_ERROR;
+ goto Done;
+ }
+
+Done:
+ if (ReturnStatus != 0) {
+ while (Options->FileList != NULL) {
+ FileList = Options->FileList->Next;
+ free (Options->FileList);
+ Options->FileList = FileList;
+ }
+ }
+
+ return ReturnStatus;
+}
+
+static
+void
+Version (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print version information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+--*/
+{
+ fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
+}
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Print usage information for this utility.
+
+Arguments:
+
+ None.
+
+Returns:
+
+ Nothing.
+
+--*/
+{
+ //
+ // Summary usage
+ //
+ fprintf (stdout, "Usage: %s -f VendorId -i DeviceId [options] [file name<s>] \n\n", UTILITY_NAME);
+
+ //
+ // Copyright declaration
+ //
+ fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n");
+
+ //
+ // Details Option
+ //
+ fprintf (stdout, "Options:\n");
+ fprintf (stdout, " -o FileName, --output FileName\n\
+ File will be created to store the output content.\n");
+ fprintf (stdout, " -e EfiFileName\n\
+ EFI PE32 image files.\n");
+ fprintf (stdout, " -ec EfiFileName\n\
+ EFI PE32 image files and will be compressed.\n");
+ fprintf (stdout, " -b BinFileName\n\
+ Legacy binary files.\n");
+ fprintf (stdout, " -l ClassCode\n\
+ Hex ClassCode in the PCI data structure header.\n");
+ fprintf (stdout, " -r Rev Hex Revision in the PCI data structure header.\n");
+ fprintf (stdout, " -n Not to automatically set the LAST bit in the last file.\n");
+ fprintf (stdout, " -f VendorId\n\
+ Hex PCI Vendor ID for the device OpROM, must be specified\n");
+ fprintf (stdout, " -i DeviceId\n\
+ One or more hex PCI Device IDs for the device OpROM, must be specified\n");
+ fprintf (stdout, " -p, --pci23\n\
+ Default layout meets PCI 3.0 specifications\n\
+ specifying this flag will for a PCI 2.3 layout.\n");
+ fprintf (stdout, " -d, --dump\n\
+ Dump the headers of an existing option ROM image.\n");
+ fprintf (stdout, " -v, --verbose\n\
+ Turn on verbose output with informational messages.\n");
+ fprintf (stdout, " --version Show program's version number and exit.\n");
+ fprintf (stdout, " -h, --help\n\
+ Show this help message and exit.\n");
+ fprintf (stdout, " -q, --quiet\n\
+ Disable all messages except FATAL ERRORS.\n");
+ fprintf (stdout, " --debug [#,0-9]\n\
+ Enable debug messages at level #.\n");
+}
+
+static
+void
+DumpImage (
+ FILE_LIST *InFile
+ )
+/*++
+
+Routine Description:
+
+ Dump the headers of an existing option ROM image
+
+Arguments:
+
+ InFile - the file name of an existing option ROM image
+
+Returns:
+
+ none
+
+--*/
+{
+ PCI_EXPANSION_ROM_HEADER PciRomHdr;
+ FILE *InFptr;
+ UINT32 ImageStart;
+ UINT32 ImageCount;
+ EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr;
+ PCI_DATA_STRUCTURE PciDs23;
+ PCI_3_0_DATA_STRUCTURE PciDs30;
+ UINT16 DevId;
+
+ //
+ // Open the input file
+ //
+ if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
+ Error (NULL, 0, 0001, "Error opening file", InFile->FileName);
+ return ;
+ }
+ //
+ // Go through the image and dump the header stuff for each
+ //
+ ImageCount = 0;
+ for (;;) {
+ //
+ // Save our position in the file, since offsets in the headers
+ // are relative to the particular image.
+ //
+ ImageStart = ftell (InFptr);
+ ImageCount++;
+
+ //
+ // Read the option ROM header. Have to assume a raw binary image for now.
+ //
+ if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) {
+ Error (NULL, 0, 3001, "Not supported", "Failed to read PCI ROM header from file!");
+ goto BailOut;
+ }
+
+ //
+ // Dump the contents of the header
+ //
+ fprintf (stdout, "Image %u -- Offset 0x%X\n", (unsigned) ImageCount, (unsigned) ImageStart);
+ fprintf (stdout, " ROM header contents\n");
+ fprintf (stdout, " Signature 0x%04X\n", PciRomHdr.Signature);
+ fprintf (stdout, " PCIR offset 0x%04X\n", PciRomHdr.PcirOffset);
+ //
+ // Find PCI data structure
+ //
+ if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {
+ Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI data structure!");
+ goto BailOut;
+ }
+ //
+ // Read and dump the PCI data structure
+ //
+ memset (&PciDs23, 0, sizeof (PciDs23));
+ memset (&PciDs30, 0, sizeof (PciDs30));
+ if (mOptions.Pci23 == 1) {
+ if (fread (&PciDs23, sizeof (PciDs23), 1, InFptr) != 1) {
+ Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName);
+ goto BailOut;
+ }
+ } else {
+ if (fread (&PciDs30, sizeof (PciDs30), 1, InFptr) != 1) {
+ Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName);
+ goto BailOut;
+ }
+ }
+ if (mOptions.Verbose) {
+ VerboseMsg("Read PCI data structure from file %s", InFile->FileName);
+ }
+
+ //fprintf (stdout, " PCI Data Structure\n");
+ if (mOptions.Pci23 == 1) {
+ fprintf (
+ stdout,
+ " Signature %c%c%c%c\n",
+ (char) PciDs23.Signature,
+ (char) (PciDs23.Signature >> 8),
+ (char) (PciDs23.Signature >> 16),
+ (char) (PciDs23.Signature >> 24)
+ );
+ fprintf (stdout, " Vendor ID 0x%04X\n", PciDs23.VendorId);
+ fprintf (stdout, " Device ID 0x%04X\n", PciDs23.DeviceId);
+ fprintf (stdout, " Length 0x%04X\n", PciDs23.Length);
+ fprintf (stdout, " Revision 0x%04X\n", PciDs23.Revision);
+ fprintf (
+ stdout,
+ " Class Code 0x%06X\n",
+ (unsigned) (PciDs23.ClassCode[0] | (PciDs23.ClassCode[1] << 8) | (PciDs23.ClassCode[2] << 16))
+ );
+ fprintf (stdout, " Image size 0x%X\n", (unsigned) PciDs23.ImageLength * 512);
+ fprintf (stdout, " Code revision: 0x%04X\n", PciDs23.CodeRevision);
+ fprintf (stdout, " Indicator 0x%02X", PciDs23.Indicator);
+ } else {
+ fprintf (
+ stdout,
+ " Signature %c%c%c%c\n",
+ (char) PciDs30.Signature,
+ (char) (PciDs30.Signature >> 8),
+ (char) (PciDs30.Signature >> 16),
+ (char) (PciDs30.Signature >> 24)
+ );
+ fprintf (stdout, " Vendor ID 0x%04X\n", PciDs30.VendorId);
+ fprintf (stdout, " Device ID 0x%04X\n", PciDs30.DeviceId);
+ fprintf (stdout, " Length 0x%04X\n", PciDs30.Length);
+ fprintf (stdout, " Revision 0x%04X\n", PciDs30.Revision);
+ fprintf (stdout, " DeviceListOffset 0x%02X\n", PciDs30.DeviceListOffset);
+ if (PciDs30.DeviceListOffset) {
+ //
+ // Print device ID list
+ //
+ fprintf (stdout, " Device list contents\n");
+ if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset + PciDs30.DeviceListOffset, SEEK_SET)) {
+ Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI device ID list!");
+ goto BailOut;
+ }
+
+ //
+ // Loop until terminating 0
+ //
+ do {
+ if (fread (&DevId, sizeof (DevId), 1, InFptr) != 1) {
+ Error (NULL, 0, 3001, "Not supported", "Failed to read PCI device ID list from file %s!", InFile->FileName);
+ goto BailOut;
+ }
+ if (DevId) {
+ fprintf (stdout, " 0x%04X\n", DevId);
+ }
+ } while (DevId);
+
+ }
+ fprintf (
+ stdout,
+ " Class Code 0x%06X\n",
+ (unsigned) (PciDs30.ClassCode[0] | (PciDs30.ClassCode[1] << 8) | (PciDs30.ClassCode[2] << 16))
+ );
+ fprintf (stdout, " Image size 0x%X\n", (unsigned) PciDs30.ImageLength * 512);
+ fprintf (stdout, " Code revision: 0x%04X\n", PciDs30.CodeRevision);
+ fprintf (stdout, " MaxRuntimeImageLength 0x%02X\n", PciDs30.MaxRuntimeImageLength);
+ fprintf (stdout, " ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset);
+ fprintf (stdout, " DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset);
+ fprintf (stdout, " Indicator 0x%02X", PciDs30.Indicator);
+ }
+ //
+ // Print the indicator, used to flag the last image
+ //
+ if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) {
+ fprintf (stdout, " (last image)\n");
+ } else {
+ fprintf (stdout, "\n");
+ }
+ //
+ // Print the code type. If EFI code, then we can provide more info.
+ //
+ if (mOptions.Pci23 == 1) {
+ fprintf (stdout, " Code type 0x%02X", PciDs23.CodeType);
+ } else {
+ fprintf (stdout, " Code type 0x%02X", PciDs30.CodeType);
+ }
+ if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
+ fprintf (stdout, " (EFI image)\n");
+ //
+ // Re-read the header as an EFI ROM header, then dump more info
+ //
+ fprintf (stdout, " EFI ROM header contents\n");
+ if (fseek (InFptr, ImageStart, SEEK_SET)) {
+ Error (NULL, 0, 5001, "Failed to re-seek to ROM header structure!", NULL);
+ goto BailOut;
+ }
+
+ if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {
+ Error (NULL, 0, 5001, "Failed to read EFI PCI ROM header from file!", NULL);
+ goto BailOut;
+ }
+ //
+ // Now dump more info
+ //
+ fprintf (stdout, " EFI Signature 0x%04X\n", (unsigned) EfiRomHdr.EfiSignature);
+ fprintf (
+ stdout,
+ " Compression Type 0x%04X ",
+ EfiRomHdr.CompressionType
+ );
+ if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ fprintf (stdout, "(compressed)\n");
+ } else {
+ fprintf (stdout, "(not compressed)\n");
+ }
+
+ fprintf (
+ stdout,
+ " Machine type 0x%04X (%s)\n",
+ EfiRomHdr.EfiMachineType,
+ GetMachineTypeStr (EfiRomHdr.EfiMachineType)
+ );
+ fprintf (
+ stdout,
+ " Subsystem 0x%04X (%s)\n",
+ EfiRomHdr.EfiSubsystem,
+ GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem)
+ );
+ fprintf (
+ stdout,
+ " EFI image offset 0x%04X (@0x%X)\n",
+ EfiRomHdr.EfiImageHeaderOffset,
+ EfiRomHdr.EfiImageHeaderOffset + (unsigned) ImageStart
+ );
+
+ } else {
+ //
+ // Not an EFI image
+ //
+ fprintf (stdout, "\n");
+ }
+ //
+ // If code type is EFI image, then dump it as well?
+ //
+ // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
+ // }
+ //
+ // If last image, then we're done
+ //
+ if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) {
+ goto BailOut;
+ }
+ //
+ // Seek to the start of the next image
+ //
+ if (mOptions.Pci23 == 1) {
+ if (fseek (InFptr, ImageStart + (PciDs23.ImageLength * 512), SEEK_SET)) {
+ Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!");
+ goto BailOut;
+ }
+ } else {
+ if (fseek (InFptr, ImageStart + (PciDs30.ImageLength * 512), SEEK_SET)) {
+ Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!");
+ goto BailOut;
+ }
+ }
+ }
+
+BailOut:
+ fclose (InFptr);
+}
+
+char *
+GetMachineTypeStr (
+ UINT16 MachineType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ MachineType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
+ if (mMachineTypes[Index].Value == MachineType) {
+ return mMachineTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
+
+static
+char *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SubsystemType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+{
+ int Index;
+
+ for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
+ if (mSubsystemTypes[Index].Value == SubsystemType) {
+ return mSubsystemTypes[Index].Name;
+ }
+ }
+
+ return "unknown";
+}
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.h
new file mode 100644
index 00000000..0a04e605
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.h
@@ -0,0 +1,353 @@
+/** @file
+This file contains the relevant declarations required to generate Option Rom File
+
+Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __EFI_ROM_H__
+#define __EFI_ROM_H__
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <Common/UefiBaseTypes.h>
+#include <IndustryStandard/PeImage.h> // for PE32 structure definitions
+
+#include <IndustryStandard/pci22.h> // for option ROM header structures
+#include <IndustryStandard/pci30.h>
+
+#include "Compress.h"
+#include "CommonLib.h"
+
+//
+// Version of this utility
+//
+#define UTILITY_NAME "EfiRom"
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+
+//
+// Define the max length of a filename
+//
+#define MAX_PATH 200
+
+//
+// Define the default file extension name
+//
+#define DEFAULT_OUTPUT_EXTENSION ".rom"
+
+//
+// Max size for an option ROM image
+//
+#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB
+
+//
+// Values for the indicator field in the PCI data structure
+//
+#define INDICATOR_LAST 0x80 // last file in series of files
+
+//
+// Masks for the FILE_LIST.FileFlags field
+//
+#define FILE_FLAG_BINARY 0x01
+#define FILE_FLAG_EFI 0x02
+#define FILE_FLAG_COMPRESS 0x04
+
+//
+// Use this linked list structure to keep track of all the filenames
+// specified on the command line.
+//
+typedef struct _FILE_LIST {
+ struct _FILE_LIST *Next;
+ CHAR8 *FileName;
+ UINT32 FileFlags;
+ UINT32 ClassCode;
+ UINT16 CodeRevision;
+} FILE_LIST;
+
+//
+// Use this to track our command-line options
+//
+typedef struct {
+ CHAR8 OutFileName[MAX_PATH];
+ INT8 NoLast;
+ UINT16 ClassCode;
+ UINT16 PciRevision;
+ UINT16 VendId;
+ UINT16 *DevIdList;
+ UINT32 DevIdCount;
+ UINT8 VendIdValid;
+ INT8 Verbose;
+ INT8 Quiet;
+ INT8 Debug;
+ INT8 Pci23;
+ INT8 Pci30;
+ INT8 DumpOption;
+// INT8 Help;
+// INT8 Version;
+ FILE_LIST *FileList;
+} OPTIONS;
+
+//
+// Make a global structure to keep track of command-line options
+//
+static OPTIONS mOptions;
+
+//
+// Use these to convert from machine type value to a named type
+//
+typedef struct {
+ UINT16 Value;
+ CHAR8 *Name;
+} STRING_LOOKUP;
+
+//
+// Machine Types
+//
+static STRING_LOOKUP mMachineTypes[] = {
+ { EFI_IMAGE_MACHINE_IA32, "IA32" },
+ { EFI_IMAGE_MACHINE_X64, "X64" },
+ { EFI_IMAGE_MACHINE_EBC, "EBC" },
+ { EFI_IMAGE_MACHINE_ARMT, "ARM" },
+ { EFI_IMAGE_MACHINE_AARCH64, "AA64" },
+ { 0, NULL }
+};
+
+//
+// Subsystem Types
+//
+static STRING_LOOKUP mSubsystemTypes[] = {
+ { EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION, "EFI application" },
+ { EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, "EFI boot service driver" },
+ { EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, "EFI runtime driver" },
+ { 0, NULL }
+};
+
+//
+// Function prototypes
+//
+static
+void
+Version (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility version to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+static
+void
+Usage (
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ Displays the utility usage syntax to STDOUT
+
+Arguments:
+
+ None
+
+Returns:
+
+ None
+
+--*/
+;
+
+static
+int
+ParseCommandLine (
+ int Argc,
+ char *Argv[],
+ OPTIONS *Options
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv[] - standard C main() argument list
+ Options - pointer to a structure to store the options in
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+;
+
+static
+int
+CheckPE32File (
+ FILE *Fptr,
+ UINT16 *MachineType,
+ UINT16 *SubSystem
+ )
+/*++
+
+Routine Description:
+
+ Given the Argc/Argv program arguments, and a pointer to an options structure,
+ parse the command-line options and check their validity.
+
+Arguments:
+
+ Argc - standard C main() argument count
+ Argv[] - standard C main() argument list
+ Options - pointer to a structure to store the options in
+
+Returns:
+
+ STATUS_SUCCESS success
+ non-zero otherwise
+
+--*/
+;
+
+static
+int
+ProcessEfiFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT16 VendId,
+ UINT16 DevId,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Process a PE32 EFI file.
+
+Arguments:
+
+ OutFptr - file pointer to output binary ROM image file we're creating
+ InFile - structure contains information on the PE32 file to process
+ VendId - vendor ID as required in the option ROM header
+ DevId - device ID as required in the option ROM header
+ Size - pointer to where to return the size added to the output file
+
+Returns:
+
+ 0 - successful
+
+--*/
+;
+
+static
+int
+ProcessBinFile (
+ FILE *OutFptr,
+ FILE_LIST *InFile,
+ UINT32 *Size
+ )
+/*++
+
+Routine Description:
+
+ Process a binary input file.
+
+Arguments:
+
+ OutFptr - file pointer to output binary ROM image file we're creating
+ InFile - structure contains information on the binary file to process
+ Size - pointer to where to return the size added to the output file
+
+Returns:
+
+ 0 - successful
+
+--*/
+;
+
+static
+void
+DumpImage (
+ FILE_LIST *InFile
+ )
+/*++
+
+Routine Description:
+
+ Dump the headers of an existing option ROM image
+
+Arguments:
+
+ InFile - the file name of an existing option ROM image
+
+Returns:
+
+ none
+
+--*/
+;
+
+char *
+GetMachineTypeStr (
+ UINT16 MachineType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ MachineType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+static
+char *
+GetSubsystemTypeStr (
+ UINT16 SubsystemType
+ )
+/*++
+
+Routine Description:
+
+ GC_TODO: Add function description
+
+Arguments:
+
+ SubsystemType - GC_TODO: add argument description
+
+Returns:
+
+ GC_TODO: add return values
+
+--*/
+;
+
+#endif
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/GNUmakefile
new file mode 100644
index 00000000..8b0e2c27
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/GNUmakefile
@@ -0,0 +1,15 @@
+## @file
+# GNU/Linux makefile for 'EfiRom' module build.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+MAKEROOT ?= ..
+
+APPNAME = EfiRom
+
+LIBS = -lCommon
+
+OBJECTS = EfiRom.o
+
+include $(MAKEROOT)/Makefiles/app.makefile
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile
new file mode 100644
index 00000000..ab64084c
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile
@@ -0,0 +1,16 @@
+## @file
+# Windows makefile for 'EfiRom' module build.
+#
+# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+!INCLUDE ..\Makefiles\ms.common
+
+APPNAME = EfiRom
+
+LIBS = $(LIB_PATH)\Common.lib
+
+OBJECTS = EfiRom.obj
+
+!INCLUDE ..\Makefiles\ms.app
+
diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile.kmk
new file mode 100644
index 00000000..29dd6c16
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile.kmk
@@ -0,0 +1,45 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-makefile for the EFI EfiRom build tool.
+#
+
+#
+# Copyright (C) 2013-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# The contents of this file may alternatively be used under the terms
+# of the Common Development and Distribution License Version 1.0
+# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+# in the VirtualBox distribution, in which case the provisions of the
+# CDDL are applicable instead of those of the GPL.
+#
+# You may elect to license modified versions of this file under the
+# terms and conditions of either the GPL or the CDDL or both.
+#
+# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+#
+
+SUB_DEPTH = ../../../../../../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+BLDPROGS += EfiRom
+EfiRom_TEMPLATE = VBoxEfiBldProg
+EfiRom_SOURCES = EfiRom.c
+
+include $(FILE_KBUILD_SUB_FOOTER)
+