mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH V3 00/11] ubiformat for barebox
@ 2012-12-17 15:48 Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 01/11] mtd: drop custom is_power_of_2() Wolfram Sang
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Another round of ubiformat for barebox. Tested on various MX28 based hardware.
I could create and attach empty UBIs or flashed files successfully. I also
tried flashing /dev/mem and /dev/c64 which failed correctly.

Changes since V1 (V2 was only internal):

* update strtoull_suffix() and size_human_readable()
* use those and get rid of libubiutils completely \o/
* use read_full instead of custom read_all
* dropped all long commandline options and references
* reworked the help to BAREBOX_CMD_HELP_* usage
* dropped FSF addresses all over
* simply quit in dubious situations instead of doing something
* add '-y' to do something in dubious situations :)
* quite some bugfixes
(* verified subpage-size handling, found a bug in nand_mxs driver)

Please test, comment, apply...

Thanks,

   Wolfram


Wolfram Sang (11):
  mtd: drop custom is_power_of_2()
  lib: misc: add 'iB' suffixes to strtoull_suffix
  lib: update size_human_readable to latest version
  ubi: consolidate ubi-media.h
  ubi: bump ubi-media.h to newest version
  devfs & mtd: add MEMERASE ioctl support
  mtd: utils: apply macros for message printouts
  lib: add libscan
  lib: add libubigen
  lib: add barebox version of libmtd
  commands: add ubiformat

 commands/Kconfig              |    8 +
 commands/Makefile             |    1 +
 commands/ubi.c                |    2 +-
 commands/ubiformat.c          |  784 +++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/core.c            |   68 ++--
 drivers/mtd/ubi/ubi-barebox.h |    5 +-
 drivers/mtd/ubi/ubi-media.h   |  369 -------------------
 drivers/mtd/ubi/ubi.h         |    3 +-
 fs/devfs-core.c               |    3 +-
 include/common.h              |    2 +-
 include/mtd/libmtd.h          |  149 ++++++++
 include/mtd/libscan.h         |  101 ++++++
 include/mtd/libubigen.h       |  182 ++++++++++
 include/mtd/ubi-media.h       |  374 ++++++++++++++++++++
 include/mtd/utils.h           |   47 +++
 include/ubi-media.h           |  370 -------------------
 lib/Kconfig                   |    9 +
 lib/Makefile                  |    3 +
 lib/display_options.c         |   47 ++-
 lib/libmtd.c                  |  368 +++++++++++++++++++
 lib/libscan.c                 |  219 ++++++++++++
 lib/libubigen.c               |  312 ++++++++++++++++
 lib/misc.c                    |    5 +-
 23 files changed, 2634 insertions(+), 797 deletions(-)
 create mode 100644 commands/ubiformat.c
 delete mode 100644 drivers/mtd/ubi/ubi-media.h
 create mode 100644 include/mtd/libmtd.h
 create mode 100644 include/mtd/libscan.h
 create mode 100644 include/mtd/libubigen.h
 create mode 100644 include/mtd/ubi-media.h
 create mode 100644 include/mtd/utils.h
 delete mode 100644 include/ubi-media.h
 create mode 100644 lib/libmtd.c
 create mode 100644 lib/libscan.c
 create mode 100644 lib/libubigen.c

-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 01/11] mtd: drop custom is_power_of_2()
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 02/11] lib: misc: add 'iB' suffixes to strtoull_suffix Wolfram Sang
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

We have proper version in log2.h these days.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 drivers/mtd/ubi/ubi-barebox.h |    5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/mtd/ubi/ubi-barebox.h b/drivers/mtd/ubi/ubi-barebox.h
index 72f29a6..7574607 100644
--- a/drivers/mtd/ubi/ubi-barebox.h
+++ b/drivers/mtd/ubi/ubi-barebox.h
@@ -25,6 +25,7 @@
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/ubi.h>
+#include <linux/log2.h>
 
 #define crc32(seed, data, length)  crc32_no_comp(seed, (unsigned char const *)data, length)
 
@@ -53,10 +54,6 @@ do {									\
 #define put_device(...)
 #define ubi_sysfs_init(...)		0
 #define ubi_sysfs_close(...)		do { } while (0)
-static inline int is_power_of_2(unsigned long n)
-{
-	return (n != 0 && ((n & (n - 1)) == 0));
-}
 
 /* FIXME */
 #define MKDEV(...)			0
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 02/11] lib: misc: add 'iB' suffixes to strtoull_suffix
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 01/11] mtd: drop custom is_power_of_2() Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 03/11] lib: update size_human_readable to latest version Wolfram Sang
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Since this is the 'official' notation, we should support it.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 lib/misc.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/lib/misc.c b/lib/misc.c
index 1a08502..0f3eb9a 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -47,8 +47,11 @@ unsigned long long strtoull_suffix(const char *str, char **endp, int base)
 		break;
 	}
 
+	if (strncmp(end, "iB", 2) == 0)
+		end += 2;
+
 	if (endp)
-		*endp = (char *)end;
+		*endp = end;
 
 	return val;
 }
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 03/11] lib: update size_human_readable to latest version
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 01/11] mtd: drop custom is_power_of_2() Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 02/11] lib: misc: add 'iB' suffixes to strtoull_suffix Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 04/11] ubi: consolidate ubi-media.h Wolfram Sang
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Copy over the latest version from u-boot which handles bigger sizes now
and does arithmetic with shifts instead of divisions.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 include/common.h      |    2 +-
 lib/display_options.c |   47 +++++++++++++++++++++++++++++++----------------
 2 files changed, 32 insertions(+), 17 deletions(-)

diff --git a/include/common.h b/include/common.h
index e30774a..1939427 100644
--- a/include/common.h
+++ b/include/common.h
@@ -105,7 +105,7 @@ void reginfo(void);
 void __noreturn hang (void);
 void __noreturn panic(const char *fmt, ...);
 
-char *size_human_readable(ulong size);
+char *size_human_readable(unsigned long long size);
 
 /* common/main.c */
 int	run_command	(const char *cmd, int flag);
diff --git a/lib/display_options.c b/lib/display_options.c
index a6050cb..0871552 100644
--- a/lib/display_options.c
+++ b/lib/display_options.c
@@ -21,35 +21,50 @@
 
 /*
  * return a pointer to a string containing the size
- * as "xxx kB", "xxx.y kB", "xxx MB" or "xxx.y MB" as needed;
+ *"as xxx KiB", "xxx.y KiB", "xxx MiB", "xxx.y MiB",
+ * xxx GiB, xxx.y GiB, etc as needed;
  */
-char *size_human_readable(ulong size)
+char *size_human_readable(unsigned long long size)
 {
 	static char buf[20];
-	ulong m, n;
-	ulong d = 1 << 20;		/* 1 MB */
-	char  c = 'M';
+	unsigned long m = 0, n;
+	unsigned long long f;
+	static const char names[] = {'E', 'P', 'T', 'G', 'M', 'K'};
+	unsigned long d = 10 * ARRAY_SIZE(names);
+	char c = 0;
+	unsigned int i;
 	char *ptr = buf;
 
-	if (size < d) {			/* print in kB */
-		c = 'k';
-		d = 1 << 10;
+	for (i = 0; i < ARRAY_SIZE(names); i++, d -= 10) {
+		if (size >> d) {
+			c = names[i];
+			break;
+		}
 	}
 
-	n = size / d;
+	if (!c) {
+		sprintf(buf, "%llu Bytes", size);
+		return buf;
+	}
+
+	n = size >> d;
+	f = size & ((1ULL << d) - 1);
 
-	m = (10 * (size - (n * d)) + (d / 2) ) / d;
+	/* If there's a remainder, deal with it */
+	if (f) {
+		m = (10ULL * f + (1ULL << (d - 1))) >> d;
 
-	if (m >= 10) {
-		m -= 10;
-		n += 1;
+		if (m >= 10) {
+			m -= 10;
+			n += 1;
+		}
 	}
 
-	ptr += sprintf(buf, "%2ld", n);
+	ptr += sprintf(buf, "%lu", n);
 	if (m) {
-		ptr += sprintf (ptr,".%ld", m);
+		ptr += sprintf(ptr, ".%ld", m);
 	}
-	sprintf(ptr, " %cB", c);
+	sprintf(ptr, " %ciB", c);
 
 	return buf;
 }
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 04/11] ubi: consolidate ubi-media.h
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (2 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 03/11] lib: update size_human_readable to latest version Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 05/11] ubi: bump ubi-media.h to newest version Wolfram Sang
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

We have two versions in the tree. Use the newer one, and put it into the
mtd directory while we are at it.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 commands/ubi.c              |    2 +-
 drivers/mtd/ubi/ubi-media.h |  369 ------------------------------------------
 drivers/mtd/ubi/ubi.h       |    3 +-
 include/mtd/ubi-media.h     |  369 ++++++++++++++++++++++++++++++++++++++++++
 include/ubi-media.h         |  370 -------------------------------------------
 5 files changed, 372 insertions(+), 741 deletions(-)
 delete mode 100644 drivers/mtd/ubi/ubi-media.h
 create mode 100644 include/mtd/ubi-media.h
 delete mode 100644 include/ubi-media.h

diff --git a/commands/ubi.c b/commands/ubi.c
index bf70071..1653eaa 100644
--- a/commands/ubi.c
+++ b/commands/ubi.c
@@ -9,7 +9,7 @@
 #include <linux/kernel.h>
 #include <linux/mtd/mtd-abi.h>
 #include <mtd/ubi-user.h>
-#include <ubi-media.h>
+#include <mtd/ubi-media.h>
 
 static int do_ubimkvol(int argc, char *argv[])
 {
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
deleted file mode 100644
index cd1bd8e..0000000
--- a/drivers/mtd/ubi/ubi-media.h
+++ /dev/null
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- *
- * Authors: Artem Bityutskiy (Битюцкий Артём)
- *          Thomas Gleixner
- *          Frank Haverkamp
- *          Oliver Lohmann
- *          Andreas Arnez
- */
-
-/*
- * This file defines the layout of UBI headers and all the other UBI on-flash
- * data structures.
- */
-
-#ifndef __UBI_MEDIA_H__
-#define __UBI_MEDIA_H__
-
-#include <asm/byteorder.h>
-
-/* The version of UBI images supported by this implementation */
-#define UBI_VERSION 1
-
-/* The highest erase counter value supported by this implementation */
-#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
-
-/* The initial CRC32 value used when calculating CRC checksums */
-#define UBI_CRC32_INIT 0xFFFFFFFFU
-
-/* Erase counter header magic number (ASCII "UBI#") */
-#define UBI_EC_HDR_MAGIC  0x55424923
-/* Volume identifier header magic number (ASCII "UBI!") */
-#define UBI_VID_HDR_MAGIC 0x55424921
-
-/*
- * Volume type constants used in the volume identifier header.
- *
- * @UBI_VID_DYNAMIC: dynamic volume
- * @UBI_VID_STATIC: static volume
- */
-enum {
-	UBI_VID_DYNAMIC = 1,
-	UBI_VID_STATIC  = 2
-};
-
-/*
- * Volume flags used in the volume table record.
- *
- * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
- *
- * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
- * table. UBI automatically re-sizes the volume which has this flag and makes
- * the volume to be of largest possible size. This means that if after the
- * initialization UBI finds out that there are available physical eraseblocks
- * present on the device, it automatically appends all of them to the volume
- * (the physical eraseblocks reserved for bad eraseblocks handling and other
- * reserved physical eraseblocks are not taken). So, if there is a volume with
- * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical
- * eraseblocks will be zero after UBI is loaded, because all of them will be
- * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared
- * after the volume had been initialized.
- *
- * The auto-resize feature is useful for device production purposes. For
- * example, different NAND flash chips may have different amount of initial bad
- * eraseblocks, depending of particular chip instance. Manufacturers of NAND
- * chips usually guarantee that the amount of initial bad eraseblocks does not
- * exceed certain percent, e.g. 2%. When one creates an UBI image which will be
- * flashed to the end devices in production, he does not know the exact amount
- * of good physical eraseblocks the NAND chip on the device will have, but this
- * number is required to calculate the volume sized and put them to the volume
- * table of the UBI image. In this case, one of the volumes (e.g., the one
- * which will store the root file system) is marked as "auto-resizable", and
- * UBI will adjust its size on the first boot if needed.
- *
- * Note, first UBI reserves some amount of physical eraseblocks for bad
- * eraseblock handling, and then re-sizes the volume, not vice-versa. This
- * means that the pool of reserved physical eraseblocks will always be present.
- */
-enum {
-	UBI_VTBL_AUTORESIZE_FLG = 0x01,
-};
-
-/*
- * Compatibility constants used by internal volumes.
- *
- * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
- * to the flash
- * @UBI_COMPAT_RO: attach this device in read-only mode
- * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
- * physical eraseblocks, don't allow the wear-leveling unit to move them
- * @UBI_COMPAT_REJECT: reject this UBI image
- */
-enum {
-	UBI_COMPAT_DELETE   = 1,
-	UBI_COMPAT_RO       = 2,
-	UBI_COMPAT_PRESERVE = 4,
-	UBI_COMPAT_REJECT   = 5
-};
-
-/* Sizes of UBI headers */
-#define UBI_EC_HDR_SIZE  sizeof(struct ubi_ec_hdr)
-#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
-
-/* Sizes of UBI headers without the ending CRC */
-#define UBI_EC_HDR_SIZE_CRC  (UBI_EC_HDR_SIZE  - sizeof(__be32))
-#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32))
-
-/**
- * struct ubi_ec_hdr - UBI erase counter header.
- * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
- * @version: version of UBI implementation which is supposed to accept this
- * UBI image
- * @padding1: reserved for future, zeroes
- * @ec: the erase counter
- * @vid_hdr_offset: where the VID header starts
- * @data_offset: where the user data start
- * @padding2: reserved for future, zeroes
- * @hdr_crc: erase counter header CRC checksum
- *
- * The erase counter header takes 64 bytes and has a plenty of unused space for
- * future usage. The unused fields are zeroed. The @version field is used to
- * indicate the version of UBI implementation which is supposed to be able to
- * work with this UBI image. If @version is greater then the current UBI
- * version, the image is rejected. This may be useful in future if something
- * is changed radically. This field is duplicated in the volume identifier
- * header.
- *
- * The @vid_hdr_offset and @data_offset fields contain the offset of the the
- * volume identifier header and user data, relative to the beginning of the
- * physical eraseblock. These values have to be the same for all physical
- * eraseblocks.
- */
-struct ubi_ec_hdr {
-	__be32  magic;
-	__u8    version;
-	__u8    padding1[3];
-	__be64  ec; /* Warning: the current limit is 31-bit anyway! */
-	__be32  vid_hdr_offset;
-	__be32  data_offset;
-	__u8    padding2[36];
-	__be32  hdr_crc;
-} __attribute__ ((packed));
-
-/**
- * struct ubi_vid_hdr - on-flash UBI volume identifier header.
- * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
- * @version: UBI implementation version which is supposed to accept this UBI
- * image (%UBI_VERSION)
- * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
- * @copy_flag: if this logical eraseblock was copied from another physical
- * eraseblock (for wear-leveling reasons)
- * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
- * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
- * @vol_id: ID of this volume
- * @lnum: logical eraseblock number
- * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
- * removed, kept only for not breaking older UBI users)
- * @data_size: how many bytes of data this logical eraseblock contains
- * @used_ebs: total number of used logical eraseblocks in this volume
- * @data_pad: how many bytes at the end of this physical eraseblock are not
- * used
- * @data_crc: CRC checksum of the data stored in this logical eraseblock
- * @padding1: reserved for future, zeroes
- * @sqnum: sequence number
- * @padding2: reserved for future, zeroes
- * @hdr_crc: volume identifier header CRC checksum
- *
- * The @sqnum is the value of the global sequence counter at the time when this
- * VID header was created. The global sequence counter is incremented each time
- * UBI writes a new VID header to the flash, i.e. when it maps a logical
- * eraseblock to a new physical eraseblock. The global sequence counter is an
- * unsigned 64-bit integer and we assume it never overflows. The @sqnum
- * (sequence number) is used to distinguish between older and newer versions of
- * logical eraseblocks.
- *
- * There are 2 situations when there may be more then one physical eraseblock
- * corresponding to the same logical eraseblock, i.e., having the same @vol_id
- * and @lnum values in the volume identifier header. Suppose we have a logical
- * eraseblock L and it is mapped to the physical eraseblock P.
- *
- * 1. Because UBI may erase physical eraseblocks asynchronously, the following
- * situation is possible: L is asynchronously erased, so P is scheduled for
- * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
- * so P1 is written to, then an unclean reboot happens. Result - there are 2
- * physical eraseblocks P and P1 corresponding to the same logical eraseblock
- * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
- * flash.
- *
- * 2. From time to time UBI moves logical eraseblocks to other physical
- * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
- * to P1, and an unclean reboot happens before P is physically erased, there
- * are two physical eraseblocks P and P1 corresponding to L and UBI has to
- * select one of them when the flash is attached. The @sqnum field says which
- * PEB is the original (obviously P will have lower @sqnum) and the copy. But
- * it is not enough to select the physical eraseblock with the higher sequence
- * number, because the unclean reboot could have happen in the middle of the
- * copying process, so the data in P is corrupted. It is also not enough to
- * just select the physical eraseblock with lower sequence number, because the
- * data there may be old (consider a case if more data was added to P1 after
- * the copying). Moreover, the unclean reboot may happen when the erasure of P
- * was just started, so it result in unstable P, which is "mostly" OK, but
- * still has unstable bits.
- *
- * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
- * copy. UBI also calculates data CRC when the data is moved and stores it at
- * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
- * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
- * examined. If it is cleared, the situation* is simple and the newer one is
- * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
- * checksum is correct, this physical eraseblock is selected (P1). Otherwise
- * the older one (P) is selected.
- *
- * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
- * in the past. But it is not used anymore and we keep it in order to be able
- * to deal with old UBI images. It will be removed at some point.
- *
- * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
- * Internal volumes are not seen from outside and are used for various internal
- * UBI purposes. In this implementation there is only one internal volume - the
- * layout volume. Internal volumes are the main mechanism of UBI extensions.
- * For example, in future one may introduce a journal internal volume. Internal
- * volumes have their own reserved range of IDs.
- *
- * The @compat field is only used for internal volumes and contains the "degree
- * of their compatibility". It is always zero for user volumes. This field
- * provides a mechanism to introduce UBI extensions and to be still compatible
- * with older UBI binaries. For example, if someone introduced a journal in
- * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
- * journal volume.  And in this case, older UBI binaries, which know nothing
- * about the journal volume, would just delete this volume and work perfectly
- * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
- * - it just ignores the Ext3fs journal.
- *
- * The @data_crc field contains the CRC checksum of the contents of the logical
- * eraseblock if this is a static volume. In case of dynamic volumes, it does
- * not contain the CRC checksum as a rule. The only exception is when the
- * data of the physical eraseblock was moved by the wear-leveling unit, then
- * the wear-leveling unit calculates the data CRC and stores it in the
- * @data_crc field. And of course, the @copy_flag is %in this case.
- *
- * The @data_size field is used only for static volumes because UBI has to know
- * how many bytes of data are stored in this eraseblock. For dynamic volumes,
- * this field usually contains zero. The only exception is when the data of the
- * physical eraseblock was moved to another physical eraseblock for
- * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
- * contents and uses both @data_crc and @data_size fields. In this case, the
- * @data_size field contains data size.
- *
- * The @used_ebs field is used only for static volumes and indicates how many
- * eraseblocks the data of the volume takes. For dynamic volumes this field is
- * not used and always contains zero.
- *
- * The @data_pad is calculated when volumes are created using the alignment
- * parameter. So, effectively, the @data_pad field reduces the size of logical
- * eraseblocks of this volume. This is very handy when one uses block-oriented
- * software (say, cramfs) on top of the UBI volume.
- */
-struct ubi_vid_hdr {
-	__be32  magic;
-	__u8    version;
-	__u8    vol_type;
-	__u8    copy_flag;
-	__u8    compat;
-	__be32  vol_id;
-	__be32  lnum;
-	__be32  leb_ver; /* obsolete, to be removed, don't use */
-	__be32  data_size;
-	__be32  used_ebs;
-	__be32  data_pad;
-	__be32  data_crc;
-	__u8    padding1[4];
-	__be64  sqnum;
-	__u8    padding2[12];
-	__be32  hdr_crc;
-} __attribute__ ((packed));
-
-/* Internal UBI volumes count */
-#define UBI_INT_VOL_COUNT 1
-
-/*
- * Starting ID of internal volumes. There is reserved room for 4096 internal
- * volumes.
- */
-#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
-
-/* The layout volume contains the volume table */
-
-#define UBI_LAYOUT_VOLUME_ID     UBI_INTERNAL_VOL_START
-#define UBI_LAYOUT_VOLUME_TYPE   UBI_VID_DYNAMIC
-#define UBI_LAYOUT_VOLUME_ALIGN  1
-#define UBI_LAYOUT_VOLUME_EBS    2
-#define UBI_LAYOUT_VOLUME_NAME   "layout volume"
-#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
-
-/* The maximum number of volumes per one UBI device */
-#define UBI_MAX_VOLUMES 128
-
-/* The maximum volume name length */
-#define UBI_VOL_NAME_MAX 127
-
-/* Size of the volume table record */
-#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
-
-/* Size of the volume table record without the ending CRC */
-#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
-
-/**
- * struct ubi_vtbl_record - a record in the volume table.
- * @reserved_pebs: how many physical eraseblocks are reserved for this volume
- * @alignment: volume alignment
- * @data_pad: how many bytes are unused at the end of the each physical
- * eraseblock to satisfy the requested alignment
- * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
- * @upd_marker: if volume update was started but not finished
- * @name_len: volume name length
- * @name: the volume name
- * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
- * @padding: reserved, zeroes
- * @crc: a CRC32 checksum of the record
- *
- * The volume table records are stored in the volume table, which is stored in
- * the layout volume. The layout volume consists of 2 logical eraseblock, each
- * of which contains a copy of the volume table (i.e., the volume table is
- * duplicated). The volume table is an array of &struct ubi_vtbl_record
- * objects indexed by the volume ID.
- *
- * If the size of the logical eraseblock is large enough to fit
- * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
- * records. Otherwise, it contains as many records as it can fit (i.e., size of
- * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
- *
- * The @upd_marker flag is used to implement volume update. It is set to %1
- * before update and set to %0 after the update. So if the update operation was
- * interrupted, UBI knows that the volume is corrupted.
- *
- * The @alignment field is specified when the volume is created and cannot be
- * later changed. It may be useful, for example, when a block-oriented file
- * system works on top of UBI. The @data_pad field is calculated using the
- * logical eraseblock size and @alignment. The alignment must be multiple to the
- * minimal flash I/O unit. If @alignment is 1, all the available space of
- * the physical eraseblocks is used.
- *
- * Empty records contain all zeroes and the CRC checksum of those zeroes.
- */
-struct ubi_vtbl_record {
-	__be32  reserved_pebs;
-	__be32  alignment;
-	__be32  data_pad;
-	__u8    vol_type;
-	__u8    upd_marker;
-	__be16  name_len;
-	__u8    name[UBI_VOL_NAME_MAX+1];
-	__u8    flags;
-	__u8    padding[23];
-	__be32  crc;
-} __attribute__ ((packed));
-
-#endif /* !__UBI_MEDIA_H__ */
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 97aed8f..964a3c4 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -45,7 +45,8 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/ubi.h>
 
-#include "ubi-media.h"
+#include <mtd/ubi-media.h>
+
 #include "scan.h"
 #include "debug.h"
 
diff --git a/include/mtd/ubi-media.h b/include/mtd/ubi-media.h
new file mode 100644
index 0000000..cd1bd8e
--- /dev/null
+++ b/include/mtd/ubi-media.h
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ *
+ * Authors: Artem Bityutskiy (Битюцкий Артём)
+ *          Thomas Gleixner
+ *          Frank Haverkamp
+ *          Oliver Lohmann
+ *          Andreas Arnez
+ */
+
+/*
+ * This file defines the layout of UBI headers and all the other UBI on-flash
+ * data structures.
+ */
+
+#ifndef __UBI_MEDIA_H__
+#define __UBI_MEDIA_H__
+
+#include <asm/byteorder.h>
+
+/* The version of UBI images supported by this implementation */
+#define UBI_VERSION 1
+
+/* The highest erase counter value supported by this implementation */
+#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
+
+/* The initial CRC32 value used when calculating CRC checksums */
+#define UBI_CRC32_INIT 0xFFFFFFFFU
+
+/* Erase counter header magic number (ASCII "UBI#") */
+#define UBI_EC_HDR_MAGIC  0x55424923
+/* Volume identifier header magic number (ASCII "UBI!") */
+#define UBI_VID_HDR_MAGIC 0x55424921
+
+/*
+ * Volume type constants used in the volume identifier header.
+ *
+ * @UBI_VID_DYNAMIC: dynamic volume
+ * @UBI_VID_STATIC: static volume
+ */
+enum {
+	UBI_VID_DYNAMIC = 1,
+	UBI_VID_STATIC  = 2
+};
+
+/*
+ * Volume flags used in the volume table record.
+ *
+ * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
+ *
+ * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
+ * table. UBI automatically re-sizes the volume which has this flag and makes
+ * the volume to be of largest possible size. This means that if after the
+ * initialization UBI finds out that there are available physical eraseblocks
+ * present on the device, it automatically appends all of them to the volume
+ * (the physical eraseblocks reserved for bad eraseblocks handling and other
+ * reserved physical eraseblocks are not taken). So, if there is a volume with
+ * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical
+ * eraseblocks will be zero after UBI is loaded, because all of them will be
+ * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared
+ * after the volume had been initialized.
+ *
+ * The auto-resize feature is useful for device production purposes. For
+ * example, different NAND flash chips may have different amount of initial bad
+ * eraseblocks, depending of particular chip instance. Manufacturers of NAND
+ * chips usually guarantee that the amount of initial bad eraseblocks does not
+ * exceed certain percent, e.g. 2%. When one creates an UBI image which will be
+ * flashed to the end devices in production, he does not know the exact amount
+ * of good physical eraseblocks the NAND chip on the device will have, but this
+ * number is required to calculate the volume sized and put them to the volume
+ * table of the UBI image. In this case, one of the volumes (e.g., the one
+ * which will store the root file system) is marked as "auto-resizable", and
+ * UBI will adjust its size on the first boot if needed.
+ *
+ * Note, first UBI reserves some amount of physical eraseblocks for bad
+ * eraseblock handling, and then re-sizes the volume, not vice-versa. This
+ * means that the pool of reserved physical eraseblocks will always be present.
+ */
+enum {
+	UBI_VTBL_AUTORESIZE_FLG = 0x01,
+};
+
+/*
+ * Compatibility constants used by internal volumes.
+ *
+ * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
+ * to the flash
+ * @UBI_COMPAT_RO: attach this device in read-only mode
+ * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
+ * physical eraseblocks, don't allow the wear-leveling unit to move them
+ * @UBI_COMPAT_REJECT: reject this UBI image
+ */
+enum {
+	UBI_COMPAT_DELETE   = 1,
+	UBI_COMPAT_RO       = 2,
+	UBI_COMPAT_PRESERVE = 4,
+	UBI_COMPAT_REJECT   = 5
+};
+
+/* Sizes of UBI headers */
+#define UBI_EC_HDR_SIZE  sizeof(struct ubi_ec_hdr)
+#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
+
+/* Sizes of UBI headers without the ending CRC */
+#define UBI_EC_HDR_SIZE_CRC  (UBI_EC_HDR_SIZE  - sizeof(__be32))
+#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32))
+
+/**
+ * struct ubi_ec_hdr - UBI erase counter header.
+ * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
+ * @version: version of UBI implementation which is supposed to accept this
+ * UBI image
+ * @padding1: reserved for future, zeroes
+ * @ec: the erase counter
+ * @vid_hdr_offset: where the VID header starts
+ * @data_offset: where the user data start
+ * @padding2: reserved for future, zeroes
+ * @hdr_crc: erase counter header CRC checksum
+ *
+ * The erase counter header takes 64 bytes and has a plenty of unused space for
+ * future usage. The unused fields are zeroed. The @version field is used to
+ * indicate the version of UBI implementation which is supposed to be able to
+ * work with this UBI image. If @version is greater then the current UBI
+ * version, the image is rejected. This may be useful in future if something
+ * is changed radically. This field is duplicated in the volume identifier
+ * header.
+ *
+ * The @vid_hdr_offset and @data_offset fields contain the offset of the the
+ * volume identifier header and user data, relative to the beginning of the
+ * physical eraseblock. These values have to be the same for all physical
+ * eraseblocks.
+ */
+struct ubi_ec_hdr {
+	__be32  magic;
+	__u8    version;
+	__u8    padding1[3];
+	__be64  ec; /* Warning: the current limit is 31-bit anyway! */
+	__be32  vid_hdr_offset;
+	__be32  data_offset;
+	__u8    padding2[36];
+	__be32  hdr_crc;
+} __attribute__ ((packed));
+
+/**
+ * struct ubi_vid_hdr - on-flash UBI volume identifier header.
+ * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
+ * @version: UBI implementation version which is supposed to accept this UBI
+ * image (%UBI_VERSION)
+ * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
+ * @copy_flag: if this logical eraseblock was copied from another physical
+ * eraseblock (for wear-leveling reasons)
+ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
+ * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ * @vol_id: ID of this volume
+ * @lnum: logical eraseblock number
+ * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
+ * removed, kept only for not breaking older UBI users)
+ * @data_size: how many bytes of data this logical eraseblock contains
+ * @used_ebs: total number of used logical eraseblocks in this volume
+ * @data_pad: how many bytes at the end of this physical eraseblock are not
+ * used
+ * @data_crc: CRC checksum of the data stored in this logical eraseblock
+ * @padding1: reserved for future, zeroes
+ * @sqnum: sequence number
+ * @padding2: reserved for future, zeroes
+ * @hdr_crc: volume identifier header CRC checksum
+ *
+ * The @sqnum is the value of the global sequence counter at the time when this
+ * VID header was created. The global sequence counter is incremented each time
+ * UBI writes a new VID header to the flash, i.e. when it maps a logical
+ * eraseblock to a new physical eraseblock. The global sequence counter is an
+ * unsigned 64-bit integer and we assume it never overflows. The @sqnum
+ * (sequence number) is used to distinguish between older and newer versions of
+ * logical eraseblocks.
+ *
+ * There are 2 situations when there may be more then one physical eraseblock
+ * corresponding to the same logical eraseblock, i.e., having the same @vol_id
+ * and @lnum values in the volume identifier header. Suppose we have a logical
+ * eraseblock L and it is mapped to the physical eraseblock P.
+ *
+ * 1. Because UBI may erase physical eraseblocks asynchronously, the following
+ * situation is possible: L is asynchronously erased, so P is scheduled for
+ * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
+ * so P1 is written to, then an unclean reboot happens. Result - there are 2
+ * physical eraseblocks P and P1 corresponding to the same logical eraseblock
+ * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
+ * flash.
+ *
+ * 2. From time to time UBI moves logical eraseblocks to other physical
+ * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
+ * to P1, and an unclean reboot happens before P is physically erased, there
+ * are two physical eraseblocks P and P1 corresponding to L and UBI has to
+ * select one of them when the flash is attached. The @sqnum field says which
+ * PEB is the original (obviously P will have lower @sqnum) and the copy. But
+ * it is not enough to select the physical eraseblock with the higher sequence
+ * number, because the unclean reboot could have happen in the middle of the
+ * copying process, so the data in P is corrupted. It is also not enough to
+ * just select the physical eraseblock with lower sequence number, because the
+ * data there may be old (consider a case if more data was added to P1 after
+ * the copying). Moreover, the unclean reboot may happen when the erasure of P
+ * was just started, so it result in unstable P, which is "mostly" OK, but
+ * still has unstable bits.
+ *
+ * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
+ * copy. UBI also calculates data CRC when the data is moved and stores it at
+ * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
+ * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
+ * examined. If it is cleared, the situation* is simple and the newer one is
+ * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
+ * checksum is correct, this physical eraseblock is selected (P1). Otherwise
+ * the older one (P) is selected.
+ *
+ * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
+ * in the past. But it is not used anymore and we keep it in order to be able
+ * to deal with old UBI images. It will be removed at some point.
+ *
+ * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
+ * Internal volumes are not seen from outside and are used for various internal
+ * UBI purposes. In this implementation there is only one internal volume - the
+ * layout volume. Internal volumes are the main mechanism of UBI extensions.
+ * For example, in future one may introduce a journal internal volume. Internal
+ * volumes have their own reserved range of IDs.
+ *
+ * The @compat field is only used for internal volumes and contains the "degree
+ * of their compatibility". It is always zero for user volumes. This field
+ * provides a mechanism to introduce UBI extensions and to be still compatible
+ * with older UBI binaries. For example, if someone introduced a journal in
+ * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
+ * journal volume.  And in this case, older UBI binaries, which know nothing
+ * about the journal volume, would just delete this volume and work perfectly
+ * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
+ * - it just ignores the Ext3fs journal.
+ *
+ * The @data_crc field contains the CRC checksum of the contents of the logical
+ * eraseblock if this is a static volume. In case of dynamic volumes, it does
+ * not contain the CRC checksum as a rule. The only exception is when the
+ * data of the physical eraseblock was moved by the wear-leveling unit, then
+ * the wear-leveling unit calculates the data CRC and stores it in the
+ * @data_crc field. And of course, the @copy_flag is %in this case.
+ *
+ * The @data_size field is used only for static volumes because UBI has to know
+ * how many bytes of data are stored in this eraseblock. For dynamic volumes,
+ * this field usually contains zero. The only exception is when the data of the
+ * physical eraseblock was moved to another physical eraseblock for
+ * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
+ * contents and uses both @data_crc and @data_size fields. In this case, the
+ * @data_size field contains data size.
+ *
+ * The @used_ebs field is used only for static volumes and indicates how many
+ * eraseblocks the data of the volume takes. For dynamic volumes this field is
+ * not used and always contains zero.
+ *
+ * The @data_pad is calculated when volumes are created using the alignment
+ * parameter. So, effectively, the @data_pad field reduces the size of logical
+ * eraseblocks of this volume. This is very handy when one uses block-oriented
+ * software (say, cramfs) on top of the UBI volume.
+ */
+struct ubi_vid_hdr {
+	__be32  magic;
+	__u8    version;
+	__u8    vol_type;
+	__u8    copy_flag;
+	__u8    compat;
+	__be32  vol_id;
+	__be32  lnum;
+	__be32  leb_ver; /* obsolete, to be removed, don't use */
+	__be32  data_size;
+	__be32  used_ebs;
+	__be32  data_pad;
+	__be32  data_crc;
+	__u8    padding1[4];
+	__be64  sqnum;
+	__u8    padding2[12];
+	__be32  hdr_crc;
+} __attribute__ ((packed));
+
+/* Internal UBI volumes count */
+#define UBI_INT_VOL_COUNT 1
+
+/*
+ * Starting ID of internal volumes. There is reserved room for 4096 internal
+ * volumes.
+ */
+#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
+
+/* The layout volume contains the volume table */
+
+#define UBI_LAYOUT_VOLUME_ID     UBI_INTERNAL_VOL_START
+#define UBI_LAYOUT_VOLUME_TYPE   UBI_VID_DYNAMIC
+#define UBI_LAYOUT_VOLUME_ALIGN  1
+#define UBI_LAYOUT_VOLUME_EBS    2
+#define UBI_LAYOUT_VOLUME_NAME   "layout volume"
+#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
+
+/* The maximum number of volumes per one UBI device */
+#define UBI_MAX_VOLUMES 128
+
+/* The maximum volume name length */
+#define UBI_VOL_NAME_MAX 127
+
+/* Size of the volume table record */
+#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
+
+/* Size of the volume table record without the ending CRC */
+#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
+
+/**
+ * struct ubi_vtbl_record - a record in the volume table.
+ * @reserved_pebs: how many physical eraseblocks are reserved for this volume
+ * @alignment: volume alignment
+ * @data_pad: how many bytes are unused at the end of the each physical
+ * eraseblock to satisfy the requested alignment
+ * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
+ * @upd_marker: if volume update was started but not finished
+ * @name_len: volume name length
+ * @name: the volume name
+ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
+ * @padding: reserved, zeroes
+ * @crc: a CRC32 checksum of the record
+ *
+ * The volume table records are stored in the volume table, which is stored in
+ * the layout volume. The layout volume consists of 2 logical eraseblock, each
+ * of which contains a copy of the volume table (i.e., the volume table is
+ * duplicated). The volume table is an array of &struct ubi_vtbl_record
+ * objects indexed by the volume ID.
+ *
+ * If the size of the logical eraseblock is large enough to fit
+ * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
+ * records. Otherwise, it contains as many records as it can fit (i.e., size of
+ * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
+ *
+ * The @upd_marker flag is used to implement volume update. It is set to %1
+ * before update and set to %0 after the update. So if the update operation was
+ * interrupted, UBI knows that the volume is corrupted.
+ *
+ * The @alignment field is specified when the volume is created and cannot be
+ * later changed. It may be useful, for example, when a block-oriented file
+ * system works on top of UBI. The @data_pad field is calculated using the
+ * logical eraseblock size and @alignment. The alignment must be multiple to the
+ * minimal flash I/O unit. If @alignment is 1, all the available space of
+ * the physical eraseblocks is used.
+ *
+ * Empty records contain all zeroes and the CRC checksum of those zeroes.
+ */
+struct ubi_vtbl_record {
+	__be32  reserved_pebs;
+	__be32  alignment;
+	__be32  data_pad;
+	__u8    vol_type;
+	__u8    upd_marker;
+	__be16  name_len;
+	__u8    name[UBI_VOL_NAME_MAX+1];
+	__u8    flags;
+	__u8    padding[23];
+	__be32  crc;
+} __attribute__ ((packed));
+
+#endif /* !__UBI_MEDIA_H__ */
diff --git a/include/ubi-media.h b/include/ubi-media.h
deleted file mode 100644
index 4edbbb2..0000000
--- a/include/ubi-media.h
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
- * the GNU General Public License for more details.
- *
- *
- * Authors: Artem Bityutskiy (Битюцкий Артём)
- *          Thomas Gleixner
- *          Frank Haverkamp
- *          Oliver Lohmann
- *          Andreas Arnez
- */
-
-/*
- * This file defines the layout of UBI headers and all the other UBI on-flash
- * data structures.
- */
-
-#ifndef __UBI_MEDIA_H__
-#define __UBI_MEDIA_H__
-
-#ifndef DOXYGEN_SHOULD_SKIP_THIS
-
-#include <asm/byteorder.h>
-
-/* The version of UBI images supported by this implementation */
-#define UBI_VERSION 1
-
-/* The highest erase counter value supported by this implementation */
-#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF
-
-/* The initial CRC32 value used when calculating CRC checksums */
-#define UBI_CRC32_INIT 0xFFFFFFFFU
-
-/* Erase counter header magic number (ASCII "UBI#") */
-#define UBI_EC_HDR_MAGIC  0x55424923
-/* Volume identifier header magic number (ASCII "UBI!") */
-#define UBI_VID_HDR_MAGIC 0x55424921
-
-/*
- * Volume type constants used in the volume identifier header.
- *
- * @UBI_VID_DYNAMIC: dynamic volume
- * @UBI_VID_STATIC: static volume
- */
-enum {
-	UBI_VID_DYNAMIC = 1,
-	UBI_VID_STATIC  = 2
-};
-
-/*
- * Volume flags used in the volume table record.
- *
- * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume
- *
- * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume
- * table. UBI automatically re-sizes the volume which has this flag and makes
- * the volume to be of largest possible size. This means that if after the
- * initialization UBI finds out that there are available physical eraseblocks
- * present on the device, it automatically appends all of them to the volume
- * (the physical eraseblocks reserved for bad eraseblocks handling and other
- * reserved physical eraseblocks are not taken). So, if there is a volume with
- * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical
- * eraseblocks will be zero after UBI is loaded, because all of them will be
- * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared
- * after the volume had been initialized.
- *
- * The auto-resize feature is useful for device production purposes. For
- * example, different NAND flash chips may have different amount of initial bad
- * eraseblocks, depending of particular chip instance. Manufacturers of NAND
- * chips usually guarantee that the amount of initial bad eraseblocks does not
- * exceed certain percent, e.g. 2%. When one creates an UBI image which will be
- * flashed to the end devices in production, he does not know the exact amount
- * of good physical eraseblocks the NAND chip on the device will have, but this
- * number is required to calculate the volume sized and put them to the volume
- * table of the UBI image. In this case, one of the volumes (e.g., the one
- * which will store the root file system) is marked as "auto-resizable", and
- * UBI will adjust its size on the first boot if needed.
- *
- * Note, first UBI reserves some amount of physical eraseblocks for bad
- * eraseblock handling, and then re-sizes the volume, not vice-versa. This
- * means that the pool of reserved physical eraseblocks will always be present.
- */
-enum {
-	UBI_VTBL_AUTORESIZE_FLG = 0x01,
-};
-
-/*
- * Compatibility constants used by internal volumes.
- *
- * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
- *                     to the flash
- * @UBI_COMPAT_RO: attach this device in read-only mode
- * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
- *                       physical eraseblocks, don't allow the wear-leveling
- *                       sub-system to move them
- * @UBI_COMPAT_REJECT: reject this UBI image
- */
-enum {
-	UBI_COMPAT_DELETE   = 1,
-	UBI_COMPAT_RO       = 2,
-	UBI_COMPAT_PRESERVE = 4,
-	UBI_COMPAT_REJECT   = 5
-};
-
-/* Sizes of UBI headers */
-#define UBI_EC_HDR_SIZE  sizeof(struct ubi_ec_hdr)
-#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr)
-
-/* Sizes of UBI headers without the ending CRC */
-#define UBI_EC_HDR_SIZE_CRC  (UBI_EC_HDR_SIZE  - sizeof(__be32))
-#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32))
-
-/**
- * struct ubi_ec_hdr - UBI erase counter header.
- * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
- * @version: version of UBI implementation which is supposed to accept this
- *           UBI image
- * @padding1: reserved for future, zeroes
- * @ec: the erase counter
- * @vid_hdr_offset: where the VID header starts
- * @data_offset: where the user data start
- * @padding2: reserved for future, zeroes
- * @hdr_crc: erase counter header CRC checksum
- *
- * The erase counter header takes 64 bytes and has a plenty of unused space for
- * future usage. The unused fields are zeroed. The @version field is used to
- * indicate the version of UBI implementation which is supposed to be able to
- * work with this UBI image. If @version is greater than the current UBI
- * version, the image is rejected. This may be useful in future if something
- * is changed radically. This field is duplicated in the volume identifier
- * header.
- *
- * The @vid_hdr_offset and @data_offset fields contain the offset of the the
- * volume identifier header and user data, relative to the beginning of the
- * physical eraseblock. These values have to be the same for all physical
- * eraseblocks.
- */
-struct ubi_ec_hdr {
-	__be32  magic;
-	__u8    version;
-	__u8    padding1[3];
-	__be64  ec; /* Warning: the current limit is 31-bit anyway! */
-	__be32  vid_hdr_offset;
-	__be32  data_offset;
-	__u8    padding2[36];
-	__be32  hdr_crc;
-} __attribute__ ((packed));
-
-/**
- * struct ubi_vid_hdr - on-flash UBI volume identifier header.
- * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
- * @version: UBI implementation version which is supposed to accept this UBI
- *           image (%UBI_VERSION)
- * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
- * @copy_flag: if this logical eraseblock was copied from another physical
- *             eraseblock (for wear-leveling reasons)
- * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
- *          %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
- * @vol_id: ID of this volume
- * @lnum: logical eraseblock number
- * @padding1: reserved for future, zeroes
- * @data_size: how many bytes of data this logical eraseblock contains
- * @used_ebs: total number of used logical eraseblocks in this volume
- * @data_pad: how many bytes at the end of this physical eraseblock are not
- *            used
- * @data_crc: CRC checksum of the data stored in this logical eraseblock
- * @padding2: reserved for future, zeroes
- * @sqnum: sequence number
- * @padding3: reserved for future, zeroes
- * @hdr_crc: volume identifier header CRC checksum
- *
- * The @sqnum is the value of the global sequence counter at the time when this
- * VID header was created. The global sequence counter is incremented each time
- * UBI writes a new VID header to the flash, i.e. when it maps a logical
- * eraseblock to a new physical eraseblock. The global sequence counter is an
- * unsigned 64-bit integer and we assume it never overflows. The @sqnum
- * (sequence number) is used to distinguish between older and newer versions of
- * logical eraseblocks.
- *
- * There are 2 situations when there may be more than one physical eraseblock
- * corresponding to the same logical eraseblock, i.e., having the same @vol_id
- * and @lnum values in the volume identifier header. Suppose we have a logical
- * eraseblock L and it is mapped to the physical eraseblock P.
- *
- * 1. Because UBI may erase physical eraseblocks asynchronously, the following
- * situation is possible: L is asynchronously erased, so P is scheduled for
- * erasure, then L is written to,i.e. mapped to another physical eraseblock P1,
- * so P1 is written to, then an unclean reboot happens. Result - there are 2
- * physical eraseblocks P and P1 corresponding to the same logical eraseblock
- * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the
- * flash.
- *
- * 2. From time to time UBI moves logical eraseblocks to other physical
- * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P
- * to P1, and an unclean reboot happens before P is physically erased, there
- * are two physical eraseblocks P and P1 corresponding to L and UBI has to
- * select one of them when the flash is attached. The @sqnum field says which
- * PEB is the original (obviously P will have lower @sqnum) and the copy. But
- * it is not enough to select the physical eraseblock with the higher sequence
- * number, because the unclean reboot could have happen in the middle of the
- * copying process, so the data in P is corrupted. It is also not enough to
- * just select the physical eraseblock with lower sequence number, because the
- * data there may be old (consider a case if more data was added to P1 after
- * the copying). Moreover, the unclean reboot may happen when the erasure of P
- * was just started, so it result in unstable P, which is "mostly" OK, but
- * still has unstable bits.
- *
- * UBI uses the @copy_flag field to indicate that this logical eraseblock is a
- * copy. UBI also calculates data CRC when the data is moved and stores it at
- * the @data_crc field of the copy (P1). So when UBI needs to pick one physical
- * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is
- * examined. If it is cleared, the situation* is simple and the newer one is
- * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC
- * checksum is correct, this physical eraseblock is selected (P1). Otherwise
- * the older one (P) is selected.
- *
- * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
- * Internal volumes are not seen from outside and are used for various internal
- * UBI purposes. In this implementation there is only one internal volume - the
- * layout volume. Internal volumes are the main mechanism of UBI extensions.
- * For example, in future one may introduce a journal internal volume. Internal
- * volumes have their own reserved range of IDs.
- *
- * The @compat field is only used for internal volumes and contains the "degree
- * of their compatibility". It is always zero for user volumes. This field
- * provides a mechanism to introduce UBI extensions and to be still compatible
- * with older UBI binaries. For example, if someone introduced a journal in
- * future, he would probably use %UBI_COMPAT_DELETE compatibility for the
- * journal volume.  And in this case, older UBI binaries, which know nothing
- * about the journal volume, would just delete this volume and work perfectly
- * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image
- * - it just ignores the Ext3fs journal.
- *
- * The @data_crc field contains the CRC checksum of the contents of the logical
- * eraseblock if this is a static volume. In case of dynamic volumes, it does
- * not contain the CRC checksum as a rule. The only exception is when the
- * data of the physical eraseblock was moved by the wear-leveling sub-system,
- * then the wear-leveling sub-system calculates the data CRC and stores it in
- * the @data_crc field. And of course, the @copy_flag is %in this case.
- *
- * The @data_size field is used only for static volumes because UBI has to know
- * how many bytes of data are stored in this eraseblock. For dynamic volumes,
- * this field usually contains zero. The only exception is when the data of the
- * physical eraseblock was moved to another physical eraseblock for
- * wear-leveling reasons. In this case, UBI calculates CRC checksum of the
- * contents and uses both @data_crc and @data_size fields. In this case, the
- * @data_size field contains data size.
- *
- * The @used_ebs field is used only for static volumes and indicates how many
- * eraseblocks the data of the volume takes. For dynamic volumes this field is
- * not used and always contains zero.
- *
- * The @data_pad is calculated when volumes are created using the alignment
- * parameter. So, effectively, the @data_pad field reduces the size of logical
- * eraseblocks of this volume. This is very handy when one uses block-oriented
- * software (say, cramfs) on top of the UBI volume.
- */
-struct ubi_vid_hdr {
-	__be32  magic;
-	__u8    version;
-	__u8    vol_type;
-	__u8    copy_flag;
-	__u8    compat;
-	__be32  vol_id;
-	__be32  lnum;
-	__be32  leb_ver;
-	__be32  data_size;
-	__be32  used_ebs;
-	__be32  data_pad;
-	__be32  data_crc;
-	__u8    padding2[4];
-	__be64  sqnum;
-	__u8    padding3[12];
-	__be32  hdr_crc;
-} __attribute__ ((packed));
-
-/* Internal UBI volumes count */
-#define UBI_INT_VOL_COUNT 1
-
-/*
- * Starting ID of internal volumes. There is reserved room for 4096 internal
- * volumes.
- */
-#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096)
-
-/* The layout volume contains the volume table */
-
-#define UBI_LAYOUT_VOLUME_ID     UBI_INTERNAL_VOL_START
-#define UBI_LAYOUT_VOLUME_TYPE   UBI_VID_DYNAMIC
-#define UBI_LAYOUT_VOLUME_ALIGN  1
-#define UBI_LAYOUT_VOLUME_EBS    2
-#define UBI_LAYOUT_VOLUME_NAME   "layout volume"
-#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT
-
-/* The maximum number of volumes per one UBI device */
-#define UBI_MAX_VOLUMES 128
-
-/* The maximum volume name length */
-#define UBI_VOL_NAME_MAX 127
-
-/* Size of the volume table record */
-#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record)
-
-/* Size of the volume table record without the ending CRC */
-#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32))
-
-/**
- * struct ubi_vtbl_record - a record in the volume table.
- * @reserved_pebs: how many physical eraseblocks are reserved for this volume
- * @alignment: volume alignment
- * @data_pad: how many bytes are unused at the end of the each physical
- * eraseblock to satisfy the requested alignment
- * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME)
- * @upd_marker: if volume update was started but not finished
- * @name_len: volume name length
- * @name: the volume name
- * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
- * @padding: reserved, zeroes
- * @crc: a CRC32 checksum of the record
- *
- * The volume table records are stored in the volume table, which is stored in
- * the layout volume. The layout volume consists of 2 logical eraseblock, each
- * of which contains a copy of the volume table (i.e., the volume table is
- * duplicated). The volume table is an array of &struct ubi_vtbl_record
- * objects indexed by the volume ID.
- *
- * If the size of the logical eraseblock is large enough to fit
- * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES
- * records. Otherwise, it contains as many records as it can fit (i.e., size of
- * logical eraseblock divided by sizeof(struct ubi_vtbl_record)).
- *
- * The @upd_marker flag is used to implement volume update. It is set to %1
- * before update and set to %0 after the update. So if the update operation was
- * interrupted, UBI knows that the volume is corrupted.
- *
- * The @alignment field is specified when the volume is created and cannot be
- * later changed. It may be useful, for example, when a block-oriented file
- * system works on top of UBI. The @data_pad field is calculated using the
- * logical eraseblock size and @alignment. The alignment must be multiple to the
- * minimal flash I/O unit. If @alignment is 1, all the available space of
- * the physical eraseblocks is used.
- *
- * Empty records contain all zeroes and the CRC checksum of those zeroes.
- */
-struct ubi_vtbl_record {
-	__be32  reserved_pebs;
-	__be32  alignment;
-	__be32  data_pad;
-	__u8    vol_type;
-	__u8    upd_marker;
-	__be16  name_len;
-	__u8    name[UBI_VOL_NAME_MAX+1];
-	__u8    flags;
-	__u8    padding[23];
-	__be32  crc;
-} __attribute__ ((packed));
-
-#endif /* DOXYGEN_SHOULD_SKIP_THIS */
-
-#endif /* !__UBI_MEDIA_H__ */
-
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 05/11] ubi: bump ubi-media.h to newest version
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (3 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 04/11] ubi: consolidate ubi-media.h Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 06/11] devfs & mtd: add MEMERASE ioctl support Wolfram Sang
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Needed for ubiformat, we are interested in image_seq especially.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 include/mtd/ubi-media.h |   55 ++++++++++++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 25 deletions(-)

