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

« back to all changes in this revision

Viewing changes to roms/SLOF/romfs/tools/build_ffs.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) 2004, 2008 IBM Corporation
 
3
 * All rights reserved.
 
4
 * This program and the accompanying materials
 
5
 * are made available under the terms of the BSD License
 
6
 * which accompanies this distribution, and is available at
 
7
 * http://www.opensource.org/licenses/bsd-license.php
 
8
 *
 
9
 * Contributors:
 
10
 *     IBM Corporation - initial implementation
 
11
 *****************************************************************************/
 
12
 
 
13
#include <stdint.h>
 
14
#include <stdio.h>
 
15
#include <stdlib.h>
 
16
#include <sys/types.h>
 
17
#include <sys/stat.h>
 
18
#include <fcntl.h>
 
19
#include <string.h>
 
20
#include <unistd.h>
 
21
 
 
22
#include <cfgparse.h>
 
23
#include <createcrc.h>
 
24
 
 
25
#define FFS_TARGET_HEADER_SIZE (4 * 8)
 
26
 
 
27
extern int verbose;
 
28
 
 
29
#define pad8_num(x) (((x) + 7) & ~7)
 
30
 
 
31
static int
 
32
file_exist(const char *name, int errdisp)
 
33
{
 
34
        struct stat fileinfo;
 
35
 
 
36
        memset((void *) &fileinfo, 0, sizeof(struct stat));
 
37
        if (stat(name, &fileinfo) != 0) {
 
38
                if (0 != errdisp) {
 
39
                        perror(name);
 
40
                }
 
41
                return 0;
 
42
        }
 
43
        if (S_ISREG(fileinfo.st_mode)) {
 
44
                return 1;
 
45
        }
 
46
        return 0;
 
47
}
 
48
 
 
49
static int
 
50
file_getsize(const char *name)
 
51
{
 
52
        int rc;
 
53
        struct stat fi;
 
54
 
 
55
        rc = stat(name, &fi);
 
56
        if (rc != 0)
 
57
                return -1;
 
58
        return fi.st_size;
 
59
}
 
60
 
 
61
static int
 
62
ffshdr_compare(const void *_a, const void *_b)
 
63
{
 
64
        const struct ffs_header_t *a = *(struct ffs_header_t * const *) _a;
 
65
        const struct ffs_header_t *b = *(struct ffs_header_t * const *) _b;
 
66
 
 
67
        if (a->romaddr == b->romaddr)
 
68
                return 0;
 
69
        if (a->romaddr > b->romaddr)
 
70
                return 1;
 
71
        return -1;
 
72
}
 
73
 
 
74
static void
 
75
hdr_print(struct ffs_header_t *hdr)
 
76
{
 
77
        printf("hdr: %p\n", hdr);
 
78
        printf("\taddr:      %08llx token:    %s\n"
 
79
               "\tflags:     %08llx romaddr:  %08llx image_len: %08x\n"
 
80
               "\tsave_len:  %08llx ffsize:   %08x hdrsize:   %08x\n"
 
81
               "\ttokensize: %08x\n",
 
82
               hdr->addr, hdr->token, hdr->flags, hdr->romaddr,
 
83
               hdr->imagefile_length, hdr->save_data_len,
 
84
               hdr->ffsize, hdr->hdrsize, hdr->tokensize);
 
85
}
 
86
 
 
87
int
 
88
reorder_ffs_chain(struct ffs_chain_t *fs)
 
89
{
 
90
        int i, j;
 
91
        int free_space;
 
92
        unsigned long long addr;
 
93
        struct ffs_header_t *hdr;
 
94
        int fix, flx, res, tab_size = fs->count;
 
95
        struct ffs_header_t *fix_tab[tab_size]; /* fixed offset */
 
96
        struct ffs_header_t *flx_tab[tab_size]; /* flexible offset */
 
97
        struct ffs_header_t *res_tab[tab_size]; /* result */
 
98
 
 
99
        /* determine size data to be able to do the reordering */
 
100
        for (hdr = fs->first; hdr; hdr = hdr->next) {
 
101
                if (hdr->linked_to)
 
102
                        hdr->imagefile_length = 0;
 
103
                else
 
104
                        hdr->imagefile_length = file_getsize(hdr->imagefile);
 
105
                if (hdr->imagefile_length == -1)
 
106
                        return -1;
 
107
 
 
108
                hdr->tokensize = pad8_num(strlen(hdr->token) + 1);
 
109
                hdr->hdrsize = FFS_TARGET_HEADER_SIZE + hdr->tokensize;
 
110
                hdr->ffsize =
 
111
                    hdr->hdrsize + pad8_num(hdr->imagefile_length) + 8;
 
112
        }
 
113
 
 
114
        memset(res_tab, 0, tab_size * sizeof(struct ffs_header_t *));
 
115
        memset(fix_tab, 0, tab_size * sizeof(struct ffs_header_t *));
 
116
        memset(flx_tab, 0, tab_size * sizeof(struct ffs_header_t *));
 
117
 
 
118
        /* now start with entries having fixed offs, reorder if needed */
 
119
        for (fix = 0, flx = 0, hdr = fs->first; hdr; hdr = hdr->next)
 
120
                if (needs_fix_offset(hdr))
 
121
                        fix_tab[fix++] = hdr;
 
122
                else
 
123
                        flx_tab[flx++] = hdr;
 
124
        qsort(fix_tab, fix, sizeof(struct ffs_header_t *), ffshdr_compare);
 
125
 
 
126
        /*
 
127
         * for fixed files we need to also remove the hdrsize from the
 
128
         * free space because it placed in front of the romaddr
 
129
         */
 
130
        for (addr = 0, res = 0, i = 0, j = 0; i < fix; i++) {
 
131
                fix_tab[i]->addr = fix_tab[i]->romaddr - fix_tab[i]->hdrsize;
 
132
                free_space = fix_tab[i]->addr - addr;
 
133
 
 
134
                /* insert as many flexible files as possible */
 
135
                for (; free_space > 0 && j < flx; j++) {
 
136
                        if (flx_tab[j]->ffsize <= free_space) { /* fits */
 
137
                                flx_tab[j]->addr = addr;
 
138
                                free_space -= flx_tab[j]->ffsize;
 
139
                                addr += flx_tab[j]->ffsize;
 
140
                                res_tab[res++] = flx_tab[j];
 
141
                        } else
 
142
                                break;
 
143
                }
 
144
                res_tab[res++] = fix_tab[i];
 
145
                addr = fix_tab[i]->romaddr + fix_tab[i]->ffsize -
 
146
                    fix_tab[i]->hdrsize;
 
147
        }
 
148
        /* at the end fill up the table with remaining flx entries */
 
149
        for (; j < flx; j++) {
 
150
                flx_tab[j]->addr = addr;
 
151
                addr += flx_tab[j]->ffsize;
 
152
                res_tab[res++] = flx_tab[j];
 
153
        }
 
154
 
 
155
        if (verbose) {
 
156
                printf("--- resulting order ---\n");
 
157
                for (i = 0; i < tab_size; i++)
 
158
                        hdr_print(res_tab[i]);
 
159
        }
 
160
 
 
161
        /* to check if the requested romfs images is greater than
 
162
         * the specified romfs_size it is necessary to add 8 for
 
163
         * the CRC to the totalsize */
 
164
        addr += 8;
 
165
 
 
166
        /* sanity checking if user specified maximum romfs size */
 
167
        if ((fs->romfs_size != 0) && addr > fs->romfs_size) {
 
168
                fprintf(stderr, "[build_romfs] romfs_size specified as %d "
 
169
                        "bytes, but %lld bytes need to be written.\n",
 
170
                        fs->romfs_size, addr);
 
171
                return 1;
 
172
        }
 
173
 
 
174
        /* resort result list */
 
175
        for (i = 0; i < tab_size - 1; i++)
 
176
                res_tab[i]->next = res_tab[i + 1];
 
177
        res_tab[i]->next = NULL;
 
178
        fs->first = res_tab[0];
 
179
        return 0;
 
180
}
 
