2
* Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation; either version 2 of the
7
* License, or any later version.
9
* This program is distributed in the hope that it will be useful, but
10
* WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20
#define FILE_LICENCE(...) extern void __file_licence ( void )
31
#include <ipxe/efi/Uefi.h>
32
#include <ipxe/efi/IndustryStandard/PeImage.h>
34
#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
36
/** Command-line options */
40
/** EFI fat binary file header */
41
struct efifatbin_file_header {
46
} __attribute__ (( packed ));
48
/** EFI fat binary signature */
49
#define EFIFATBIN_SIGNATURE 0x0ef1fab9
51
/** EFI fat binary image header */
52
struct efifatbin_image_header {
61
} __attribute__ (( packed ));
63
/** EFI fat binary default flags */
64
#define EFIFATBIN_FLAGS 0x0000000300000007ULL
66
/** EFI fat binary 64-bit flag */
67
#define EFIFATBIN_64BIT 0x0000000001000000ULL
72
* @v len Length of memory to allocate
73
* @ret ptr Pointer to allocated memory
75
static void * xmalloc ( size_t len ) {
80
eprintf ( "Could not allocate %zd bytes\n", len );
88
* Generate EFI fat binary
90
* @v count Number of input files
91
* @v infile_names Input filenames
92
* @v outfile_name Output filename
94
static void make_efifatbin ( unsigned int count, char **infile_names,
95
const char *outfile_name ) {
98
struct stat stat[count];
100
struct efifatbin_file_header file_header;
101
struct efifatbin_image_header header[count];
103
EFI_IMAGE_DOS_HEADER *dos;
105
EFI_IMAGE_NT_HEADERS32 nt32;
106
EFI_IMAGE_NT_HEADERS64 nt64;
110
/* Generate file header */
111
file_header.signature = EFIFATBIN_SIGNATURE;
112
file_header.count = count;
113
offset = ( sizeof ( file_header ) + sizeof ( header ) );
115
/* Process input files */
116
for ( i = 0 ; i < count ; i++ ) {
118
/* Open input file */
119
infile[i] = fopen ( infile_names[i], "r" );
121
eprintf ( "Could not open %s for reading: %s\n",
122
infile_names[i], strerror ( errno ) );
126
/* Determine PE file size */
127
if ( fstat ( fileno ( infile[i] ), &stat[i] ) != 0 ) {
128
eprintf ( "Could not stat %s: %s\n",
129
infile_names[i], strerror ( errno ) );
133
/* Allocate buffer and read in PE file */
134
buf[i] = xmalloc ( stat[i].st_size );
135
if ( fread ( buf[i], stat[i].st_size, 1, infile[i] ) != 1 ) {
136
eprintf ( "Could not read %s: %s\n",
137
infile_names[i], strerror ( errno ) );
141
/* Close input file */
142
fclose ( infile[i] );
144
/* Generate image header */
145
header[i].flags = EFIFATBIN_FLAGS;
146
header[i].offset = offset;
147
header[i].len = stat[i].st_size;
150
/* Determine architecture */
152
nt = ( buf[i] + dos->e_lfanew );
153
if ( nt->nt32.FileHeader.Machine == EFI_IMAGE_MACHINE_X64 )
154
header[i].flags |= EFIFATBIN_64BIT;
156
/* Allow space for this image */
157
offset += stat[i].st_size;
160
/* Open output file */
161
outfile = fopen ( outfile_name, "w" );
163
eprintf ( "Could not open %s for writing: %s\n",
164
outfile_name, strerror ( errno ) );
168
/* Write fat binary header */
169
if ( fwrite ( &file_header, sizeof ( file_header ), 1, outfile ) != 1 ){
170
eprintf ( "Could not write %s: %s\n",
171
outfile_name, strerror ( errno ) );
174
for ( i = 0 ; i < count ; i++ ) {
175
if ( fwrite ( &header[i], sizeof ( header[i] ), 1,
177
eprintf ( "Could not write %s: %s\n",
178
outfile_name, strerror ( errno ) );
184
for ( i = 0 ; i < count ; i++ ) {
185
if ( fwrite ( buf[i], stat[i].st_size, 1, outfile ) != 1 ) {
186
eprintf ( "Could not write %s: %s\n",
187
outfile_name, strerror ( errno ) );
192
/* Close output file */
199
* @v program_name Program name
201
static void print_help ( const char *program_name ) {
202
eprintf ( "Syntax: %s infile [infile...] outfile\n", program_name );
206
* Parse command-line options
208
* @v argc Argument count
209
* @v argv Argument list
210
* @v opts Options structure to populate
212
static int parse_options ( const int argc, char **argv,
213
struct options *opts __attribute__ (( unused )) ) {
217
int option_index = 0;
218
static struct option long_options[] = {
219
{ "help", 0, NULL, 'h' },
223
if ( ( c = getopt_long ( argc, argv, "h",
225
&option_index ) ) == -1 ) {
231
print_help ( argv[0] );
241
int main ( int argc, char **argv ) {
247
/* Parse command-line arguments */
248
memset ( &opts, 0, sizeof ( opts ) );
249
infile_index = parse_options ( argc, argv, &opts );
250
outfile_index = ( argc - 1 );
251
count = ( outfile_index - infile_index );
253
print_help ( argv[0] );
257
/* Generate fat binary */
258
make_efifatbin ( count, &argv[infile_index], argv[outfile_index] );