diff --git a/include/mtd/ubi-media.h b/include/mtd/ubi-media.h
index cd1bd8e..d552db8 100644
--- a/include/mtd/ubi-media.h
+++ b/include/mtd/ubi-media.h
@@ -11,7 +11,6 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  * the GNU General Public License for more details.
  *
- *
  * Authors: Artem Bityutskiy (Битюцкий Артём)
  *          Thomas Gleixner
  *          Frank Haverkamp
@@ -95,10 +94,11 @@ enum {
  * Compatibility constants used by internal volumes.
  *
  * @UBI_COMPAT_DELETE: delete this internal volume before anything is written
- * to the flash
+ *                     to the flash
  * @UBI_COMPAT_RO: attach this device in read-only mode
  * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its
- * physical eraseblocks, don't allow the wear-leveling unit to move them
+ *                       physical eraseblocks, don't allow the wear-leveling
+ *                       sub-system to move them
  * @UBI_COMPAT_REJECT: reject this UBI image
  */
 enum {
@@ -120,18 +120,19 @@ enum {
  * struct ubi_ec_hdr - UBI erase counter header.
  * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC)
  * @version: version of UBI implementation which is supposed to accept this
- * UBI image
+ *           UBI image
  * @padding1: reserved for future, zeroes
  * @ec: the erase counter
  * @vid_hdr_offset: where the VID header starts
  * @data_offset: where the user data start
+ * @image_seq: image sequence number
  * @padding2: reserved for future, zeroes
  * @hdr_crc: erase counter header CRC checksum
  *
  * The erase counter header takes 64 bytes and has a plenty of unused space for
  * future usage. The unused fields are zeroed. The @version field is used to
  * indicate the version of UBI implementation which is supposed to be able to
- * work with this UBI image. If @version is greater then the current UBI
+ * work with this UBI image. If @version is greater than the current UBI
  * version, the image is rejected. This may be useful in future if something
  * is changed radically. This field is duplicated in the volume identifier
  * header.
@@ -140,6 +141,14 @@ enum {
  * volume identifier header and user data, relative to the beginning of the
  * physical eraseblock. These values have to be the same for all physical
  * eraseblocks.
+ *
+ * The @image_seq field is used to validate a UBI image that has been prepared
+ * for a UBI device. The @image_seq value can be any value, but it must be the
+ * same on all eraseblocks. UBI will ensure that all new erase counter headers
+ * also contain this value, and will check the value when scanning at start-up.
+ * One way to make use of @image_seq is to increase its value by one every time
+ * an image is flashed over an existing image, then, if the flashing does not
+ * complete, UBI will detect the error when scanning.
  */
 struct ubi_ec_hdr {
 	__be32  magic;
@@ -148,7 +157,8 @@ struct ubi_ec_hdr {
 	__be64  ec; /* Warning: the current limit is 31-bit anyway! */
 	__be32  vid_hdr_offset;
 	__be32  data_offset;
-	__u8    padding2[36];
+	__be32  image_seq;
+	__u8    padding2[32];
 	__be32  hdr_crc;
 } __attribute__ ((packed));
 
@@ -156,24 +166,23 @@ struct ubi_ec_hdr {
  * struct ubi_vid_hdr - on-flash UBI volume identifier header.
  * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC)
  * @version: UBI implementation version which is supposed to accept this UBI
- * image (%UBI_VERSION)
+ *           image (%UBI_VERSION)
  * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
  * @copy_flag: if this logical eraseblock was copied from another physical
- * eraseblock (for wear-leveling reasons)
+ *             eraseblock (for wear-leveling reasons)
  * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
- * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ *          %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
  * @vol_id: ID of this volume
  * @lnum: logical eraseblock number
- * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be
- * removed, kept only for not breaking older UBI users)
+ * @padding1: reserved for future, zeroes
  * @data_size: how many bytes of data this logical eraseblock contains
  * @used_ebs: total number of used logical eraseblocks in this volume
  * @data_pad: how many bytes at the end of this physical eraseblock are not
- * used
+ *            used
  * @data_crc: CRC checksum of the data stored in this logical eraseblock
- * @padding1: reserved for future, zeroes
- * @sqnum: sequence number
  * @padding2: reserved for future, zeroes
+ * @sqnum: sequence number
+ * @padding3: reserved for future, zeroes
  * @hdr_crc: volume identifier header CRC checksum
  *
  * The @sqnum is the value of the global sequence counter at the time when this
@@ -184,7 +193,7 @@ struct ubi_ec_hdr {
  * (sequence number) is used to distinguish between older and newer versions of
  * logical eraseblocks.
  *
- * There are 2 situations when there may be more then one physical eraseblock
+ * There are 2 situations when there may be more than one physical eraseblock
  * corresponding to the same logical eraseblock, i.e., having the same @vol_id
  * and @lnum values in the volume identifier header. Suppose we have a logical
  * eraseblock L and it is mapped to the physical eraseblock P.
@@ -221,10 +230,6 @@ struct ubi_ec_hdr {
  * checksum is correct, this physical eraseblock is selected (P1). Otherwise
  * the older one (P) is selected.
  *
- * Note, there is an obsolete @leb_ver field which was used instead of @sqnum
- * in the past. But it is not used anymore and we keep it in order to be able
- * to deal with old UBI images. It will be removed at some point.
- *
  * There are 2 sorts of volumes in UBI: user volumes and internal volumes.
  * Internal volumes are not seen from outside and are used for various internal
  * UBI purposes. In this implementation there is only one internal volume - the
@@ -245,9 +250,9 @@ struct ubi_ec_hdr {
  * The @data_crc field contains the CRC checksum of the contents of the logical
  * eraseblock if this is a static volume. In case of dynamic volumes, it does
  * not contain the CRC checksum as a rule. The only exception is when the
- * data of the physical eraseblock was moved by the wear-leveling unit, then
- * the wear-leveling unit calculates the data CRC and stores it in the
- * @data_crc field. And of course, the @copy_flag is %in this case.
+ * data of the physical eraseblock was moved by the wear-leveling sub-system,
+ * then the wear-leveling sub-system calculates the data CRC and stores it in
+ * the @data_crc field. And of course, the @copy_flag is %in this case.
  *
  * The @data_size field is used only for static volumes because UBI has to know
  * how many bytes of data are stored in this eraseblock. For dynamic volumes,
@@ -274,14 +279,14 @@ struct ubi_vid_hdr {
 	__u8    compat;
 	__be32  vol_id;
 	__be32  lnum;
-	__be32  leb_ver; /* obsolete, to be removed, don't use */
+	__be32  leb_ver;
 	__be32  data_size;
 	__be32  used_ebs;
 	__be32  data_pad;
 	__be32  data_crc;
-	__u8    padding1[4];
+	__u8    padding2[4];
 	__be64  sqnum;
-	__u8    padding2[12];
+	__u8    padding3[12];
 	__be32  hdr_crc;
 } __attribute__ ((packed));
 
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 06/11] devfs & mtd: add MEMERASE ioctl support
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (4 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 05/11] ubi: bump ubi-media.h to newest version Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 07/11] mtd: utils: apply macros for message printouts Wolfram Sang
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

To make that, we need to shift mtd_erase before mtd_ioctl.
ubi-utils need that, especially ubiformat.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 drivers/mtd/core.c |   68 +++++++++++++++++++++++++++-------------------------
 fs/devfs-core.c    |    3 ++-
 2 files changed, 37 insertions(+), 34 deletions(-)

diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index 8601787..83e1a39 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -123,7 +123,37 @@ static ssize_t mtd_write(struct cdev* cdev, const void *buf, size_t _count,
 out:
 	return ret ? ret : _count;
 }
-#endif
+
+static int mtd_erase(struct cdev *cdev, size_t count, loff_t offset)
+{
+	struct mtd_info *mtd = cdev->priv;
+	struct erase_info erase;
+	int ret;
+
+	memset(&erase, 0, sizeof(erase));
+	erase.mtd = mtd;
+	erase.addr = offset;
+	erase.len = mtd->erasesize;
+
+	while (count > 0) {
+		dev_dbg(cdev->dev, "erase %d %d\n", erase.addr, erase.len);
+
+		ret = mtd_block_isbad(mtd, erase.addr);
+		if (ret > 0) {
+			printf("Skipping bad block at 0x%08x\n", erase.addr);
+		} else {
+			ret = mtd->erase(mtd, &erase);
+			if (ret)
+				return ret;
+		}
+
+		erase.addr += mtd->erasesize;
+		count -= count > mtd->erasesize ? mtd->erasesize : count;
+	}
+
+	return 0;
+}
+#endif /* CONFIG_MTD_WRITE */
 
 int mtd_ioctl(struct cdev *cdev, int request, void *buf)
 {
@@ -134,6 +164,7 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf)
 	struct mtd_ecc_stats *ecc = buf;
 #endif
 	struct region_info_user *reg = buf;
+	struct erase_info_user *ei = buf;
 	loff_t *offset = buf;
 
 	switch (request) {
@@ -146,6 +177,9 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf)
 		dev_dbg(cdev->dev, "MEMSETBADBLOCK: 0x%08llx\n", *offset);
 		ret = mtd->block_markbad(mtd, *offset);
 		break;
+	case MEMERASE:
+		ret = mtd_erase(cdev, ei->length, ei->start + cdev->offset);
+		break;
 #endif
 	case MEMGETINFO:
 		user->type	= mtd->type;
@@ -183,38 +217,6 @@ int mtd_ioctl(struct cdev *cdev, int request, void *buf)
 	return ret;
 }
 
-#ifdef CONFIG_MTD_WRITE
-static int mtd_erase(struct cdev *cdev, size_t count, loff_t offset)
-{
-	struct mtd_info *mtd = cdev->priv;
-	struct erase_info erase;
-	int ret;
-
-	memset(&erase, 0, sizeof(erase));
-	erase.mtd = mtd;
-	erase.addr = offset;
-	erase.len = mtd->erasesize;
-
-	while (count > 0) {
-		dev_dbg(cdev->dev, "erase %d %d\n", erase.addr, erase.len);
-
-		ret = mtd_block_isbad(mtd, erase.addr);
-		if (ret > 0) {
-			printf("Skipping bad block at 0x%08x\n", erase.addr);
-		} else {
-			ret = mtd->erase(mtd, &erase);
-			if (ret)
-				return ret;
-		}
-
-		erase.addr += mtd->erasesize;
-		count -= count > mtd->erasesize ? mtd->erasesize : count;
-	}
-
-	return 0;
-}
-#endif
-
 static struct file_operations mtd_ops = {
 	.read   = mtd_read,
 #ifdef CONFIG_MTD_WRITE
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 0d2f75a..262e0a2 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -152,13 +152,14 @@ static int partition_ioctl(struct cdev *cdev, int request, void *buf)
 		break;
 #if (defined(CONFIG_NAND_ECC_HW) || defined(CONFIG_NAND_ECC_SOFT))
 	case ECCGETSTATS:
+#endif
+	case MEMERASE:
 		if (!cdev->ops->ioctl) {
 			ret = -EINVAL;
 			break;
 		}
 		ret = cdev->ops->ioctl(cdev, request, buf);
 		break;
-#endif
 #ifdef CONFIG_PARTITION
 	case MEMGETREGIONINFO:
 		if (cdev->mtd) {
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 07/11] mtd: utils: apply macros for message printouts
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (5 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 06/11] devfs & mtd: add MEMERASE ioctl support Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 08/11] lib: add libscan Wolfram Sang
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

mtd-utils have a few macros for printouts. Provide the wrappers to make
it easier to import them.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 include/mtd/utils.h |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 include/mtd/utils.h

diff --git a/include/mtd/utils.h b/include/mtd/utils.h
new file mode 100644
index 0000000..fca64ab
--- /dev/null
+++ b/include/mtd/utils.h
@@ -0,0 +1,47 @@
+/*
+ * mtd/utils.h - helper functions for various MTD utilities
+ *
+ * Copyright (C) 2012 by Wolfram Sang <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef INCLUDE_MTD_UTILS_H
+# define INCLUDE_MTD_UTILS_H
+
+/* Messages as used in mtd-utils */
+
+#define bareverbose(verbose, fmt, ...) do {                        \
+	if (verbose)                                               \
+		printf(fmt, ##__VA_ARGS__);                        \
+} while(0)
+#define verbose(verbose, fmt, ...) \
+	bareverbose(verbose, "%s: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__)
+
+#define normsg_cont(fmt, ...) do {                                 \
+	printf("%s: " fmt, PROGRAM_NAME, ##__VA_ARGS__);           \
+} while(0)
+
+#define normsg(fmt, ...) do {                                      \
+	normsg_cont(fmt "\n", ##__VA_ARGS__);                      \
+} while(0)
+
+#define errmsg(fmt, ...)  ({                                                \
+	printf("%s: error!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \
+	-1;                                                                 \
+})
+#define sys_errmsg errmsg
+
+#define warnmsg(fmt, ...) do {                                                \
+	fprintf(stderr, "%s: warning!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \
+} while(0)
+
+#endif /* INCLUDE_MTD_UTILS_H */
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 08/11] lib: add libscan
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (6 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 07/11] mtd: utils: apply macros for message printouts Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 09/11] lib: add libubigen Wolfram Sang
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Imported from mtd-utils and stripped down to needed functionality.
Add prefix to functions so we have a clean namespace.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 include/mtd/libscan.h |  101 +++++++++++++++++++++++
 lib/Kconfig           |    3 +
 lib/Makefile          |    1 +
 lib/libscan.c         |  219 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 324 insertions(+)
 create mode 100644 include/mtd/libscan.h
 create mode 100644 lib/libscan.c

diff --git a/include/mtd/libscan.h b/include/mtd/libscan.h
new file mode 100644
index 0000000..bb01482
--- /dev/null
+++ b/include/mtd/libscan.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * UBI scanning library.
+ */
+
+#ifndef __LIBSCAN_H__
+#define __LIBSCAN_H__
+
+#include <mtd/ubi-media.h>
+
+/*
+ * If an eraseblock does not contain an erase counter, this value is used
+ * instead of the erase counter.
+ */
+#define NO_EC 0xFFFFFFFF
+
+/*
+ * If an eraseblock contains a corrupted erase counter, this value is used
+ * instead of the erase counter.
+ */
+#define CORRUPT_EC 0xFFFFFFFE
+
+/*
+ * If an eraseblock does not contain an erase counter, one of these values is
+ * used.
+ *
+ * @EB_EMPTY: the eraseblock appeared to be empty
+ * @EB_CORRUPTED: the eraseblock contains corrupted erase counter header
+ * @EB_ALIEN: the eraseblock contains some non-UBI data
+ * @EC_MAX: maximum allowed erase counter value
+ */
+enum
+{
+	EB_EMPTY     = 0xFFFFFFFF,
+	EB_CORRUPTED = 0xFFFFFFFE,
+	EB_ALIEN     = 0xFFFFFFFD,
+	EB_BAD       = 0xFFFFFFFC,
+	EC_MAX       = UBI_MAX_ERASECOUNTER,
+};
+
+/**
+ * struct ubi_scan_info - UBI scanning information.
+ * @ec: erase counters or eraseblock status for all eraseblocks
+ * @mean_ec: mean erase counter
+ * @ok_cnt: count of eraseblock with correct erase counter header
+ * @empty_cnt: count of supposedly eraseblocks
+ * @corrupted_cnt: count of eraseblocks with corrupted erase counter header
+ * @alien_cnt: count of eraseblock containing non-ubi data
+ * @bad_cnt: count of bad eraseblocks
+ * @bad_cnt: count of non-bad eraseblocks
+ * @vid_hdr_offs: volume ID header offset from the found EC headers (%-1 means
+ *                undefined)
+ * @data_offs: data offset from the found EC headers (%-1 means undefined)
+ */
+struct ubi_scan_info
+{
+	uint32_t *ec;
+	long long mean_ec;
+	int ok_cnt;
+	int empty_cnt;
+	int corrupted_cnt;
+	int alien_cnt;
+	int bad_cnt;
+	int good_cnt;
+	int vid_hdr_offs;
+	int data_offs;
+};
+
+struct mtd_dev_info;
+
+/**
+ * ubi_scan - scan an MTD device.
+ * @mtd: information about the MTD device to scan
+ * @fd: MTD device node file descriptor
+ * @info: the result of the scanning is returned here
+ * @verbose: verbose mode: %0 - be silent, %1 - output progress information,
+ *           2 - debugging output mode
+ */
+int libscan_ubi_scan(struct mtd_dev_info *mtd, int fd, struct ubi_scan_info **info,
+	     int verbose);
+
+/**
+ * ubi_scan_free - free scanning information.
+ * @si: scanning information to free
+ */
+void libscan_ubi_scan_free(struct ubi_scan_info *si);
+
+#endif /* __LIBSCAN_H__ */
diff --git a/lib/Kconfig b/lib/Kconfig
index 13ecab0..8aa6f7d 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -41,6 +41,9 @@ config QSORT
 config XYMODEM
 	bool
 
+config LIBSCAN
+	bool
+
 source lib/gui/Kconfig
 
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index eb0af92..20d96dd 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -34,5 +34,6 @@ obj-$(CONFIG_UNCOMPRESS)	+= uncompress.o
 obj-$(CONFIG_BCH)	+= bch.o
 obj-$(CONFIG_BITREV)	+= bitrev.o
 obj-$(CONFIG_QSORT)	+= qsort.o
+obj-$(CONFIG_LIBSCAN)	+= libscan.o
 obj-y			+= gui/
 obj-$(CONFIG_XYMODEM)	+= xymodem.o
diff --git a/lib/libscan.c b/lib/libscan.c
new file mode 100644
index 0000000..af55269
--- /dev/null
+++ b/lib/libscan.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * UBI scanning library.
+ */
+
+#define PROGRAM_NAME "libscan"
+
+#include <common.h>
+#include <fcntl.h>
+#include <crc.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <linux/mtd/mtd.h>
+#include <linux/stat.h>
+#include <linux/mtd/mtd-abi.h>
+#include <mtd/libmtd.h>
+#include <mtd/libscan.h>
+#include <mtd/ubi-user.h>
+#include <mtd/utils.h>
+#include <mtd/ubi-media.h>
+#include <asm-generic/div64.h>
+
+static int all_ff(const void *buf, int len)
+{
+	int i;
+	const uint8_t *p = buf;
+
+	for (i = 0; i < len; i++)
+		if (p[i] != 0xFF)
+			return 0;
+	return 1;
+}
+
+int libscan_ubi_scan(struct mtd_dev_info *mtd, int fd, struct ubi_scan_info **info,
+	     int verbose)
+{
+	int eb, v = (verbose == 2), pr = (verbose == 1);
+	struct ubi_scan_info *si;
+	unsigned long long sum = 0;
+
+	si = calloc(1, sizeof(struct ubi_scan_info));
+	if (!si)
+		return sys_errmsg("cannot allocate %zd bytes of memory",
+				  sizeof(struct ubi_scan_info));
+
+	si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t));
+	if (!si->ec) {
+		sys_errmsg("cannot allocate %zd bytes of memory",
+			   sizeof(struct ubi_scan_info));
+		goto out_si;
+	}
+
+	si->vid_hdr_offs = si->data_offs = -1;
+
+	verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt);
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		int ret;
+		uint32_t crc;
+		struct ubi_ec_hdr ech;
+		unsigned long long ec;
+
+		if (v)
+			normsg_cont("scanning eraseblock %d", eb);
+		if (pr) {
+			printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2u %% complete  ",
+			       eb, (eb + 1) * 100 / mtd->eb_cnt);
+		}
+
+		ret = mtd_is_bad(mtd, fd, eb);
+		if (ret == -1)
+			goto out_ec;
+		if (ret) {
+			si->bad_cnt += 1;
+			si->ec[eb] = EB_BAD;
+			if (v)
+				printf(": bad\n");
+			continue;
+		}
+
+		ret = mtd_read(mtd, fd, eb, 0, &ech, sizeof(struct ubi_ec_hdr));
+		if (ret < 0)
+			goto out_ec;
+
+		if (be32_to_cpu(ech.magic) != UBI_EC_HDR_MAGIC) {
+			if (all_ff(&ech, sizeof(struct ubi_ec_hdr))) {
+				si->empty_cnt += 1;
+				si->ec[eb] = EB_EMPTY;
+				if (v)
+					printf(": empty\n");
+			} else {
+				si->alien_cnt += 1;
+				si->ec[eb] = EB_ALIEN;
+				if (v)
+					printf(": alien\n");
+			}
+			continue;
+		}
+
+		crc = crc32_no_comp(UBI_CRC32_INIT, &ech, UBI_EC_HDR_SIZE_CRC);
+		if (be32_to_cpu(ech.hdr_crc) != crc) {
+			si->corrupted_cnt += 1;
+			si->ec[eb] = EB_CORRUPTED;
+			if (v)
+				printf(": bad CRC %#08x, should be %#08x\n",
+				       crc, be32_to_cpu(ech.hdr_crc));
+			continue;
+		}
+
+		ec = be64_to_cpu(ech.ec);
+		if (ec > EC_MAX) {
+			if (pr)
+				printf("\n");
+			errmsg("erase counter in EB %d is %llu, while this "
+			       "program expects them to be less than %u",
+			       eb, ec, EC_MAX);
+			goto out_ec;
+		}
+
+		if (si->vid_hdr_offs == -1) {
+			si->vid_hdr_offs = be32_to_cpu(ech.vid_hdr_offset);
+			si->data_offs = be32_to_cpu(ech.data_offset);
+			if (si->data_offs % mtd->min_io_size) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("bad data offset %d at eraseblock %d (n"
+					"of multiple of min. I/O unit size %d)",
+					si->data_offs, eb, mtd->min_io_size);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+
+			}
+		} else {
+			if ((int)be32_to_cpu(ech.vid_hdr_offset) != si->vid_hdr_offs) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("inconsistent VID header offset: was "
+					"%d, but is %d in eraseblock %d",
+					si->vid_hdr_offs,
+					be32_to_cpu(ech.vid_hdr_offset), eb);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+			}
+			if ((int)be32_to_cpu(ech.data_offset) != si->data_offs) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("inconsistent data offset: was %d, but"
+					" is %d in eraseblock %d",
+					si->data_offs,
+					be32_to_cpu(ech.data_offset), eb);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+			}
+		}
+
+		si->ok_cnt += 1;
+		si->ec[eb] = ec;
+		if (v)
+			printf(": OK, erase counter %u\n", si->ec[eb]);
+	}
+
+	if (si->ok_cnt != 0) {
+		/* Calculate mean erase counter */
+		for (eb = 0; eb < mtd->eb_cnt; eb++) {
+			if (si->ec[eb] > EC_MAX)
+				continue;
+			sum += si->ec[eb];
+		}
+		do_div(sum, si->ok_cnt);
+		si->mean_ec = sum;
+	}
+
+	si->good_cnt = mtd->eb_cnt - si->bad_cnt;
+	verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d "
+		"alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt,
+		si->empty_cnt, si->alien_cnt, si->bad_cnt);
+
+	*info = si;
+	if (pr)
+		printf("\n");
+	return 0;
+
+out_ec:
+	free(si->ec);
+out_si:
+	free(si);
+	*info = NULL;
+	return -1;
+}
+
+void libscan_ubi_scan_free(struct ubi_scan_info *si)
+{
+	free(si->ec);
+	free(si);
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 09/11] lib: add libubigen
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (7 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 08/11] lib: add libscan Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 10/11] lib: add barebox version of libmtd Wolfram Sang
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Imported from mtd-utils and stripped down to needed functionality.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 include/mtd/libubigen.h |  182 +++++++++++++++++++++++++++
 lib/Kconfig             |    3 +
 lib/Makefile            |    1 +
 lib/libubigen.c         |  312 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 498 insertions(+)
 create mode 100644 include/mtd/libubigen.h
 create mode 100644 lib/libubigen.c

