mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 00/10] add ubiformat command
@ 2012-12-10  8:14 Wolfram Sang
  2012-12-10  8:14 ` [PATCH 01/10] mtd: move is_power_of_2() to a public place Wolfram Sang
                   ` (9 more replies)
  0 siblings, 10 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Hi,

here is the ubiformat series rebased against v2012.12.0. All comments I have
received have been addressed. The command has been tested on a MX35 based
board. Please help testing.

Regards,

   Wolfram Sang

Wolfram Sang (10):
  mtd: move is_power_of_2() to a public place
  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 ubiutils-common
  lib: add libscan
  lib: add libubigen
  lib: add barebox version of libmtd
  commands: add ubiformat

 commands/Kconfig              |    9 +
 commands/Makefile             |    1 +
 commands/ubi.c                |    2 +-
 commands/ubiformat.c          |  794 +++++++++++++++++++++++++++++++++++++++++
 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/mtd/libmtd.h          |  154 ++++++++
 include/mtd/libscan.h         |  105 ++++++
 include/mtd/libubigen.h       |  186 ++++++++++
 include/mtd/ubi-media.h       |  378 ++++++++++++++++++++
 include/mtd/ubiutils-common.h |   26 ++
 include/mtd/utils.h           |   52 +++
 include/ubi-media.h           |  370 -------------------
 lib/Kconfig                   |   12 +
 lib/Makefile                  |    4 +
 lib/libmtd.c                  |  371 +++++++++++++++++++
 lib/libscan.c                 |  223 ++++++++++++
 lib/libubigen.c               |  316 ++++++++++++++++
 lib/ubiutils-common.c         |  122 +++++++
 22 files changed, 2794 insertions(+), 779 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/ubiutils-common.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
 create mode 100644 lib/ubiutils-common.c

-- 
1.7.10.4


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

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

* [PATCH 01/10] mtd: move is_power_of_2() to a public place
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-11  9:22   ` Sascha Hauer
  2012-12-10  8:14 ` [PATCH 02/10] ubi: consolidate ubi-media.h Wolfram Sang
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

Will need this later for ubiformat.

Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
---
 drivers/mtd/ubi/ubi-barebox.h |    5 +----
 include/mtd/utils.h           |   25 +++++++++++++++++++++++++
 2 files changed, 26 insertions(+), 4 deletions(-)
 create mode 100644 include/mtd/utils.h

diff --git a/drivers/mtd/ubi/ubi-barebox.h b/drivers/mtd/ubi/ubi-barebox.h
index 72f29a6..919dc50 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 <mtd/utils.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
diff --git a/include/mtd/utils.h b/include/mtd/utils.h
new file mode 100644
index 0000000..229fb34
--- /dev/null
+++ b/include/mtd/utils.h
@@ -0,0 +1,25 @@
+/*
+ * 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
+
+static inline int is_power_of_2(unsigned long n)
+{
+	return (n != 0 && ((n & (n - 1)) == 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] 19+ messages in thread

* [PATCH 02/10] ubi: consolidate ubi-media.h
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
  2012-12-10  8:14 ` [PATCH 01/10] mtd: move is_power_of_2() to a public place Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-10  8:14 ` [PATCH 03/10] ubi: bump ubi-media.h to newest version Wolfram Sang
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 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.h                        |    3 +-
 {drivers/mtd/ubi => include/mtd}/ubi-media.h |    0
 include/ubi-media.h                          |  370 --------------------------
 4 files changed, 3 insertions(+), 372 deletions(-)
 rename {drivers/mtd/ubi => include/mtd}/ubi-media.h (100%)
 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.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/drivers/mtd/ubi/ubi-media.h b/include/mtd/ubi-media.h
similarity index 100%
rename from drivers/mtd/ubi/ubi-media.h
rename to include/mtd/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] 19+ messages in thread

* [PATCH 03/10] ubi: bump ubi-media.h to newest version
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
  2012-12-10  8:14 ` [PATCH 01/10] mtd: move is_power_of_2() to a public place Wolfram Sang
  2012-12-10  8:14 ` [PATCH 02/10] ubi: consolidate ubi-media.h Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-11  9:24   ` Sascha Hauer
  2012-12-10  8:14 ` [PATCH 04/10] devfs & mtd: add MEMERASE ioctl support Wolfram Sang
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 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 |   57 +++++++++++++++++++++++++++--------------------
 1 file changed, 33 insertions(+), 24 deletions(-)

diff --git a/include/mtd/ubi-media.h b/include/mtd/ubi-media.h
index cd1bd8e..08bec3e 100644
--- a/include/mtd/ubi-media.h
+++ b/include/mtd/ubi-media.h
@@ -11,6 +11,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
  * the GNU General Public License for more details.
  *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  * Authors: Artem Bityutskiy (Битюцкий Артём)
  *          Thomas Gleixner
@@ -95,10 +98,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 +124,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 +145,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 +161,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 +170,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 +197,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 +234,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 +254,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 +283,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] 19+ messages in thread

* [PATCH 04/10] devfs & mtd: add MEMERASE ioctl support
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
                   ` (2 preceding siblings ...)
  2012-12-10  8:14 ` [PATCH 03/10] ubi: bump ubi-media.h to newest version Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-10  8:14 ` [PATCH 05/10] mtd: utils: apply macros for message printouts Wolfram Sang
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 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] 19+ messages in thread

* [PATCH 05/10] mtd: utils: apply macros for message printouts
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
                   ` (3 preceding siblings ...)
  2012-12-10  8:14 ` [PATCH 04/10] devfs & mtd: add MEMERASE ioctl support Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-10  8:14 ` [PATCH 06/10] lib: add ubiutils-common Wolfram Sang
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 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 |   27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

diff --git a/include/mtd/utils.h b/include/mtd/utils.h
index 229fb34..05a3405 100644
--- a/include/mtd/utils.h
+++ b/include/mtd/utils.h
@@ -17,6 +17,33 @@
 #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)
+
 static inline int is_power_of_2(unsigned long n)
 {
 	return (n != 0 && ((n & (n - 1)) == 0));
-- 
1.7.10.4


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

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

* [PATCH 06/10] lib: add ubiutils-common
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
                   ` (4 preceding siblings ...)
  2012-12-10  8:14 ` [PATCH 05/10] mtd: utils: apply macros for message printouts Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-11  9:35   ` Sascha Hauer
  2012-12-10  8:14 ` [PATCH 07/10] lib: add libscan Wolfram Sang
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 UTC (permalink / raw)
  To: barebox; +Cc: Wolfram Sang

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

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

diff --git a/include/mtd/ubiutils-common.h b/include/mtd/ubiutils-common.h
new file mode 100644
index 0000000..3a16617
--- /dev/null
+++ b/include/mtd/ubiutils-common.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) Artem Bityutskiy, 2007, 2008
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __UBI_UTILS_COMMON_H__
+#define __UBI_UTILS_COMMON_H__
+
+long long ubiutils_get_bytes(const char *str);
+void ubiutils_print_bytes(long long bytes, int bracket);
+
+#endif /* !__UBI_UTILS_COMMON_H__ */
+
diff --git a/lib/Kconfig b/lib/Kconfig
index 13ecab0..b2d72df 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -41,6 +41,9 @@ config QSORT
 config XYMODEM
 	bool
 
+config UBIUTILS
+	bool
+
 source lib/gui/Kconfig
 
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index eb0af92..76ca1db 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_UBIUTILS)	+= ubiutils-common.o
 obj-y			+= gui/
 obj-$(CONFIG_XYMODEM)	+= xymodem.o
