From dd7185f1764fb8ed93940c2ac44cd6c400ebae7e Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 4 Sep 2013 15:16:58 +0100 Subject: cmd_ubi: use int64_t volume size for 'ubi create' int64_t matches the bytes field in struct ubi_mkvol_req to which the size is assigned. With the prior signed 32 bit integer, volumes were restricted to being less than 2GiB in size. Signed-off-by: Paul Burton Acked-by: Stefan Roese --- common/cmd_ubi.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'common/cmd_ubi.c') diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c index 5ba4feb48..f11cb61f1 100644 --- a/common/cmd_ubi.c +++ b/common/cmd_ubi.c @@ -167,7 +167,7 @@ bad: return err; } -static int ubi_create_vol(char *volume, int size, int dynamic) +static int ubi_create_vol(char *volume, int64_t size, int dynamic) { struct ubi_mkvol_req req; int err; @@ -191,7 +191,7 @@ static int ubi_create_vol(char *volume, int size, int dynamic) printf("verify_mkvol_req failed %d\n", err); return err; } - printf("Creating %s volume %s of size %d\n", + printf("Creating %s volume %s of size %lld\n", dynamic ? "dynamic" : "static", volume, size); /* Call real ubi create volume */ return ubi_create_volume(ubi, &req); @@ -498,7 +498,7 @@ int ubi_part(char *part_name, const char *vid_header_offset) static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - size_t size = 0; + int64_t size = 0; ulong addr = 0; if (argc < 2) @@ -558,13 +558,13 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } /* E.g., create volume size */ if (argc == 4) { - size = simple_strtoul(argv[3], NULL, 16); + size = simple_strtoull(argv[3], NULL, 16); argc--; } /* Use maximum available size */ if (!size) { - size = ubi->avail_pebs * ubi->leb_size; - printf("No size specified -> Using max size (%u)\n", size); + size = (int64_t)ubi->avail_pebs * ubi->leb_size; + printf("No size specified -> Using max size (%lld)\n", size); } /* E.g., create volume */ if (argc == 3) @@ -590,7 +590,7 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ret = ubi_volume_write(argv[3], (void *)addr, size); if (!ret) { - printf("%d bytes written to volume %s\n", size, + printf("%lld bytes written to volume %s\n", size, argv[3]); } @@ -613,7 +613,7 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) } if (argc == 3) { - printf("Read %d bytes from volume %s to %lx\n", size, + printf("Read %lld bytes from volume %s to %lx\n", size, argv[3], addr); return ubi_volume_read(argv[3], (char *)addr, size); -- cgit v1.2.3-70-g09d2 From cc734f5ab26134e5e8d57c34edc257c89ac5b1d2 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Wed, 4 Sep 2013 15:16:59 +0100 Subject: cmd_ubi: add write.part command, to write a volume in multiple parts This allows you to write data to an UBI volume when the amount of memory available to write that data from is less than the total size of the data. For example, you may split a root filesystem UBIFS image into parts, provide the total size of the image to the first write.part command and then use multiple write.part commands to write the subsequent parts of the volume. This results in a sequence of commands akin to: ext4load mmc 0:1 0x80000000 rootfs.ubifs.0 ubi write.part 0x80000000 root 0x08000000 0x18000000 ext4load mmc 0:1 0x80000000 rootfs.ubifs.1 ubi write.part 0x80000000 root 0x08000000 ext4load mmc 0:1 0x80000000 rootfs.ubifs.2 ubi write.part 0x80000000 root 0x08000000 This would write 384MiB of data to the UBI volume 'root' whilst only requiring 128MiB of said data to be held in memory at a time. Signed-off-by: Paul Burton Acked-by: Stefan Roese --- common/cmd_ubi.c | 63 ++++++++++++++++++++++++++++++++++++++++++-------------- doc/README.ubi | 3 +++ 2 files changed, 51 insertions(+), 15 deletions(-) (limited to 'common/cmd_ubi.c') diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c index f11cb61f1..122ba7e17 100644 --- a/common/cmd_ubi.c +++ b/common/cmd_ubi.c @@ -266,28 +266,15 @@ out_err: return err; } -int ubi_volume_write(char *volume, void *buf, size_t size) +int ubi_volume_continue_write(char *volume, void *buf, size_t size) { int err = 1; - int rsvd_bytes = 0; struct ubi_volume *vol; vol = ubi_find_volume(volume); if (vol == NULL) return ENODEV; - rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); - if (size < 0 || size > rsvd_bytes) { - printf("size > volume size! Aborting!\n"); - return EINVAL; - } - - 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"); @@ -314,6 +301,37 @@ int ubi_volume_write(char *volume, void *buf, size_t size) return 0; } +int ubi_volume_begin_write(char *volume, void *buf, size_t size, + size_t full_size) +{ + int err = 1; + int rsvd_bytes = 0; + struct ubi_volume *vol; + + vol = ubi_find_volume(volume); + if (vol == NULL) + return ENODEV; + + rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad); + if (size < 0 || size > rsvd_bytes) { + printf("size > volume size! Aborting!\n"); + return EINVAL; + } + + err = ubi_start_update(ubi, vol, full_size); + if (err < 0) { + printf("Cannot start volume update\n"); + return -err; + } + + return ubi_volume_continue_write(volume, buf, size); +} + +int ubi_volume_write(char *volume, void *buf, size_t size) +{ + return ubi_volume_begin_write(volume, buf, size, size); +} + int ubi_volume_read(char *volume, char *buf, size_t size) { int err, lnum, off, len, tbuf_size; @@ -588,7 +606,20 @@ static int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) addr = simple_strtoul(argv[2], NULL, 16); size = simple_strtoul(argv[4], NULL, 16); - ret = ubi_volume_write(argv[3], (void *)addr, size); + if (strlen(argv[1]) == 10 && + strncmp(argv[1] + 5, ".part", 5) == 0) { + if (argc < 6) { + ret = ubi_volume_continue_write(argv[3], + (void *)addr, size); + } else { + size_t full_size; + full_size = simple_strtoul(argv[5], NULL, 16); + ret = ubi_volume_begin_write(argv[3], + (void *)addr, size, full_size); + } + } else { + ret = ubi_volume_write(argv[3], (void *)addr, size); + } if (!ret) { printf("%lld bytes written to volume %s\n", size, argv[3]); @@ -636,6 +667,8 @@ U_BOOT_CMD( " - create volume name with size\n" "ubi write[vol] address volume size" " - Write volume from address with size\n" + "ubi write.part address volume size [fullsize]\n" + " - Write part of a volume from address\n" "ubi read[vol] address volume [size]" " - Read volume to address with size\n" "ubi remove[vol] volume" diff --git a/doc/README.ubi b/doc/README.ubi index 3cf4ef232..d82c75c84 100644 --- a/doc/README.ubi +++ b/doc/README.ubi @@ -14,6 +14,8 @@ ubi part [part] [offset] ubi info [l[ayout]] - Display volume and ubi layout information ubi create[vol] volume [size] [type] - create volume name with size ubi write[vol] address volume size - Write volume from address with size +ubi write.part address volume size [fullsize] + - Write part of a volume from address ubi read[vol] address volume [size] - Read volume to address with size ubi remove[vol] volume - Remove volume [Legends] @@ -77,6 +79,7 @@ ubi createvol Create UBI volume on UBI device ubi removevol Remove UBI volume from UBI device ubi read Read data from UBI volume to memory ubi write Write data from memory to UBI volume +ubi write.part Write data from memory to UBI volume, in parts Here a few examples on the usage: -- cgit v1.2.3-70-g09d2