git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2210 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			372 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			372 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c)  1999-2006 Intel Corporation. All rights reserved
 | 
						|
This program and the accompanying materials are licensed and made available 
 | 
						|
under the terms and conditions of the BSD License which accompanies this 
 | 
						|
distribution.  The full text of the license may be found at
 | 
						|
http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
    SecFixup.c
 | 
						|
 | 
						|
Abstract:
 | 
						|
 | 
						|
    This utility is part of build process for IA32 SEC FFS file.
 | 
						|
    
 | 
						|
    It fixup the reset vector data. The reset vector data binary file
 | 
						|
    will be wrapped as a RAW section and be located immediately after
 | 
						|
    the PE/TE section.
 | 
						|
 | 
						|
    The SEC EXE file can be either PE or TE file.
 | 
						|
    
 | 
						|
--*/
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
#include <Common/UefiBaseTypes.h>
 | 
						|
#include <Common/EfiImage.h>
 | 
						|
#include <Common/FirmwareVolumeImageFormat.h>
 | 
						|
 | 
						|
#include "EfiUtilityMsgs.c"
 | 
						|
#include "SecFixup.h"
 | 
						|
 | 
						|
VOID
 | 
						|
Version (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Displays the standard utility information to SDTOUT
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  printf ("%s v%d.%d -Tiano IA32 SEC Fixup Utility.\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
 | 
						|
  printf ("Copyright (c) 1999-2007 Intel Corporation. All rights reserved.\n");
 | 
						|
}
 | 
						|
 | 
						|
VOID
 | 
						|
Usage (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Displays the utility usage syntax to STDOUT
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  Version();
 | 
						|
  
 | 
						|
  printf ("\nUsage: %s SecExeFile ResetVectorDataFile OutputFile\n", UTILITY_NAME);
 | 
						|
  printf ("  Where:\n");
 | 
						|
  printf ("     SecExeFile           - Name of the IA32 SEC EXE file.\n");
 | 
						|
  printf ("     ResetVectorDataFile  - Name of the reset vector data binary file.\n");
 | 
						|
  printf ("     OutputFileName       - Name of the output file.\n");
 | 
						|
}
 | 
						|
 | 
						|
STATUS
 | 
						|
main (
 | 
						|
  IN INTN   argc,
 | 
						|
  IN CHAR8  **argv
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Main function.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  argc - Number of command line parameters.
 | 
						|
  argv - Array of pointers to parameter strings.
 | 
						|
 | 
						|
Returns:
 | 
						|
  STATUS_SUCCESS - Utility exits successfully.
 | 
						|
  STATUS_ERROR   - Some error occurred during execution.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  FILE    *FpIn;
 | 
						|
 | 
						|
  FILE    *FpOut;
 | 
						|
  UINT32  AddressOfEntryPoint;
 | 
						|
  INT32   DestRel;
 | 
						|
  STATUS  Status;
 | 
						|
  UINT32  SecFileSize;
 | 
						|
 | 
						|
  SetUtilityName (UTILITY_NAME);
 | 
						|
 | 
						|
  if (argc == 1) {
 | 
						|
    Usage();
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
    
 | 
						|
  if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0) ||
 | 
						|
      (strcmp(argv[1], "-?") == 0) || (strcmp(argv[1], "/?") == 0)) {
 | 
						|
    Usage();
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if ((strcmp(argv[1], "-V") == 0) || (strcmp(argv[1], "--version") == 0)) {
 | 
						|
    Version();
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Verify the correct number of arguments
 | 
						|
  //
 | 
						|
  if (argc != MAX_ARGS) {
 | 
						|
    Error (NULL, 0, 0, "invalid number of input parameters specified", NULL);
 | 
						|
    Usage ();
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Open the SEC exe file
 | 
						|
  //
 | 
						|
  if ((FpIn = fopen (argv[1], "rb")) == NULL) {
 | 
						|
    Error (NULL, 0, 0, "Unable to open file", argv[1]);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the entry point of the EXE file
 | 
						|
  //
 | 
						|
  Status = GetEntryPoint (FpIn, &AddressOfEntryPoint);
 | 
						|
  if (Status != STATUS_SUCCESS) {
 | 
						|
    fclose (FpIn);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the SEC file size
 | 
						|
  //
 | 
						|
  fseek (FpIn, 0, SEEK_END);
 | 
						|
  SecFileSize = ftell (FpIn);
 | 
						|
 | 
						|
  //
 | 
						|
  // Close the SEC file
 | 
						|
  //
 | 
						|
  fclose (FpIn);
 | 
						|
 | 
						|
  //
 | 
						|
  // Open the reset vector data file
 | 
						|
  //
 | 
						|
  if ((FpIn = fopen (argv[2], "rb")) == NULL) {
 | 
						|
    Error (NULL, 0, 0, "Unable to open file", argv[2]);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Open the output file
 | 
						|
  //
 | 
						|
  if ((FpOut = fopen (argv[3], "w+b")) == NULL) {
 | 
						|
    Error (NULL, 0, 0, "Unable to open file", argv[3]);
 | 
						|
    fclose (FpIn);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Copy the input file to the output file
 | 
						|
  //
 | 
						|
  if (CopyFile (FpIn, FpOut) != STATUS_SUCCESS) {
 | 
						|
    fclose (FpIn);
 | 
						|
    fclose (FpOut);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Close the reset vector data file
 | 
						|
  //
 | 
						|
  fclose (FpIn);
 | 
						|
 | 
						|
  //
 | 
						|
  // Fix the destination relative in the jmp instruction
 | 
						|
  // in the reset vector data structure
 | 
						|
  //
 | 
						|
  fseek (FpOut, -DEST_REL_OFFSET, SEEK_END);
 | 
						|
  DestRel = AddressOfEntryPoint - (SecFileSize + sizeof (EFI_COMMON_SECTION_HEADER) + (UINT32) (ftell (FpOut)) + 2);
 | 
						|
  if (DestRel <= -65536) {
 | 
						|
    Error (NULL, 0, 0, "The SEC EXE file size is too big", NULL);
 | 
						|
    fclose (FpOut);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (fwrite (&DestRel, sizeof (UINT16), 1, FpOut) != 1) {
 | 
						|
    Error (NULL, 0, 0, "Failed to write to the output file", NULL);
 | 
						|
    fclose (FpOut);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Close the output file
 | 
						|
  //
 | 
						|
  fclose (FpOut);
 | 
						|
 | 
						|
  return STATUS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
STATUS
 | 
						|
GetEntryPoint (
 | 
						|
  IN  FILE   *ExeFile,
 | 
						|
  OUT UINT32 *EntryPoint
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Get the address of the entry point of a PE/TE file.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  PeFile     - File pointer to the specified PE/TE file.
 | 
						|
  EntryPoint - Buffer for the address of the entry point to be returned.
 | 
						|
 | 
						|
Returns:
 | 
						|
  STATUS_SUCCESS - Function completed successfully.
 | 
						|
  STATUS_ERROR   - Error occured.
 | 
						|
 | 
						|
--*/
 | 
						|
// GC_TODO:    ExeFile - add argument and description to function comment
 | 
						|
{
 | 
						|
  EFI_IMAGE_DOS_HEADER    DosHeader;
 | 
						|
  EFI_IMAGE_NT_HEADERS32  NtHeader;
 | 
						|
  EFI_TE_IMAGE_HEADER     TeHeader;
 | 
						|
 | 
						|
  //
 | 
						|
  // Check if it is a TE file
 | 
						|
  //
 | 
						|
  fseek (ExeFile, 0, SEEK_SET);
 | 
						|
  //
 | 
						|
  // Attempt to read the TE header
 | 
						|
  //
 | 
						|
  if (fread (&TeHeader, sizeof (TeHeader), 1, ExeFile) == 1) {
 | 
						|
    if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
 | 
						|
      if (TeHeader.Machine != EFI_IMAGE_MACHINE_IA32) {
 | 
						|
        Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);
 | 
						|
        return STATUS_ERROR;
 | 
						|
      }
 | 
						|
 | 
						|
      *EntryPoint = TeHeader.AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader.StrippedSize;
 | 
						|
      return STATUS_SUCCESS;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check if it is a PE file
 | 
						|
  //
 | 
						|
  fseek (ExeFile, 0, SEEK_SET);
 | 
						|
  //
 | 
						|
  // Attempt to read the DOS header
 | 
						|
  //
 | 
						|
  if (fread (&DosHeader, sizeof (DosHeader), 1, ExeFile) != 1) {
 | 
						|
    goto InvalidFile;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the magic number
 | 
						|
  //
 | 
						|
  if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) {
 | 
						|
    goto InvalidFile;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Position into the file and read the NT PE header
 | 
						|
  //
 | 
						|
  fseek (ExeFile, (long) DosHeader.e_lfanew, SEEK_SET);
 | 
						|
  if (fread (&NtHeader, sizeof (NtHeader), 1, ExeFile) != 1) {
 | 
						|
    goto InvalidFile;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Check the PE signature in the header
 | 
						|
  //
 | 
						|
  if (NtHeader.Signature != EFI_IMAGE_NT_SIGNATURE) {
 | 
						|
    goto InvalidFile;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Make sure the PE file is PE32 for IA32
 | 
						|
  //
 | 
						|
  if (NtHeader.FileHeader.Machine != EFI_IMAGE_MACHINE_IA32 ||
 | 
						|
      NtHeader.OptionalHeader.Magic != EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
 | 
						|
      ) {
 | 
						|
    Error (NULL, 0, 0, "The SEC file is PE but is not PE32 for IA32", NULL);
 | 
						|
    return STATUS_ERROR;
 | 
						|
  }
 | 
						|
  //
 | 
						|
  // Get the entry point from the optional header
 | 
						|
  //
 | 
						|
  *EntryPoint = NtHeader.OptionalHeader.AddressOfEntryPoint;
 | 
						|
  return STATUS_SUCCESS;
 | 
						|
 | 
						|
InvalidFile:
 | 
						|
  Error (NULL, 0, 0, "The SEC file is neither PE nor TE file", NULL);
 | 
						|
  return STATUS_ERROR;
 | 
						|
}
 | 
						|
 | 
						|
STATUS
 | 
						|
CopyFile (
 | 
						|
  FILE    *FpIn,
 | 
						|
  FILE    *FpOut
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Copy file.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  FpIn  - File pointer to the source file.
 | 
						|
  FpOut - File pointer to the destination file.
 | 
						|
 | 
						|
Returns:
 | 
						|
  STATUS_SUCCESS - Function completed successfully.
 | 
						|
  STATUS_ERROR   - Error occured.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  INTN  FileSize;
 | 
						|
 | 
						|
  INTN  Offset;
 | 
						|
 | 
						|
  INTN  Length;
 | 
						|
  UINT8 Buffer[BUF_SIZE];
 | 
						|
 | 
						|
  fseek (FpIn, 0, SEEK_END);
 | 
						|
  FileSize = ftell (FpIn);
 | 
						|
 | 
						|
  fseek (FpIn, 0, SEEK_SET);
 | 
						|
  fseek (FpOut, 0, SEEK_SET);
 | 
						|
 | 
						|
  Offset = 0;
 | 
						|
  while (Offset < FileSize) {
 | 
						|
    Length = sizeof (Buffer);
 | 
						|
    if (FileSize - Offset < Length) {
 | 
						|
      Length = FileSize - Offset;
 | 
						|
    }
 | 
						|
 | 
						|
    if (fread (Buffer, Length, 1, FpIn) != 1 || fwrite (Buffer, Length, 1, FpOut) != 1) {
 | 
						|
      Error (NULL, 0, 0, "Copy file error", NULL);
 | 
						|
      return STATUS_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    Offset += Length;
 | 
						|
  }
 | 
						|
 | 
						|
  return STATUS_SUCCESS;
 | 
						|
}
 |