diff --git a/lib/ubiutils-common.c b/lib/ubiutils-common.c
new file mode 100644
index 0000000..d01e723
--- /dev/null
+++ b/lib/ubiutils-common.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2007, 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file contains various common stuff used by UBI utilities.
+ *
+ * Authors: Artem Bityutskiy
+ *          Adrian Hunter
+ */
+
+#include <common.h>
+#include <stdlib.h>
+#include <string.h>
+
+/**
+ * get_multiplier - convert size specifier to an integer multiplier.
+ * @str: the size specifier string
+ *
+ * This function parses the @str size specifier, which may be one of
+ * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
+ * size multiplier in case of success and %-1 in case of failure.
+ */
+static int get_multiplier(const char *str)
+{
+	if (!str)
+		return 1;
+
+	/* Remove spaces before the specifier */
+	while (*str == ' ' || *str == '\t')
+		str += 1;
+
+	if (!strcmp(str, "KiB"))
+		return 1024;
+	if (!strcmp(str, "MiB"))
+		return 1024 * 1024;
+	if (!strcmp(str, "GiB"))
+		return 1024 * 1024 * 1024;
+
+	return -1;
+}
+
+/**
+ * ubiutils_get_bytes - convert a string containing amount of bytes into an
+ * integer
+ * @str: string to convert
+ *
+ * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
+ * size specifiers. Returns positive amount of bytes in case of success and %-1
+ * in case of failure.
+ */
+long long ubiutils_get_bytes(const char *str)
+{
+	char *endp;
+	long long bytes = simple_strtoull(str, &endp, 0);
+
+	if (endp == str || bytes < 0) {
+		fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
+		return -1;
+	}
+
+	if (*endp != '\0') {
+		int mult = get_multiplier(endp);
+
+		if (mult == -1) {
+			fprintf(stderr, "bad size specifier: \"%s\" - "
+			        "should be 'KiB', 'MiB' or 'GiB'\n", endp);
+			return -1;
+		}
+		bytes *= mult;
+	}
+
+	return bytes;
+}
+
+/**
+ * ubiutils_print_bytes - print bytes.
+ * @bytes: variable to print
+ * @bracket: whether brackets have to be put or not
+ *
+ * This is a helper function which prints amount of bytes in a human-readable
+ * form, i.e., it prints the exact amount of bytes following by the approximate
+ * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes
+ * is.
+ */
+void ubiutils_print_bytes(long long bytes, int bracket)
+{
+	const char *p;
+
+	if (bracket)
+		p = " (";
+	else
+		p = ", ";
+
+	printf("%lld bytes", bytes);
+
+	if (bytes > 1024 * 1024 * 1024)
+		printf("%s%lld GiB", p, bytes / (1024 * 1024 * 1024));
+	else if (bytes > 1024 * 1024)
+		printf("%s%lld MiB", p, bytes / (1024 * 1024));
+	else if (bytes > 1024 && bytes != 0)
+		printf("%s%lld KiB", p, bytes / 1024);
+	else
+		return;
+
+	if (bracket)
+		printf(")");
+}
-- 
1.7.10.4


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

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

* [PATCH 07/10] lib: add libscan
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
                   ` (5 preceding siblings ...)
  2012-12-10  8:14 ` [PATCH 06/10] lib: add ubiutils-common Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-10  8:14 ` [PATCH 08/10] lib: add libubigen Wolfram Sang
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 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 |  105 +++++++++++++++++++++++
 lib/Kconfig           |    3 +
 lib/Makefile          |    1 +
 lib/libscan.c         |  223 +++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 332 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..193b07b
--- /dev/null
+++ b/include/mtd/libscan.h
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 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 b2d72df..1a283d6 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -44,6 +44,9 @@ config XYMODEM
 config UBIUTILS
 	bool
 
+config LIBSCAN
+	bool
+
 source lib/gui/Kconfig
 
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 76ca1db..72306f8 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_UBIUTILS)	+= ubiutils-common.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..951e0e7
--- /dev/null
+++ b/lib/libscan.c
@@ -0,0 +1,223 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 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] 19+ messages in thread

* [PATCH 08/10] lib: add libubigen
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
                   ` (6 preceding siblings ...)
  2012-12-10  8:14 ` [PATCH 07/10] lib: add libscan Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-10  8:14 ` [PATCH 09/10] lib: add barebox version of libmtd Wolfram Sang
  2012-12-10  8:14 ` [PATCH 10/10] commands: add ubiformat Wolfram Sang
  9 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 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 |  186 ++++++++++++++++++++++++++++
 lib/Kconfig             |    3 +
 lib/Makefile            |    1 +
 lib/libubigen.c         |  316 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 506 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..5ebdb78
--- /dev/null
+++ b/include/mtd/libubigen.h
@@ -0,0 +1,186 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * 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 1a283d6..5e4cf82 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -47,6 +47,9 @@ config UBIUTILS
 config LIBSCAN
 	bool
 
+config LIBUBIGEN
+	bool
+
 source lib/gui/Kconfig
 
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 72306f8..aeeaad3 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -36,5 +36,6 @@ obj-$(CONFIG_BITREV)	+= bitrev.o
 obj-$(CONFIG_QSORT)	+= qsort.o
 obj-$(CONFIG_UBIUTILS)	+= ubiutils-common.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..9001c3b
--- /dev/null
+++ b/lib/libubigen.c
@@ -0,0 +1,316 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * 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] 19+ messages in thread

* [PATCH 09/10] lib: add barebox version of libmtd
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
                   ` (7 preceding siblings ...)
  2012-12-10  8:14 ` [PATCH 08/10] lib: add libubigen Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-10  8:14 ` [PATCH 10/10] commands: add ubiformat Wolfram Sang
  9 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 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 |  154 +++++++++++++++++++++
 lib/Kconfig          |    3 +
 lib/Makefile         |    1 +
 lib/libmtd.c         |  371 ++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 529 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..6267dac
