EfiRom.c revision 1be2ed90a20618d71ddf34b8a07d038da0b36854
130fdf1140b8d1ce93f3821d986fa165552023440lgao/** @file
230fdf1140b8d1ce93f3821d986fa165552023440lgao
31be2ed90a20618d71ddf34b8a07d038da0b36854Hess ChenCopyright (c) 1999 - 2014, Intel Corporation. All rights reserved.<BR>
430fdf1140b8d1ce93f3821d986fa165552023440lgaoThis program and the accompanying materials are licensed and made available
530fdf1140b8d1ce93f3821d986fa165552023440lgaounder the terms and conditions of the BSD License which accompanies this
630fdf1140b8d1ce93f3821d986fa165552023440lgaodistribution.  The full text of the license may be found at
730fdf1140b8d1ce93f3821d986fa165552023440lgaohttp://opensource.org/licenses/bsd-license.php
830fdf1140b8d1ce93f3821d986fa165552023440lgao
930fdf1140b8d1ce93f3821d986fa165552023440lgaoTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
1030fdf1140b8d1ce93f3821d986fa165552023440lgaoWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
1130fdf1140b8d1ce93f3821d986fa165552023440lgao
1230fdf1140b8d1ce93f3821d986fa165552023440lgaoModule Name:
1330fdf1140b8d1ce93f3821d986fa165552023440lgao
1430fdf1140b8d1ce93f3821d986fa165552023440lgao  EfiRom.c
1530fdf1140b8d1ce93f3821d986fa165552023440lgao
1630fdf1140b8d1ce93f3821d986fa165552023440lgaoAbstract:
1730fdf1140b8d1ce93f3821d986fa165552023440lgao
1830fdf1140b8d1ce93f3821d986fa165552023440lgao  Utility program to create an EFI option ROM image from binary and
1930fdf1140b8d1ce93f3821d986fa165552023440lgao  EFI PE32 files.
2030fdf1140b8d1ce93f3821d986fa165552023440lgao
2130fdf1140b8d1ce93f3821d986fa165552023440lgao**/
2230fdf1140b8d1ce93f3821d986fa165552023440lgao
2330fdf1140b8d1ce93f3821d986fa165552023440lgao#include "EfiUtilityMsgs.h"
2430fdf1140b8d1ce93f3821d986fa165552023440lgao#include "ParseInf.h"
2530fdf1140b8d1ce93f3821d986fa165552023440lgao#include "EfiRom.h"
2630fdf1140b8d1ce93f3821d986fa165552023440lgao
2730fdf1140b8d1ce93f3821d986fa165552023440lgaoUINT64  DebugLevel = 0;
2830fdf1140b8d1ce93f3821d986fa165552023440lgao
2930fdf1140b8d1ce93f3821d986fa165552023440lgaoint
3030fdf1140b8d1ce93f3821d986fa165552023440lgaomain (
3130fdf1140b8d1ce93f3821d986fa165552023440lgao  int   Argc,
3230fdf1140b8d1ce93f3821d986fa165552023440lgao  char  *Argv[]
3330fdf1140b8d1ce93f3821d986fa165552023440lgao  )
3430fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
3530fdf1140b8d1ce93f3821d986fa165552023440lgao
3630fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
3730fdf1140b8d1ce93f3821d986fa165552023440lgao
3830fdf1140b8d1ce93f3821d986fa165552023440lgao  Given an EFI image filename, create a ROM-able image by creating an option
3930fdf1140b8d1ce93f3821d986fa165552023440lgao  ROM header and PCI data structure, filling them in, and then writing the
4030fdf1140b8d1ce93f3821d986fa165552023440lgao  option ROM header + PCI data structure + EFI image out to the output file.
4130fdf1140b8d1ce93f3821d986fa165552023440lgao
4230fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
4330fdf1140b8d1ce93f3821d986fa165552023440lgao
4430fdf1140b8d1ce93f3821d986fa165552023440lgao  Argc            - standard C main() argument count
4530fdf1140b8d1ce93f3821d986fa165552023440lgao
4630fdf1140b8d1ce93f3821d986fa165552023440lgao  Argv            - standard C main() argument list
4730fdf1140b8d1ce93f3821d986fa165552023440lgao
4830fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
4930fdf1140b8d1ce93f3821d986fa165552023440lgao
5030fdf1140b8d1ce93f3821d986fa165552023440lgao  0             success
5130fdf1140b8d1ce93f3821d986fa165552023440lgao  non-zero      otherwise
5230fdf1140b8d1ce93f3821d986fa165552023440lgao
5330fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
5430fdf1140b8d1ce93f3821d986fa165552023440lgao{
5530fdf1140b8d1ce93f3821d986fa165552023440lgao  CHAR8     *Ext;
5630fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE      *FptrOut;
5730fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32    Status;
5830fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE_LIST *FList;
5930fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32    TotalSize;
6030fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32    Size;
6130fdf1140b8d1ce93f3821d986fa165552023440lgao  CHAR8     *Ptr0;
6230fdf1140b8d1ce93f3821d986fa165552023440lgao
6330fdf1140b8d1ce93f3821d986fa165552023440lgao  SetUtilityName(UTILITY_NAME);
6430fdf1140b8d1ce93f3821d986fa165552023440lgao
6530fdf1140b8d1ce93f3821d986fa165552023440lgao  Status  = STATUS_SUCCESS;
6630fdf1140b8d1ce93f3821d986fa165552023440lgao  FptrOut = NULL;
6730fdf1140b8d1ce93f3821d986fa165552023440lgao
6830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
6930fdf1140b8d1ce93f3821d986fa165552023440lgao  // Parse the command line arguments
7030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
7130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (ParseCommandLine (Argc, Argv, &mOptions)) {
7230fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
7330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
7430fdf1140b8d1ce93f3821d986fa165552023440lgao
7530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Quiet) {
7630fdf1140b8d1ce93f3821d986fa165552023440lgao    SetPrintLevel(40);
7730fdf1140b8d1ce93f3821d986fa165552023440lgao  } else if (mOptions.Verbose) {
7830fdf1140b8d1ce93f3821d986fa165552023440lgao    SetPrintLevel(15);
7930fdf1140b8d1ce93f3821d986fa165552023440lgao  } else if (mOptions.Debug) {
8030fdf1140b8d1ce93f3821d986fa165552023440lgao    SetPrintLevel(DebugLevel);
8130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
8230fdf1140b8d1ce93f3821d986fa165552023440lgao
8330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Verbose) {
8430fdf1140b8d1ce93f3821d986fa165552023440lgao    VerboseMsg("%s tool start.\n", UTILITY_NAME);
8530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
8630fdf1140b8d1ce93f3821d986fa165552023440lgao
8730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
8830fdf1140b8d1ce93f3821d986fa165552023440lgao  // If dumping an image, then do that and quit
8930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
9030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.DumpOption == 1) {
91fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    if (mOptions.FileList != NULL) {
92fd171542e0aa89ac12a09d79608173f48019b14bvanjeff      if ((Ptr0 = strstr ((CONST CHAR8 *) mOptions.FileList->FileName, DEFAULT_OUTPUT_EXTENSION)) != NULL) {
9330fdf1140b8d1ce93f3821d986fa165552023440lgao        DumpImage (mOptions.FileList);
9430fdf1140b8d1ce93f3821d986fa165552023440lgao        goto BailOut;
9530fdf1140b8d1ce93f3821d986fa165552023440lgao      } else {
9630fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 1002, "No PciRom input file", "No *.rom input file");
9730fdf1140b8d1ce93f3821d986fa165552023440lgao        goto BailOut;
9830fdf1140b8d1ce93f3821d986fa165552023440lgao      }
9930fdf1140b8d1ce93f3821d986fa165552023440lgao    }
10030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
10130fdf1140b8d1ce93f3821d986fa165552023440lgao  //
10230fdf1140b8d1ce93f3821d986fa165552023440lgao  // Determine the output filename. Either what they specified on
10330fdf1140b8d1ce93f3821d986fa165552023440lgao  // the command line, or the first input filename with a different extension.
10430fdf1140b8d1ce93f3821d986fa165552023440lgao  //
10530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (!mOptions.OutFileName[0]) {
10630fdf1140b8d1ce93f3821d986fa165552023440lgao    strcpy (mOptions.OutFileName, mOptions.FileList->FileName);
10730fdf1140b8d1ce93f3821d986fa165552023440lgao    //
10830fdf1140b8d1ce93f3821d986fa165552023440lgao    // Find the last . on the line and replace the filename extension with
10930fdf1140b8d1ce93f3821d986fa165552023440lgao    // the default
11030fdf1140b8d1ce93f3821d986fa165552023440lgao    //
11130fdf1140b8d1ce93f3821d986fa165552023440lgao    for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1;
11230fdf1140b8d1ce93f3821d986fa165552023440lgao         (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\');
11330fdf1140b8d1ce93f3821d986fa165552023440lgao         Ext--
11430fdf1140b8d1ce93f3821d986fa165552023440lgao        )
11530fdf1140b8d1ce93f3821d986fa165552023440lgao      ;
11630fdf1140b8d1ce93f3821d986fa165552023440lgao    //
11730fdf1140b8d1ce93f3821d986fa165552023440lgao    // If dot here, then insert extension here, otherwise append
11830fdf1140b8d1ce93f3821d986fa165552023440lgao    //
11930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (*Ext != '.') {
12030fdf1140b8d1ce93f3821d986fa165552023440lgao      Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
12130fdf1140b8d1ce93f3821d986fa165552023440lgao    }
12230fdf1140b8d1ce93f3821d986fa165552023440lgao
12330fdf1140b8d1ce93f3821d986fa165552023440lgao    strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
12430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
12530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
12630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Make sure we don't have the same filename for input and output files
12730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
12830fdf1140b8d1ce93f3821d986fa165552023440lgao  for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
12930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (stricmp (mOptions.OutFileName, FList->FileName) == 0) {
13030fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
13130fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 1002, "Invalid input paramter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName);
13230fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
13330fdf1140b8d1ce93f3821d986fa165552023440lgao    }
13430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
13530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
13630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Now open our output file
13730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
1381be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chen  if ((FptrOut = fopen (LongFilePath (mOptions.OutFileName), "wb")) == NULL) {
13930fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", mOptions.OutFileName);
14030fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
14130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
14230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
14330fdf1140b8d1ce93f3821d986fa165552023440lgao  // Process all our files
14430fdf1140b8d1ce93f3821d986fa165552023440lgao  //
14530fdf1140b8d1ce93f3821d986fa165552023440lgao  TotalSize = 0;
14630fdf1140b8d1ce93f3821d986fa165552023440lgao  for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
14730fdf1140b8d1ce93f3821d986fa165552023440lgao    Size = 0;
14830fdf1140b8d1ce93f3821d986fa165552023440lgao    if ((FList->FileFlags & FILE_FLAG_EFI) != 0) {
14930fdf1140b8d1ce93f3821d986fa165552023440lgao      if (mOptions.Verbose) {
15030fdf1140b8d1ce93f3821d986fa165552023440lgao        VerboseMsg("Processing EFI file    %s\n", FList->FileName);
15130fdf1140b8d1ce93f3821d986fa165552023440lgao      }
15230fdf1140b8d1ce93f3821d986fa165552023440lgao
15330fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);
15430fdf1140b8d1ce93f3821d986fa165552023440lgao    } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) {
15530fdf1140b8d1ce93f3821d986fa165552023440lgao      if (mOptions.Verbose) {
15630fdf1140b8d1ce93f3821d986fa165552023440lgao        VerboseMsg("Processing binary file %s\n", FList->FileName);
15730fdf1140b8d1ce93f3821d986fa165552023440lgao      }
15830fdf1140b8d1ce93f3821d986fa165552023440lgao
15930fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = ProcessBinFile (FptrOut, FList, &Size);
16030fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
16130fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 2000, "Invalid parameter", "File type not specified, it must be either an EFI or binary file: %s.", FList->FileName);
16230fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
16330fdf1140b8d1ce93f3821d986fa165552023440lgao    }
16430fdf1140b8d1ce93f3821d986fa165552023440lgao
16530fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Verbose) {
166fd171542e0aa89ac12a09d79608173f48019b14bvanjeff      VerboseMsg("  Output size = 0x%X\n", (unsigned) Size);
16730fdf1140b8d1ce93f3821d986fa165552023440lgao    }
16830fdf1140b8d1ce93f3821d986fa165552023440lgao
16930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (Status != STATUS_SUCCESS) {
17030fdf1140b8d1ce93f3821d986fa165552023440lgao      break;
17130fdf1140b8d1ce93f3821d986fa165552023440lgao    }
17230fdf1140b8d1ce93f3821d986fa165552023440lgao
17330fdf1140b8d1ce93f3821d986fa165552023440lgao    TotalSize += Size;
17430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
17530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
17630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Check total size
17730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
17830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (TotalSize > MAX_OPTION_ROM_SIZE) {
17930fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid paramter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE);
18030fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
18130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
18230fdf1140b8d1ce93f3821d986fa165552023440lgao
18330fdf1140b8d1ce93f3821d986fa165552023440lgaoBailOut:
18430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Status == STATUS_SUCCESS) {
18530fdf1140b8d1ce93f3821d986fa165552023440lgao    if (FptrOut != NULL) {
18630fdf1140b8d1ce93f3821d986fa165552023440lgao      fclose (FptrOut);
18730fdf1140b8d1ce93f3821d986fa165552023440lgao    }
18830fdf1140b8d1ce93f3821d986fa165552023440lgao    //
18930fdf1140b8d1ce93f3821d986fa165552023440lgao    // Clean up our file list
19030fdf1140b8d1ce93f3821d986fa165552023440lgao    //
19130fdf1140b8d1ce93f3821d986fa165552023440lgao    while (mOptions.FileList != NULL) {
19230fdf1140b8d1ce93f3821d986fa165552023440lgao      FList = mOptions.FileList->Next;
19330fdf1140b8d1ce93f3821d986fa165552023440lgao      free (mOptions.FileList);
19430fdf1140b8d1ce93f3821d986fa165552023440lgao      mOptions.FileList = FList;
19530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
19630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
19730fdf1140b8d1ce93f3821d986fa165552023440lgao
19830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Verbose) {
19930fdf1140b8d1ce93f3821d986fa165552023440lgao    VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ());
20030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
20130fdf1140b8d1ce93f3821d986fa165552023440lgao
20230fdf1140b8d1ce93f3821d986fa165552023440lgao  return GetUtilityStatus ();
20330fdf1140b8d1ce93f3821d986fa165552023440lgao}
20430fdf1140b8d1ce93f3821d986fa165552023440lgao
20530fdf1140b8d1ce93f3821d986fa165552023440lgaostatic
20630fdf1140b8d1ce93f3821d986fa165552023440lgaoint
20730fdf1140b8d1ce93f3821d986fa165552023440lgaoProcessBinFile (
20830fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE      *OutFptr,
20930fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE_LIST *InFile,
21030fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32    *Size
21130fdf1140b8d1ce93f3821d986fa165552023440lgao  )
21230fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
21330fdf1140b8d1ce93f3821d986fa165552023440lgao
21430fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
21530fdf1140b8d1ce93f3821d986fa165552023440lgao
21630fdf1140b8d1ce93f3821d986fa165552023440lgao  Process a binary input file.
21730fdf1140b8d1ce93f3821d986fa165552023440lgao
21830fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
21930fdf1140b8d1ce93f3821d986fa165552023440lgao
22030fdf1140b8d1ce93f3821d986fa165552023440lgao  OutFptr     - file pointer to output binary ROM image file we're creating
22130fdf1140b8d1ce93f3821d986fa165552023440lgao  InFile      - structure contains information on the binary file to process
22230fdf1140b8d1ce93f3821d986fa165552023440lgao  Size        - pointer to where to return the size added to the output file
22330fdf1140b8d1ce93f3821d986fa165552023440lgao
22430fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
22530fdf1140b8d1ce93f3821d986fa165552023440lgao
22630fdf1140b8d1ce93f3821d986fa165552023440lgao  0 - successful
22730fdf1140b8d1ce93f3821d986fa165552023440lgao
22830fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
22930fdf1140b8d1ce93f3821d986fa165552023440lgao{
23030fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE                      *InFptr;
23130fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                    TotalSize;
23230fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                    FileSize;
23330fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT8                     *Buffer;
23430fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                    Status;
23530fdf1140b8d1ce93f3821d986fa165552023440lgao  PCI_EXPANSION_ROM_HEADER  *RomHdr;
23630fdf1140b8d1ce93f3821d986fa165552023440lgao  PCI_DATA_STRUCTURE        *PciDs23;
23730fdf1140b8d1ce93f3821d986fa165552023440lgao  PCI_3_0_DATA_STRUCTURE    *PciDs30;
23830fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                    Index;
23930fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT8                     ByteCheckSum;
2402bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  UINT16                    CodeType;
24130fdf1140b8d1ce93f3821d986fa165552023440lgao
242fd171542e0aa89ac12a09d79608173f48019b14bvanjeff  PciDs23 = NULL;
243fd171542e0aa89ac12a09d79608173f48019b14bvanjeff  PciDs30 = NULL;
24430fdf1140b8d1ce93f3821d986fa165552023440lgao  Status = STATUS_SUCCESS;
24530fdf1140b8d1ce93f3821d986fa165552023440lgao
24630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
24730fdf1140b8d1ce93f3821d986fa165552023440lgao  // Try to open the input file
24830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
2491be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chen  if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
25030fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0001, "Error opening file", InFile->FileName);
25130fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
25230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
25330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
25430fdf1140b8d1ce93f3821d986fa165552023440lgao  // Seek to the end of the input file and get the file size. Then allocate
25530fdf1140b8d1ce93f3821d986fa165552023440lgao  // a buffer to read it in to.
25630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
25730fdf1140b8d1ce93f3821d986fa165552023440lgao  fseek (InFptr, 0, SEEK_END);
25830fdf1140b8d1ce93f3821d986fa165552023440lgao  FileSize = ftell (InFptr);
25930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Verbose) {
260fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    VerboseMsg("  File size   = 0x%X\n", (unsigned) FileSize);
26130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
26230fdf1140b8d1ce93f3821d986fa165552023440lgao
26330fdf1140b8d1ce93f3821d986fa165552023440lgao  fseek (InFptr, 0, SEEK_SET);
26430fdf1140b8d1ce93f3821d986fa165552023440lgao  Buffer = (UINT8 *) malloc (FileSize);
26530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Buffer == NULL) {
26630fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 4003, "Resource", "memory cannot be allocated!");
26730fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
26830fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
26930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
27030fdf1140b8d1ce93f3821d986fa165552023440lgao
27130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (fread (Buffer, FileSize, 1, InFptr) != 1) {
27230fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid", "Failed to read all bytes from input file.");
27330fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
27430fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
27530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
27630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
27730fdf1140b8d1ce93f3821d986fa165552023440lgao  // Total size must be an even multiple of 512 bytes, and can't exceed
27830fdf1140b8d1ce93f3821d986fa165552023440lgao  // the option ROM image size.
27930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
28030fdf1140b8d1ce93f3821d986fa165552023440lgao  TotalSize = FileSize;
28130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (TotalSize & 0x1FF) {
28230fdf1140b8d1ce93f3821d986fa165552023440lgao    TotalSize = (TotalSize + 0x200) &~0x1ff;
28330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
28430fdf1140b8d1ce93f3821d986fa165552023440lgao
28530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (TotalSize > MAX_OPTION_ROM_SIZE) {
28630fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 3001, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);
28730fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
28830fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
28930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
29030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
29130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Return the size to the caller so they can keep track of the running total.
29230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
29330fdf1140b8d1ce93f3821d986fa165552023440lgao  *Size = TotalSize;
29430fdf1140b8d1ce93f3821d986fa165552023440lgao
29530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
29630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Crude check to make sure it's a legitimate ROM image
29730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
29830fdf1140b8d1ce93f3821d986fa165552023440lgao  RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer;
29930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
30030fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid parameter", "ROM image file has an invalid ROM signature.");
30130fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
30230fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
30330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
30430fdf1140b8d1ce93f3821d986fa165552023440lgao  //
30530fdf1140b8d1ce93f3821d986fa165552023440lgao  // Make sure the pointer to the PCI data structure is within the size of the image.
30630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Then check it for valid signature.
30730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
30830fdf1140b8d1ce93f3821d986fa165552023440lgao  if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {
30930fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid parameter", "Invalid PCI data structure offset.");
31030fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
31130fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
31230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
31330fdf1140b8d1ce93f3821d986fa165552023440lgao
31430fdf1140b8d1ce93f3821d986fa165552023440lgao  //
31530fdf1140b8d1ce93f3821d986fa165552023440lgao  // Check the header is conform to PCI2.3 or PCI3.0
31630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
31730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Pci23 == 1) {
31830fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23 = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset);
31930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (PciDs23->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
32030fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature.");
32130fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
32230fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
32330fdf1140b8d1ce93f3821d986fa165552023440lgao    }
32430fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
32530fdf1140b8d1ce93f3821d986fa165552023440lgao    //
32630fdf1140b8d1ce93f3821d986fa165552023440lgao    // Default setting is PCI3.0 header
32730fdf1140b8d1ce93f3821d986fa165552023440lgao    //
32830fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30 = (PCI_3_0_DATA_STRUCTURE *)(Buffer + RomHdr->PcirOffset);
32930fdf1140b8d1ce93f3821d986fa165552023440lgao    if (PciDs30->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
33030fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature.");
33130fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
33230fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
33330fdf1140b8d1ce93f3821d986fa165552023440lgao    }
33430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
33530fdf1140b8d1ce93f3821d986fa165552023440lgao
33630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
33730fdf1140b8d1ce93f3821d986fa165552023440lgao  // ReSet Option Rom size
33830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
33930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Pci23 == 1) {
34030fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23->ImageLength = (UINT16) (TotalSize / 512);
3412bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    CodeType = PciDs23->CodeType;
34230fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
34330fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30->ImageLength = (UINT16) (TotalSize / 512);
3442bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    CodeType = PciDs30->CodeType;
34530fdf1140b8d1ce93f3821d986fa165552023440lgao	}
34630fdf1140b8d1ce93f3821d986fa165552023440lgao
34730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
34830fdf1140b8d1ce93f3821d986fa165552023440lgao  // If this is the last image, then set the LAST bit unless requested not
34930fdf1140b8d1ce93f3821d986fa165552023440lgao  // to via the command-line -n argument. Otherwise, make sure you clear it.
35030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
35130fdf1140b8d1ce93f3821d986fa165552023440lgao  if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
35230fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Pci23 == 1) {
35330fdf1140b8d1ce93f3821d986fa165552023440lgao      PciDs23->Indicator = INDICATOR_LAST;
35430fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
35530fdf1140b8d1ce93f3821d986fa165552023440lgao      PciDs30->Indicator = INDICATOR_LAST;
35630fdf1140b8d1ce93f3821d986fa165552023440lgao		}
35730fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
35830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Pci23 == 1) {
35930fdf1140b8d1ce93f3821d986fa165552023440lgao      PciDs23->Indicator = 0;
36030fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
36130fdf1140b8d1ce93f3821d986fa165552023440lgao      PciDs30->Indicator = 0;
36230fdf1140b8d1ce93f3821d986fa165552023440lgao		}
36330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
36430fdf1140b8d1ce93f3821d986fa165552023440lgao
3652bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  if (CodeType != PCI_CODE_TYPE_EFI_IMAGE) {
3662bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    ByteCheckSum = 0;
3672bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    for (Index = 0; Index < FileSize - 1; Index++) {
3682bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming      ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]);
3692bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    }
37030fdf1140b8d1ce93f3821d986fa165552023440lgao
3712bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1);
3722bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    if (mOptions.Verbose) {
3732bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming      VerboseMsg("  Checksum = %02x\n\n", Buffer[FileSize - 1]);
3742bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    }
37530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
37630fdf1140b8d1ce93f3821d986fa165552023440lgao
37730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
37830fdf1140b8d1ce93f3821d986fa165552023440lgao  // Now copy the input file contents out to the output file
37930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
38030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
38130fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0005, "Failed to write all file bytes to output file.", NULL);
38230fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
38330fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
38430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
38530fdf1140b8d1ce93f3821d986fa165552023440lgao
38630fdf1140b8d1ce93f3821d986fa165552023440lgao  TotalSize -= FileSize;
38730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
38830fdf1140b8d1ce93f3821d986fa165552023440lgao  // Pad the rest of the image to make it a multiple of 512 bytes
38930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
39030fdf1140b8d1ce93f3821d986fa165552023440lgao  while (TotalSize > 0) {
39130fdf1140b8d1ce93f3821d986fa165552023440lgao    putc (~0, OutFptr);
39230fdf1140b8d1ce93f3821d986fa165552023440lgao    TotalSize--;
39330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
39430fdf1140b8d1ce93f3821d986fa165552023440lgao
39530fdf1140b8d1ce93f3821d986fa165552023440lgaoBailOut:
39630fdf1140b8d1ce93f3821d986fa165552023440lgao  if (InFptr != NULL) {
39730fdf1140b8d1ce93f3821d986fa165552023440lgao    fclose (InFptr);
39830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
39930fdf1140b8d1ce93f3821d986fa165552023440lgao
40030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Buffer != NULL) {
40130fdf1140b8d1ce93f3821d986fa165552023440lgao    free (Buffer);
40230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
40330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
40430fdf1140b8d1ce93f3821d986fa165552023440lgao  // Print the file name if errors occurred
40530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
40630fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Status != STATUS_SUCCESS) {
40730fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0003, "Error", "Error parsing file: %s", InFile->FileName);
40830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
40930fdf1140b8d1ce93f3821d986fa165552023440lgao
41030fdf1140b8d1ce93f3821d986fa165552023440lgao  return Status;
41130fdf1140b8d1ce93f3821d986fa165552023440lgao}
41230fdf1140b8d1ce93f3821d986fa165552023440lgao
41330fdf1140b8d1ce93f3821d986fa165552023440lgaostatic
41430fdf1140b8d1ce93f3821d986fa165552023440lgaoint
41530fdf1140b8d1ce93f3821d986fa165552023440lgaoProcessEfiFile (
41630fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE      *OutFptr,
41730fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE_LIST *InFile,
41830fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT16    VendId,
41930fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT16    DevId,
42030fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32    *Size
42130fdf1140b8d1ce93f3821d986fa165552023440lgao  )
42230fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
42330fdf1140b8d1ce93f3821d986fa165552023440lgao
42430fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
42530fdf1140b8d1ce93f3821d986fa165552023440lgao
42630fdf1140b8d1ce93f3821d986fa165552023440lgao  Process a PE32 EFI file.
42730fdf1140b8d1ce93f3821d986fa165552023440lgao
42830fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
42930fdf1140b8d1ce93f3821d986fa165552023440lgao
43030fdf1140b8d1ce93f3821d986fa165552023440lgao  OutFptr     - file pointer to output binary ROM image file we're creating
43130fdf1140b8d1ce93f3821d986fa165552023440lgao  InFile      - structure contains information on the PE32 file to process
43230fdf1140b8d1ce93f3821d986fa165552023440lgao  VendId      - vendor ID as required in the option ROM header
43330fdf1140b8d1ce93f3821d986fa165552023440lgao  DevId       - device ID as required in the option ROM header
43430fdf1140b8d1ce93f3821d986fa165552023440lgao  Size        - pointer to where to return the size added to the output file
43530fdf1140b8d1ce93f3821d986fa165552023440lgao
43630fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
43730fdf1140b8d1ce93f3821d986fa165552023440lgao
43830fdf1140b8d1ce93f3821d986fa165552023440lgao  0 - successful
43930fdf1140b8d1ce93f3821d986fa165552023440lgao
44030fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
44130fdf1140b8d1ce93f3821d986fa165552023440lgao{
44230fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                        Status;
44330fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE                          *InFptr;
44430fdf1140b8d1ce93f3821d986fa165552023440lgao  EFI_PCI_EXPANSION_ROM_HEADER  RomHdr;
44530fdf1140b8d1ce93f3821d986fa165552023440lgao  PCI_DATA_STRUCTURE            PciDs23;
44630fdf1140b8d1ce93f3821d986fa165552023440lgao  PCI_3_0_DATA_STRUCTURE        PciDs30;
44730fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                        FileSize;
44830fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                        CompressedFileSize;
44930fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT8                         *Buffer;
45030fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT8                         *CompressedBuffer;
45130fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT8                         *TempBufferPtr;
45230fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                        TotalSize;
45330fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                        HeaderSize;
45430fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT16                        MachineType;
45530fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT16                        SubSystem;
45630fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                        HeaderPadBytes;
4572bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  UINT32                        PadBytesBeforeImage;
4582bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  UINT32                        PadBytesAfterImage;
45930fdf1140b8d1ce93f3821d986fa165552023440lgao
46030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
46130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Try to open the input file
46230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
4631be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chen  if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
46430fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", InFile->FileName);
46530fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
46630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
46730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
46830fdf1140b8d1ce93f3821d986fa165552023440lgao  // Initialize our buffer pointers to null.
46930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
47030fdf1140b8d1ce93f3821d986fa165552023440lgao  Buffer            = NULL;
47130fdf1140b8d1ce93f3821d986fa165552023440lgao  CompressedBuffer  = NULL;
47230fdf1140b8d1ce93f3821d986fa165552023440lgao
47330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
47430fdf1140b8d1ce93f3821d986fa165552023440lgao  // Double-check the file to make sure it's what we expect it to be
47530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
47630fdf1140b8d1ce93f3821d986fa165552023440lgao  Status = CheckPE32File (InFptr, &MachineType, &SubSystem);
47730fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Status != STATUS_SUCCESS) {
47830fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
47930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
48030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
48130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Seek to the end of the input file and get the file size
48230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
48330fdf1140b8d1ce93f3821d986fa165552023440lgao  fseek (InFptr, 0, SEEK_END);
48430fdf1140b8d1ce93f3821d986fa165552023440lgao  FileSize = ftell (InFptr);
48530fdf1140b8d1ce93f3821d986fa165552023440lgao
48630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
48730fdf1140b8d1ce93f3821d986fa165552023440lgao  // Get the size of the headers we're going to put in front of the image. The
48830fdf1140b8d1ce93f3821d986fa165552023440lgao  // EFI header must be aligned on a 4-byte boundary, so pad accordingly.
48930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
49030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (sizeof (RomHdr) & 0x03) {
49130fdf1140b8d1ce93f3821d986fa165552023440lgao    HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);
49230fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
49330fdf1140b8d1ce93f3821d986fa165552023440lgao    HeaderPadBytes = 0;
49430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
49530fdf1140b8d1ce93f3821d986fa165552023440lgao
49630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
49730fdf1140b8d1ce93f3821d986fa165552023440lgao  // For Pci3.0 to use the different data structure.
49830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
49930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Pci23 == 1) {
50030fdf1140b8d1ce93f3821d986fa165552023440lgao    HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
50130fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
50230fdf1140b8d1ce93f3821d986fa165552023440lgao    HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
50330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
50430fdf1140b8d1ce93f3821d986fa165552023440lgao
50530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Verbose) {
506fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    VerboseMsg("  File size   = 0x%X\n", (unsigned) FileSize);
50730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
50830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
50930fdf1140b8d1ce93f3821d986fa165552023440lgao  // Allocate memory for the entire file (in case we have to compress), then
51030fdf1140b8d1ce93f3821d986fa165552023440lgao  // seek back to the beginning of the file and read it into our buffer.
51130fdf1140b8d1ce93f3821d986fa165552023440lgao  //
51230fdf1140b8d1ce93f3821d986fa165552023440lgao  Buffer = (UINT8 *) malloc (FileSize);
51330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Buffer == NULL) {
51430fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
51530fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
51630fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
51730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
51830fdf1140b8d1ce93f3821d986fa165552023440lgao
51930fdf1140b8d1ce93f3821d986fa165552023440lgao  fseek (InFptr, 0, SEEK_SET);
52030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (fread (Buffer, FileSize, 1, InFptr) != 1) {
52130fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0004, "Error reading file", "File %s", InFile->FileName);
52230fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
52330fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
52430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
52530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
52630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Now determine the size of the final output file. It's either the header size
52730fdf1140b8d1ce93f3821d986fa165552023440lgao  // plus the file's size, or the header size plus the compressed file size.
52830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
52930fdf1140b8d1ce93f3821d986fa165552023440lgao  if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) {
53030fdf1140b8d1ce93f3821d986fa165552023440lgao    //
53130fdf1140b8d1ce93f3821d986fa165552023440lgao    // Allocate a buffer into which we can compress the image, compress it,
53230fdf1140b8d1ce93f3821d986fa165552023440lgao    // and use that size as the new size.
53330fdf1140b8d1ce93f3821d986fa165552023440lgao    //
53430fdf1140b8d1ce93f3821d986fa165552023440lgao    CompressedBuffer = (UINT8 *) malloc (FileSize);
53530fdf1140b8d1ce93f3821d986fa165552023440lgao    if (CompressedBuffer == NULL) {
53630fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!");
53730fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
53830fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
53930fdf1140b8d1ce93f3821d986fa165552023440lgao    }
54030fdf1140b8d1ce93f3821d986fa165552023440lgao
54130fdf1140b8d1ce93f3821d986fa165552023440lgao    CompressedFileSize  = FileSize;
54230fdf1140b8d1ce93f3821d986fa165552023440lgao    Status              = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);
54330fdf1140b8d1ce93f3821d986fa165552023440lgao    if (Status != STATUS_SUCCESS) {
54430fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 0007, "Error compressing file!", NULL);
54530fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
54630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
54730fdf1140b8d1ce93f3821d986fa165552023440lgao    //
54830fdf1140b8d1ce93f3821d986fa165552023440lgao    // Now compute the size, then swap buffer pointers.
54930fdf1140b8d1ce93f3821d986fa165552023440lgao    //
55030fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Verbose) {
551fd171542e0aa89ac12a09d79608173f48019b14bvanjeff      VerboseMsg("  Comp size   = 0x%X\n", (unsigned) CompressedFileSize);
55230fdf1140b8d1ce93f3821d986fa165552023440lgao    }
55330fdf1140b8d1ce93f3821d986fa165552023440lgao
55430fdf1140b8d1ce93f3821d986fa165552023440lgao    TotalSize         = CompressedFileSize + HeaderSize;
55530fdf1140b8d1ce93f3821d986fa165552023440lgao    FileSize          = CompressedFileSize;
55630fdf1140b8d1ce93f3821d986fa165552023440lgao    TempBufferPtr     = Buffer;
55730fdf1140b8d1ce93f3821d986fa165552023440lgao    Buffer            = CompressedBuffer;
55830fdf1140b8d1ce93f3821d986fa165552023440lgao    CompressedBuffer  = TempBufferPtr;
55930fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
56030fdf1140b8d1ce93f3821d986fa165552023440lgao    TotalSize = FileSize + HeaderSize;
56130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
56230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
56330fdf1140b8d1ce93f3821d986fa165552023440lgao  // Total size must be an even multiple of 512 bytes
56430fdf1140b8d1ce93f3821d986fa165552023440lgao  //
56530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (TotalSize & 0x1FF) {
56630fdf1140b8d1ce93f3821d986fa165552023440lgao    TotalSize = (TotalSize + 0x200) &~0x1ff;
56730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
56830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
5692bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  // Workaround:
5702bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  //   If compressed, put the pad bytes after the image,
5712bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  //   else put the pad bytes before the image.
5722bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  //
5732bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) {
5742bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    PadBytesBeforeImage = 0;
5752bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    PadBytesAfterImage = TotalSize - (FileSize + HeaderSize);
5762bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  } else {
5772bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    PadBytesBeforeImage = TotalSize - (FileSize + HeaderSize);
5782bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    PadBytesAfterImage = 0;
5792bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  }
5802bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  //
58130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Check size
58230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
58330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (TotalSize > MAX_OPTION_ROM_SIZE) {
58430fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE);
58530fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
58630fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
58730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
58830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
58930fdf1140b8d1ce93f3821d986fa165552023440lgao  // Return the size to the caller so they can keep track of the running total.
59030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
59130fdf1140b8d1ce93f3821d986fa165552023440lgao  *Size = TotalSize;
59230fdf1140b8d1ce93f3821d986fa165552023440lgao
59330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
59430fdf1140b8d1ce93f3821d986fa165552023440lgao  // Now fill in the ROM header. These values come from chapter 18 of the
59530fdf1140b8d1ce93f3821d986fa165552023440lgao  // EFI 1.02 specification.
59630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
59730fdf1140b8d1ce93f3821d986fa165552023440lgao  memset (&RomHdr, 0, sizeof (RomHdr));
59830fdf1140b8d1ce93f3821d986fa165552023440lgao  RomHdr.Signature            = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
59930fdf1140b8d1ce93f3821d986fa165552023440lgao  RomHdr.InitializationSize   = (UINT16) (TotalSize / 512);
60030fdf1140b8d1ce93f3821d986fa165552023440lgao  RomHdr.EfiSignature         = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
60130fdf1140b8d1ce93f3821d986fa165552023440lgao  RomHdr.EfiSubsystem         = SubSystem;
60230fdf1140b8d1ce93f3821d986fa165552023440lgao  RomHdr.EfiMachineType       = MachineType;
6032bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  RomHdr.EfiImageHeaderOffset = (UINT16) (HeaderSize + PadBytesBeforeImage);
60430fdf1140b8d1ce93f3821d986fa165552023440lgao  RomHdr.PcirOffset           = (UINT16) (sizeof (RomHdr) + HeaderPadBytes);
60530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
60630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Set image as compressed or not
60730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
60830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
60930fdf1140b8d1ce93f3821d986fa165552023440lgao    RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;
61030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
61130fdf1140b8d1ce93f3821d986fa165552023440lgao  //
61230fdf1140b8d1ce93f3821d986fa165552023440lgao  // Fill in the PCI data structure
61330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
61430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Pci23 == 1) {
61530fdf1140b8d1ce93f3821d986fa165552023440lgao    memset (&PciDs23, 0, sizeof (PCI_DATA_STRUCTURE));
61630fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
61730fdf1140b8d1ce93f3821d986fa165552023440lgao    memset (&PciDs30, 0, sizeof (PCI_3_0_DATA_STRUCTURE));
61830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
61930fdf1140b8d1ce93f3821d986fa165552023440lgao
62030fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Pci23 == 1) {
62130fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
62230fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.VendorId  = VendId;
62330fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.DeviceId  = DevId;
62430fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.Length    = (UINT16) sizeof (PCI_DATA_STRUCTURE);
62530fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.Revision  = 0;
62630fdf1140b8d1ce93f3821d986fa165552023440lgao    //
62730fdf1140b8d1ce93f3821d986fa165552023440lgao    // Class code and code revision from the command line (optional)
62830fdf1140b8d1ce93f3821d986fa165552023440lgao    //
62930fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.ClassCode[0]  = (UINT8) InFile->ClassCode;
63030fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.ClassCode[1]  = (UINT8) (InFile->ClassCode >> 8);
63130fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.ClassCode[2]  = (UINT8) (InFile->ClassCode >> 16);
63230fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.ImageLength   = RomHdr.InitializationSize;
63330fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.CodeRevision  = InFile->CodeRevision;
63430fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs23.CodeType      = PCI_CODE_TYPE_EFI_IMAGE;
63530fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
63630fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE;
63730fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.VendorId  = VendId;
63830fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.DeviceId  = DevId;
63930fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.DeviceListOffset = 0; // to be fixed
64030fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.Length    = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE);
64130fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.Revision  = 0x3;
64230fdf1140b8d1ce93f3821d986fa165552023440lgao    //
64330fdf1140b8d1ce93f3821d986fa165552023440lgao    // Class code and code revision from the command line (optional)
64430fdf1140b8d1ce93f3821d986fa165552023440lgao    //
64530fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.ClassCode[0]  = (UINT8) InFile->ClassCode;
64630fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.ClassCode[1]  = (UINT8) (InFile->ClassCode >> 8);
64730fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.ClassCode[2]  = (UINT8) (InFile->ClassCode >> 16);
64830fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.ImageLength   = RomHdr.InitializationSize;
64930fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.CodeRevision  = InFile->CodeRevision;
65030fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.CodeType      = PCI_CODE_TYPE_EFI_IMAGE;
65130fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.MaxRuntimeImageLength = 0; // to be fixed
65230fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.ConfigUtilityCodeHeaderOffset = 0; // to be fixed
65330fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.DMTFCLPEntryPointOffset = 0; // to be fixed
65430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
65530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
65630fdf1140b8d1ce93f3821d986fa165552023440lgao  // If this is the last image, then set the LAST bit unless requested not
65730fdf1140b8d1ce93f3821d986fa165552023440lgao  // to via the command-line -n argument.
65830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
65930fdf1140b8d1ce93f3821d986fa165552023440lgao  if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
66030fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Pci23 == 1) {
66130fdf1140b8d1ce93f3821d986fa165552023440lgao      PciDs23.Indicator = INDICATOR_LAST;
66230fdf1140b8d1ce93f3821d986fa165552023440lgao	  } else {
66330fdf1140b8d1ce93f3821d986fa165552023440lgao    PciDs30.Indicator = INDICATOR_LAST;}
66430fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
66530fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Pci23 == 1) {
66630fdf1140b8d1ce93f3821d986fa165552023440lgao      PciDs23.Indicator = 0;
66730fdf1140b8d1ce93f3821d986fa165552023440lgao	} else {
66830fdf1140b8d1ce93f3821d986fa165552023440lgao      PciDs30.Indicator = 0;
66930fdf1140b8d1ce93f3821d986fa165552023440lgao    }
67030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
67130fdf1140b8d1ce93f3821d986fa165552023440lgao  //
67230fdf1140b8d1ce93f3821d986fa165552023440lgao  // Write the ROM header to the output file
67330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
67430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {
67530fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0002, "Failed to write ROM header to output file!", NULL);
67630fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
67730fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
67830fdf1140b8d1ce93f3821d986fa165552023440lgao  }
67930fdf1140b8d1ce93f3821d986fa165552023440lgao
68030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
68130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Write pad bytes to align the PciDs
68230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
68330fdf1140b8d1ce93f3821d986fa165552023440lgao  while (HeaderPadBytes > 0) {
68430fdf1140b8d1ce93f3821d986fa165552023440lgao    if (putc (0, OutFptr) == EOF) {
68530fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 0002, "Failed to write ROM header pad bytes to output file!", NULL);
68630fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
68730fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
68830fdf1140b8d1ce93f3821d986fa165552023440lgao    }
68930fdf1140b8d1ce93f3821d986fa165552023440lgao
69030fdf1140b8d1ce93f3821d986fa165552023440lgao    HeaderPadBytes--;
69130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
69230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
69330fdf1140b8d1ce93f3821d986fa165552023440lgao  // Write the PCI data structure header to the output file
69430fdf1140b8d1ce93f3821d986fa165552023440lgao  //
69530fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Pci23 == 1) {
69630fdf1140b8d1ce93f3821d986fa165552023440lgao    if (fwrite (&PciDs23, sizeof (PciDs23), 1, OutFptr) != 1) {
69730fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);
69830fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
69930fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
70030fdf1140b8d1ce93f3821d986fa165552023440lgao    }
70130fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
70230fdf1140b8d1ce93f3821d986fa165552023440lgao    if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) {
70330fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL);
70430fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
70530fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
70630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
70730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
7082bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming
70930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
7102bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  // Pad head to make it a multiple of 512 bytes
71130fdf1140b8d1ce93f3821d986fa165552023440lgao  //
7122bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  while (PadBytesBeforeImage > 0) {
7132bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    if (putc (~0, OutFptr) == EOF) {
7142bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming      Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);
7152bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming      Status = STATUS_ERROR;
7162bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming      goto BailOut;
7172bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    }
7182bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    PadBytesBeforeImage--;
7192bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  }
72030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
72130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Now dump the input file's contents to the output file
72230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
72330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
72430fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0002, "Failed to write all file bytes to output file!", NULL);
72530fdf1140b8d1ce93f3821d986fa165552023440lgao    Status = STATUS_ERROR;
72630fdf1140b8d1ce93f3821d986fa165552023440lgao    goto BailOut;
72730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
72830fdf1140b8d1ce93f3821d986fa165552023440lgao
72930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
73030fdf1140b8d1ce93f3821d986fa165552023440lgao  // Pad the rest of the image to make it a multiple of 512 bytes
73130fdf1140b8d1ce93f3821d986fa165552023440lgao  //
7322bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming  while (PadBytesAfterImage > 0) {
73330fdf1140b8d1ce93f3821d986fa165552023440lgao    if (putc (~0, OutFptr) == EOF) {
73430fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL);
73530fdf1140b8d1ce93f3821d986fa165552023440lgao      Status = STATUS_ERROR;
73630fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
73730fdf1140b8d1ce93f3821d986fa165552023440lgao    }
73830fdf1140b8d1ce93f3821d986fa165552023440lgao
7392bc3256ca6d439ebf5d85d5e74e5f3e68df14130Gao, Liming    PadBytesAfterImage--;
74030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
74130fdf1140b8d1ce93f3821d986fa165552023440lgao
74230fdf1140b8d1ce93f3821d986fa165552023440lgaoBailOut:
74330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (InFptr != NULL) {
74430fdf1140b8d1ce93f3821d986fa165552023440lgao    fclose (InFptr);
74530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
74630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
74730fdf1140b8d1ce93f3821d986fa165552023440lgao  // Free up our buffers
74830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
74930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Buffer != NULL) {
75030fdf1140b8d1ce93f3821d986fa165552023440lgao    free (Buffer);
75130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
75230fdf1140b8d1ce93f3821d986fa165552023440lgao
75330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (CompressedBuffer != NULL) {
75430fdf1140b8d1ce93f3821d986fa165552023440lgao    free (CompressedBuffer);
75530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
75630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
75730fdf1140b8d1ce93f3821d986fa165552023440lgao  // Print the file name if errors occurred
75830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
75930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Status != STATUS_SUCCESS) {
76030fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0003, "Error parsing", "Error parsing file: %s", InFile->FileName);
76130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
76230fdf1140b8d1ce93f3821d986fa165552023440lgao
76330fdf1140b8d1ce93f3821d986fa165552023440lgao  return Status;
76430fdf1140b8d1ce93f3821d986fa165552023440lgao}
76530fdf1140b8d1ce93f3821d986fa165552023440lgao
76630fdf1140b8d1ce93f3821d986fa165552023440lgaostatic
76730fdf1140b8d1ce93f3821d986fa165552023440lgaoint
76830fdf1140b8d1ce93f3821d986fa165552023440lgaoCheckPE32File (
76930fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE      *Fptr,
77030fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT16    *MachineType,
77130fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT16    *SubSystem
77230fdf1140b8d1ce93f3821d986fa165552023440lgao  )
77330fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
77430fdf1140b8d1ce93f3821d986fa165552023440lgao
77530fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
77630fdf1140b8d1ce93f3821d986fa165552023440lgao
77730fdf1140b8d1ce93f3821d986fa165552023440lgao  Given a file pointer to a supposed PE32 image file, verify that it is indeed a
77830fdf1140b8d1ce93f3821d986fa165552023440lgao  PE32 image file, and then return the machine type in the supplied pointer.
77930fdf1140b8d1ce93f3821d986fa165552023440lgao
78030fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
78130fdf1140b8d1ce93f3821d986fa165552023440lgao
78230fdf1140b8d1ce93f3821d986fa165552023440lgao  Fptr          File pointer to the already-opened PE32 file
78330fdf1140b8d1ce93f3821d986fa165552023440lgao  MachineType   Location to stuff the machine type of the PE32 file. This is needed
78430fdf1140b8d1ce93f3821d986fa165552023440lgao                because the image may be Itanium-based, IA32, or EBC.
78530fdf1140b8d1ce93f3821d986fa165552023440lgao
78630fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
78730fdf1140b8d1ce93f3821d986fa165552023440lgao
78830fdf1140b8d1ce93f3821d986fa165552023440lgao  0             success
78930fdf1140b8d1ce93f3821d986fa165552023440lgao  non-zero      otherwise
79030fdf1140b8d1ce93f3821d986fa165552023440lgao
79130fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
79230fdf1140b8d1ce93f3821d986fa165552023440lgao{
79330fdf1140b8d1ce93f3821d986fa165552023440lgao  EFI_IMAGE_DOS_HEADER            DosHeader;
79430fdf1140b8d1ce93f3821d986fa165552023440lgao  EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr;
79530fdf1140b8d1ce93f3821d986fa165552023440lgao
79630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
79730fdf1140b8d1ce93f3821d986fa165552023440lgao  // Position to the start of the file
79830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
79930fdf1140b8d1ce93f3821d986fa165552023440lgao  fseek (Fptr, 0, SEEK_SET);
80030fdf1140b8d1ce93f3821d986fa165552023440lgao
80130fdf1140b8d1ce93f3821d986fa165552023440lgao  //
80230fdf1140b8d1ce93f3821d986fa165552023440lgao  // Read the DOS header
80330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
80430fdf1140b8d1ce93f3821d986fa165552023440lgao  if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
80530fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0004, "Failed to read the DOS stub from the input file!", NULL);
80630fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
80730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
80830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
80930fdf1140b8d1ce93f3821d986fa165552023440lgao  // Check the magic number (0x5A4D)
81030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
81130fdf1140b8d1ce93f3821d986fa165552023440lgao  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
81230fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (magic number)!");
81330fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
81430fdf1140b8d1ce93f3821d986fa165552023440lgao  }
81530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
81630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Position into the file and check the PE signature
81730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
81830fdf1140b8d1ce93f3821d986fa165552023440lgao  fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET);
81930fdf1140b8d1ce93f3821d986fa165552023440lgao
82030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
82130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Read PE headers
82230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
82330fdf1140b8d1ce93f3821d986fa165552023440lgao  if (fread (&PeHdr, sizeof (PeHdr), 1, Fptr) != 1) {
82430fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0004, "Failed to read PE/COFF headers from input file!", NULL);
82530fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
82630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
82730fdf1140b8d1ce93f3821d986fa165552023440lgao
82830fdf1140b8d1ce93f3821d986fa165552023440lgao
82930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
83030fdf1140b8d1ce93f3821d986fa165552023440lgao  // Check the PE signature in the header "PE\0\0"
83130fdf1140b8d1ce93f3821d986fa165552023440lgao  //
83230fdf1140b8d1ce93f3821d986fa165552023440lgao  if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) {
83330fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (signature)!");
83430fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
83530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
83630fdf1140b8d1ce93f3821d986fa165552023440lgao
83730fdf1140b8d1ce93f3821d986fa165552023440lgao  memcpy ((char *) MachineType, &PeHdr.Pe32.FileHeader.Machine, 2);
83830fdf1140b8d1ce93f3821d986fa165552023440lgao
83930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
84030fdf1140b8d1ce93f3821d986fa165552023440lgao    *SubSystem = PeHdr.Pe32.OptionalHeader.Subsystem;
84130fdf1140b8d1ce93f3821d986fa165552023440lgao  } else if (PeHdr.Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
84230fdf1140b8d1ce93f3821d986fa165552023440lgao    *SubSystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem;
84330fdf1140b8d1ce93f3821d986fa165552023440lgao  } else {
84430fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid parameter", "Unable to find subsystem type!");
84530fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
84630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
84730fdf1140b8d1ce93f3821d986fa165552023440lgao
84830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (mOptions.Verbose) {
849fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    VerboseMsg("  Got subsystem = 0x%X from image\n", *SubSystem);
85030fdf1140b8d1ce93f3821d986fa165552023440lgao  }
85130fdf1140b8d1ce93f3821d986fa165552023440lgao
85230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
85330fdf1140b8d1ce93f3821d986fa165552023440lgao  // File was successfully identified as a PE32
85430fdf1140b8d1ce93f3821d986fa165552023440lgao  //
85530fdf1140b8d1ce93f3821d986fa165552023440lgao  return STATUS_SUCCESS;
85630fdf1140b8d1ce93f3821d986fa165552023440lgao}
85730fdf1140b8d1ce93f3821d986fa165552023440lgao
85830fdf1140b8d1ce93f3821d986fa165552023440lgaostatic
85930fdf1140b8d1ce93f3821d986fa165552023440lgaoint
86030fdf1140b8d1ce93f3821d986fa165552023440lgaoParseCommandLine (
86130fdf1140b8d1ce93f3821d986fa165552023440lgao  int         Argc,
86230fdf1140b8d1ce93f3821d986fa165552023440lgao  char        *Argv[],
86330fdf1140b8d1ce93f3821d986fa165552023440lgao  OPTIONS     *Options
86430fdf1140b8d1ce93f3821d986fa165552023440lgao  )
86530fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
86630fdf1140b8d1ce93f3821d986fa165552023440lgao
86730fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
86830fdf1140b8d1ce93f3821d986fa165552023440lgao
86930fdf1140b8d1ce93f3821d986fa165552023440lgao  Given the Argc/Argv program arguments, and a pointer to an options structure,
87030fdf1140b8d1ce93f3821d986fa165552023440lgao  parse the command-line options and check their validity.
87130fdf1140b8d1ce93f3821d986fa165552023440lgao
87230fdf1140b8d1ce93f3821d986fa165552023440lgao
87330fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
87430fdf1140b8d1ce93f3821d986fa165552023440lgao
87530fdf1140b8d1ce93f3821d986fa165552023440lgao  Argc            - standard C main() argument count
87630fdf1140b8d1ce93f3821d986fa165552023440lgao  Argv[]          - standard C main() argument list
87730fdf1140b8d1ce93f3821d986fa165552023440lgao  Options         - pointer to a structure to store the options in
87830fdf1140b8d1ce93f3821d986fa165552023440lgao
87930fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
88030fdf1140b8d1ce93f3821d986fa165552023440lgao
88130fdf1140b8d1ce93f3821d986fa165552023440lgao  STATUS_SUCCESS    success
88230fdf1140b8d1ce93f3821d986fa165552023440lgao  non-zero          otherwise
88330fdf1140b8d1ce93f3821d986fa165552023440lgao
88430fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
88530fdf1140b8d1ce93f3821d986fa165552023440lgao{
88630fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE_LIST *FileList;
88730fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE_LIST *PrevFileList;
88830fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32    FileFlags;
88930fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32    ClassCode;
89030fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32    CodeRevision;
89130fdf1140b8d1ce93f3821d986fa165552023440lgao  EFI_STATUS Status;
89230fdf1140b8d1ce93f3821d986fa165552023440lgao  BOOLEAN    EfiRomFlag;
89330fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT64     TempValue;
89430fdf1140b8d1ce93f3821d986fa165552023440lgao
89530fdf1140b8d1ce93f3821d986fa165552023440lgao  FileFlags = 0;
89630fdf1140b8d1ce93f3821d986fa165552023440lgao  EfiRomFlag = FALSE;
89730fdf1140b8d1ce93f3821d986fa165552023440lgao
89830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
89930fdf1140b8d1ce93f3821d986fa165552023440lgao  // Clear out the options
90030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
90130fdf1140b8d1ce93f3821d986fa165552023440lgao  memset ((char *) Options, 0, sizeof (OPTIONS));
90230fdf1140b8d1ce93f3821d986fa165552023440lgao
90330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
90430fdf1140b8d1ce93f3821d986fa165552023440lgao  // To avoid compile warnings
90530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
90630fdf1140b8d1ce93f3821d986fa165552023440lgao  FileList                = PrevFileList = NULL;
90730fdf1140b8d1ce93f3821d986fa165552023440lgao
90830fdf1140b8d1ce93f3821d986fa165552023440lgao  ClassCode               = 0;
90930fdf1140b8d1ce93f3821d986fa165552023440lgao  CodeRevision            = 0;
91030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
91130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Skip over the program name
91230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
91330fdf1140b8d1ce93f3821d986fa165552023440lgao  Argc--;
91430fdf1140b8d1ce93f3821d986fa165552023440lgao  Argv++;
91530fdf1140b8d1ce93f3821d986fa165552023440lgao
91630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
91730fdf1140b8d1ce93f3821d986fa165552023440lgao  // If no arguments, assume they want usage info
91830fdf1140b8d1ce93f3821d986fa165552023440lgao  //
91930fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Argc == 0) {
92030fdf1140b8d1ce93f3821d986fa165552023440lgao    Usage ();
92130fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
92230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
92330fdf1140b8d1ce93f3821d986fa165552023440lgao
92430fdf1140b8d1ce93f3821d986fa165552023440lgao  if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) {
92530fdf1140b8d1ce93f3821d986fa165552023440lgao    Usage();
92630fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
92730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
92830fdf1140b8d1ce93f3821d986fa165552023440lgao
92930fdf1140b8d1ce93f3821d986fa165552023440lgao  if ((stricmp(Argv[0], "--version") == 0)) {
93030fdf1140b8d1ce93f3821d986fa165552023440lgao    Version();
93130fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
93230fdf1140b8d1ce93f3821d986fa165552023440lgao  }
93330fdf1140b8d1ce93f3821d986fa165552023440lgao
93430fdf1140b8d1ce93f3821d986fa165552023440lgao  //
93530fdf1140b8d1ce93f3821d986fa165552023440lgao  // Process until no more arguments
93630fdf1140b8d1ce93f3821d986fa165552023440lgao  //
93730fdf1140b8d1ce93f3821d986fa165552023440lgao  while (Argc > 0) {
93830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (Argv[0][0] == '-') {
93930fdf1140b8d1ce93f3821d986fa165552023440lgao      //
94030fdf1140b8d1ce93f3821d986fa165552023440lgao      // Vendor ID specified with -f
94130fdf1140b8d1ce93f3821d986fa165552023440lgao      //
94230fdf1140b8d1ce93f3821d986fa165552023440lgao      if (stricmp (Argv[0], "-f") == 0) {
94330fdf1140b8d1ce93f3821d986fa165552023440lgao        //
94430fdf1140b8d1ce93f3821d986fa165552023440lgao        // Make sure there's another parameter
94530fdf1140b8d1ce93f3821d986fa165552023440lgao        //
94630fdf1140b8d1ce93f3821d986fa165552023440lgao        Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
94730fdf1140b8d1ce93f3821d986fa165552023440lgao        if (EFI_ERROR (Status)) {
94830fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
94930fdf1140b8d1ce93f3821d986fa165552023440lgao          return 1;
95030fdf1140b8d1ce93f3821d986fa165552023440lgao        }
95130fdf1140b8d1ce93f3821d986fa165552023440lgao        if (TempValue >= 0x10000) {
95230fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]);
95330fdf1140b8d1ce93f3821d986fa165552023440lgao          return 1;
95430fdf1140b8d1ce93f3821d986fa165552023440lgao        }
95530fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->VendId       = (UINT16) TempValue;
95630fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->VendIdValid  = 1;
95730fdf1140b8d1ce93f3821d986fa165552023440lgao
95830fdf1140b8d1ce93f3821d986fa165552023440lgao        Argv++;
95930fdf1140b8d1ce93f3821d986fa165552023440lgao        Argc--;
96030fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if (stricmp (Argv[0], "-i") == 0) {
96130fdf1140b8d1ce93f3821d986fa165552023440lgao        //
96230fdf1140b8d1ce93f3821d986fa165552023440lgao        // Device ID specified with -i
96330fdf1140b8d1ce93f3821d986fa165552023440lgao        // Make sure there's another parameter
96430fdf1140b8d1ce93f3821d986fa165552023440lgao        //
96530fdf1140b8d1ce93f3821d986fa165552023440lgao        Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
96630fdf1140b8d1ce93f3821d986fa165552023440lgao        if (EFI_ERROR (Status)) {
96730fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
96830fdf1140b8d1ce93f3821d986fa165552023440lgao          return 1;
96930fdf1140b8d1ce93f3821d986fa165552023440lgao        }
97030fdf1140b8d1ce93f3821d986fa165552023440lgao        if (TempValue >= 0x10000) {
97130fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]);
97230fdf1140b8d1ce93f3821d986fa165552023440lgao          return 1;
97330fdf1140b8d1ce93f3821d986fa165552023440lgao        }
97430fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->DevId      = (UINT16) TempValue;
97530fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->DevIdValid = 1;
97630fdf1140b8d1ce93f3821d986fa165552023440lgao
97730fdf1140b8d1ce93f3821d986fa165552023440lgao        Argv++;
97830fdf1140b8d1ce93f3821d986fa165552023440lgao        Argc--;
97930fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) {
98030fdf1140b8d1ce93f3821d986fa165552023440lgao        //
98130fdf1140b8d1ce93f3821d986fa165552023440lgao        // Output filename specified with -o
98230fdf1140b8d1ce93f3821d986fa165552023440lgao        // Make sure there's another parameter
98330fdf1140b8d1ce93f3821d986fa165552023440lgao        //
98430fdf1140b8d1ce93f3821d986fa165552023440lgao        if (Argv[1] == NULL || Argv[1][0] == '-') {
98530fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]);
98630fdf1140b8d1ce93f3821d986fa165552023440lgao          return STATUS_ERROR;
98730fdf1140b8d1ce93f3821d986fa165552023440lgao        }
98830fdf1140b8d1ce93f3821d986fa165552023440lgao        strcpy (Options->OutFileName, Argv[1]);
98930fdf1140b8d1ce93f3821d986fa165552023440lgao
99030fdf1140b8d1ce93f3821d986fa165552023440lgao        Argv++;
99130fdf1140b8d1ce93f3821d986fa165552023440lgao        Argc--;
99230fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if ((stricmp (Argv[0], "-h") == 0) || (stricmp (Argv[0], "--help") == 0)) {
99330fdf1140b8d1ce93f3821d986fa165552023440lgao        //
99430fdf1140b8d1ce93f3821d986fa165552023440lgao        // Help option
99530fdf1140b8d1ce93f3821d986fa165552023440lgao        //
99630fdf1140b8d1ce93f3821d986fa165552023440lgao        Usage ();
99730fdf1140b8d1ce93f3821d986fa165552023440lgao        return STATUS_ERROR;
99830fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if (stricmp (Argv[0], "-b") == 0) {
99930fdf1140b8d1ce93f3821d986fa165552023440lgao        //
100030fdf1140b8d1ce93f3821d986fa165552023440lgao        // Specify binary files with -b
100130fdf1140b8d1ce93f3821d986fa165552023440lgao        //
100230fdf1140b8d1ce93f3821d986fa165552023440lgao        FileFlags = FILE_FLAG_BINARY;
100330fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) {
100430fdf1140b8d1ce93f3821d986fa165552023440lgao        //
100530fdf1140b8d1ce93f3821d986fa165552023440lgao        // Specify EFI files with -e. Specify EFI-compressed with -c.
100630fdf1140b8d1ce93f3821d986fa165552023440lgao        //
100730fdf1140b8d1ce93f3821d986fa165552023440lgao        FileFlags = FILE_FLAG_EFI;
100830fdf1140b8d1ce93f3821d986fa165552023440lgao        if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) {
100930fdf1140b8d1ce93f3821d986fa165552023440lgao          FileFlags |= FILE_FLAG_COMPRESS;
101030fdf1140b8d1ce93f3821d986fa165552023440lgao        }
101130fdf1140b8d1ce93f3821d986fa165552023440lgao        //
101230fdf1140b8d1ce93f3821d986fa165552023440lgao        // Specify not to set the LAST bit in the last file with -n
101330fdf1140b8d1ce93f3821d986fa165552023440lgao        //
101430fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if (stricmp (Argv[0], "-n") == 0) {
101530fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->NoLast = 1;
101630fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if (((stricmp (Argv[0], "-v") == 0)) || ((stricmp (Argv[0], "--verbose") == 0))) {
101730fdf1140b8d1ce93f3821d986fa165552023440lgao        //
101830fdf1140b8d1ce93f3821d986fa165552023440lgao        // -v for verbose
101930fdf1140b8d1ce93f3821d986fa165552023440lgao        //
102030fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->Verbose = 1;
102130fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if (stricmp (Argv[0], "--debug") == 0) {
102230fdf1140b8d1ce93f3821d986fa165552023440lgao        Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel);
102330fdf1140b8d1ce93f3821d986fa165552023440lgao        if (EFI_ERROR (Status)) {
102430fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
102530fdf1140b8d1ce93f3821d986fa165552023440lgao          return 1;
102630fdf1140b8d1ce93f3821d986fa165552023440lgao        }
102730fdf1140b8d1ce93f3821d986fa165552023440lgao        if (DebugLevel > 9)  {
1028fd171542e0aa89ac12a09d79608173f48019b14bvanjeff          Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]);
102930fdf1140b8d1ce93f3821d986fa165552023440lgao          return 1;
103030fdf1140b8d1ce93f3821d986fa165552023440lgao        }
103130fdf1140b8d1ce93f3821d986fa165552023440lgao        if (DebugLevel>=5 && DebugLevel<=9) {
103230fdf1140b8d1ce93f3821d986fa165552023440lgao          Options->Debug = TRUE;
103330fdf1140b8d1ce93f3821d986fa165552023440lgao        } else {
103430fdf1140b8d1ce93f3821d986fa165552023440lgao          Options->Debug = FALSE;
103530fdf1140b8d1ce93f3821d986fa165552023440lgao        }
103630fdf1140b8d1ce93f3821d986fa165552023440lgao        Argv++;
103730fdf1140b8d1ce93f3821d986fa165552023440lgao        Argc--;
103830fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if ((stricmp (Argv[0], "--quiet") == 0) || (stricmp (Argv[0], "-q") == 0)) {
103930fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->Quiet = TRUE;
104030fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if ((stricmp (Argv[0], "--dump") == 0) || (stricmp (Argv[0], "-d") == 0)) {
104130fdf1140b8d1ce93f3821d986fa165552023440lgao        //
104230fdf1140b8d1ce93f3821d986fa165552023440lgao        // -dump for dumping a ROM image. In this case, say that the device id
104330fdf1140b8d1ce93f3821d986fa165552023440lgao        // and vendor id are valid so we don't have to specify bogus ones on the
104430fdf1140b8d1ce93f3821d986fa165552023440lgao        // command line.
104530fdf1140b8d1ce93f3821d986fa165552023440lgao        //
104630fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->DumpOption   = 1;
104730fdf1140b8d1ce93f3821d986fa165552023440lgao
104830fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->VendIdValid  = 1;
104930fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->DevIdValid   = 1;
105030fdf1140b8d1ce93f3821d986fa165552023440lgao        FileFlags             = FILE_FLAG_BINARY;
105130fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) {
105230fdf1140b8d1ce93f3821d986fa165552023440lgao        //
105330fdf1140b8d1ce93f3821d986fa165552023440lgao        // Class code value for the next file in the list.
105430fdf1140b8d1ce93f3821d986fa165552023440lgao        // Make sure there's another parameter
105530fdf1140b8d1ce93f3821d986fa165552023440lgao        //
105630fdf1140b8d1ce93f3821d986fa165552023440lgao        Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
105730fdf1140b8d1ce93f3821d986fa165552023440lgao        if (EFI_ERROR (Status)) {
105830fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
105930fdf1140b8d1ce93f3821d986fa165552023440lgao          return 1;
106030fdf1140b8d1ce93f3821d986fa165552023440lgao        }
106130fdf1140b8d1ce93f3821d986fa165552023440lgao        ClassCode = (UINT32) TempValue;
106230fdf1140b8d1ce93f3821d986fa165552023440lgao        if (ClassCode & 0xFF000000) {
106330fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]);
106430fdf1140b8d1ce93f3821d986fa165552023440lgao          return STATUS_ERROR;
106530fdf1140b8d1ce93f3821d986fa165552023440lgao        }
106630fdf1140b8d1ce93f3821d986fa165552023440lgao        if (FileList != NULL && FileList->ClassCode == 0) {
106730fdf1140b8d1ce93f3821d986fa165552023440lgao          FileList->ClassCode = ClassCode;
106830fdf1140b8d1ce93f3821d986fa165552023440lgao        }
106930fdf1140b8d1ce93f3821d986fa165552023440lgao        Argv++;
107030fdf1140b8d1ce93f3821d986fa165552023440lgao        Argc--;
107130fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if ((stricmp (Argv[0], "-r") == 0) || (stricmp (Argv[0], "--Revision") == 0)) {
107230fdf1140b8d1ce93f3821d986fa165552023440lgao        //
107330fdf1140b8d1ce93f3821d986fa165552023440lgao        // Code revision in the PCI data structure. The value is for the next
107430fdf1140b8d1ce93f3821d986fa165552023440lgao        // file in the list.
107530fdf1140b8d1ce93f3821d986fa165552023440lgao        // Make sure there's another parameter
107630fdf1140b8d1ce93f3821d986fa165552023440lgao        //
107730fdf1140b8d1ce93f3821d986fa165552023440lgao        Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue);
107830fdf1140b8d1ce93f3821d986fa165552023440lgao        if (EFI_ERROR (Status)) {
107930fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]);
108030fdf1140b8d1ce93f3821d986fa165552023440lgao          return 1;
108130fdf1140b8d1ce93f3821d986fa165552023440lgao        }
108230fdf1140b8d1ce93f3821d986fa165552023440lgao        CodeRevision = (UINT32) TempValue;
108330fdf1140b8d1ce93f3821d986fa165552023440lgao        if (CodeRevision & 0xFFFF0000) {
108430fdf1140b8d1ce93f3821d986fa165552023440lgao          Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]);
108530fdf1140b8d1ce93f3821d986fa165552023440lgao          return STATUS_ERROR;
108630fdf1140b8d1ce93f3821d986fa165552023440lgao        }
108730fdf1140b8d1ce93f3821d986fa165552023440lgao        if (FileList != NULL && FileList->CodeRevision == 0) {
108830fdf1140b8d1ce93f3821d986fa165552023440lgao          FileList->CodeRevision = (UINT16) CodeRevision;
108930fdf1140b8d1ce93f3821d986fa165552023440lgao        }
109030fdf1140b8d1ce93f3821d986fa165552023440lgao        Argv++;
109130fdf1140b8d1ce93f3821d986fa165552023440lgao        Argc--;
109230fdf1140b8d1ce93f3821d986fa165552023440lgao      } else if ((stricmp (Argv[0], "-p") == 0) || (stricmp (Argv[0], "--pci23") == 0)) {
109330fdf1140b8d1ce93f3821d986fa165552023440lgao        //
109430fdf1140b8d1ce93f3821d986fa165552023440lgao        // Default layout meets PCI 3.0 specifications, specifying this flag will for a PCI 2.3 layout.
109530fdf1140b8d1ce93f3821d986fa165552023440lgao        //
109630fdf1140b8d1ce93f3821d986fa165552023440lgao        mOptions.Pci23 = 1;
109730fdf1140b8d1ce93f3821d986fa165552023440lgao      } else {
109830fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]);
109930fdf1140b8d1ce93f3821d986fa165552023440lgao        return STATUS_ERROR;
110030fdf1140b8d1ce93f3821d986fa165552023440lgao      }
110130fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
110230fdf1140b8d1ce93f3821d986fa165552023440lgao      //
110330fdf1140b8d1ce93f3821d986fa165552023440lgao      // Not a slash-option argument. Must be a file name. Make sure they've specified
110430fdf1140b8d1ce93f3821d986fa165552023440lgao      // -e or -b already.
110530fdf1140b8d1ce93f3821d986fa165552023440lgao      //
110630fdf1140b8d1ce93f3821d986fa165552023440lgao      if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) {
110730fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]);
110830fdf1140b8d1ce93f3821d986fa165552023440lgao        return STATUS_ERROR;
110930fdf1140b8d1ce93f3821d986fa165552023440lgao      }
111030fdf1140b8d1ce93f3821d986fa165552023440lgao      //
111130fdf1140b8d1ce93f3821d986fa165552023440lgao      // Check Efi Option RomImage
111230fdf1140b8d1ce93f3821d986fa165552023440lgao      //
111330fdf1140b8d1ce93f3821d986fa165552023440lgao      if ((FileFlags & FILE_FLAG_EFI) == FILE_FLAG_EFI) {
111430fdf1140b8d1ce93f3821d986fa165552023440lgao        EfiRomFlag = TRUE;
111530fdf1140b8d1ce93f3821d986fa165552023440lgao      }
111630fdf1140b8d1ce93f3821d986fa165552023440lgao      //
111730fdf1140b8d1ce93f3821d986fa165552023440lgao      // Create a new file structure
111830fdf1140b8d1ce93f3821d986fa165552023440lgao      //
111930fdf1140b8d1ce93f3821d986fa165552023440lgao      FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST));
112030fdf1140b8d1ce93f3821d986fa165552023440lgao      if (FileList == NULL) {
112130fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL);
112230fdf1140b8d1ce93f3821d986fa165552023440lgao        return STATUS_ERROR;
112330fdf1140b8d1ce93f3821d986fa165552023440lgao      }
112430fdf1140b8d1ce93f3821d986fa165552023440lgao
112530fdf1140b8d1ce93f3821d986fa165552023440lgao      //
112630fdf1140b8d1ce93f3821d986fa165552023440lgao      // set flag and class code for this image.
112730fdf1140b8d1ce93f3821d986fa165552023440lgao      //
112830fdf1140b8d1ce93f3821d986fa165552023440lgao      memset ((char *) FileList, 0, sizeof (FILE_LIST));
112930fdf1140b8d1ce93f3821d986fa165552023440lgao      FileList->FileName      = Argv[0];
113030fdf1140b8d1ce93f3821d986fa165552023440lgao      FileList->FileFlags     = FileFlags;
113130fdf1140b8d1ce93f3821d986fa165552023440lgao      FileList->ClassCode     = ClassCode;
113230fdf1140b8d1ce93f3821d986fa165552023440lgao      FileList->CodeRevision  = (UINT16) CodeRevision;
113330fdf1140b8d1ce93f3821d986fa165552023440lgao      ClassCode               = 0;
113430fdf1140b8d1ce93f3821d986fa165552023440lgao      CodeRevision            = 0;
113530fdf1140b8d1ce93f3821d986fa165552023440lgao
113630fdf1140b8d1ce93f3821d986fa165552023440lgao      if (Options->FileList == NULL) {
113730fdf1140b8d1ce93f3821d986fa165552023440lgao        Options->FileList = FileList;
113830fdf1140b8d1ce93f3821d986fa165552023440lgao      } else {
113930fdf1140b8d1ce93f3821d986fa165552023440lgao        if (PrevFileList == NULL) {
114030fdf1140b8d1ce93f3821d986fa165552023440lgao          PrevFileList = FileList;
114130fdf1140b8d1ce93f3821d986fa165552023440lgao        } else {
114230fdf1140b8d1ce93f3821d986fa165552023440lgao          PrevFileList->Next = FileList;
114330fdf1140b8d1ce93f3821d986fa165552023440lgao        }
114430fdf1140b8d1ce93f3821d986fa165552023440lgao      }
114530fdf1140b8d1ce93f3821d986fa165552023440lgao
114630fdf1140b8d1ce93f3821d986fa165552023440lgao      PrevFileList = FileList;
114730fdf1140b8d1ce93f3821d986fa165552023440lgao    }
114830fdf1140b8d1ce93f3821d986fa165552023440lgao    //
114930fdf1140b8d1ce93f3821d986fa165552023440lgao    // Next argument
115030fdf1140b8d1ce93f3821d986fa165552023440lgao    //
115130fdf1140b8d1ce93f3821d986fa165552023440lgao    Argv++;
115230fdf1140b8d1ce93f3821d986fa165552023440lgao    Argc--;
115330fdf1140b8d1ce93f3821d986fa165552023440lgao  }
115430fdf1140b8d1ce93f3821d986fa165552023440lgao
115530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
115630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Must have specified some files
115730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
115830fdf1140b8d1ce93f3821d986fa165552023440lgao  if (Options->FileList == NULL) {
115930fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!");
116030fdf1140b8d1ce93f3821d986fa165552023440lgao    return STATUS_ERROR;
116130fdf1140b8d1ce93f3821d986fa165552023440lgao  }
116230fdf1140b8d1ce93f3821d986fa165552023440lgao
116330fdf1140b8d1ce93f3821d986fa165552023440lgao  //
116430fdf1140b8d1ce93f3821d986fa165552023440lgao  // For EFI OptionRom image, Make sure a device ID and vendor ID are both specified.
116530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
116630fdf1140b8d1ce93f3821d986fa165552023440lgao  if (EfiRomFlag) {
116730fdf1140b8d1ce93f3821d986fa165552023440lgao    if (!Options->VendIdValid) {
116830fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL);
116930fdf1140b8d1ce93f3821d986fa165552023440lgao      return STATUS_ERROR;
117030fdf1140b8d1ce93f3821d986fa165552023440lgao    }
117130fdf1140b8d1ce93f3821d986fa165552023440lgao
117230fdf1140b8d1ce93f3821d986fa165552023440lgao    if (!Options->DevIdValid) {
117330fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 2000, "Missing Device ID in command line", NULL);
117430fdf1140b8d1ce93f3821d986fa165552023440lgao      return STATUS_ERROR;
117530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
117630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
117730fdf1140b8d1ce93f3821d986fa165552023440lgao
117830fdf1140b8d1ce93f3821d986fa165552023440lgao  return 0;
117930fdf1140b8d1ce93f3821d986fa165552023440lgao}
118030fdf1140b8d1ce93f3821d986fa165552023440lgao
118130fdf1140b8d1ce93f3821d986fa165552023440lgaostatic
118230fdf1140b8d1ce93f3821d986fa165552023440lgaovoid
118330fdf1140b8d1ce93f3821d986fa165552023440lgaoVersion (
118430fdf1140b8d1ce93f3821d986fa165552023440lgao  VOID
118530fdf1140b8d1ce93f3821d986fa165552023440lgao  )
118630fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
118730fdf1140b8d1ce93f3821d986fa165552023440lgao
118830fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
118930fdf1140b8d1ce93f3821d986fa165552023440lgao
119030fdf1140b8d1ce93f3821d986fa165552023440lgao  Print version information for this utility.
119130fdf1140b8d1ce93f3821d986fa165552023440lgao
119230fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
119330fdf1140b8d1ce93f3821d986fa165552023440lgao
119430fdf1140b8d1ce93f3821d986fa165552023440lgao  None.
119530fdf1140b8d1ce93f3821d986fa165552023440lgao
119630fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
119730fdf1140b8d1ce93f3821d986fa165552023440lgao
119830fdf1140b8d1ce93f3821d986fa165552023440lgao  Nothing.
119930fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
120030fdf1140b8d1ce93f3821d986fa165552023440lgao{
1201b36d134faf4305247830522b8e2bb255e98c5699lgao fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION);
120230fdf1140b8d1ce93f3821d986fa165552023440lgao}
120330fdf1140b8d1ce93f3821d986fa165552023440lgao
120430fdf1140b8d1ce93f3821d986fa165552023440lgaostatic
120530fdf1140b8d1ce93f3821d986fa165552023440lgaovoid
120630fdf1140b8d1ce93f3821d986fa165552023440lgaoUsage (
120730fdf1140b8d1ce93f3821d986fa165552023440lgao  VOID
120830fdf1140b8d1ce93f3821d986fa165552023440lgao  )
120930fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
121030fdf1140b8d1ce93f3821d986fa165552023440lgao
121130fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
121230fdf1140b8d1ce93f3821d986fa165552023440lgao
121330fdf1140b8d1ce93f3821d986fa165552023440lgao  Print usage information for this utility.
121430fdf1140b8d1ce93f3821d986fa165552023440lgao
121530fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
121630fdf1140b8d1ce93f3821d986fa165552023440lgao
121730fdf1140b8d1ce93f3821d986fa165552023440lgao  None.
121830fdf1140b8d1ce93f3821d986fa165552023440lgao
121930fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
122030fdf1140b8d1ce93f3821d986fa165552023440lgao
122130fdf1140b8d1ce93f3821d986fa165552023440lgao  Nothing.
122230fdf1140b8d1ce93f3821d986fa165552023440lgao
122330fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
122430fdf1140b8d1ce93f3821d986fa165552023440lgao{
122530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
122630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Summary usage
122730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
1228d0acc87a41d9aa25fe87eb096efa62afacd1f865lgao  fprintf (stdout, "Usage: %s -f VendorId -i DeviceId [options] [file name<s>] \n\n", UTILITY_NAME);
122930fdf1140b8d1ce93f3821d986fa165552023440lgao
123030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
123130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Copyright declaration
123230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
12331be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chen  fprintf (stdout, "Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.\n\n");
123430fdf1140b8d1ce93f3821d986fa165552023440lgao
123530fdf1140b8d1ce93f3821d986fa165552023440lgao  //
123630fdf1140b8d1ce93f3821d986fa165552023440lgao  // Details Option
123730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
123830fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "Options:\n");
123930fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -o FileName, --output FileName\n\
1240d0acc87a41d9aa25fe87eb096efa62afacd1f865lgao            File will be created to store the output content.\n");
124130fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -e EfiFileName\n\
124230fdf1140b8d1ce93f3821d986fa165552023440lgao            EFI PE32 image files.\n");
124330fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -ec EfiFileName\n\
124430fdf1140b8d1ce93f3821d986fa165552023440lgao            EFI PE32 image files and will be compressed.\n");
124530fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -b BinFileName\n\
124630fdf1140b8d1ce93f3821d986fa165552023440lgao            Legacy binary files.\n");
124730fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -l ClassCode\n\
124830fdf1140b8d1ce93f3821d986fa165552023440lgao            Hex ClassCode in the PCI data structure header.\n");
124930fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -r Rev    Hex Revision in the PCI data structure header.\n");
125030fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -n        Not to automatically set the LAST bit in the last file.\n");
125130fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -f VendorId\n\
1252d0acc87a41d9aa25fe87eb096efa62afacd1f865lgao            Hex PCI Vendor ID for the device OpROM, must be specified\n");
125330fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -i DeviceId\n\
1254d0acc87a41d9aa25fe87eb096efa62afacd1f865lgao            Hex PCI Device ID for the device OpROM, must be specified\n");
125530fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -p, --pci23\n\
125630fdf1140b8d1ce93f3821d986fa165552023440lgao            Default layout meets PCI 3.0 specifications\n\
125730fdf1140b8d1ce93f3821d986fa165552023440lgao            specifying this flag will for a PCI 2.3 layout.\n");
125830fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -d, --dump\n\
125930fdf1140b8d1ce93f3821d986fa165552023440lgao            Dump the headers of an existing option ROM image.\n");
126030fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -v, --verbose\n\
126130fdf1140b8d1ce93f3821d986fa165552023440lgao            Turn on verbose output with informational messages.\n");
126230fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  --version Show program's version number and exit.\n");
126330fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -h, --help\n\
126430fdf1140b8d1ce93f3821d986fa165552023440lgao            Show this help message and exit.\n");
126530fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  -q, --quiet\n\
126630fdf1140b8d1ce93f3821d986fa165552023440lgao            Disable all messages except FATAL ERRORS.\n");
126730fdf1140b8d1ce93f3821d986fa165552023440lgao  fprintf (stdout, "  --debug [#,0-9]\n\
126830fdf1140b8d1ce93f3821d986fa165552023440lgao            Enable debug messages at level #.\n");
126930fdf1140b8d1ce93f3821d986fa165552023440lgao}
127030fdf1140b8d1ce93f3821d986fa165552023440lgao
127130fdf1140b8d1ce93f3821d986fa165552023440lgaostatic
127230fdf1140b8d1ce93f3821d986fa165552023440lgaovoid
127330fdf1140b8d1ce93f3821d986fa165552023440lgaoDumpImage (
127430fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE_LIST *InFile
127530fdf1140b8d1ce93f3821d986fa165552023440lgao  )
127630fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
127730fdf1140b8d1ce93f3821d986fa165552023440lgao
127830fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
127930fdf1140b8d1ce93f3821d986fa165552023440lgao
128030fdf1140b8d1ce93f3821d986fa165552023440lgao  Dump the headers of an existing option ROM image
128130fdf1140b8d1ce93f3821d986fa165552023440lgao
128230fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
128330fdf1140b8d1ce93f3821d986fa165552023440lgao
128430fdf1140b8d1ce93f3821d986fa165552023440lgao  InFile  - the file name of an existing option ROM image
128530fdf1140b8d1ce93f3821d986fa165552023440lgao
128630fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
128730fdf1140b8d1ce93f3821d986fa165552023440lgao
128830fdf1140b8d1ce93f3821d986fa165552023440lgao  none
128930fdf1140b8d1ce93f3821d986fa165552023440lgao
129030fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
129130fdf1140b8d1ce93f3821d986fa165552023440lgao{
129230fdf1140b8d1ce93f3821d986fa165552023440lgao  PCI_EXPANSION_ROM_HEADER      PciRomHdr;
129330fdf1140b8d1ce93f3821d986fa165552023440lgao  FILE                          *InFptr;
129430fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                        ImageStart;
129530fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT32                        ImageCount;
129630fdf1140b8d1ce93f3821d986fa165552023440lgao  EFI_PCI_EXPANSION_ROM_HEADER  EfiRomHdr;
129730fdf1140b8d1ce93f3821d986fa165552023440lgao  PCI_DATA_STRUCTURE            PciDs23;
129830fdf1140b8d1ce93f3821d986fa165552023440lgao  PCI_3_0_DATA_STRUCTURE        PciDs30;
129930fdf1140b8d1ce93f3821d986fa165552023440lgao
130030fdf1140b8d1ce93f3821d986fa165552023440lgao  //
130130fdf1140b8d1ce93f3821d986fa165552023440lgao  // Open the input file
130230fdf1140b8d1ce93f3821d986fa165552023440lgao  //
13031be2ed90a20618d71ddf34b8a07d038da0b36854Hess Chen  if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) {
130430fdf1140b8d1ce93f3821d986fa165552023440lgao    Error (NULL, 0, 0001, "Error opening file", InFile->FileName);
130530fdf1140b8d1ce93f3821d986fa165552023440lgao    return ;
130630fdf1140b8d1ce93f3821d986fa165552023440lgao  }
130730fdf1140b8d1ce93f3821d986fa165552023440lgao  //
130830fdf1140b8d1ce93f3821d986fa165552023440lgao  // Go through the image and dump the header stuff for each
130930fdf1140b8d1ce93f3821d986fa165552023440lgao  //
131030fdf1140b8d1ce93f3821d986fa165552023440lgao  ImageCount = 0;
131130fdf1140b8d1ce93f3821d986fa165552023440lgao  for (;;) {
131230fdf1140b8d1ce93f3821d986fa165552023440lgao    //
131330fdf1140b8d1ce93f3821d986fa165552023440lgao    // Save our postition in the file, since offsets in the headers
131430fdf1140b8d1ce93f3821d986fa165552023440lgao    // are relative to the particular image.
131530fdf1140b8d1ce93f3821d986fa165552023440lgao    //
131630fdf1140b8d1ce93f3821d986fa165552023440lgao    ImageStart = ftell (InFptr);
131730fdf1140b8d1ce93f3821d986fa165552023440lgao    ImageCount++;
131830fdf1140b8d1ce93f3821d986fa165552023440lgao
131930fdf1140b8d1ce93f3821d986fa165552023440lgao    //
132030fdf1140b8d1ce93f3821d986fa165552023440lgao    // Read the option ROM header. Have to assume a raw binary image for now.
132130fdf1140b8d1ce93f3821d986fa165552023440lgao    //
132230fdf1140b8d1ce93f3821d986fa165552023440lgao    if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) {
132330fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 3001, "Not supported", "Failed to read PCI ROM header from file!");
132430fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
132530fdf1140b8d1ce93f3821d986fa165552023440lgao    }
132630fdf1140b8d1ce93f3821d986fa165552023440lgao
132730fdf1140b8d1ce93f3821d986fa165552023440lgao    //
132830fdf1140b8d1ce93f3821d986fa165552023440lgao    // Dump the contents of the header
132930fdf1140b8d1ce93f3821d986fa165552023440lgao    //
1330fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "Image %u -- Offset 0x%X\n", (unsigned) ImageCount, (unsigned) ImageStart);
133130fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "  ROM header contents\n");
1332fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    Signature              0x%04X\n", PciRomHdr.Signature);
1333fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    PCIR offset            0x%04X\n", PciRomHdr.PcirOffset);
133430fdf1140b8d1ce93f3821d986fa165552023440lgao    //
133530fdf1140b8d1ce93f3821d986fa165552023440lgao    // Find PCI data structure
133630fdf1140b8d1ce93f3821d986fa165552023440lgao    //
133730fdf1140b8d1ce93f3821d986fa165552023440lgao    if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) {
133830fdf1140b8d1ce93f3821d986fa165552023440lgao      Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI data structure!");
133930fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
134030fdf1140b8d1ce93f3821d986fa165552023440lgao    }
134130fdf1140b8d1ce93f3821d986fa165552023440lgao    //
134230fdf1140b8d1ce93f3821d986fa165552023440lgao    // Read and dump the PCI data structure
134330fdf1140b8d1ce93f3821d986fa165552023440lgao    //
134430fdf1140b8d1ce93f3821d986fa165552023440lgao    memset (&PciDs23, 0, sizeof (PciDs23));
134530fdf1140b8d1ce93f3821d986fa165552023440lgao    memset (&PciDs30, 0, sizeof (PciDs30));
134630fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Pci23 == 1) {
134730fdf1140b8d1ce93f3821d986fa165552023440lgao      if (fread (&PciDs23, sizeof (PciDs23), 1, InFptr) != 1) {
134830fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName);
134930fdf1140b8d1ce93f3821d986fa165552023440lgao        goto BailOut;
135030fdf1140b8d1ce93f3821d986fa165552023440lgao      }
135130fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
135230fdf1140b8d1ce93f3821d986fa165552023440lgao      if (fread (&PciDs30, sizeof (PciDs30), 1, InFptr) != 1) {
135330fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName);
135430fdf1140b8d1ce93f3821d986fa165552023440lgao        goto BailOut;
135530fdf1140b8d1ce93f3821d986fa165552023440lgao      }
135630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
135730fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Verbose) {
135830fdf1140b8d1ce93f3821d986fa165552023440lgao      VerboseMsg("Read PCI data structure from file %s", InFile->FileName);
135930fdf1140b8d1ce93f3821d986fa165552023440lgao    }
136030fdf1140b8d1ce93f3821d986fa165552023440lgao
136130fdf1140b8d1ce93f3821d986fa165552023440lgao    //fprintf (stdout, "  PCI Data Structure\n");
136230fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Pci23 == 1) {
136330fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (
136430fdf1140b8d1ce93f3821d986fa165552023440lgao      stdout,
136530fdf1140b8d1ce93f3821d986fa165552023440lgao      "    Signature              %c%c%c%c\n",
136630fdf1140b8d1ce93f3821d986fa165552023440lgao      (char) PciDs23.Signature,
136730fdf1140b8d1ce93f3821d986fa165552023440lgao      (char) (PciDs23.Signature >> 8),
136830fdf1140b8d1ce93f3821d986fa165552023440lgao      (char) (PciDs23.Signature >> 16),
136930fdf1140b8d1ce93f3821d986fa165552023440lgao      (char) (PciDs23.Signature >> 24)
137030fdf1140b8d1ce93f3821d986fa165552023440lgao      );
137130fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Vendor ID              0x%04X\n", PciDs23.VendorId);
137230fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Device ID              0x%04X\n", PciDs23.DeviceId);
137330fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Length                 0x%04X\n", PciDs23.Length);
137430fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Revision               0x%04X\n", PciDs23.Revision);
137530fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (
137630fdf1140b8d1ce93f3821d986fa165552023440lgao      stdout,
137730fdf1140b8d1ce93f3821d986fa165552023440lgao      "    Class Code             0x%06X\n",
1378fd171542e0aa89ac12a09d79608173f48019b14bvanjeff      (unsigned) (PciDs23.ClassCode[0] | (PciDs23.ClassCode[1] << 8) | (PciDs23.ClassCode[2] << 16))
137930fdf1140b8d1ce93f3821d986fa165552023440lgao      );
1380fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    Image size             0x%X\n", (unsigned) PciDs23.ImageLength * 512);
138130fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Code revision:         0x%04X\n", PciDs23.CodeRevision);
1382fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    Indicator              0x%02X", PciDs23.Indicator);
138330fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
138430fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (
138530fdf1140b8d1ce93f3821d986fa165552023440lgao      stdout,
138630fdf1140b8d1ce93f3821d986fa165552023440lgao      "    Signature               %c%c%c%c\n",
138730fdf1140b8d1ce93f3821d986fa165552023440lgao      (char) PciDs30.Signature,
138830fdf1140b8d1ce93f3821d986fa165552023440lgao      (char) (PciDs30.Signature >> 8),
138930fdf1140b8d1ce93f3821d986fa165552023440lgao      (char) (PciDs30.Signature >> 16),
139030fdf1140b8d1ce93f3821d986fa165552023440lgao      (char) (PciDs30.Signature >> 24)
139130fdf1140b8d1ce93f3821d986fa165552023440lgao      );
139230fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Vendor ID               0x%04X\n", PciDs30.VendorId);
139330fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Device ID               0x%04X\n", PciDs30.DeviceId);
139430fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Length                  0x%04X\n", PciDs30.Length);
139530fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Revision                0x%04X\n", PciDs30.Revision);
1396fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    DeviceListOffset        0x%02X\n", PciDs30.DeviceListOffset);
139730fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (
139830fdf1140b8d1ce93f3821d986fa165552023440lgao      stdout,
139930fdf1140b8d1ce93f3821d986fa165552023440lgao      "    Class Code              0x%06X\n",
1400fd171542e0aa89ac12a09d79608173f48019b14bvanjeff      (unsigned) (PciDs30.ClassCode[0] | (PciDs30.ClassCode[1] << 8) | (PciDs30.ClassCode[2] << 16))
140130fdf1140b8d1ce93f3821d986fa165552023440lgao      );
1402fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    Image size              0x%X\n", (unsigned) PciDs30.ImageLength * 512);
140330fdf1140b8d1ce93f3821d986fa165552023440lgao    fprintf (stdout, "    Code revision:          0x%04X\n", PciDs30.CodeRevision);
1404fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    MaxRuntimeImageLength   0x%02X\n", PciDs30.MaxRuntimeImageLength);
1405fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset);
1406fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset);
1407fd171542e0aa89ac12a09d79608173f48019b14bvanjeff    fprintf (stdout, "    Indicator               0x%02X", PciDs30.Indicator);
140830fdf1140b8d1ce93f3821d986fa165552023440lgao    }
140930fdf1140b8d1ce93f3821d986fa165552023440lgao    //
141030fdf1140b8d1ce93f3821d986fa165552023440lgao    // Print the indicator, used to flag the last image
141130fdf1140b8d1ce93f3821d986fa165552023440lgao    //
141230fdf1140b8d1ce93f3821d986fa165552023440lgao    if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) {
141330fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (stdout, "   (last image)\n");
141430fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
141530fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (stdout, "\n");
141630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
141730fdf1140b8d1ce93f3821d986fa165552023440lgao    //
141830fdf1140b8d1ce93f3821d986fa165552023440lgao    // Print the code type. If EFI code, then we can provide more info.
141930fdf1140b8d1ce93f3821d986fa165552023440lgao    //
142030fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Pci23 == 1) {
1421fd171542e0aa89ac12a09d79608173f48019b14bvanjeff      fprintf (stdout, "    Code type              0x%02X", PciDs23.CodeType);
142230fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
1423fd171542e0aa89ac12a09d79608173f48019b14bvanjeff      fprintf (stdout, "    Code type               0x%02X", PciDs30.CodeType);
142430fdf1140b8d1ce93f3821d986fa165552023440lgao    }
142530fdf1140b8d1ce93f3821d986fa165552023440lgao    if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
142630fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (stdout, "   (EFI image)\n");
142730fdf1140b8d1ce93f3821d986fa165552023440lgao      //
142830fdf1140b8d1ce93f3821d986fa165552023440lgao      // Re-read the header as an EFI ROM header, then dump more info
142930fdf1140b8d1ce93f3821d986fa165552023440lgao      //
143030fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (stdout, "  EFI ROM header contents\n");
143130fdf1140b8d1ce93f3821d986fa165552023440lgao      if (fseek (InFptr, ImageStart, SEEK_SET)) {
143230fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 5001, "Failed to re-seek to ROM header structure!", NULL);
143330fdf1140b8d1ce93f3821d986fa165552023440lgao        goto BailOut;
143430fdf1140b8d1ce93f3821d986fa165552023440lgao      }
143530fdf1140b8d1ce93f3821d986fa165552023440lgao
143630fdf1140b8d1ce93f3821d986fa165552023440lgao      if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) {
143730fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 5001, "Failed to read EFI PCI ROM header from file!", NULL);
143830fdf1140b8d1ce93f3821d986fa165552023440lgao        goto BailOut;
143930fdf1140b8d1ce93f3821d986fa165552023440lgao      }
144030fdf1140b8d1ce93f3821d986fa165552023440lgao      //
144130fdf1140b8d1ce93f3821d986fa165552023440lgao      // Now dump more info
144230fdf1140b8d1ce93f3821d986fa165552023440lgao      //
1443fd171542e0aa89ac12a09d79608173f48019b14bvanjeff      fprintf (stdout, "    EFI Signature          0x%04X\n", (unsigned) EfiRomHdr.EfiSignature);
144430fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (
144530fdf1140b8d1ce93f3821d986fa165552023440lgao        stdout,
144630fdf1140b8d1ce93f3821d986fa165552023440lgao        "    Compression Type       0x%04X ",
1447fd171542e0aa89ac12a09d79608173f48019b14bvanjeff        EfiRomHdr.CompressionType
144830fdf1140b8d1ce93f3821d986fa165552023440lgao        );
144930fdf1140b8d1ce93f3821d986fa165552023440lgao      if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
145030fdf1140b8d1ce93f3821d986fa165552023440lgao        fprintf (stdout, "(compressed)\n");
145130fdf1140b8d1ce93f3821d986fa165552023440lgao      } else {
145230fdf1140b8d1ce93f3821d986fa165552023440lgao        fprintf (stdout, "(not compressed)\n");
145330fdf1140b8d1ce93f3821d986fa165552023440lgao      }
145430fdf1140b8d1ce93f3821d986fa165552023440lgao
145530fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (
145630fdf1140b8d1ce93f3821d986fa165552023440lgao        stdout,
145730fdf1140b8d1ce93f3821d986fa165552023440lgao        "    Machine type           0x%04X (%s)\n",
145830fdf1140b8d1ce93f3821d986fa165552023440lgao        EfiRomHdr.EfiMachineType,
145930fdf1140b8d1ce93f3821d986fa165552023440lgao        GetMachineTypeStr (EfiRomHdr.EfiMachineType)
146030fdf1140b8d1ce93f3821d986fa165552023440lgao        );
146130fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (
146230fdf1140b8d1ce93f3821d986fa165552023440lgao        stdout,
146330fdf1140b8d1ce93f3821d986fa165552023440lgao        "    Subsystem              0x%04X (%s)\n",
146430fdf1140b8d1ce93f3821d986fa165552023440lgao        EfiRomHdr.EfiSubsystem,
146530fdf1140b8d1ce93f3821d986fa165552023440lgao        GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem)
146630fdf1140b8d1ce93f3821d986fa165552023440lgao        );
146730fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (
146830fdf1140b8d1ce93f3821d986fa165552023440lgao        stdout,
146930fdf1140b8d1ce93f3821d986fa165552023440lgao        "    EFI image offset       0x%04X (@0x%X)\n",
1470fd171542e0aa89ac12a09d79608173f48019b14bvanjeff        EfiRomHdr.EfiImageHeaderOffset,
1471fd171542e0aa89ac12a09d79608173f48019b14bvanjeff        EfiRomHdr.EfiImageHeaderOffset + (unsigned) ImageStart
147230fdf1140b8d1ce93f3821d986fa165552023440lgao        );
147330fdf1140b8d1ce93f3821d986fa165552023440lgao
147430fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
147530fdf1140b8d1ce93f3821d986fa165552023440lgao      //
147630fdf1140b8d1ce93f3821d986fa165552023440lgao      // Not an EFI image
147730fdf1140b8d1ce93f3821d986fa165552023440lgao      //
147830fdf1140b8d1ce93f3821d986fa165552023440lgao      fprintf (stdout, "\n");
147930fdf1140b8d1ce93f3821d986fa165552023440lgao    }
148030fdf1140b8d1ce93f3821d986fa165552023440lgao    //
148130fdf1140b8d1ce93f3821d986fa165552023440lgao    // If code type is EFI image, then dump it as well?
148230fdf1140b8d1ce93f3821d986fa165552023440lgao    //
148330fdf1140b8d1ce93f3821d986fa165552023440lgao    // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) {
148430fdf1140b8d1ce93f3821d986fa165552023440lgao    // }
148530fdf1140b8d1ce93f3821d986fa165552023440lgao    //
148630fdf1140b8d1ce93f3821d986fa165552023440lgao    // If last image, then we're done
148730fdf1140b8d1ce93f3821d986fa165552023440lgao    //
148830fdf1140b8d1ce93f3821d986fa165552023440lgao    if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) {
148930fdf1140b8d1ce93f3821d986fa165552023440lgao      goto BailOut;
149030fdf1140b8d1ce93f3821d986fa165552023440lgao    }
149130fdf1140b8d1ce93f3821d986fa165552023440lgao    //
149230fdf1140b8d1ce93f3821d986fa165552023440lgao    // Seek to the start of the next image
149330fdf1140b8d1ce93f3821d986fa165552023440lgao    //
149430fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mOptions.Pci23 == 1) {
149530fdf1140b8d1ce93f3821d986fa165552023440lgao      if (fseek (InFptr, ImageStart + (PciDs23.ImageLength * 512), SEEK_SET)) {
149630fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!");
149730fdf1140b8d1ce93f3821d986fa165552023440lgao        goto BailOut;
149830fdf1140b8d1ce93f3821d986fa165552023440lgao      }
149930fdf1140b8d1ce93f3821d986fa165552023440lgao    } else {
150030fdf1140b8d1ce93f3821d986fa165552023440lgao      if (fseek (InFptr, ImageStart + (PciDs30.ImageLength * 512), SEEK_SET)) {
150130fdf1140b8d1ce93f3821d986fa165552023440lgao        Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!");
150230fdf1140b8d1ce93f3821d986fa165552023440lgao        goto BailOut;
150330fdf1140b8d1ce93f3821d986fa165552023440lgao      }
150430fdf1140b8d1ce93f3821d986fa165552023440lgao    }
150530fdf1140b8d1ce93f3821d986fa165552023440lgao  }
150630fdf1140b8d1ce93f3821d986fa165552023440lgao
150730fdf1140b8d1ce93f3821d986fa165552023440lgaoBailOut:
150830fdf1140b8d1ce93f3821d986fa165552023440lgao  fclose (InFptr);
150930fdf1140b8d1ce93f3821d986fa165552023440lgao}
151030fdf1140b8d1ce93f3821d986fa165552023440lgao
151130fdf1140b8d1ce93f3821d986fa165552023440lgaochar *
151230fdf1140b8d1ce93f3821d986fa165552023440lgaoGetMachineTypeStr (
151330fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT16    MachineType
151430fdf1140b8d1ce93f3821d986fa165552023440lgao  )
151530fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
151630fdf1140b8d1ce93f3821d986fa165552023440lgao
151730fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
151830fdf1140b8d1ce93f3821d986fa165552023440lgao
151930fdf1140b8d1ce93f3821d986fa165552023440lgao  GC_TODO: Add function description
152030fdf1140b8d1ce93f3821d986fa165552023440lgao
152130fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
152230fdf1140b8d1ce93f3821d986fa165552023440lgao
152330fdf1140b8d1ce93f3821d986fa165552023440lgao  MachineType - GC_TODO: add argument description
152430fdf1140b8d1ce93f3821d986fa165552023440lgao
152530fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
152630fdf1140b8d1ce93f3821d986fa165552023440lgao
152730fdf1140b8d1ce93f3821d986fa165552023440lgao  GC_TODO: add return values
152830fdf1140b8d1ce93f3821d986fa165552023440lgao
152930fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
153030fdf1140b8d1ce93f3821d986fa165552023440lgao{
153130fdf1140b8d1ce93f3821d986fa165552023440lgao  int Index;
153230fdf1140b8d1ce93f3821d986fa165552023440lgao
153330fdf1140b8d1ce93f3821d986fa165552023440lgao  for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) {
153430fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mMachineTypes[Index].Value == MachineType) {
153530fdf1140b8d1ce93f3821d986fa165552023440lgao      return mMachineTypes[Index].Name;
153630fdf1140b8d1ce93f3821d986fa165552023440lgao    }
153730fdf1140b8d1ce93f3821d986fa165552023440lgao  }
153830fdf1140b8d1ce93f3821d986fa165552023440lgao
153930fdf1140b8d1ce93f3821d986fa165552023440lgao  return "unknown";
154030fdf1140b8d1ce93f3821d986fa165552023440lgao}
154130fdf1140b8d1ce93f3821d986fa165552023440lgao
154230fdf1140b8d1ce93f3821d986fa165552023440lgaostatic
154330fdf1140b8d1ce93f3821d986fa165552023440lgaochar *
154430fdf1140b8d1ce93f3821d986fa165552023440lgaoGetSubsystemTypeStr (
154530fdf1140b8d1ce93f3821d986fa165552023440lgao  UINT16  SubsystemType
154630fdf1140b8d1ce93f3821d986fa165552023440lgao  )
154730fdf1140b8d1ce93f3821d986fa165552023440lgao/*++
154830fdf1140b8d1ce93f3821d986fa165552023440lgao
154930fdf1140b8d1ce93f3821d986fa165552023440lgaoRoutine Description:
155030fdf1140b8d1ce93f3821d986fa165552023440lgao
155130fdf1140b8d1ce93f3821d986fa165552023440lgao  GC_TODO: Add function description
155230fdf1140b8d1ce93f3821d986fa165552023440lgao
155330fdf1140b8d1ce93f3821d986fa165552023440lgaoArguments:
155430fdf1140b8d1ce93f3821d986fa165552023440lgao
155530fdf1140b8d1ce93f3821d986fa165552023440lgao  SubsystemType - GC_TODO: add argument description
155630fdf1140b8d1ce93f3821d986fa165552023440lgao
155730fdf1140b8d1ce93f3821d986fa165552023440lgaoReturns:
155830fdf1140b8d1ce93f3821d986fa165552023440lgao
155930fdf1140b8d1ce93f3821d986fa165552023440lgao  GC_TODO: add return values
156030fdf1140b8d1ce93f3821d986fa165552023440lgao
156130fdf1140b8d1ce93f3821d986fa165552023440lgao--*/
156230fdf1140b8d1ce93f3821d986fa165552023440lgao{
156330fdf1140b8d1ce93f3821d986fa165552023440lgao  int Index;
156430fdf1140b8d1ce93f3821d986fa165552023440lgao
156530fdf1140b8d1ce93f3821d986fa165552023440lgao  for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) {
156630fdf1140b8d1ce93f3821d986fa165552023440lgao    if (mSubsystemTypes[Index].Value == SubsystemType) {
156730fdf1140b8d1ce93f3821d986fa165552023440lgao      return mSubsystemTypes[Index].Name;
156830fdf1140b8d1ce93f3821d986fa165552023440lgao    }
156930fdf1140b8d1ce93f3821d986fa165552023440lgao  }
157030fdf1140b8d1ce93f3821d986fa165552023440lgao
157130fdf1140b8d1ce93f3821d986fa165552023440lgao  return "unknown";
157230fdf1140b8d1ce93f3821d986fa165552023440lgao}
1573