* [U-Boot] [PATCH] [UBI] UBI command support v3
@ 2008-10-28 7:59 Kyungmin Park
2008-10-31 16:19 ` Magnus Lilja
2008-11-02 21:01 ` Magnus Lilja
0 siblings, 2 replies; 5+ messages in thread
From: Kyungmin Park @ 2008-10-28 7:59 UTC (permalink / raw)
To: u-boot
It supports basic operation such as create, remove, read, and write.
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
diff --git a/common/Makefile b/common/Makefile
index f00cbd9..b02a541 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -139,6 +139,7 @@ COBJS-$(CONFIG_CMD_SETEXPR) += cmd_setexpr.o
COBJS-$(CONFIG_CMD_SPI) += cmd_spi.o
COBJS-$(CONFIG_CMD_STRINGS) += cmd_strings.o
COBJS-$(CONFIG_CMD_TERMINAL) += cmd_terminal.o
+COBJS-$(CONFIG_CMD_UBI) += cmd_ubi.o
COBJS-$(CONFIG_CMD_UNIVERSE) += cmd_universe.o
ifdef CONFIG_CMD_USB
COBJS-y += cmd_usb.o
diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
new file mode 100644
index 0000000..8c46cca
--- /dev/null
+++ b/common/cmd_ubi.c
@@ -0,0 +1,515 @@
+/*
+ * Unsorted Block Image commands
+ *
+ * Copyright (C) 2008 Samsung Electronics
+ * Kyungmin Park <kyungmin.park@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <exports.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <ubi_uboot.h>
+#include <asm/errno.h>
+
+/* Private own data */
+static struct ubi_device *ubi;
+static int ubi_initialized;
+
+static void ubi_dump_vol_info(const struct ubi_volume *vol)
+{
+ ubi_msg("volume information dump:");
+ ubi_msg("vol_id %d", vol->vol_id);
+ ubi_msg("reserved_pebs %d", vol->reserved_pebs);
+ ubi_msg("alignment %d", vol->alignment);
+ ubi_msg("data_pad %d", vol->data_pad);
+ ubi_msg("vol_type %d", vol->vol_type);
+ ubi_msg("name_len %d", vol->name_len);
+ ubi_msg("usable_leb_size %d", vol->usable_leb_size);
+ ubi_msg("used_ebs %d", vol->used_ebs);
+ ubi_msg("used_bytes %lld", vol->used_bytes);
+ ubi_msg("last_eb_bytes %d", vol->last_eb_bytes);
+ ubi_msg("corrupted %d", vol->corrupted);
+ ubi_msg("upd_marker %d", vol->upd_marker);
+
+ if (vol->name_len <= UBI_VOL_NAME_MAX &&
+ strnlen(vol->name, vol->name_len + 1) == vol->name_len) {
+ ubi_msg("name %s", vol->name);
+ } else {
+ ubi_msg("the 1st 5 characters of the name: %c%c%c%c%c",
+ vol->name[0], vol->name[1], vol->name[2],
+ vol->name[3], vol->name[4]);
+ }
+ printf("\n");
+}
+
+static void display_volume_info(struct ubi_device *ubi)
+{
+ int i;
+
+ for (i = 0; i < (ubi->vtbl_slots + 1); i++) {
+ if (!ubi->volumes[i])
+ continue; /* Empty record */
+ ubi_dump_vol_info(ubi->volumes[i]);
+ }
+}
+
+static void display_ubi_info(struct ubi_device *ubi)
+{
+ ubi_msg("MTD device name: \"%s\"", ubi->mtd->name);
+ ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
+ ubi_msg("physical eraseblock size: %d bytes (%d KiB)",
+ ubi->peb_size, ubi->peb_size >> 10);
+ ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size);
+ ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
+ ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
+ ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size);
+ ubi_msg("VID header offset: %d (aligned %d)",
+ ubi->vid_hdr_offset, ubi->vid_hdr_aloffset);
+ ubi_msg("data offset: %d", ubi->leb_start);
+ ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
+ ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
+ ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
+ ubi_msg("number of user volumes: %d",
+ ubi->vol_count - UBI_INT_VOL_COUNT);
+ ubi_msg("available PEBs: %d", ubi->avail_pebs);
+ ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs);
+ ubi_msg("number of PEBs reserved for bad PEB handling: %d",
+ ubi->beb_rsvd_pebs);
+ ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
+}
+
+static int ubi_info(int layout)
+{
+ if (layout)
+ display_volume_info(ubi);
+ else
+ display_ubi_info(ubi);
+
+ return 0;
+}
+
+static int parse_num(size_t *num, const char *token)
+{
+ char *endp;
+ size_t n;
+
+ n = (size_t) ustrtoul(token, &endp, 0);
+ if (*endp)
+ return -EINVAL;
+
+ *num = n;
+ return 0;
+}
+
+static int verify_mkvol_req(const struct ubi_device *ubi,
+ const struct ubi_mkvol_req *req)
+{
+ int n, err = -EINVAL;
+
+ if (req->bytes < 0 || req->alignment < 0 || req->vol_type < 0 ||
+ req->name_len < 0)
+ goto bad;
+
+ if ((req->vol_id < 0 || req->vol_id >= ubi->vtbl_slots) &&
+ req->vol_id != UBI_VOL_NUM_AUTO)
+ goto bad;
+
+ if (req->alignment == 0)
+ goto bad;
+
+ if (req->bytes == 0)
+ goto bad;
+
+ if (req->vol_type != UBI_DYNAMIC_VOLUME &&
+ req->vol_type != UBI_STATIC_VOLUME)
+ goto bad;
+
+ if (req->alignment > ubi->leb_size)
+ goto bad;
+
+ n = req->alignment % ubi->min_io_size;
+ if (req->alignment != 1 && n)
+ goto bad;
+
+ if (req->name_len > UBI_VOL_NAME_MAX) {
+ err = -ENAMETOOLONG;
+ goto bad;
+ }
+
+ return 0;
+bad:
+ printf("bad volume creation request");
+ return err;
+}
+
+static int ubi_create_vol(char *volume, int size, int dynamic)
+{
+ struct ubi_mkvol_req req;
+ int err;
+
+ if (dynamic)
+ req.vol_type = UBI_DYNAMIC_VOLUME;
+ else
+ req.vol_type = UBI_STATIC_VOLUME;
+
+ req.vol_id = UBI_VOL_NUM_AUTO;
+ req.alignment = 1;
+ req.bytes = size;
+
+ strcpy(req.name, volume);
+ req.name_len = strlen(volume);
+ req.name[req.name_len] = '\0';
+ req.padding1 = 0;
+ /* It's duplicated at drivers/mtd/ubi/cdev.c */
+ err = verify_mkvol_req(ubi, &req);
+ if (err) {
+ printf("verify_mkvol_req failed %d\n", err);
+ return err;
+ }
+ printf("Creating %s volume %s of size %d\n",
+ dynamic ? "dynamic" : "static", volume, size);
+ /* Call real ubi create volume */
+ return ubi_create_volume(ubi, &req);
+}
+
+static int ubi_remove_vol(char *volume)
+{
+ int i, err, reserved_pebs;
+ int found = 0, vol_id = 0;
+ struct ubi_volume *vol;
+
+ for (i = 0; i < ubi->vtbl_slots; i++) {
+ vol = ubi->volumes[i];
+ if (vol && !strcmp(vol->name, volume)) {
+ printf("Volume %s found at valid %d\n", volume, i);
+ vol_id = i;
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ printf("%s volume not found\n", volume);
+ return -ENODEV;
+ }
+ printf("remove UBI volume %s (id %d)\n", vol->name, vol->vol_id);
+
+ if (ubi->ro_mode) {
+ printf("It's read-only mode\n");
+ err = -EROFS;
+ goto out_err;
+ }
+
+ err = ubi_change_vtbl_record(ubi, vol_id, NULL);
+ if (err) {
+ printf("Error changing Vol tabel record err=%x\n", err);
+ goto out_err;
+ }
+ reserved_pebs = vol->reserved_pebs;
+ for (i = 0; i < vol->reserved_pebs; i++) {
+ err = ubi_eba_unmap_leb(ubi, vol, i);
+ if (err)
+ goto out_err;
+ }
+
+ kfree(vol->eba_tbl);
+ ubi->volumes[vol_id]->eba_tbl = NULL;
+ ubi->volumes[vol_id] = NULL;
+
+ ubi->rsvd_pebs -= reserved_pebs;
+ ubi->avail_pebs += reserved_pebs;
+ i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
+ if (i > 0) {
+ i = ubi->avail_pebs >= i ? i : ubi->avail_pebs;
+ ubi->avail_pebs -= i;
+ ubi->rsvd_pebs += i;
+ ubi->beb_rsvd_pebs += i;
+ if (i > 0)
+ ubi_msg("reserve more %d PEBs", i);
+ }
+ ubi->vol_count -= 1;
+
+ return 0;
+out_err:
+ ubi_err("cannot remove volume %d, error %d", vol_id, err);
+ return err;
+}
+
+static int ubi_volume_write(char *volume, void *buf, size_t size)
+{
+ int i = 0, err = -1;
+ int rsvd_bytes = 0;
+ int found = 0;
+ struct ubi_volume *vol;
+
+ for (i = 0; i < ubi->vtbl_slots; i++) {
+ vol = ubi->volumes[i];
+ if (vol && !strcmp(vol->name, volume)) {
+ printf("Volume \"%s\" found with id %d\n", volume, i);
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ printf("%s voume not found\n", volume);
+ return 1;
+ }
+ rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad);
+ if (size < 0 || size > rsvd_bytes) {
+ printf("rsvd_bytes=%d vol->reserved_pebs=%d ubi->leb_size=%d\n",
+ rsvd_bytes, vol->reserved_pebs, ubi->leb_size);
+ printf("vol->data_pad=%d\n", vol->data_pad);
+ printf("Size > volume size !!\n");
+ return 1;
+ }
+
+ err = ubi_start_update(ubi, vol, size);
+ if (err < 0) {
+ printf("Cannot start volume update\n");
+ return err;
+ }
+
+ err = ubi_more_update_data(ubi, vol, buf, size);
+ if (err < 0) {
+ printf("Couldnt or partially wrote data \n");
+ return err;
+ }
+
+ if (err) {
+ size = err;
+
+ err = ubi_check_volume(ubi, vol->vol_id);
+ if (err < 0)
+ return err;
+
+ if (err) {
+ ubi_warn("volume %d on UBI device %d is corrupted",
+ vol->vol_id, ubi->ubi_num);
+ vol->corrupted = 1;
+ }
+
+ vol->checked = 1;
+ ubi_gluebi_updated(vol);
+ }
+
+ return 0;
+}
+
+static int ubi_volume_read(char *volume, char *buf, size_t size)
+{
+ int err, lnum, off, len, tbuf_size, i = 0;
+ size_t count_save = size;
+ void *tbuf;
+ unsigned long long tmp;
+ struct ubi_volume *vol = NULL;
+ loff_t offp = 0;
+
+ for (i = 0; i < ubi->vtbl_slots; i++) {
+ vol = ubi->volumes[i];
+ if (vol && !strcmp(vol->name, volume)) {
+ printf("Volume %s found at volume id %d\n",
+ volume, vol->vol_id);
+ break;
+ }
+ }
+ if (i == ubi->vtbl_slots) {
+ printf("%s voume not found\n", volume);
+ return 0;
+ }
+
+ printf("read %i bytes from volume %d to %x(buf address)\n",
+ (int) size, vol->vol_id, (unsigned)buf);
+
+ if (vol->updating) {
+ printf("updating");
+ return -EBUSY;
+ }
+ if (vol->upd_marker) {
+ printf("damaged volume, update marker is set");
+ return -EBADF;
+ }
+ if (offp == vol->used_bytes)
+ return 0;
+
+ if (size == 0) {
+ printf("Read [%lu] bytes\n", (unsigned long) vol->used_bytes);
+ size = vol->used_bytes;
+ }
+
+ if (vol->corrupted)
+ printf("read from corrupted volume %d", vol->vol_id);
+ if (offp + size > vol->used_bytes)
+ count_save = size = vol->used_bytes - offp;
+
+ tbuf_size = vol->usable_leb_size;
+ if (size < tbuf_size)
+ tbuf_size = ALIGN(size, ubi->min_io_size);
+ tbuf = malloc(tbuf_size);
+ if (!tbuf) {
+ printf("NO MEM\n");
+ return -ENOMEM;
+ }
+ len = size > tbuf_size ? tbuf_size : size;
+
+ tmp = offp;
+ off = do_div(tmp, vol->usable_leb_size);
+ lnum = tmp;
+ printf("off=%d lnum=%d\n", off, lnum);
+ do {
+ if (off + len >= vol->usable_leb_size)
+ len = vol->usable_leb_size - off;
+
+ err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
+ if (err) {
+ printf("read err %x\n", err);
+ break;
+ }
+ off += len;
+ if (off == vol->usable_leb_size) {
+ lnum += 1;
+ off -= vol->usable_leb_size;
+ }
+
+ size -= len;
+ offp += len;
+
+ printf("buf = %x\n", (unsigned)buf);
+ memcpy(buf, tbuf, len);
+ printf("buf[0] = %x\n", buf[0]);
+
+ buf += len;
+ len = size > tbuf_size ? tbuf_size : size;
+ } while (size);
+
+ free(tbuf);
+ return err ? err : count_save - size;
+}
+
+static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ size_t size = 0;
+ ulong addr = 0;
+ int err = 0;
+
+ if (!ubi_initialized) {
+ err = ubi_board_scan();
+ if (err) {
+ printf("UBI init error %d\n", err);
+ return err;
+ }
+ ubi = ubi_devices[0];
+ ubi_initialized = 1;
+ }
+
+ if (argc < 2) {
+ printf("Usage:\n%s\n", cmdtp->usage);
+ return 1;
+ }
+ if (strcmp(argv[1], "info") == 0) {
+ int layout = 0;
+ if (argc > 2 && !strncmp(argv[2], "l", 1))
+ layout = 1;
+ return ubi_info(layout);
+ }
+ if (strncmp(argv[1], "create", 6) == 0) {
+ int dynamic = 1; /* default: dynamic volume */
+
+ /* Use maximum available size */
+ size = 0;
+
+ /* E.g., create volume size type */
+ if (argc == 5) {
+ if (strncmp(argv[4], "s", 1) == 0)
+ dynamic = 0;
+ else if (strncmp(argv[4], "d", 1) != 0) {
+ printf("Incorrect type\n");
+ return 1;
+ }
+ argc--;
+ }
+ /* E.g., create volume size */
+ if (argc == 4) {
+ err = parse_num(&size, argv[3]);
+ if (err) {
+ printf("Incorrect type\n");
+ return err;
+ }
+ argc--;
+ }
+ /* Use maximum available size */
+ if (!size)
+ size = ubi->avail_pebs * ubi->leb_size;
+ /* E.g., create volume */
+ if (argc == 3)
+ return ubi_create_vol(argv[2], size, dynamic);
+ }
+ if (strncmp(argv[1], "remove", 6) == 0) {
+ /* E.g., remove volume */
+ if (argc == 3)
+ return ubi_remove_vol(argv[2]);
+ }
+ if (strncmp(argv[1], "write", 5) == 0) {
+ if (argc < 5) {
+ printf("Please see usage\n");
+ return 1;
+ }
+
+ addr = simple_strtoul(argv[2], NULL, 16);
+ err = parse_num(&size, argv[4]);
+ if (err) {
+ printf("Please see usage\n");
+ return err;
+ }
+
+ return ubi_volume_write(argv[3], (void *)addr, size);
+ }
+ if (strncmp(argv[1], "read", 4) == 0) {
+ size = 0;
+
+ /* E.g., read volume size */
+ if (argc == 5) {
+ err = parse_num(&size, argv[4]);
+ if (err) {
+ printf("Please see usage\n");
+ return err;
+ }
+ argc--;
+ }
+
+ /* E.g., read volume */
+ if (argc == 4) {
+ addr = simple_strtoul(argv[2], NULL, 16);
+ argc--;
+ }
+
+ if (argc == 3)
+ return ubi_volume_read(argv[3], (char *)addr, size);
+ }
+
+ printf("Please see usage\n");
+ return -1;
+}
+
+U_BOOT_CMD(ubi, 6, 1, do_ubi,
+ "ubi - ubi commands\n",
+ "info [l[ayout]]"
+ " - Display volume and ubi layout information\n"
+ "ubi create[vol] volume [size] [type]"
+ " - create volume name with size\n"
+ "ubi write[vol] address volume size"
+ " - Write volume from address with size\n"
+ "ubi read[vol] address volume [size]"
+ " - Read volume to address with size\n"
+ "ubi remove[vol] volume"
+ " - Remove volume\n"
+ "[Legends]\n"
+ " volume: charater name\n"
+ " size: KiB, MiB, GiB, and bytes\n"
+ " type: s[tatic] or d[ynamic] (default=dynamic)\n"
+);
diff --git a/include/exports.h b/include/exports.h
index 6377875..0620e9e 100644
--- a/include/exports.h
+++ b/include/exports.h
@@ -25,6 +25,7 @@ char *getenv (char *name);
int setenv (char *varname, char *varvalue);
long simple_strtol(const char *cp,char **endp,unsigned int base);
int strcmp(const char * cs,const char * ct);
+int ustrtoul(const char *cp, char **endp, unsigned int base);
#ifdef CONFIG_HAS_UID
void forceenv (char *varname, char *varvalue);
#endif
diff --git a/include/jffs2/load_kernel.h b/include/jffs2/load_kernel.h
index 551fd0c..e9b7d6e 100644
--- a/include/jffs2/load_kernel.h
+++ b/include/jffs2/load_kernel.h
@@ -73,4 +73,9 @@ struct mtdids {
#define putLabeledWord(x, y) printf("%s %08x\n", x, (unsigned int)y)
#define led_blink(x, y, z, a)
+/* common/cmd_jffs2.c */
+extern int mtdparts_init(void);
+extern int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part);
+
#endif /* load_kernel_h */
diff --git a/lib_generic/vsprintf.c b/lib_generic/vsprintf.c
index 6e903db..767dde1 100644
--- a/lib_generic/vsprintf.c
+++ b/lib_generic/vsprintf.c
@@ -55,6 +55,29 @@ long simple_strtol(const char *cp,char **endp,unsigned int base)
return simple_strtoul(cp,endp,base);
}
+int ustrtoul(const char *cp, char **endp, unsigned int base)
+{
+ unsigned long result = simple_strtoul(cp, endp, base);
+ switch (**endp) {
+ case 'G' :
+ result *= 1024;
+ /* fall through */
+ case 'M':
+ result *= 1024;
+ /* fall through */
+ case 'K':
+ case 'k':
+ result *= 1024;
+ if ((*endp)[1] == 'i') {
+ if ((*endp)[2] == 'B')
+ (*endp) += 3;
+ else
+ (*endp) += 2;
+ }
+ }
+ return result;
+}
+
#ifdef CONFIG_SYS_64BIT_STRTOUL
unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base)
{
^ permalink raw reply related [flat|nested] 5+ messages in thread* [U-Boot] [PATCH] [UBI] UBI command support v3
2008-10-28 7:59 [U-Boot] [PATCH] [UBI] UBI command support v3 Kyungmin Park
@ 2008-10-31 16:19 ` Magnus Lilja
2008-11-01 2:04 ` Kyungmin Park
2008-11-02 21:01 ` Magnus Lilja
1 sibling, 1 reply; 5+ messages in thread
From: Magnus Lilja @ 2008-10-31 16:19 UTC (permalink / raw)
To: u-boot
2008/10/28 Kyungmin Park <kmpark@infradead.org>:
> It supports basic operation such as create, remove, read, and write.
>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Would it be possible to have the U-boot environment in the part of the
flash managed by UBI? I suppose it involves creating a U-Boot
Environment volume in UBI and then using ubi function to read/update
that volume.
Regards, Magnus
^ permalink raw reply [flat|nested] 5+ messages in thread
* [U-Boot] [PATCH] [UBI] UBI command support v3
2008-10-31 16:19 ` Magnus Lilja
@ 2008-11-01 2:04 ` Kyungmin Park
0 siblings, 0 replies; 5+ messages in thread
From: Kyungmin Park @ 2008-11-01 2:04 UTC (permalink / raw)
To: u-boot
Hi,
On Sat, Nov 1, 2008 at 1:19 AM, Magnus Lilja <lilja.magnus@gmail.com> wrote:
> 2008/10/28 Kyungmin Park <kmpark@infradead.org>:
>> It supports basic operation such as create, remove, read, and write.
>>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>
> Would it be possible to have the U-boot environment in the part of the
> flash managed by UBI? I suppose it involves creating a U-Boot
> Environment volume in UBI and then using ubi function to read/update
> that volume.
Principally yes. But not yet used
This implementation only used kernel side UBI, rootfs, user data area.
However the UBI supports multiple UBI devices. It cant combine several
UBI device such as params UBI, kernel UBI, and rootfs UBI. Of course
it depends on your configurations
I will list the TODO list this one.
Thank you,
Kyungmin Park
^ permalink raw reply [flat|nested] 5+ messages in thread
* [U-Boot] [PATCH] [UBI] UBI command support v3
2008-10-28 7:59 [U-Boot] [PATCH] [UBI] UBI command support v3 Kyungmin Park
2008-10-31 16:19 ` Magnus Lilja
@ 2008-11-02 21:01 ` Magnus Lilja
2008-11-02 23:39 ` Kyungmin Park
1 sibling, 1 reply; 5+ messages in thread
From: Magnus Lilja @ 2008-11-02 21:01 UTC (permalink / raw)
To: u-boot
Dear Kyungmin Park,
Some more comments.
2008/10/28 Kyungmin Park <kmpark@infradead.org>:
> It supports basic operation such as create, remove, read, and write.
>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
> diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
> new file mode 100644
> index 0000000..8c46cca
> --- /dev/null
> +++ b/common/cmd_ubi.c
> +static int ubi_volume_read(char *volume, char *buf, size_t size)
> +{
> + int err, lnum, off, len, tbuf_size, i = 0;
> + size_t count_save = size;
> + void *tbuf;
> + unsigned long long tmp;
> + struct ubi_volume *vol = NULL;
> + loff_t offp = 0;
> +
> + for (i = 0; i < ubi->vtbl_slots; i++) {
> + vol = ubi->volumes[i];
> + if (vol && !strcmp(vol->name, volume)) {
> + printf("Volume %s found at volume id %d\n",
> + volume, vol->vol_id);
> + break;
> + }
> + }
> + if (i == ubi->vtbl_slots) {
> + printf("%s voume not found\n", volume);
> + return 0;
> + }
> +
> + printf("read %i bytes from volume %d to %x(buf address)\n",
> + (int) size, vol->vol_id, (unsigned)buf);
> +
> + if (vol->updating) {
> + printf("updating");
> + return -EBUSY;
> + }
> + if (vol->upd_marker) {
> + printf("damaged volume, update marker is set");
> + return -EBADF;
> + }
> + if (offp == vol->used_bytes)
> + return 0;
> +
> + if (size == 0) {
> + printf("Read [%lu] bytes\n", (unsigned long) vol->used_bytes);
> + size = vol->used_bytes;
> + }
> +
> + if (vol->corrupted)
> + printf("read from corrupted volume %d", vol->vol_id);
> + if (offp + size > vol->used_bytes)
> + count_save = size = vol->used_bytes - offp;
> +
> + tbuf_size = vol->usable_leb_size;
> + if (size < tbuf_size)
> + tbuf_size = ALIGN(size, ubi->min_io_size);
> + tbuf = malloc(tbuf_size);
> + if (!tbuf) {
> + printf("NO MEM\n");
> + return -ENOMEM;
> + }
> + len = size > tbuf_size ? tbuf_size : size;
> +
> + tmp = offp;
> + off = do_div(tmp, vol->usable_leb_size);
> + lnum = tmp;
> + printf("off=%d lnum=%d\n", off, lnum);
> + do {
> + if (off + len >= vol->usable_leb_size)
> + len = vol->usable_leb_size - off;
> +
> + err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
> + if (err) {
> + printf("read err %x\n", err);
> + break;
> + }
> + off += len;
> + if (off == vol->usable_leb_size) {
> + lnum += 1;
> + off -= vol->usable_leb_size;
> + }
> +
> + size -= len;
> + offp += len;
> +
> + printf("buf = %x\n", (unsigned)buf);
> + memcpy(buf, tbuf, len);
> + printf("buf[0] = %x\n", buf[0]);
The printf()'s before and after memcpy() looks like stuff used during
development of this file and they should be removed.
> +
> + buf += len;
> + len = size > tbuf_size ? tbuf_size : size;
> + } while (size);
> +
> + free(tbuf);
> + return err ? err : count_save - size;
> +}
> +
> +static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
> +{
> + size_t size = 0;
> + ulong addr = 0;
> + int err = 0;
> +
> + if (!ubi_initialized) {
> + err = ubi_board_scan();
> + if (err) {
> + printf("UBI init error %d\n", err);
> + return err;
> + }
> + ubi = ubi_devices[0];
> + ubi_initialized = 1;
> + }
> +
> + if (argc < 2) {
> + printf("Usage:\n%s\n", cmdtp->usage);
> + return 1;
> + }
> + if (strcmp(argv[1], "info") == 0) {
> + int layout = 0;
> + if (argc > 2 && !strncmp(argv[2], "l", 1))
> + layout = 1;
> + return ubi_info(layout);
> + }
> + if (strncmp(argv[1], "create", 6) == 0) {
> + int dynamic = 1; /* default: dynamic volume */
> +
> + /* Use maximum available size */
> + size = 0;
> +
> + /* E.g., create volume size type */
> + if (argc == 5) {
> + if (strncmp(argv[4], "s", 1) == 0)
> + dynamic = 0;
> + else if (strncmp(argv[4], "d", 1) != 0) {
> + printf("Incorrect type\n");
> + return 1;
> + }
> + argc--;
> + }
> + /* E.g., create volume size */
> + if (argc == 4) {
> + err = parse_num(&size, argv[3]);
> + if (err) {
> + printf("Incorrect type\n");
> + return err;
> + }
> + argc--;
> + }
> + /* Use maximum available size */
> + if (!size)
> + size = ubi->avail_pebs * ubi->leb_size;
> + /* E.g., create volume */
> + if (argc == 3)
> + return ubi_create_vol(argv[2], size, dynamic);
> + }
> + if (strncmp(argv[1], "remove", 6) == 0) {
> + /* E.g., remove volume */
> + if (argc == 3)
> + return ubi_remove_vol(argv[2]);
> + }
> + if (strncmp(argv[1], "write", 5) == 0) {
> + if (argc < 5) {
> + printf("Please see usage\n");
> + return 1;
> + }
> +
> + addr = simple_strtoul(argv[2], NULL, 16);
> + err = parse_num(&size, argv[4]);
> + if (err) {
> + printf("Please see usage\n");
> + return err;
> + }
> +
> + return ubi_volume_write(argv[3], (void *)addr, size);
> + }
> + if (strncmp(argv[1], "read", 4) == 0) {
> + size = 0;
> +
> + /* E.g., read volume size */
> + if (argc == 5) {
> + err = parse_num(&size, argv[4]);
> + if (err) {
> + printf("Please see usage\n");
> + return err;
> + }
> + argc--;
> + }
> +
> + /* E.g., read volume */
> + if (argc == 4) {
> + addr = simple_strtoul(argv[2], NULL, 16);
> + argc--;
> + }
> +
> + if (argc == 3)
> + return ubi_volume_read(argv[3], (char *)addr, size);
It seems to me that ubi_volume_read() can return 0 when there is an
error, so it may not be correct to use that return value here. AFAIK
do_ubi()-like functions return 0 upon success and non-zero otherwise.
Regards, Magnus
^ permalink raw reply [flat|nested] 5+ messages in thread* [U-Boot] [PATCH] [UBI] UBI command support v3
2008-11-02 21:01 ` Magnus Lilja
@ 2008-11-02 23:39 ` Kyungmin Park
0 siblings, 0 replies; 5+ messages in thread
From: Kyungmin Park @ 2008-11-02 23:39 UTC (permalink / raw)
To: u-boot
On Mon, Nov 3, 2008 at 6:01 AM, Magnus Lilja <lilja.magnus@gmail.com> wrote:
> Dear Kyungmin Park,
>
> Some more comments.
>
> 2008/10/28 Kyungmin Park <kmpark@infradead.org>:
>> It supports basic operation such as create, remove, read, and write.
>>
>> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
>> ---
>> diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
>> new file mode 100644
>> index 0000000..8c46cca
>> --- /dev/null
>> +++ b/common/cmd_ubi.c
>> +static int ubi_volume_read(char *volume, char *buf, size_t size)
>> +{
>> + int err, lnum, off, len, tbuf_size, i = 0;
>> + size_t count_save = size;
>> + void *tbuf;
>> + unsigned long long tmp;
>> + struct ubi_volume *vol = NULL;
>> + loff_t offp = 0;
>> +
>> + for (i = 0; i < ubi->vtbl_slots; i++) {
>> + vol = ubi->volumes[i];
>> + if (vol && !strcmp(vol->name, volume)) {
>> + printf("Volume %s found at volume id %d\n",
>> + volume, vol->vol_id);
>> + break;
>> + }
>> + }
>> + if (i == ubi->vtbl_slots) {
>> + printf("%s voume not found\n", volume);
>> + return 0;
>> + }
>> +
>> + printf("read %i bytes from volume %d to %x(buf address)\n",
>> + (int) size, vol->vol_id, (unsigned)buf);
>> +
>> + if (vol->updating) {
>> + printf("updating");
>> + return -EBUSY;
>> + }
>> + if (vol->upd_marker) {
>> + printf("damaged volume, update marker is set");
>> + return -EBADF;
>> + }
>> + if (offp == vol->used_bytes)
>> + return 0;
>> +
>> + if (size == 0) {
>> + printf("Read [%lu] bytes\n", (unsigned long) vol->used_bytes);
>> + size = vol->used_bytes;
>> + }
>> +
>> + if (vol->corrupted)
>> + printf("read from corrupted volume %d", vol->vol_id);
>> + if (offp + size > vol->used_bytes)
>> + count_save = size = vol->used_bytes - offp;
>> +
>> + tbuf_size = vol->usable_leb_size;
>> + if (size < tbuf_size)
>> + tbuf_size = ALIGN(size, ubi->min_io_size);
>> + tbuf = malloc(tbuf_size);
>> + if (!tbuf) {
>> + printf("NO MEM\n");
>> + return -ENOMEM;
>> + }
>> + len = size > tbuf_size ? tbuf_size : size;
>> +
>> + tmp = offp;
>> + off = do_div(tmp, vol->usable_leb_size);
>> + lnum = tmp;
>> + printf("off=%d lnum=%d\n", off, lnum);
>> + do {
>> + if (off + len >= vol->usable_leb_size)
>> + len = vol->usable_leb_size - off;
>> +
>> + err = ubi_eba_read_leb(ubi, vol, lnum, tbuf, off, len, 0);
>> + if (err) {
>> + printf("read err %x\n", err);
>> + break;
>> + }
>> + off += len;
>> + if (off == vol->usable_leb_size) {
>> + lnum += 1;
>> + off -= vol->usable_leb_size;
>> + }
>> +
>> + size -= len;
>> + offp += len;
>> +
>> + printf("buf = %x\n", (unsigned)buf);
>> + memcpy(buf, tbuf, len);
>> + printf("buf[0] = %x\n", buf[0]);
>
> The printf()'s before and after memcpy() looks like stuff used during
> development of this file and they should be removed.
Yes, correct, I'll remove it
>
>> +
>> + buf += len;
>> + len = size > tbuf_size ? tbuf_size : size;
>> + } while (size);
>> +
>> + free(tbuf);
>> + return err ? err : count_save - size;
>> +}
>> +
>> +static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
>> +{
>> + size_t size = 0;
>> + ulong addr = 0;
>> + int err = 0;
>> +
>> + if (!ubi_initialized) {
>> + err = ubi_board_scan();
>> + if (err) {
>> + printf("UBI init error %d\n", err);
>> + return err;
>> + }
>> + ubi = ubi_devices[0];
>> + ubi_initialized = 1;
>> + }
>> +
>> + if (argc < 2) {
>> + printf("Usage:\n%s\n", cmdtp->usage);
>> + return 1;
>> + }
>> + if (strcmp(argv[1], "info") == 0) {
>> + int layout = 0;
>> + if (argc > 2 && !strncmp(argv[2], "l", 1))
>> + layout = 1;
>> + return ubi_info(layout);
>> + }
>> + if (strncmp(argv[1], "create", 6) == 0) {
>> + int dynamic = 1; /* default: dynamic volume */
>> +
>> + /* Use maximum available size */
>> + size = 0;
>> +
>> + /* E.g., create volume size type */
>> + if (argc == 5) {
>> + if (strncmp(argv[4], "s", 1) == 0)
>> + dynamic = 0;
>> + else if (strncmp(argv[4], "d", 1) != 0) {
>> + printf("Incorrect type\n");
>> + return 1;
>> + }
>> + argc--;
>> + }
>> + /* E.g., create volume size */
>> + if (argc == 4) {
>> + err = parse_num(&size, argv[3]);
>> + if (err) {
>> + printf("Incorrect type\n");
>> + return err;
>> + }
>> + argc--;
>> + }
>> + /* Use maximum available size */
>> + if (!size)
>> + size = ubi->avail_pebs * ubi->leb_size;
>> + /* E.g., create volume */
>> + if (argc == 3)
>> + return ubi_create_vol(argv[2], size, dynamic);
>> + }
>> + if (strncmp(argv[1], "remove", 6) == 0) {
>> + /* E.g., remove volume */
>> + if (argc == 3)
>> + return ubi_remove_vol(argv[2]);
>> + }
>> + if (strncmp(argv[1], "write", 5) == 0) {
>> + if (argc < 5) {
>> + printf("Please see usage\n");
>> + return 1;
>> + }
>> +
>> + addr = simple_strtoul(argv[2], NULL, 16);
>> + err = parse_num(&size, argv[4]);
>> + if (err) {
>> + printf("Please see usage\n");
>> + return err;
>> + }
>> +
>> + return ubi_volume_write(argv[3], (void *)addr, size);
>> + }
>> + if (strncmp(argv[1], "read", 4) == 0) {
>> + size = 0;
>> +
>> + /* E.g., read volume size */
>> + if (argc == 5) {
>> + err = parse_num(&size, argv[4]);
>> + if (err) {
>> + printf("Please see usage\n");
>> + return err;
>> + }
>> + argc--;
>> + }
>> +
>> + /* E.g., read volume */
>> + if (argc == 4) {
>> + addr = simple_strtoul(argv[2], NULL, 16);
>> + argc--;
>> + }
>> +
>> + if (argc == 3)
>> + return ubi_volume_read(argv[3], (char *)addr, size);
>
> It seems to me that ubi_volume_read() can return 0 when there is an
> error, so it may not be correct to use that return value here. AFAIK
Really? I will check the return value.
> do_ubi()-like functions return 0 upon success and non-zero otherwise.
Agreed
Thank you,
Kyungmin Park
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2008-11-02 23:39 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-10-28 7:59 [U-Boot] [PATCH] [UBI] UBI command support v3 Kyungmin Park
2008-10-31 16:19 ` Magnus Lilja
2008-11-01 2:04 ` Kyungmin Park
2008-11-02 21:01 ` Magnus Lilja
2008-11-02 23:39 ` Kyungmin Park
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox