* [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices
@ 2009-04-03 20:18 Kevin Cernekee
2010-05-11 8:28 ` saeed bishara
0 siblings, 1 reply; 5+ messages in thread
From: Kevin Cernekee @ 2009-04-03 20:18 UTC (permalink / raw)
To: linux-mtd
Use the new kernel ioctls to erase/lock/unlock/readoob/writeoob >4GiB
flash devices.
Use the new sysfs interface to query device info.
Dependencies:
"4GiB" extended ioctls:
http://lists.infradead.org/pipermail/linux-mtd/2009-April/025122.html
Driver model updates 1/2: http://lkml.org/lkml/2009/4/3/477
Optional: Driver model updates 2/2:
http://lists.infradead.org/pipermail/linux-mtd/2009-March/025011.html
Signed-off-by: Kevin Cernekee <kpc.mtd@gmail.com>
---
Makefile | 19 +++-
flash_erase.c | 59 ++++++----
flash_eraseall.c | 31 +++--
flash_lock.c | 21 ++--
flash_unlock.c | 9 +-
flashcp.c | 22 ++--
include/mtd/mtd-abi.h | 24 ++++-
include/mtd/mtd-user.h | 4 +-
mtd_debug.c | 114 ++++++++++---------
mtd_ioctl.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++++
mtd_ioctl.h | 38 ++++++
nanddump.c | 23 +++--
nandtest.c | 35 +++---
nandwrite.c | 54 +++++----
14 files changed, 585 insertions(+), 171 deletions(-)
create mode 100644 mtd_ioctl.c
create mode 100644 mtd_ioctl.h
diff --git a/Makefile b/Makefile
index 969ab87..8bf2695 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 dca6794..37509bf 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 * 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 648dc4f..b7793b7 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;
/*
* Parse command line options
@@ -43,7 +44,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);
@@ -52,7 +53,7 @@ int main(int argc, char *argv[])
mtdLockInfo.start = 0;
mtdLockInfo.length = mtdInfo.size;
- 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/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index 86defe1..5e336bf 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -1,23 +1,35 @@
/*
- * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
- *
* Portions of MTD ABI definition which are shared by kernel and user space
*/
#ifndef __MTD_ABI_H__
#define __MTD_ABI_H__
+#include <linux/types.h>
+
struct erase_info_user {
uint32_t start;
uint32_t length;
};
+struct erase_info_user64 {
+ __u64 start;
+ __u64 length;
+};
+
struct mtd_oob_buf {
uint32_t start;
uint32_t length;
unsigned char *ptr;
};
+struct mtd_oob_buf64 {
+ __u64 start;
+ __u32 res0;
+ __u32 length;
+ __u64 usr_ptr;
+};
+
#define MTD_ABSENT 0
#define MTD_RAM 1
#define MTD_ROM 2
@@ -29,7 +41,7 @@ struct mtd_oob_buf {
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
#define MTD_NO_ERASE 0x1000 /* No erase necessary */
-#define MTD_STUPID_LOCK 0x2000 /* Always locked after reset */
+#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
// Some common devices / combinations of capabilities
#define MTD_CAP_ROM 0
@@ -96,6 +108,12 @@ struct otp_info {
#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
#define MTDFILEMODE _IO('M', 19)
+#define MEMERASE64 _IOW('M', 20, struct erase_info_user64)
+#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64)
+#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64)
+#define MEMLOCK64 _IOW('M', 23, struct erase_info_user64)
+#define MEMUNLOCK64 _IOW('M', 24, struct erase_info_user64)
+
/*
* Obsolete legacy interface. Keep it in order not to break userspace
* interfaces
diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h
index 713f34d..a5ec18e 100644
--- a/include/mtd/mtd-user.h
+++ b/include/mtd/mtd-user.h
@@ -1,6 +1,4 @@
/*
- * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $
- *
* MTD ABI header for use by user space only.
*/
@@ -18,4 +16,6 @@ typedef struct region_info_user region_info_t;
typedef struct nand_oobinfo nand_oobinfo_t;
typedef struct nand_ecclayout nand_ecclayout_t;
+typedef struct erase_info_user64 erase_info64_t;
+
#endif /* __MTD_USER_H__ */
diff --git a/mtd_debug.c b/mtd_debug.c
index 85d48e9..7d7dc3b 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,®ions[i]);
+ err = mtd_ioctl_getregioninfo (fd,®ions[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..500a743
--- /dev/null
+++ b/mtd_ioctl.c
@@ -0,0 +1,303 @@
+/*
+ * 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)
+{
+ int ret;
+ struct erase_info_user oldarg;
+
+ if(try_new_ioctl(fd, MEMLOCK64, (unsigned long)arg, &ret) != 0)
+ return(ret);
+
+ 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)
+{
+ int ret;
+ struct erase_info_user oldarg;
+
+ if(try_new_ioctl(fd, MEMUNLOCK64, (unsigned long)arg, &ret) != 0)
+ return(ret);
+
+ 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..2c62553
--- /dev/null
+++ b/mtd_ioctl.h
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+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 678d684..fbe4f9a 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);
}
@@ -320,11 +325,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;
}
@@ -359,8 +364,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 7613a52..48ec1a7 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 0b2a9ee..4221722 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 $"
@@ -114,7 +115,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;
@@ -195,7 +196,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);
@@ -207,7 +208,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);
}
@@ -253,14 +254,13 @@ 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, readlen;
int oobinfochanged = 0;
struct nand_oobinfo old_oobinfo;
- int readcnt = 0;
process_options(argc, argv);
@@ -278,8 +278,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);
}
@@ -375,8 +375,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) {
@@ -425,8 +426,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;
}
@@ -450,7 +452,7 @@ int main(int argc, char * const argv[])
offs = blockstart;
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 */
@@ -462,9 +464,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) {
@@ -571,8 +574,8 @@ 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;
}
imglen -= meminfo.oobsize;
@@ -582,7 +585,7 @@ int main(int argc, char * const argv[])
if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) !=
meminfo.writesize) {
int rewind_blocks;
off_t rewind_bytes;
- erase_info_t erase;
+ erase_info64_t erase;
perror ("pwrite");
/* Must rewind to blockstart if we can */
@@ -595,18 +598,21 @@ int main(int argc, char * const argv[])
fprintf(stderr, "Failed to seek backwards to recover from write error\n");
goto closeall;
}
+ 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) {
- perror("MEMERASE");
+ 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");
/* But continue anyway */
--
1.5.6.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices
2009-04-03 20:18 [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices Kevin Cernekee
@ 2010-05-11 8:28 ` saeed bishara
2010-05-11 8:43 ` Artem Bityutskiy
0 siblings, 1 reply; 5+ messages in thread
From: saeed bishara @ 2010-05-11 8:28 UTC (permalink / raw)
To: Kevin Cernekee, linux-mtd
hi,
This patch is needed when using >4GiB nand partitions, any idea why
it has not been merged yet?
saeed
On Fri, Apr 3, 2009 at 11:18 PM, Kevin Cernekee <kpc.mtd@gmail.com> wrote:
> Use the new kernel ioctls to erase/lock/unlock/readoob/writeoob >4GiB
> flash devices.
>
> Use the new sysfs interface to query device info.
>
> Dependencies:
>
> "4GiB" extended ioctls:
> http://lists.infradead.org/pipermail/linux-mtd/2009-April/025122.html
>
> Driver model updates 1/2: http://lkml.org/lkml/2009/4/3/477
>
> Optional: Driver model updates 2/2:
> http://lists.infradead.org/pipermail/linux-mtd/2009-March/025011.html
>
> Signed-off-by: Kevin Cernekee <kpc.mtd@gmail.com>
> ---
> Makefile | 19 +++-
> flash_erase.c | 59 ++++++----
> flash_eraseall.c | 31 +++--
> flash_lock.c | 21 ++--
> flash_unlock.c | 9 +-
> flashcp.c | 22 ++--
> include/mtd/mtd-abi.h | 24 ++++-
> include/mtd/mtd-user.h | 4 +-
> mtd_debug.c | 114 ++++++++++---------
> mtd_ioctl.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++++
> mtd_ioctl.h | 38 ++++++
> nanddump.c | 23 +++--
> nandtest.c | 35 +++---
> nandwrite.c | 54 +++++----
> 14 files changed, 585 insertions(+), 171 deletions(-)
> create mode 100644 mtd_ioctl.c
> create mode 100644 mtd_ioctl.h
>
> diff --git a/Makefile b/Makefile
> index 969ab87..8bf2695 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 dca6794..37509bf 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 * 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 648dc4f..b7793b7 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;
>
> /*
> * Parse command line options
> @@ -43,7 +44,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);
> @@ -52,7 +53,7 @@ int main(int argc, char *argv[])
>
> mtdLockInfo.start = 0;
> mtdLockInfo.length = mtdInfo.size;
> - 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/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
> index 86defe1..5e336bf 100644
> --- a/include/mtd/mtd-abi.h
> +++ b/include/mtd/mtd-abi.h
> @@ -1,23 +1,35 @@
> /*
> - * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
> - *
> * Portions of MTD ABI definition which are shared by kernel and user space
> */
>
> #ifndef __MTD_ABI_H__
> #define __MTD_ABI_H__
>
> +#include <linux/types.h>
> +
> struct erase_info_user {
> uint32_t start;
> uint32_t length;
> };
>
> +struct erase_info_user64 {
> + __u64 start;
> + __u64 length;
> +};
> +
> struct mtd_oob_buf {
> uint32_t start;
> uint32_t length;
> unsigned char *ptr;
> };
>
> +struct mtd_oob_buf64 {
> + __u64 start;
> + __u32 res0;
> + __u32 length;
> + __u64 usr_ptr;
> +};
> +
> #define MTD_ABSENT 0
> #define MTD_RAM 1
> #define MTD_ROM 2
> @@ -29,7 +41,7 @@ struct mtd_oob_buf {
> #define MTD_WRITEABLE 0x400 /* Device is writeable */
> #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
> #define MTD_NO_ERASE 0x1000 /* No erase necessary */
> -#define MTD_STUPID_LOCK 0x2000 /* Always locked after reset */
> +#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
>
> // Some common devices / combinations of capabilities
> #define MTD_CAP_ROM 0
> @@ -96,6 +108,12 @@ struct otp_info {
> #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
> #define MTDFILEMODE _IO('M', 19)
>
> +#define MEMERASE64 _IOW('M', 20, struct erase_info_user64)
> +#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64)
> +#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64)
> +#define MEMLOCK64 _IOW('M', 23, struct erase_info_user64)
> +#define MEMUNLOCK64 _IOW('M', 24, struct erase_info_user64)
> +
> /*
> * Obsolete legacy interface. Keep it in order not to break userspace
> * interfaces
> diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h
> index 713f34d..a5ec18e 100644
> --- a/include/mtd/mtd-user.h
> +++ b/include/mtd/mtd-user.h
> @@ -1,6 +1,4 @@
> /*
> - * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $
> - *
> * MTD ABI header for use by user space only.
> */
>
> @@ -18,4 +16,6 @@ typedef struct region_info_user region_info_t;
> typedef struct nand_oobinfo nand_oobinfo_t;
> typedef struct nand_ecclayout nand_ecclayout_t;
>
> +typedef struct erase_info_user64 erase_info64_t;
> +
> #endif /* __MTD_USER_H__ */
> diff --git a/mtd_debug.c b/mtd_debug.c
> index 85d48e9..7d7dc3b 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,®ions[i]);
> + err = mtd_ioctl_getregioninfo (fd,®ions[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..500a743
> --- /dev/null
> +++ b/mtd_ioctl.c
> @@ -0,0 +1,303 @@
> +/*
> + * 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)
> +{
> + int ret;
> + struct erase_info_user oldarg;
> +
> + if(try_new_ioctl(fd, MEMLOCK64, (unsigned long)arg, &ret) != 0)
> + return(ret);
> +
> + 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)
> +{
> + int ret;
> + struct erase_info_user oldarg;
> +
> + if(try_new_ioctl(fd, MEMUNLOCK64, (unsigned long)arg, &ret) != 0)
> + return(ret);
> +
> + 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..2c62553
> --- /dev/null
> +++ b/mtd_ioctl.h
> @@ -0,0 +1,38 @@
> +/*
> + * 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;
> +
> +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 678d684..fbe4f9a 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);
> }
> @@ -320,11 +325,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;
> }
> @@ -359,8 +364,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 7613a52..48ec1a7 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 0b2a9ee..4221722 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 $"
> @@ -114,7 +115,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;
> @@ -195,7 +196,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);
> @@ -207,7 +208,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);
> }
> @@ -253,14 +254,13 @@ 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, readlen;
> int oobinfochanged = 0;
> struct nand_oobinfo old_oobinfo;
> - int readcnt = 0;
>
> process_options(argc, argv);
>
> @@ -278,8 +278,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);
> }
> @@ -375,8 +375,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) {
> @@ -425,8 +426,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;
> }
> @@ -450,7 +452,7 @@ int main(int argc, char * const argv[])
> offs = blockstart;
> 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 */
> @@ -462,9 +464,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) {
> @@ -571,8 +574,8 @@ 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;
> }
> imglen -= meminfo.oobsize;
> @@ -582,7 +585,7 @@ int main(int argc, char * const argv[])
> if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) !=
> meminfo.writesize) {
> int rewind_blocks;
> off_t rewind_bytes;
> - erase_info_t erase;
> + erase_info64_t erase;
>
> perror ("pwrite");
> /* Must rewind to blockstart if we can */
> @@ -595,18 +598,21 @@ int main(int argc, char * const argv[])
> fprintf(stderr, "Failed to seek backwards to recover from write error\n");
> goto closeall;
> }
> + 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) {
> - perror("MEMERASE");
> + 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");
> /* But continue anyway */
> --
> 1.5.6.3
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices
2010-05-11 8:28 ` saeed bishara
@ 2010-05-11 8:43 ` Artem Bityutskiy
2010-05-12 11:25 ` saeed bishara
0 siblings, 1 reply; 5+ messages in thread
From: Artem Bityutskiy @ 2010-05-11 8:43 UTC (permalink / raw)
To: saeed bishara; +Cc: linux-mtd
On Tue, 2010-05-11 at 11:28 +0300, saeed bishara wrote:
> hi,
> This patch is needed when using >4GiB nand partitions, any idea why
> it has not been merged yet?
>
> saeed
>
> On Fri, Apr 3, 2009 at 11:18 PM, Kevin Cernekee <kpc.mtd@gmail.com> wrote:
> > Use the new kernel ioctls to erase/lock/unlock/readoob/writeoob >4GiB
> > flash devices.
> >
> > Use the new sysfs interface to query device info.
> >
> > Dependencies:
> >
> > "4GiB" extended ioctls:
> > http://lists.infradead.org/pipermail/linux-mtd/2009-April/025122.html
> >
> > Driver model updates 1/2: http://lkml.org/lkml/2009/4/3/477
> >
> > Optional: Driver model updates 2/2:
> > http://lists.infradead.org/pipermail/linux-mtd/2009-March/025011.html
> >
Dunno, I did not follow these. Kevin, would you re-send your patches
please?
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices
2010-05-11 8:43 ` Artem Bityutskiy
@ 2010-05-12 11:25 ` saeed bishara
2010-05-12 12:11 ` Artem Bityutskiy
0 siblings, 1 reply; 5+ messages in thread
From: saeed bishara @ 2010-05-12 11:25 UTC (permalink / raw)
To: dedekind1; +Cc: Tawfic Bayyouk, linux-mtd
[-- Attachment #1: Type: text/plain, Size: 1144 bytes --]
On Tue, May 11, 2010 at 11:43 AM, Artem Bityutskiy <dedekind1@gmail.com> wrote:
> On Tue, 2010-05-11 at 11:28 +0300, saeed bishara wrote:
>> hi,
>> This patch is needed when using >4GiB nand partitions, any idea why
>> it has not been merged yet?
>>
>> saeed
>>
>> On Fri, Apr 3, 2009 at 11:18 PM, Kevin Cernekee <kpc.mtd@gmail.com> wrote:
>> > Use the new kernel ioctls to erase/lock/unlock/readoob/writeoob >4GiB
>> > flash devices.
>> >
>> > Use the new sysfs interface to query device info.
>> >
>> > Dependencies:
>> >
>> > "4GiB" extended ioctls:
>> > http://lists.infradead.org/pipermail/linux-mtd/2009-April/025122.html
>> >
>> > Driver model updates 1/2: http://lkml.org/lkml/2009/4/3/477
>> >
>> > Optional: Driver model updates 2/2:
>> > http://lists.infradead.org/pipermail/linux-mtd/2009-March/025011.html
>> >
>
> Dunno, I did not follow these. Kevin, would you re-send your patches
> please?
>
> --
> Best Regards,
> Artem Bityutskiy (Артём Битюцкий)
>
attached updated version of the patch.
also, another patch added to make the ubi format use the 64bit erase ioctl.
saeed
[-- Attachment #2: 0001-mtd-utils-use-new-64-bit-ioctls-sysfs-tio-support-4G.patch --]
[-- Type: application/octet-stream, Size: 44446 bytes --]
From f37d0a223d6dda771791f4f68ca464ae4eb5d3d1 Mon Sep 17 00:00:00 2001
From: Tawfic Bayyouk <tawficb@gmail.com>
Date: Tue, 11 May 2010 19:10:28 +0300
Subject: [PATCH 1/2] mtd-utils: use new 64-bit ioctls + sysfs tio support >4GiB devices
Use the new kernel ioctls to erase/lock/unlock/readoob/writeoob >4GiB
flash devices.
Use the new sysfs interface to query device info.
Dependencies:
"4GiB" extended ioctls:
http://lists.infradead.org/pipermail/linux-mtd/2009-April/025122.html
Driver model updates 1/2: http://lkml.org/lkml/2009/4/3/477
Optional: Driver model updates 2/2:
http://lists.infradead.org/pipermail/linux-mtd/2009-March/025011.html
Signed-off-by: Kevin Cernekee <kpc.mtd@gmail.com>
Signed-off-by: Tawfic Bayyouk <tawficb@gmail.com>
---
Makefile | 19 +++-
flash_erase.c | 59 ++++++----
flash_eraseall.c | 31 +++--
flash_lock.c | 21 ++--
flash_unlock.c | 9 +-
flashcp.c | 22 ++--
include/mtd/mtd-abi.h | 24 ++++-
include/mtd/mtd-user.h | 4 +-
mtd_debug.c | 114 ++++++++++---------
mtd_ioctl.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++++
mtd_ioctl.h | 38 ++++++
nanddump.c | 23 +++--
nandtest.c | 35 +++---
nandwrite.c | 60 +++++-----
14 files changed, 587 insertions(+), 175 deletions(-)
mode change 100644 => 100755 flash_unlock.c
create mode 100644 mtd_ioctl.c
create mode 100644 mtd_ioctl.h
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
old mode 100644
new mode 100755
index 3969453..9921996
--- 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/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index 86defe1..5e336bf 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -1,23 +1,35 @@
/*
- * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $
- *
* Portions of MTD ABI definition which are shared by kernel and user space
*/
#ifndef __MTD_ABI_H__
#define __MTD_ABI_H__
+#include <linux/types.h>
+
struct erase_info_user {
uint32_t start;
uint32_t length;
};
+struct erase_info_user64 {
+ __u64 start;
+ __u64 length;
+};
+
struct mtd_oob_buf {
uint32_t start;
uint32_t length;
unsigned char *ptr;
};
+struct mtd_oob_buf64 {
+ __u64 start;
+ __u32 res0;
+ __u32 length;
+ __u64 usr_ptr;
+};
+
#define MTD_ABSENT 0
#define MTD_RAM 1
#define MTD_ROM 2
@@ -29,7 +41,7 @@ struct mtd_oob_buf {
#define MTD_WRITEABLE 0x400 /* Device is writeable */
#define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */
#define MTD_NO_ERASE 0x1000 /* No erase necessary */
-#define MTD_STUPID_LOCK 0x2000 /* Always locked after reset */
+#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */
// Some common devices / combinations of capabilities
#define MTD_CAP_ROM 0
@@ -96,6 +108,12 @@ struct otp_info {
#define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats)
#define MTDFILEMODE _IO('M', 19)
+#define MEMERASE64 _IOW('M', 20, struct erase_info_user64)
+#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64)
+#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64)
+#define MEMLOCK64 _IOW('M', 23, struct erase_info_user64)
+#define MEMUNLOCK64 _IOW('M', 24, struct erase_info_user64)
+
/*
* Obsolete legacy interface. Keep it in order not to break userspace
* interfaces
diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h
index 713f34d..a5ec18e 100644
--- a/include/mtd/mtd-user.h
+++ b/include/mtd/mtd-user.h
@@ -1,6 +1,4 @@
/*
- * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $
- *
* MTD ABI header for use by user space only.
*/
@@ -18,4 +16,6 @@ typedef struct region_info_user region_info_t;
typedef struct nand_oobinfo nand_oobinfo_t;
typedef struct nand_ecclayout nand_ecclayout_t;
+typedef struct erase_info_user64 erase_info64_t;
+
#endif /* __MTD_USER_H__ */
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,®ions[i]);
+ err = mtd_ioctl_getregioninfo (fd,®ions[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..500a743
--- /dev/null
+++ b/mtd_ioctl.c
@@ -0,0 +1,303 @@
+/*
+ * 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)
+{
+ int ret;
+ struct erase_info_user oldarg;
+
+ if(try_new_ioctl(fd, MEMLOCK64, (unsigned long)arg, &ret) != 0)
+ return(ret);
+
+ 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)
+{
+ int ret;
+ struct erase_info_user oldarg;
+
+ if(try_new_ioctl(fd, MEMUNLOCK64, (unsigned long)arg, &ret) != 0)
+ return(ret);
+
+ 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..2c62553
--- /dev/null
+++ b/mtd_ioctl.h
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+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..fbaf367 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 = 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;
--
1.7.0.4
[-- Attachment #3: 0002-Fix-the-ubiformat-with-devices-4GiB.patch --]
[-- Type: application/octet-stream, Size: 1514 bytes --]
From 47141c8f3b37188924d0f0eb3b13f324ecbb858e Mon Sep 17 00:00:00 2001
From: Tawfic Bayyouk <tawficb@gmail.com>
Date: Wed, 12 May 2010 10:45:59 +0300
Subject: [PATCH 2/2] Fix the ubiformat with devices >4GiB
Update the mtd_erase() to try the MEMERASE64 as the first option.
Signed-off-by: Tawfic Bayyouk <tawficb@gmail.com>
---
ubi-utils/src/libmtd.c | 20 ++++++++++++++++----
1 files changed, 16 insertions(+), 4 deletions(-)
mode change 100644 => 100755 ubi-utils/src/libmtd.c
diff --git a/ubi-utils/src/libmtd.c b/ubi-utils/src/libmtd.c
old mode 100644
new mode 100755
index 249fa23..c0eac4b
--- a/ubi-utils/src/libmtd.c
+++ b/ubi-utils/src/libmtd.c
@@ -791,11 +791,23 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb)
{
- struct erase_info_user ei;
+ struct erase_info_user64 arg;
+ struct erase_info_user oldarg;
+ int ret;
+
+ arg.start = ((__u64)eb * (__u64)mtd->eb_size);
+ arg.length = mtd->eb_size;
- ei.start = eb * mtd->eb_size;;
- ei.length = mtd->eb_size;
- return ioctl(fd, MEMERASE, &ei);
+ printf("\nmtd_erase: Off %llx, size %llx\n", arg.start, arg.length);
+
+ ret = ioctl(fd, MEMERASE64, (unsigned long)&arg);
+ if((ret < 0) && (errno == ENOTTY)) {
+ oldarg.start = eb * mtd->eb_size;
+ oldarg.length = mtd->eb_size;
+ return(ioctl(fd, MEMERASE, (unsigned long)&oldarg));
+ }
+
+ return (ret);
}
/* Patterns to write to a physical eraseblock when torturing it */
--
1.7.0.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices
2010-05-12 11:25 ` saeed bishara
@ 2010-05-12 12:11 ` Artem Bityutskiy
0 siblings, 0 replies; 5+ messages in thread
From: Artem Bityutskiy @ 2010-05-12 12:11 UTC (permalink / raw)
To: saeed bishara; +Cc: Tawfic Bayyouk, linux-mtd
On Wed, 2010-05-12 at 14:25 +0300, saeed bishara wrote:
> attached updated version of the patch.
> also, another patch added to make the ubi format use the 64bit erase ioctl.
It is better get them from Kevin.
--
Best Regards,
Artem Bityutskiy (Артём Битюцкий)
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-05-12 12:12 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-03 20:18 [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices Kevin Cernekee
2010-05-11 8:28 ` saeed bishara
2010-05-11 8:43 ` Artem Bityutskiy
2010-05-12 11:25 ` saeed bishara
2010-05-12 12:11 ` Artem Bityutskiy
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).