Annotation of qemu/roms/SLOF/romfs/tools/build_ffs.c, revision 1.1.1.1

1.1       root        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 positon */
                    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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.