[U-Boot] [PATCH] [UBI] UBI command support v3

Magnus Lilja lilja.magnus at gmail.com
Sun Nov 2 22:01:09 CET 2008


Dear Kyungmin Park,

Some more comments.

2008/10/28 Kyungmin Park <kmpark at infradead.org>:
> It supports basic operation such as create, remove, read, and write.
>
> Signed-off-by: Kyungmin Park <kyungmin.park at 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


More information about the U-Boot mailing list