diff options
authorArtem Bityutskiy <>2011-04-01 11:11:15 +0300
committerArtem Bityutskiy <>2011-04-01 19:31:43 +0300
commitb22f7f386ba37a766aedd8e8cf34781a3d1daad2 (patch)
parent82869c99a0d0a948fa095c2e04cf01172f6338f3 (diff)
libmtd: fix OOB read and write interfacev1.4.4
When reading and writing OOB we specify the address as absolute offset from the beginning of the MTD device. This offset is basically an absolute page offset plus the OOB offset. And it does not have to be aligned to the min. I/O unit size (NAND page size). So fix the 'do_oob_op()' function and remove incorrect checking that the offset is page-aligned. This check leads to the following errors: libmtd: error!: unaligned address 2, mtd0 page size is 2048 But obviously, the intent was to write to offset 2 of the OOB area of the very first NAND page. Instead of that incorrect check, we should check that the OOB offset we write to is within the OOB size and the length is withing the OOB size. This patch adds such check. Reported-by: Kelly Anderson <> Signed-off-by: Artem Bityutskiy <> Tested-by: Kelly Anderson <>
1 files changed, 8 insertions, 5 deletions
diff --git a/lib/libmtd.c b/lib/libmtd.c
index e0c0934..418ba29 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -1079,7 +1079,7 @@ int do_oob_op(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
uint64_t start, uint64_t length, void *data, unsigned int cmd64,
unsigned int cmd)
- int ret;
+ int ret, oob_offs;
struct mtd_oob_buf64 oob64;
struct mtd_oob_buf oob;
unsigned long long max_offs;
@@ -1102,10 +1102,13 @@ int do_oob_op(libmtd_t desc, const struct mtd_dev_info *mtd, int fd,
errno = EINVAL;
return -1;
- if (start % mtd->min_io_size) {
- errmsg("unaligned address %llu, mtd%d page size is %d",
- (unsigned long long)start, mtd->mtd_num,
- mtd->min_io_size);
+ oob_offs = start & (mtd->min_io_size - 1);
+ if (oob_offs + length > mtd->oob_size || length == 0) {
+ errmsg("Cannot write %llu OOB bytes to address %llu "
+ "(OOB offset %u) - mtd%d OOB size is only %d bytes",
+ (unsigned long long)length, (unsigned long long)start,
+ oob_offs, mtd->mtd_num, mtd->oob_size);
errno = EINVAL;
return -1;