From f299486ef9ee5531ebee567211eb7861ae7a93bf Mon Sep 17 00:00:00 2001 From: pancake Date: Sat, 2 Jun 2007 02:23:58 +0200 Subject: * Covardly copy the nanddump() function from the mtd-utils to fix dump functionality - The new function works like the old rf_extract one, no parameters has changed. - Now a complete dump/restore will be possible. - Check for badblocks while copying data - Shows information about the partition * Better use of query_error_message() for debugging --- src/Makefile | 2 +- src/dump.c | 317 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/flash.c | 39 ++++--- src/mtd/ftl-user.h | 76 ++++++++++++ src/mtd/inftl-user.h | 91 +++++++++++++++ src/mtd/jffs2-user.h | 82 +++++++++++++ src/mtd/mtd-abi.h | 158 +++++++++++++++++++++++++ src/mtd/mtd-user.h | 21 ++++ src/mtd/nftl-user.h | 76 ++++++++++++ 9 files changed, 826 insertions(+), 36 deletions(-) create mode 100644 src/mtd/ftl-user.h create mode 100644 src/mtd/inftl-user.h create mode 100644 src/mtd/jffs2-user.h create mode 100644 src/mtd/mtd-abi.h create mode 100644 src/mtd/mtd-user.h create mode 100644 src/mtd/nftl-user.h diff --git a/src/Makefile b/src/Makefile index 71c8396..c495117 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,7 @@ VERSION=0.2 OBJ=main.o fiasco.o hexdump.o dump.o flash.o OBJ+=hash.o fpid.o query.o pieces.o utils.o devices.o BIN=0xFFFF -CFLAGS+=-DVERSION=\"${VERSION}\" -Wall -g +CFLAGS+=-DVERSION=\"${VERSION}\" -Wall -g -I . all: ${OBJ} ${CC} ${LDFLAGS} -o ${BIN} ${OBJ} -lusb diff --git a/src/dump.c b/src/dump.c index b286fe3..5c29c4a 100644 --- a/src/dump.c +++ b/src/dump.c @@ -24,6 +24,13 @@ #include #include +/* + * Extracts a piece from an mtd device + * ----------------------------------- + * This function is known to be buggy, It does not takes care about + * badblocks and oob data. It is replaced by nanddump(), but will + * probably be fixed in the future or it will die. + */ int rf_extract(char *dev, off_t from, off_t to, char *file) { off_t i, blk = 0xfffff; @@ -60,6 +67,272 @@ __rf_extract_exit: return 1; } +/* + * This function was covardly copied from nanddump.c @ mtd-utils-20060907 + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// configuration for nanddump // +int ignoreerrors = 1; // ignore errors +int pretty_print = 0; // print nice in ascii +int noecc = 0; // don't error correct +int omitoob = 1; // omit oob data +int omitbad = 1; +// configuration for nanddump // + +int nanddump(char *mtddev, unsigned long start_addr, unsigned long length, char *dumpfile) +{ + unsigned char readbuf[2048]; + unsigned char oobbuf[64]; + struct nand_oobinfo none_oobinfo = { + .useecc = MTD_NANDECC_OFF, + }; + unsigned long ofs, end_addr = 0; + unsigned long long blockstart = 1; + int i, fd, ofd, bs, badblock = 0; + struct mtd_oob_buf oob = {0, 16, oobbuf}; + mtd_info_t meminfo; + char pretty_buf[80]; + int oobinfochanged = 0 ; + int badblocks = 1; + struct nand_oobinfo old_oobinfo; + struct mtd_ecc_stats stat1, stat2; + int eccstats = 0; + + printf("\nExtracting %s from %s...\n", dumpfile, mtddev); + + /* Open MTD device */ + if ((fd = open(mtddev, O_RDONLY)) == -1) { + perror("open flash"); + return 1; + } + + /* Fill in MTD device capability structure */ + if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { + perror("MEMGETINFO"); + close(fd); + return 1; + } + + /* Make sure device page sizes are valid */ + if (!(meminfo.oobsize == 64 && meminfo.writesize == 2048) && + !(meminfo.oobsize == 16 && meminfo.writesize == 512) && + !(meminfo.oobsize == 8 && meminfo.writesize == 256)) { + fprintf(stderr, "Unknown flash (not normal NAND)\n"); + close(fd); + return 1; + } + /* Read the real oob length */ + oob.length = meminfo.oobsize; + + if (noecc) { + switch (ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW)) { + case -ENOTTY: + if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) { + perror ("MEMGETOOBSEL"); + close (fd); + exit (1); + } + if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) { + perror ("MEMSETOOBSEL"); + close (fd); + exit (1); + } + oobinfochanged = 1; + break; + + case 0: + oobinfochanged = 2; + break; + default: + perror ("MTDFILEMODE"); + close (fd); + return 1; + } + } else { + /* check if we can read ecc stats */ + if (!ioctl(fd, ECCGETSTATS, &stat1)) { + eccstats = 1; + fprintf(stderr, "ECC failed: %d\n", stat1.failed); + fprintf(stderr, "ECC corrected: %d\n", stat1.corrected); + fprintf(stderr, "Number of bad blocks: %d\n", stat1.badblocks); + fprintf(stderr, "Number of bbt blocks: %d\n", stat1.bbtblocks); + } else + perror("No ECC status information available"); + } + + /* Open output file for writing. If file name is "-", write to standard + * output. */ + if (!dumpfile) { + ofd = STDOUT_FILENO; + } else if ((ofd = open(dumpfile, O_WRONLY | O_TRUNC | O_CREAT, 0644))== -1) { + perror ("open outfile"); + close(fd); + return 1; + } + + /* Initialize start/end addresses and block size */ + if (length) + end_addr = start_addr + length; + if (!length || end_addr > meminfo.size) + end_addr = meminfo.size; + + bs = meminfo.writesize; + + /* Print informative message */ + fprintf(stderr, "Block size %u, page size %u, OOB size %u\n", + meminfo.erasesize, meminfo.writesize, meminfo.oobsize); + fprintf(stderr, + "Dumping data starting at 0x%08x and ending at 0x%08x...\n", + (unsigned int) start_addr, (unsigned int) end_addr); + + /* Dump the flash contents */ + for (ofs = start_addr; ofs < end_addr ; ofs+=bs) { + + progressbar(ofs, end_addr); + + // new eraseblock , check for bad block + if (blockstart != (ofs & (~meminfo.erasesize + 1))) { + blockstart = ofs & (~meminfo.erasesize + 1); + if ((badblock = ioctl(fd, MEMGETBADBLOCK, &blockstart)) < 0) { + perror("ioctl(MEMGETBADBLOCK)"); + goto closeall; + } + } + + if (badblock) { + if (omitbad) + continue; + memset (readbuf, 0xff, bs); + } else { + /* Read page data and exit on failure */ + if (pread(fd, readbuf, bs, ofs) != bs) { + perror("pread"); + goto closeall; + } + } + + /* ECC stats available ? */ + if (eccstats) { + if (ioctl(fd, ECCGETSTATS, &stat2)) { + perror("ioctl(ECCGETSTATS)"); + goto closeall; + } + if (stat1.failed != stat2.failed) + fprintf(stderr, "ECC: %d uncorrectable bitflip(s)" + " at offset 0x%08lx\n", + stat2.failed - stat1.failed, ofs); + if (stat1.corrected != stat2.corrected) + fprintf(stderr, "ECC: %d corrected bitflip(s) at" + " offset 0x%08lx\n", + stat2.corrected - stat1.corrected, ofs); + stat1 = stat2; + } + + /* Write out page data */ + if (pretty_print) { + for (i = 0; i < bs; i += 16) { + sprintf(pretty_buf, + "0x%08x: %02x %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + (unsigned int) (ofs + i), readbuf[i], + readbuf[i+1], readbuf[i+2], + readbuf[i+3], readbuf[i+4], + readbuf[i+5], readbuf[i+6], + readbuf[i+7], readbuf[i+8], + readbuf[i+9], readbuf[i+10], + readbuf[i+11], readbuf[i+12], + readbuf[i+13], readbuf[i+14], + readbuf[i+15]); + write(ofd, pretty_buf, 60); + } + } else + write(ofd, readbuf, bs); + + + if (badblock) { + printf("Oops badblock %d at 0x%lx !\n", badblocks++, ofs); + memset (readbuf, 0xff, meminfo.oobsize); + } else { + /* Read OOB data and exit on failure */ + oob.start = ofs; + if (ioctl(fd, MEMREADOOB, &oob) != 0) { + perror("ioctl(MEMREADOOB)"); + goto closeall; + } + } + + if (omitoob) + continue; + + /* Write out OOB data */ + if (pretty_print) { + if (meminfo.oobsize < 16) { + sprintf(pretty_buf, " OOB Data: %02x %02x %02x %02x %02x %02x " + "%02x %02x\n", + oobbuf[0], oobbuf[1], oobbuf[2], + oobbuf[3], oobbuf[4], oobbuf[5], + oobbuf[6], oobbuf[7]); + write(ofd, pretty_buf, 48); + continue; + } + + for (i = 0; i < meminfo.oobsize; i += 16) { + sprintf(pretty_buf, " OOB Data: %02x %02x %02x %02x %02x %02x " + "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + oobbuf[i], oobbuf[i+1], oobbuf[i+2], + oobbuf[i+3], oobbuf[i+4], oobbuf[i+5], + oobbuf[i+6], oobbuf[i+7], oobbuf[i+8], + oobbuf[i+9], oobbuf[i+10], oobbuf[i+11], + oobbuf[i+12], oobbuf[i+13], oobbuf[i+14], + oobbuf[i+15]); + write(ofd, pretty_buf, 60); + } + } else + write(ofd, oobbuf, meminfo.oobsize); + } + + /* reset oobinfo */ + if (oobinfochanged == 1) { + if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { + perror ("MEMSETOOBSEL"); + close(fd); + close(ofd); + return 1; + } + } + /* Close the output file and MTD device */ + close(fd); + close(ofd); + + /* Exit happy */ + return 0; + + closeall: + /* The new mode change is per file descriptor ! */ + if (oobinfochanged == 1) { + if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) { + perror ("MEMSETOOBSEL"); + } + } + close(fd); + close(ofd); + return 1; +} + int rf_strip(char *file) { FILE *fd = fopen(file, "rw"); @@ -74,18 +347,19 @@ int rf_strip(char *file) printf("Stripping padding from %s... ", file); fflush(stdout); fseek(fd, 0, SEEK_END); - - do { - fseek(fd, -4096, SEEK_CUR); - ret = fread(buf, 1, 4096, fd); - fseek(fd, -4096, SEEK_CUR); - for(ret--;ret>0;ret--) - if (buf[ret]!=0xff) { - fseek(fd, ret+1, SEEK_CUR); - eof = ftell(fd); - goto __done; - } - } while(1); + if (ftell(fd)>4096) { + do { + fseek(fd, -4096, SEEK_CUR); + ret = fread(buf, 1, 4096, fd); + fseek(fd, -4096, SEEK_CUR); + for(ret--;ret>0;ret--) + if (buf[ret]!=0xff) { + fseek(fd, ret+1, SEEK_CUR); + eof = ftell(fd); + goto __done; + } + } while(1); + } __done: fclose(fd); @@ -114,21 +388,26 @@ int is_n800() return n800; } - int reverse_extract_pieces(char *dir) { char reply; chdir(dir); - rf_extract("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin"); - rf_extract("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin"); - rf_extract("/dev/mtd2", 0x000800, 0x200000, "zImage"); - rf_extract("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2"); + nanddump("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin"); + //rf_extract("/dev/mtd0", is_n800()?0x200:0, 0x003600, "xloader.bin"); + nanddump("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin"); + //rf_extract("/dev/mtd0", 0x004000, 0x01ffff, "secondary.bin"); + nanddump("/dev/mtd2", 0x000800, 0x200000, "zImage"); + //rf_extract("/dev/mtd2", 0x000800, 0x200000, "zImage"); + nanddump("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2"); + //rf_extract("/dev/mtd3", 0x000000, 0x1D00000, "initfs.jffs2"); printf("\nWARNING: the rootfs extraction on n800 is known to be buggy! feedback is welcome.\n\n"); printf("Extract rootfs? (y/N): "); fflush(stdout); read(0, &reply, 1); - if (reply=='y'||reply=='Y') - rf_extract("/dev/mtd4", 0x000000, 0x6000000, "rootfs.jffs2"); + if (reply=='y'||reply=='Y') { + nanddump("/dev/mtd4", 0x000000, 0x6000000, "rootfs.jffs2"); + //rf_extract("/dev/mtd4", 0x000000, 0x6000000, "rootfs.jffs2"); + } else printf("*** Ignoring rootfs\n"); rf_strip("xloader.bin"); rf_strip("secondary.bin"); diff --git a/src/flash.c b/src/flash.c index c81d97c..8d39f43 100644 --- a/src/flash.c +++ b/src/flash.c @@ -20,6 +20,7 @@ #include "main.h" #include "hash.h" +#include "hexdump.h" #include #include #include @@ -32,6 +33,26 @@ void check_nolo_order_failed() exit(1); } +void query_error_message() +{ + /* query error message */ + int len = 0; + char nolomsg[2048]; + memset(nolomsg, '\0', 2048); + usb_control_msg(dev, 192, 5, 0, 0, nolomsg, 2048, 2000); + nolomsg[2047] = '\0'; + printf("\nNOLO says:\n"); + if (nolomsg[0] == '\0') { + printf(" (.. silence ..)\n"); + } else { + dump_bytes((unsigned char *)nolomsg, 128); + do { + printf(" - %s\n", nolomsg+len); + len+=strlen(nolomsg+len)+1; + } while(nolomsg[len]!='\0'); + } +} + void check_nolo_order() { int i, xlo = 0; @@ -100,6 +121,7 @@ void flash_image(char *filename, char *piece, char *version) //dump_bytes(fquery, 27+vlen); if (usb_control_msg(dev, CMD_WRITE, request, 0, 0, (char *)fquery, 27+vlen, 2000) <0) { + query_error_message(); perror("flash_image.header"); exit(1); } @@ -124,22 +146,7 @@ void flash_image(char *filename, char *piece, char *version) printf("WARNING: Oops wrong read %d vs %d \n", bread, bsize); bread = usb_bulk_write(dev, 2, buf, bsize, 5000); if (bread == 64) { - /* query error message */ - int len = 0; - char nolomsg[2048]; - memset(nolomsg, '\0', 2048); - usb_control_msg(dev, 192, 5, 0, 0, nolomsg, 2048, 2000); - nolomsg[2047] = '\0'; - printf("\nNOLO says:\n"); - if (nolomsg[0] == '\0') { - printf(" (.. silence ..)\n"); - } else { - dump_bytes(nolomsg, 128); - do { - printf(" - %s\n", nolomsg+len); - len+=strlen(nolomsg+len)+1; - } while(nolomsg[len]!='\0'); - } + query_error_message(); fclose(fd); return; } diff --git a/src/mtd/ftl-user.h b/src/mtd/ftl-user.h new file mode 100644 index 0000000..53e94c2 --- /dev/null +++ b/src/mtd/ftl-user.h @@ -0,0 +1,76 @@ +/* + * $Id: ftl.h,v 1.7 2005/11/07 11:14:54 gleixner Exp $ + * + * Derived from (and probably identical to): + * ftl.h 1.7 1999/10/25 20:23:17 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License + * at http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and + * limitations under the License. + * + * The initial developer of the original code is David A. Hinds + * . Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * Alternatively, the contents of this file may be used under the + * terms of the GNU General Public License version 2 (the "GPL"), in + * which case the provisions of the GPL are applicable instead of the + * above. If you wish to allow the use of your version of this file + * only under the terms of the GPL and not to allow others to use + * your version of this file under the MPL, indicate your decision by + * deleting the provisions above and replace them with the notice and + * other provisions required by the GPL. If you do not delete the + * provisions above, a recipient may use your version of this file + * under either the MPL or the GPL. + */ + +#ifndef __MTD_FTL_USER_H__ +#define __MTD_FTL_USER_H__ + +typedef struct erase_unit_header_t { + u_int8_t LinkTargetTuple[5]; + u_int8_t DataOrgTuple[10]; + u_int8_t NumTransferUnits; + u_int32_t EraseCount; + u_int16_t LogicalEUN; + u_int8_t BlockSize; + u_int8_t EraseUnitSize; + u_int16_t FirstPhysicalEUN; + u_int16_t NumEraseUnits; + u_int32_t FormattedSize; + u_int32_t FirstVMAddress; + u_int16_t NumVMPages; + u_int8_t Flags; + u_int8_t Code; + u_int32_t SerialNumber; + u_int32_t AltEUHOffset; + u_int32_t BAMOffset; + u_int8_t Reserved[12]; + u_int8_t EndTuple[2]; +} erase_unit_header_t; + +/* Flags in erase_unit_header_t */ +#define HIDDEN_AREA 0x01 +#define REVERSE_POLARITY 0x02 +#define DOUBLE_BAI 0x04 + +/* Definitions for block allocation information */ + +#define BLOCK_FREE(b) ((b) == 0xffffffff) +#define BLOCK_DELETED(b) (((b) == 0) || ((b) == 0xfffffffe)) + +#define BLOCK_TYPE(b) ((b) & 0x7f) +#define BLOCK_ADDRESS(b) ((b) & ~0x7f) +#define BLOCK_NUMBER(b) ((b) >> 9) +#define BLOCK_CONTROL 0x30 +#define BLOCK_DATA 0x40 +#define BLOCK_REPLACEMENT 0x60 +#define BLOCK_BAD 0x70 + +#endif /* __MTD_FTL_USER_H__ */ diff --git a/src/mtd/inftl-user.h b/src/mtd/inftl-user.h new file mode 100644 index 0000000..9b1e252 --- /dev/null +++ b/src/mtd/inftl-user.h @@ -0,0 +1,91 @@ +/* + * $Id: inftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $ + * + * Parts of INFTL headers shared with userspace + * + */ + +#ifndef __MTD_INFTL_USER_H__ +#define __MTD_INFTL_USER_H__ + +#define OSAK_VERSION 0x5120 +#define PERCENTUSED 98 + +#define SECTORSIZE 512 + +/* Block Control Information */ + +struct inftl_bci { + uint8_t ECCsig[6]; + uint8_t Status; + uint8_t Status1; +} __attribute__((packed)); + +struct inftl_unithead1 { + uint16_t virtualUnitNo; + uint16_t prevUnitNo; + uint8_t ANAC; + uint8_t NACs; + uint8_t parityPerField; + uint8_t discarded; +} __attribute__((packed)); + +struct inftl_unithead2 { + uint8_t parityPerField; + uint8_t ANAC; + uint16_t prevUnitNo; + uint16_t virtualUnitNo; + uint8_t NACs; + uint8_t discarded; +} __attribute__((packed)); + +struct inftl_unittail { + uint8_t Reserved[4]; + uint16_t EraseMark; + uint16_t EraseMark1; +} __attribute__((packed)); + +union inftl_uci { + struct inftl_unithead1 a; + struct inftl_unithead2 b; + struct inftl_unittail c; +}; + +struct inftl_oob { + struct inftl_bci b; + union inftl_uci u; +}; + + +/* INFTL Media Header */ + +struct INFTLPartition { + __u32 virtualUnits; + __u32 firstUnit; + __u32 lastUnit; + __u32 flags; + __u32 spareUnits; + __u32 Reserved0; + __u32 Reserved1; +} __attribute__((packed)); + +struct INFTLMediaHeader { + char bootRecordID[8]; + __u32 NoOfBootImageBlocks; + __u32 NoOfBinaryPartitions; + __u32 NoOfBDTLPartitions; + __u32 BlockMultiplierBits; + __u32 FormatFlags; + __u32 OsakVersion; + __u32 PercentUsed; + struct INFTLPartition Partitions[4]; +} __attribute__((packed)); + +/* Partition flag types */ +#define INFTL_BINARY 0x20000000 +#define INFTL_BDTL 0x40000000 +#define INFTL_LAST 0x80000000 + +#endif /* __MTD_INFTL_USER_H__ */ + + diff --git a/src/mtd/jffs2-user.h b/src/mtd/jffs2-user.h new file mode 100644 index 0000000..bc5d99a --- /dev/null +++ b/src/mtd/jffs2-user.h @@ -0,0 +1,82 @@ +/* + * $Id: jffs2-user.h,v 1.1 2004/05/05 11:57:54 dwmw2 Exp $ + * + * JFFS2 definitions for use in user space only + */ + +#ifndef __JFFS2_USER_H__ +#define __JFFS2_USER_H__ + +/* This file is blessed for inclusion by userspace */ +#include +#include +#include + +#undef cpu_to_je16 +#undef cpu_to_je32 +#undef cpu_to_jemode +#undef je16_to_cpu +#undef je32_to_cpu +#undef jemode_to_cpu + +extern int target_endian; + +#define t16(x) ({ uint16_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_16(__b); }) +#define t32(x) ({ uint32_t __b = (x); (target_endian==__BYTE_ORDER)?__b:bswap_32(__b); }) + +#define cpu_to_je16(x) ((jint16_t){t16(x)}) +#define cpu_to_je32(x) ((jint32_t){t32(x)}) +#define cpu_to_jemode(x) ((jmode_t){t32(x)}) + +#define je16_to_cpu(x) (t16((x).v16)) +#define je32_to_cpu(x) (t32((x).v32)) +#define jemode_to_cpu(x) (t32((x).m)) + +#define le16_to_cpu(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x)) +#define le32_to_cpu(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x)) +#define cpu_to_le16(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_16(x)) +#define cpu_to_le32(x) (__BYTE_ORDER==__LITTLE_ENDIAN ? (x) : bswap_32(x)) + +/* XATTR/POSIX-ACL related definition */ +/* Namespaces copied from xattr.h and posix_acl_xattr.h */ +#define XATTR_USER_PREFIX "user." +#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1) +#define XATTR_SECURITY_PREFIX "security." +#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1) +#define POSIX_ACL_XATTR_ACCESS "system.posix_acl_access" +#define POSIX_ACL_XATTR_ACCESS_LEN (sizeof (POSIX_ACL_XATTR_ACCESS) - 1) +#define POSIX_ACL_XATTR_DEFAULT "system.posix_acl_default" +#define POSIX_ACL_XATTR_DEFAULT_LEN (sizeof (POSIX_ACL_XATTR_DEFAULT) - 1) +#define XATTR_TRUSTED_PREFIX "trusted." +#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1) + +struct jffs2_acl_entry { + jint16_t e_tag; + jint16_t e_perm; + jint32_t e_id; +}; + +struct jffs2_acl_entry_short { + jint16_t e_tag; + jint16_t e_perm; +}; + +struct jffs2_acl_header { + jint32_t a_version; +}; + +/* copied from include/linux/posix_acl_xattr.h */ +#define POSIX_ACL_XATTR_VERSION 0x0002 + +struct posix_acl_xattr_entry { + uint16_t e_tag; + uint16_t e_perm; + uint32_t e_id; +}; + +struct posix_acl_xattr_header { + uint32_t a_version; + struct posix_acl_xattr_entry a_entries[0]; +}; + +#endif /* __JFFS2_USER_H__ */ diff --git a/src/mtd/mtd-abi.h b/src/mtd/mtd-abi.h new file mode 100644 index 0000000..7ccadb1 --- /dev/null +++ b/src/mtd/mtd-abi.h @@ -0,0 +1,158 @@ +/* + * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $ + * + * Portions of MTD ABI definition which are shared by kernel and user space + */ + +#ifndef __MTD_ABI_H__ +#define __MTD_ABI_H__ + +#ifndef __KERNEL__ /* Urgh. The whole point of splitting this out into + separate files was to avoid #ifdef __KERNEL__ */ +#define __user +#endif + +struct erase_info_user { + uint32_t start; + uint32_t length; +}; + +struct mtd_oob_buf { + uint32_t start; + uint32_t length; + unsigned char __user *ptr; +}; + +#define MTD_ABSENT 0 +#define MTD_NORFLASH 3 +#define MTD_NANDFLASH 4 +#define MTD_DATAFLASH 6 +#define MTD_GENERIC_TYPE 7 + +#define MTD_WRITEABLE 0x400 /* Device is writeable */ +#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ +#define MTD_NO_ERASE 0x1000 /* No erase necessary */ + +// Some common devices / combinations of capabilities +#define MTD_CAP_ROM 0 +#define MTD_CAP_RAM (MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE) +#define MTD_CAP_NORFLASH (MTD_WRITEABLE | MTD_BIT_WRITEABLE) +#define MTD_CAP_NANDFLASH (MTD_WRITEABLE) + + +// Types of automatic ECC/Checksum available +#define MTD_ECC_NONE 0 // No automatic ECC available +#define MTD_ECC_RS_DiskOnChip 1 // Automatic ECC on DiskOnChip +#define MTD_ECC_SW 2 // SW ECC for Toshiba & Samsung devices + +/* ECC byte placement */ +#define MTD_NANDECC_OFF 0 // Switch off ECC (Not recommended) +#define MTD_NANDECC_PLACE 1 // Use the given placement in the structure (YAFFS1 legacy mode) +#define MTD_NANDECC_AUTOPLACE 2 // Use the default placement scheme +#define MTD_NANDECC_PLACEONLY 3 // Use the given placement in the structure (Do not store ecc result on read) +#define MTD_NANDECC_AUTOPL_USR 4 // Use the given autoplacement scheme rather than using the default + +/* OTP mode selection */ +#define MTD_OTP_OFF 0 +#define MTD_OTP_FACTORY 1 +#define MTD_OTP_USER 2 + +struct mtd_info_user { + uint8_t type; + uint32_t flags; + uint32_t size; // Total size of the MTD + uint32_t erasesize; + uint32_t writesize; + uint32_t oobsize; // Amount of OOB data per block (e.g. 16) + uint32_t ecctype; + uint32_t eccsize; +}; + +struct region_info_user { + uint32_t offset; /* At which this region starts, + * from the beginning of the MTD */ + uint32_t erasesize; /* For this region */ + uint32_t numblocks; /* Number of blocks in this region */ + uint32_t regionindex; +}; + +struct otp_info { + uint32_t start; + uint32_t length; + uint32_t locked; +}; + +#define MEMGETINFO _IOR('M', 1, struct mtd_info_user) +#define MEMERASE _IOW('M', 2, struct erase_info_user) +#define MEMWRITEOOB _IOWR('M', 3, struct mtd_oob_buf) +#define MEMREADOOB _IOWR('M', 4, struct mtd_oob_buf) +#define MEMLOCK _IOW('M', 5, struct erase_info_user) +#define MEMUNLOCK _IOW('M', 6, struct erase_info_user) +#define MEMGETREGIONCOUNT _IOR('M', 7, int) +#define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) +#define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) +#define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) +#define MEMGETBADBLOCK _IOW('M', 11, loff_t) +#define MEMSETBADBLOCK _IOW('M', 12, loff_t) +#define OTPSELECT _IOR('M', 13, int) +#define OTPGETREGIONCOUNT _IOW('M', 14, int) +#define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) +#define OTPLOCK _IOR('M', 16, struct otp_info) +#define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) +#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) +#define MTDFILEMODE _IO('M', 19) + +/* + * Obsolete legacy interface. Keep it in order not to break userspace + * interfaces + */ +struct nand_oobinfo { + uint32_t useecc; + uint32_t eccbytes; + uint32_t oobfree[8][2]; + uint32_t eccpos[32]; +}; + +struct nand_oobfree { + uint32_t offset; + uint32_t length; +}; + +#define MTD_MAX_OOBFREE_ENTRIES 8 +/* + * ECC layout control structure. Exported to userspace for + * diagnosis and to allow creation of raw images + */ +struct nand_ecclayout { + uint32_t eccbytes; + uint32_t eccpos[64]; + uint32_t oobavail; + struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; +}; + +/** + * struct mtd_ecc_stats - error correction status + * + * @corrected: number of corrected bits + * @failed: number of uncorrectable errors + * @badblocks: number of bad blocks in this partition + * @bbtblocks: number of blocks reserved for bad block tables + */ +struct mtd_ecc_stats { + uint32_t corrected; + uint32_t failed; + uint32_t badblocks; + uint32_t bbtblocks; +}; + +/* + * Read/write file modes for access to MTD + */ +enum mtd_file_modes { + MTD_MODE_NORMAL = MTD_OTP_OFF, + MTD_MODE_OTP_FACTORY = MTD_OTP_FACTORY, + MTD_MODE_OTP_USER = MTD_OTP_USER, + MTD_MODE_RAW, +}; + +#endif /* __MTD_ABI_H__ */ diff --git a/src/mtd/mtd-user.h b/src/mtd/mtd-user.h new file mode 100644 index 0000000..713f34d --- /dev/null +++ b/src/mtd/mtd-user.h @@ -0,0 +1,21 @@ +/* + * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $ + * + * MTD ABI header for use by user space only. + */ + +#ifndef __MTD_USER_H__ +#define __MTD_USER_H__ + +#include + +/* This file is blessed for inclusion by userspace */ +#include + +typedef struct mtd_info_user mtd_info_t; +typedef struct erase_info_user erase_info_t; +typedef struct region_info_user region_info_t; +typedef struct nand_oobinfo nand_oobinfo_t; +typedef struct nand_ecclayout nand_ecclayout_t; + +#endif /* __MTD_USER_H__ */ diff --git a/src/mtd/nftl-user.h b/src/mtd/nftl-user.h new file mode 100644 index 0000000..b2bca18 --- /dev/null +++ b/src/mtd/nftl-user.h @@ -0,0 +1,76 @@ +/* + * $Id: nftl-user.h,v 1.2 2005/11/07 11:14:56 gleixner Exp $ + * + * Parts of NFTL headers shared with userspace + * + */ + +#ifndef __MTD_NFTL_USER_H__ +#define __MTD_NFTL_USER_H__ + +/* Block Control Information */ + +struct nftl_bci { + unsigned char ECCSig[6]; + uint8_t Status; + uint8_t Status1; +}__attribute__((packed)); + +/* Unit Control Information */ + +struct nftl_uci0 { + uint16_t VirtUnitNum; + uint16_t ReplUnitNum; + uint16_t SpareVirtUnitNum; + uint16_t SpareReplUnitNum; +} __attribute__((packed)); + +struct nftl_uci1 { + uint32_t WearInfo; + uint16_t EraseMark; + uint16_t EraseMark1; +} __attribute__((packed)); + +struct nftl_uci2 { + uint16_t FoldMark; + uint16_t FoldMark1; + uint32_t unused; +} __attribute__((packed)); + +union nftl_uci { + struct nftl_uci0 a; + struct nftl_uci1 b; + struct nftl_uci2 c; +}; + +struct nftl_oob { + struct nftl_bci b; + union nftl_uci u; +}; + +/* NFTL Media Header */ + +struct NFTLMediaHeader { + char DataOrgID[6]; + uint16_t NumEraseUnits; + uint16_t FirstPhysicalEUN; + uint32_t FormattedSize; + unsigned char UnitSizeFactor; +} __attribute__((packed)); + +#define MAX_ERASE_ZONES (8192 - 512) + +#define ERASE_MARK 0x3c69 +#define SECTOR_FREE 0xff +#define SECTOR_USED 0x55 +#define SECTOR_IGNORE 0x11 +#define SECTOR_DELETED 0x00 + +#define FOLD_MARK_IN_PROGRESS 0x5555 + +#define ZONE_GOOD 0xff +#define ZONE_BAD_ORIGINAL 0 +#define ZONE_BAD_MARKED 7 + + +#endif /* __MTD_NFTL_USER_H__ */ -- cgit v1.2.3