|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.