source: bootcd/isolinux/syslinux-6.03/gpxe/src/util/zbin.c @ 26ffad7

Last change on this file since 26ffad7 was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 8.7 KB
Line 
1#include <stdio.h>
2#include <sys/stat.h>
3
4#define ENCODE
5#define VERBOSE
6#include "nrv2b.c"
7FILE *infile, *outfile;
8
9#define DEBUG 0
10
11struct input_file {
12        void *buf;
13        size_t len;
14};
15
16struct output_file {
17        void *buf;
18        size_t len;
19        size_t max_len;
20};
21
22struct zinfo_common {
23        char type[4];
24        char pad[12];
25};
26
27struct zinfo_copy {
28        char type[4];
29        uint32_t offset;
30        uint32_t len;
31        uint32_t align;
32};
33
34struct zinfo_pack {
35        char type[4];
36        uint32_t offset;
37        uint32_t len;
38        uint32_t align;
39};
40
41struct zinfo_add {
42        char type[4];
43        uint32_t offset;
44        uint32_t divisor;
45        uint32_t pad;
46};
47
48union zinfo_record {
49        struct zinfo_common common;
50        struct zinfo_copy copy;
51        struct zinfo_pack pack;
52        struct zinfo_add add;
53};
54
55struct zinfo_file {
56        union zinfo_record *zinfo;
57        unsigned int num_entries;
58};
59
60static unsigned long align ( unsigned long value, unsigned long align ) {
61        return ( ( value + align - 1 ) & ~( align - 1 ) );
62}
63
64static int read_file ( const char *filename, void **buf, size_t *len ) {
65        FILE *file;
66        struct stat stat;
67
68        file = fopen ( filename, "r" );
69        if ( ! file ) {
70                fprintf ( stderr, "Could not open %s: %s\n", filename,
71                          strerror ( errno ) );
72                goto err;
73        }
74
75        if ( fstat ( fileno ( file ), &stat ) < 0 ) {
76                fprintf ( stderr, "Could not stat %s: %s\n", filename,
77                          strerror ( errno ) );
78                goto err;
79        }
80
81        *len = stat.st_size;
82        *buf = malloc ( *len );
83        if ( ! *buf ) {
84                fprintf ( stderr, "Could not malloc() %zd bytes for %s: %s\n",
85                          *len, filename, strerror ( errno ) );
86                goto err;
87        }
88
89        if ( fread ( *buf, 1, *len, file ) != *len ) {
90                fprintf ( stderr, "Could not read %zd bytes from %s: %s\n",
91                          *len, filename, strerror ( errno ) );
92                goto err;
93        }
94
95        fclose ( file );
96        return 0;
97
98 err:
99        if ( file )
100                fclose ( file );
101        return -1;
102}
103
104static int read_input_file ( const char *filename,
105                             struct input_file *input ) {
106        return read_file ( filename, &input->buf, &input->len );
107}
108
109static int read_zinfo_file ( const char *filename,
110                             struct zinfo_file *zinfo ) {
111        void *buf;
112        size_t len;
113
114        if ( read_file ( filename, &buf, &len ) < 0 )
115                return -1;
116
117        if ( ( len % sizeof ( *(zinfo->zinfo) ) ) != 0 ) {
118                fprintf ( stderr, ".zinfo file %s has invalid length %zd\n",
119                          filename, len );
120                return -1;
121        }
122
123        zinfo->zinfo = buf;
124        zinfo->num_entries = ( len / sizeof ( *(zinfo->zinfo) ) );
125        return 0;
126}
127
128static int alloc_output_file ( size_t max_len, struct output_file *output ) {
129        output->len = 0;
130        output->max_len = ( max_len );
131        output->buf = malloc ( max_len );
132        if ( ! output->buf ) {
133                fprintf ( stderr, "Could not allocate %zd bytes for output\n",
134                          max_len );
135                return -1;
136        }
137        memset ( output->buf, 0xff, sizeof ( output->buf ) );
138        return 0;
139}
140
141static int process_zinfo_copy ( struct input_file *input,
142                                struct output_file *output,
143                                union zinfo_record *zinfo ) {
144        struct zinfo_copy *copy = &zinfo->copy;
145        size_t offset = copy->offset;
146        size_t len = copy->len;
147
148        if ( ( offset + len ) > input->len ) {
149                fprintf ( stderr, "Input buffer overrun on copy\n" );
150                return -1;
151        }
152
153        output->len = align ( output->len, copy->align );
154        if ( ( output->len + len ) > output->max_len ) {
155                fprintf ( stderr, "Output buffer overrun on copy\n" );
156                return -1;
157        }
158
159        if ( DEBUG ) {
160                fprintf ( stderr, "COPY [%#zx,%#zx) to [%#zx,%#zx)\n",
161                          offset, ( offset + len ), output->len,
162                          ( output->len + len ) );
163        }
164
165        memcpy ( ( output->buf + output->len ),
166                 ( input->buf + offset ), len );
167        output->len += len;
168        return 0;
169}
170
171static int process_zinfo_pack ( struct input_file *input,
172                                struct output_file *output,
173                                union zinfo_record *zinfo ) {
174        struct zinfo_pack *pack = &zinfo->pack;
175        size_t offset = pack->offset;
176        size_t len = pack->len;
177        unsigned long packed_len;
178
179        if ( ( offset + len ) > input->len ) {
180                fprintf ( stderr, "Input buffer overrun on pack\n" );
181                return -1;
182        }
183
184        output->len = align ( output->len, pack->align );
185        if ( output->len > output->max_len ) {
186                fprintf ( stderr, "Output buffer overrun on pack\n" );
187                return -1;
188        }
189
190        if ( ucl_nrv2b_99_compress ( ( input->buf + offset ), len,
191                                     ( output->buf + output->len ),
192                                     &packed_len, 0 ) != UCL_E_OK ) {
193                fprintf ( stderr, "Compression failure\n" );
194                return -1;
195        }
196
197        if ( DEBUG ) {
198                fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n",
199                          offset, ( offset + len ), output->len,
200                          ( size_t )( output->len + packed_len ) );
201        }
202
203        output->len += packed_len;
204        if ( output->len > output->max_len ) {
205                fprintf ( stderr, "Output buffer overrun on pack\n" );
206                return -1;
207        }
208
209        return 0;
210}
211
212static int process_zinfo_add ( struct input_file *input,
213                               struct output_file *output,
214                               struct zinfo_add *add,
215                               size_t datasize ) {
216        size_t offset = add->offset;
217        void *target;
218        signed long addend;
219        unsigned long size;
220        signed long val;
221        unsigned long mask;
222
223        if ( ( offset + datasize ) > output->len ) {
224                fprintf ( stderr, "Add at %#zx outside output buffer\n",
225                          offset );
226                return -1;
227        }
228
229        target = ( output->buf + offset );
230        size = ( align ( output->len, add->divisor ) / add->divisor );
231
232        switch ( datasize ) {
233        case 1:
234                addend = *( ( int8_t * ) target );
235                break;
236        case 2:
237                addend = *( ( int16_t * ) target );
238                break;
239        case 4:
240                addend = *( ( int32_t * ) target );
241                break;
242        default:
243                fprintf ( stderr, "Unsupported add datasize %zd\n",
244                          datasize );
245                return -1;
246        }
247
248        val = size + addend;
249
250        /* The result of 1UL << ( 8 * sizeof(unsigned long) ) is undefined */
251        mask = ( ( datasize < sizeof ( mask ) ) ?
252                 ( ( 1UL << ( 8 * datasize ) ) - 1 ) : ~0UL );
253
254        if ( val < 0 ) {
255                fprintf ( stderr, "Add %s%#x+%#lx at %#zx %sflows field\n",
256                          ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
257                          offset, ( ( addend < 0 ) ? "under" : "over" ) );
258                return -1;
259        }
260
261        if ( val & ~mask ) {
262                fprintf ( stderr, "Add %s%#x+%#lx at %#zx overflows %zd-byte "
263                          "field (%d bytes too big)\n",
264                          ( ( addend < 0 ) ? "-" : "" ), abs ( addend ), size,
265                          offset, datasize,
266                          ( int )( ( val - mask - 1 ) * add->divisor ) );
267                return -1;
268        }
269
270        switch ( datasize ) {
271        case 1:
272                *( ( uint8_t * ) target ) = val;
273                break;
274        case 2:
275                *( ( uint16_t * ) target ) = val;
276                break;
277        case 4:
278                *( ( uint32_t * ) target ) = val;
279                break;
280        }
281
282        if ( DEBUG ) {
283                fprintf ( stderr, "ADDx [%#zx,%#zx) (%s%#x+(%#zx/%#x)) = "
284                          "%#lx\n", offset, ( offset + datasize ),
285                          ( ( addend < 0 ) ? "-" : "" ), abs ( addend ),
286                          output->len, add->divisor, val );
287        }
288
289        return 0;
290}
291
292static int process_zinfo_addb ( struct input_file *input,
293                                struct output_file *output,
294                                union zinfo_record *zinfo ) {
295        return process_zinfo_add ( input, output, &zinfo->add, 1 );
296}
297
298static int process_zinfo_addw ( struct input_file *input,
299                                struct output_file *output,
300                                union zinfo_record *zinfo ) {
301        return process_zinfo_add ( input, output, &zinfo->add, 2 );
302}
303
304static int process_zinfo_addl ( struct input_file *input,
305                                struct output_file *output,
306                                union zinfo_record *zinfo ) {
307        return process_zinfo_add ( input, output, &zinfo->add, 4 );
308}
309
310struct zinfo_processor {
311        char *type;
312        int ( * process ) ( struct input_file *input,
313                            struct output_file *output,
314                            union zinfo_record *zinfo );
315};
316
317static struct zinfo_processor zinfo_processors[] = {
318        { "COPY", process_zinfo_copy },
319        { "PACK", process_zinfo_pack },
320        { "ADDB", process_zinfo_addb },
321        { "ADDW", process_zinfo_addw },
322        { "ADDL", process_zinfo_addl },
323};
324
325static int process_zinfo ( struct input_file *input,
326                           struct output_file *output,
327                           union zinfo_record *zinfo ) {
328        struct zinfo_common *common = &zinfo->common;
329        struct zinfo_processor *processor;
330        char type[ sizeof ( common->type ) + 1 ] = "";
331        unsigned int i;
332
333        strncat ( type, common->type, sizeof ( type ) - 1 );
334        for ( i = 0 ; i < ( sizeof ( zinfo_processors ) /
335                            sizeof ( zinfo_processors[0] ) ) ; i++ ) {
336                processor = &zinfo_processors[i];
337                if ( strcmp ( processor->type, type ) == 0 )
338                        return processor->process ( input, output, zinfo );
339        }
340
341        fprintf ( stderr, "Unknown zinfo record type \"%s\"\n", &type[0] );
342        return -1;
343}
344
345static int write_output_file ( struct output_file *output ) {
346        if ( fwrite ( output->buf, 1, output->len, stdout ) != output->len ) {
347                fprintf ( stderr, "Could not write %zd bytes of output: %s\n",
348                          output->len, strerror ( errno ) );
349                return -1;
350        }
351        return 0;
352}
353
354int main ( int argc, char **argv ) {
355        struct input_file input;
356        struct output_file output;
357        struct zinfo_file zinfo;
358        unsigned int i;
359
360        if ( argc != 3 ) {
361                fprintf ( stderr, "Syntax: %s file.bin file.zinfo "
362                          "> file.zbin\n", argv[0] );
363                exit ( 1 );
364        }
365
366        if ( read_input_file ( argv[1], &input ) < 0 )
367                exit ( 1 );
368        if ( read_zinfo_file ( argv[2], &zinfo ) < 0 )
369                exit ( 1 );
370        if ( alloc_output_file ( ( input.len * 4 ), &output ) < 0 )
371                exit ( 1 );
372
373        for ( i = 0 ; i < zinfo.num_entries ; i++ ) {
374                if ( process_zinfo ( &input, &output,
375                                     &zinfo.zinfo[i] ) < 0 )
376                        exit ( 1 );
377        }
378
379        if ( write_output_file ( &output ) < 0 )
380                exit ( 1 );
381
382        return 0;
383}
Note: See TracBrowser for help on using the repository browser.