diff --git a/include/mtd/libubigen.h b/include/mtd/libubigen.h
new file mode 100644
index 0000000..f05978b
--- /dev/null
+++ b/include/mtd/libubigen.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ */
+
+/*
+ * Authors: Frank Haverkamp
+ *          Artem Bityutskiy
+ */
+
+#ifndef __LIBUBIGEN_H__
+#define __LIBUBIGEN_H__
+
+#include <mtd/ubi-media.h>
+
+/**
+ * struct ubigen_info - libubigen information.
+ * @leb_size: logical eraseblock size
+ * @peb_size: size of the physical eraseblock
+ * @min_io_size: minimum input/output unit size
+ * @vid_hdr_offs: offset of the VID header
+ * @data_offs: data offset
+ * @ubi_ver: UBI version
+ * @vtbl_size: volume table size
+ * @max_volumes: maximum amount of volumes
+ * @image_seq: UBI image sequence number
+ */
+struct ubigen_info
+{
+	int leb_size;
+	int peb_size;
+	int min_io_size;
+	int vid_hdr_offs;
+	int data_offs;
+	int ubi_ver;
+	int vtbl_size;
+	int max_volumes;
+	uint32_t image_seq;
+};
+
+/**
+ * struct ubigen_vol_info - information about a volume.
+ * @id: volume id
+ * @type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC)
+ * @alignment: volume alignment
+ * @data_pad: how many bytes are unused at the end of the each physical
+ *            eraseblock to satisfy the requested alignment
+ * @usable_leb_size: LEB size accessible for volume users
+ * @name: volume name
+ * @name_len: volume name length
+ * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE,
+ *          %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT)
+ * @used_ebs: total number of used logical eraseblocks in this volume (relevant
+ *            for static volumes only)
+ * @bytes: size of the volume contents in bytes (relevant for static volumes
+ *         only)
+ * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG)
+ */
+struct ubigen_vol_info
+{
+	int id;
+	int type;
+	int alignment;
+	int data_pad;
+	int usable_leb_size;
+	const char *name;
+	int name_len;
+	int compat;
+	int used_ebs;
+	long long bytes;
+	uint8_t flags;
+};
+
+/**
+ * ubigen_info_init - initialize libubigen.
+ * @ui: libubigen information
+ * @peb_size: flash physical eraseblock size
+ * @min_io_size: flash minimum input/output unit size
+ * @subpage_size: flash sub-page, if present (has to be equivalent to
+ *                @min_io_size if does not exist)
+ * @vid_hdr_offs: offset of the VID header
+ * @ubi_ver: UBI version
+ * @image_seq: UBI image sequence number
+ */
+void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
+		      int subpage_size, int vid_hdr_offs, int ubi_ver,
+		      uint32_t image_seq);
+
+/**
+ * ubigen_create_empty_vtbl - creates empty volume table.
+ * @ui: libubigen information
+ *
+ * This function creates an empty volume table and returns a pointer to it in
+ * case of success and %NULL in case of failure. The returned object has to be
+ * freed with 'free()' call.
+ */
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui);
+
+/**
+ * ubigen_init_ec_hdr - initialize EC header.
+ * @ui: libubigen information
+ * @hdr: the EC header to initialize
+ * @ec: erase counter value
+ */
+void ubigen_init_ec_hdr(const struct ubigen_info *ui,
+		        struct ubi_ec_hdr *hdr, long long ec);
+
+/**
+ * ubigen_init_vid_hdr - initialize VID header.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @hdr: the VID header to initialize
+ * @lnum: logical eraseblock number
+ * @data: the contents of the LEB (static volumes only)
+ * @data_size: amount of data in this LEB (static volumes only)
+ *
+ * Note, @used_ebs, @data and @data_size are ignored in case of dynamic
+ * volumes.
+ */
+void ubigen_init_vid_hdr(const struct ubigen_info *ui,
+			 const struct ubigen_vol_info *vi,
+			 struct ubi_vid_hdr *hdr, int lnum,
+			 const void *data, int data_size);
+
+/**
+ * ubigen_add_volume - add a volume to the volume table.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @vtbl: volume table to add to
+ *
+ * This function adds volume described by input parameters to the volume table
+ * @vtbl.
+ */
+int ubigen_add_volume(const struct ubigen_info *ui,
+		      const struct ubigen_vol_info *vi,
+		      struct ubi_vtbl_record *vtbl);
+
+/**
+ * ubigen_write_volume - write UBI volume.
+ * @ui: libubigen information
+ * @vi: volume information
+ * @ec: erase counter value to put to EC headers
+ * @bytes: volume size in bytes
+ * @in: input file descriptor (has to be properly seeked)
+ * @out: output file descriptor
+ *
+ * This function reads the contents of the volume from the input file @in and
+ * writes the UBI volume to the output file @out. Returns zero on success and
+ * %-1 on failure.
+ */
+int ubigen_write_volume(const struct ubigen_info *ui,
+			const struct ubigen_vol_info *vi, long long ec,
+			long long bytes, int in, int out);
+
+/**
+ * ubigen_write_layout_vol - write UBI layout volume
+ * @ui: libubigen information
+ * @peb1: physical eraseblock number to write the first volume table copy
+ * @peb2: physical eraseblock number to write the second volume table copy
+ * @ec1: erase counter value for @peb1
+ * @ec2: erase counter value for @peb1
+ * @vtbl: volume table
+ * @fd: output file descriptor seeked to the proper position
+ *
+ * This function creates the UBI layout volume which contains 2 copies of the
+ * volume table. Returns zero in case of success and %-1 in case of failure.
+ */
+int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
+			    long long ec1, long long ec2,
+			    struct ubi_vtbl_record *vtbl, int fd);
+
+#endif /* !__LIBUBIGEN_H__ */
diff --git a/lib/Kconfig b/lib/Kconfig
index 8aa6f7d..5dbf069 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -44,6 +44,9 @@ config XYMODEM
 config LIBSCAN
 	bool
 
+config LIBUBIGEN
+	bool
+
 source lib/gui/Kconfig
 
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 20d96dd..2125af2 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,5 +35,6 @@ obj-$(CONFIG_BCH)	+= bch.o
 obj-$(CONFIG_BITREV)	+= bitrev.o
 obj-$(CONFIG_QSORT)	+= qsort.o
 obj-$(CONFIG_LIBSCAN)	+= libscan.o
+obj-$(CONFIG_LIBUBIGEN)	+= libubigen.o
 obj-y			+= gui/
 obj-$(CONFIG_XYMODEM)	+= xymodem.o
diff --git a/lib/libubigen.c b/lib/libubigen.c
new file mode 100644
index 0000000..4026f1d
--- /dev/null
+++ b/lib/libubigen.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ */
+
+/*
+ * Generating UBI images.
+ *
+ * Authors: Oliver Lohmann
+ *          Artem Bityutskiy
+ */
+
+#define PROGRAM_NAME "libubigen"
+
+#include <common.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <crc.h>
+#include <fs.h>
+
+#include <mtd/utils.h>
+#include <mtd/ubi-media.h>
+#include <mtd/libubigen.h>
+
+void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
+		      int subpage_size, int vid_hdr_offs, int ubi_ver,
+		      uint32_t image_seq)
+{
+	if (!vid_hdr_offs) {
+		vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1;
+		vid_hdr_offs /= subpage_size;
+		vid_hdr_offs *= subpage_size;
+	}
+
+	ui->peb_size = peb_size;
+	ui->min_io_size = min_io_size;
+	ui->vid_hdr_offs = vid_hdr_offs;
+	ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
+	ui->data_offs /= min_io_size;
+	ui->data_offs *= min_io_size;
+	ui->leb_size = peb_size - ui->data_offs;
+	ui->ubi_ver = ubi_ver;
+	ui->image_seq = image_seq;
+
+	ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE;
+	if (ui->max_volumes > UBI_MAX_VOLUMES)
+		ui->max_volumes = UBI_MAX_VOLUMES;
+	ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE;
+}
+
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
+{
+	struct ubi_vtbl_record *vtbl;
+	int i;
+
+	vtbl = calloc(1, ui->vtbl_size);
+	if (!vtbl) {
+		sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
+		return NULL;
+	}
+
+	for (i = 0; i < ui->max_volumes; i++) {
+		uint32_t crc = crc32_no_comp(UBI_CRC32_INIT, &vtbl[i],
+				     UBI_VTBL_RECORD_SIZE_CRC);
+		vtbl[i].crc = cpu_to_be32(crc);
+	}
+
+	return vtbl;
+}
+
+int ubigen_add_volume(const struct ubigen_info *ui,
+		      const struct ubigen_vol_info *vi,
+		      struct ubi_vtbl_record *vtbl)
+{
+	struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
+	uint32_t tmp;
+
+	if (vi->id >= ui->max_volumes) {
+		errmsg("too high volume id %d, max. volumes is %d",
+		       vi->id, ui->max_volumes);
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (vi->alignment >= ui->leb_size) {
+		errmsg("too large alignment %d, max is %d (LEB size)",
+		       vi->alignment, ui->leb_size);
+		errno = EINVAL;
+		return -1;
+	}
+
+	memset(vtbl_rec, 0, sizeof(struct ubi_vtbl_record));
+	tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
+	vtbl_rec->reserved_pebs = cpu_to_be32(tmp);
+	vtbl_rec->alignment = cpu_to_be32(vi->alignment);
+	vtbl_rec->vol_type = vi->type;
+	tmp = ui->leb_size % vi->alignment;
+	vtbl_rec->data_pad = cpu_to_be32(tmp);
+	vtbl_rec->flags = vi->flags;
+
+	memcpy(vtbl_rec->name, vi->name, vi->name_len);
+	vtbl_rec->name[vi->name_len] = '\0';
+	vtbl_rec->name_len = cpu_to_be16(vi->name_len);
+
+	tmp = crc32_no_comp(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
+	vtbl_rec->crc =	 cpu_to_be32(tmp);
+	return 0;
+}
+
+void ubigen_init_ec_hdr(const struct ubigen_info *ui,
+		        struct ubi_ec_hdr *hdr, long long ec)
+{
+	uint32_t crc;
+
+	memset(hdr, 0, sizeof(struct ubi_ec_hdr));
+
+	hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
+	hdr->version = ui->ubi_ver;
+	hdr->ec = cpu_to_be64(ec);
+	hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
+	hdr->data_offset = cpu_to_be32(ui->data_offs);
+	hdr->image_seq = cpu_to_be32(ui->image_seq);
+
+	crc = crc32_no_comp(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
+}
+
+void ubigen_init_vid_hdr(const struct ubigen_info *ui,
+			 const struct ubigen_vol_info *vi,
+			 struct ubi_vid_hdr *hdr, int lnum,
+			 const void *data, int data_size)
+{
+	uint32_t crc;
+
+	memset(hdr, 0, sizeof(struct ubi_vid_hdr));
+
+	hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
+	hdr->version = ui->ubi_ver;
+	hdr->vol_type = vi->type;
+	hdr->vol_id = cpu_to_be32(vi->id);
+	hdr->lnum = cpu_to_be32(lnum);
+	hdr->data_pad = cpu_to_be32(vi->data_pad);
+	hdr->compat = vi->compat;
+
+	if (vi->type == UBI_VID_STATIC) {
+		hdr->data_size = cpu_to_be32(data_size);
+		hdr->used_ebs = cpu_to_be32(vi->used_ebs);
+		crc = crc32_no_comp(UBI_CRC32_INIT, data, data_size);
+		hdr->data_crc = cpu_to_be32(crc);
+	}
+
+	crc = crc32_no_comp(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
+}
+
+int ubigen_write_volume(const struct ubigen_info *ui,
+			const struct ubigen_vol_info *vi, long long ec,
+			long long bytes, int in, int out)
+{
+	int len = vi->usable_leb_size, rd, lnum = 0;
+	char *inbuf, *outbuf;
+
+	if (vi->id >= ui->max_volumes) {
+		errmsg("too high volume id %d, max. volumes is %d",
+		       vi->id, ui->max_volumes);
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (vi->alignment >= ui->leb_size) {
+		errmsg("too large alignment %d, max is %d (LEB size)",
+		       vi->alignment, ui->leb_size);
+		errno = EINVAL;
+		return -1;
+	}
+
+	inbuf = malloc(ui->leb_size);
+	if (!inbuf)
+		return sys_errmsg("cannot allocate %d bytes of memory",
+				  ui->leb_size);
+	outbuf = malloc(ui->peb_size);
+	if (!outbuf) {
+		sys_errmsg("cannot allocate %d bytes of memory", ui->peb_size);
+		goto out_free;
+	}
+
+	memset(outbuf, 0xFF, ui->data_offs);
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec);
+
+	while (bytes) {
+		int l;
+		struct ubi_vid_hdr *vid_hdr;
+
+		if (bytes < len)
+			len = bytes;
+		bytes -= len;
+
+		l = len;
+		do {
+			rd = read(in, inbuf + len - l, l);
+			if (rd != l) {
+				sys_errmsg("cannot read %d bytes from the input file", l);
+				goto out_free1;
+			}
+
+			l -= rd;
+		} while (l);
+
+		vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+		ubigen_init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
+
+		memcpy(outbuf + ui->data_offs, inbuf, len);
+		memset(outbuf + ui->data_offs + len, 0xFF,
+		       ui->peb_size - ui->data_offs - len);
+
+		if (write(out, outbuf, ui->peb_size) != ui->peb_size) {
+			sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
+			goto out_free1;
+		}
+
+		lnum += 1;
+	}
+
+	free(outbuf);
+	free(inbuf);
+	return 0;
+
+out_free1:
+	free(outbuf);
+out_free:
+	free(inbuf);
+	return -1;
+}
+
+int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
+			    long long ec1, long long ec2,
+			    struct ubi_vtbl_record *vtbl, int fd)
+{
+	int ret;
+	struct ubigen_vol_info vi;
+	char *outbuf;
+	struct ubi_vid_hdr *vid_hdr;
+	off_t seek;
+
+	vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
+	vi.id = UBI_LAYOUT_VOLUME_ID;
+	vi.alignment = UBI_LAYOUT_VOLUME_ALIGN;
+	vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
+	vi.usable_leb_size = ui->leb_size - vi.data_pad;
+	vi.data_pad = ui->leb_size - vi.usable_leb_size;
+	vi.type = UBI_LAYOUT_VOLUME_TYPE;
+	vi.name = UBI_LAYOUT_VOLUME_NAME;
+	vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
+	vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
+
+	outbuf = malloc(ui->peb_size);
+	if (!outbuf)
+		return sys_errmsg("failed to allocate %d bytes",
+				  ui->peb_size);
+
+	memset(outbuf, 0xFF, ui->data_offs);
+	vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+	memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size);
+	memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF,
+	       ui->peb_size - ui->data_offs - ui->vtbl_size);
+
+	seek = (off_t) peb1 * ui->peb_size;
+	if (lseek(fd, seek, SEEK_SET) != seek) {
+		sys_errmsg("cannot seek output file");
+		goto out_free;
+	}
+
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
+	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
+	ret = write(fd, outbuf, ui->peb_size);
+	if (ret != ui->peb_size) {
+		sys_errmsg("cannot write %d bytes", ui->peb_size);
+		goto out_free;
+	}
+
+	seek = (off_t) peb2 * ui->peb_size;
+	if (lseek(fd, seek, SEEK_SET) != seek) {
+		sys_errmsg("cannot seek output file");
+		goto out_free;
+	}
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
+	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
+	ret = write(fd, outbuf, ui->peb_size);
+	if (ret != ui->peb_size) {
+		sys_errmsg("cannot write %d bytes", ui->peb_size);
+		goto out_free;
+	}
+
+	free(outbuf);
+	return 0;
+
+out_free:
+	free(outbuf);
+	return -1;
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 10/11] lib: add barebox version of libmtd
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (8 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 09/11] lib: add libubigen Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-17 15:48 ` [PATCH V3 11/11] commands: add ubiformat Wolfram Sang
  2012-12-19 11:50 ` [PATCH V3 00/11] ubiformat for barebox Sascha Hauer
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Based on mtd-utils and stripped down to needed functionality and
reworked to barebox interfaces.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 include/mtd/libmtd.h |  149 ++++++++++++++++++++
 lib/Kconfig          |    3 +
 lib/Makefile         |    1 +
 lib/libmtd.c         |  368 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 521 insertions(+)
 create mode 100644 include/mtd/libmtd.h
 create mode 100644 lib/libmtd.c

diff --git a/include/mtd/libmtd.h b/include/mtd/libmtd.h
new file mode 100644
index 0000000..e88a9a2
--- /dev/null
+++ b/include/mtd/libmtd.h
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2008, 2009 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ * Author: Artem Bityutskiy
+ *
+ * MTD library.
+ */
+
+#ifndef __LIBMTD_H__
+#define __LIBMTD_H__
+
+/* Maximum MTD device name length */
+#define MTD_NAME_MAX 127
+/* Maximum MTD device type string length */
+#define MTD_TYPE_MAX 64
+
+/**
+ * struct mtd_dev_info - information about an MTD device.
+ * @node: node pointing to device
+ * @type: flash type (constants like %MTD_NANDFLASH defined in mtd-abi.h)
+ * @type_str: static R/O flash type string
+ * @name: device name
+ * @size: device size in bytes
+ * @eb_cnt: count of eraseblocks
+ * @eb_size: eraseblock size
+ * @min_io_size: minimum input/output unit size
+ * @subpage_size: sub-page size
+ * @oob_size: OOB size (zero if the device does not have OOB area)
+ * @region_cnt: count of additional erase regions
+ * @writable: zero if the device is read-only
+ * @bb_allowed: non-zero if the MTD device may have bad eraseblocks
+ */
+struct mtd_dev_info
+{
+	const char *node;
+	int type;
+	const char type_str[MTD_TYPE_MAX + 1];
+	long long size;
+	int eb_cnt;
+	int eb_size;
+	int min_io_size;
+	int subpage_size;
+	int oob_size;
+	int region_cnt;
+	unsigned int writable:1;
+	unsigned int bb_allowed:1;
+};
+
+/**
+ * mtd_get_dev_info - get information about an MTD device.
+ * @desc: MTD library descriptor
+ * @node: name of the MTD device node
+ * @mtd: the MTD device information is returned here
+ *
+ * This function gets information about MTD device defined by the @node device
+ * node file and saves this information in the @mtd object. Returns %0 in case
+ * of success and %-1 in case of failure. If MTD subsystem is not present in the
+ * system, or the MTD device does not exist, errno is set to @ENODEV.
+ */
+int mtd_get_dev_info(const char *node, struct mtd_dev_info *mtd);
+
+/**
+ * mtd_erase - erase an eraseblock.
+ * @desc: MTD library descriptor
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to erase
+ *
+ * This function erases eraseblock @eb of MTD device described by @fd. Returns
+ * %0 in case of success and %-1 in case of failure.
+ */
+int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb);
+
+/**
+ * mtd_torture - torture an eraseblock.
+ * @desc: MTD library descriptor
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to torture
+ *
+ * This function tortures eraseblock @eb. Returns %0 in case of success and %-1
+ * in case of failure.
+ */
+int mtd_torture(const struct mtd_dev_info *mtd, int fd, int eb);
+
+/**
+ * mtd_is_bad - check if eraseblock is bad.
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to check
+ *
+ * This function checks if eraseblock @eb is bad. Returns %0 if not, %1 if yes,
+ * and %-1 in case of failure.
+ */
+int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb);
+
+/**
+ * mtd_mark_bad - mark an eraseblock as bad.
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to mark as bad
+ *
+ * This function marks eraseblock @eb as bad. Returns %0 in case of success and
+ * %-1 in case of failure.
+ */
+int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb);
+
+/**
+ * mtd_read - read data from an MTD device.
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to read from
+ * @offs: offset withing the eraseblock to read from
+ * @buf: buffer to read data to
+ * @len: how many bytes to read
+ *
+ * This function reads @len bytes of data from eraseblock @eb and offset @offs
+ * of the MTD device defined by @mtd and stores the read data at buffer @buf.
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
+	     void *buf, int len);
+
+/**
+ * mtd_write - write data to an MTD device.
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to write to
+ * @offs: offset withing the eraseblock to write to
+ * @buf: buffer to write
+ * @len: how many bytes to write
+ *
+ * This function writes @len bytes of data to eraseblock @eb and offset @offs
+ * of the MTD device defined by @mtd. Returns %0 in case of success and %-1 in
+ * case of failure.
+ */
+int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
+	      void *buf, int len);
+
+#endif /* __LIBMTD_H__ */
diff --git a/lib/Kconfig b/lib/Kconfig
index 5dbf069..b97c828 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -47,6 +47,9 @@ config LIBSCAN
 config LIBUBIGEN
 	bool
 
