From cead69c528d4f107288717aeca6af52d0d9d47e9 Mon Sep 17 00:00:00 2001 From: Alexey Romanov Date: Thu, 18 Jul 2024 08:45:23 +0300 Subject: ubi: allow to read from volume with offset Now user can pass an additional parameter 'offset' to ubi_volume_read() function. Signed-off-by: Alexey Romanov Reviewed-by: Heiko Schocher Acked-by: Heiko Schocher Signed-off-by: Michael Trimarchi --- cmd/ubi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/ubi.c b/cmd/ubi.c index 92998af2b02..4bf7c099dde 100644 --- a/cmd/ubi.c +++ b/cmd/ubi.c @@ -428,13 +428,13 @@ 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 ubi_volume_read(char *volume, char *buf, loff_t offset, size_t size) { int err, lnum, off, len, tbuf_size; void *tbuf; unsigned long long tmp; struct ubi_volume *vol; - loff_t offp = 0; + loff_t offp = offset; size_t len_read; vol = ubi_find_volume(volume); @@ -795,7 +795,7 @@ static int do_ubi(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) } if (argc == 3) { - return ubi_volume_read(argv[3], (char *)addr, size); + return ubi_volume_read(argv[3], (char *)addr, 0, size); } } -- cgit v1.2.3 From 25ee9c2005958e6f06609eef5c9d9915c77ece97 Mon Sep 17 00:00:00 2001 From: Alexey Romanov Date: Thu, 18 Jul 2024 08:45:24 +0300 Subject: 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 --- cmd/ubi.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 69 insertions(+), 3 deletions(-) (limited to 'cmd') diff --git a/cmd/ubi.c b/cmd/ubi.c index 4bf7c099dde..0e62e449327 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, -- cgit v1.2.3