123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801 |
- /*
- * dumpjffs2.c
- *
- * Copyright (C) 2003 Thomas Gleixner (tglx@linutronix.de)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Overview:
- * This utility dumps the contents of a binary JFFS2 image
- *
- *
- * Bug/ToDo:
- */
- #define PROGRAM_NAME "jffs2dump"
- #include <errno.h>
- #include <stdint.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <time.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/param.h>
- #include <asm/types.h>
- #include <dirent.h>
- #include <mtd/jffs2-user.h>
- #include <endian.h>
- #include <byteswap.h>
- #include <getopt.h>
- #include <crc32.h>
- #include "summary.h"
- #include "common.h"
- #define PAD(x) (((x)+3)&~3)
- /* For outputting a byte-swapped version of the input image. */
- #define cnv_e32(x) ((jint32_t){bswap_32(x.v32)})
- #define cnv_e16(x) ((jint16_t){bswap_16(x.v16)})
- #define t32_backwards(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?bswap_32(__b):__b; })
- #define cpu_to_e32(x) ((jint32_t){t32_backwards(x)})
- // Global variables
- long imglen; // length of image
- char *data; // image data
- static void display_help (int error)
- {
- printf("Usage: %s [OPTION]... INPUTFILE\n"
- "Dump the contents of a binary JFFS2 image.\n\n"
- " -h, --help display this help and exit\n"
- " -V, --version display version information and exit\n"
- " -b, --bigendian image is big endian\n"
- " -l, --littleendian image is little endian\n"
- " -c, --content dump image contents\n"
- " -e, --endianconvert=FNAME convert image endianness, output to file fname\n"
- " -r, --recalccrc recalc name and data crc on endian conversion\n"
- " -d, --datsize=LEN size of data chunks, when oob data in binary image (NAND only)\n"
- " -o, --oobsize=LEN size of oob data chunk in binary image (NAND only)\n"
- " -v, --verbose verbose output\n",
- PROGRAM_NAME);
- exit(error ? EXIT_FAILURE : EXIT_SUCCESS);
- }
- static void display_version (void)
- {
- common_print_version();
- printf("Copyright (C) 2003 Thomas Gleixner \n"
- "\n"
- "%1$s comes with NO WARRANTY\n"
- "to the extent permitted by law.\n"
- "\n"
- "You may redistribute copies of %1$s\n"
- "under the terms of the GNU General Public Licence.\n"
- "See the file `COPYING' for more information.\n",
- PROGRAM_NAME);
- exit(0);
- }
- // Option variables
- int verbose; // verbose output
- char *img; // filename of image
- int dumpcontent; // dump image content
- int target_endian = __BYTE_ORDER; // image endianess
- int convertendian; // convert endianness
- int recalccrc; // recalc name and data crc's on endian conversion
- char cnvfile[256]; // filename for conversion output
- int datsize; // Size of data chunks, when oob data is inside the binary image
- int oobsize; // Size of oob chunks, when oob data is inside the binary image
- static void process_options (int argc, char *argv[])
- {
- int error = 0;
- for (;;) {
- int option_index = 0;
- static const char *short_options = "blce:rd:o:vVh";
- static const struct option long_options[] = {
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {"bigendian", no_argument, 0, 'b'},
- {"littleendian", no_argument, 0, 'l'},
- {"content", no_argument, 0, 'c'},
- {"endianconvert", required_argument, 0, 'e'},
- {"datsize", required_argument, 0, 'd'},
- {"oobsize", required_argument, 0, 'o'},
- {"recalccrc", required_argument, 0, 'r'},
- {"verbose", no_argument, 0, 'v'},
- {0, 0, 0, 0},
- };
- int c = getopt_long(argc, argv, short_options,
- long_options, &option_index);
- if (c == EOF) {
- break;
- }
- switch (c) {
- case 'h':
- display_help(0);
- break;
- case 'V':
- display_version();
- break;
- case 'v':
- verbose = 1;
- break;
- case 'b':
- target_endian = __BIG_ENDIAN;
- break;
- case 'l':
- target_endian = __LITTLE_ENDIAN;
- break;
- case 'c':
- dumpcontent = 1;
- break;
- case 'd':
- datsize = atoi(optarg);
- break;
- case 'o':
- oobsize = atoi(optarg);
- break;
- case 'e':
- convertendian = 1;
- strncpy (cnvfile, optarg, sizeof(cnvfile) - 1);
- cnvfile[sizeof(cnvfile) - 1] = '\0';
- break;
- case 'r':
- recalccrc = 1;
- break;
- case '?':
- error = 1;
- break;
- }
- }
- if ((argc - optind) != 1 || error)
- display_help (error);
- img = argv[optind];
- }
- /*
- * Dump image contents
- */
- static void do_dumpcontent (void)
- {
- char *p = data, *p_free_begin;
- union jffs2_node_union *node;
- int empty = 0, dirty = 0;
- char name[256];
- uint32_t crc;
- uint16_t type;
- int bitchbitmask = 0;
- int obsolete;
- p_free_begin = NULL;
- while ( p < (data + imglen)) {
- node = (union jffs2_node_union*) p;
- /* Skip empty space */
- if (!p_free_begin)
- p_free_begin = p;
- if (je16_to_cpu (node->u.magic) == 0xFFFF && je16_to_cpu (node->u.nodetype) == 0xFFFF) {
- p += 4;
- empty += 4;
- continue;
- }
- if (p != p_free_begin)
- printf("Empty space found from 0x%08zx to 0x%08zx\n", p_free_begin-data, p-data);
- p_free_begin = NULL;
- if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK) {
- if (!bitchbitmask++)
- printf ("Wrong bitmask at 0x%08zx, 0x%04x\n", p - data, je16_to_cpu (node->u.magic));
- p += 4;
- dirty += 4;
- continue;
- }
- bitchbitmask = 0;
- type = je16_to_cpu(node->u.nodetype);
- if ((type & JFFS2_NODE_ACCURATE) != JFFS2_NODE_ACCURATE) {
- obsolete = 1;
- type |= JFFS2_NODE_ACCURATE;
- } else
- obsolete = 0;
- /* Set accurate for CRC check */
- node->u.nodetype = cpu_to_je16(type);
- crc = mtd_crc32 (0, node, sizeof (struct jffs2_unknown_node) - 4);
- if (crc != je32_to_cpu (node->u.hdr_crc)) {
- printf ("Wrong hdr_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->u.hdr_crc), crc);
- p += 4;
- dirty += 4;
- continue;
- }
- switch(je16_to_cpu(node->u.nodetype)) {
- case JFFS2_NODETYPE_INODE:
- printf ("%8s Inode node at 0x%08zx, totlen 0x%08x, #ino %5d, version %5d, isize %8d, csize %8d, dsize %8d, offset %8d\n",
- obsolete ? "Obsolete" : "",
- p - data, je32_to_cpu (node->i.totlen), je32_to_cpu (node->i.ino),
- je32_to_cpu ( node->i.version), je32_to_cpu (node->i.isize),
- je32_to_cpu (node->i.csize), je32_to_cpu (node->i.dsize), je32_to_cpu (node->i.offset));
- crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_inode) - 8);
- if (crc != je32_to_cpu (node->i.node_crc)) {
- printf ("Wrong node_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->i.node_crc), crc);
- p += PAD(je32_to_cpu (node->i.totlen));
- dirty += PAD(je32_to_cpu (node->i.totlen));;
- continue;
- }
- crc = mtd_crc32(0, p + sizeof (struct jffs2_raw_inode), je32_to_cpu(node->i.csize));
- if (crc != je32_to_cpu(node->i.data_crc)) {
- printf ("Wrong data_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->i.data_crc), crc);
- p += PAD(je32_to_cpu (node->i.totlen));
- dirty += PAD(je32_to_cpu (node->i.totlen));;
- continue;
- }
- p += PAD(je32_to_cpu (node->i.totlen));
- break;
- case JFFS2_NODETYPE_DIRENT:
- memcpy (name, node->d.name, node->d.nsize);
- name [node->d.nsize] = 0x0;
- printf ("%8s Dirent node at 0x%08zx, totlen 0x%08x, #pino %5d, version %5d, #ino %8d, nsize %8d, name %s\n",
- obsolete ? "Obsolete" : "",
- p - data, je32_to_cpu (node->d.totlen), je32_to_cpu (node->d.pino),
- je32_to_cpu ( node->d.version), je32_to_cpu (node->d.ino),
- node->d.nsize, name);
- crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_dirent) - 8);
- if (crc != je32_to_cpu (node->d.node_crc)) {
- printf ("Wrong node_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->d.node_crc), crc);
- p += PAD(je32_to_cpu (node->d.totlen));
- dirty += PAD(je32_to_cpu (node->d.totlen));;
- continue;
- }
- crc = mtd_crc32(0, p + sizeof (struct jffs2_raw_dirent), node->d.nsize);
- if (crc != je32_to_cpu(node->d.name_crc)) {
- printf ("Wrong name_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->d.name_crc), crc);
- p += PAD(je32_to_cpu (node->d.totlen));
- dirty += PAD(je32_to_cpu (node->d.totlen));;
- continue;
- }
- p += PAD(je32_to_cpu (node->d.totlen));
- break;
- case JFFS2_NODETYPE_XATTR:
- memcpy(name, node->x.data, node->x.name_len);
- name[node->x.name_len] = '\x00';
- printf ("%8s Xattr node at 0x%08zx, totlen 0x%08x, xid %5d, version %5d, name_len %3d, name %s\n",
- obsolete ? "Obsolete" : "",
- p - data,
- je32_to_cpu (node->x.totlen),
- je32_to_cpu (node->x.xid),
- je32_to_cpu (node->x.version),
- node->x.name_len,
- name);
- crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_xattr) - sizeof (node->x.node_crc));
- if (crc != je32_to_cpu (node->x.node_crc)) {
- printf ("Wrong node_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->x.node_crc), crc);
- p += PAD(je32_to_cpu (node->x.totlen));
- dirty += PAD(je32_to_cpu (node->x.totlen));
- continue;
- }
- crc = mtd_crc32 (0, p + sizeof (struct jffs2_raw_xattr), node->x.name_len + je16_to_cpu (node->x.value_len) + 1);
- if (crc != je32_to_cpu (node->x.data_crc)) {
- printf ("Wrong data_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->x.data_crc), crc);
- p += PAD(je32_to_cpu (node->x.totlen));
- dirty += PAD(je32_to_cpu (node->x.totlen));
- continue;
- }
- p += PAD(je32_to_cpu (node->x.totlen));
- break;
- case JFFS2_NODETYPE_XREF:
- printf ("%8s Xref node at 0x%08zx, totlen 0x%08x, xid %5d, xseqno %5d, #ino %8d\n",
- obsolete ? "Obsolete" : "",
- p - data,
- je32_to_cpu (node->r.totlen),
- je32_to_cpu (node->r.xid),
- je32_to_cpu (node->r.xseqno),
- je32_to_cpu (node->r.ino));
- p += PAD(je32_to_cpu (node->r.totlen));
- break;
- case JFFS2_NODETYPE_SUMMARY: {
- int i;
- struct jffs2_sum_marker * sm;
- printf("%8s Inode Sum node at 0x%08zx, totlen 0x%08x, sum_num %5d, cleanmarker size %5d\n",
- obsolete ? "Obsolete" : "",
- p - data,
- je32_to_cpu (node->s.totlen),
- je32_to_cpu (node->s.sum_num),
- je32_to_cpu (node->s.cln_mkr));
- crc = mtd_crc32 (0, node, sizeof (struct jffs2_raw_summary) - 8);
- if (crc != je32_to_cpu (node->s.node_crc)) {
- printf ("Wrong node_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->s.node_crc), crc);
- p += PAD(je32_to_cpu (node->s.totlen));
- dirty += PAD(je32_to_cpu (node->s.totlen));;
- continue;
- }
- crc = mtd_crc32(0, p + sizeof (struct jffs2_raw_summary), je32_to_cpu (node->s.totlen) - sizeof(struct jffs2_raw_summary));
- if (crc != je32_to_cpu(node->s.sum_crc)) {
- printf ("Wrong data_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->s.sum_crc), crc);
- p += PAD(je32_to_cpu (node->s.totlen));
- dirty += PAD(je32_to_cpu (node->s.totlen));;
- continue;
- }
- if (verbose) {
- void *sp;
- sp = (p + sizeof(struct jffs2_raw_summary));
- for(i=0; i<je32_to_cpu(node->s.sum_num); i++) {
- switch(je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) {
- case JFFS2_NODETYPE_INODE : {
- struct jffs2_sum_inode_flash *spi;
- spi = sp;
- printf ("%14s #ino %5d, version %5d, offset 0x%08x, totlen 0x%08x\n",
- "",
- je32_to_cpu (spi->inode),
- je32_to_cpu (spi->version),
- je32_to_cpu (spi->offset),
- je32_to_cpu (spi->totlen));
- sp += JFFS2_SUMMARY_INODE_SIZE;
- break;
- }
- case JFFS2_NODETYPE_DIRENT : {
- char name[255];
- struct jffs2_sum_dirent_flash *spd;
- spd = sp;
- memcpy(name,spd->name,spd->nsize);
- name [spd->nsize] = 0x0;
- printf ("%14s dirent offset 0x%08x, totlen 0x%08x, #pino %5d, version %5d, #ino %8d, nsize %8d, name %s \n",
- "",
- je32_to_cpu (spd->offset),
- je32_to_cpu (spd->totlen),
- je32_to_cpu (spd->pino),
- je32_to_cpu (spd->version),
- je32_to_cpu (spd->ino),
- spd->nsize,
- name);
- sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize);
- break;
- }
- case JFFS2_NODETYPE_XATTR : {
- struct jffs2_sum_xattr_flash *spx;
- spx = sp;
- printf ("%14s Xattr offset 0x%08x, totlen 0x%08x, version %5d, #xid %8d\n",
- "",
- je32_to_cpu (spx->offset),
- je32_to_cpu (spx->totlen),
- je32_to_cpu (spx->version),
- je32_to_cpu (spx->xid));
- sp += JFFS2_SUMMARY_XATTR_SIZE;
- break;
- }
- case JFFS2_NODETYPE_XREF : {
- struct jffs2_sum_xref_flash *spr;
- spr = sp;
- printf ("%14s Xref offset 0x%08x\n",
- "",
- je32_to_cpu (spr->offset));
- sp += JFFS2_SUMMARY_XREF_SIZE;
- break;
- }
- default :
- printf("Unknown summary node!\n");
- break;
- }
- }
- sm = (struct jffs2_sum_marker *) ((char *)p + je32_to_cpu(node->s.totlen) - sizeof(struct jffs2_sum_marker));
- printf("%14s Sum Node Offset 0x%08x, Magic 0x%08x, Padded size 0x%08x\n",
- "",
- je32_to_cpu(sm->offset),
- je32_to_cpu(sm->magic),
- je32_to_cpu(node->s.padded));
- }
- p += PAD(je32_to_cpu (node->s.totlen));
- break;
- }
- case JFFS2_NODETYPE_CLEANMARKER:
- if (verbose) {
- printf ("%8s Cleanmarker at 0x%08zx, totlen 0x%08x\n",
- obsolete ? "Obsolete" : "",
- p - data, je32_to_cpu (node->u.totlen));
- }
- p += PAD(je32_to_cpu (node->u.totlen));
- break;
- case JFFS2_NODETYPE_PADDING:
- if (verbose) {
- printf ("%8s Padding node at 0x%08zx, totlen 0x%08x\n",
- obsolete ? "Obsolete" : "",
- p - data, je32_to_cpu (node->u.totlen));
- }
- p += PAD(je32_to_cpu (node->u.totlen));
- break;
- case 0xffff:
- p += 4;
- empty += 4;
- break;
- default:
- if (verbose) {
- printf ("%8s Unknown node at 0x%08zx, totlen 0x%08x\n",
- obsolete ? "Obsolete" : "",
- p - data, je32_to_cpu (node->u.totlen));
- }
- p += PAD(je32_to_cpu (node->u.totlen));
- dirty += PAD(je32_to_cpu (node->u.totlen));
- }
- }
- if (verbose)
- printf ("Empty space: %d, dirty space: %d\n", empty, dirty);
- }
- /*
- * Convert endianess
- */
- static void do_endianconvert (void)
- {
- char *p = data;
- union jffs2_node_union *node, newnode;
- int fd, len;
- jint32_t mode;
- uint32_t crc;
- fd = open (cnvfile, O_WRONLY | O_CREAT, 0644);
- if (fd < 0) {
- fprintf (stderr, "Cannot open / create file: %s\n", cnvfile);
- return;
- }
- while ( p < (data + imglen)) {
- node = (union jffs2_node_union*) p;
- /* Skip empty space */
- if (je16_to_cpu (node->u.magic) == 0xFFFF && je16_to_cpu (node->u.nodetype) == 0xFFFF) {
- write_nocheck (fd, p, 4);
- p += 4;
- continue;
- }
- if (je16_to_cpu (node->u.magic) != JFFS2_MAGIC_BITMASK) {
- printf ("Wrong bitmask at 0x%08zx, 0x%04x\n", p - data, je16_to_cpu (node->u.magic));
- newnode.u.magic = cnv_e16 (node->u.magic);
- newnode.u.nodetype = cnv_e16 (node->u.nodetype);
- write_nocheck (fd, &newnode, 4);
- p += 4;
- continue;
- }
- crc = mtd_crc32 (0, node, sizeof (struct jffs2_unknown_node) - 4);
- if (crc != je32_to_cpu (node->u.hdr_crc)) {
- printf ("Wrong hdr_crc at 0x%08zx, 0x%08x instead of 0x%08x\n", p - data, je32_to_cpu (node->u.hdr_crc), crc);
- }
- switch(je16_to_cpu(node->u.nodetype)) {
- case JFFS2_NODETYPE_INODE:
- newnode.i.magic = cnv_e16 (node->i.magic);
- newnode.i.nodetype = cnv_e16 (node->i.nodetype);
- newnode.i.totlen = cnv_e32 (node->i.totlen);
- newnode.i.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
- newnode.i.ino = cnv_e32 (node->i.ino);
- newnode.i.version = cnv_e32 (node->i.version);
- mode.v32 = node->i.mode.m;
- mode = cnv_e32 (mode);
- newnode.i.mode.m = mode.v32;
- newnode.i.uid = cnv_e16 (node->i.uid);
- newnode.i.gid = cnv_e16 (node->i.gid);
- newnode.i.isize = cnv_e32 (node->i.isize);
- newnode.i.atime = cnv_e32 (node->i.atime);
- newnode.i.mtime = cnv_e32 (node->i.mtime);
- newnode.i.ctime = cnv_e32 (node->i.ctime);
- newnode.i.offset = cnv_e32 (node->i.offset);
- newnode.i.csize = cnv_e32 (node->i.csize);
- newnode.i.dsize = cnv_e32 (node->i.dsize);
- newnode.i.compr = node->i.compr;
- newnode.i.usercompr = node->i.usercompr;
- newnode.i.flags = cnv_e16 (node->i.flags);
- if (recalccrc) {
- len = je32_to_cpu(node->i.csize);
- newnode.i.data_crc = cpu_to_e32 ( mtd_crc32(0, p + sizeof (struct jffs2_raw_inode), len));
- } else
- newnode.i.data_crc = cnv_e32 (node->i.data_crc);
- newnode.i.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_inode) - 8));
- write_nocheck (fd, &newnode, sizeof (struct jffs2_raw_inode));
- write_nocheck (fd, p + sizeof (struct jffs2_raw_inode), PAD (je32_to_cpu (node->i.totlen) - sizeof (struct jffs2_raw_inode)));
- p += PAD(je32_to_cpu (node->i.totlen));
- break;
- case JFFS2_NODETYPE_DIRENT:
- newnode.d.magic = cnv_e16 (node->d.magic);
- newnode.d.nodetype = cnv_e16 (node->d.nodetype);
- newnode.d.totlen = cnv_e32 (node->d.totlen);
- newnode.d.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
- newnode.d.pino = cnv_e32 (node->d.pino);
- newnode.d.version = cnv_e32 (node->d.version);
- newnode.d.ino = cnv_e32 (node->d.ino);
- newnode.d.mctime = cnv_e32 (node->d.mctime);
- newnode.d.nsize = node->d.nsize;
- newnode.d.type = node->d.type;
- newnode.d.unused[0] = node->d.unused[0];
- newnode.d.unused[1] = node->d.unused[1];
- newnode.d.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_dirent) - 8));
- if (recalccrc)
- newnode.d.name_crc = cpu_to_e32 ( mtd_crc32(0, p + sizeof (struct jffs2_raw_dirent), node->d.nsize));
- else
- newnode.d.name_crc = cnv_e32 (node->d.name_crc);
- write_nocheck (fd, &newnode, sizeof (struct jffs2_raw_dirent));
- write_nocheck (fd, p + sizeof (struct jffs2_raw_dirent), PAD (je32_to_cpu (node->d.totlen) - sizeof (struct jffs2_raw_dirent)));
- p += PAD(je32_to_cpu (node->d.totlen));
- break;
- case JFFS2_NODETYPE_XATTR:
- newnode.x.magic = cnv_e16 (node->x.magic);
- newnode.x.nodetype = cnv_e16 (node->x.nodetype);
- newnode.x.totlen = cnv_e32 (node->x.totlen);
- newnode.x.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
- newnode.x.xid = cnv_e32 (node->x.xid);
- newnode.x.version = cnv_e32 (node->x.version);
- newnode.x.xprefix = node->x.xprefix;
- newnode.x.name_len = node->x.name_len;
- newnode.x.value_len = cnv_e16 (node->x.value_len);
- if (recalccrc)
- newnode.x.data_crc = cpu_to_e32 (mtd_crc32 (0, p + sizeof (struct jffs2_raw_xattr), node->x.name_len + je16_to_cpu (node->x.value_len) + 1));
- else
- newnode.x.data_crc = cnv_e32 (node->x.data_crc);
- newnode.x.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_xattr) - sizeof (newnode.x.node_crc)));
- write_nocheck (fd, &newnode, sizeof (struct jffs2_raw_xattr));
- write_nocheck (fd, p + sizeof (struct jffs2_raw_xattr), PAD (je32_to_cpu (node->d.totlen) - sizeof (struct jffs2_raw_xattr)));
- p += PAD(je32_to_cpu (node->x.totlen));
- break;
- case JFFS2_NODETYPE_XREF:
- newnode.r.magic = cnv_e16 (node->r.magic);
- newnode.r.nodetype = cnv_e16 (node->r.nodetype);
- newnode.r.totlen = cnv_e32 (node->r.totlen);
- newnode.r.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - sizeof (newnode.r.hdr_crc)));
- newnode.r.ino = cnv_e32 (node->r.ino);
- newnode.r.xid = cnv_e32 (node->r.xid);
- newnode.r.xseqno = cnv_e32 (node->r.xseqno);
- newnode.r.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_xref) - sizeof (newnode.r.node_crc)));
- p += PAD(je32_to_cpu (node->x.totlen));
- break;
- case JFFS2_NODETYPE_CLEANMARKER:
- case JFFS2_NODETYPE_PADDING:
- newnode.u.magic = cnv_e16 (node->u.magic);
- newnode.u.nodetype = cnv_e16 (node->u.nodetype);
- newnode.u.totlen = cnv_e32 (node->u.totlen);
- newnode.u.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
- write_nocheck (fd, &newnode, sizeof (struct jffs2_unknown_node));
- len = PAD(je32_to_cpu (node->u.totlen) - sizeof (struct jffs2_unknown_node));
- if (len > 0)
- write_nocheck (fd, p + sizeof (struct jffs2_unknown_node), len);
- p += PAD(je32_to_cpu (node->u.totlen));
- break;
- case JFFS2_NODETYPE_SUMMARY : {
- struct jffs2_sum_marker *sm_ptr;
- int i,sum_len;
- int counter = 0;
- newnode.s.magic = cnv_e16 (node->s.magic);
- newnode.s.nodetype = cnv_e16 (node->s.nodetype);
- newnode.s.totlen = cnv_e32 (node->s.totlen);
- newnode.s.hdr_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_unknown_node) - 4));
- newnode.s.sum_num = cnv_e32 (node->s.sum_num);
- newnode.s.cln_mkr = cnv_e32 (node->s.cln_mkr);
- newnode.s.padded = cnv_e32 (node->s.padded);
- newnode.s.node_crc = cpu_to_e32 (mtd_crc32 (0, &newnode, sizeof (struct jffs2_raw_summary) - 8));
- // summary header
- p += sizeof (struct jffs2_raw_summary);
- // summary data
- sum_len = je32_to_cpu (node->s.totlen) - sizeof (struct jffs2_raw_summary) - sizeof (struct jffs2_sum_marker);
- for (i=0; i<je32_to_cpu (node->s.sum_num); i++) {
- union jffs2_sum_flash *fl_ptr;
- fl_ptr = (union jffs2_sum_flash *) p;
- switch (je16_to_cpu (fl_ptr->u.nodetype)) {
- case JFFS2_NODETYPE_INODE:
- fl_ptr->i.nodetype = cnv_e16 (fl_ptr->i.nodetype);
- fl_ptr->i.inode = cnv_e32 (fl_ptr->i.inode);
- fl_ptr->i.version = cnv_e32 (fl_ptr->i.version);
- fl_ptr->i.offset = cnv_e32 (fl_ptr->i.offset);
- fl_ptr->i.totlen = cnv_e32 (fl_ptr->i.totlen);
- p += sizeof (struct jffs2_sum_inode_flash);
- counter += sizeof (struct jffs2_sum_inode_flash);
- break;
- case JFFS2_NODETYPE_DIRENT:
- fl_ptr->d.nodetype = cnv_e16 (fl_ptr->d.nodetype);
- fl_ptr->d.totlen = cnv_e32 (fl_ptr->d.totlen);
- fl_ptr->d.offset = cnv_e32 (fl_ptr->d.offset);
- fl_ptr->d.pino = cnv_e32 (fl_ptr->d.pino);
- fl_ptr->d.version = cnv_e32 (fl_ptr->d.version);
- fl_ptr->d.ino = cnv_e32 (fl_ptr->d.ino);
- p += sizeof (struct jffs2_sum_dirent_flash) + fl_ptr->d.nsize;
- counter += sizeof (struct jffs2_sum_dirent_flash) + fl_ptr->d.nsize;
- break;
- case JFFS2_NODETYPE_XATTR:
- fl_ptr->x.nodetype = cnv_e16 (fl_ptr->x.nodetype);
- fl_ptr->x.xid = cnv_e32 (fl_ptr->x.xid);
- fl_ptr->x.version = cnv_e32 (fl_ptr->x.version);
- fl_ptr->x.offset = cnv_e32 (fl_ptr->x.offset);
- fl_ptr->x.totlen = cnv_e32 (fl_ptr->x.totlen);
- p += sizeof (struct jffs2_sum_xattr_flash);
- counter += sizeof (struct jffs2_sum_xattr_flash);
- break;
- case JFFS2_NODETYPE_XREF:
- fl_ptr->r.nodetype = cnv_e16 (fl_ptr->r.nodetype);
- fl_ptr->r.offset = cnv_e32 (fl_ptr->r.offset);
- p += sizeof (struct jffs2_sum_xref_flash);
- counter += sizeof (struct jffs2_sum_xref_flash);
- break;
- default :
- printf("Unknown node in summary information!!! nodetype(%x)\n", je16_to_cpu (fl_ptr->u.nodetype));
- exit(EXIT_FAILURE);
- break;
- }
- }
- //pad
- p += sum_len - counter;
- // summary marker
- sm_ptr = (struct jffs2_sum_marker *) p;
- sm_ptr->offset = cnv_e32 (sm_ptr->offset);
- sm_ptr->magic = cnv_e32 (sm_ptr->magic);
- p += sizeof (struct jffs2_sum_marker);
- // generate new crc on sum data
- newnode.s.sum_crc = cpu_to_e32 ( mtd_crc32(0, ((char *) node) + sizeof (struct jffs2_raw_summary),
- je32_to_cpu (node->s.totlen) - sizeof (struct jffs2_raw_summary)));
- // write out new node header
- write_nocheck(fd, &newnode, sizeof (struct jffs2_raw_summary));
- // write out new summary data
- write_nocheck(fd, &node->s.sum, sum_len + sizeof (struct jffs2_sum_marker));
- break;
- }
- case 0xffff:
- write_nocheck (fd, p, 4);
- p += 4;
- break;
- default:
- printf ("Unknown node type: 0x%04x at 0x%08zx, totlen 0x%08x\n", je16_to_cpu (node->u.nodetype), p - data, je32_to_cpu (node->u.totlen));
- p += PAD(je32_to_cpu (node->u.totlen));
- }
- }
- close (fd);
- }
- /*
- * Main program
- */
- int main(int argc, char **argv)
- {
- int fd;
- process_options(argc, argv);
- /* Open the input file */
- if ((fd = open(img, O_RDONLY)) == -1) {
- perror("open input file");
- exit(EXIT_FAILURE);
- }
- // get image length
- imglen = lseek(fd, 0, SEEK_END);
- lseek (fd, 0, SEEK_SET);
- data = malloc (imglen);
- if (!data) {
- perror("out of memory");
- close (fd);
- exit(EXIT_FAILURE);
- }
- if (datsize && oobsize) {
- int idx = 0;
- long len = imglen;
- uint8_t oob[oobsize];
- printf ("Peeling data out of combined data/oob image\n");
- while (len) {
- // read image data
- read_nocheck (fd, &data[idx], datsize);
- read_nocheck (fd, oob, oobsize);
- idx += datsize;
- imglen -= oobsize;
- len -= datsize + oobsize;
- }
- } else {
- // read image data
- read_nocheck (fd, data, imglen);
- }
- // Close the input file
- close(fd);
- if (dumpcontent)
- do_dumpcontent ();
- if (convertendian)
- do_endianconvert ();
- // free memory
- free (data);
- // Return happy
- exit (EXIT_SUCCESS);
- }
|