--- /dev/null
+++ b/include/mtd/libmtd.h
@@ -0,0 +1,154 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 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 5e4cf82..d49e1dc 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -50,6 +50,9 @@ config LIBSCAN
 config LIBUBIGEN
 	bool
 
+config LIBMTD
+	bool
+
 source lib/gui/Kconfig
 
 endmenu
diff --git a/lib/Makefile b/lib/Makefile
index aeeaad3..3604343 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -37,5 +37,6 @@ obj-$(CONFIG_QSORT)	+= qsort.o
 obj-$(CONFIG_UBIUTILS)	+= ubiutils-common.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..dd5717a
--- /dev/null
+++ b/lib/libmtd.c
@@ -0,0 +1,371 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * 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-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] 19+ messages in thread

* [PATCH 10/10] commands: add ubiformat
  2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
                   ` (8 preceding siblings ...)
  2012-12-10  8:14 ` [PATCH 09/10] lib: add barebox version of libmtd Wolfram Sang
@ 2012-12-10  8:14 ` Wolfram Sang
  2012-12-11  9:57   ` Sascha Hauer
  9 siblings, 1 reply; 19+ messages in thread
From: Wolfram Sang @ 2012-12-10  8:14 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     |    9 +
 commands/Makefile    |    1 +
 commands/ubiformat.c |  794 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 804 insertions(+)
 create mode 100644 commands/ubiformat.c

diff --git a/commands/Kconfig b/commands/Kconfig
index ac9b797..b30e84e 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -347,6 +347,15 @@ config CMD_UBI
 	depends on UBI
 	prompt "ubimkvol, ubirmvol, ubiattach"
 