+config LIBMTD
+	bool
+
 source lib/gui/Kconfig
 
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 2125af2..82e578f 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -36,5 +36,6 @@ obj-$(CONFIG_BITREV)	+= bitrev.o
 obj-$(CONFIG_QSORT)	+= qsort.o
 obj-$(CONFIG_LIBSCAN)	+= libscan.o
 obj-$(CONFIG_LIBUBIGEN)	+= libubigen.o
+obj-$(CONFIG_LIBMTD)	+= libmtd.o
 obj-y			+= gui/
 obj-$(CONFIG_XYMODEM)	+= xymodem.o
diff --git a/lib/libmtd.c b/lib/libmtd.c
new file mode 100644
index 0000000..8c4152e
--- /dev/null
+++ b/lib/libmtd.c
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation
+ * Copyright (C) 2012 Wolfram Sang, Pengutronix e.K. <w.sang@pengutronix.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * Author: Artem Bityutskiy
+ * Author: Wolfram Sang
+ *
+ * This file is part of the MTD library. Based on pre-2.6.30 kernels support,
+ * now adapted to barebox.
+ *
+ * NOTE: No support for 64 bit sizes yet!
+ */
+
+#include <common.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+#include <errno.h>
+#include <crc.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <ioctl.h>
+#include <linux/stat.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/mtd-abi.h>
+#include <mtd/libmtd.h>
+#include <mtd/utils.h>
+
+#define PROGRAM_NAME "libmtd"
+
+static inline int mtd_ioctl_error(const struct mtd_dev_info *mtd, int eb,
+				  const char *sreq)
+{
+	return sys_errmsg("%s ioctl failed for eraseblock %d (%s)",
+			  sreq, eb, mtd->node);
+}
+
+static int mtd_valid_erase_block(const struct mtd_dev_info *mtd, int eb)
+{
+	if (eb < 0 || eb >= mtd->eb_cnt) {
+		errmsg("bad eraseblock number %d, %s has %d eraseblocks",
+		       eb, mtd->node, mtd->eb_cnt);
+		errno = EINVAL;
+		return -1;
+	}
+	return 0;
+}
+
+int mtd_erase(const struct mtd_dev_info *mtd, int fd, int eb)
+{
+	int ret;
+	struct erase_info_user ei;
+
+	ret = mtd_valid_erase_block(mtd, eb);
+	if (ret)
+		return ret;
+
+	ei.start = (__u64)eb * mtd->eb_size;
+	ei.length = mtd->eb_size;
+
+	ret = ioctl(fd, MEMERASE, &ei);
+	if (ret < 0)
+		return mtd_ioctl_error(mtd, eb, "MEMERASE");
+	return 0;
+}
+
+/* Patterns to write to a physical eraseblock when torturing it */
+static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
+
+/**
+ * check_pattern - check if buffer contains only a certain byte pattern.
+ * @buf: buffer to check
+ * @patt: the pattern to check
+ * @size: buffer size in bytes
+ *
+ * This function returns %1 in there are only @patt bytes in @buf, and %0 if
+ * something else was also found.
+ */
+static int check_pattern(const void *buf, uint8_t patt, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i++)
+		if (((const uint8_t *)buf)[i] != patt)
+			return 0;
+	return 1;
+}
+
+int mtd_torture(const struct mtd_dev_info *mtd, int fd, int eb)
+{
+	int err, i, patt_count;
+	void *buf;
+
+	normsg("run torture test for PEB %d", eb);
+	patt_count = ARRAY_SIZE(patterns);
+
+	buf = xmalloc(mtd->eb_size);
+
+	for (i = 0; i < patt_count; i++) {
+		err = mtd_erase(mtd, fd, eb);
+		if (err)
+			goto out;
+
+		/* Make sure the PEB contains only 0xFF bytes */
+		err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
+		if (err)
+			goto out;
+
+		err = check_pattern(buf, 0xFF, mtd->eb_size);
+		if (err == 0) {
+			errmsg("erased PEB %d, but a non-0xFF byte found", eb);
+			errno = EIO;
+			goto out;
+		}
+
+		/* Write a pattern and check it */
+		memset(buf, patterns[i], mtd->eb_size);
+		err = mtd_write(mtd, fd, eb, 0, buf, mtd->eb_size);
+		if (err)
+			goto out;
+
+		memset(buf, ~patterns[i], mtd->eb_size);
+		err = mtd_read(mtd, fd, eb, 0, buf, mtd->eb_size);
+		if (err)
+			goto out;
+
+		err = check_pattern(buf, patterns[i], mtd->eb_size);
+		if (err == 0) {
+			errmsg("pattern %x checking failed for PEB %d",
+				patterns[i], eb);
+			errno = EIO;
+			goto out;
+		}
+	}
+
+	err = 0;
+	normsg("PEB %d passed torture test, do not mark it a bad", eb);
+
+out:
+	free(buf);
+	return -1;
+}
+
+int mtd_is_bad(const struct mtd_dev_info *mtd, int fd, int eb)
+{
+	int ret;
+	loff_t seek;
+
+	ret = mtd_valid_erase_block(mtd, eb);
+	if (ret)
+		return ret;
+
+	if (!mtd->bb_allowed)
+		return 0;
+
+	seek = (loff_t)eb * mtd->eb_size;
+	ret = ioctl(fd, MEMGETBADBLOCK, &seek);
+	if (ret == -1)
+		return mtd_ioctl_error(mtd, eb, "MEMGETBADBLOCK");
+	return ret;
+}
+
+int mtd_mark_bad(const struct mtd_dev_info *mtd, int fd, int eb)
+{
+	int ret;
+	loff_t seek;
+
+	if (!mtd->bb_allowed) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	ret = mtd_valid_erase_block(mtd, eb);
+	if (ret)
+		return ret;
+
+	seek = (loff_t)eb * mtd->eb_size;
+	ret = ioctl(fd, MEMSETBADBLOCK, &seek);
+	if (ret == -1)
+		return mtd_ioctl_error(mtd, eb, "MEMSETBADBLOCK");
+	return 0;
+}
+
+int mtd_read(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
+	     void *buf, int len)
+{
+	int ret, rd = 0;
+	off_t seek;
+
+	ret = mtd_valid_erase_block(mtd, eb);
+	if (ret)
+		return ret;
+
+	if (offs < 0 || offs + len > mtd->eb_size) {
+		errmsg("bad offset %d or length %d, %s eraseblock size is %d",
+		       offs, len, mtd->node, mtd->eb_size);
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Seek to the beginning of the eraseblock */
+	seek = (off_t)eb * mtd->eb_size + offs;
+	if (lseek(fd, seek, SEEK_SET) != seek)
+		return sys_errmsg("cannot seek %s to offset %llu",
+				  mtd->node, (unsigned long long)seek);
+
+	while (rd < len) {
+		ret = read(fd, buf, len);
+		if (ret < 0)
+			return sys_errmsg("cannot read %d bytes from %s (eraseblock %d, offset %d)",
+					  len, mtd->node, eb, offs);
+		rd += ret;
+	}
+
+	return 0;
+}
+
+int mtd_write(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
+	      void *buf, int len)
+{
+	int ret;
+	off_t seek;
+
+	ret = mtd_valid_erase_block(mtd, eb);
+	if (ret)
+		return ret;
+
+	if (offs < 0 || offs + len > mtd->eb_size) {
+		errmsg("bad offset %d or length %d, %s eraseblock size is %d",
+		       offs, len, mtd->node, mtd->eb_size);
+		errno = EINVAL;
+		return -1;
+	}
+	if (offs % mtd->subpage_size) {
+		errmsg("write offset %d is not aligned to %s min. I/O size %d",
+		       offs, mtd->node, mtd->subpage_size);
+		errno = EINVAL;
+		return -1;
+	}
+	if (len % mtd->subpage_size) {
+		errmsg("write length %d is not aligned to %s min. I/O size %d",
+		       len, mtd->node, mtd->subpage_size);
+		errno = EINVAL;
+		return -1;
+	}
+
+	/* Seek to the beginning of the eraseblock */
+	seek = (off_t)eb * mtd->eb_size + offs;
+	if (lseek(fd, seek, SEEK_SET) != seek)
+		return sys_errmsg("cannot seek %s to offset %llu",
+				  mtd->node, (unsigned long long)seek);
+
+	ret = write(fd, buf, len);
+	if (ret != len)
+		return sys_errmsg("cannot write %d bytes to %s (eraseblock %d, offset %d)",
+				  len, mtd->node, eb, offs);
+
+	return 0;
+}
+
+/**
+ * mtd_get_dev_info - fill the mtd_dev_info structure
+ * @node: name of the MTD device node
+ * @mtd: the MTD device information is returned here
+ */
+int mtd_get_dev_info(const char *node, struct mtd_dev_info *mtd)
+{
+	struct mtd_info_user ui;
+	int fd, ret;
+	loff_t offs = 0;
+
+	memset(mtd, '\0', sizeof(struct mtd_dev_info));
+
+	mtd->node = node;
+
+	fd = open(node, O_RDWR);
+	if (fd < 0)
+		return sys_errmsg("cannot open \"%s\"", node);
+
+	if (ioctl(fd, MEMGETINFO, &ui)) {
+		sys_errmsg("MEMGETINFO ioctl request failed");
+		goto out_close;
+	}
+
+	ret = ioctl(fd, MEMGETBADBLOCK, &offs);
+	if (ret == -1) {
+		if (errno != EOPNOTSUPP) {
+			sys_errmsg("MEMGETBADBLOCK ioctl failed");
+			goto out_close;
+		}
+		errno = 0;
+		mtd->bb_allowed = 0;
+	} else
+		mtd->bb_allowed = 1;
+
+	mtd->type = ui.type;
+	mtd->size = ui.size;
+	mtd->eb_size = ui.erasesize;
+	mtd->min_io_size = ui.writesize;
+	mtd->oob_size = ui.oobsize;
+
+	if (mtd->min_io_size <= 0) {
+		errmsg("%s has insane min. I/O unit size %d",
+		       node, mtd->min_io_size);
+		goto out_close;
+	}
+	if (mtd->eb_size <= 0 || mtd->eb_size < mtd->min_io_size) {
+		errmsg("%s has insane eraseblock size %d",
+		       node, mtd->eb_size);
+		goto out_close;
+	}
+	if (mtd->size <= 0 || mtd->size < mtd->eb_size) {
+		errmsg("%s has insane size %lld",
+		       node, mtd->size);
+		goto out_close;
+	}
+
+	mtd->eb_cnt = ui.size / ui.erasesize;
+
+	switch(mtd->type) {
+	case MTD_ABSENT:
+		errmsg("%s (%s) is removable and is not present",
+		       mtd->node, node);
+		goto out_close;
+	case MTD_RAM:
+		strcpy((char *)mtd->type_str, "ram");
+		break;
+	case MTD_ROM:
+		strcpy((char *)mtd->type_str, "rom");
+		break;
+	case MTD_NORFLASH:
+		strcpy((char *)mtd->type_str, "nor");
+		break;
+	case MTD_NANDFLASH:
+		strcpy((char *)mtd->type_str, "nand");
+		break;
+	case MTD_DATAFLASH:
+		strcpy((char *)mtd->type_str, "dataflash");
+		break;
+	case MTD_UBIVOLUME:
+		strcpy((char *)mtd->type_str, "ubi");
+		break;
+	default:
+		goto out_close;
+	}
+
+	if (ui.flags & MTD_WRITEABLE)
+		mtd->writable = 1;
+	mtd->subpage_size = mtd->min_io_size;
+
+	close(fd);
+
+	return 0;
+
+out_close:
+	close(fd);
+	return -1;
+}
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH V3 11/11] commands: add ubiformat
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (9 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 10/11] lib: add barebox version of libmtd Wolfram Sang
@ 2012-12-17 15:48 ` Wolfram Sang
  2012-12-19 11:50 ` [PATCH V3 00/11] ubiformat for barebox Sascha Hauer
  11 siblings, 0 replies; 13+ messages in thread
