~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/util/efifatbin.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2014 Michael Brown <mbrown@fensystems.co.uk>.
 
3
 *
 
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.
 
8
 *
 
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.
 
13
 *
 
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
 
17
 * 02110-1301, USA.
 
18
 */
 
19
 
 
20
#define FILE_LICENCE(...) extern void __file_licence ( void )
 
21
#include <stdint.h>
 
22
#include <stddef.h>
 
23
#include <stdlib.h>
 
24
#include <stdio.h>
 
25
#include <string.h>
 
26
#include <sys/stat.h>
 
27
#include <unistd.h>
 
28
#include <errno.h>
 
29
#include <assert.h>
 
30
#include <getopt.h>
 
31
#include <ipxe/efi/Uefi.h>
 
32
#include <ipxe/efi/IndustryStandard/PeImage.h>
 
33
 
 
34
#define eprintf(...) fprintf ( stderr, __VA_ARGS__ )
 
35
 
 
36
/** Command-line options */
 
37
struct options {
 
38
};
 
39
 
 
40
/** EFI fat binary file header */
 
41
struct efifatbin_file_header {
 
42
        /** Signature */
 
43
        uint32_t signature;
 
44
        /** Count */
 
45
        uint32_t count;
 
46
} __attribute__ (( packed ));
 
47
 
 
48
/** EFI fat binary signature */
 
49
#define EFIFATBIN_SIGNATURE 0x0ef1fab9
 
50
 
 
51
/** EFI fat binary image header */
 
52
struct efifatbin_image_header {
 
53
        /** Flags */
 
54
        uint64_t flags;
 
55
        /** Offset */
 
56
        uint32_t offset;
 
57
        /** Length */
 
58
        uint32_t len;
 
59
        /** Padding */
 
60
        uint32_t pad;
 
61
} __attribute__ (( packed ));
 
62
 
 
63
/** EFI fat binary default flags */
 
64
#define EFIFATBIN_FLAGS 0x0000000300000007ULL
 
65
 
 
66
/** EFI fat binary 64-bit flag */
 
67
#define EFIFATBIN_64BIT 0x0000000001000000ULL
 
68
 
 
69
/**
 
70
 * Allocate memory
 
71
 *
 
72
 * @v len               Length of memory to allocate
 
73
 * @ret ptr             Pointer to allocated memory
 
74
 */
 
75
static void * xmalloc ( size_t len ) {
 
76
        void *ptr;
 
77
 
 
78
        ptr = malloc ( len );
 
79
        if ( ! ptr ) {
 
80
                eprintf ( "Could not allocate %zd bytes\n", len );
 
81
                exit ( 1 );
 
82
        }
 
83
 
 
84
        return ptr;
 
85
}
 
86
 
 
87
/**
 
88
 * Generate EFI fat binary
 
89
 *
 
90
 * @v count             Number of input files
 
91
 * @v infile_names      Input filenames
 
92
 * @v outfile_name      Output filename
 
93
 */
 
94
static void make_efifatbin ( unsigned int count, char **infile_names,
 
95
                             const char *outfile_name ) {
 
96
        FILE *infile[count];
 
97
        FILE *outfile;
 
98
        struct stat stat[count];
 
99
        void *buf[count];
 
100
        struct efifatbin_file_header file_header;
 
101
        struct efifatbin_image_header header[count];
 
102
        size_t offset;
 
103
        EFI_IMAGE_DOS_HEADER *dos;
 
104
        union {
 
105
                EFI_IMAGE_NT_HEADERS32 nt32;
 
106
                EFI_IMAGE_NT_HEADERS64 nt64;
 
107
        } *nt;
 
108
        unsigned int i;
 
109
 
 
110
        /* Generate file header */
 
111
        file_header.signature = EFIFATBIN_SIGNATURE;
 
112
        file_header.count = count;
 
113
        offset = ( sizeof ( file_header ) + sizeof ( header ) );
 
114
 
 
115
        /* Process input files */
 
116
        for ( i = 0 ; i < count ; i++ ) {
 
117
 
 
118
                /* Open input file */
 
119
                infile[i] = fopen ( infile_names[i], "r" );
 
120
                if ( ! infile[i] ) {
 
121
                        eprintf ( "Could not open %s for reading: %s\n",
 
122
                                  infile_names[i], strerror ( errno ) );
 
123
                        exit ( 1 );
 
124
                }
 
125
 
 
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 ) );
 
130
                        exit ( 1 );
 
131
                }
 
132
 
 
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 ) );
 
138
                        exit ( 1 );
 
139
                }
 
140
 
 
141
                /* Close input file */
 
142
                fclose ( infile[i] );
 
143
 
 
144
                /* Generate image header */
 
145
                header[i].flags = EFIFATBIN_FLAGS;
 
146
                header[i].offset = offset;
 
147
                header[i].len = stat[i].st_size;
 
148
                header[i].pad = 0;
 
149
 
 
150
                /* Determine architecture */
 
151
                dos = buf[i];
 
152
                nt = ( buf[i] + dos->e_lfanew );
 
153
                if ( nt->nt32.FileHeader.Machine == EFI_IMAGE_MACHINE_X64 )
 
154
                        header[i].flags |= EFIFATBIN_64BIT;
 
155
 
 
156
                /* Allow space for this image */
 
157
                offset += stat[i].st_size;
 
158
        }
 
159
 
 
160
        /* Open output file */
 
161
        outfile = fopen ( outfile_name, "w" );
 
162
        if ( ! outfile ) {
 
163
                eprintf ( "Could not open %s for writing: %s\n",
 
164
                          outfile_name, strerror ( errno ) );
 
165
                exit ( 1 );
 
166
        }
 
167
 
 
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 ) );
 
172
                exit ( 1 );
 
173
        }
 
174
        for ( i = 0 ; i < count ; i++ ) {
 
175
                if ( fwrite ( &header[i], sizeof ( header[i] ), 1,
 
176
                              outfile ) != 1 ) {
 
177
                        eprintf ( "Could not write %s: %s\n",
 
178
                                  outfile_name, strerror ( errno ) );
 
179
                        exit ( 1 );
 
180
                }
 
181
        }
 
182
 
 
183
        /* Write images */
 
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 ) );
 
188
                        exit ( 1 );
 
189
                }
 
190
        }
 
191
 
 
192
        /* Close output file */
 
193
        fclose ( outfile );
 
194
}
 
195
 
 
196
/**
 
197
 * Print help
 
198
 *
 
199
 * @v program_name      Program name
 
200
 */
 
201
static void print_help ( const char *program_name ) {
 
202
        eprintf ( "Syntax: %s infile [infile...] outfile\n", program_name );
 
203
}
 
204
 
 
205
/**
 
206
 * Parse command-line options
 
207
 *
 
208
 * @v argc              Argument count
 
209
 * @v argv              Argument list
 
210
 * @v opts              Options structure to populate
 
211
 */
 
212
static int parse_options ( const int argc, char **argv,
 
213
                           struct options *opts __attribute__ (( unused )) ) {
 
214
        int c;
 
215
 
 
216
        while (1) {
 
217
                int option_index = 0;
 
218
                static struct option long_options[] = {
 
219
                        { "help", 0, NULL, 'h' },
 
220
                        { 0, 0, 0, 0 }
 
221
                };
 
222
 
 
223
                if ( ( c = getopt_long ( argc, argv, "h",
 
224
                                         long_options,
 
225
                                         &option_index ) ) == -1 ) {
 
226
                        break;
 
227
                }
 
228
 
 
229
                switch ( c ) {
 
230
                case 'h':
 
231
                        print_help ( argv[0] );
 
232
                        exit ( 0 );
 
233
                case '?':
 
234
                default:
 
235
                        exit ( 2 );
 
236
                }
 
237
        }
 
238
        return optind;
 
239
}
 
240
 
 
241
int main ( int argc, char **argv ) {
 
242
        struct options opts;
 
243
        int infile_index;
 
244
        int outfile_index;
 
245
        int count;
 
246
 
 
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 );
 
252
        if ( count <= 0 ) {
 
253
                print_help ( argv[0] );
 
254
                exit ( 2 );
 
255
        }
 
256
 
 
257
        /* Generate fat binary */
 
258
        make_efifatbin ( count, &argv[infile_index], argv[outfile_index] );
 
259
 
 
260
        return 0;
 
261
}