+config CMD_UBIFORMAT
+	tristate
+	depends on UBI
+	select LIBMTD
+	select LIBSCAN
+	select LIBUBIGEN
+	select UBIUTILS
+	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..e6b0e0f
--- /dev/null
+++ b/commands/ubiformat.c
@@ -0,0 +1,794 @@
+/*
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * 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_VERSION "1.5"
+#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 <linux/mtd/mtd.h>
+#include <linux/kernel.h>
+#include <linux/stat.h>
+#include <linux/mtd/mtd-abi.h>
+#include <mtd/libmtd.h>
+#include <mtd/libscan.h>
+#include <mtd/libubigen.h>
+#include <mtd/ubiutils-common.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 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, "nyqve:x:s:O:f:S:");
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 's':
+			args.subpage_size = ubiutils_get_bytes(optarg);
+			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 '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;
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	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 (use -h for help)");
+	else if (optind != argc - 1)
+		return errmsg("more then one MTD device specified (use -h for help)");
+
+	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;
+}
+
+static int read_all(int fd, void *buf, size_t len)
+{
+	while (len > 0) {
+		ssize_t l = read(fd, buf, len);
+		if (l == 0) {
+			return errmsg("eof reached; %zu bytes remaining", len);
+		} else if (l > 0) {
+			buf += l;
+			len -= l;
+		} else if (errno == EINTR || errno == EAGAIN) {
+			continue;
+		} else {
+			return sys_errmsg("reading failed; %zu bytes remaining", len);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * 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", eb);
+
+	if (!args.quiet)
+		printf("\n");
+
+	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_all(fd, buf, mtd->eb_size);
+		if (err) {
+			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)
+		goto out_close_mtd;
+
+	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;
+	}
+
+	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;
+		}
+
+		if (mtd.min_io_size % args.subpage_size) {
+			errmsg("min. I/O unit size should be multiple of "
+			       "sub-page size");
+			goto out_close;
+		}
+	}
+
+	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 ", mtd.node, mtd.type_str);
+		ubiutils_print_bytes(mtd.size, 1);
+		printf(", %d eraseblocks of ", mtd.eb_cnt);
+		ubiutils_print_bytes(mtd.eb_size, 1);
+		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);
+			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);
+				normsg("erase counter 0 will be used for all eraseblocks");
+				normsg("note, arbitrary erase counter value may be specified using -e option");
+			}
+			 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);
+				normsg("mean erase counter %lld will be used for the rest of eraseblock",
+				       si->mean_ec);
+			}
+			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("use 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;
+}
+
+static const __maybe_unused char cmd_ubiformat_help[] =
+" - a tool to format MTD devices and flash UBI images\n"
+"\n"
+"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
+"                             headers, e.g. sub-page size in case of NAND\n"
+"                             flash (equivalent to the minimum input/output\n"
+"                             unit size by default)\n"
+"-O, --vid-hdr-offset=<offs>  offset if the VID header from start of the\n"
+"                             physical eraseblock (default is the next\n"
+"                             minimum I/O unit or sub-page after the EC\n"
+"                             header)\n"
+"-n, --no-volume-table        only erase all eraseblock and preserve erase\n"
+"                             counters, do not write empty volume table\n"
+"-f, --flash-image=<file>     flash image file\n"
+"-e, --erase-counter=<value>  use <value> as the erase counter value for all\n"
+"                             eraseblocks\n"
+"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
+"                             (default is 1)\n"
+"-Q, --image-seq=<num>        32-bit UBI image sequence number to use\n"
+"                             (by default a random number is picked)\n"
+"-q, --quiet                  suppress progress percentage information\n"
+"-v, --verbose                be verbose\n"
+"-h, -?, --help               print help message\n"
+"\n"
+"Usage: " PROGRAM_NAME " <MTD device node file name> [-s <bytes>] [-O <offs>] [-n]\n"
+"\t\t\t[-f <file>] [-e <value>] [-x <num>] [-y] [-q] [-v] [-h] [-v]\n"
+"\t\t\t[--sub-page-size=<bytes>] [--vid-hdr-offset=<offs>] [--no-volume-table]\n"
+"\t\t\t[--flash-image=<file>] [--image-size=<bytes>] [--erase-counter=<value>]\n"
+"\t\t\t[--ubi-ver=<num>] [--quiet] [--verbose]\n\n"
+"Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n"
+"           not ask questions.\n"
+"Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n"
+"           be quiet and force erase counter value 0.\n";
+
+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] 19+ messages in thread

* Re: [PATCH 01/10] mtd: move is_power_of_2() to a public place
  2012-12-10  8:14 ` [PATCH 01/10] mtd: move is_power_of_2() to a public place Wolfram Sang
@ 2012-12-11  9:22   ` Sascha Hauer
  2012-12-11 14:57     ` Wolfram Sang
  0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2012-12-11  9:22 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: barebox

On Mon, Dec 10, 2012 at 09:14:06AM +0100, Wolfram Sang wrote:
> Will need this later for ubiformat.
> 
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>

We already have it in a public place: include/linux/log2.h

Sascha

> ---
>  drivers/mtd/ubi/ubi-barebox.h |    5 +----
>  include/mtd/utils.h           |   25 +++++++++++++++++++++++++
>  2 files changed, 26 insertions(+), 4 deletions(-)
>  create mode 100644 include/mtd/utils.h
> 
> diff --git a/drivers/mtd/ubi/ubi-barebox.h b/drivers/mtd/ubi/ubi-barebox.h
> index 72f29a6..919dc50 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 <mtd/utils.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
> diff --git a/include/mtd/utils.h b/include/mtd/utils.h
> new file mode 100644
> index 0000000..229fb34
> --- /dev/null
> +++ b/include/mtd/utils.h
> @@ -0,0 +1,25 @@
> +/*
> + * 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
> +
> +static inline int is_power_of_2(unsigned long n)
> +{
> +	return (n != 0 && ((n & (n - 1)) == 0));
> +}
> +
> +#endif /* INCLUDE_MTD_UTILS_H */
> -- 
> 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] 19+ messages in thread

* Re: [PATCH 03/10] ubi: bump ubi-media.h to newest version
  2012-12-10  8:14 ` [PATCH 03/10] ubi: bump ubi-media.h to newest version Wolfram Sang
@ 2012-12-11  9:24   ` Sascha Hauer
  2012-12-11 15:17     ` Wolfram Sang
  0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2012-12-11  9:24 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: barebox

On Mon, Dec 10, 2012 at 09:14:08AM +0100, Wolfram Sang wrote:
> Needed for ubiformat, we are interested in image_seq especially.
> 
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> ---
>  include/mtd/ubi-media.h |   57 +++++++++++++++++++++++++++--------------------
>  1 file changed, 33 insertions(+), 24 deletions(-)
> 
> diff --git a/include/mtd/ubi-media.h b/include/mtd/ubi-media.h
> index cd1bd8e..08bec3e 100644
> --- a/include/mtd/ubi-media.h
> +++ b/include/mtd/ubi-media.h
> @@ -11,6 +11,9 @@
>   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
>   * the GNU General Public License for more details.
>   *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Could you drop this hunk? I just patched out all addresses of the FSF.
The above is outdated anyway.

Sascha

-- 
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] 19+ messages in thread

* Re: [PATCH 06/10] lib: add ubiutils-common
  2012-12-10  8:14 ` [PATCH 06/10] lib: add ubiutils-common Wolfram Sang
@ 2012-12-11  9:35   ` Sascha Hauer
  2012-12-11 19:17     ` Wolfram Sang
  0 siblings, 1 reply; 19+ messages in thread