From: Wolfram Sang @ 2012-12-17 15:48 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Imported from mtd-utils and stripped down to needed functionality.
Based on an older version (1.4.5.) since the newer do use MEMWRITE
interfaces which we don't have in barebox (yet).

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 commands/Kconfig     |    8 +
 commands/Makefile    |    1 +
 commands/ubiformat.c |  784 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 793 insertions(+)
 create mode 100644 commands/ubiformat.c

diff --git a/commands/Kconfig b/commands/Kconfig
index ac9b797..82c3223 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -347,6 +347,14 @@ config CMD_UBI
 	depends on UBI
 	prompt "ubimkvol, ubirmvol, ubiattach"
 
+config CMD_UBIFORMAT
+	tristate
+	depends on UBI
+	select LIBMTD
+	select LIBSCAN
+	select LIBUBIGEN
+	prompt "ubiformat"
+
 endmenu
 
 
diff --git a/commands/Makefile b/commands/Makefile
index effc91b..359f566 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -57,6 +57,7 @@ obj-$(CONFIG_CMD_UNCOMPRESS)	+= uncompress.o
 obj-$(CONFIG_CMD_I2C)		+= i2c.o
 obj-$(CONFIG_CMD_SPI)		+= spi.o
 obj-$(CONFIG_CMD_UBI)		+= ubi.o
+obj-$(CONFIG_CMD_UBIFORMAT)	+= ubiformat.o
 obj-$(CONFIG_CMD_MENU)		+= menu.o
 obj-$(CONFIG_CMD_PASSWD)	+= passwd.o
 obj-$(CONFIG_CMD_LOGIN)		+= login.o
