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

📄 efirom.c

📁 Next BIOS Source code : Extensible Firmware Interface
💻 C
📖 第 1 页 / 共 3 页
字号:
    fprintf(stdout, "ERROR: Failed to write all file bytes to output file\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }
  TotalSize -= FileSize;
  //
  // Pad the rest of the image to make it a multiple of 512 bytes
  //
  while (TotalSize > 0) {
    putc (~0, OutFptr);
    TotalSize--;
  }

BailOut:
  if (InFptr != NULL) {
    fclose (InFptr);
  }  
  if (Buffer != NULL) {
    free (Buffer);
  }
  //
  // Print the file name if errors occurred
  //
  if (Status != STATUS_SUCCESS) {
    fprintf (stdout, "Error processing binary file %s\n", InFile->FileName);
  }
  return Status;
}
static 
int
ProcessEfiFile (
  FILE      *OutFptr,
  FILE_LIST *InFile,
  UINT16    VendId,
  UINT16    DevId,
  UINT32    *Size
  )
/*++

Routine Description:
  
  Process a PE32 EFI file.

Arguments:

  OutFptr     - file pointer to output binary ROM image file we're creating
  InFile      - structure contains information on the PE32 file to process
  VendId      - vendor ID as required in the option ROM header
  DevId       - device ID as required in the option ROM header
  Size        - pointer to where to return the size added to the output file

Returns:

  0 - successful

--*/
{
  UINT32                          Status;
  FILE                            *InFptr;
  EFI_PCI_EXPANSION_ROM_HEADER    RomHdr;
  PCI_DATA_STRUCTURE              PciDs;
  UINT32                          FileSize, CompressedFileSize;
  UINT8                           *Buffer;
  UINT8                           *CompressedBuffer;
  UINT8                           *TempBufferPtr;
  UINT32                          TotalSize;
  UINT32                          HeaderSize;
  UINT16                          MachineType, SubSystem;
  UINT32                          HeaderPadBytes;

  //
  // 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;
  }

  //
  // Initialize our buffer pointers to null.
  //
  Buffer = NULL;
  CompressedBuffer = NULL;

  //
  // Double-check the file to make sure it's what we expect it to be
  //
  Status = CheckPE32File (InFptr, &MachineType, &SubSystem);
  if (Status != STATUS_SUCCESS) {
    goto BailOut;
  }

  //
  // Seek to the end of the input file and get the file size
  //
  fseek (InFptr, 0, SEEK_END);
  FileSize = ftell (InFptr);

  //
  // Get the size of the headers we're going to put in front of the image. The
  // EFI header must be aligned on a 4-byte boundary, so pad accordingly.
  //
  if (sizeof (RomHdr) & 0x03) {
    HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03);
  } else {
    HeaderPadBytes = 0;
  }
  HeaderSize =  sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + 
                sizeof (EFI_PCI_EXPANSION_ROM_HEADER);
  if (mOptions.Verbose) {
    fprintf (stdout, "  File size   = 0x%X\n", FileSize);
  }

  //
  // Allocate memory for the entire file (in case we have to compress), then
  // seek back to the beginning of the file and read it into our buffer.
  //
  Buffer = (INT8 *) malloc (FileSize);
  if (Buffer == NULL) {
    fprintf (stdout, "ERROR: Memory allocation failed\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }
  fseek (InFptr, 0, SEEK_SET);
  if (fread (Buffer, FileSize, 1, InFptr) != 1) {
    fprintf(stdout, "ERROR: Failed to read all bytes from input file\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }

  //
  // Now determine the size of the final output file. It's either the header size
  // plus the file's size, or the header size plus the compressed file size.
  //
  if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
    //
    // Allocate a buffer into which we can compress the image, compress it, 
    // and use that size as the new size.
    //
    CompressedBuffer = (INT8 *) malloc (FileSize);
    if (CompressedBuffer == NULL) {
      fprintf (stdout, "ERROR: Memory allocation failed\n");
      Status = STATUS_ERROR;
      goto BailOut;
    }
    CompressedFileSize = FileSize;
    Status = Compress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize);
    if (Status != STATUS_SUCCESS) {
      fprintf (stdout, "ERROR: Compression failed\n");
      goto BailOut;
    }
    //
    // Now compute the size, then swap buffer pointers.
    //
    if (mOptions.Verbose) {
      fprintf (stdout, "  Comp size   = 0x%X\n", CompressedFileSize);
    }
    TotalSize  = CompressedFileSize + HeaderSize;
    FileSize = CompressedFileSize;
    TempBufferPtr = Buffer;
    Buffer = CompressedBuffer;
    CompressedBuffer = TempBufferPtr;
  } else {
    TotalSize = FileSize + HeaderSize;
  }
  //
  // Total size must be an even multiple of 512 bytes
  //
  if (TotalSize & 0x1FF) {
    TotalSize = (TotalSize + 0x200) & ~0x1ff;
  }
  //
  // Check size
  //
  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;

  //
  // Now fill in the ROM header. These values come from chapter 18 of the
  // EFI 1.02 specification.
  //
  memset (&RomHdr,0, sizeof (RomHdr));
  RomHdr.Signature            = PCI_EXPANSION_ROM_HEADER_SIGNATURE;
  RomHdr.InitializationSize   = (UINT16)(TotalSize / 512);
  RomHdr.EfiSignature         = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE;
  RomHdr.EfiSubsystem         = SubSystem;
  RomHdr.EfiMachineType       = MachineType;
  RomHdr.EfiImageHeaderOffset = (UINT16)HeaderSize;
  RomHdr.PcirOffset           = (UINT16)(sizeof (RomHdr) + HeaderPadBytes);
  //
  // Set image as compressed or not
  //
  if (InFile->FileFlags & FILE_FLAG_COMPRESS) {
    RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED;
  }
  //
  // Fill in the PCI data structure
  //
  memset (&PciDs,0, sizeof (PCI_DATA_STRUCTURE)); 

  PciDs.Signature   = PCI_DATA_STRUCTURE_SIGNATURE;
  PciDs.VendorId    = VendId;
  PciDs.DeviceId    = DevId;
  PciDs.Length      = (UINT16) sizeof (PCI_DATA_STRUCTURE);
  PciDs.Revision    = 0;
  //
  // Class code and code revision from the command line (optional)
  //
  PciDs.ClassCode[0]  = (UINT8)InFile->ClassCode;
  PciDs.ClassCode[1]  = (UINT8)(InFile->ClassCode >> 8);
  PciDs.ClassCode[2]  = (UINT8)(InFile->ClassCode >> 16);
  PciDs.ImageLength   = RomHdr.InitializationSize;
  PciDs.CodeRevision  = InFile->CodeRevision;
  PciDs.CodeType      = PCI_CODE_TYPE_EFI_IMAGE;

  //
  // If this is the last image, then set the LAST bit unless requested not
  // to via the command-line -l argument.
  //
  if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) {
    PciDs.Indicator = INDICATOR_LAST;
  }
  //
  // Write the ROM header to the output file
  //
  if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) {
    fprintf (stdout, "ERROR: Failed to write ROM header to output file\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }
  // 
  // Write pad bytes to align the PciDs
  //
  while (HeaderPadBytes > 0) {
    if (putc (0, OutFptr) == EOF) {
      fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n");
      Status = STATUS_ERROR;
      goto BailOut;
    }
    HeaderPadBytes--;
  }
  //
  // Write the PCI data structure header to the output file
  //
  if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) {
    fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }

  //
  // Keep track of how many bytes left to write
  //
  TotalSize -= HeaderSize;

  // 
  // Now dump the input file's contents to the output file
  //
  if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) {
    fprintf(stdout, "ERROR: Failed to write all file bytes to output file\n");
    Status = STATUS_ERROR;
    goto BailOut;
  }
  TotalSize -= FileSize;
  //
  // Pad the rest of the image to make it a multiple of 512 bytes
  //
  while (TotalSize > 0) {
    if (putc (~0, OutFptr) == EOF) {
      fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n");
      Status = STATUS_ERROR;
      goto BailOut;
    }
    TotalSize--;
  }

