From: Alexey Romanov Date: Thu, 18 Jul 2024 05:45:24 +0000 (+0300) Subject: ubi: allow to write to volume with offset X-Git-Url: http://git.dujemihanovic.xyz/img/static/git-favicon.png?a=commitdiff_plain;h=25ee9c2005958e6f06609eef5c9d9915c77ece97;p=u-boot.git ubi: allow to write to volume with offset Introduce ubi_volume_offset_write() helper, which allow to write to ubi volume with specified offset. Signed-off-by: Alexey Romanov Reviewed-by: Heiko Schocher Acked-by: Heiko Schocher Signed-off-by: Michael Trimarchi --- diff --git a/cmd/ubi.c b/cmd/ubi.c index 4bf7c099dd..0e62e44932 100644 --- a/cmd/ubi.c +++ b/cmd/ubi.c @@ -423,9 +423,75 @@ int ubi_volume_begin_write(char *volume, void *buf, size_t size, return ubi_volume_continue_write(volume, buf, size); } -int ubi_volume_write(char *volume, void *buf, size_t size) +static int ubi_volume_offset_write(char *volume, void *buf, loff_t offset, + size_t size) { - return ubi_volume_begin_write(volume, buf, size, size); + int len, tbuf_size, ret; + u64 lnum; + struct ubi_volume *vol; + loff_t off = offset; + void *tbuf; + + vol = ubi_find_volume(volume); + if (!vol) + return -ENODEV; + + if (size > vol->reserved_pebs * (ubi->leb_size - vol->data_pad)) + return -EINVAL; + + tbuf_size = vol->usable_leb_size; + tbuf = malloc_cache_aligned(tbuf_size); + if (!tbuf) + return -ENOMEM; + + lnum = off; + off = do_div(lnum, vol->usable_leb_size); + + do { + struct ubi_volume_desc desc = { + .vol = vol, + .mode = UBI_READWRITE, + }; + + len = size > tbuf_size ? tbuf_size : size; + if (off + len >= vol->usable_leb_size) + len = vol->usable_leb_size - off; + + ret = ubi_read(&desc, (int)lnum, tbuf, 0, tbuf_size); + if (ret) { + pr_err("Failed to read leb %lld (%d)\n", lnum, ret); + goto exit; + } + + memcpy(tbuf + off, buf, len); + + ret = ubi_leb_change(&desc, (int)lnum, tbuf, tbuf_size); + if (ret) { + pr_err("Failed to write leb %lld (%d)\n", lnum, ret); + goto exit; + } + + off += len; + if (off >= vol->usable_leb_size) { + lnum++; + off -= vol->usable_leb_size; + } + + buf += len; + size -= len; + } while (size); + +exit: + free(tbuf); + return ret; +} + +int ubi_volume_write(char *volume, void *buf, loff_t offset, size_t size) +{ + if (!offset) + return ubi_volume_begin_write(volume, buf, size, size); + + return ubi_volume_offset_write(volume, buf, offset, size); } int ubi_volume_read(char *volume, char *buf, loff_t offset, size_t size) @@ -769,7 +835,7 @@ static int do_ubi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) (void *)addr, size, full_size); } } else { - ret = ubi_volume_write(argv[3], (void *)addr, size); + ret = ubi_volume_write(argv[3], (void *)addr, 0, size); } if (!ret) { printf("%lld bytes written to volume %s\n", size, diff --git a/env/ubi.c b/env/ubi.c index 22f2cafcfb..2f4ca571ed 100644 --- a/env/ubi.c +++ b/env/ubi.c @@ -53,7 +53,7 @@ static int env_ubi_save(void) if (gd->env_valid == ENV_VALID) { puts("Writing to redundant UBI... "); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME_REDUND, - (void *)env_new, CONFIG_ENV_SIZE)) { + (void *)env_new, 0, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME_REDUND); @@ -62,7 +62,7 @@ static int env_ubi_save(void) } else { puts("Writing to UBI... "); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, - (void *)env_new, CONFIG_ENV_SIZE)) { + (void *)env_new, 0, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); @@ -92,7 +92,7 @@ static int env_ubi_save(void) return 1; } - if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, + if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, (void *)env_new, 0, CONFIG_ENV_SIZE)) { printf("\n** Unable to write env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); @@ -196,7 +196,7 @@ static int env_ubi_erase(void) memset(env_buf, 0x0, CONFIG_ENV_SIZE); if (ubi_volume_write(CONFIG_ENV_UBI_VOLUME, - (void *)env_buf, CONFIG_ENV_SIZE)) { + (void *)env_buf, 0, CONFIG_ENV_SIZE)) { printf("\n** Unable to erase env to %s:%s **\n", CONFIG_ENV_UBI_PART, CONFIG_ENV_UBI_VOLUME); @@ -204,7 +204,7 @@ static int env_ubi_erase(void) } if (IS_ENABLED(CONFIG_SYS_REDUNDAND_ENVIRONMENT)) { if (ubi_volume_write(ENV_UBI_VOLUME_REDUND, - (void *)env_buf, CONFIG_ENV_SIZE)) { + (void *)env_buf, 0, CONFIG_ENV_SIZE)) { printf("\n** Unable to erase env to %s:%s **\n", CONFIG_ENV_UBI_PART, ENV_UBI_VOLUME_REDUND); diff --git a/include/ubi_uboot.h b/include/ubi_uboot.h index a4be0feabb..d36bb92348 100644 --- a/include/ubi_uboot.h +++ b/include/ubi_uboot.h @@ -48,7 +48,7 @@ extern int ubi_mtd_param_parse(const char *val, struct kernel_param *kp); extern int ubi_init(void); extern void ubi_exit(void); extern int ubi_part(char *part_name, const char *vid_header_offset); -extern int ubi_volume_write(char *volume, void *buf, size_t size); +extern int ubi_volume_write(char *volume, void *buf, loff_t offset, size_t size); extern int ubi_volume_read(char *volume, char *buf, loff_t offset, size_t size); extern struct ubi_device *ubi_devices[];