diff --git a/commands/ubiformat.c b/commands/ubiformat.c
new file mode 100644
index 0000000..3bb2c9a
--- /dev/null
+++ b/commands/ubiformat.c
@@ -0,0 +1,784 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2012 Wolfram Sang, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ */
+
+/*
+ * An utility to format MTD devices into UBI and flash UBI images.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+/*
+ * Maximum amount of consequtive eraseblocks which are considered as normal by
+ * this utility. Otherwise it is assume that something is wrong with the flash
+ * or the driver, and eraseblocks are stopped being marked as bad.
+ */
+#define MAX_CONSECUTIVE_BAD_BLOCKS 4
+
+#define PROGRAM_NAME    "ubiformat"
+
+#include <common.h>
+#include <command.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <getopt.h>
+#include <crc.h>
+#include <stdlib.h>
+#include <clock.h>
+#include <malloc.h>
+#include <ioctl.h>
+#include <libbb.h>
+#include <linux/mtd/mtd.h>
+#include <linux/kernel.h>
+#include <linux/stat.h>
+#include <linux/log2.h>
+#include <linux/mtd/mtd-abi.h>
+#include <mtd/libmtd.h>
+#include <mtd/libscan.h>
+#include <mtd/libubigen.h>
+#include <mtd/ubi-user.h>
+#include <mtd/utils.h>
+#include <mtd/ubi-media.h>
+
+/* The variables below are set by command line arguments */
+struct args {
+	unsigned int yes:1;
+	unsigned int quiet:1;
+	unsigned int verbose:1;
+	unsigned int override_ec:1;
+	unsigned int novtbl:1;
+	unsigned int manual_subpage;
+	int subpage_size;
+	int vid_hdr_offs;
+	int ubi_ver;
+	uint32_t image_seq;
+	long long ec;
+	const char *image;
+	const char *node;
+	int node_fd;
+};
+
+static struct args args;
+
+static int parse_opt(int argc, char *argv[])
+{
+	srand(get_time_ns());
+	memset(&args, 0, sizeof(args));
+	args.ubi_ver = 1;
+	args.image_seq = rand();
+
+	while (1) {
+		int key;
+		unsigned long int image_seq;
+
+		key = getopt(argc, argv, "nyyqve:x:s:O:f:S:");
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 's':
+			args.subpage_size = strtoull_suffix(optarg, NULL, 0);
+			if (args.subpage_size <= 0)
+				return errmsg("bad sub-page size: \"%s\"", optarg);
+			if (!is_power_of_2(args.subpage_size))
+				return errmsg("sub-page size should be power of 2");
+			break;
+
+		case 'O':
+			args.vid_hdr_offs = simple_strtoul(optarg, NULL, 0);
+			if (args.vid_hdr_offs <= 0)
+				return errmsg("bad VID header offset: \"%s\"", optarg);
+			break;
+
+		case 'e':
+			args.ec = simple_strtoull(optarg, NULL, 0);
+			if (args.ec < 0)
+				return errmsg("bad erase counter value: \"%s\"", optarg);
+			if (args.ec >= EC_MAX)
+				return errmsg("too high erase %llu, counter, max is %u", args.ec, EC_MAX);
+			args.override_ec = 1;
+			break;
+
+		case 'f':
+			args.image = optarg;
+			break;
+
+		case 'n':
+			args.novtbl = 1;
+			break;
+
+		case 'y':
+			args.yes = 1;
+			break;
+
+		case 'q':
+			args.quiet = 1;
+			break;
+
+		case 'x':
+			args.ubi_ver = simple_strtoul(optarg, NULL, 0);
+			if (args.ubi_ver < 0)
+				return errmsg("bad UBI version: \"%s\"", optarg);
+			break;
+
+		case 'Q':
+			image_seq = simple_strtoul(optarg, NULL, 0);
+			if (image_seq > 0xFFFFFFFF)
+				return errmsg("bad UBI image sequence number: \"%s\"", optarg);
+			args.image_seq = image_seq;
+			break;
+
+		case 'v':
+			args.verbose = 1;
+			break;
+
+		default:
+			return COMMAND_ERROR_USAGE;
+		}
+	}
+
+	if (args.quiet && args.verbose)
+		return errmsg("using \"-q\" and \"-v\" at the same time does not make sense");
+
+	if (optind == argc)
+		return errmsg("MTD device name was not specified");
+	else if (optind != argc - 1)
+		return errmsg("more then one MTD device specified");
+
+	if (args.image && args.novtbl)
+		return errmsg("-n cannot be used together with -f");
+
+
+	args.node = argv[optind];
+	return 0;
+}
+
+static void print_bad_eraseblocks(const struct mtd_dev_info *mtd,
+				  const struct ubi_scan_info *si)
+{
+	int first = 1, eb;
+
+	if (si->bad_cnt == 0)
+		return;
+
+	normsg_cont("%d bad eraseblocks found, numbers: ", si->bad_cnt);
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		if (si->ec[eb] != EB_BAD)
+			continue;
+		if (first) {
+			printf("%d", eb);
+			first = 0;
+		} else
+			printf(", %d", eb);
+	}
+	printf("\n");
+}
+
+static int change_ech(struct ubi_ec_hdr *hdr, uint32_t image_seq,
+		      long long ec)
+{
+	uint32_t crc;
+
+	/* Check the EC header */
+	if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC)
+		return errmsg("bad UBI magic %#08x, should be %#08x",
+			      be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC);
+
+	crc = crc32_no_comp(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	if (be32_to_cpu(hdr->hdr_crc) != crc)
+		return errmsg("bad CRC %#08x, should be %#08x\n",
+			      crc, be32_to_cpu(hdr->hdr_crc));
+
+	hdr->image_seq = cpu_to_be32(image_seq);
+	hdr->ec = cpu_to_be64(ec);
+	crc = crc32_no_comp(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
+
+	return 0;
+}
+
+static int drop_ffs(const struct mtd_dev_info *mtd, const void *buf, int len)
+{
+	int i;
+
+        for (i = len - 1; i >= 0; i--)
+		if (((const uint8_t *)buf)[i] != 0xFF)
+		      break;
+
+        /* The resulting length must be aligned to the minimum flash I/O size */
+	len = i + 1;
+	len = (len + mtd->min_io_size - 1) / mtd->min_io_size;
+	len *=  mtd->min_io_size;
+	return len;
+}
+
+static int open_file(off_t *sz)
+{
+	int fd;
+	struct stat st;
+
+	if (stat(args.image, &st))
+		return sys_errmsg("cannot open \"%s\"", args.image);
+
+	*sz = st.st_size;
+	fd  = open(args.image, O_RDWR);
+	if (fd < 0)
+		return sys_errmsg("cannot open \"%s\"", args.image);
+
+	return fd;
+}
+
+/*
+ * Returns %-1 if consecutive bad blocks exceeds the
+ * MAX_CONSECUTIVE_BAD_BLOCKS and returns %0 otherwise.
+ */
+static int consecutive_bad_check(int eb)
+{
+	static int consecutive_bad_blocks = 1;
+	static int prev_bb = -1;
+
+	if (prev_bb == -1)
+		prev_bb = eb;
+
+	if (eb == prev_bb + 1)
+		consecutive_bad_blocks += 1;
+	else
+		consecutive_bad_blocks = 1;
+
+	prev_bb = eb;
+
+	if (consecutive_bad_blocks >= MAX_CONSECUTIVE_BAD_BLOCKS) {
+		if (!args.quiet)
+			printf("\n");
+		return errmsg("consecutive bad blocks exceed limit: %d, bad flash?",
+		              MAX_CONSECUTIVE_BAD_BLOCKS);
+	}
+
+	return 0;
+}
+
+/* TODO: we should actually torture the PEB before marking it as bad */
+static int mark_bad(const struct mtd_dev_info *mtd, struct ubi_scan_info *si, int eb)
+{
+	int err;
+
+	if (!args.quiet)
+		normsg_cont("marking block %d bad\n", eb);
+
+	if (!mtd->bb_allowed) {
+		if (!args.quiet)
+			printf("\n");
+		return errmsg("bad blocks not supported by this flash");
+	}
+
+	err = mtd_mark_bad(mtd, args.node_fd, eb);
+	if (err)
+		return err;
+
+	si->bad_cnt += 1;
+	si->ec[eb] = EB_BAD;
+
+	return consecutive_bad_check(eb);
+}
+
+static int flash_image(const struct mtd_dev_info *mtd,
+		       const struct ubigen_info *ui, struct ubi_scan_info *si)
+{
+	int fd, img_ebs, eb, written_ebs = 0, divisor;
+	off_t st_size;
+
+	fd = open_file(&st_size);
+	if (fd < 0)
+		return fd;
+
+	img_ebs = st_size / mtd->eb_size;
+
+	if (img_ebs > si->good_cnt) {
+		sys_errmsg("file \"%s\" is too large (%lld bytes)",
+			   args.image, (long long)st_size);
+		goto out_close;
+	}
+
+	if (st_size % mtd->eb_size) {
+		return sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of ""eraseblock size (%d bytes)",
+				  args.image, (long long)st_size, mtd->eb_size);
+		goto out_close;
+	}
+
+	verbose(args.verbose, "will write %d eraseblocks", img_ebs);
+	divisor = img_ebs;
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		int err, new_len;
+		char buf[mtd->eb_size];
+		long long ec;
+
+		if (!args.quiet && !args.verbose) {
+			printf("\r" PROGRAM_NAME ": flashing eraseblock %d -- %2u %% complete  ",
+			       eb, (eb + 1) * 100 / mtd->eb_cnt);
+		}
+
+		if (si->ec[eb] == EB_BAD) {
+			divisor += 1;
+			continue;
+		}
+
+		if (args.verbose) {
+			normsg_cont("eraseblock %d: erase", eb);
+		}
+
+		err = mtd_erase(mtd, args.node_fd, eb);
+		if (err) {
+			if (!args.quiet)
+				printf("\n");
+			sys_errmsg("failed to erase eraseblock %d", eb);
+
+			if (errno != EIO)
+				goto out_close;
+
+			if (mark_bad(mtd, si, eb))
+				goto out_close;
+
+			continue;
+		}
+
+		err = read_full(fd, buf, mtd->eb_size);
+		if (err < 0) {
+			sys_errmsg("failed to read eraseblock %d from \"%s\"",
+				   written_ebs, args.image);
+			goto out_close;
+		}
+
+		if (args.override_ec)
+			ec = args.ec;
+		else if (si->ec[eb] <= EC_MAX)
+			ec = si->ec[eb] + 1;
+		else
+			ec = si->mean_ec;
+
+		if (args.verbose) {
+			printf(", change EC to %lld", ec);
+		}
+
+		err = change_ech((struct ubi_ec_hdr *)buf, ui->image_seq, ec);
+		if (err) {
+			errmsg("bad EC header at eraseblock %d of \"%s\"",
+			       written_ebs, args.image);
+			goto out_close;
+		}
+
+		if (args.verbose) {
+			printf(", write data\n");
+		}
+
+		new_len = drop_ffs(mtd, buf, mtd->eb_size);
+
+		err = mtd_write(mtd, args.node_fd, eb, 0, buf, new_len);
+		if (err) {
+			sys_errmsg("cannot write eraseblock %d", eb);
+
+			if (errno != EIO)
+				goto out_close;
+
+			err = mtd_torture(mtd, args.node_fd, eb);
+			if (err) {
+				if (mark_bad(mtd, si, eb))
+					goto out_close;
+			}
+			continue;
+		}
+		if (++written_ebs >= img_ebs)
+			break;
+	}
+
+	if (!args.quiet && !args.verbose)
+		printf("\n");
+	close(fd);
+	return eb + 1;
+
+out_close:
+	close(fd);
+	return -1;
+}
+
+static int format(const struct mtd_dev_info *mtd,
+		  const struct ubigen_info *ui, struct ubi_scan_info *si,
+		  int start_eb, int novtbl)
+{
+	int eb, err, write_size;
+	struct ubi_ec_hdr *hdr;
+	struct ubi_vtbl_record *vtbl;
+	int eb1 = -1, eb2 = -1;
+	long long ec1 = -1, ec2 = -1;
+
+	write_size = UBI_EC_HDR_SIZE + mtd->subpage_size - 1;
+	write_size /= mtd->subpage_size;
+	write_size *= mtd->subpage_size;
+	hdr = malloc(write_size);
+	if (!hdr)
+		return sys_errmsg("cannot allocate %d bytes of memory", write_size);
+	memset(hdr, 0xFF, write_size);
+
+	for (eb = start_eb; eb < mtd->eb_cnt; eb++) {
+		long long ec;
+
+		if (!args.quiet && !args.verbose) {
+			printf("\r" PROGRAM_NAME ": formatting eraseblock %d -- %2u %% complete  ",
+			       eb, (eb + 1 - start_eb) * 100 / (mtd->eb_cnt - start_eb));
+		}
+
+		if (si->ec[eb] == EB_BAD)
+			continue;
+
+		if (args.override_ec)
+			ec = args.ec;
+		else if (si->ec[eb] <= EC_MAX)
+			ec = si->ec[eb] + 1;
+		else
+			ec = si->mean_ec;
+		ubigen_init_ec_hdr(ui, hdr, ec);
+
+		if (args.verbose) {
+			normsg_cont("eraseblock %d: erase", eb);
+		}
+
+		err = mtd_erase(mtd, args.node_fd, eb);
+		if (err) {
+			if (!args.quiet)
+				printf("\n");
+
+			sys_errmsg("failed to erase eraseblock %d", eb);
+			if (errno != EIO)
+				goto out_free;
+
+			if (mark_bad(mtd, si, eb))
+				goto out_free;
+			continue;
+		}
+
+		if ((eb1 == -1 || eb2 == -1) && !novtbl) {
+			if (eb1 == -1) {
+				eb1 = eb;
+				ec1 = ec;
+			} else if (eb2 == -1) {
+				eb2 = eb;
+				ec2 = ec;
+			}
+			if (args.verbose)
+				printf(", do not write EC, leave for vtbl\n");
+			continue;
+		}
+
+		if (args.verbose) {
+			printf(", write EC %lld\n", ec);
+		}
+
+		err = mtd_write(mtd, args.node_fd, eb, 0, hdr, write_size);
+		if (err) {
+			if (!args.quiet && !args.verbose)
+				printf("\n");
+			sys_errmsg("cannot write EC header (%d bytes buffer) to eraseblock %d",
+				   write_size, eb);
+
+			if (errno != EIO) {
+				if (!args.subpage_size != mtd->min_io_size)
+					normsg("may be sub-page size is "
+					       "incorrect?");
+				goto out_free;
+			}
+
+			err = mtd_torture(mtd, args.node_fd, eb);
+			if (err) {
+				if (mark_bad(mtd, si, eb))
+					goto out_free;
+			}
+			continue;
+
+		}
+	}
+
+	if (!args.quiet && !args.verbose)
+		printf("\n");
+
+	if (!novtbl) {
+		if (eb1 == -1 || eb2 == -1) {
+			errmsg("no eraseblocks for volume table");
+			goto out_free;
+		}
+
+		verbose(args.verbose, "write volume table to eraseblocks %d and %d", eb1, eb2);
+		vtbl = ubigen_create_empty_vtbl(ui);
+		if (!vtbl)
+			goto out_free;
+
+		err = ubigen_write_layout_vol(ui, eb1, eb2, ec1,  ec2, vtbl,
+					      args.node_fd);
+		free(vtbl);
+		if (err) {
+			errmsg("cannot write layout volume");
+			goto out_free;
+		}
+	}
+
+	free(hdr);
+	return 0;
+
+out_free:
+	free(hdr);
+	return -1;
+}
+
+int do_ubiformat(int argc, char *argv[])
+{
+	int err, verbose;
+	struct mtd_dev_info mtd;
+	struct ubigen_info ui;
+	struct ubi_scan_info *si;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return err;
+
+	err = mtd_get_dev_info(args.node, &mtd);
+	if (err) {
+		sys_errmsg("cannot get information about \"%s\"", args.node);
+		goto out_close_mtd;
+	}
+
+	if (!is_power_of_2(mtd.min_io_size)) {
+		errmsg("min. I/O size is %d, but should be power of 2",
+		       mtd.min_io_size);
+		goto out_close_mtd;
+	}
+
+	if (args.subpage_size && args.subpage_size != mtd.subpage_size) {
+		mtd.subpage_size = args.subpage_size;
+		args.manual_subpage = 1;
+	}
+
+	if (args.manual_subpage) {
+		/* Do some sanity check */
+		if (args.subpage_size > mtd.min_io_size) {
+			errmsg("sub-page cannot be larger than min. I/O unit");
+			goto out_close_mtd;
+		}
+
+		if (mtd.min_io_size % args.subpage_size) {
+			errmsg("min. I/O unit size should be multiple of "
+			       "sub-page size");
+			goto out_close_mtd;
+		}
+	}
+
+	args.node_fd = open(args.node, O_RDWR);
+	if (args.node_fd < 0) {
+		sys_errmsg("cannot open \"%s\"", args.node);
+		goto out_close_mtd;
+	}
+
+	/* Validate VID header offset if it was specified */
+	if (args.vid_hdr_offs != 0) {
+		if (args.vid_hdr_offs % 8) {
+			errmsg("VID header offset has to be multiple of min. I/O unit size");
+			goto out_close;
+		}
+		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE > mtd.eb_size) {
+			errmsg("bad VID header offset");
+			goto out_close;
+		}
+	}
+
+	if (!mtd.writable) {
+		errmsg("%s (%s) is a read-only device", mtd.node, args.node);
+		goto out_close;
+	}
+
+	/* Make sure this MTD device is not attached to UBI */
+	/* FIXME! Find a proper way to do this in barebox! */
+
+	if (!args.quiet) {
+		normsg_cont("%s (%s), size %lld bytes (%s)", mtd.node, mtd.type_str,
+			mtd.size, size_human_readable(mtd.size));
+		printf(", %d eraseblocks of %d bytes (%s)", mtd.eb_cnt,
+			mtd.eb_size, size_human_readable(mtd.eb_size));
+		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
+	}
+
+	if (args.quiet)
+		verbose = 0;
+	else if (args.verbose)
+		verbose = 2;
+	else
+		verbose = 1;
+	err = libscan_ubi_scan(&mtd, args.node_fd, &si, verbose);
+	if (err) {
+		errmsg("failed to scan %s (%s)", mtd.node, args.node);
+		goto out_close;
+	}
+
+	if (si->good_cnt == 0) {
+		errmsg("all %d eraseblocks are bad", si->bad_cnt);
+		goto out_free;
+	}
+
+	if (si->good_cnt < 2 && (!args.novtbl || args.image)) {
+		errmsg("too few non-bad eraseblocks (%d) on %s",
+		       si->good_cnt, mtd.node);
+		goto out_free;
+	}
+
+	if (!args.quiet) {
+		if (si->ok_cnt)
+			normsg("%d eraseblocks have valid erase counter, mean value is %lld",
+			       si->ok_cnt, si->mean_ec);
+		if (si->empty_cnt)
+			normsg("%d eraseblocks are supposedly empty", si->empty_cnt);
+		if (si->corrupted_cnt)
+			normsg("%d corrupted erase counters", si->corrupted_cnt);
+		print_bad_eraseblocks(&mtd, si);
+	}
+
+	if (si->alien_cnt) {
+		if (!args.quiet)
+			warnmsg("%d of %d eraseblocks contain non-ubifs data",
+				si->alien_cnt, si->good_cnt);
+		if (!args.yes && !args.quiet)
+			warnmsg("use '-y' to force erasing");
+		if (!args.yes)
+			goto out_free;
+	}
+
+	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
+		int percent = (si->ok_cnt * 100) / si->good_cnt;
+
+		/*
+		 * Make sure the majority of eraseblocks have valid
+		 * erase counters.
+		 */
+		if (percent < 50) {
+			if (!args.quiet) {
+				warnmsg("only %d of %d eraseblocks have valid erase counter",
+					si->ok_cnt, si->good_cnt);
+				if (args.yes) {
+					normsg("erase counter 0 will be used for all eraseblocks");
+					normsg("note, arbitrary erase counter value may be specified using -e option");
+
+				} else {
+					warnmsg("use '-y' to force erase counters");
+				}
+			}
+
+			if (!args.yes)
+				goto out_free;
+
+			args.ec = 0;
+			args.override_ec = 1;
+
+		} else if (percent < 95) {
+			if (!args.quiet) {
+				warnmsg("only %d of %d eraseblocks have valid erase counter",
+					si->ok_cnt, si->good_cnt);
+				if (args.yes)
+					normsg("mean erase counter %lld will be used for the rest of eraseblock",
+					       si->mean_ec);
+				else
+					warnmsg("use '-y' to force erase counters");
+			}
+
+			if (!args.yes)
+				goto out_free;
+
+			args.ec = si->mean_ec;
+			args.override_ec = 1;
+		}
+	}
+
+	if (!args.quiet && args.override_ec)
+		normsg("use erase counter %lld for all eraseblocks", args.ec);
+
+	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, mtd.subpage_size,
+			 args.vid_hdr_offs, args.ubi_ver, args.image_seq);
+
+	if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) {
+		/*
+		 * Hmm, what we read from flash and what we calculated using
+		 * min. I/O unit size and sub-page size differs.
+		 */
+		if (!args.quiet) {
+			warnmsg("VID header and data offsets on flash are %d and %d, "
+				"which is different to requested offsets %d and %d",
+				si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs,
+				ui.data_offs);
+			normsg("using offsets %d and %d",  ui.vid_hdr_offs, ui.data_offs);
+		}
+	}
+
+	if (args.image) {
+		err = flash_image(&mtd, &ui, si);
+		if (err < 0)
+			goto out_free;
+
+		err = format(&mtd, &ui, si, err, 1);
+		if (err)
+			goto out_free;
+	} else {
+		err = format(&mtd, &ui, si, 0, args.novtbl);
+		if (err)
+			goto out_free;
+	}
+
+	libscan_ubi_scan_free(si);
+	close(args.node_fd);
+	return 0;
+
+out_free:
+	libscan_ubi_scan_free(si);
+out_close:
+	close(args.node_fd);
+out_close_mtd:
+	return 1;
+}
+
+BAREBOX_CMD_HELP_START(ubiformat)
+BAREBOX_CMD_HELP_USAGE(PROGRAM_NAME " <MTD device file name> [-s <bytes>] [-O <offs>] [-n]\n"
+	"\t[-f <file>] [-e <value>] [-x <num>] [-Q <num>] [-y] [-q] [-v]\n")
+BAREBOX_CMD_HELP_SHORT("A tool to format MTD devices and flash UBI images\n")
+BAREBOX_CMD_HELP_OPT("-s <bytes>", "minimum input/output unit used for UBI headers, "
+"e.g. sub-page size in case of NAND flash (equivalent to the minimum input/output "
+"unit size by default)\n")
+BAREBOX_CMD_HELP_OPT("-O <offs>", "offset if the VID header from start of the "
+"physical eraseblock (default is the next minimum I/O unit or sub-page after the EC "
+"header)\n")
+BAREBOX_CMD_HELP_OPT("-n", "only erase all eraseblock and preserve erase "
+"counters, do not write empty volume table\n")
+BAREBOX_CMD_HELP_OPT("-f <file>", "flash image file\n")
+BAREBOX_CMD_HELP_OPT("-e <value>", "use <value> as the erase counter value for all eraseblocks\n")
+BAREBOX_CMD_HELP_OPT("-x <num>", "UBI version number to put to EC headers "
+"(default is 1)\n")
+BAREBOX_CMD_HELP_OPT("-Q <num>", "32-bit UBI image sequence number to use "
+"(by default a random number is picked)\n")
+BAREBOX_CMD_HELP_OPT("-q", "suppress progress percentage information\n")
+BAREBOX_CMD_HELP_OPT("-v", "be verbose\n")
+BAREBOX_CMD_HELP_TEXT(
+"Example 1: " PROGRAM_NAME " /dev/nand0 -y - format nand0 and assume yes\n"
+"Example 2: " PROGRAM_NAME " /dev/nand0 -q -e 0 - format nand0,\n"
+"           be quiet and force erase counter value 0.\n";
+)
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(ubiformat)
+	.cmd		= do_ubiformat,
+	.usage		= "format an ubi volume",
+	BAREBOX_CMD_HELP(cmd_ubiformat_help)
+BAREBOX_CMD_END
-- 
1.7.10.4


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH V3 00/11] ubiformat for barebox
  2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
                   ` (10 preceding siblings ...)
  2012-12-17 15:48 ` [PATCH V3 11/11] commands: add ubiformat Wolfram Sang
@ 2012-12-19 11:50 ` Sascha Hauer
  11 siblings, 0 replies; 13+ messages in thread
From: Sascha Hauer @ 2012-12-19 11:50 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: barebox

On Mon, Dec 17, 2012 at 04:48:22PM +0100, Wolfram Sang wrote:
> Another round of ubiformat for barebox. Tested on various MX28 based hardware.
> I could create and attach empty UBIs or flashed files successfully. I also
> tried flashing /dev/mem and /dev/c64 which failed correctly.
> 
> Changes since V1 (V2 was only internal):
> 
> * update strtoull_suffix() and size_human_readable()
> * use those and get rid of libubiutils completely \o/
> * use read_full instead of custom read_all
> * dropped all long commandline options and references
> * reworked the help to BAREBOX_CMD_HELP_* usage
> * dropped FSF addresses all over
> * simply quit in dubious situations instead of doing something
> * add '-y' to do something in dubious situations :)
> * quite some bugfixes
> (* verified subpage-size handling, found a bug in nand_mxs driver)
> 
> Please test, comment, apply...

Applied, thanks

Sascha

> 
> Thanks,
> 
>    Wolfram
> 
> 
> Wolfram Sang (11):
>   mtd: drop custom is_power_of_2()
>   lib: misc: add 'iB' suffixes to strtoull_suffix
>   lib: update size_human_readable to latest version
>   ubi: consolidate ubi-media.h
>   ubi: bump ubi-media.h to newest version
>   devfs & mtd: add MEMERASE ioctl support
>   mtd: utils: apply macros for message printouts
>   lib: add libscan
>   lib: add libubigen
>   lib: add barebox version of libmtd
>   commands: add ubiformat
> 
>  commands/Kconfig              |    8 +
>  commands/Makefile             |    1 +
>  commands/ubi.c                |    2 +-
>  commands/ubiformat.c          |  784 +++++++++++++++++++++++++++++++++++++++++
>  drivers/mtd/core.c            |   68 ++--
>  drivers/mtd/ubi/ubi-barebox.h |    5 +-
>  drivers/mtd/ubi/ubi-media.h   |  369 -------------------
>  drivers/mtd/ubi/ubi.h         |    3 +-
>  fs/devfs-core.c               |    3 +-
>  include/common.h              |    2 +-
>  include/mtd/libmtd.h          |  149 ++++++++
>  include/mtd/libscan.h         |  101 ++++++
>  include/mtd/libubigen.h       |  182 ++++++++++
>  include/mtd/ubi-media.h       |  374 ++++++++++++++++++++
>  include/mtd/utils.h           |   47 +++
>  include/ubi-media.h           |  370 -------------------
>  lib/Kconfig                   |    9 +
>  lib/Makefile                  |    3 +
>  lib/display_options.c         |   47 ++-
>  lib/libmtd.c                  |  368 +++++++++++++++++++
>  lib/libscan.c                 |  219 ++++++++++++
>  lib/libubigen.c               |  312 ++++++++++++++++
>  lib/misc.c                    |    5 +-
>  23 files changed, 2634 insertions(+), 797 deletions(-)
>  create mode 100644 commands/ubiformat.c
>  delete mode 100644 drivers/mtd/ubi/ubi-media.h
>  create mode 100644 include/mtd/libmtd.h
>  create mode 100644 include/mtd/libscan.h
>  create mode 100644 include/mtd/libubigen.h
>  create mode 100644 include/mtd/ubi-media.h
>  create mode 100644 include/mtd/utils.h
>  delete mode 100644 include/ubi-media.h
>  create mode 100644 lib/libmtd.c
>  create mode 100644 lib/libscan.c
>  create mode 100644 lib/libubigen.c
> 
> -- 
> 1.7.10.4
> 
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2012-12-19 11:50 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-17 15:48 [PATCH V3 00/11] ubiformat for barebox Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 01/11] mtd: drop custom is_power_of_2() Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 02/11] lib: misc: add 'iB' suffixes to strtoull_suffix Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 03/11] lib: update size_human_readable to latest version Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 04/11] ubi: consolidate ubi-media.h Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 05/11] ubi: bump ubi-media.h to newest version Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 06/11] devfs & mtd: add MEMERASE ioctl support Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 07/11] mtd: utils: apply macros for message printouts Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 08/11] lib: add libscan Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 09/11] lib: add libubigen Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 10/11] lib: add barebox version of libmtd Wolfram Sang
2012-12-17 15:48 ` [PATCH V3 11/11] commands: add ubiformat Wolfram Sang
2012-12-19 11:50 ` [PATCH V3 00/11] ubiformat for barebox Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox