nearly working nandroid, built against libc
diff --git a/mtdutils/mtdutils.c b/mtdutils/mtdutils.c
index 18e6a5d..25feabd 100644
--- a/mtdutils/mtdutils.c
+++ b/mtdutils/mtdutils.c
@@ -38,6 +38,7 @@
struct MtdReadContext {
const MtdPartition *partition;
char *buffer;
+ size_t read_size;
size_t consumed;
int fd;
};
@@ -564,3 +565,84 @@
}
return pos;
}
+
+
+ssize_t mtd_read_raw(MtdReadContext *ctx, char *data, size_t len)
+{
+ static const int SPARE_SIZE = (2048 >> 5);
+ struct mtd_info_user mtd_info;
+ struct mtd_oob_buf oob_buf;
+ struct nand_ecclayout ecc_layout;
+ struct nand_oobfree *fp;
+ unsigned char ecc[SPARE_SIZE];
+ char *src, *dst;
+ int i, n, ret;
+
+/*
+ * FIXME: These two ioctls should be cached in MtdReadContext.
+ */
+ ret = ioctl(ctx->fd, MEMGETINFO, &mtd_info);
+ if (ret < 0)
+ return -1;
+
+ ret = ioctl(ctx->fd, ECCGETLAYOUT, &ecc_layout);
+ if (ret < 0)
+ return -1;
+
+ ctx->read_size = mtd_info.writesize;
+ ctx->consumed = ctx->read_size;
+
+/*
+ * Read next good data block.
+ */
+ ret = read_block(ctx->partition, ctx->fd, data);
+ if (ret < 0)
+ return -1;
+
+ dst = src = data + ctx->read_size;
+
+/*
+ * Read OOB data for last block read in read_block().
+ */
+ oob_buf.start = lseek(ctx->fd, 0, SEEK_CUR) - ctx->read_size;
+ oob_buf.length = mtd_info.oobsize;
+ oob_buf.ptr = (unsigned char *) src;
+
+ ret = ioctl(ctx->fd, MEMREADOOB, &oob_buf);
+ if (ret < 0)
+ return -1;
+
+/*
+ * As yaffs and yaffs2 use mode MEM_OOB_AUTO, but mtdchar uses
+ * MEM_OOB_PLACE, copy the spare data down the hard way.
+ *
+ * Safe away ECC data:
+ */
+ for (i = 0; i < ecc_layout.eccbytes; i++) {
+ ecc[i] = src[ecc_layout.eccpos[i]];
+ }
+ for ( ; i < SPARE_SIZE; i++) {
+ ecc[i] = 0;
+ }
+
+/*
+ * Copy yaffs2 spare data down.
+ */
+ n = ecc_layout.oobavail;
+ fp = &ecc_layout.oobfree[0];
+ while (n) {
+ if (fp->offset) {
+ memmove(dst, src + fp->offset, fp->length);
+ }
+ dst += fp->length;
+ n -= fp->length;
+ ++fp;
+ }
+
+/*
+ * Restore ECC data behind spare data.
+ */
+ memcpy(dst, ecc, (ctx->read_size >> 5) - ecc_layout.oobavail);
+
+ return ctx->read_size + (ctx->read_size >> 5);
+}