From aaad509cdca2ed5f2c92a26f5279ec0e89c4fd5f Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 1 Dec 2010 09:51:44 +1100 Subject: Initial import of slof-JX-1.7.0-4 Signed-off-by: Benjamin Herrenschmidt --- romfs/header.img | 1 + romfs/tools/Makefile | 55 ++++++ romfs/tools/build_ffs.c | 476 +++++++++++++++++++++++++++++++++++++++++++++ romfs/tools/cfg_parse.c | 371 +++++++++++++++++++++++++++++++++++ romfs/tools/cfgparse.h | 59 ++++++ romfs/tools/create_crc.c | 467 ++++++++++++++++++++++++++++++++++++++++++++ romfs/tools/create_flash.c | 163 ++++++++++++++++ romfs/tools/createcrc.h | 19 ++ 8 files changed, 1611 insertions(+) create mode 100644 romfs/header.img create mode 100644 romfs/tools/Makefile create mode 100644 romfs/tools/build_ffs.c create mode 100644 romfs/tools/cfg_parse.c create mode 100644 romfs/tools/cfgparse.h create mode 100644 romfs/tools/create_crc.c create mode 100644 romfs/tools/create_flash.c create mode 100644 romfs/tools/createcrc.h (limited to 'romfs') diff --git a/romfs/header.img b/romfs/header.img new file mode 100644 index 0000000..794129c --- /dev/null +++ b/romfs/header.img @@ -0,0 +1 @@ +Key.Polynome....XXXXXXXX..Mask..XXXXXXXX.Polynome.Length....XXXX.Header.and.File.lengthXXXXXXXX... und weiter im Text! diff --git a/romfs/tools/Makefile b/romfs/tools/Makefile new file mode 100644 index 0000000..8f399a8 --- /dev/null +++ b/romfs/tools/Makefile @@ -0,0 +1,55 @@ +# ***************************************************************************** +# * Copyright (c) 2004, 2008 IBM Corporation +# * All rights reserved. +# * This program and the accompanying materials +# * are made available under the terms of the BSD License +# * which accompanies this distribution, and is available at +# * http://www.opensource.org/licenses/bsd-license.php +# * +# * Contributors: +# * IBM Corporation - initial implementation +# ****************************************************************************/ + +# FIXME review -I ... +# export NEW_BUILD=1 + +TOPCMNDIR ?= ../.. +INCLCMNDIR ?= ../../include + +include $(TOPCMNDIR)/make.rules + + +CPPFLAGS = -I$(INCLCMNDIR) -I$(INCLBRDDIR) -I. +CFLAGS += $(FLAG) + +SRCS = build_ffs.c cfg_parse.c create_flash.c create_crc.c +OBJS = $(SRCS:%.c=%.o) + +all: build_romfs + +build_romfs: $(OBJS) + $(HOSTCC) $(HOSTCFLAGS) $(FLAG) -o $@ $^ + +testing: build_romfs + make -C test + +%.o: %.c + $(HOSTCC) $(CPPFLAGS) $(HOSTCFLAGS) $(FLAG) -c $< -o $@ + +clean: + rm -f build_romfs *.o + +distclean: clean + rm -f Makefile.dep + + +# Rules for creating the dependency file: +depend: + rm -f Makefile.dep + $(MAKE) Makefile.dep + +Makefile.dep: Makefile + $(HOSTCC) -MM $(CPPFLAGS) $(HOSTCFLAGS) $(SRCS) > Makefile.dep + +# Include dependency file if available: +-include Makefile.dep diff --git a/romfs/tools/build_ffs.c b/romfs/tools/build_ffs.c new file mode 100644 index 0000000..d00fecb --- /dev/null +++ b/romfs/tools/build_ffs.c @@ -0,0 +1,476 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define FFS_TARGET_HEADER_SIZE (4 * 8) + +extern int verbose; + +#define pad8_num(x) (((x) + 7) & ~7) + +static int +file_exist(const char *name, int errdisp) +{ + struct stat fileinfo; + + memset((void *) &fileinfo, 0, sizeof(struct stat)); + if (stat(name, &fileinfo) != 0) { + if (0 != errdisp) { + perror(name); + } + return 0; + } + if (S_ISREG(fileinfo.st_mode)) { + return 1; + } + return 0; +} + +static int +file_getsize(const char *name) +{ + int rc; + struct stat fi; + + rc = stat(name, &fi); + if (rc != 0) + return -1; + return fi.st_size; +} + +static int +ffshdr_compare(const void *_a, const void *_b) +{ + const struct ffs_header_t *a = *(struct ffs_header_t * const *) _a; + const struct ffs_header_t *b = *(struct ffs_header_t * const *) _b; + + if (a->romaddr == b->romaddr) + return 0; + if (a->romaddr > b->romaddr) + return 1; + return -1; +} + +static void +hdr_print(struct ffs_header_t *hdr) +{ + printf("hdr: %p\n", hdr); + printf("\taddr: %08llx token: %s\n" + "\tflags: %08llx romaddr: %08llx image_len: %08x\n" + "\tsave_len: %08llx ffsize: %08x hdrsize: %08x\n" + "\ttokensize: %08x\n", + hdr->addr, hdr->token, hdr->flags, hdr->romaddr, + hdr->imagefile_length, hdr->save_data_len, + hdr->ffsize, hdr->hdrsize, hdr->tokensize); +} + +int +reorder_ffs_chain(struct ffs_chain_t *fs) +{ + int i, j; + int free_space; + unsigned long long addr; + struct ffs_header_t *hdr; + int fix, flx, res, tab_size = fs->count; + struct ffs_header_t *fix_tab[tab_size]; /* fixed offset */ + struct ffs_header_t *flx_tab[tab_size]; /* flexible offset */ + struct ffs_header_t *res_tab[tab_size]; /* result */ + + /* determine size data to be able to do the reordering */ + for (hdr = fs->first; hdr; hdr = hdr->next) { + if (hdr->linked_to) + hdr->imagefile_length = 0; + else + hdr->imagefile_length = file_getsize(hdr->imagefile); + if (hdr->imagefile_length == -1) + return -1; + + hdr->tokensize = pad8_num(strlen(hdr->token) + 1); + hdr->hdrsize = FFS_TARGET_HEADER_SIZE + hdr->tokensize; + hdr->ffsize = + hdr->hdrsize + pad8_num(hdr->imagefile_length) + 8; + } + + memset(res_tab, 0, tab_size * sizeof(struct ffs_header_t *)); + memset(fix_tab, 0, tab_size * sizeof(struct ffs_header_t *)); + memset(flx_tab, 0, tab_size * sizeof(struct ffs_header_t *)); + + /* now start with entries having fixed offs, reorder if needed */ + for (fix = 0, flx = 0, hdr = fs->first; hdr; hdr = hdr->next) + if (needs_fix_offset(hdr)) + fix_tab[fix++] = hdr; + else + flx_tab[flx++] = hdr; + qsort(fix_tab, fix, sizeof(struct ffs_header_t *), ffshdr_compare); + + /* + * for fixed files we need to also remove the hdrsize from the + * free space because it placed in front of the romaddr + */ + for (addr = 0, res = 0, i = 0, j = 0; i < fix; i++) { + fix_tab[i]->addr = fix_tab[i]->romaddr - fix_tab[i]->hdrsize; + free_space = fix_tab[i]->addr - addr; + + /* insert as many flexible files as possible */ + for (; free_space > 0 && j < flx; j++) { + if (flx_tab[j]->ffsize <= free_space) { /* fits */ + flx_tab[j]->addr = addr; + free_space -= flx_tab[j]->ffsize; + addr += flx_tab[j]->ffsize; + res_tab[res++] = flx_tab[j]; + } else + break; + } + res_tab[res++] = fix_tab[i]; + addr = fix_tab[i]->romaddr + fix_tab[i]->ffsize - + fix_tab[i]->hdrsize; + } + /* at the end fill up the table with remaining flx entries */ + for (; j < flx; j++) { + flx_tab[j]->addr = addr; + addr += flx_tab[j]->ffsize; + res_tab[res++] = flx_tab[j]; + } + + if (verbose) { + printf("--- resulting order ---\n"); + for (i = 0; i < tab_size; i++) + hdr_print(res_tab[i]); + } + + /* to check if the requested romfs images is greater than + * the specified romfs_size it is necessary to add 8 for + * the CRC to the totalsize */ + addr += 8; + + /* sanity checking if user specified maximum romfs size */ + if ((fs->romfs_size != 0) && addr > fs->romfs_size) { + fprintf(stderr, "[build_romfs] romfs_size specified as %d " + "bytes, but %lld bytes need to be written.\n", + fs->romfs_size, addr); + return 1; + } + + /* resort result list */ + for (i = 0; i < tab_size - 1; i++) + res_tab[i]->next = res_tab[i + 1]; + res_tab[i]->next = NULL; + fs->first = res_tab[0]; + return 0; +} + +/** + * allocate memory for a romfs file including header + */ +static unsigned char * +malloc_file(int hdrsz, int datasz, int *ffsz) +{ + void *tmp; + + /* complete file size is: + * header + 8byte aligned(data) + end of file marker (-1) */ + *ffsz = hdrsz + pad8_num(datasz) + 8; + /* get the mem */ + tmp = malloc(*ffsz); + + if (!tmp) + return NULL; + + memset(tmp, 0, *ffsz); + + return (unsigned char *) tmp; +} + +static int +copy_file(struct ffs_header_t *hdr, unsigned char *ffile, int datasize, + int ffile_offset, int ffsize) +{ + int cnt = 0; + int imgfd; + int i; + + if (!file_exist(hdr->imagefile, 1)) { + printf("access error to file: %s\n", hdr->imagefile); + free(ffile); + return -1; + } + + imgfd = open(hdr->imagefile, O_RDONLY); + if (0 >= imgfd) { + perror(hdr->imagefile); + free(ffile); + return -1; + } + + /* now copy file to file buffer */ + /* FIXME using fread might be a good idea so + that we do not need to deal with shortened + reads/writes. Also error handling looks + broken to me. Are we sure that all data is + read when exiting this loop? */ + while (1) { + i = read(imgfd, ffile + ffile_offset, ffsize - ffile_offset); + if (i <= 0) + break; + ffile_offset += i; + cnt += i; + } + + /* sanity check */ + if (cnt != datasize) { + printf("BUG!!! copy error on image file [%s](e%d, g%d)\n", + hdr->imagefile, datasize, cnt); + close(imgfd); + free(ffile); + return -1; + } + + close(imgfd); + + return cnt; +} + +static uint64_t +next_file_offset(struct ffs_header_t *hdr, int rom_pos, int ffsize) +{ + uint64_t tmp; + + /* no next file; end of filesystem */ + if (hdr->next == NULL) + return 0; + + if (hdr->next->romaddr > 0) { + /* the next file does not follow directly after the + * current file because it requested to be + * placed at a special address; + * we need to calculate the offset of the + * next file; + * the next file starts at hdr->next->romaddr which + * is the address requested by the user */ + tmp = hdr->next->romaddr; + /* the next file starts, however, a bit earlier; + * we need to point at the header of the next file; + * therefore it is necessary to subtract the header size + * of the _next_ file */ + tmp -= FFS_TARGET_HEADER_SIZE; + /* also remove the length of the filename of the _next_ + * file */ + tmp -= pad8_num(strlen(hdr->next->token) + 1); + /* and it needs to be relative to the current file */ + tmp -= rom_pos; + return tmp; + } + + /* if no special treatment is required the next file just + * follows after the current file; + * therefore just return the complete filesize as offset */ + return ffsize; +} + +static int +next_file_address(struct ffs_header_t *hdr, unsigned int rom_pos, int hdrsize, + unsigned int num_files) +{ + /* check if file wants a specific address */ + void *tmp; + + if ((hdr->flags & FLAG_LLFW) == 0) + /* flag to get a specific address has been set */ + return rom_pos; + + if (hdr->romaddr == 0) + /* if the requested address is 0 then + * something is not right; ignore the flag */ + return rom_pos; + + /* check if romaddress is below current position */ + if (hdr->romaddr < (rom_pos + hdrsize)) { + printf("[%s] ERROR: requested impossible " "romaddr of %llx\n", + hdr->token, hdr->romaddr); + return -1; + } + + /* spin offset to new positon */ + if (pad8_num(hdr->romaddr) != hdr->romaddr) { + printf("BUG!!!! pad8_num(hdr->romaddr) != hdr->romaddr\n"); + return -1; + } + + tmp = malloc(hdr->romaddr - rom_pos - hdrsize); + + if (!tmp) + return -1; + + memset(tmp, 0, hdr->romaddr - rom_pos - hdrsize); + if (buildDataStream(tmp, hdr->romaddr - rom_pos - hdrsize)) { + free(tmp); + printf("write failed\n"); + return -1; + } + + free(tmp); + + if (!num_files) + printf("\nWARNING: The filesystem will have no entry header!\n" + " It is still usable but you need to find\n" + " the FS by yourself in the image.\n\n"); + + return hdr->romaddr - hdrsize; +} + +int +build_ffs(struct ffs_chain_t *fs, const char *outfile, int notime) +{ + int ofdCRC; + int ffsize, datasize, i; + int tokensize, hdrsize, ffile_offset, hdrbegin; + struct ffs_header_t *hdr; + unsigned char *ffile; + unsigned int rom_pos = 0; + unsigned int num_files = 0; + uint64_t tmp; + + if (NULL == fs->first) { + return 1; + } + hdr = fs->first; + + /* check output file and open it for creation */ + if (file_exist(outfile, 0)) { + printf("Output file (%s) will be overwritten\n", outfile); + } + + while (hdr) { + + if (hdr->linked_to) { + printf("\nBUG!!! links not supported anymore\n"); + return 1; + } + + /* add +1 to strlen for zero termination */ + tokensize = pad8_num(strlen(hdr->token) + 1); + hdrsize = FFS_TARGET_HEADER_SIZE + tokensize; + datasize = file_getsize(hdr->imagefile); + + if (datasize == -1) { + perror(hdr->imagefile); + return 1; + } + + ffile_offset = 0; + ffile = malloc_file(hdrsize, datasize, &ffsize); + + if (NULL == ffile) { + perror("alloc mem for ffile"); + return 1; + } + + /* check if file wants a specific address */ + rom_pos = next_file_address(hdr, rom_pos, hdrsize, num_files); + hdrbegin = rom_pos; + + if (hdrbegin == -1) { + /* something went wrong */ + free(ffile); + return 1; + } + + /* write header ******************************************* */ + /* next addr ********************************************** */ + tmp = next_file_offset(hdr, rom_pos, ffsize); + + *(uint64_t *) (ffile + ffile_offset) = cpu_to_be64(tmp); + rom_pos += 8; + ffile_offset += 8; + + /* length ************************************************* */ + hdr->save_data_len = datasize; + + *(uint64_t *) (ffile + ffile_offset) = cpu_to_be64(datasize); + rom_pos += 8; + ffile_offset += 8; + + /* flags ************************************************** */ + *(uint64_t *) (ffile + ffile_offset) = cpu_to_be64(hdr->flags); + rom_pos += 8; + ffile_offset += 8; + + /* datapointer ******************************************** */ + + //save-data pointer is relative to rombase + hdr->save_data = hdrbegin + hdrsize; + hdr->save_data_valid = 1; + //changed pointers to be relative to file: + tmp = hdr->save_data - hdrbegin; + + *(uint64_t *) (ffile + ffile_offset) = cpu_to_be64(tmp); + rom_pos += 8; + ffile_offset += 8; + + /* name (token) ******************************************* */ + memset(ffile + ffile_offset, 0, tokensize); + strcpy((char *) ffile + ffile_offset, hdr->token); + rom_pos += tokensize; + ffile_offset += tokensize; + + /* image file ********************************************* */ + i = copy_file(hdr, ffile, datasize, ffile_offset, ffsize); + + if (i == -1) + return 1; + + /* pad file */ + rom_pos += i + pad8_num(datasize) - datasize; + ffile_offset += i + pad8_num(datasize) - datasize; + + /* limiter ************************************************ */ + *(uint64_t *) (ffile + ffile_offset) = -1; + rom_pos += 8; + ffile_offset += 8; + + if (buildDataStream(ffile, ffsize) != 0) { + printf + ("Failed while processing file '%s' (size = %d bytes)\n", + hdr->imagefile, datasize); + return 1; + } + free(ffile); + hdr = hdr->next; + num_files++; + } + + /* + * FIXME Current limination seems to be about 4MiB. + */ + ofdCRC = open(outfile, O_CREAT | O_WRONLY | O_TRUNC, 0666); + if (0 > ofdCRC) { + perror(outfile); + return 1; + } + i = writeDataStream(ofdCRC, notime); + close(ofdCRC); + + if (i) + return 1; + return 0; +} diff --git a/romfs/tools/cfg_parse.c b/romfs/tools/cfg_parse.c new file mode 100644 index 0000000..5137fbe --- /dev/null +++ b/romfs/tools/cfg_parse.c @@ -0,0 +1,371 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include + +static int inbetween_white(char *s, int max, char **start, char **end, + char **next); +static int add_header(struct ffs_chain_t *, struct ffs_header_t *); + +static int glob_come_from_cr = 0; + +static int +find_next_entry(int file, struct ffs_chain_t *chain) +{ +#define MAX_LINE_SIZE 1024 + char lnbuf[MAX_LINE_SIZE], b0 = 0, b1 = 0; + char *start, *end, *next; + struct ffs_header_t *hdr; //, *hdr2; + int lc, rc; + char c; + + /* search for new config line */ + if (0 == glob_come_from_cr) { + while (1 == (rc = read(file, &c, 1))) { + //printf("b0=%c b1=%c c=%c\n", + // b0, b1, c); + b0 = b1; + b1 = c; + /* this looks for starting sign "[^#]" */ + if (((0x0a == b0) || (0x0d == b0)) && + (('#' != b1) && (0x0a != b1) && (0x0d != b1))) { + break; + } + } + } else { + /* normalize */ + while (1 == (rc = read(file, &c, 1))) { + //printf("read c=%c\n", c); + if ((0x0a != c) && (0x0d != c)) { + break; + } + } + glob_come_from_cr = 0; + //printf("debug: glob_come_from_cr = 0\n"); + } + if (1 != rc) { + return 1; + } + + /* now buffer it until end of line */ + memset((void *) lnbuf, 0, MAX_LINE_SIZE); + lnbuf[0] = c; + lc = 1; + while ((1 == read(file, &(lnbuf[lc]), 1)) && (lc < MAX_LINE_SIZE)) { + //printf("read lnbuf=%c\n", lnbuf[lc]); + if ((0x0a == lnbuf[lc]) || (0x0d == lnbuf[lc])) { + glob_come_from_cr = 1; + //printf("debug: glob_come_from_cr = 1\n"); + break; + } + lc++; + } + + /* allocate header */ + hdr = malloc(sizeof(struct ffs_header_t)); + if (NULL == hdr) { + perror("alloc memory"); + return 2; + } + memset((void *) hdr, 0, sizeof(struct ffs_header_t)); + + /* attach header to chain */ + if (0 != add_header(chain, hdr)) { + return 2; + } + + /**********************************************************/ + /* extract token name *********************************** */ + start = NULL; + if (inbetween_white(lnbuf, MAX_LINE_SIZE, &start, &end, &next) != 0) { + printf("parsing error 1"); + return 2; + } + /* get memory for it */ + hdr->token = malloc(end - start + 1); + if (NULL == hdr->token) { + return 2; + } + /* set string */ + strncpy(hdr->token, start, end - start + 1); + hdr->token[end - start] = 0; + + /**********************************************************/ + /* extract file name *********************************** */ + if (NULL == next) { + return 2; + } + start = next; + if (inbetween_white(lnbuf, MAX_LINE_SIZE, &start, &end, &next) != 0) { + printf("parsing error 1"); + return 2; + } + + /* get memory for it */ + hdr->imagefile = malloc(end - start + 1); + if (NULL == hdr->imagefile) { + return 2; + } + + /* check if file is existing */ + + /* set string */ + strncpy(hdr->imagefile, start, end - start + 1); + hdr->imagefile[end - start] = 0; + + /* check if entry is linked to another header */ + if (':' == *start) { + printf + ("\nERROR: links are removed as feature in this version\n"); + return 2; + + /* + start++; + if (0 != find_entry_by_token(chain, hdr->imagefile+1, &hdr2)) { + printf("[%s]: link to [%s] not found\n", + hdr->token, hdr->imagefile+1); + dump_fs_contents(chain); + return 2; + } + hdr->linked_to = hdr2; + */ + } + + /**********************************************************/ + /* extract flags name *********************************** */ + if (NULL == next) { + return 2; + } + start = next; + if (inbetween_white(lnbuf, MAX_LINE_SIZE, &start, &end, &next) != 0) { + printf("parsing error 1"); + return 2; + } + hdr->flags = strtoul(start, NULL, 16); + + /**********************************************************/ + /* extract rom start name *********************************** */ + if (NULL == next) { + return 2; + } + start = next; + if (inbetween_white(lnbuf, MAX_LINE_SIZE, &start, &end, &next) != 0) { + printf("parsing error 1"); + return 2; + } + if ('-' == *start) { + /* this means not specific address request for data */ + hdr->romaddr = 0; + } else { + /* data has to begin at specific address */ + hdr->romaddr = strtoul(start, NULL, 16); + } + + return 0; +} + +int +read_config(int conf_file, struct ffs_chain_t *ffs_chain) +{ + int rc; + + while (1) { + rc = find_next_entry(conf_file, ffs_chain); + if (rc != 0) + break; + } + return rc; +} + +static int +inbetween_white(char *s, int max, char **start, char **end, char **next) +{ + int pos = 0, posalt; + + if (NULL != *start) { + pos = *start - s; + s = *start; + } + + /* wind to first non white */ + while (pos < max) { + if ((' ' == *s) || (' ' == *s)) { + s++; + pos++; + continue; + } + break; + } + if (pos >= max) { + /* no non-white found */ + return 1; + } + + /* assign start */ + *start = s; + + /* wind to end of non white or end of buffer */ + posalt = pos; + while (pos < max) { + if ((' ' == *s) || (' ' == *s) || + (0x0a == *s) || (0x0d == *s)) { + break; + } + s++; + pos++; + } + + if (pos == posalt) { + return 1; + } + + *end = s; + + if ((pos + 1) >= max) { + *next = NULL; + } else { + *next = s; + } + + return 0; +} + +int +add_header(struct ffs_chain_t *chain, struct ffs_header_t *hdr) +{ + struct ffs_header_t *next; + + if (NULL == chain->first) { + chain->count = 1; + chain->first = hdr; + return 0; + } + next = chain->first; + + /* find last */ + while (NULL != next->next) { + next = next->next; + } + next->next = hdr; + chain->count++; + + return 0; +} + +void +dump_fs_contents(struct ffs_chain_t *chain) +{ + struct ffs_header_t *next; + + if (NULL == chain->first) { + printf("no contents in fs\n"); + return; + } + next = chain->first; + + while (1) { + if (NULL != next->token) { + printf("Token [%s] ", next->token); + } else { + printf(" [not-set], "); + } + + if (NULL != next->imagefile) { + printf(" <%s>, ", next->imagefile); + } else { + printf(" file, "); + } + + printf("flags<%llx>, ", next->flags); + printf("romaddr<%llx>, ", next->romaddr); + + if (NULL != next->linked_to) { + printf("linked to [%s]", next->linked_to->token); + } + + printf("\n"); + if (NULL == next->next) { + break; + } + + next = next->next; + } + +} + +void +free_chain_memory(struct ffs_chain_t *chain) +{ + struct ffs_header_t *hdr, *next_hdr; + + if (NULL != chain->first) { + hdr = chain->first; + chain->first = NULL; + } else { + return; + } + + while (NULL != hdr) { + //printf("%p ", hdr); + if (NULL != hdr->token) { + //printf("free up %s\n", hdr->token); + free(hdr->token); + } + if (NULL != hdr->imagefile) { + free(hdr->imagefile); + } + next_hdr = hdr->next; + free(hdr); + hdr = next_hdr; + } +} + + +/* + * Detect duplicate entries in the romfs list + */ +void +find_duplicates(struct ffs_chain_t *chain) +{ + struct ffs_header_t *act, *sub; + + if (NULL == chain->first) { + printf("no contents in fs\n"); + return; + } + act = chain->first; + + do { + sub = act->next; + while (sub != NULL) { + + if (act->token == NULL || sub->token == NULL) { + printf("find_duplicates: token not set!\n"); + } else if (strcmp(act->token, sub->token) == 0) { + printf("*** NOTE: duplicate romfs file '%s'.\n", + act->token); + } + sub = sub->next; + } + + act = act->next; + + } while (act != NULL); + +} diff --git a/romfs/tools/cfgparse.h b/romfs/tools/cfgparse.h new file mode 100644 index 0000000..ed5c885 --- /dev/null +++ b/romfs/tools/cfgparse.h @@ -0,0 +1,59 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#ifndef CFGPARSE_H +#define CFGPARSE_H + +#include +#include + +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_to_be64(x) (x) +#else +#define cpu_to_be64(x) bswap_64(x) +#endif + +struct ffs_chain_t { + int count; + unsigned int romfs_size; + struct ffs_header_t *first; +}; + +#define FLAG_LLFW 1 /* low level firmware at fix offs in romfs */ + +#define needs_fix_offset(hdr) ((hdr)->flags & FLAG_LLFW) + +struct ffs_header_t { + unsigned long long flags; + unsigned long long romaddr; + char *token; + char *imagefile; + int imagefile_length; + struct ffs_header_t *linked_to; + struct ffs_header_t *next; + unsigned long long save_data; + unsigned long long save_data_len; + int save_data_valid; + + unsigned long long addr; /* tmp */ + int hdrsize; /* tmp */ + int tokensize; /* tmp */ + int ffsize; /* tmp */ +}; + +void dump_fs_contents(struct ffs_chain_t *chain); +void find_duplicates(struct ffs_chain_t *chain); +void free_chain_memory(struct ffs_chain_t *chain); + +int read_config(int conf_file, struct ffs_chain_t *ffs_chain); +int reorder_ffs_chain(struct ffs_chain_t *fs); +int build_ffs(struct ffs_chain_t *fs, const char *outfile, int notime); +#endif diff --git a/romfs/tools/create_crc.c b/romfs/tools/create_crc.c new file mode 100644 index 0000000..38235e5 --- /dev/null +++ b/romfs/tools/create_crc.c @@ -0,0 +1,467 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "createcrc.h" + +int createHeaderImage(int); +unsigned int calCRCEthernet32(unsigned char *TextPtr, + unsigned long int TextLength, + unsigned int AccumCRC); +int createCRCParameter(uint64_t * ui64RegisterMask, + unsigned int *iRegisterLength); +uint64_t calCRCbyte(unsigned char *TextPtr, uint32_t Residual, + uint64_t AccumCRC); +uint64_t calCRCword(unsigned char *TextPtr, uint32_t Residual, + uint64_t AccumCRC); +uint64_t checkCRC(unsigned char *TextPtr, uint32_t Residual, uint64_t AccumCRC); + +/* file length in bytes */ +static uint64_t ui64globalFileSize = 0; +/* space for the file stream >= 4MB + 4bytes */ +static unsigned char pucFileStream[4400000]; +/* header length in bytes */ +static uint64_t ui64globalHeaderSize = 0; +/* flag to filter detect the header in buildDataStream() */ +static int iglobalHeaderFlag = 1; +static uint64_t ui64Generator1; + +/** + * Build the file image and store it as Data Stream of bytes + * calculate a first CRC for the first file and + * catch the position of this CRC + */ +int +buildDataStream(unsigned char *pucbuf, int size) +{ + if (ui64globalFileSize + size > sizeof(pucFileStream)) { + printf("Error: File size is too big!\n"); + return -1; + } + + /* copy the data into the destination buffer */ + memcpy(pucFileStream + ui64globalFileSize, pucbuf, size); + ui64globalFileSize += size; + + if (iglobalHeaderFlag == 1) { // catch header + + ui64globalHeaderSize = ui64globalFileSize; + iglobalHeaderFlag = 0; + } + + return 0; +} + +/** + * write Header.img + */ +int +createHeaderImage(int notime) +{ + int iCounter; + uint64_t ui64RomAddr, ui64DataAddr; + time_t caltime; + struct tm *tm; + char *pcVersion; + char dastr[16] = { 0, }; + unsigned long long da = 0; + + union { + unsigned char pcArray[FLASHFS_HEADER_DATA_SIZE]; + struct stH stHeader; + } uHeader; + + /* initialize Header */ + memset(uHeader.pcArray, 0x00, FLASHFS_HEADER_DATA_SIZE); + + /* read driver info */ + if (NULL != (pcVersion = getenv("DRIVER_NAME"))) { + strncpy(uHeader.stHeader.version, pcVersion, 16); + } else if (NULL != (pcVersion = getenv("USER"))) { + strncpy(uHeader.stHeader.version, pcVersion, 16); + } else if (pcVersion == NULL) { + strncpy(uHeader.stHeader.version, "No known user!", 16); + } + + if (!notime) { + /* read time and write it into data stream */ + if ((caltime = time(NULL)) == -1) { + printf("time error\n"); + } + if ((tm = localtime(&caltime)) == NULL) { + printf("local time error\n"); + } + // length must be 13 instead 12 because of terminating + // NUL. Therefore uH.stH.platform_revison must be + // writen later to overwrite the terminating NUL + if (strftime(dastr, 15, "0x%Y%m%d%H%M", tm) == 0) { + printf("strftime error\n"); + } + da = cpu_to_be64(strtoll(dastr, NULL, 16)); + } + memcpy(uHeader.stHeader.date, &da, 8); + + /* write Magic value into data stream */ + strcpy(uHeader.stHeader.magic, FLASHFS_MAGIC); + /* write platform name into data stream */ + strcpy(uHeader.stHeader.platform_name, FLASHFS_PLATFORM_MAGIC); + /* write platform revision into data stream */ + strcpy(uHeader.stHeader.platform_revision, FLASHFS_PLATFORM_REVISION); + + + /* fill end of file info (8 bytes of FF) into data stream */ + uHeader.stHeader.ui64FileEnd = -1; + + /* read address of next file and address of header date, both are 64 bit values */ + ui64RomAddr = 0; + ui64DataAddr = 0; + for (iCounter = 0; iCounter < 8; iCounter++) { + /* addr of next file */ + ui64RomAddr = (ui64RomAddr << 8) + pucFileStream[FLASHFS_ROMADDR + iCounter]; + /* addr of header data */ + ui64DataAddr = (ui64DataAddr << 8) + pucFileStream[FLASHFS_DATADDR + iCounter]; + } + + /* calculate final flash-header-size and flash-file-size */ + /* calculate end addr of header */ + ui64globalHeaderSize = (uint32_t) ui64DataAddr + (uint32_t) FLASHFS_HEADER_DATA_SIZE; + /* cut 64 bit to place CRC for File-End */ + ui64globalHeaderSize -= 8; + /* add 64 bit to place CRC behind File-End */ + ui64globalFileSize += 8; + + if (ui64globalHeaderSize >= ui64RomAddr) { + printf("%s\n", "--- Header File to long"); + return 1; + } + + /* fill free space in Header with zeros */ + memset(&pucFileStream[ui64DataAddr], 0, (ui64RomAddr - ui64DataAddr)); + /* place data to header */ + memcpy(&pucFileStream[ui64DataAddr], uHeader.pcArray, + FLASHFS_HEADER_DATA_SIZE); + + /* insert header length into data stream */ + *(uint64_t *) (pucFileStream + FLASHFS_HEADER_SIZE_ADDR) = + cpu_to_be64(ui64globalHeaderSize); + + /* insert flash length into data stream */ + *(uint64_t *) (pucFileStream + ui64DataAddr + FLASHFS_FILE_SIZE_ADDR) = + cpu_to_be64(ui64globalFileSize); + + /* insert zeros as placeholder for CRC */ + *(uint64_t *) (pucFileStream + ui64globalHeaderSize - 8) = 0; + *(uint64_t *) (pucFileStream + ui64globalFileSize - 8) = 0; + + return 0; +} + +/** + * calculate standart ethernet 32 bit CRC + * generator polynome is 0x104C11DB7 + * this algorithm can be used for encoding and decoding + */ +unsigned int +calCRCEthernet32(unsigned char *TextPtr, unsigned long int TextLength, + unsigned int AccumCRC) +{ + const unsigned int CrcTableHigh[16] = { + 0x00000000, 0x4C11DB70, 0x9823B6E0, 0xD4326D90, + 0x34867077, 0x7897AB07, 0xACA5C697, 0xE0B41DE7, + 0x690CE0EE, 0x251D3B9E, 0xF12F560E, 0xBD3E8D7E, + 0x5D8A9099, 0x119B4BE9, 0xC5A92679, 0x89B8FD09 + }; + const unsigned CrcTableLow[16] = { + 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, + 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, + 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, + 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD + }; + + unsigned char *Buffer = TextPtr; + unsigned long int Residual = TextLength; + + + while (Residual > 0) { + unsigned int Temp = ((AccumCRC >> 24) ^ *Buffer) & 0x000000ff; + AccumCRC <<= 8; + AccumCRC ^= CrcTableHigh[Temp / 16]; + AccumCRC ^= CrcTableLow[Temp % 16]; + ++Buffer; + --Residual; + } + return AccumCRC; +} + +/** + * create CRC Parameter: CRC Polynome, Shiftregister Mask and length + * + * ui64Generator[0] = 0; + * ui64Generator[1] = 0x42F0E1EB; + * ui64Generator[1] = (ui64Generator[1] << 32) + 0xA9EA3693; + * iRegisterLength = 63; + * ui64RegisterMask = 0xffffffff; + * ui64RegisterMask = ((ui64RegisterMask) << 32) + 0xffffffff; + * + * ucl=0x00000000ffffffff = Mask for 32 bit LSFR to cut down number of bits + * in the variable to get the same length as LFSR + * + * il = length of LSFR = degree of generator polynom reduce il by one to calculate the degree + * of the highest register in LSFR + * + * Examples: + * CRC-16 for Tap: x16 + x15 + x2 + 1 + * generator = 0x8005, il = 16, ucl = 0x000000000000FFFF + * + * CRC-16 for Floppy: x16 + x12 + x5 +1 + * generator = 0x1021, il = 16, ucl = 0x000000000000FFFF + * + * CRC-32 for Ethernet: x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x + 1 + * generator = 0x04C11DB7, il = 32, ucl = 0x00000000FFFFFFFF + * + * CRC-64 SP-TrEMBL x64 + x4 + x3 + x + 1 (maximal-length LFSR) + * generator = 0x1B, il = 64, ucl = 0xFFFFFFFFFFFFFFFF + * + * CRC-64 improved + * x64 + x63 + x61 + x59 + x58 + x56 + x55 + x52 + x49 + x48 + x47 + x46+ x44 + + * x41 + x37 + x36 + x34 + x32 + x31 + x28 + x26 + x23 + x22 + x19 + x16 + x13 + + * x12 + x10 + x9 + x6 + x4 + x3 + 1 + * (see http://www.cs.ud.ac.uk/staff/D.Jones/crcbote.pdf) + * generator = 0xAD93D23594C9362D, il = 64, ucl = 0xFFFFFFFFFFFFFFFF + * + * CRC-64 DLT1 spec + * x64 + x62 + x57 + x55 + x54 + x53 + x52 + x47 + x46 + x45 + x40 + x39 + x38 + x37 + + * x35 + x33 + x32 + x31 + x29 + x27 + x24 + x23 + x22 + x21 + x19 + x17 + x13 + x12 + + * x10 + x9 + x7 + x4 + x + 1 + * (see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-182.pdf -> page63) + * generator = 0x42F0E1EBA9EA3693 + * + * CRC-64 from internet G(x)= 1006003C000F0D50B + */ +int +createCRCParameter(uint64_t * ui64RegisterMask, unsigned int *uiRegisterLength) +{ + enum Generators { Tape_16, Floppy_16, Ethernet_32, SPTrEMBL_64, + SPTrEMBL_improved_64, DLT1_64 + }; + enum Generators Generator; + + Generator = CRC_METHODE; + switch (Generator) { + case Tape_16:{ + *ui64RegisterMask = 0x0000ffff; + ui64Generator1 = 0x00008005; + *uiRegisterLength = 16; + break; + } + case Floppy_16:{ + *ui64RegisterMask = 0x0000ffff; + ui64Generator1 = 0x00001021; + *uiRegisterLength = 16; + break; + } + case Ethernet_32:{ + *ui64RegisterMask = 0xffffffff; + ui64Generator1 = 0x04C11DB7; + *uiRegisterLength = 32; + break; + } + case SPTrEMBL_64:{ + *ui64RegisterMask = 0xffffffff; + *ui64RegisterMask = + ((*ui64RegisterMask) << 32) + 0xffffffff; + ui64Generator1 = 0x0000001B; + *uiRegisterLength = 64; + break; + } + case SPTrEMBL_improved_64:{ + *ui64RegisterMask = 0xffffffff; + *ui64RegisterMask = + ((*ui64RegisterMask) << 32) + 0xffffffff; + ui64Generator1 = 0xAD93D235; + ui64Generator1 = (ui64Generator1 << 32) + 0x94C9362D; + *uiRegisterLength = 64; + break; + } + case DLT1_64:{ + *ui64RegisterMask = 0xffffffff; + *ui64RegisterMask = + ((*ui64RegisterMask) << 32) + 0xffffffff; + ui64Generator1 = 0x42F0E1EB; + ui64Generator1 = (ui64Generator1 << 32) + 0xA9EA3693; + *uiRegisterLength = 64; + break; + } + } + (*uiRegisterLength)--; + + return 0; +} + +/** + * Check CRC by using Linear Feadback Shift Register (LFSR) + */ +uint64_t +calCRCbyte(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) +{ + + uint64_t ui64Mask, ui64Generator0; + uint8_t ui8Buffer; + unsigned int uiRegisterLength; + int iShift; + + createCRCParameter(&ui64Mask, &uiRegisterLength); + + ui8Buffer = (*cPtr); + while (ui32NoWords > 0) { + for (iShift = 7; iShift >= 0; iShift--) { + + ui64Generator0 = (AccumCRC >> uiRegisterLength); + AccumCRC <<= 1; + ui64Generator0 &= 0x01; + ui64Generator0 = (0 - ui64Generator0); + AccumCRC ^= (ui64Generator1 & ui64Generator0); + } + AccumCRC ^= ui8Buffer; + AccumCRC &= ui64Mask; + ui32NoWords -= 1; + cPtr += 1; + ui8Buffer = (*cPtr); + } + return AccumCRC; +} + +/** + * Check CRC by using Linear Feadback Shift Register (LFSR) + */ +uint64_t +calCRCword(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) +{ + + uint64_t ui64Mask, ui64Generator0; + uint16_t ui16Buffer; + unsigned int uiRegisterLength; + int iShift; + + createCRCParameter(&ui64Mask, &uiRegisterLength); + + if ((ui32NoWords % 2) != 0) { + /* if Data string does not end at word boundery add one byte */ + ui32NoWords++; + cPtr[ui32NoWords] = 0; + } + ui16Buffer = ((*(cPtr + 0)) * 256) + (*(cPtr + 1)); + while (ui32NoWords > 0) { + for (iShift = 15; iShift >= 0; iShift--) { + ui64Generator0 = (AccumCRC >> uiRegisterLength); + AccumCRC <<= 1; + ui64Generator0 &= 0x01; + ui64Generator0 = (0 - ui64Generator0); + AccumCRC ^= (ui64Generator1 & ui64Generator0); + } + AccumCRC ^= ui16Buffer; + AccumCRC &= ui64Mask; + ui32NoWords -= 2; + cPtr += 2; + ui16Buffer = ((*(cPtr + 0)) * 256) + (*(cPtr + 1)); + } + return AccumCRC; +} + +uint64_t +checkCRC(unsigned char *cPtr, uint32_t ui32NoWords, uint64_t AccumCRC) +{ + + enum Generators { Ethernet_32 }; + enum Generators Generator; + uint64_t ui64Buffer = AccumCRC; + + Generator = CRC_METHODE; + + switch (Generator) { + case Ethernet_32:{ + /* (ui32NoWords - 4),no need of 4 bytes 0x as + * with shift-register method */ + AccumCRC = + calCRCEthernet32(cPtr, (ui32NoWords - 4), AccumCRC); + break; + } + default:{ + AccumCRC = calCRCword(cPtr, ui32NoWords, AccumCRC); + break; + } + } + + if (calCRCbyte(cPtr, ui32NoWords, ui64Buffer) != AccumCRC) { + printf("\n --- big Endian - small Endian problem --- \n"); + AccumCRC--; + } + + return (AccumCRC); +} + +/** + * insert header and file CRC into data stream + * do CRC check on header and file + * write data stream to disk + */ +int +writeDataStream(int iofd, int notime) +{ + uint64_t ui64FileCRC = 0, ui64HeaderCRC = 0, ui64RegisterMask; + unsigned int uiRegisterLength; + + if (0 != createHeaderImage(notime)) { + return 1; + } + + createCRCParameter(&ui64RegisterMask, &uiRegisterLength); + + /* calculate CRC */ + ui64HeaderCRC = checkCRC(pucFileStream, ui64globalHeaderSize, 0); + *(uint64_t *) (pucFileStream + ui64globalHeaderSize - 8) = + cpu_to_be64(ui64HeaderCRC); + + ui64FileCRC = checkCRC(pucFileStream, ui64globalFileSize, 0); + *(uint64_t *) (pucFileStream + ui64globalFileSize - 8) = + cpu_to_be64(ui64FileCRC); + + /* check CRC-implementation */ + ui64HeaderCRC = calCRCword(pucFileStream, ui64globalHeaderSize, 0); + ui64FileCRC = calCRCword(pucFileStream, ui64globalFileSize, 0); + + if ((ui64HeaderCRC != 0) || (ui64FileCRC != 0)) { + printf("\n\n %s \n %s \n\n", "CRCs not correct implemented.", + " ---> Data will not be written do disk."); + return -1; + } + + /* write file image to disk */ + if (0 < write(iofd, pucFileStream, ui64globalFileSize)) + return 0; + + printf("<< write failed >>\n"); + return -1; +} diff --git a/romfs/tools/create_flash.c b/romfs/tools/create_flash.c new file mode 100644 index 0000000..f99fd62 --- /dev/null +++ b/romfs/tools/create_flash.c @@ -0,0 +1,163 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +int verbose = 0; + +#define dprintf(fmt, args...) if (verbose) printf(fmt, ##args) + +static void +print_usage(void) +{ + printf + ("Usage: build_romfs [-?] [--help] [-s|--romfs-size ]\n" + "\t[-p|--smart-pad] [-n|--notime] \n"); +} + +unsigned long +str_to_num(const char *str) +{ + char *s = (char *) str; + unsigned long num = strtoul(s, &s, 0); + if (s) { + if (s[0] == 'K') + num <<= 10; + if (s[0] == 'M') + num <<= 20; + } + return num; +} + +/* + * NOTE: We should consider to install an exit handler which does the + * unlink() of the output file. In case of error we just do exit() and + * forget about all the clumsy error handling free/close code, which + * blows up the code significantly and makes it hard to read. + */ +int +main(int argc, char *argv[]) +{ + int conf_file, rc; + struct ffs_chain_t ffs_chain; + int c; + int smart_pad = 0; /* default */ + int notime = 0; + const char *config_file = "boot_rom.ffs"; + const char *output_file = "boot_rom.bin"; + + memset((void *) &ffs_chain, 0, sizeof(struct ffs_chain_t)); + + while (1) { + int option_index = 0; + static struct option long_options[] = { + {"romfs-size", 1, 0, 's'}, + {"smart-pad", 0, 0, 'p'}, + {"notime", 0, 0, 'n'}, + {"verbose", 0, 0, 'v'}, + {"help", 1, 0, 'h'}, + {0, 0, 0, 0} + }; + c = getopt_long(argc, argv, "s:ph?nv", long_options, + &option_index); + if (c == -1) + break; + + switch (c) { + case 's': + ffs_chain.romfs_size = str_to_num(optarg); + break; + case 'p': + smart_pad = 1; + break; + case 'n': + notime = 1; + break; + case 'v': + verbose = 1; + break; + case '?': + case 'h': + print_usage(); + return EXIT_SUCCESS; + default: + printf("?? getopt returned character code 0%o ??\n", c); + } + } + + /* two files must always be specified: config-file and output-file */ + if (optind + 2 != argc) { + print_usage(); + return EXIT_FAILURE; + } + + config_file = argv[optind++]; + output_file = argv[optind++]; + + dprintf("ROMFS FILESYSTEM CREATION V0.3 (bad parser)\n" + "Build directory structure...\n" + " smart padding %s, maximum romfs size %d bytes\n", + smart_pad ? "enabled" : "disabled", ffs_chain.romfs_size); + + conf_file = open(config_file, O_RDONLY); + if (0 >= conf_file) { + perror("load config file:"); + return EXIT_FAILURE; + } + + rc = read_config(conf_file, &ffs_chain); + close(conf_file); + if (rc < 1) { + fprintf(stderr, "flash cannot be built due to config errors\n"); + return EXIT_FAILURE; + } + + rc = EXIT_SUCCESS; + + if (verbose) + dump_fs_contents(&ffs_chain); + if (smart_pad) + /* FIXME: size is only verified during reorder */ + rc = reorder_ffs_chain(&ffs_chain); + + if (rc == EXIT_FAILURE) + goto out; + + dprintf("Build ffs and write to image file...\n"); + if (build_ffs(&ffs_chain, output_file, notime) != 0) { + fprintf(stderr, "build ffs failed\n"); + rc = EXIT_FAILURE; + } else { + rc = EXIT_SUCCESS; + } + + /* Check if there are any duplicate entries in the image, + print warning if this is the case. */ + find_duplicates(&ffs_chain); + free_chain_memory(&ffs_chain); + dprintf("\n"); + + out: + /* If the build failed, remove the target image file */ + if (rc == EXIT_FAILURE) + unlink(output_file); + + return rc; +} diff --git a/romfs/tools/createcrc.h b/romfs/tools/createcrc.h new file mode 100644 index 0000000..1f23598 --- /dev/null +++ b/romfs/tools/createcrc.h @@ -0,0 +1,19 @@ +/****************************************************************************** + * Copyright (c) 2004, 2008 IBM Corporation + * All rights reserved. + * This program and the accompanying materials + * are made available under the terms of the BSD License + * which accompanies this distribution, and is available at + * http://www.opensource.org/licenses/bsd-license.php + * + * Contributors: + * IBM Corporation - initial implementation + *****************************************************************************/ +#ifndef CREATECRC_H +#define CREATECRC_H + +int buildDataStream(unsigned char *pucbuf, int size); +int createHeaderImgage(char *pcFilename); +int writeDataStream(int ofd, int notime); + +#endif -- cgit v1.1