Patchwork [U-Boot,3/3] cmd_ubi: add write.part command, to write a volume in multiple parts

login
register
mail settings
Submitter Paul Burton
Date Aug. 6, 2013, 10:13 a.m.
Message ID <1375784029-9310-4-git-send-email-paul.burton@imgtec.com>
Download mbox | patch
Permalink /patch/264999/
State Superseded
Delegated to: Stefan Roese
Headers show

Comments

Paul Burton - Aug. 6, 2013, 10:13 a.m.
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 <paul.burton@imgtec.com>
---
 common/cmd_ubi.c | 62 ++++++++++++++++++++++++++++++++++++++++++--------------
 doc/README.ubi   |  3 +++
 2 files changed, 50 insertions(+), 15 deletions(-)
Stefan Roese - Aug. 19, 2013, 9:07 a.m.
Hi Paul,

On 06.08.2013 12:13, Paul Burton wrote:
> 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.

Some coding-style (nitpicking) comments below.

> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
> ---
>  common/cmd_ubi.c | 62 ++++++++++++++++++++++++++++++++++++++++++--------------
>  doc/README.ubi   |  3 +++
>  2 files changed, 50 insertions(+), 15 deletions(-)
> 
> diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
> index 5ba4feb..dadb27b 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,19 @@ 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);

Please use braces for multi-line statements.

> +			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);
> +			}

Especially when the other branch also uses braces.

> +		} else
> +			ret = ubi_volume_write(argv[3], (void *)addr, size);

Here again, please braces since the other branch also uses them.

Thanks,
Stefan
Paul Burton - Aug. 20, 2013, 9:55 a.m.
Thanks, I'll fix the style issues and send v2 soon.

Paul

On 19/08/13 10:07, Stefan Roese wrote:
> Hi Paul,
>
> On 06.08.2013 12:13, Paul Burton wrote:
>> 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.
> Some coding-style (nitpicking) comments below.
>
>> Signed-off-by: Paul Burton <paul.burton@imgtec.com>
>> ---
>>   common/cmd_ubi.c | 62 ++++++++++++++++++++++++++++++++++++++++++--------------
>>   doc/README.ubi   |  3 +++
>>   2 files changed, 50 insertions(+), 15 deletions(-)
>>
>> diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
>> index 5ba4feb..dadb27b 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,19 @@ 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);
> Please use braces for multi-line statements.
>
>> +			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);
>> +			}
> Especially when the other branch also uses braces.
>
>> +		} else
>> +			ret = ubi_volume_write(argv[3], (void *)addr, size);
> Here again, please braces since the other branch also uses them.
>
> Thanks,
> Stefan
>
Stefan Roese - Aug. 27, 2013, 11:53 a.m.
On 20.08.2013 11:55, Paul Burton wrote:
> Thanks, I'll fix the style issues and send v2 soon.

Yes, please do.

Thanks,
Stefan

Patch

diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
index 5ba4feb..dadb27b 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,19 @@  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("%d bytes written to volume %s\n", size,
 			       argv[3]);
@@ -636,6 +666,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 3cf4ef2..d82c75c 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: