FreeCalypso > hg > freecalypso-reveng
diff mpffs/common.c @ 30:9c3c5a572b57
mpffs-ls works with the length code stubbed out
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 30 Jun 2013 06:28:58 +0000 |
parents | e96d6862cec0 |
children | 3cca8070ef0f |
line wrap: on
line diff
--- a/mpffs/common.c Sun Jun 30 05:16:23 2013 +0000 +++ b/mpffs/common.c Sun Jun 30 06:28:58 2013 +0000 @@ -17,13 +17,16 @@ #include "struct.h" u8 mpffs_header[6] = {'F', 'f', 's', '#', 0x10, 0x02}; +u8 blank_flash_line[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; char *imgfile; u32 eraseblk_size; int total_blocks; u32 total_ffs_size; u8 *image, *indexblk; -int index_blk_num, root_node_no; +int index_blk_num = -1, root_node_no; +struct objinfo root; int verbose; /* @@ -42,13 +45,58 @@ eraseblk_size_reasonable() { - if (count_ones(eraseblk_size) != 1 || eraseblk_size < 16384) { + if (count_ones(eraseblk_size) != 1 || eraseblk_size < 16384 || + eraseblk_size > 0x100000) { fprintf(stderr, "0x%lx is an unreasonable erase block size\n", (u_long) eraseblk_size); exit(1); } } +parse_cmdline_options(argc, argv) + char **argv; +{ + extern char *optarg; + int c; + + while ((c = getopt(argc, argv, "a:e:mn:pr:v")) != EOF) + switch (c) { + case 'a': + index_blk_num = atoi(optarg); + continue; + case 'e': + eraseblk_size = strtoul(optarg, 0, 0); + eraseblk_size_reasonable(); + continue; + case 'm': /* "moko" */ + eraseblk_size = 0x10000; + total_blocks = 7; + continue; + case 'n': + total_blocks = atoi(optarg); + if (total_blocks < 1) { + fprintf(stderr, "invalid -n value\n"); + exit(1); + } + continue; + case 'p': /* Pirelli */ + eraseblk_size = 0x40000; + total_blocks = 18; + continue; + case 'r': + root_node_no = atoi(optarg); + continue; + case 'v': + verbose++; + continue; + default: + usage(); + exit(1); + } + + return(0); +} + read_img_file() { int fd; @@ -114,8 +162,8 @@ int i, abcnt; u8 *ptr; - if (index_blk_num) { - if (index_blk_num < 0 || index_blk_num >= total_blocks) { + if (index_blk_num >= 0) { + if (index_blk_num >= total_blocks) { fprintf(stderr, "invalid block # given with the -a option\n"); exit(1); @@ -205,7 +253,7 @@ exit(1); } dptr <<= 4; - if (dptr >= total_img_size - oi->len) + if (dptr > total_ffs_size - oi->len) goto invdptr; oi->offset = dptr; oi->dataptr = image + dptr; @@ -262,3 +310,64 @@ ch->offset, ch->entryno); exit(1); } + +find_root_node() +{ + struct objinfo obj; + u16 lim; + + lim = (eraseblk_size >> 4) - 1; + if (root_node_no) { + if (root_node_no < 1 || root_node_no > lim) { + fprintf(stderr, + "root node # given with -r is invalid\n"); + exit(1); + } + return(1); + } + for (obj.entryno = 1; obj.entryno <= lim; obj.entryno++) { + get_index_entry(&obj); + if (!bcmp(obj.idxrec, blank_flash_line, 16)) + break; + if (obj.type != 0xF2) + continue; + validate_chunk(&obj); + validate_obj_name(&obj); + if (*obj.dataptr != '/') + continue; + root_node_no = obj.entryno; + if (verbose) + printf("Found root node at index #%x\n", root_node_no); + return(0); + } + fprintf(stderr, "error: no root node found (try -r)\n"); + exit(1); +} + +validate_root_node() +{ + root.entryno = root_node_no; + get_index_entry(&root); + validate_chunk(&root); + validate_obj_name(&root); + if (verbose) + printf("Root node name: %s\n", (char *)root.dataptr); + if (root.type != 0xF2) { + fprintf(stderr, + "error: index entry #%x (expected root dir) is not a directory\n", + root_node_no); + exit(1); + } + if (root.sibling != 0xFFFF) + fprintf(stderr, + "warning: root entry has a non-nil sibling pointer\n"); + return(0); +} + +preliminaries() +{ + read_img_file(); + find_index_block(); + find_root_node(); + validate_root_node(); +}