diff mbox

[v5,2/3] mtd-utils: support >4GiB devices

Message ID 5e05b5a05a30b2dc2035b87a60bb82f3137174cb@localhost.localdomain
State New, archived
Headers show

Commit Message

Kevin Cernekee May 13, 2010, 2:23 a.m. UTC
This patch updates the following programs to handle >4GiB flash devices:

flash_erase
flash_eraseall
flashcp
mtd_debug
nanddump
nandtest
nandwrite

It also lays the groundwork for >4GiB support in:

flash_lock
flash_unlock

The latter two utilities would require MEMLOCK64 / MEMUNLOCK64
functionality on the kernel side (currently unimplemented).  For now
they still use MEMLOCK / MEMUNLOCK and cannot access blocks above 4GiB.

By default, the compatibility layer (mtd_ioctl.c) will attempt to use
the MTD sysfs interface and MEM*64 ioctls in 2.6.31+.  It will fall back
to the older ABI if it determines that the running kernel does not
support the new calls.

Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
---
 Makefile              |   19 +++-
 flash_erase.c         |   59 ++++++----
 flash_eraseall.c      |   31 +++--
 flash_lock.c          |   21 ++--
 flash_unlock.c        |    9 +-
 flashcp.c             |   22 ++--
 mtd_debug.c           |  114 ++++++++++---------
 mtd_ioctl.c           |  307 +++++++++++++++++++++++++++++++++++++++++++++++++
 mtd_ioctl.h           |   39 ++++++
 nanddump.c            |   23 +++--
 nandtest.c            |   35 +++---
 nandwrite.c           |   60 +++++-----
 13 files changed, 570 insertions(+), 171 deletions(-)
 create mode 100644 mtd_ioctl.c
 create mode 100644 mtd_ioctl.h

Comments

Artem Bityutskiy May 13, 2010, 10:11 a.m. UTC | #1
On Wed, 2010-05-12 at 19:23 -0700, Kevin Cernekee wrote:
> This patch updates the following programs to handle >4GiB flash devices:
> 
> flash_erase
> flash_eraseall
> flashcp
> mtd_debug
> nanddump
> nandtest
> nandwrite
> 
> It also lays the groundwork for >4GiB support in:
> 
> flash_lock
> flash_unlock
> 
> The latter two utilities would require MEMLOCK64 / MEMUNLOCK64
> functionality on the kernel side (currently unimplemented).  For now
> they still use MEMLOCK / MEMUNLOCK and cannot access blocks above 4GiB.
> 
> By default, the compatibility layer (mtd_ioctl.c) will attempt to use
> the MTD sysfs interface and MEM*64 ioctls in 2.6.31+.  It will fall back
> to the older ABI if it determines that the running kernel does not
> support the new calls.
> 
> Signed-off-by: Kevin Cernekee <cernekee@gmail.com>
> ---
>  Makefile              |   19 +++-
>  flash_erase.c         |   59 ++++++----
>  flash_eraseall.c      |   31 +++--
>  flash_lock.c          |   21 ++--
>  flash_unlock.c        |    9 +-
>  flashcp.c             |   22 ++--
>  mtd_debug.c           |  114 ++++++++++---------
>  mtd_ioctl.c           |  307 +++++++++++++++++++++++++++++++++++++++++++++++++
>  mtd_ioctl.h           |   39 ++++++
>  nanddump.c            |   23 +++--
>  nandtest.c            |   35 +++---
>  nandwrite.c           |   60 +++++-----
>  13 files changed, 570 insertions(+), 171 deletions(-)
>  create mode 100644 mtd_ioctl.c
>  create mode 100644 mtd_ioctl.h

Any chance to extend and use mtd-utils/ubi-utils/src/libmtd.c instead of
mtd_ioctl.c?
Artem Bityutskiy June 12, 2010, 11:36 a.m. UTC | #2
On Thu, 2010-05-13 at 13:11 +0300, Artem Bityutskiy wrote:
> >  nandwrite.c           |   60 +++++-----
> >  13 files changed, 570 insertions(+), 171 deletions(-)
> >  create mode 100644 mtd_ioctl.c
> >  create mode 100644 mtd_ioctl.h
> 
> Any chance to extend and use mtd-utils/ubi-utils/src/libmtd.c instead of
> mtd_ioctl.c?

Does silence mean that that answer is "no"? :-)
Artem Bityutskiy June 29, 2010, 6:35 a.m. UTC | #3
On Sat, 2010-06-12 at 14:36 +0300, Artem Bityutskiy wrote:
> On Thu, 2010-05-13 at 13:11 +0300, Artem Bityutskiy wrote:
> > >  nandwrite.c           |   60 +++++-----
> > >  13 files changed, 570 insertions(+), 171 deletions(-)
> > >  create mode 100644 mtd_ioctl.c
> > >  create mode 100644 mtd_ioctl.h
> > 
> > Any chance to extend and use mtd-utils/ubi-utils/src/libmtd.c instead of
> > mtd_ioctl.c?
> 
> Does silence mean that that answer is "no"? :-)

I have a dilemma whether to take your patches as they are or not :-) On
the one hand, they are needed, on the other hand, if we re-use libmtd.c,
we do not have duplicated code. libmtd.c is tested and it distinguish
beween old kernels (no sysfs support in mtd) and new kernels (expose
stuff via sysfs). It would be nice to share more code...

I guess I do not take your patches so far.
diff mbox

Patch