From: Sascha Hauer @ 2012-12-11  9:35 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: barebox

On Mon, Dec 10, 2012 at 09:14:11AM +0100, Wolfram Sang wrote:
> Imported from mtd-utils and stripped down to needed functionality for
> ubiformat.
> 
> Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> ---
>  include/mtd/ubiutils-common.h |   26 +++++++++
>  lib/Kconfig                   |    3 +
>  lib/Makefile                  |    1 +
>  lib/ubiutils-common.c         |  122 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 152 insertions(+)
>  create mode 100644 include/mtd/ubiutils-common.h
>  create mode 100644 lib/ubiutils-common.c
> 
> diff --git a/include/mtd/ubiutils-common.h b/include/mtd/ubiutils-common.h
> new file mode 100644
> index 0000000..3a16617
> --- /dev/null
> +++ b/include/mtd/ubiutils-common.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright (c) Artem Bityutskiy, 2007, 2008
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +#ifndef __UBI_UTILS_COMMON_H__
> +#define __UBI_UTILS_COMMON_H__
> +
> +long long ubiutils_get_bytes(const char *str);
> +void ubiutils_print_bytes(long long bytes, int bracket);
> +
> +#endif /* !__UBI_UTILS_COMMON_H__ */
> +
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 13ecab0..b2d72df 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -41,6 +41,9 @@ config QSORT
>  config XYMODEM
>  	bool
>  
> +config UBIUTILS
> +	bool
> +
>  source lib/gui/Kconfig
>  
>  endmenu
> diff --git a/lib/Makefile b/lib/Makefile
> index eb0af92..76ca1db 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_UBIUTILS)	+= ubiutils-common.o
>  obj-y			+= gui/
>  obj-$(CONFIG_XYMODEM)	+= xymodem.o
> diff --git a/lib/ubiutils-common.c b/lib/ubiutils-common.c
> new file mode 100644
> index 0000000..d01e723
> --- /dev/null
> +++ b/lib/ubiutils-common.c
> @@ -0,0 +1,122 @@
> +/*
> + * Copyright (C) 2007, 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.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> + */
> +
> +/*
> + * This file contains various common stuff used by UBI utilities.
> + *
> + * Authors: Artem Bityutskiy
> + *          Adrian Hunter
> + */
> +
> +#include <common.h>
> +#include <stdlib.h>
> +#include <string.h>
> +
> +/**
> + * get_multiplier - convert size specifier to an integer multiplier.
> + * @str: the size specifier string
> + *
> + * This function parses the @str size specifier, which may be one of
> + * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
> + * size multiplier in case of success and %-1 in case of failure.
> + */
> +static int get_multiplier(const char *str)
> +{
> +	if (!str)
> +		return 1;
> +
> +	/* Remove spaces before the specifier */
> +	while (*str == ' ' || *str == '\t')
> +		str += 1;
> +
> +	if (!strcmp(str, "KiB"))
> +		return 1024;
> +	if (!strcmp(str, "MiB"))
> +		return 1024 * 1024;
> +	if (!strcmp(str, "GiB"))
> +		return 1024 * 1024 * 1024;
> +
> +	return -1;
> +}
> +
> +/**
> + * ubiutils_get_bytes - convert a string containing amount of bytes into an
> + * integer
> + * @str: string to convert
> + *
> + * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
> + * size specifiers. Returns positive amount of bytes in case of success and %-1
> + * in case of failure.
> + */
> +long long ubiutils_get_bytes(const char *str)
> +{
> +	char *endp;
> +	long long bytes = simple_strtoull(str, &endp, 0);
> +
> +	if (endp == str || bytes < 0) {
> +		fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
> +		return -1;
> +	}
> +
> +	if (*endp != '\0') {
> +		int mult = get_multiplier(endp);
> +
> +		if (mult == -1) {
> +			fprintf(stderr, "bad size specifier: \"%s\" - "
> +			        "should be 'KiB', 'MiB' or 'GiB'\n", endp);
> +			return -1;
> +		}
> +		bytes *= mult;
> +	}
> +
> +	return bytes;
> +}

In barebox we have the strtoull_suffix function. We normally accept 'G',
'M' and 'k' suffixes. Restricting the ubi functions to '*iB' suffixes
might be confusing for barebox users. Not accepting '*iB' suffixes might
be confusing to UBI tool users. How about extending strtoull_suffix to
accept '*iB' suffixes and use it here? It seems the all that's missing
is to adjust *endp to skip the additional 'iB'

Sascha

