@@ -190,40 +190,18 @@
if (jffs2) {
cleanmarker.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK);
cleanmarker.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER);
- if (!isNAND)
+ if (!isNAND) {
cleanmarker.totlen = cpu_to_je32(sizeof(cleanmarker));
- else {
- struct nand_oobinfo oobinfo;
-
- if (ioctl(fd, MEMGETOOBSEL, &oobinfo) != 0)
- return sys_errmsg("%s: unable to get NAND oobinfo", mtd_device);
-
- /* Check for autoplacement */
- if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
- /* Get the position of the free bytes */
- if (!oobinfo.oobfree[0][1])
- return errmsg(" Eeep. Autoplacement selected and no empty space in oob");
- clmpos = oobinfo.oobfree[0][0];
- clmlen = oobinfo.oobfree[0][1];
- if (clmlen > 8)
- clmlen = 8;
- } else {
- /* Legacy mode */
- switch (mtd.oob_size) {
- case 8:
- clmpos = 6;
- clmlen = 2;
- break;
- case 16:
- clmpos = 8;
- clmlen = 8;
- break;
- case 64:
- clmpos = 16;
- clmlen = 8;
- break;
- }
- }
+ } else {
+ if (!mtd.oob_free[0].length) {
+ fprintf(stderr, " Eeep. No empty space in oob for JFFS2 cleanmarkers\n");
+ return 1;
+ }
+ clmpos = mtd.oob_free[0].offset;
+ clmlen = mtd.oob_free[0].length;
+ if (clmlen > 8)
+ clmlen = 8;
+
cleanmarker.totlen = cpu_to_je32(8);
}
cleanmarker.hdr_crc = cpu_to_je32(mtd_crc32(0, &cleanmarker,
sizeof(cleanmarker) - 4));
@@ -31,6 +31,8 @@
#define MTD_NAME_MAX 127
/* Maximum MTD device type string length */
#define MTD_TYPE_MAX 64
+/* Maximum MTD nand OOB free entries */
+#define MTD_NAND_MAX_OOBFREE_ENTRIES 8
/* MTD library descriptor */
typedef void * libmtd_t;
@@ -50,6 +52,17 @@
};
/**
+ * struct mtd_nand_oobfree - information about free OOB areas
+ * @offset: offset of free OOB area from start of OOB area
+ * @length: length of free OOB area
+ */
+struct mtd_nand_oobfree
+{
+ int offset;
+ int length;
+};
+
+/**
* struct mtd_dev_info - information about an MTD device.
* @mtd_num: MTD device number
* @major: major number of corresponding character device
@@ -66,6 +79,10 @@
* @region_cnt: count of additional erase regions
* @writable: zero if the device is read-only
* @bb_allowed: non-zero if the MTD device may have bad eraseblocks
+ * @eccbytes: number of ecc bytes in OOB area
+ * @eccpos: position of ecc bytes in OOB area
+ * @oob_available: number of bytes available in OOB area free other
use then ECC
+ * @oob_free: location and sizes of free OOB areas
*/
struct mtd_dev_info
{
@@ -84,6 +101,10 @@
int region_cnt;
unsigned int writable:1;
unsigned int bb_allowed:1;
+ int eccbytes;
+ int eccpos[64];
+ int oob_available;
+ struct mtd_nand_oobfree oob_free[MTD_NAND_MAX_OOBFREE_ENTRIES];
};
/**
@@ -37,6 +37,8 @@
#include "libmtd_int.h"
#include "common.h"
+#define MTD_DEV_PATT "/dev/mtd%d"
+
/**
* mkpath - compose full path from 2 given components.
* @path: the first component
@@ -548,6 +550,80 @@
return 1;
}
+/**
+ * mtd_get_oob_info - fill the mtd_dev_info structure with information
+ * about the OOB data.
+ */
+static int mtd_get_oob_info(struct mtd_dev_info *mtd)
+{
+ int i, fd;
+ char node[sizeof(MTD_DEV_PATT) + 20];
+
+ sprintf(node, MTD_DEV_PATT, mtd->mtd_num);
+ fd = open(node, O_RDWR);
+ if (fd == -1)
+ return sys_errmsg("cannot open \"%s\"", node);
+
+ if (mtd->type == MTD_NANDFLASH) {
+ /* get ECC/OOB information for NAND flash */
+#if defined(ECCGETLAYOUT)
+ struct nand_ecclayout ecclayout;
+ memset(&ecclayout, 0, sizeof(ecclayout));
+ if (ioctl(fd, ECCGETLAYOUT, &ecclayout) == 0) {
+ mtd->eccbytes = ecclayout.eccbytes;
+ for(i=0; i<64; i++) {
+ mtd->eccpos[i] = ecclayout.eccpos[i];
+ }
+ mtd->oob_available = ecclayout.oobavail;
+ for (i=0; i<MTD_NAND_MAX_OOBFREE_ENTRIES; i++) {
+ mtd->oob_free[i].offset = ecclayout.oobfree[i].offset;
+ mtd->oob_free[i].length = ecclayout.oobfree[i].length;
+ }
+ } else {
+#endif/*defined(ECCGETLAYOUT)*/
+ /* new ECC interface failed or not available, fall back to old OOB
interface, which does not support large flash */
+ struct nand_oobinfo oobinfo;
+ if (ioctl(fd, MEMGETOOBSEL, &oobinfo) == 0)
+ {
+ /* Check for autoplacement */
+ mtd->eccbytes = oobinfo.eccbytes;
+ for(i=0;i<32;i++) {
+ mtd->eccpos[i] = oobinfo.eccpos[i];
+ }
+ if (oobinfo.useecc == MTD_NANDECC_AUTOPLACE) {
+ for(i=0;i<8;i++) {
+ mtd->oob_free[i].offset = oobinfo.oobfree[i][0];
+ mtd->oob_free[i].length = oobinfo.oobfree[i][1];
+ mtd->oob_available += mtd->oob_free[i].length;
+ }
+ } else{
+ /* Legacy mode */
+ switch (mtd->oob_size) {
+ case 8:
+ mtd->oob_free[0].offset = 6;
+ mtd->oob_free[0].length = 2;
+ break;
+ case 16:
+ mtd->oob_free[0].offset = 8;
+ mtd->oob_free[0].length = 8;
+ break;
+ case 64:
+ mtd->oob_free[0].offset = 16;
+ mtd->oob_free[0].length = 8;
+ break;
+ }
+ mtd->oob_available = mtd->oob_free[0].length;
+ }
+ }
+#if defined(ECCGETLAYOUT)
+ }
+#endif/*defined(ECCGETLAYOUT)*/
+ }
+ close(fd);
+
+ return 0;
+}
+
libmtd_t libmtd_open(void)
{