2009-07-17 11:10:31 +02:00
/** @file
2010-05-18 07:04:32 +02:00
Copyright ( c ) 2006 - 2010 , Intel Corporation . All rights reserved . < BR >
This program and the accompanying materials
2009-07-17 11:10:31 +02:00
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 :
efildrimage . c
Abstract :
Creates and EFILDR image .
This tool combines several PE Image files together using following format denoted as EBNF :
FILE : = EFILDR_HEADER
EFILDR_IMAGE +
< PeImageFileContent > +
The order of EFILDR_IMAGE is same as the order of placing PeImageFileContent .
Revision History
* */
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include "ParseInf.h"
# include "CommonLib.h"
# include "EfiUtilityMsgs.h"
# define MAX_PE_IMAGES 63
# define FILE_TYPE_FIXED_LOADER 0
# define FILE_TYPE_RELOCATABLE_PE_IMAGE 1
typedef struct {
UINT32 CheckSum ;
UINT32 Offset ;
UINT32 Length ;
UINT8 FileName [ 52 ] ;
} EFILDR_IMAGE ;
typedef struct {
UINT32 Signature ;
UINT32 HeaderCheckSum ;
UINT32 FileLength ;
UINT32 NumberOfImages ;
} EFILDR_HEADER ;
//
// Utility Name
//
# define UTILITY_NAME "EfiLdrImage"
//
// Utility version information
//
# define UTILITY_MAJOR_VERSION 0
# define UTILITY_MINOR_VERSION 1
void
Version (
void
)
/*++
Routine Description :
Displays the standard utility information to SDTOUT
Arguments :
None
Returns :
None
- - */
{
2011-09-18 14:17:25 +02:00
printf ( " %s v%d.%d %s -Utility to break a file into two pieces at the request offset. \n " , UTILITY_NAME , UTILITY_MAJOR_VERSION , UTILITY_MINOR_VERSION , __BUILD_VERSION ) ;
2010-03-01 00:39:39 +01:00
printf ( " Copyright (c) 1999-2010 Intel Corporation. All rights reserved. \n " ) ;
2009-07-17 11:10:31 +02:00
}
VOID
Usage (
VOID
)
{
printf ( " Usage: EfiLdrImage -o OutImage LoaderImage PeImage1 PeImage2 ... PeImageN \n " ) ;
exit ( 1 ) ;
}
EFI_STATUS
CountVerboseLevel (
IN CONST CHAR8 * VerboseLevelString ,
IN CONST UINT64 Length ,
OUT UINT64 * ReturnValue
)
{
UINT64 i = 0 ;
for ( ; i < Length ; + + i ) {
if ( VerboseLevelString [ i ] ! = ' v ' & & VerboseLevelString [ i ] ! = ' V ' ) {
return EFI_ABORTED ;
}
+ + ( * ReturnValue ) ;
}
return EFI_SUCCESS ;
}
UINT64
FCopyFile (
FILE * in ,
FILE * out
)
/*++
Routine Description :
Write all the content of input file to output file .
Arguments :
in - input file pointer
out - output file pointer
Return :
UINT64 : file size of input file
- - */
{
2009-09-11 05:14:43 +02:00
UINT32 filesize , offset , length ;
2009-07-17 11:10:31 +02:00
CHAR8 Buffer [ 8 * 1024 ] ;
fseek ( in , 0 , SEEK_END ) ;
filesize = ftell ( in ) ;
fseek ( in , 0 , SEEK_SET ) ;
offset = 0 ;
while ( offset < filesize ) {
length = sizeof ( Buffer ) ;
if ( filesize - offset < length ) {
length = filesize - offset ;
}
fread ( Buffer , length , 1 , in ) ;
fwrite ( Buffer , length , 1 , out ) ;
offset + = length ;
}
return filesize ;
}
int
main (
int argc ,
char * argv [ ]
)
/*++
Routine Description :
Arguments :
Returns :
- - */
{
UINT64 i ;
UINT64 filesize ;
FILE * fpIn , * fpOut ;
EFILDR_HEADER EfiLdrHeader ;
EFILDR_IMAGE EfiLdrImage [ MAX_PE_IMAGES ] ;
CHAR8 * OutputFileName = NULL ;
CHAR8 * InputFileNames [ MAX_PE_IMAGES + 1 ] ;
UINT8 InputFileCount = 0 ;
BOOLEAN QuietFlag = FALSE ;
UINT64 DebugLevel = 0 ;
UINT64 VerboseLevel = 0 ;
EFI_STATUS Status = EFI_SUCCESS ;
SetUtilityName ( UTILITY_NAME ) ;
if ( argc = = 1 ) {
Usage ( ) ;
return STATUS_ERROR ;
}
argc - - ;
argv + + ;
if ( ( stricmp ( argv [ 0 ] , " -h " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --help " ) = = 0 ) ) {
Usage ( ) ;
return STATUS_SUCCESS ;
}
if ( stricmp ( argv [ 0 ] , " --version " ) = = 0 ) {
Version ( ) ;
return STATUS_SUCCESS ;
}
while ( argc > 0 ) {
if ( ( stricmp ( argv [ 0 ] , " -o " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --output " ) = = 0 ) ) {
OutputFileName = argv [ 1 ] ;
if ( OutputFileName = = NULL ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " Output file can't be null " ) ;
return STATUS_ERROR ;
}
argc - = 2 ;
argv + = 2 ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -q " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --quiet " ) = = 0 ) ) {
QuietFlag = TRUE ;
argc - - ;
argv + + ;
continue ;
}
if ( ( strlen ( argv [ 0 ] ) > = 2 & & argv [ 0 ] [ 0 ] = = ' - ' & & ( argv [ 0 ] [ 1 ] = = ' v ' | | argv [ 0 ] [ 1 ] = = ' V ' ) ) | | ( stricmp ( argv [ 0 ] , " --verbose " ) = = 0 ) ) {
VerboseLevel = 1 ;
if ( strlen ( argv [ 0 ] ) > 2 ) {
Status = CountVerboseLevel ( & argv [ 0 ] [ 2 ] , strlen ( argv [ 0 ] ) - 2 , & VerboseLevel ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , argv [ 0 ] ) ;
return STATUS_ERROR ;
}
}
argc - - ;
argv + + ;
continue ;
}
if ( ( stricmp ( argv [ 0 ] , " -d " ) = = 0 ) | | ( stricmp ( argv [ 0 ] , " --debug " ) = = 0 ) ) {
Status = AsciiStringToUint64 ( argv [ 1 ] , FALSE , & DebugLevel ) ;
if ( EFI_ERROR ( Status ) ) {
Error ( NULL , 0 , 1003 , " Invalid option value " , " %s = %s " , argv [ 0 ] , argv [ 1 ] ) ;
return STATUS_ERROR ;
}
argc - = 2 ;
argv + = 2 ;
continue ;
}
//
2009-09-11 05:14:43 +02:00
// Don't recognize the parameter, should be regarded as the input file name.
2009-07-17 11:10:31 +02:00
//
InputFileNames [ InputFileCount ] = argv [ 0 ] ;
InputFileCount + + ;
argc - - ;
argv + + ;
}
if ( InputFileCount = = 0 ) {
Error ( NULL , 0 , 1001 , " Missing option " , " No input file " ) ;
return STATUS_ERROR ;
}
//
// Open output file for write
//
if ( OutputFileName = = NULL ) {
Error ( NULL , 0 , 1001 , " Missing option " , " No output file " ) ;
return STATUS_ERROR ;
}
fpOut = fopen ( OutputFileName , " w+b " ) ;
if ( ! fpOut ) {
Error ( NULL , 0 , 0001 , " Could not open output file " , OutputFileName ) ;
return STATUS_ERROR ;
}
memset ( & EfiLdrHeader , 0 , sizeof ( EfiLdrHeader ) ) ;
memset ( & EfiLdrImage , 0 , sizeof ( EFILDR_IMAGE ) * ( InputFileCount ) ) ;
memcpy ( & EfiLdrHeader . Signature , " EFIL " , 4 ) ;
EfiLdrHeader . FileLength = sizeof ( EFILDR_HEADER ) + sizeof ( EFILDR_IMAGE ) * ( InputFileCount ) ;
//
// Skip the file header first
//
fseek ( fpOut , EfiLdrHeader . FileLength , SEEK_SET ) ;
//
// copy all the input files to the output file
//
for ( i = 0 ; i < InputFileCount ; i + + ) {
//
// Copy the content of PeImage file to output file
//
fpIn = fopen ( InputFileNames [ i ] , " rb " ) ;
if ( ! fpIn ) {
Error ( NULL , 0 , 0001 , " Could not open input file " , InputFileNames [ i ] ) ;
fclose ( fpOut ) ;
return STATUS_ERROR ;
}
filesize = FCopyFile ( fpIn , fpOut ) ;
fclose ( fpIn ) ;
//
// And in the same time update the EfiLdrHeader and EfiLdrImage array
//
EfiLdrImage [ i ] . Offset = EfiLdrHeader . FileLength ;
2009-09-11 05:14:43 +02:00
EfiLdrImage [ i ] . Length = ( UINT32 ) filesize ;
2009-07-17 11:10:31 +02:00
strncpy ( ( CHAR8 * ) EfiLdrImage [ i ] . FileName , InputFileNames [ i ] , sizeof ( EfiLdrImage [ i ] . FileName ) - 1 ) ;
2009-09-11 05:14:43 +02:00
EfiLdrHeader . FileLength + = ( UINT32 ) filesize ;
2009-07-17 11:10:31 +02:00
EfiLdrHeader . NumberOfImages + + ;
}
//
// Write the image header to the output file finally
//
fseek ( fpOut , 0 , SEEK_SET ) ;
fwrite ( & EfiLdrHeader , sizeof ( EFILDR_HEADER ) , 1 , fpOut ) ;
fwrite ( & EfiLdrImage , sizeof ( EFILDR_IMAGE ) * ( InputFileCount ) , 1 , fpOut ) ;
fclose ( fpOut ) ;
printf ( " Created %s \n " , OutputFileName ) ;
return 0 ;
}