-- 
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] 19+ messages in thread

* Re: [PATCH 10/10] commands: add ubiformat
  2012-12-10  8:14 ` [PATCH 10/10] commands: add ubiformat Wolfram Sang
@ 2012-12-11  9:57   ` Sascha Hauer
  0 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2012-12-11  9:57 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: barebox

On Mon, Dec 10, 2012 at 09:14:15AM +0100, Wolfram Sang wrote:
> 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>
> ---
> +
> +		default:
> +			fprintf(stderr, "Use -h for help\n");
> +			return -1;
> +		}

Oh no. I'm stuck in a loop. ubiformat -h tells me that this option
is not supported and I should try ubiformat -h. Luckily my head internal
watchdog triggered which allowed me to write this mail.

Please return COMMAND_ERROR_USAGE from ubiformat.

> +static int read_all(int fd, void *buf, size_t len)
> +{
> +	while (len > 0) {
> +		ssize_t l = read(fd, buf, len);
> +		if (l == 0) {
> +			return errmsg("eof reached; %zu bytes remaining", len);
> +		} else if (l > 0) {
> +			buf += l;
> +			len -= l;
> +		} else if (errno == EINTR || errno == EAGAIN) {
> +			continue;
> +		} else {
> +			return sys_errmsg("reading failed; %zu bytes remaining", len);
> +		}
> +	}
> +
> +	return 0;
> +}

We have read_full in barebox.

> +static const __maybe_unused char cmd_ubiformat_help[] =
> +" - a tool to format MTD devices and flash UBI images\n"
> +"\n"
> +"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
> +"                             headers, e.g. sub-page size in case of NAND\n"
> +"                             flash (equivalent to the minimum input/output\n"
> +"                             unit size by default)\n"
> +"-O, --vid-hdr-offset=<offs>  offset if the VID header from start of the\n"
> +"                             physical eraseblock (default is the next\n"
> +"                             minimum I/O unit or sub-page after the EC\n"
> +"                             header)\n"
> +"-n, --no-volume-table        only erase all eraseblock and preserve erase\n"
> +"                             counters, do not write empty volume table\n"
> +"-f, --flash-image=<file>     flash image file\n"
> +"-e, --erase-counter=<value>  use <value> as the erase counter value for all\n"
> +"                             eraseblocks\n"
> +"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
> +"                             (default is 1)\n"
> +"-Q, --image-seq=<num>        32-bit UBI image sequence number to use\n"
> +"                             (by default a random number is picked)\n"
> +"-q, --quiet                  suppress progress percentage information\n"
> +"-v, --verbose                be verbose\n"
> +"-h, -?, --help               print help message\n"
> +"\n"
> +"Usage: " PROGRAM_NAME " <MTD device node file name> [-s <bytes>] [-O <offs>] [-n]\n"
> +"\t\t\t[-f <file>] [-e <value>] [-x <num>] [-y] [-q] [-v] [-h] [-v]\n"
> +"\t\t\t[--sub-page-size=<bytes>] [--vid-hdr-offset=<offs>] [--no-volume-table]\n"
> +"\t\t\t[--flash-image=<file>] [--image-size=<bytes>] [--erase-counter=<value>]\n"
> +"\t\t\t[--ubi-ver=<num>] [--quiet] [--verbose]\n\n"
> +"Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n"
> +"           not ask questions.\n"
> +"Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n"
> +"           be quiet and force erase counter value 0.\n";

Long options are not supported in barebox, they shouldn't be mentioned
in the help text.

Sascha

-- 
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] 19+ messages in thread

* Re: [PATCH 01/10] mtd: move is_power_of_2() to a public place
  2012-12-11  9:22   ` Sascha Hauer
@ 2012-12-11 14:57     ` Wolfram Sang
  0 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-11 14:57 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox


[-- Attachment #1.1: Type: text/plain, Size: 526 bytes --]

On Tue, Dec 11, 2012 at 10:22:05AM +0100, Sascha Hauer wrote:
> On Mon, Dec 10, 2012 at 09:14:06AM +0100, Wolfram Sang wrote:
> > Will need this later for ubiformat.
> > 
> > Signed-off-by: Wolfram Sang <w.sang@pengutronix.de>
> 
> We already have it in a public place: include/linux/log2.h

...where the old occasion was not removed. Will update the patch.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 149 bytes --]

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

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

* Re: [PATCH 03/10] ubi: bump ubi-media.h to newest version
  2012-12-11  9:24   ` Sascha Hauer
@ 2012-12-11 15:17     ` Wolfram Sang
  0 siblings, 0 replies; 19+ messages in thread
