Skip to contentSkip to conversation

UBI command support v3

PATCH New Kyungmin Park 2 participants 5 messages Oct 28, 2008 – Nov 2, 2008

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 UBI command support v3

It supports basic operation such as create, remove, read, and write.

---

common/Makefile +1 -0
index f00cbd9..b02a541 100644
@@ -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
common/cmd_ubi.c new file +515 -0

515 lines not on this page · raw message

include/exports.h +1 -0
index 6377875..0620e9e 100644
@@ -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
include/jffs2/load_kernel.h +5 -0
index 551fd0c..e9b7d6e 100644
@@ -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 */
lib_generic/vsprintf.c +23 -0
index 6e903db..767dde1 100644
@@ -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)
 {
#1 lore raw

PATCH 1/1 UBI command support v3

2008/10/28 Kyungmin Park <[email protected]>:

Quoted 3 lines

It supports basic operation such as create, remove, read, and write.

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

#2 lore raw

PATCH 1/1 UBI command support v3

Hi,

Quoted 9 lines · Magnus Lilja

2008/10/28 Kyungmin Park <[email protected]>:

Quoted 3 lines

It supports basic operation such as create, remove, read, and write.

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

#3 lore raw

PATCH 1/1 UBI command support v3

In reply to Kyungmin Park

Dear Kyungmin Park,

Some more comments.

2008/10/28 Kyungmin Park <[email protected]>:

Quoted 80 lines

It supports basic operation such as create, remove, read, and write.

---

common/cmd_ubi.c new file +71 -0
new file mode 100644
index 0000000..8c46cca
+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) {

common/cmd_ubi.c line 384

Quoted 10 lines
common/cmd_ubi.c new file +10 -0
+                       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.

Quoted 98 lines
common/cmd_ubi.c new file +98 -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--;

common/cmd_ubi.c line 492

Quoted 10 lines
common/cmd_ubi.c new file +10 -0
+               }
+
+               /* 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

#4 lore raw

PATCH 1/1 UBI command support v3

Quoted 90 lines · Magnus Lilja

Dear Kyungmin Park,

Some more comments.

2008/10/28 Kyungmin Park <[email protected]>:

Quoted 85 lines

It supports basic operation such as create, remove, read, and write.

---

common/cmd_ubi.c new file +76 -0
new file mode 100644
index 0000000..8c46cca
+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;
Quoted 8 lines

common/cmd_ubi.c line 384

Quoted 5 lines
common/cmd_ubi.c new file +5 -0
+               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

Quoted 104 lines
Quoted 104 lines
common/cmd_ubi.c new file +103 -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);
Quoted 8 lines

common/cmd_ubi.c line 492

Quoted 5 lines
common/cmd_ubi.c new file +5 -0
+                       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.

Quoted 1 line

do_ubi()-like functions return 0 upon success and non-zero otherwise.

Agreed

Thank you,
Kyungmin Park