BailOut:
  if (InFptr != NULL) {
    fclose (InFptr);
  }  
  // 
  // Free up our buffers
  //
  if (Buffer != NULL) {
    free (Buffer);
  }
  if (CompressedBuffer != NULL) {
    free (CompressedBuffer);
  }
  //
  // Print the file name if errors occurred
  //
  if (Status != STATUS_SUCCESS) {
    fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName);
  }
  return Status;
}

static
int
CheckPE32File ( 
  FILE      *Fptr,
  UINT16    *MachineType,
  UINT16    *SubSystem
  )
{
/*++

Routine Description:
  
  Given a file pointer to a supposed PE32 image file, verify that it is indeed a
  PE32 image file, and then return the machine type in the supplied pointer.

Arguments:

  Fptr          File pointer to the already-opened PE32 file
  MachineType   Location to stuff the machine type of the PE32 file. This is needed
                because the image may be Itanium-based, IA32, or EBC.

Returns:

  0             success
  non-zero      otherwise

--*/
  EFI_IMAGE_DOS_HEADER        DosHeader;
  EFI_IMAGE_FILE_HEADER       FileHdr;
  EFI_IMAGE_OPTIONAL_HEADER   OptionalHdr;
  UINT32                      PESig;

  //
  // Position to the start of the file
  //
  fseek (Fptr, 0, SEEK_SET);

  //
  // Read the DOS header
  //
  if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) {
    fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n");
    return STATUS_ERROR;
  }
  //
  // Check the magic number (0x5A4D)
  //
  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
    fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n");
    return STATUS_ERROR;
  }
  //
  // Position into the file and check the PE signature
  //
  fseek(Fptr, (long)DosHeader.e_lfanew, SEEK_SET);
  if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) {
    fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n");
    return STATUS_ERROR;
  }
  //
  // Check the PE signature in the header "PE\0\0"
  //
  if (PESig != EFI_IMAGE_NT_SIGNATURE) {
    fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n");
    return STATUS_ERROR;
  }
  //
  // Read the file header and stuff their MachineType
  //
  if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) {
    fprintf (stdout, "ERROR: Failed to read PE file header from input file\n");
    return STATUS_ERROR;
  }
  memcpy ((char *)MachineType, &FileHdr.Machine, 2);   

  //
  // Read the optional header so we can get the subsystem
  //
  if (fread (&OptionalHdr, sizeof(OptionalHdr), 1, Fptr) != 1) {
    fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n");
    return STATUS_ERROR;
  }
  *SubSystem = OptionalHdr.Subsystem;
  if (mOptions.Verbose) {
    fprintf (stdout, "  Got subsystem = 0x%X from image\n", (int)*SubSystem);
  }
  //
  // Good to go
  //
  return STATUS_SUCCESS;
}

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

Routine Description:
  
  Given the Argc/Argv program arguments, and a pointer to an options structure,
  parse the command-line options and check their validity.


Arguments:

  Argc            - standard C main() argument count
  Argv            - standard C main() argument list
  Options         - pointer to a structure to store the options in

Returns:

  STATUS_SUCCESS    success
  non-zero          otherwise

--*/
{
  FILE_LIST   *FileList, *PrevFileList;
  UINT32      FileFlags;
  UINT32      ClassCode;
  UINT32      CodeRevision;

  FileFlags = 0;

  //
  // Clear out the options
  //
  memset ((char *)Options, 0, sizeof (OPTIONS));

  //
  // To avoid compile warnings
  //
  FileList = PrevFileList = NULL;

  ClassCode = 0;
  CodeRevision = 0;
  //
  // Skip over the program name
  //
  Argc--;
  Argv++;

  //
  // If no arguments, assume they want usage info
  //
  if (Argc == 0) {
    Usage();
    return STATUS_ERROR;
  }

⌨️ 快捷键说明

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