aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/Kconfig19
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/abootimg.c75
-rw-r--r--cmd/blk_common.c15
-rw-r--r--cmd/blkmap.c233
5 files changed, 318 insertions, 25 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 8c9b430f99..bab35fc667 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1980,6 +1980,25 @@ config CMD_BLOCK_CACHE
during development, but also allows the cache to be disabled when
it might hurt performance (e.g. when using the ums command).
+config CMD_BLKMAP
+ bool "blkmap - Composable virtual block devices"
+ depends on BLKMAP
+ default y if BLKMAP
+ help
+ Create virtual block devices that are backed by various sources,
+ e.g. RAM, or parts of an existing block device. Though much more
+ rudimentary, it borrows a lot of ideas from Linux's device mapper
+ subsystem.
+
+ Example use-cases:
+ - Treat a region of RAM as a block device, i.e. a RAM disk. This let's
+ you extract files from filesystem images stored in RAM (perhaps as a
+ result of a TFTP transfer).
+ - Create a virtual partition on an existing device. This let's you
+ access filesystems that aren't stored at an exact partition
+ boundary. A common example is a filesystem image embedded in an FIT
+ image.
+
config CMD_BUTTON
bool "button"
depends on BUTTON
diff --git a/cmd/Makefile b/cmd/Makefile
index e032091621..054ef42017 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_CMD_BCB) += bcb.o
obj-$(CONFIG_CMD_BDI) += bdinfo.o
obj-$(CONFIG_CMD_BIND) += bind.o
obj-$(CONFIG_CMD_BINOP) += binop.o
+obj-$(CONFIG_CMD_BLKMAP) += blkmap.o
obj-$(CONFIG_CMD_BLOBLIST) += bloblist.o
obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o
obj-$(CONFIG_CMD_BMP) += bmp.o
diff --git a/cmd/abootimg.c b/cmd/abootimg.c
index f48a9dcb02..2653b555b1 100644
--- a/cmd/abootimg.c
+++ b/cmd/abootimg.c
@@ -15,17 +15,28 @@
/* Please use abootimg_addr() macro to obtain the boot image address */
static ulong _abootimg_addr = -1;
+static ulong _avendor_bootimg_addr = -1;
+
+ulong get_abootimg_addr(void)
+{
+ return (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr);
+}
+
+ulong get_avendor_bootimg_addr(void)
+{
+ return _avendor_bootimg_addr;
+}
static int abootimg_get_ver(int argc, char *const argv[])
{
- const struct andr_img_hdr *hdr;
+ const struct andr_boot_img_hdr_v0 *hdr;
int res = CMD_RET_SUCCESS;
if (argc > 1)
return CMD_RET_USAGE;
hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
- if (android_image_check_header(hdr)) {
+ if (!is_android_boot_image_header(hdr)) {
printf("Error: Boot Image header is incorrect\n");
res = CMD_RET_FAILURE;
goto exit;
@@ -65,33 +76,43 @@ static int abootimg_get_recovery_dtbo(int argc, char *const argv[])
static int abootimg_get_dtb_load_addr(int argc, char *const argv[])
{
- const struct andr_img_hdr *hdr;
- int res = CMD_RET_SUCCESS;
-
if (argc > 1)
return CMD_RET_USAGE;
+ struct andr_image_data img_data = {0};
+ const struct andr_boot_img_hdr_v0 *hdr;
+ const struct andr_vnd_boot_img_hdr *vhdr;
hdr = map_sysmem(abootimg_addr(), sizeof(*hdr));
- if (android_image_check_header(hdr)) {
- printf("Error: Boot Image header is incorrect\n");
- res = CMD_RET_FAILURE;
- goto exit;
+ if (get_avendor_bootimg_addr() != -1)
+ vhdr = map_sysmem(get_avendor_bootimg_addr(), sizeof(*vhdr));
+
+ if (!android_image_get_data(hdr, vhdr, &img_data)) {
+ if (get_avendor_bootimg_addr() != -1)
+ unmap_sysmem(vhdr);
+ unmap_sysmem(hdr);
+ return CMD_RET_FAILURE;
}
- if (hdr->header_version < 2) {
+ if (get_avendor_bootimg_addr() != -1)
+ unmap_sysmem(vhdr);
+ unmap_sysmem(hdr);
+
+ if (img_data.header_version < 2) {
printf("Error: header_version must be >= 2 for this\n");
- res = CMD_RET_FAILURE;
- goto exit;
+ return CMD_RET_FAILURE;
+ }
+
+ if (!img_data.dtb_load_addr) {
+ printf("Error: failed to read dtb_load_addr\n");
+ return CMD_RET_FAILURE;
}
if (argc == 0)
- printf("%lx\n", (ulong)hdr->dtb_addr);
+ printf("%lx\n", (ulong)img_data.dtb_load_addr);
else
- env_set_hex(argv[0], (ulong)hdr->dtb_addr);
+ env_set_hex(argv[0], (ulong)img_data.dtb_load_addr);
-exit:
- unmap_sysmem(hdr);
- return res;
+ return CMD_RET_SUCCESS;
}
static int abootimg_get_dtb_by_index(int argc, char *const argv[])
@@ -117,7 +138,8 @@ static int abootimg_get_dtb_by_index(int argc, char *const argv[])
return CMD_RET_FAILURE;
}
- if (!android_image_get_dtb_by_index(abootimg_addr(), num,
+ if (!android_image_get_dtb_by_index(abootimg_addr(),
+ get_avendor_bootimg_addr(), num,
&addr, &size)) {
return CMD_RET_FAILURE;
}
@@ -158,7 +180,7 @@ static int do_abootimg_addr(struct cmd_tbl *cmdtp, int flag, int argc,
char *endp;
ulong img_addr;
- if (argc != 2)
+ if (argc < 2 || argc > 3)
return CMD_RET_USAGE;
img_addr = hextoul(argv[1], &endp);
@@ -168,6 +190,17 @@ static int do_abootimg_addr(struct cmd_tbl *cmdtp, int flag, int argc,
}
_abootimg_addr = img_addr;
+
+ if (argc == 3) {
+ img_addr = simple_strtoul(argv[2], &endp, 16);
+ if (*endp != '\0') {
+ printf("Error: Wrong vendor image address\n");
+ return CMD_RET_FAILURE;
+ }
+
+ _avendor_bootimg_addr = img_addr;
+ }
+
return CMD_RET_SUCCESS;
}
@@ -211,7 +244,7 @@ static int do_abootimg_dump(struct cmd_tbl *cmdtp, int flag, int argc,
}
static struct cmd_tbl cmd_abootimg_sub[] = {
- U_BOOT_CMD_MKENT(addr, 2, 1, do_abootimg_addr, "", ""),
+ U_BOOT_CMD_MKENT(addr, 3, 1, do_abootimg_addr, "", ""),
U_BOOT_CMD_MKENT(dump, 2, 1, do_abootimg_dump, "", ""),
U_BOOT_CMD_MKENT(get, 5, 1, do_abootimg_get, "", ""),
};
@@ -239,7 +272,7 @@ static int do_abootimg(struct cmd_tbl *cmdtp, int flag, int argc,
U_BOOT_CMD(
abootimg, CONFIG_SYS_MAXARGS, 0, do_abootimg,
"manipulate Android Boot Image",
- "addr <addr>\n"
+ "addr <boot_img_addr> [<vendor_boot_img_addr>]>\n"
" - set the address in RAM where boot image is located\n"
" ($loadaddr is used by default)\n"
"abootimg dump dtb\n"
diff --git a/cmd/blk_common.c b/cmd/blk_common.c
index 75a072caf5..9f9d4327a9 100644
--- a/cmd/blk_common.c
+++ b/cmd/blk_common.c
@@ -11,6 +11,7 @@
#include <common.h>
#include <blk.h>
#include <command.h>
+#include <mapmem.h>
int blk_common_cmd(int argc, char *const argv[], enum uclass_id uclass_id,
int *cur_devnump)
@@ -63,31 +64,37 @@ int blk_common_cmd(int argc, char *const argv[], enum uclass_id uclass_id,
default: /* at least 4 args */
if (strcmp(argv[1], "read") == 0) {
- ulong addr = hextoul(argv[2], NULL);
+ phys_addr_t paddr = hextoul(argv[2], NULL);
lbaint_t blk = hextoul(argv[3], NULL);
ulong cnt = hextoul(argv[4], NULL);
+ void *vaddr;
ulong n;
printf("\n%s read: device %d block # "LBAFU", count %lu ... ",
if_name, *cur_devnump, blk, cnt);
+ vaddr = map_sysmem(paddr, 512 * cnt);
n = blk_read_devnum(uclass_id, *cur_devnump, blk, cnt,
- (ulong *)addr);
+ vaddr);
+ unmap_sysmem(vaddr);
printf("%ld blocks read: %s\n", n,
n == cnt ? "OK" : "ERROR");
return n == cnt ? 0 : 1;
} else if (strcmp(argv[1], "write") == 0) {
- ulong addr = hextoul(argv[2], NULL);
+ phys_addr_t paddr = hextoul(argv[2], NULL);
lbaint_t blk = hextoul(argv[3], NULL);
ulong cnt = hextoul(argv[4], NULL);
+ void *vaddr;
ulong n;
printf("\n%s write: device %d block # "LBAFU", count %lu ... ",
if_name, *cur_devnump, blk, cnt);
+ vaddr = map_sysmem(paddr, 512 * cnt);
n = blk_write_devnum(uclass_id, *cur_devnump, blk, cnt,
- (ulong *)addr);
+ vaddr);
+ unmap_sysmem(vaddr);
printf("%ld blocks written: %s\n", n,
n == cnt ? "OK" : "ERROR");
diff --git a/cmd/blkmap.c b/cmd/blkmap.c
new file mode 100644
index 0000000000..b34c013072
--- /dev/null
+++ b/cmd/blkmap.c
@@ -0,0 +1,233 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2023 Addiva Elektronik
+ * Author: Tobias Waldekranz <tobias@waldekranz.com>
+ */
+
+#include <blk.h>
+#include <blkmap.h>
+#include <common.h>
+#include <command.h>
+#include <malloc.h>
+#include <dm/device.h>
+
+static int blkmap_curr_dev;
+
+struct map_ctx {
+ struct udevice *dev;
+ lbaint_t blknr, blkcnt;
+};
+
+typedef int (*map_parser_fn)(struct map_ctx *ctx, int argc, char *const argv[]);
+
+struct map_handler {
+ const char *name;
+ map_parser_fn fn;
+};
+
+int do_blkmap_map_linear(struct map_ctx *ctx, int argc, char *const argv[])
+{
+ struct blk_desc *lbd;
+ int err, ldevnum;
+ lbaint_t lblknr;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ ldevnum = dectoul(argv[2], NULL);
+ lblknr = dectoul(argv[3], NULL);
+
+ lbd = blk_get_devnum_by_uclass_idname(argv[1], ldevnum);
+ if (!lbd) {
+ printf("Found no device matching \"%s %d\"\n",
+ argv[1], ldevnum);
+ return CMD_RET_FAILURE;
+ }
+
+ err = blkmap_map_linear(ctx->dev, ctx->blknr, ctx->blkcnt,
+ lbd->bdev, lblknr);
+ if (err) {
+ printf("Unable to map \"%s %d\" at block 0x" LBAF ": %d\n",
+ argv[1], ldevnum, ctx->blknr, err);
+
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Block 0x" LBAF "+0x" LBAF " mapped to block 0x" LBAF " of \"%s %d\"\n",
+ ctx->blknr, ctx->blkcnt, lblknr, argv[1], ldevnum);
+ return CMD_RET_SUCCESS;
+}
+
+int do_blkmap_map_mem(struct map_ctx *ctx, int argc, char *const argv[])
+{
+ phys_addr_t addr;
+ int err;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ addr = hextoul(argv[1], NULL);
+
+ err = blkmap_map_pmem(ctx->dev, ctx->blknr, ctx->blkcnt, addr);
+ if (err) {
+ printf("Unable to map %#llx at block 0x" LBAF ": %d\n",
+ (unsigned long long)addr, ctx->blknr, err);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Block 0x" LBAF "+0x" LBAF " mapped to %#llx\n",
+ ctx->blknr, ctx->blkcnt, (unsigned long long)addr);
+ return CMD_RET_SUCCESS;
+}
+
+struct map_handler map_handlers[] = {
+ { .name = "linear", .fn = do_blkmap_map_linear },
+ { .name = "mem", .fn = do_blkmap_map_mem },
+
+ { .name = NULL }
+};
+
+static int do_blkmap_map(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct map_handler *handler;
+ struct map_ctx ctx;
+
+ if (argc < 5)
+ return CMD_RET_USAGE;
+
+ ctx.dev = blkmap_from_label(argv[1]);
+ if (!ctx.dev) {
+ printf("\"%s\" is not the name of any known blkmap\n", argv[1]);
+ return CMD_RET_FAILURE;
+ }
+
+ ctx.blknr = hextoul(argv[2], NULL);
+ ctx.blkcnt = hextoul(argv[3], NULL);
+ argc -= 4;
+ argv += 4;
+
+ for (handler = map_handlers; handler->name; handler++) {
+ if (!strcmp(handler->name, argv[0]))
+ return handler->fn(&ctx, argc, argv);
+ }
+
+ printf("Unknown map type \"%s\"\n", argv[0]);
+ return CMD_RET_USAGE;
+}
+
+static int do_blkmap_create(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ const char *label;
+ int err;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ label = argv[1];
+
+ err = blkmap_create(label, NULL);
+ if (err) {
+ printf("Unable to create \"%s\": %d\n", label, err);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Created \"%s\"\n", label);
+ return CMD_RET_SUCCESS;
+}
+
+static int do_blkmap_destroy(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct udevice *dev;
+ const char *label;
+ int err;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ label = argv[1];
+
+ dev = blkmap_from_label(label);
+ if (!dev) {
+ printf("\"%s\" is not the name of any known blkmap\n", label);
+ return CMD_RET_FAILURE;
+ }
+
+ err = blkmap_destroy(dev);
+ if (err) {
+ printf("Unable to destroy \"%s\": %d\n", label, err);
+ return CMD_RET_FAILURE;
+ }
+
+ printf("Destroyed \"%s\"\n", label);
+ return CMD_RET_SUCCESS;
+}
+
+static int do_blkmap_get(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ struct udevice *dev;
+ const char *label;
+ int err;
+
+ if (argc < 3)
+ return CMD_RET_USAGE;
+
+ label = argv[1];
+
+ dev = blkmap_from_label(label);
+ if (!dev) {
+ printf("\"%s\" is not the name of any known blkmap\n", label);
+ return CMD_RET_FAILURE;
+ }
+
+ if (!strcmp(argv[2], "dev")) {
+ if (argc == 3) {
+ printf("%d\n", dev_seq(dev));
+ } else {
+ err = env_set_hex(argv[3], dev_seq(dev));
+ if (err)
+ return CMD_RET_FAILURE;
+ }
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_blkmap_common(struct cmd_tbl *cmdtp, int flag,
+ int argc, char *const argv[])
+{
+ /* The subcommand parsing pops the original argv[0] ("blkmap")
+ * which blk_common_cmd expects. Push it back again.
+ */
+ argc++;
+ argv--;
+
+ return blk_common_cmd(argc, argv, UCLASS_BLKMAP, &blkmap_curr_dev);
+}
+
+U_BOOT_CMD_WITH_SUBCMDS(
+ blkmap, "Composeable virtual block devices",
+ "info - list configured devices\n"
+ "blkmap part - list available partitions on current blkmap device\n"
+ "blkmap dev [<dev>] - show or set current blkmap device\n"
+ "blkmap read <addr> <blk#> <cnt>\n"
+ "blkmap write <addr> <blk#> <cnt>\n"
+ "blkmap get <label> dev [<var>] - store device number in variable\n"
+ "blkmap create <label> - create device\n"
+ "blkmap destroy <label> - destroy device\n"
+ "blkmap map <label> <blk#> <cnt> linear <interface> <dev> <blk#> - device mapping\n"
+ "blkmap map <label> <blk#> <cnt> mem <addr> - memory mapping\n",
+ U_BOOT_SUBCMD_MKENT(info, 2, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(part, 2, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(dev, 4, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(read, 5, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(write, 5, 1, do_blkmap_common),
+ U_BOOT_SUBCMD_MKENT(get, 5, 1, do_blkmap_get),
+ U_BOOT_SUBCMD_MKENT(create, 2, 1, do_blkmap_create),
+ U_BOOT_SUBCMD_MKENT(destroy, 2, 1, do_blkmap_destroy),
+ U_BOOT_SUBCMD_MKENT(map, 32, 1, do_blkmap_map));