|
|
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.