diff --git a/Makefile b/Makefile
index 577634f..5bf1292 100644
--- a/Makefile
+++ b/Makefile
@@ -41,7 +41,24 @@  $(BUILDDIR)/mkfs.jffs2: $(addprefix $(BUILDDIR)/,\
 LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
 LDLIBS_mkfs.jffs2  = -lz -llzo2
 
-$(BUILDDIR)/flash_eraseall: $(BUILDDIR)/crc32.o $(BUILDDIR)/flash_eraseall.o
+$(BUILDDIR)/flash_eraseall: $(BUILDDIR)/crc32.o $(BUILDDIR)/flash_eraseall.o \
+	$(BUILDDIR)/mtd_ioctl.o
+
+$(BUILDDIR)/flash_erase: $(BUILDDIR)/flash_erase.o $(BUILDDIR)/mtd_ioctl.o
+
+$(BUILDDIR)/nandwrite: $(BUILDDIR)/nandwrite.o $(BUILDDIR)/mtd_ioctl.o
+
+$(BUILDDIR)/nandtest: $(BUILDDIR)/nandtest.o $(BUILDDIR)/mtd_ioctl.o
+
+$(BUILDDIR)/nanddump: $(BUILDDIR)/nanddump.o $(BUILDDIR)/mtd_ioctl.o
+
+$(BUILDDIR)/flashcp: $(BUILDDIR)/flashcp.o $(BUILDDIR)/mtd_ioctl.o
+
+$(BUILDDIR)/flash_lock: $(BUILDDIR)/flash_lock.o $(BUILDDIR)/mtd_ioctl.o
+
+$(BUILDDIR)/flash_unlock: $(BUILDDIR)/flash_unlock.o $(BUILDDIR)/mtd_ioctl.o
+
+$(BUILDDIR)/mtd_debug: $(BUILDDIR)/mtd_debug.o $(BUILDDIR)/mtd_ioctl.o
 
 $(BUILDDIR)/jffs2reader: $(BUILDDIR)/jffs2reader.o
 LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
diff --git a/flash_erase.c b/flash_erase.c
index fdf9918..f689cf5 100644
--- a/flash_erase.c
+++ b/flash_erase.c
@@ -11,22 +11,25 @@ 
 #include <sys/ioctl.h>
 #include <sys/mount.h>
 #include <mtd/mtd-user.h>
+#include "mtd_ioctl.h"
 
-int region_erase(int Fd, int start, int count, int unlock, int regcount)
+int region_erase(int Fd, long long start, int count, int unlock, int regcount)
 {
 	int i, j;
-	region_info_t * reginfo;
+	region_info64_t * reginfo;
 
 	reginfo = calloc(regcount, sizeof(region_info_t));
 
 	for(i = 0; i < regcount; i++)
 	{
 		reginfo[i].regionindex = i;
-		if(ioctl(Fd,MEMGETREGIONINFO,&(reginfo[i])) != 0)
+		if(mtd_ioctl_getregioninfo(Fd,&(reginfo[i])) != 0)
 			return 8;
 		else
-			printf("Region %d is at %d of %d sector and with sector "
-					"size %x\n", i, reginfo[i].offset, reginfo[i].numblocks,
+			printf("Region %d is at %lld of %d sector and with sector "
+					"size %x\n", i,
+					(unsigned long long)reginfo[i].offset,
+					reginfo[i].numblocks,
 					reginfo[i].erasesize);
 	}
 
@@ -34,7 +37,7 @@  int region_erase(int Fd, int start, int count, int unlock, int regcount)
 
 	for(i = 0; i < regcount; i++)
 	{ //Loop through the regions
-		region_info_t * r = &(reginfo[i]);
+		region_info64_t * r = &(reginfo[i]);
 
 		if((start >= reginfo[i].offset) &&
 				(start < (r->offset + r->numblocks*r->erasesize)))
@@ -43,7 +46,7 @@  int region_erase(int Fd, int start, int count, int unlock, int regcount)
 
 	if(i >= regcount)
 	{
-		printf("Starting offset %x not within chip.\n", start);
+		printf("Starting offset %llx not within chip.\n", start);
 		return 8;
 	}
 
@@ -52,25 +55,28 @@  int region_erase(int Fd, int start, int count, int unlock, int regcount)
 
 	for(j = 0; (j < count)&&(i < regcount); j++)
 	{
-		erase_info_t erase;
-		region_info_t * r = &(reginfo[i]);
+		erase_info64_t erase;
+		region_info64_t * r = &(reginfo[i]);
+		
+		memset(&erase, 0, sizeof(erase));
 
 		erase.start = start;
 		erase.length = r->erasesize;
 
 		if(unlock != 0)
 		{ //Unlock the sector first.
-			if(ioctl(Fd, MEMUNLOCK, &erase) != 0)
+			if(mtd_ioctl_unlock(Fd, &erase) != 0)
 			{
 				perror("\nMTD Unlock failure");
 				close(Fd);
 				return 8;
 			}
 		}
-		printf("\rPerforming Flash Erase of length %u at offset 0x%x",
-				erase.length, erase.start);
+		printf("\rPerforming Flash Erase of length %llu at offset 0x%llx",
+				(unsigned long long)erase.length,
+				(unsigned long long)erase.start);
 		fflush(stdout);
-		if(ioctl(Fd, MEMERASE, &erase) != 0)
+		if(mtd_ioctl_erase(Fd, &erase) != 0)
 		{
 			perror("\nMTD Erase failure");
 			close(Fd);
@@ -91,28 +97,31 @@  int region_erase(int Fd, int start, int count, int unlock, int regcount)
 	return 0;
 }
 
-int non_region_erase(int Fd, int start, int count, int unlock)
+int non_region_erase(int Fd, long long start, int count, int unlock)
 {
-	mtd_info_t meminfo;
+	mtd_info64_t meminfo;
 
-	if (ioctl(Fd,MEMGETINFO,&meminfo) == 0)
+	if (mtd_ioctl_getinfo(Fd,&meminfo) == 0)
 	{
-		erase_info_t erase;
+		erase_info64_t erase;
 
-		erase.start = start;
+		memset(&erase, 0, sizeof(erase));
 
+		erase.start = start;
 		erase.length = meminfo.erasesize;
 
 		for (; count > 0; count--) {
-			printf("\rPerforming Flash Erase of length %u at offset 0x%x",
-					erase.length, erase.start);
+			printf("\rPerforming Flash Erase of length %llu at offset 0x%llx",
+					(unsigned long long)erase.length,
+					(unsigned long long)erase.start);
 			fflush(stdout);
 
 			if(unlock != 0)
 			{
 				//Unlock the sector first.
-				printf("\rPerforming Flash unlock at offset 0x%x",erase.start);
-				if(ioctl(Fd, MEMUNLOCK, &erase) != 0)
+				printf("\rPerforming Flash unlock at offset 0x%llx",
+					(unsigned long long)erase.start);
+				if(mtd_ioctl_unlock(Fd, &erase) != 0)
 				{
 					perror("\nMTD Unlock failure");
 					close(Fd);
@@ -120,7 +129,7 @@  int non_region_erase(int Fd, int start, int count, int unlock)
 				}
 			}
 
-			if (ioctl(Fd,MEMERASE,&erase) != 0)
+			if (mtd_ioctl_erase(Fd,&erase) != 0)
 			{
 				perror("\nMTD Erase failure");
 				close(Fd);
@@ -137,7 +146,7 @@  int main(int argc,char *argv[])
 {
 	int regcount;
 	int Fd;
-	int start;
+	long long start;
 	int count;
 	int unlock;
 	int res = 0;
@@ -149,7 +158,7 @@  int main(int argc,char *argv[])
 	}
 
 	if (argc > 2)
-		start = strtol(argv[2], NULL, 0);
+		start = strtoll(argv[2], NULL, 0);
 	else
 		start = 0;
 
diff --git a/flash_eraseall.c b/flash_eraseall.c
index a22fc49..8f44570 100644
--- a/flash_eraseall.c
+++ b/flash_eraseall.c
@@ -36,6 +36,7 @@ 
 #include <sys/ioctl.h>
 #include <sys/mount.h>
 #include "crc32.h"
+#include "mtd_ioctl.h"
 
 #include <mtd/mtd-user.h>
 #include <mtd/jffs2-user.h>
@@ -49,7 +50,7 @@  static int quiet;		/* true -- don't output progress */
 static int jffs2;		// format for jffs2 usage
 
 static void process_options (int argc, char *argv[]);
-void show_progress (mtd_info_t *meminfo, erase_info_t *erase);
+void show_progress (mtd_info64_t *meminfo, erase_info64_t *erase);
 static void display_help (void);
 static void display_version (void);
 static struct jffs2_unknown_node cleanmarker;
@@ -57,9 +58,9 @@  int target_endian = __BYTE_ORDER;
 
 int main (int argc, char *argv[])
 {
-	mtd_info_t meminfo;
+	mtd_info64_t meminfo;
 	int fd, clmpos = 0, clmlen = 8;
-	erase_info_t erase;
+	erase_info64_t erase;
 	int isNAND, bbtest = 1;
 
 	process_options(argc, argv);
@@ -70,11 +71,12 @@  int main (int argc, char *argv[])
 	}
 
 
-	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
+	if (mtd_ioctl_getinfo(fd, &meminfo) != 0) {
 		fprintf(stderr, "%s: %s: unable to get MTD device info\n", exe_name, mtd_device);
 		return 1;
 	}
 
+	memset(&erase, 0, sizeof(erase));
 	erase.length = meminfo.erasesize;
 	isNAND = meminfo.type == MTD_NANDFLASH ? 1 : 0;
 
@@ -130,7 +132,8 @@  int main (int argc, char *argv[])
 			int ret = ioctl(fd, MEMGETBADBLOCK, &offset);
 			if (ret > 0) {
 				if (!quiet)
-					printf ("\nSkipping bad block at 0x%08x\n", erase.start);
+					printf ("\nSkipping bad block at 0x%08llx\n",
+						(unsigned long long)erase.start);
 				continue;
 			} else if (ret < 0) {
 				if (errno == EOPNOTSUPP) {
@@ -149,7 +152,7 @@  int main (int argc, char *argv[])
 		if (!quiet)
 			show_progress(&meminfo, &erase);
 
-		if (ioctl(fd, MEMERASE, &erase) != 0) {
+		if (mtd_ioctl_erase(fd, &erase) != 0) {
 			fprintf(stderr, "\n%s: %s: MTD Erase failure: %s\n", exe_name, mtd_device, strerror(errno));
 			continue;
 		}
@@ -160,11 +163,12 @@  int main (int argc, char *argv[])
 
 		/* write cleanmarker */
 		if (isNAND) {
-			struct mtd_oob_buf oob;
-			oob.ptr = (unsigned char *) &cleanmarker;
+			struct mtd_oob_buf64 oob;
+			memset(&oob, 0, sizeof(oob));
+			oob.usr_ptr = (uintptr_t) &cleanmarker;
 			oob.start = erase.start + clmpos;
 			oob.length = clmlen;
-			if (ioctl (fd, MEMWRITEOOB, &oob) != 0) {
+			if (mtd_ioctl_writeoob(fd, &oob) != 0) {
 				fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno));
 				continue;
 			}
@@ -179,7 +183,8 @@  int main (int argc, char *argv[])
 			}
 		}
 		if (!quiet)
-			printf (" Cleanmarker written at %x.", erase.start);
+			printf (" Cleanmarker written at %llx.",
+				(unsigned long long)erase.start);
 	}
 	if (!quiet) {
 		show_progress(&meminfo, &erase);
@@ -250,10 +255,10 @@  void process_options (int argc, char *argv[])
 	mtd_device = argv[optind];
 }
 
-void show_progress (mtd_info_t *meminfo, erase_info_t *erase)
+void show_progress (mtd_info64_t *meminfo, erase_info64_t *erase)
 {
-	printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.",
-		meminfo->erasesize / 1024, erase->start,
+	printf("\rErasing %d Kibyte @ %llx -- %2llu %% complete.",
+		meminfo->erasesize / 1024, (unsigned long long)erase->start,
 		(unsigned long long) erase->start * 100 / meminfo->size);
 	fflush(stdout);
 }
diff --git a/flash_lock.c b/flash_lock.c
index 37f2ad3..a8a8241 100644
--- a/flash_lock.c
+++ b/flash_lock.c
@@ -15,14 +15,15 @@ 
 #include <string.h>
 
 #include <mtd/mtd-user.h>
+#include "mtd_ioctl.h"
 
 int main(int argc, char *argv[])
 {
 	int fd;
-	struct mtd_info_user mtdInfo;
-	struct erase_info_user mtdLockInfo;
-	int num_sectors;
-	int ofs;
+	struct mtd_info_user64 mtdInfo;
+	struct erase_info_user64 mtdLockInfo;
+	long long num_sectors;
+	long long ofs;
 
 	/*
 	 * Parse command line options
@@ -45,17 +46,17 @@  int main(int argc, char *argv[])
 		exit(1);
 	}
 
-	if(ioctl(fd, MEMGETINFO, &mtdInfo))
+	if(mtd_ioctl_getinfo(fd, &mtdInfo))
 	{
 		fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]);
 		close(fd);
 		exit(1);
 	}
-	sscanf(argv[2], "%x",&ofs);
-	sscanf(argv[3], "%d",&num_sectors);
+	sscanf(argv[2], "%llx",&ofs);
+	sscanf(argv[3], "%lld",&num_sectors);
 	if(ofs > mtdInfo.size - mtdInfo.erasesize)
 	{
-		fprintf(stderr, "%x is beyond device size %x\n",ofs,(unsigned int)(mtdInfo.size - mtdInfo.erasesize));
+		fprintf(stderr, "%llx is beyond device size %llx\n",ofs,(unsigned long long)(mtdInfo.size - mtdInfo.erasesize));
 		exit(1);
 	}
 
@@ -65,14 +66,14 @@  int main(int argc, char *argv[])
 	else {
 		if(num_sectors > mtdInfo.size/mtdInfo.erasesize)
 		{
-			fprintf(stderr, "%d are too many sectors, device only has %d\n",num_sectors,(int)(mtdInfo.size/mtdInfo.erasesize));
+			fprintf(stderr, "%lld are too many sectors, device only has %lld\n",num_sectors,(long long)(mtdInfo.size/mtdInfo.erasesize));
 			exit(1);
 		}
 	}
 
 	mtdLockInfo.start = ofs;
 	mtdLockInfo.length = (num_sectors - 1) * mtdInfo.erasesize;
-	if(ioctl(fd, MEMLOCK, &mtdLockInfo))
+	if(mtd_ioctl_lock(fd, &mtdLockInfo))
 	{
 		fprintf(stderr, "Could not lock MTD device: %s\n", argv[1]);
 		close(fd);
diff --git a/flash_unlock.c b/flash_unlock.c
index 3969453..9921996 100644
--- a/flash_unlock.c
+++ b/flash_unlock.c
@@ -15,12 +15,13 @@ 
 #include <string.h>
 
 #include <mtd/mtd-user.h>
+#include "mtd_ioctl.h"
 
 int main(int argc, char *argv[])
 {
 	int fd;
-	struct mtd_info_user mtdInfo;
-	struct erase_info_user mtdLockInfo;
+	struct mtd_info_user64 mtdInfo;
+	struct erase_info_user64 mtdLockInfo;
 	int count;
 
 	/*
@@ -44,7 +45,7 @@  int main(int argc, char *argv[])
 		exit(1);
 	}
 
-	if(ioctl(fd, MEMGETINFO, &mtdInfo))
+	if(mtd_ioctl_getinfo(fd, &mtdInfo))
 	{
 		fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]);
 		close(fd);
@@ -63,7 +64,7 @@  int main(int argc, char *argv[])
 		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
 	}
 
-	if(ioctl(fd, MEMUNLOCK, &mtdLockInfo))
+	if(mtd_ioctl_unlock(fd, &mtdLockInfo))
 	{
 		fprintf(stderr, "Could not unlock MTD device: %s\n", argv[1]);
 		close(fd);
diff --git a/flashcp.c b/flashcp.c
index 8775022..d9bab84 100644
--- a/flashcp.c
+++ b/flashcp.c
@@ -40,6 +40,7 @@ 
 #include <unistd.h>
 #include <mtd/mtd-user.h>
 #include <getopt.h>
+#include "mtd_ioctl.h"
 
 typedef int bool;
 #define true 1
@@ -169,8 +170,8 @@  int main (int argc,char *argv[])
 	int i,flags = FLAG_NONE;
 	ssize_t result;
 	size_t size,written;
-	struct mtd_info_user mtd;
-	struct erase_info_user erase;
+	struct mtd_info_user64 mtd;
+	struct erase_info_user64 erase;
 	struct stat filestat;
 	unsigned char src[BUFSIZE],dest[BUFSIZE];
 
@@ -226,7 +227,7 @@  int main (int argc,char *argv[])
 
 	/* get some info about the flash device */
 	dev_fd = safe_open (device,O_SYNC | O_RDWR);
-	if (ioctl (dev_fd,MEMGETINFO,&mtd) < 0)
+	if (mtd_ioctl_getinfo (dev_fd,&mtd) < 0)
 	{
 		DEBUG("ioctl(): %m\n");
 		log_printf (LOG_ERROR,"This doesn't seem to be a valid MTD flash device!\n");
@@ -254,6 +255,7 @@  int main (int argc,char *argv[])
 
 #warning "Check for smaller erase regions"
 
+	memset(&erase, 0, sizeof(erase));
 	erase.start = 0;
 	erase.length = (filestat.st_size + mtd.erasesize - 1) / mtd.erasesize;
 	erase.length *= mtd.erasesize;
@@ -261,18 +263,18 @@  int main (int argc,char *argv[])
 	if (flags & FLAG_VERBOSE)
 	{
 		/* if the user wants verbose output, erase 1 block at a time and show him/her what's going on */
-		int blocks = erase.length / mtd.erasesize;
+		long long blocks = erase.length / mtd.erasesize;
 		erase.length = mtd.erasesize;
 		log_printf (LOG_NORMAL,"Erasing blocks: 0/%d (0%%)",blocks);
 		for (i = 1; i <= blocks; i++)
 		{
 			log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (%d%%)",i,blocks,PERCENTAGE (i,blocks));
-			if (ioctl (dev_fd,MEMERASE,&erase) < 0)
+			if (mtd_ioctl_erase (dev_fd, &erase) < 0)
 			{
 				log_printf (LOG_NORMAL,"\n");
 				log_printf (LOG_ERROR,
-						"While erasing blocks 0x%.8x-0x%.8x on %s: %m\n",
-						(unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device);
+						"While erasing blocks 0x%.8llx-0x%.8llx on %s: %m\n",
+						erase.start, (erase.start + erase.length),device);
 				exit (EXIT_FAILURE);
 			}
 			erase.start += mtd.erasesize;
@@ -282,11 +284,11 @@  int main (int argc,char *argv[])
 	else
 	{
 		/* if not, erase the whole chunk in one shot */
-		if (ioctl (dev_fd,MEMERASE,&erase) < 0)
+		if (mtd_ioctl_erase (dev_fd, &erase) < 0)
 		{
 			log_printf (LOG_ERROR,
-					"While erasing blocks from 0x%.8x-0x%.8x on %s: %m\n",
-					(unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device);
+					"While erasing blocks from 0x%.8llx-0x%.8llx on %s: %m\n",
+					erase.start, (erase.start + erase.length),device);
 			exit (EXIT_FAILURE);
 		}
 	}
diff --git a/mtd_debug.c b/mtd_debug.c
index 49a4567..1020fe2 100644
--- a/mtd_debug.c
+++ b/mtd_debug.c
@@ -37,28 +37,13 @@ 
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <mtd/mtd-user.h>
-
-/*
- * MEMGETINFO
- */
-static int getmeminfo (int fd,struct mtd_info_user *mtd)
-{
-	return (ioctl (fd,MEMGETINFO,mtd));
-}
-
-/*
- * MEMERASE
- */
-static int memerase (int fd,struct erase_info_user *erase)
-{
-	return (ioctl (fd,MEMERASE,erase));
-}
+#include "mtd_ioctl.h"
 
 /*
  * MEMGETREGIONCOUNT
- * MEMGETREGIONINFO
+ * MEMGETREGIONINFO64
  */
-static int getregions (int fd,struct region_info_user *regions,int *n)
+static int getregions (int fd,struct region_info_user64 *regions,int *n)
 {
 	int i,err;
 	err = ioctl (fd,MEMGETREGIONCOUNT,n);
@@ -66,44 +51,48 @@  static int getregions (int fd,struct region_info_user *regions,int *n)
 	for (i = 0; i < *n; i++)
 	{
 		regions[i].regionindex = i;
-		err = ioctl (fd,MEMGETREGIONINFO,&regions[i]);
+		err = mtd_ioctl_getregioninfo (fd,&regions[i]);
 		if (err) return (err);
 	}
 	return (0);
 }
 
-int erase_flash (int fd,u_int32_t offset,u_int32_t bytes)
+int erase_flash (int fd,u_int64_t offset,u_int64_t bytes)
 {
 	int err;
-	struct erase_info_user erase;
+	struct erase_info_user64 erase;
+
+	memset(&erase, 0, sizeof(erase));
 	erase.start = offset;
 	erase.length = bytes;
-	err = memerase (fd,&erase);
+
+	err = mtd_ioctl_erase (fd,&erase);
 	if (err < 0)
 	{
 		perror ("MEMERASE");
 		return (1);
 	}
-	fprintf (stderr,"Erased %d bytes from address 0x%.8x in flash\n",bytes,offset);
+	fprintf (stderr,"Erased %lld bytes from address 0x%.8llx in flash\n",
+		(unsigned long long)bytes, (unsigned long long)offset);
 	return (0);
 }
 
-void printsize (u_int32_t x)
+void printsize (u_int64_t x)
 {
 	int i;
 	static const char *flags = "KMGT";
-	printf ("%u ",x);
+	printf ("%llu ", (unsigned long long)x);
 	for (i = 0; x >= 1024 && flags[i] != '\0'; i++) x /= 1024;
 	i--;
-	if (i >= 0) printf ("(%u%c)",x,flags[i]);
+	if (i >= 0) printf ("(%llu%c)",(unsigned long long)x,flags[i]);
 }
 
-int flash_to_file (int fd,u_int32_t offset,size_t len,const char *filename)
+int flash_to_file (int fd, off_t offset,size_t len,const char *filename)
 {
 	u_int8_t *buf = NULL;
 	int outfd,err;
-	int size = len * sizeof (u_int8_t);
-	int n = len;
+	size_t size = len * sizeof (u_int8_t);
+	size_t n = len;
 
 	if (offset != lseek (fd,offset,SEEK_SET))
 	{
@@ -121,10 +110,12 @@  retry:
 	if ((buf = (u_int8_t *) malloc (size)) == NULL)
 	{
 #define BUF_SIZE	(64 * 1024 * sizeof (u_int8_t))
-		fprintf (stderr, "%s: malloc(%#x)\n", __FUNCTION__, size);
+		fprintf (stderr, "%s: malloc(%#x)\n", __FUNCTION__,
+			(unsigned int)size);
 		if (size != BUF_SIZE) {
 			size = BUF_SIZE;
-			fprintf (stderr, "%s: trying buffer size %#x\n", __FUNCTION__, size);
+			fprintf (stderr, "%s: trying buffer size %#x\n",
+				__FUNCTION__, (unsigned int)size);
 			goto retry;
 		}
 		perror ("malloc()");
@@ -136,20 +127,25 @@  retry:
 		err = read (fd,buf,size);
 		if (err < 0)
 		{
-			fprintf (stderr, "%s: read, size %#x, n %#x\n", __FUNCTION__, size, n);
+			fprintf (stderr, "%s: read, size %#x, n %#x\n",
+				__FUNCTION__, (unsigned int)size,
+				(unsigned int)n);
 			perror ("read()");
 			goto err2;
 		}
 		err = write (outfd,buf,size);
 		if (err < 0)
 		{
-			fprintf (stderr, "%s: write, size %#x, n %#x\n", __FUNCTION__, size, n);
+			fprintf (stderr, "%s: write, size %#x, n %#x\n",
+				__FUNCTION__, (unsigned int)size,
+				(unsigned int)n);
 			perror ("write()");
 			goto err2;
 		}
 		if (err != size)
 		{
-			fprintf (stderr,"Couldn't copy entire buffer to %s. (%d/%d bytes copied)\n",filename,err,size);
+			fprintf (stderr,"Couldn't copy entire buffer to %s. (%d/%d bytes copied)\n",
+				filename,err,(int)size);
 			goto err2;
 		}
 		n -= size;
@@ -158,7 +154,8 @@  retry:
 	if (buf != NULL)
 		free (buf);
 	close (outfd);
-	printf ("Copied %d bytes from address 0x%.8x in flash to %s\n",len,offset,filename);
+	printf ("Copied %d bytes from address 0x%.8llx in flash to %s\n",
+		(int)len,(unsigned long long)offset,filename);
 	return (0);
 
 err2:
@@ -170,13 +167,13 @@  err0:
 	return (1);
 }
 
-int file_to_flash (int fd,u_int32_t offset,u_int32_t len,const char *filename)
+int file_to_flash (int fd, off_t offset, size_t len,const char *filename)
 {
 	u_int8_t *buf = NULL;
 	FILE *fp;
 	int err;
-	int size = len * sizeof (u_int8_t);
-	int n = len;
+	size_t size = len * sizeof (u_int8_t);
+	size_t n = len;
 
 	if (offset != lseek (fd,offset,SEEK_SET))
 	{
@@ -191,10 +188,12 @@  int file_to_flash (int fd,u_int32_t offset,u_int32_t len,const char *filename)
 retry:
 	if ((buf = (u_int8_t *) malloc (size)) == NULL)
 	{
-		fprintf (stderr, "%s: malloc(%#x) failed\n", __FUNCTION__, size);
+		fprintf (stderr, "%s: malloc(%#x) failed\n",
+			__FUNCTION__, (int)size);
 		if (size != BUF_SIZE) {
 			size = BUF_SIZE;
-			fprintf (stderr, "%s: trying buffer size %#x\n", __FUNCTION__, size);
+			fprintf (stderr, "%s: trying buffer size %#x\n",
+				__FUNCTION__, (int)size);
 			goto retry;
 		}
 		perror ("malloc()");
@@ -206,7 +205,9 @@  retry:
 			size = n;
 		if (fread (buf,size,1,fp) != 1 || ferror (fp))
 		{
-			fprintf (stderr, "%s: fread, size %#x, n %#x\n", __FUNCTION__, size, n);
+			fprintf (stderr, "%s: fread, size %#x, n %#x\n",
+				__FUNCTION__, (unsigned int)size,
+				(unsigned int)n);
 			perror ("fread()");
 			free (buf);
 			fclose (fp);
@@ -215,7 +216,9 @@  retry:
 		err = write (fd,buf,size);
 		if (err < 0)
 		{
-			fprintf (stderr, "%s: write, size %#x, n %#x\n", __FUNCTION__, size, n);
+			fprintf (stderr, "%s: write, size %#x, n %#x\n",
+				__FUNCTION__, (unsigned int)size,
+				(unsigned int)n);
 			perror ("write()");
 			free (buf);
 			fclose (fp);
@@ -227,23 +230,26 @@  retry:
 	if (buf != NULL)
 		free (buf);
 	fclose (fp);
-	printf ("Copied %d bytes from %s to address 0x%.8x in flash\n",len,filename,offset);
+	printf ("Copied %d bytes from %s to address 0x%.8llx in flash\n",
+		(int)len,filename,(unsigned long long)offset);
 	return (0);
 }
 
 int showinfo (int fd)
 {
 	int i,err,n;
-	struct mtd_info_user mtd;
-	static struct region_info_user region[1024];
+	struct mtd_info_user64 mtd;
+	static struct region_info_user64 region[1024];
 
-	err = getmeminfo (fd,&mtd);
+	err = mtd_ioctl_getinfo (fd,&mtd);
 	if (err < 0)
 	{
-		perror ("MEMGETINFO");
+		perror ("MEMGETINFO64");
 		return (1);
 	}
 
+	memset(region, 0, sizeof(region));
+
 	err = getregions (fd,region,&n);
 	if (err < 0)
 	{
@@ -301,7 +307,7 @@  int showinfo (int fd)
 			{ "MTD_WRITEABLE", MTD_WRITEABLE },
 			{ "MTD_BIT_WRITEABLE", MTD_BIT_WRITEABLE },
 			{ "MTD_NO_ERASE", MTD_NO_ERASE },
-			{ "MTD_STUPID_LOCK", MTD_STUPID_LOCK },
+			{ "MTD_POWERUP_LOCK", MTD_POWERUP_LOCK },
 			{ NULL, -1 }
 		};
 		for (i = 0; flags[i].name != NULL; i++)
@@ -309,7 +315,7 @@  int showinfo (int fd)
 			{
 				if (first)
 				{
-					printf (flags[i].name);
+					printf ("%s", flags[i].name);
 					first = 0;
 				}
 				else printf (" | %s",flags[i].name);
@@ -335,9 +341,9 @@  int showinfo (int fd)
 
 	for (i = 0; i < n; i++)
 	{
-		printf ("region[%d].offset = 0x%.8x\n"
+		printf ("region[%d].offset = 0x%.8llx\n"
 				"region[%d].erasesize = ",
-				i,region[i].offset,i);
+				i,(unsigned long long)region[i].offset,i);
 		printsize (region[i].erasesize);
 		printf ("\nregion[%d].numblocks = %d\n"
 				"region[%d].regionindex = %d\n",
@@ -399,13 +405,13 @@  int main (int argc,char *argv[])
 			showinfo (fd);
 			break;
 		case OPT_READ:
-			err = flash_to_file (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0),argv[5]);
+			err = flash_to_file (fd,strtoll (argv[3],NULL,0),strtoll (argv[4],NULL,0),argv[5]);
 			break;
 		case OPT_WRITE:
-			err = file_to_flash (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0),argv[5]);
+			err = file_to_flash (fd,strtoll (argv[3],NULL,0),strtoll (argv[4],NULL,0),argv[5]);
 			break;
 		case OPT_ERASE:
-			err = erase_flash (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0));
+			err = erase_flash (fd,strtoll (argv[3],NULL,0),strtoll (argv[4],NULL,0));
 			break;
 	}
 
diff --git a/mtd_ioctl.c b/mtd_ioctl.c
new file mode 100644
index 0000000..d19dcd3
--- /dev/null
+++ b/mtd_ioctl.c
@@ -0,0 +1,307 @@ 
+/*
+ * mtd_ioctl.c - backward compatibility wrappers for MTD ioctls
+ */
+
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <mtd/mtd-user.h>
+#include "mtd_ioctl.h"
+
+#define BUF_LEN		64
+
+static int use_old_abi = 0;
+
+static int try_new_ioctl(int fd, unsigned int cmd, unsigned long arg, int *retp)
+{
+	int ret;
+
+	if(use_old_abi)
+		return(0);
+	ret = ioctl(fd, cmd, arg);
+	if((ret < 0) && (errno == ENOTTY)) {
+		use_old_abi = 1;
+		return(0);
+	}
+	*retp = ret;
+	return(1);
+}
+
+/**
+ * mkpath - compose full path from 2 given components.
+ * @path: the first component
+ * @name: the second component
+ *
+ * This function returns the resulting path in case of success and %NULL in
+ * case of failure.
+ */
+static char *mkpath(const char *path, const char *name)
+{
+	char *n;
+	int len1 = strlen(path);
+	int len2 = strlen(name);
+
+	n = malloc(len1 + len2 + 2);
+	if (!n) {
+		return NULL;
+	}
+
+	memcpy(n, path, len1);
+	if (n[len1 - 1] != '/')
+		n[len1++] = '/';
+
+	memcpy(n + len1, name, len2 + 1);
+	return n;
+}
+
+/**
+ * read_data - read data from a file.
+ * @file: the file to read from
+ * @buf: the buffer to read to
+ * @buf_len: buffer length
+ *
+ * This function returns number of read bytes in case of success and %-1 in
+ * case of failure. Note, if the file contains more then @buf_len bytes of
+ * date, this function fails with %EINVAL error code.
+ */
+static int sysfs_get_str(const char *prefix, const char *element,
+	char *buf, int buf_len)
+{
+	int fd, rd, tmp, tmp1;
+	char *file = mkpath(prefix, element), *sep;
+
+	if(! file)
+		return -1;
+
+	fd = open(file, O_RDONLY);
+	if (fd == -1) {
+		free(file);
+		return -1;
+	}
+
+	rd = read(fd, buf, buf_len);
+	if (rd == -1) {
+		goto out_error;
+	}
+
+	/* Make sure all data is read */
+	tmp1 = read(fd, &tmp, 1);
+	if (tmp1 == 1) {
+		goto out_error;
+	}
+	if (tmp1) {
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	if (close(fd)) {
+		rd = -1;
+	}
+
+	sep = index(buf, '\n');
+	if(sep)
+		*sep = 0;
+	else
+		buf[buf_len - 1] = 0;
+
+	free(file);
+	return rd;
+
+out_error:
+	close(fd);
+	free(file);
+	return -1;
+}
+
+static int sysfs_get_ull(const char *prefix, const char *element,
+	unsigned long long *out)
+{
+	int ret;
+	char buf[BUF_LEN];
+
+	ret = sysfs_get_str(prefix, element, buf, BUF_LEN);
+	if(ret <= 0)
+		return(ret);
+	
+	if(sscanf(buf, "0x%llx", out) == 1)
+		return(0);
+	
+	if(sscanf(buf, "%llu", out) == 1)
+		return(0);
+
+	return(-1);
+}
+
+int mtd_ioctl_getinfo(int fd, struct mtd_info_user64 *arg)
+{
+	int ret;
+	struct mtd_info_user oldarg;
+	struct stat st;
+	char prefix[BUF_LEN], str[BUF_LEN];
+	unsigned long long tmp;
+
+	if((fstat(fd, &st) < 0) || !S_ISCHR(st.st_mode))
+		return(-1);
+	
+	snprintf(prefix, BUF_LEN, "/sys/class/mtd/mtd%d/",
+		minor(st.st_rdev) >> 1);
+
+	if(sysfs_get_str(prefix, "type", str, BUF_LEN) > 0) {
+		if(strcasecmp(str, "absent") == 0)
+			arg->type = MTD_ABSENT;
+		else if(strcasecmp(str, "ram") == 0)
+			arg->type = MTD_RAM;
+		else if(strcasecmp(str, "rom") == 0)
+			arg->type = MTD_ROM;
+		else if(strcasecmp(str, "nor") == 0)
+			arg->type = MTD_NORFLASH;
+		else if(strcasecmp(str, "nand") == 0)
+			arg->type = MTD_NANDFLASH;
+		else if(strcasecmp(str, "dataflash") == 0)
+			arg->type = MTD_DATAFLASH;
+		else if(strcasecmp(str, "ubi") == 0)
+			arg->type = MTD_UBIVOLUME;
+		else
+			return(-1);
+
+		if(sysfs_get_ull(prefix, "flags", &tmp) != 0)
+			return(-1);
+		arg->flags = tmp;
+
+		if(sysfs_get_ull(prefix, "size", &tmp) != 0)
+			return(-1);
+		arg->size = tmp;
+
+		if(sysfs_get_ull(prefix, "erasesize", &tmp) != 0)
+			return(-1);
+		arg->erasesize = tmp;
+
+		if(sysfs_get_ull(prefix, "writesize", &tmp) != 0)
+			return(-1);
+		arg->writesize = tmp;
+
+		if(sysfs_get_ull(prefix, "oobsize", &tmp) != 0)
+			return(-1);
+		arg->oobsize = tmp;
+
+		return(0);
+	}
+
+	ret = ioctl(fd, MEMGETINFO, (unsigned long)&oldarg);
+	if(ret < 0)
+		return(ret);
+	
+	arg->type = oldarg.type;
+	arg->flags = oldarg.flags;
+	arg->size = oldarg.size;
+	arg->erasesize = oldarg.erasesize;
+	arg->writesize = oldarg.writesize;
+	arg->oobsize = oldarg.oobsize;
+
+	return(ret);
+}
+
+int mtd_ioctl_erase(int fd, struct erase_info_user64 *arg)
+{
+	int ret;
+	struct erase_info_user oldarg;
+
+	if(try_new_ioctl(fd, MEMERASE64, (unsigned long)arg, &ret) != 0)
+		return(ret);
+	
+	oldarg.start = arg->start;
+	oldarg.length = arg->length;
+
+	return(ioctl(fd, MEMERASE, (unsigned long)&oldarg));
+}
+
+int mtd_ioctl_writeoob(int fd, struct mtd_oob_buf64 *arg)
+{
+	int ret;
+	struct mtd_oob_buf oldarg;
+
+	if(try_new_ioctl(fd, MEMWRITEOOB64, (unsigned long)arg, &ret) != 0)
+		return(ret);
+	
+	oldarg.start = arg->start;
+	oldarg.length = arg->length;
+	oldarg.ptr = (void *)(uintptr_t)arg->usr_ptr;
+
+	ret = ioctl(fd, MEMWRITEOOB, (unsigned long)&oldarg);
+
+	arg->length = oldarg.length;
+	return(ret);
+}
+
+int mtd_ioctl_readoob(int fd, struct mtd_oob_buf64 *arg)
+{
+	int ret;
+	struct mtd_oob_buf oldarg;
+
+	if(try_new_ioctl(fd, MEMREADOOB64, (unsigned long)arg, &ret) != 0)
+		return(ret);
+	
+	oldarg.start = arg->start;
+	oldarg.length = arg->length;
+	oldarg.ptr = (void *)(uintptr_t)arg->usr_ptr;
+
+	ret = ioctl(fd, MEMREADOOB, (unsigned long)&oldarg);
+
+	/* old ABI puts returned length in "start" */
+	arg->length = oldarg.start;
+	return(ret);
+}
+
+int mtd_ioctl_lock(int fd, struct erase_info_user64 *arg)
+{
+	struct erase_info_user oldarg;
+#ifdef MEMLOCK64
+	int ret;
+
+	if(try_new_ioctl(fd, MEMLOCK64, (unsigned long)arg, &ret) != 0)
+		return(ret);
+#endif
+
+	oldarg.start = arg->start;
+	oldarg.length = arg->length;
+
+	return(ioctl(fd, MEMLOCK, (unsigned long)&oldarg));
+}
+
+int mtd_ioctl_unlock(int fd, struct erase_info_user64 *arg)
+{
+	struct erase_info_user oldarg;
+#ifdef MEMUNLOCK64
+	int ret;
+
+	if(try_new_ioctl(fd, MEMUNLOCK64, (unsigned long)arg, &ret) != 0)
+		return(ret);
+#endif
+	
+	oldarg.start = arg->start;
+	oldarg.length = arg->length;
+
+	return(ioctl(fd, MEMUNLOCK, (unsigned long)&oldarg));
+}
+
+int mtd_ioctl_getregioninfo(int fd, struct region_info_user64 *arg)
+{
+	int ret;
+	struct region_info_user oldarg;
+
+	oldarg.regionindex = arg->regionindex;
+
+	ret = ioctl(fd, MEMGETREGIONINFO, (unsigned long)&oldarg);
+
+	arg->offset = oldarg.offset;
+	arg->erasesize = oldarg.erasesize;
+	arg->numblocks = oldarg.numblocks;
+
+	return(ret);
+}
diff --git a/mtd_ioctl.h b/mtd_ioctl.h
new file mode 100644
index 0000000..a479793
--- /dev/null
+++ b/mtd_ioctl.h
@@ -0,0 +1,39 @@ 
+/*
+ * mtd_ioctl.h - backward compatibility wrappers for MTD ioctls
+ */
+
+#ifndef _MTD_IOCTL_H
+#define _MTD_IOCTL_H
+
+#include <mtd/mtd-user.h>
+
+struct region_info_user64 {
+	uint64_t offset;		/* At which this region starts,
+					 * from the beginning of the MTD */
+	uint32_t erasesize;		/* For this region */
+	uint32_t numblocks;		/* Number of blocks in this region */
+	uint32_t regionindex;
+};
+
+struct mtd_info_user64 {
+	uint32_t type;
+	uint32_t flags;
+	uint64_t size;			/* Total size of the MTD */
+	uint32_t erasesize;
+	uint32_t writesize;
+	uint32_t oobsize;		/* OOB bytes per page (e.g. 16) */
+};
+
+typedef struct mtd_info_user64 mtd_info64_t;
+typedef struct region_info_user64 region_info64_t;
+typedef struct erase_info_user64 erase_info64_t;
+
+int mtd_ioctl_getinfo(int fd, struct mtd_info_user64 *arg);
+int mtd_ioctl_erase(int fd, struct erase_info_user64 *arg);
+int mtd_ioctl_writeoob(int fd, struct mtd_oob_buf64 *arg);
+int mtd_ioctl_readoob(int fd, struct mtd_oob_buf64 *arg);
+int mtd_ioctl_lock(int fd, struct erase_info_user64 *arg);
+int mtd_ioctl_unlock(int fd, struct erase_info_user64 *arg);
+int mtd_ioctl_getregioninfo(int fd, struct region_info_user64 *arg);
+
+#endif /* !_MTD_IOCTL_H */
diff --git a/nanddump.c b/nanddump.c
index ae0e425..6f101d2 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -29,6 +29,7 @@ 
 
 #include <asm/types.h>
 #include <mtd/mtd-user.h>
+#include "mtd_ioctl.h"
 
 #define PROGRAM "nanddump"
 #define VERSION "$Revision: 1.29 $"
@@ -182,11 +183,15 @@  static unsigned char oobbuf[128];
  */
 int main(int argc, char * const argv[])
 {
-	unsigned long ofs, end_addr = 0;
+	unsigned long long ofs, end_addr = 0;
 	unsigned long long blockstart = 1;
 	int ret, i, fd, ofd, bs, badblock = 0;
-	struct mtd_oob_buf oob = {0, 16, oobbuf};
-	mtd_info_t meminfo;
+	struct mtd_oob_buf64 oob = {	
+		.start = 0,
+		.length = 16,
+		.usr_ptr = (uintptr_t)oobbuf,
+	};
+	mtd_info64_t meminfo;
 	char pretty_buf[80];
 	int oobinfochanged = 0 ;
 	struct nand_oobinfo old_oobinfo;
@@ -202,8 +207,8 @@  int main(int argc, char * const argv[])
 	}
 
 	/* Fill in MTD device capability structure */
-	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
-		perror("MEMGETINFO");
+	if (mtd_ioctl_getinfo(fd, &meminfo) != 0) {
+		perror("MEMGETINFO64");
 		close(fd);
 		exit (EXIT_FAILURE);
 	}
@@ -322,11 +327,11 @@  int main(int argc, char * const argv[])
 			}
 			if (stat1.failed != stat2.failed)
 				fprintf(stderr, "ECC: %d uncorrectable bitflip(s)"
-						" at offset 0x%08lx\n",
+						" at offset 0x%08llx\n",
 						stat2.failed - stat1.failed, ofs);
 			if (stat1.corrected != stat2.corrected)
 				fprintf(stderr, "ECC: %d corrected bitflip(s) at"
-						" offset 0x%08lx\n",
+						" offset 0x%08llx\n",
 						stat2.corrected - stat1.corrected, ofs);
 			stat1 = stat2;
 		}
@@ -361,8 +366,8 @@  int main(int argc, char * const argv[])
 		} else {
 			/* Read OOB data and exit on failure */
 			oob.start = ofs;
-			if (ioctl(fd, MEMREADOOB, &oob) != 0) {
-				perror("ioctl(MEMREADOOB)");
+			if (mtd_ioctl_readoob(fd, &oob) != 0) {
+				perror("ioctl(MEMREADOOB64)");
 				goto closeall;
 			}
 		}
diff --git a/nandtest.c b/nandtest.c
index e31e28a..ef31130 100644
--- a/nandtest.c
+++ b/nandtest.c
@@ -14,6 +14,7 @@ 
 
 #include <asm/types.h>
 #include "mtd/mtd-user.h"
+#include "mtd_ioctl.h"
 
 void usage(void)
 {
@@ -28,7 +29,7 @@  void usage(void)
 	exit(1);
 }
 
-struct mtd_info_user meminfo;
+struct mtd_info_user64 meminfo;
 struct mtd_ecc_stats oldstats, newstats;
 int fd;
 int markbad=0;
@@ -36,26 +37,28 @@  int seed;
 
 int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf)
 {
-	struct erase_info_user er;
+	struct erase_info_user64 er;
 	ssize_t len;
 	int i;
 
-	printf("\r%08x: erasing... ", (unsigned)ofs);
+	printf("\r%08llx: erasing... ", ofs);
 	fflush(stdout);
 
+	memset(&er, 0, sizeof(er));
+
 	er.start = ofs;
 	er.length = meminfo.erasesize;
 
-	if (ioctl(fd, MEMERASE, &er)) {
-		perror("MEMERASE");
+	if (mtd_ioctl_erase(fd, &er)) {
+		perror("MEMERASE64");
 		if (markbad) {
-			printf("Mark block bad at %08lx\n", (long)ofs);
+			printf("Mark block bad at %08llx\n", ofs);
 			ioctl(fd, MEMSETBADBLOCK, &ofs);
 		}
 		return 1;
 	}
 
-	printf("\r%08x: writing...", (unsigned)ofs);
+	printf("\r%08llx: writing...", ofs);
 	fflush(stdout);
 
 	len = pwrite(fd, data, meminfo.erasesize, ofs);
@@ -132,8 +135,8 @@  int main(int argc, char **argv)
 	int pass;
 	int nr_passes = 1;
 	int keep_contents = 0;
-	uint32_t offset = 0;
-	uint32_t length = -1;
+	uint64_t offset = 0;
+	uint64_t length = -1;
 
 	for (;;) {
 		static const char *short_options="hkl:mo:p:s:";
@@ -175,11 +178,11 @@  int main(int argc, char **argv)
 			break;
 
 		case 'o':
-			offset = atol(optarg);
+			offset = atoll(optarg);
 			break;
 
 		case 'l':
-			length = strtol(optarg, NULL, 0);
+			length = strtoll(optarg, NULL, 0);
 			break;
 			
 		}
@@ -193,8 +196,8 @@  int main(int argc, char **argv)
 		exit(1);
 	}
 	
-	if (ioctl(fd, MEMGETINFO, &meminfo)) {
-		perror("MEMGETINFO");
+	if (mtd_ioctl_getinfo(fd, &meminfo)) {
+		perror("MEMGETINFO64");
 		close(fd);
 		exit(1);
 	}
@@ -203,17 +206,17 @@  int main(int argc, char **argv)
 		length = meminfo.size;
 
 	if (offset % meminfo.erasesize) {
-		fprintf(stderr, "Offset %x not multiple of erase size %x\n", 
+		fprintf(stderr, "Offset %llx not multiple of erase size %x\n",
 			offset, meminfo.erasesize);
 		exit(1);
 	}
 	if (length % meminfo.erasesize) {
-		fprintf(stderr, "Length %x not multiple of erase size %x\n", 
+		fprintf(stderr, "Length %llx not multiple of erase size %x\n", 
 			length, meminfo.erasesize);
 		exit(1);
 	}
 	if (length + offset > meminfo.size) {
-		fprintf(stderr, "Length %x + offset %x exceeds device size %x\n", 
+		fprintf(stderr, "Length %llx + offset %llx exceeds device size %llx\n",
 			length, offset, meminfo.size);
 		exit(1);
 	}		
diff --git a/nandwrite.c b/nandwrite.c
index b77edd6..9684b95 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -38,6 +38,7 @@ 
 
 #include <asm/types.h>
 #include "mtd/mtd-user.h"
+#include "mtd_ioctl.h"
 
 #define PROGRAM "nandwrite"
 #define VERSION "$Revision: 1.32 $"
@@ -107,7 +108,7 @@  static void display_version (void)
 
 static const char	*standard_input = "-";
 static const char	*mtd_device, *img;
-static int		mtdoffset = 0;
+static long long	mtdoffset = 0;
 static bool		quiet = false;
 static bool		writeoob = false;
 static bool		autoplace = false;
@@ -188,7 +189,7 @@  static void process_options (int argc, char * const argv[])
 				pad = true;
 				break;
 			case 's':
-				mtdoffset = strtol (optarg, NULL, 0);
+				mtdoffset = strtoll (optarg, NULL, 0);
 				break;
 			case 'b':
 				blockalign = atoi (optarg);
@@ -200,7 +201,7 @@  static void process_options (int argc, char * const argv[])
 	}
 
 	if (mtdoffset < 0) {
-		fprintf(stderr, "Can't specify a negative device offset `%d'\n",
+		fprintf(stderr, "Can't specify a negative device offset `%lld'\n",
 				mtdoffset);
 		exit (EXIT_FAILURE);
 	}
@@ -246,9 +247,9 @@  int main(int argc, char * const argv[])
 	int ifd = -1;
 	int imglen = 0, pagelen;
 	bool baderaseblock = false;
-	int blockstart = -1;
-	struct mtd_info_user meminfo;
-	struct mtd_oob_buf oob;
+	long long blockstart = -1;
+	struct mtd_info_user64 meminfo;
+	struct mtd_oob_buf64 oob;
 	loff_t offs;
 	int ret;
 	int oobinfochanged = 0;
@@ -280,8 +281,8 @@  int main(int argc, char * const argv[])
 	}
 
 	/* Fill in MTD device capability structure */
-	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
-		perror("MEMGETINFO");
+	if (mtd_ioctl_getinfo(fd, &meminfo) != 0) {
+		perror("MEMGETINFO64");
 		close(fd);
 		exit (EXIT_FAILURE);
 	}
@@ -377,8 +378,9 @@  int main(int argc, char * const argv[])
 		}
 	}
 
+	memset(&oob, 0, sizeof(oob));
 	oob.length = meminfo.oobsize;
-	oob.ptr = noecc ? oobreadbuf : oobbuf;
+	oob.usr_ptr = (uintptr_t)(noecc ? oobreadbuf : oobbuf);
 
 	/* Determine if we are reading from standard input or from a file. */
 	if (strcmp(img, standard_input) == 0) {
@@ -421,8 +423,9 @@  int main(int argc, char * const argv[])
 
 	// Check, if length fits into device
 	if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) {
-		fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %u bytes\n",
-				imglen, pagelen, meminfo.writesize, meminfo.size);
+		fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %llu bytes\n",
+				imglen, pagelen, meminfo.writesize,
+				(unsigned long long)meminfo.size);
 		perror ("Input file does not fit into device");
 		goto closeall;
 	}
@@ -467,7 +470,7 @@  int main(int argc, char * const argv[])
 
 			baderaseblock = false;
 			if (!quiet)
-				fprintf (stdout, "Writing data to block %d at offset 0x%x\n",
+				fprintf (stdout, "Writing data to block %lld at offset 0x%llx\n",
 						 blockstart / meminfo.erasesize, blockstart);
 
 			/* Check all the blocks in an erase block for bad blocks */
@@ -479,9 +482,10 @@  int main(int argc, char * const argv[])
 				if (ret == 1) {
 					baderaseblock = true;
 					if (!quiet)
-						fprintf (stderr, "Bad block at %x, %u block(s) "
-								"from %x will be skipped\n",
-								(int) offs, blockalign, blockstart);
+						fprintf (stderr, "Bad block at %llx, %u block(s) "
+								"from %llx will be skipped\n",
+								(unsigned long long)offs,
+								blockalign, blockstart);
 				}
 
 				if (baderaseblock) {
@@ -580,7 +584,7 @@  int main(int argc, char * const argv[])
 			}
 
 			if (noecc) {
-				oob.ptr = oobreadbuf;
+				oob.usr_ptr = (uintptr_t)oobreadbuf;
 			} else {
 				int i, start, len;
 				/*
@@ -610,15 +614,15 @@  int main(int argc, char * const argv[])
 			}
 			/* Write OOB data first, as ecc will be placed in there*/
 			oob.start = mtdoffset;
-			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
-				perror ("ioctl(MEMWRITEOOB)");
+			if (mtd_ioctl_writeoob(fd, &oob) != 0) {
+				perror ("ioctl(MEMWRITEOOB64)");
 				goto closeall;
 			}
 		}
 
 		/* Write out the Page data */
 		if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != meminfo.writesize) {
-			erase_info_t erase;
+			erase_info64_t erase;
 
 			if (errno != EIO) {
 				perror("pwrite");
@@ -628,21 +632,21 @@  int main(int argc, char * const argv[])
 			/* Must rewind to blockstart if we can */
 			writebuf = filebuf;
 
+			memset(&erase, 0, sizeof(erase));
 			erase.start = blockstart;
 			erase.length = meminfo.erasesize;
-			fprintf(stderr, "Erasing failed write from %08lx-%08lx\n",
-				(long)erase.start, (long)erase.start+erase.length-1);
-			if (ioctl(fd, MEMERASE, &erase) != 0) {
-				int errno_tmp = errno;
-				perror("MEMERASE");
-				if (errno_tmp != EIO) {
-					goto closeall;
-				}
+			fprintf(stderr, "Erasing failed write from %08llx-%08llx\n",
+				(unsigned long long)erase.start,
+				(unsigned long long)(erase.start+erase.length-1));
+			if (mtd_ioctl_erase(fd, &erase) != 0) {
+				perror("MEMERASE64");
+				goto closeall;
 			}
 
 			if (markbad) {
 				loff_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1);
-				fprintf(stderr, "Marking block at %08lx bad\n", (long)bad_addr);
+				fprintf(stderr, "Marking block at %08llx bad\n",
+					(unsigned long long)bad_addr);
 				if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) {
 					perror("MEMSETBADBLOCK");
 					goto closeall;