FreeCalypso > hg > freecalypso-reveng
diff mpffs/common.c @ 29:e96d6862cec0
mpffs-rdutils code started
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 30 Jun 2013 05:16:23 +0000 |
parents | |
children | 9c3c5a572b57 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mpffs/common.c Sun Jun 30 05:16:23 2013 +0000 @@ -0,0 +1,264 @@ +/* + * This module contains the code that will be common between mpffs-cat, + * mpffs-ls and mpffs-xtr. + */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <endian.h> +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <unistd.h> +#include "types.h" +#include "struct.h" + +u8 mpffs_header[6] = {'F', 'f', 's', '#', 0x10, 0x02}; + +char *imgfile; +u32 eraseblk_size; +int total_blocks; +u32 total_ffs_size; +u8 *image, *indexblk; +int index_blk_num, root_node_no; +int verbose; + +/* + * The following function is used to verify that the specified or computed + * flash erase block size is a power of 2. + */ +count_ones(word) + u32 word; +{ + int count; + + for (count = 0; word; word >>= 1) + count += word & 1; + return count; +} + +eraseblk_size_reasonable() +{ + if (count_ones(eraseblk_size) != 1 || eraseblk_size < 16384) { + fprintf(stderr, "0x%lx is an unreasonable erase block size\n", + (u_long) eraseblk_size); + exit(1); + } +} + +read_img_file() +{ + int fd; + struct stat st; + + fd = open(imgfile, O_RDONLY); + if (fd < 0) { + perror(imgfile); + exit(1); + } + fstat(fd, &st); + if (!S_ISREG(st.st_mode)) { + fprintf(stderr, "%s is not a regular file\n", imgfile); + exit(1); + } + if (!eraseblk_size && !total_blocks) { + switch (st.st_size) { + case 0x70000: + /* assume Closedmoko */ + eraseblk_size = 0x10000; + total_blocks = 7; + break; + case 0x480000: + /* assume Pirelli */ + eraseblk_size = 0x40000; + total_blocks = 18; + break; + default: +noauto: fprintf(stderr, + "cannot intuit the flash parameters of %s: use -e and -n options\n", + imgfile); + exit(1); + } + } else if (!total_blocks) { + total_blocks = st.st_size / eraseblk_size; + if (!total_blocks || total_blocks * eraseblk_size != st.st_size) + goto noauto; + } else if (!eraseblk_size) { + if (total_blocks * 0x10000 == st.st_size) + eraseblk_size = 0x10000; + else if (total_blocks * 0x40000 == st.st_size) + eraseblk_size = 0x40000; + else + goto noauto; + } + total_ffs_size = eraseblk_size * total_blocks; + if (st.st_size < total_ffs_size) { + fprintf(stderr, "%s has fewer than 0x%x bytes\n", imgfile, + total_ffs_size); + exit(1); + } + image = malloc(total_ffs_size); + if (!image) { + perror("malloc"); + exit(1); + } + read(fd, image, total_ffs_size); + close(fd); +} + +find_index_block() +{ + int i, abcnt; + u8 *ptr; + + if (index_blk_num) { + if (index_blk_num < 0 || index_blk_num >= total_blocks) { + fprintf(stderr, + "invalid block # given with the -a option\n"); + exit(1); + } + ptr = image + index_blk_num * eraseblk_size; + if (bcmp(ptr, mpffs_header, 6) || ptr[8] != 0xAB) { + fprintf(stderr, + "no MPFFS index found at the specified block #%d\n", + index_blk_num); + exit(1); + } + indexblk = ptr; + return(0); + } + abcnt = 0; + for (ptr = image, i = 0; i < total_blocks; i++, ptr += eraseblk_size) { + if (bcmp(ptr, mpffs_header, 6)) { + fprintf(stderr, + "warning: no MPFFS signature in erase block #%d (offset %x)\n", + i, ptr - image); + continue; + } + switch (ptr[8]) { + case 0xAB: + if (verbose) + printf( + "Found AB index in erase block #%d (offset %x)\n", + i, ptr - image); + index_blk_num = i; + indexblk = ptr; + abcnt++; + continue; + case 0xBD: + case 0xBF: + continue; + } + fprintf(stderr, + "warning: non-understood block type %02X at offset %x\n", + ptr[8], ptr - image); + } + if (!indexblk) { + fprintf(stderr, "could not find an MPFFS index block in %s\n", + imgfile); + exit(1); + } + if (abcnt > 1) { + fprintf(stderr, "found more than one AB block; use -a\n"); + exit(1); + } + return(0); +} + +get_index_entry(oi) + struct objinfo *oi; +{ + struct mpffs_index *le; + + if (oi->entryno >= (eraseblk_size >> 4)) { + fprintf(stderr, + "error: index block pointer %x past the erase block size!\n", + oi->entryno); + exit(1); + } + le = (struct mpffs_index *) indexblk + oi->entryno; + oi->idxrec = le; + oi->len = le16toh(le->len); + oi->type = le->type; + oi->descend = le16toh(le->descend); + oi->sibling = le16toh(le->sibling); + return(0); +} + +validate_chunk(oi) + struct objinfo *oi; +{ + u32 dptr; + + if (oi->len & 0xF || !oi->len) { + fprintf(stderr, "index entry #%x: invalid chunk length\n", + oi->entryno); + exit(1); + } + dptr = le32toh(oi->idxrec->dataptr); + if (dptr > 0x0FFFFFFF) { +invdptr: fprintf(stderr, "index entry #%x: invalid data pointer\n", + oi->entryno); + exit(1); + } + dptr <<= 4; + if (dptr >= total_img_size - oi->len) + goto invdptr; + oi->offset = dptr; + oi->dataptr = image + dptr; + return(0); +} + +validate_obj_name(oi) + struct objinfo *oi; +{ + u8 *cp; + int cnt; + + for (cp = oi->dataptr, cnt = 0; ; cp++, cnt++) { + if (cnt >= oi->len) { + fprintf(stderr, + "object at index %x: name expected at %x: length overrun\n", + oi->entryno, oi->offset); + exit(1); + } + if (!*cp) + break; + if (*cp < '!' || *cp > '~') { + fprintf(stderr, + "object at index %x: name expected at %x: bad character\n", + oi->entryno, oi->offset); + exit(1); + } + } + if (!cnt) { + fprintf(stderr, + "object at index %x: name expected at %x: null string\n", + oi->entryno, oi->offset); + exit(1); + } + return(0); +} + +u8 * +find_end_of_chunk(ch) + struct objinfo *ch; +{ + u8 *p; + int i; + + p = ch->dataptr + ch->len; + for (i = 1; i <= 16; i++) { + if (!p[-i]) + return(p - i); + if (p[-1] != 0xFF) + break; + } + fprintf(stderr, + "chunk starting at %x (index entry %x): no valid termination found\n", + ch->offset, ch->entryno); + exit(1); +}