From: Wolfram Sang @ 2012-12-11 15:17 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox


[-- Attachment #1.1: Type: text/plain, Size: 534 bytes --]


> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, write to the Free Software
> > + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> 
> Could you drop this hunk? I just patched out all addresses of the FSF.
> The above is outdated anyway.

Dropped it from the whole series.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 149 bytes --]

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

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

* Re: [PATCH 06/10] lib: add ubiutils-common
  2012-12-11  9:35   ` Sascha Hauer
@ 2012-12-11 19:17     ` Wolfram Sang
  2012-12-12  9:08       ` Sascha Hauer
  0 siblings, 1 reply; 19+ messages in thread
From: Wolfram Sang @ 2012-12-11 19:17 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: barebox


[-- Attachment #1.1: Type: text/plain, Size: 811 bytes --]


> In barebox we have the strtoull_suffix function. We normally accept 'G',
> 'M' and 'k' suffixes. Restricting the ubi functions to '*iB' suffixes
> might be confusing for barebox users. Not accepting '*iB' suffixes might
> be confusing to UBI tool users. How about extending strtoull_suffix to
> accept '*iB' suffixes and use it here? It seems the all that's missing
> is to adjust *endp to skip the additional 'iB'

OK. It probably makes sense to move the ubiutils_print_bytes() function
then to misc.c also and completely get rif of ubiutils-common? What
would be a proper name for the function, printull_suffix? Or
ulltostr_suffix? :)

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

[-- Attachment #2: Type: text/plain, Size: 149 bytes --]

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

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

* Re: [PATCH 06/10] lib: add ubiutils-common
  2012-12-11 19:17     ` Wolfram Sang
@ 2012-12-12  9:08       ` Sascha Hauer
  0 siblings, 0 replies; 19+ messages in thread
From: Sascha Hauer @ 2012-12-12  9:08 UTC (permalink / raw)
  To: Wolfram Sang; +Cc: barebox

On Tue, Dec 11, 2012 at 08:17:42PM +0100, Wolfram Sang wrote:
> 
> > In barebox we have the strtoull_suffix function. We normally accept 'G',
> > 'M' and 'k' suffixes. Restricting the ubi functions to '*iB' suffixes
> > might be confusing for barebox users. Not accepting '*iB' suffixes might
> > be confusing to UBI tool users. How about extending strtoull_suffix to
> > accept '*iB' suffixes and use it here? It seems the all that's missing
> > is to adjust *endp to skip the additional 'iB'
> 
> OK. It probably makes sense to move the ubiutils_print_bytes() function
> then to misc.c also and completely get rif of ubiutils-common? What
> would be a proper name for the function, printull_suffix? Or
> ulltostr_suffix? :)

Both seem fine. BTW we already have size_human_readable()

Sascha


-- 
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] 19+ messages in thread

end of thread, other threads:[~2012-12-12  9:08 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-10  8:14 [PATCH 00/10] add ubiformat command Wolfram Sang
2012-12-10  8:14 ` [PATCH 01/10] mtd: move is_power_of_2() to a public place Wolfram Sang
2012-12-11  9:22   ` Sascha Hauer
2012-12-11 14:57     ` Wolfram Sang
2012-12-10  8:14 ` [PATCH 02/10] ubi: consolidate ubi-media.h Wolfram Sang
2012-12-10  8:14 ` [PATCH 03/10] ubi: bump ubi-media.h to newest version Wolfram Sang
2012-12-11  9:24   ` Sascha Hauer
2012-12-11 15:17     ` Wolfram Sang
2012-12-10  8:14 ` [PATCH 04/10] devfs & mtd: add MEMERASE ioctl support Wolfram Sang
2012-12-10  8:14 ` [PATCH 05/10] mtd: utils: apply macros for message printouts Wolfram Sang
2012-12-10  8:14 ` [PATCH 06/10] lib: add ubiutils-common Wolfram Sang
2012-12-11  9:35   ` Sascha Hauer
2012-12-11 19:17     ` Wolfram Sang
2012-12-12  9:08       ` Sascha Hauer
2012-12-10  8:14 ` [PATCH 07/10] lib: add libscan Wolfram Sang
2012-12-10  8:14 ` [PATCH 08/10] lib: add libubigen Wolfram Sang
2012-12-10  8:14 ` [PATCH 09/10] lib: add barebox version of libmtd Wolfram Sang
2012-12-10  8:14 ` [PATCH 10/10] commands: add ubiformat Wolfram Sang
2012-12-11  9:57   ` Sascha Hauer

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