⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 efirom.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 3 页
字号:
/*++

Copyright (c)  1999 - 2002 Intel Corporation. All rights reserved
This software and associated documentation (if any) is furnished
under a license and may only be used or copied in accordance
with the terms of the license. Except as permitted by such
license, no part of this software or documentation may be
reproduced, stored in a retrieval system, or transmitted in any
form or by any means without the express written consent of
Intel Corporation.

Module Name:

  EfiRom.c
  
Abstract:

  Utility program to create an EFI option ROM image from binary and 
  EFI PE32 files.


--*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

//
// Includes for EFI 1.1 build
//
#include "Efi.h"        // required defines for Compress.h
#include "EfiImage.h"   // for PE32 structure definitions
#include "Compress.h"   // for compression function

#include "Pci22.h"      // for option ROM header structures

//
// Version of this utility 
//
#define UTILITY_VERSION         "v2.5"

//
// Define some status return values
//
#define STATUS_SUCCESS        0
#define STATUS_WARNING        1
#define STATUS_ERROR          2

//
// Define the max length of a filename
//
#define MAX_PATH          200

#define DEFAULT_OUTPUT_EXTENSION   ".rom"

//
// Max size for an option ROM image
//
#define MAX_OPTION_ROM_SIZE      (1024 * 1024 * 16)  // 16MB

//
// Values for the indicator field in the PCI data structure
//
#define INDICATOR_LAST    0x80      // last file in series of files

//
// Masks for the FILE_LIST.FileFlags field
//
#define FILE_FLAG_BINARY        0x01
#define FILE_FLAG_EFI           0x02
#define FILE_FLAG_COMPRESS      0x04

//
// Use this linked list structure to keep track of all the filenames
// specified on the command line.
//
typedef struct _FILE_LIST {
  struct _FILE_LIST     *Next;
  INT8                  *FileName;
  UINT32                FileFlags;
  UINT32                ClassCode;
  UINT16                CodeRevision;
} FILE_LIST;

//
// Use this to track our command-line options
//
typedef struct {
  INT8            OutFileName[MAX_PATH];
  INT8            NoLast;
  INT8            Verbose;
  INT8            DumpOption;
  UINT8           DevIdValid;
  UINT8           VendIdValid;
  UINT16          VendId;
  UINT16          DevId;
  FILE_LIST       *FileList;
} OPTIONS;

//
// Make a global structure to keep track of command-line options
//
static OPTIONS             mOptions;

//
// Use these to convert from machine type value to a named type
//
typedef struct {
  UINT16    Value;
  char      *Name;
} STRING_LOOKUP;

static STRING_LOOKUP mMachineTypes[] = {
  EFI_IMAGE_MACHINE_IA32, "IA32",
  EFI_IMAGE_MACHINE_IA64, "IA64",
  EFI_IMAGE_MACHINE_EBC,  "EBC",
  0, NULL
};

static STRING_LOOKUP mSubsystemTypes[] = {
  EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION, "EFI application",
  EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, "EFI boot service driver",
  EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, "EFI runtime driver",
  0, NULL
};
//
//  Function prototypes
//
static 
void 
Usage ();

static 
int 
ParseCommandLine (
  int       Argc,
  char      *Argv[],
  OPTIONS   *Options
  );


static
int
CheckPE32File ( 
  FILE      *Fptr,
  UINT16    *MachineType,
  UINT16    *SubSystem
  );

static 
int
ProcessEfiFile (
  FILE      *OutFptr,
  FILE_LIST *InFile,
  UINT16    VendId,
  UINT16    DevId,
  UINT32    *Size
  );

static 
int
ProcessBinFile (
  FILE      *OutFptr,
  FILE_LIST *InFile,
  UINT32    *Size
  );

static
void
DumpImage (
  FILE_LIST *InFile
  );

char *
GetMachineTypeStr (
  UINT16    MachineType
  );

static
char  *
GetSubsystemTypeStr (
  UINT16  SubsystemType
  );

main(
  int   Argc,
  char  *Argv[]
  )
/*++

Routine Description:
  
  Given an EFI image filename, create a ROM-able image by creating an option 
  ROM header and PCI data structure, filling them in, and then writing the
  option ROM header + PCI data structure + EFI image out to the output file.

Arguments:

  Argc            - standard C main() argument count

  Argv            - standard C main() argument list

Returns:

  0             success
  non-zero      otherwise

--*/
{
  INT8                *Ext;
  FILE                *FptrOut;
  UINT32              Status;
  FILE_LIST           *FList;
  UINT32              TotalSize, Size;

  Status = STATUS_SUCCESS; 
  FptrOut = NULL;

  //
  // Parse the command line arguments
  //
  if (ParseCommandLine(Argc, Argv, &mOptions)) {
    return STATUS_ERROR;
  }
  //
  // If dumping an image, then do that and quit
  //
  if (mOptions.DumpOption) {
    DumpImage (mOptions.FileList);
    goto BailOut;
  }
  //
  // Determine the output filename. Either what they specified on 
  // the command line, or the first input filename with a different extension.
  //
  if (!mOptions.OutFileName[0]) {
    strcpy (mOptions.OutFileName, mOptions.FileList->FileName);
    //
    // Find the last . on the line and replace the filename extension with 
    // the default
    //
    for (Ext = mOptions.OutFileName + strlen(mOptions.OutFileName) - 1; 
          (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\') ;
          Ext--);
    //
    // If dot here, then insert extension here, otherwise append
    //
    if (*Ext != '.')
      Ext = mOptions.OutFileName + strlen (mOptions.OutFileName);
    strcpy (Ext, DEFAULT_OUTPUT_EXTENSION);
  }
  //
  // Make sure we don't have the same filename for input and output files
  //
  for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
    if (stricmp(mOptions.OutFileName, FList->FileName) == 0) {
      Status = STATUS_ERROR;
      fprintf(stdout, "ERROR: Input and output file names must be different - %s = %s\n",
          FList->FileName, mOptions.OutFileName);
      goto BailOut;
    }
  }
  
  //
  // Now open our output file
  //
  if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) {
    fprintf (stdout, "ERROR: Failed to open output file %s\n", mOptions.OutFileName);
    goto BailOut;
  }

  //
  // Process all our files
  //
  TotalSize = 0;
  for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) {
    Size = 0;
    if (FList->FileFlags & FILE_FLAG_EFI) {
      if (mOptions.Verbose) {
        fprintf (stdout, "Processing EFI file    %s\n", FList->FileName);
      }
      Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size);
    } else if (FList->FileFlags & FILE_FLAG_BINARY) {
      if (mOptions.Verbose) {
        fprintf (stdout, "Processing binary file %s\n", FList->FileName);
      }
      Status = ProcessBinFile (FptrOut, FList, &Size);
    } else {
      fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName);
      Status = STATUS_ERROR;
    }
    if (mOptions.Verbose) {
      fprintf (stdout, "  Output size = 0x%X\n", Size);
    }
    if (Status != STATUS_SUCCESS) {
      break;
    }
    TotalSize += Size;
  }

  //
  // Check total size
  //
  if (TotalSize > MAX_OPTION_ROM_SIZE) {
    fprintf (stdout, "ERROR: Option ROM image size exceeds limit 0x%X bytes\n", 
      MAX_OPTION_ROM_SIZE);
    Status = STATUS_ERROR;
  }


BailOut:
  if (FptrOut != NULL) {
    fclose (FptrOut);
  }
  //
  // Clean up our file list
  //
  while (mOptions.FileList != NULL) {
    FList = mOptions.FileList->Next;
    free (mOptions.FileList);
    mOptions.FileList = FList;
  }
  return Status;
}


static 
int
ProcessBinFile (
  FILE      *OutFptr,
  FILE_LIST *InFile,
  UINT32    *Size
  )
/*++

Routine Description:
  
  Process a binary input file.

Arguments:

  OutFptr     - file pointer to output binary ROM image file we're creating
  InFile      - structure contains information on the binary file to process
  Size        - pointer to where to return the size added to the output file

Returns:

  0 - successful

--*/
{
  FILE                        *InFptr;
  UINT32                      TotalSize;
  UINT32                      FileSize;
  UINT8                       *Buffer;
  UINT32                      Status;
  PCI_EXPANSION_ROM_HEADER    *RomHdr;
  PCI_DATA_STRUCTURE          *PciDs;
  UINT32                      Index;
  UINT8                       ByteCheckSum;

  Status = STATUS_SUCCESS;

  //
  // Try to open the input file
  //
  if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) {
    fprintf (stdout, "ERROR: Failed to open input file %s\n", InFile->FileName);
    return STATUS_ERROR;
  }

  //
  // Seek to the end of the input file and get the file size. Then allocate 
  // a buffer to read it in to.
  //
  fseek (InFptr, 0, SEEK_END);
  FileSize = ftell (InFptr);
  if (mOptions.Verbose) {
    fprintf (stdout, "  File size   = 0x%X\n", FileSize);
  }
  fseek (InFptr, 0, SEEK_SET);
  Buffer = (INT8 *)malloc (FileSize);  
  if (Buffer == NULL) {
    fprintf (stdout, "ERROR: Memory allocation failed\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }
  if (fread (Buffer, FileSize, 1, InFptr) != 1) {
    fprintf(stdout, "ERROR: Failed to read all bytes from input file\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }
  
  //
  // Total size must be an even multiple of 512 bytes, and can't exceed 
  // the option ROM image size.
  //
  TotalSize = FileSize;
  if (TotalSize & 0x1FF) {
    TotalSize = (TotalSize + 0x200) & ~0x1ff;
  }
  if (TotalSize > MAX_OPTION_ROM_SIZE) {
    fprintf (stdout, "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n", 
      InFile->FileName, MAX_OPTION_ROM_SIZE);
    Status = STATUS_ERROR;
    goto BailOut;
  }
  //
  // Return the size to the caller so they can keep track of the running total.
  //
  *Size = TotalSize;

  //
  // Crude check to make sure it's a legitimate ROM image
  //
  RomHdr = (PCI_EXPANSION_ROM_HEADER *)Buffer;
  if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
    fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }
  //
  // Make sure the pointer to the PCI data structure is within the size of the image.
  // Then check it for valid signature.
  //
  if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) {
    fprintf (stdout, "ERROR: Invalid PCI data structure offset\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }
  PciDs = (PCI_DATA_STRUCTURE *)(Buffer + RomHdr->PcirOffset);
  if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
    fprintf (stdout, "ERROR: PCI data structure has invalid signature\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }


  //
  // If this is the last image, then set the LAST bit unless requested not
  // to via the command-line -l argument. Otherwise, make sure you clear it.
  //
  if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
    PciDs->Indicator = INDICATOR_LAST;
  } else {
    PciDs->Indicator = 0;
  }

  ByteCheckSum = 0;
  for (Index = 0; Index < FileSize - 1; Index++) {
    ByteCheckSum = (UINT8)(ByteCheckSum + Buffer[Index]);
  }
  Buffer[FileSize-1] = (UINT8)((~ByteCheckSum) + 1);
  fprintf (stdout, "CheckSUm = %02x\n", (UINT32)Buffer[FileSize-1]);

  //
  // Now copy the input file contents out to the output file
  //
  if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -