mtdchar : writing image with oob and NOP=1
Hi,
We need to write our bootloader with a special ecc (use by cpu rom).
For that we use MTD_MODE_RAW, write and MEMWRITEOOB. This work fine, but from my understanding this will do a first page program with oob set to 0xff and then program again oob.
But some recent nand support only 1 program per page (NOP=1). How can we program nand with NOP=1 with a custom ecc ?
From what I see in mtdchar either datbuf is set (and oobbuf is null) or oobbuf is set (and datbuf is null).
So this mean we need to add an ioctl to do that ?
Matthieu
Quoted 6 lines · Matthieu CASTET
Hi,
We need to write our bootloader with a special ecc (use by cpu rom).
For that we use
MTD_MODE_RAW, write and MEMWRITEOOB. This work fine, but from my understanding this will do a first page program with oob set to0xffand then program again oob.
Quoted 8 lines
But some recent nand support only 1 program per page (NOP=1). How can we program nand with NOP=1 with a custom ecc ?
From what I see in mtdchar either datbuf is set (and oobbuf is null) or
oobbuf is set (and datbuf is null).So this mean we need to add an ioctl to do that ?
For info here what we did for our 2.6.27 kernel.
Matthieu
drivers/mtd/mtdchar.c +78 -0
@@ -547,6 +547,84 @@ static int mtd_ioctl(struct inode *inode, struct file *file,break ; } +case MEMWRITEPAGE : + { +struct mtd_page_buf buf; +struct mtd_oob_ops ops; +struct mtd_page_buf __user *user_buf = argp; +uint32_t retlen; + +if (!(file->f_mode &2 )) +return -EPERM ; + +if (copy_from_user (&buf, argp,sizeof (struct mtd_page_buf ))) +return -EFAULT ; + +if (buf.length != mtd->writesize || buf.oob_length != mtd->oobsize) +return -EINVAL ; + +if (!mtd->write_oob) +return -EOPNOTSUPP ; + + ret =access_ok (VERIFY_READ , buf.ptr, + buf.length) ?0 :EFAULT ; +if (ret) +return ret; + + ret =access_ok (VERIFY_READ , buf.oob_ptr, + buf.oob_length) ?0 :EFAULT ; +if (ret) +return ret; + + ops.ooblen = mtd->oobsize; + ops.ooboffs =0 ; + ops.len = mtd->writesize; + ops.mode =MTD_OOB_RAW ; + +if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) +return -EINVAL ; + + ops.datbuf =kmalloc (buf.length,GFP_KERNEL ); +if (!ops.datbuf) +return -ENOMEM ; + +if (copy_from_user (ops.datbuf, buf.ptr, buf.length)) { +kfree (ops.datbuf); +return -EFAULT ; + } + + ops.oobbuf =kmalloc (buf.oob_length,GFP_KERNEL ); +if (!ops.oobbuf) { +kfree (ops.datbuf); +return -ENOMEM ; + } + +if (copy_from_user (ops.oobbuf, buf.oob_ptr, buf.oob_length)) { +kfree (ops.datbuf); +kfree (ops.oobbuf); +return -EFAULT ; + } + + ret = mtd->write_oob (mtd, buf.start, &ops); + +if (!ret) { + retlen = ops.retlen; +if (copy_to_user (&user_buf->length, &retlen,sizeof (buf.length))) + ret = -EFAULT ; + } + +if (!ret) { + retlen = ops.oobretlen; +if (copy_to_user (&user_buf->oob_length, &retlen,sizeof (buf.oob_length))) + ret = -EFAULT ; + } + + +kfree (ops.datbuf); +kfree (ops.oobbuf); +break ; + + }case MEMREADOOB : {
include/mtd/mtd-abi.h +8 -0
@@ -16,6 +16,13 @@ struct mtd_oob_buf {unsigned char __user *ptr; }; +struct mtd_page_buf { +uint32_t start; +uint32_t length; +unsigned char __user *ptr; +uint32_t oob_length; +unsigned char __user *oob_ptr; +};#define MTD_ABSENT 0#define MTD_RAM 1#define MTD_ROM 2
@@ -93,6 +100,7 @@ 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) +#define MEMWRITEPAGE _IOWR('M', 30, struct mtd_page_buf)/* * Obsolete legacy interface. Keep it in order not to break userspace
Quoted 8 lines · Matthieu CASTET
Hi,
We need to write our bootloader with a special ecc (use by cpu rom).
For that we use
MTD_MODE_RAW, write and MEMWRITEOOB. This work fine, but from my understanding this will do a first page program with oob set to0xffand then program again oob.
Quoted 7 lines
But some recent nand support only 1 program per page (NOP=1). How can we program nand with NOP=1 with a custom ecc ?
From what I see in mtdchar either datbuf is set (and oobbuf is null) or
oobbuf is set (and datbuf is null).So this mean we need to add an ioctl to do that ?
Certainly not ioctl. MEMWRITEOOB should handle this and hide from users, I think.
Signature · 2 lines
Best Regards, Artem Bityutskiy (Артём Битюцкий)