181
 
 
182
/**
 
183
 * allocate memory for a romfs file including header
 
184
 */
 
185
static unsigned char *
 
186
malloc_file(int hdrsz, int datasz, int *ffsz)
 
187
{
 
188
        void *tmp;
 
189
 
 
190
        /* complete file size is:
 
191
         * header + 8byte aligned(data) + end of file marker (-1) */
 
192
        *ffsz = hdrsz + pad8_num(datasz) + 8;
 
193
        /* get the mem */
 
194
        tmp = malloc(*ffsz);
 
195
 
 
196
        if (!tmp)
 
197
                return NULL;
 
198
 
 
199
        memset(tmp, 0, *ffsz);
 
200
 
 
201
        return (unsigned char *) tmp;
 
202
}
 
203
 
 
204
static int
 
205
copy_file(struct ffs_header_t *hdr, unsigned char *ffile, int datasize,
 
206
          int ffile_offset, int ffsize)
 
207
{
 
208
        int cnt = 0;
 
209
        int imgfd;
 
210
        int i;
 
211
 
 
212
        if (!file_exist(hdr->imagefile, 1)) {
 
213
                printf("access error to file: %s\n", hdr->imagefile);
 
214
                free(ffile);
 
215
                return -1;
 
216
        }
 
217
 
 
218
        imgfd = open(hdr->imagefile, O_RDONLY);
 
219
        if (0 >= imgfd) {
 
220
                perror(hdr->imagefile);
 
221
                free(ffile);
 
222
                return -1;
 
223
        }
 
224
 
 
225
        /* now copy file to file buffer */
 
226
        /* FIXME using fread might be a good idea so
 
227
           that we do not need to deal with shortened
 
228
           reads/writes. Also error handling looks
 
229
           broken to me. Are we sure that all data is
 
230
           read when exiting this loop? */
 
231
        while (1) {
 
232
                i = read(imgfd, ffile + ffile_offset, ffsize - ffile_offset);
 
233
                if (i <= 0)
 
234
                        break;
 
235
                ffile_offset += i;
 
236
                cnt += i;
 
237
        }
 
238
 
 
239
        /* sanity check */
 
240
        if (cnt != datasize) {
 
241
                printf("BUG!!! copy error on image file [%s](e%d, g%d)\n",
 
242
                       hdr->imagefile, datasize, cnt);
 
243
                close(imgfd);
 
244
                free(ffile);
 
245
                return -1;
 
246
        }
 
247
 
 
248
        close(imgfd);
 
249
 
 
250
        return cnt;
 
251
}
 
252
 
 
253
static uint64_t
 
254
next_file_offset(struct ffs_header_t *hdr, int rom_pos, int ffsize)
 
255
{
 
256
        uint64_t tmp;
 
257
 
 
258
        /* no next file; end of filesystem */
 
259
        if (hdr->next == NULL)
 
260
                return 0;
 
261
 
 
262
        if (hdr->next->romaddr > 0) {
 
263
                /* the next file does not follow directly after the
 
264
                 * current file because it requested to be
 
265
                 * placed at a special address;
 
266
                 * we need to calculate the offset of the
 
267
                 * next file;
 
268
                 * the next file starts at hdr->next->romaddr which
 
269
                 * is the address requested by the user */
 
270
                tmp = hdr->next->romaddr;
 
271
                /* the next file starts, however, a bit earlier;
 
272
                 * we need to point at the header of the next file;
 
273
                 * therefore it is necessary to subtract the header size
 
274
                 * of the _next_ file */
 
275
                tmp -= FFS_TARGET_HEADER_SIZE;
 
276
                /* also remove the length of the filename of the _next_
 
277
                 * file */
 
278
                tmp -= pad8_num(strlen(hdr->next->token) + 1);
 
279
                /* and it needs to be relative to the current file */
 
280
                tmp -= rom_pos;
 
281
                return tmp;
 
282
        }
 
283
 
 
284
        /* if no special treatment is required the next file just
 
285
         * follows after the current file;
 
286
         * therefore just return the complete filesize as offset */
 
287
        return ffsize;
 
288
}
 
289
 
 
290
static int
 
291
next_file_address(struct ffs_header_t *hdr, unsigned int rom_pos, int hdrsize,
 
292
                  unsigned int num_files)
 
293
{
 
294
        /* check if file wants a specific address */
 
295
        void *tmp;
 
296
 
 
297
        if ((hdr->flags & FLAG_LLFW) == 0)
 
298
                /* flag to get a specific address has been set */
 
299
                return rom_pos;
 
300
 
 
301
        if (hdr->romaddr == 0)
 
302
                /* if the requested address is 0 then
 
303
                 * something is not right; ignore the flag */
 
304
                return rom_pos;
 
305
 
 
306
        /* check if romaddress is below current position */
 
307
        if (hdr->romaddr < (rom_pos + hdrsize)) {
 
308
                printf("[%s] ERROR: requested impossible " "romaddr of %llx\n",
 
309
                       hdr->token, hdr->romaddr);
 
310
                return -1;
 
311
        }
 
312
 
 
313
        /* spin offset to new position */
 
314
        if (pad8_num(hdr->romaddr) != hdr->romaddr) {
 
315
                printf("BUG!!!! pad8_num(hdr->romaddr) != hdr->romaddr\n");
 
316
                return -1;
 
317
        }
 
318
 
 
319
        tmp = malloc(hdr->romaddr - rom_pos - hdrsize);
 
320
 
 
321
        if (!tmp)
 
322
                return -1;
 
323
 
 
324
        memset(tmp, 0, hdr->romaddr - rom_pos - hdrsize);
 
325
        if (buildDataStream(tmp, hdr->romaddr - rom_pos - hdrsize)) {
 
326
                free(tmp);
 
327
                printf("write failed\n");
 
328
                return -1;
 
329
        }
 
330
 
 
331
        free(tmp);
 
332
 
 
333
        if (!num_files)
 
334
                printf("\nWARNING: The filesystem will have no entry header!\n"
 
335
                       "         It is still usable but you need to find\n"
 
336
                       "         the FS by yourself in the image.\n\n");
 
337
 
 
338
        return hdr->romaddr - hdrsize;
 
339
}
 
340
 
 
341
int
 
342
build_ffs(struct ffs_chain_t *fs, const char *outfile, int notime)
 
343
{
 
344
        int ofdCRC;
 
345
        int ffsize, datasize, i;
 
346
        int tokensize, hdrsize, ffile_offset, hdrbegin;
 
347
        struct ffs_header_t *hdr;
 
348
        unsigned char *ffile;
 
349
        unsigned int rom_pos = 0;
 
350
        unsigned int num_files = 0;
 
351
        uint64_t tmp;
 
352
 
 
353
        if (NULL == fs->first) {
 
354
                return 1;
 
355
        }
 
356
        hdr = fs->first;
 
357
 
 
358
        /* check output file and open it for creation */
 
359
        if (file_exist(outfile, 0)) {
 
360
                printf("Output file (%s) will be overwritten\n", outfile);
 
361
        }
 
362
 
 
363
        while (hdr) {
 
364
 
 
365
                if (hdr->linked_to) {
 
366
                        printf("\nBUG!!! links not supported anymore\n");
 
367
                        return 1;
 
368
                }
 
369
 
 
370
                /* add +1 to strlen for zero termination */
 
371
                tokensize = pad8_num(strlen(hdr->token) + 1);
 
372
                hdrsize = FFS_TARGET_HEADER_SIZE + tokensize;
 
373
                datasize = file_getsize(hdr->imagefile);
 
374
 
 
375
                if (datasize == -1) {
 
376
                        perror(hdr->imagefile);
 
377
                        return 1;
 
378
                }
 
379
 
 
380
                ffile_offset = 0;
 
381
                ffile = malloc_file(hdrsize, datasize, &ffsize);
 
382
 
 
383
                if (NULL == ffile) {
 
384
                        perror("alloc mem for ffile");
 
385
                        return 1;
 
386
                }
 
387
 
 
388
                /* check if file wants a specific address */
 
389
                rom_pos = next_file_address(hdr, rom_pos, hdrsize, num_files);
 
390
                hdrbegin = rom_pos;
 
391
 
 
392
                if (hdrbegin == -1) {
 
393
                        /* something went wrong */
 
394
                        free(ffile);
 
395
                        return 1;
 
396
                }
 
397
 
 
398
                /* write header ******************************************* */
 
399
                /* next addr ********************************************** */
 
400
                tmp = next_file_offset(hdr, rom_pos, ffsize);
 
401
 
 
402
                *(uint64_t *) (ffile + ffile_offset) = cpu_to_be64(tmp);
 
403
                rom_pos += 8;
 
404
                ffile_offset += 8;
 
405
 
 
406
                /* length ************************************************* */
 
407
                hdr->save_data_len = datasize;
 
408
 
 
409
                *(uint64_t *) (ffile + ffile_offset) = cpu_to_be64(datasize);
 
410
                rom_pos += 8;
 
411
                ffile_offset += 8;
 
412
 
 
413
                /* flags ************************************************** */
 
414
                *(uint64_t *) (ffile + ffile_offset) = cpu_to_be64(hdr->flags);
 
415
                rom_pos += 8;
 
416
                ffile_offset += 8;
 
417
 
 
418
                /* datapointer ******************************************** */
 
419
 
 
420
                //save-data pointer is relative to rombase
 
421
                hdr->save_data = hdrbegin + hdrsize;
 
422
                hdr->save_data_valid = 1;
 
423
                //changed pointers to be relative to file:
 
424
                tmp = hdr->save_data - hdrbegin;
 
425
 
 
426
                *(uint64_t *) (ffile + ffile_offset) = cpu_to_be64(tmp);
 
427
                rom_pos += 8;
 
428
                ffile_offset += 8;
 
429
 
 
430
                /* name (token) ******************************************* */
 
431
                memset(ffile + ffile_offset, 0, tokensize);
 
432
                strcpy((char *) ffile + ffile_offset, hdr->token);
 
433
                rom_pos += tokensize;
 
434
                ffile_offset += tokensize;
 
435
 
 
436
                /* image file ********************************************* */
 
437
                i = copy_file(hdr, ffile, datasize, ffile_offset, ffsize);
 
438
 
 
439
                if (i == -1)
 
440
                        return 1;
 
441
 
 
442
                /* pad file */
 
443
                rom_pos += i + pad8_num(datasize) - datasize;
 
444
                ffile_offset += i + pad8_num(datasize) - datasize;
 
445
 
 
446
                /* limiter ************************************************ */
 
447
                *(uint64_t *) (ffile + ffile_offset) = -1;
 
448
                rom_pos += 8;
 
449
                ffile_offset += 8;
 
450
 
 
451
                if (buildDataStream(ffile, ffsize) != 0) {
 
452
                        printf
 
453
                            ("Failed while processing file '%s' (size = %d bytes)\n",
 
454
                             hdr->imagefile, datasize);
 
455
                        return 1;
 
456
                }
 
457
                free(ffile);
 
458
                hdr = hdr->next;
 
459
                num_files++;
 
460
        }
 
461
 
 
462
        /*
 
463
         * FIXME Current limination seems to be about 4MiB.
 
464
         */
 
465
        ofdCRC = open(outfile, O_CREAT | O_WRONLY | O_TRUNC, 0666);
 
466
        if (0 > ofdCRC) {
 
467
                perror(outfile);
 
468
                return 1;
 
469
        }
 
470
        i = writeDataStream(ofdCRC, notime);
 
471
        close(ofdCRC);
 
472
 
 
473
        if (i)
 
474
                return 1;
 
475
        return 0;
 
476
}