diff --git a/src/mtd.c b/src/mtd.c
index 02af33b..f6fa962 100644
--- a/src/mtd.c
+++ b/src/mtd.c
@@ -254,14 +254,26 @@ int mtd_read_page(struct mtd_data *md, int chip, loff_t ofs, int ecc)
 
 	mtd_set_ecc_mode(md, ecc);
 
-	data = md->buf;
+	if (ecc) {
+		data = md->buf;
+	} else {
+		data = malloc(mtd_writesize(md) + mtd_oobsize(md));
+		if (!data) {
+			fprintf(stderr, "mtd: %s failed to allocate buffer\n", __func__);
+			return -1;
+		}
+	}
+
 	oobdata = data + mtd_writesize(md);
 
 	/* make sure it's aligned to a page */
-	if ((ofs % mtd_writesize(md)) != 0)
+	if ((ofs % mtd_writesize(md)) != 0) {
+		if (!ecc)
+			free(data);
 		return -1;
+	}
 
-	memset(md->buf, 0, mtd_writesize(md) + mtd_oobsize(md));
+	memset(data, 0, mtd_writesize(md) + mtd_oobsize(md));
 
 	size = mtd_writesize(md);
 
@@ -269,6 +281,33 @@ int mtd_read_page(struct mtd_data *md, int chip, loff_t ofs, int ecc)
 		r = pread(md->part[chip].fd, data, size, ofs);
 	} while (r == -1 && (errno == EAGAIN || errno == EBUSY));
 
+	if (!ecc) {
+		int i;
+		struct nfc_geometry *nfc_geo = &md->nfc_geometry;
+		int eccbytes = ((nfc_geo->ecc_strength * nfc_geo->gf_len) + 7) / 8;
+		int chunksize = nfc_geo->ecc_chunk_size_in_bytes;
+		int dst_offset = 0;
+
+		memcpy(md->buf, oobdata, nfc_geo->metadata_size_in_bytes);
+		dst_offset += nfc_geo->metadata_size_in_bytes;
+		for (i = 0; i < nfc_geo->ecc_chunk_count; i++) {
+			memcpy(md->buf + dst_offset, data + (i * chunksize), chunksize);
+			dst_offset += chunksize;
+			memcpy(md->buf + dst_offset,
+			       oobdata + nfc_geo->metadata_size_in_bytes + (i * eccbytes),
+			       eccbytes);
+			dst_offset += eccbytes;
+		}
+
+		if (mtd_writesize(md) + mtd_oobsize(md) > dst_offset) {
+			memcpy(md->buf + dst_offset,
+			       oobdata + nfc_geo->metadata_size_in_bytes + (i * eccbytes),
+			       mtd_writesize(md) + mtd_oobsize(md) - dst_offset);
+		}
+
+		free(data);
+	}
+
 	/* end of partition? */
 	if (r == 0)
 		return 0;
@@ -329,23 +368,71 @@ int mtd_write_page(struct mtd_data *md, int chip, loff_t ofs, int ecc)
 	int r;
 	const void *data;
 	const void *oobdata;
+	struct mtd_write_req ops;
 
 	mtd_set_ecc_mode(md, ecc);
 
-	data = md->buf;
-	oobdata = data + mtd_oobsize(md);
+	if (ecc) {
+		data = md->buf;
+		oobdata = data + mtd_writesize(md);
+	} else {
+		int i;
+		struct nfc_geometry *nfc_geo = &md->nfc_geometry;
+		int eccbytes = ((nfc_geo->ecc_strength * nfc_geo->gf_len) + 7) / 8;
+		int chunksize = nfc_geo->ecc_chunk_size_in_bytes;
+		int src_offset = 0;
+
+		data = malloc(mtd_writesize(md) + mtd_oobsize(md));
+		if (!data) {
+			fprintf(stderr, "mtd: %s failed to allocate buffer\n", __func__);
+			return -1;
+		}
+		oobdata = data + mtd_writesize(md);
+		memset(data, 0, mtd_writesize(md) + mtd_oobsize(md));
+		memcpy(oobdata, md->buf, nfc_geo->metadata_size_in_bytes);
+		src_offset += nfc_geo->metadata_size_in_bytes;
+		for (i = 0; i < nfc_geo->ecc_chunk_count; i++) {
+			memcpy(data + (i * chunksize), md->buf + src_offset, chunksize);
+			src_offset += chunksize;
+			memcpy(oobdata + nfc_geo->metadata_size_in_bytes + (i * eccbytes),
+			       md->buf + src_offset, eccbytes);
+			src_offset += eccbytes;
+		}
+
+		if (mtd_writesize(md) + mtd_oobsize(md) > src_offset) {
+			memcpy(oobdata + nfc_geo->metadata_size_in_bytes + (i * eccbytes),
+			       md->buf + src_offset,
+			       mtd_writesize(md) + mtd_oobsize(md) - src_offset);
+		}
+	}
 
 	/* make sure it's aligned to a page */
 	if ((ofs % mtd_writesize(md)) != 0) {
 		fprintf(stderr, "mtd: %s failed\n", __func__);
+		if (!ecc)
+			free(data);
 		return -1;
 	}
 
 	size = mtd_writesize(md);
 
+	ops.start = ofs;
+	ops.len = size;
+	ops.ooblen = ecc ? 0 : mtd_oobsize(md);
+	ops.usr_oob = (uint64_t)(unsigned long)oobdata;
+	ops.usr_data = (uint64_t)(unsigned long)data;
+	ops.mode = ecc ? MTD_OPS_AUTO_OOB : MTD_OPS_RAW;
+	r = ioctl(md->part[chip].fd, MEMWRITE, &ops);
+	if (!r)
+		r = size;
+	/*
 	do {
 		r = pwrite(md->part[chip].fd, data, size, ofs);
 	} while (r == -1 && (errno == EAGAIN || errno == EBUSY));
+	*/
+
+	if (!ecc)
+		free(data);
 
 	/* end of partition? */
 	if (r == 0) {
