How to write to nand with an image containing oob data, including ECC?
Kelly Anderson
kelly at silka.with-linux.com
Tue Mar 29 18:00:15 EDT 2011
On 03/29/11 09:42, Artem Bityutskiy wrote:
> On Tue, 2011-03-29 at 17:30 +0200, Ricard Wanderlof wrote:
>> Hi,
>>
>> In order to test an ECC algorithm (BCH in this case, as I recently posted
>> about), i want to write an image to a nand flash which contains bit
>> errors.
>>
>> What I want to do, and I seem to remember doing this in the past, is to
>> dump the whole image, change a single bit, and write it back, including
>> the oob.
>>
>> So what I'm doing is
>>
>> $ nandwrite -o -n /dev/mtd3 /tmp/mtd3-badimage
>>
>> where /tmp/mtd3-badimage contains an image including all oobs for all
>> pages.
>>
>> However, this fails saying
>>
>> Writing data to block 0 at offset 0x0
>> libmtd: error!: cannot write 2048 bytes to mtd3 (eraseblock 0, offset 0)
>> error 22 (Invalid argument)
>> nandwrite: error!: /dev/mtd3: MTD write failure
>> error 22 (Invalid argument)
>> Data was only partially written due to error
>> : Invalid argument
>>
>> Using just -o doesn't work because it seems nandwrite writes the oob, but
>> then since it doesn't write the main page in raw mode, the ecc gets
>> overwritten. Strangely enough, the ECC doesn't seem to match the data
>> written, as I get uncorrectable errors when reading back (not just with
>> BCH, but also with the standard mtd built-in algorithm). Perhaps the oob
>> gets written twice, once with my data and once more with the calculated
>> ecc?
>>
>> Is this a known bug, or are the some other options I should be using?
> Check this bug-report, probably it is about the same. Not sure, I did
> not have time to look at this:
>
> http://lists.infradead.org/pipermail/linux-mtd/2011-March/034505.html
>
> would be great if someone just sent a fix :-)
>
OK, I'll be nice.
When I sent the original bug report I was dog tired. Now with a good
nights sleep I've got the energy to write a fix.
Not sure if this is technically correct, or if it handles corner cases
adequately. In any case, it does work. As far as 16 goes, I selected
it based on the code that calls do_oob_op and it looked to be the
largest clmpos that was valid.
--- ./lib/libmtd.c.orig 2011-03-29 15:24:13.000000000 -0600
+++ ./lib/libmtd.c 2011-03-29 15:42:47.000000000 -0600
@@ -1085,6 +1085,7 @@ int do_oob_op(libmtd_t desc, const struc
unsigned long long max_offs;
const char *cmd64_str, *cmd_str;
struct libmtd *lib = (struct libmtd *)desc;
+ uint64_t clmpos = (start % mtd->min_io_size);
if (cmd64 == MEMREADOOB64) {
cmd64_str = "MEMREADOOB64";
@@ -1102,10 +1103,10 @@ int do_oob_op(libmtd_t desc, const struc
errno = EINVAL;
return -1;
}
- if (start % mtd->min_io_size) {
- errmsg("unaligned address %llu, mtd%d page size is %d",
+ if ( clmpos > 16 ) {
+ errmsg("address %llu, mtd%d page size is %d, clmpos=%llu",
(unsigned long long)start, mtd->mtd_num,
- mtd->min_io_size);
+ mtd->min_io_size, clmpos);
errno = EINVAL;
return -1;
}
More information about the linux-mtd
mailing list