summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Protsenko <joe.skb7@gmail.com>2020-01-24 17:53:42 +0200
committerLokesh Vutla <lokeshvutla@ti.com>2020-02-04 09:07:24 +0530
commit94f6d0d1bd602ffa520e5676177e770fcfe8472f (patch)
tree91e3dd207747fd9d379510d36fc0c6843d93ba10
parent7f2531502c74c02323af107c4d2d9714b582848d (diff)
downloadu-boot-94f6d0d1bd602ffa520e5676177e770fcfe8472f.tar.gz
u-boot-94f6d0d1bd602ffa520e5676177e770fcfe8472f.tar.bz2
u-boot-94f6d0d1bd602ffa520e5676177e770fcfe8472f.zip
cmd: abootimg: Add abootimg command
This command can be used to extract fields and image payloads from Android Boot Image. It can be used for example to implement boot flow where dtb is taken from boot.img (as v2 incorporated dtb inside of boot.img). Using this command, one can obtain needed dtb blob from boot.img in scripting manner, and then apply needed dtbo's (from "dtbo" partition) on top of that, providing then the resulting image to bootm command in order to boot the Android. Also right now this command has the sub-command to get an address and size of recovery dtbo from recovery image (for non-A/B devices only, see [1,2] for details). It can be tested like this: => mmc dev 1 => part start mmc 1 boot_a boot_start => part size mmc 1 boot_a boot_size => mmc read $loadaddr $boot_start $boot_size => abootimg get ver => abootimg dump dtb [1] https://source.android.com/devices/bootloader/boot-image-header [2] https://source.android.com/devices/architecture/dto/partitions Signed-off-by: Sam Protsenko <joe.skb7@gmail.com> Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
-rw-r--r--cmd/Kconfig8
-rw-r--r--cmd/Makefile1
-rw-r--r--cmd/abootimg.c258
3 files changed, 267 insertions, 0 deletions
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 6e1efaaf85..4734da17fe 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -386,6 +386,14 @@ config CMD_ADTIMG
files should be merged in one dtb further, which needs to be passed to
the kernel, as part of a boot process.
+config CMD_ABOOTIMG
+ bool "abootimg"
+ depends on ANDROID_BOOT_IMAGE
+ help
+ Android Boot Image manipulation commands. Allows one to extract
+ images contained in boot.img, like kernel, ramdisk, dtb, etc, and
+ obtain corresponding meta-information from boot.img.
+
config CMD_ELF
bool "bootelf, bootvx"
default y
diff --git a/cmd/Makefile b/cmd/Makefile
index 4f29b72c69..f1dd513a4b 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -48,6 +48,7 @@ ifdef CONFIG_POST
obj-$(CONFIG_CMD_DIAG) += diag.o
endif
obj-$(CONFIG_CMD_ADTIMG) += adtimg.o
+obj-$(CONFIG_CMD_ABOOTIMG) += abootimg.o
obj-$(CONFIG_CMD_ECHO) += echo.o
obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o
obj-$(CONFIG_CMD_EEPROM) += eeprom.o
diff --git a/cmd/abootimg.c b/cmd/abootimg.c
new file mode 100644
index 0000000000..670bcb3aaa
--- /dev/null
+++ b/cmd/abootimg.c
@@ -0,0 +1,258 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2020
+ * Sam Protsenko <joe.skb7@gmail.com>
+ */
+
+#include <android_image.h>
+#include <common.h>
+#include <mapmem.h>
+
+#define abootimg_addr() \
+ (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr)
+
+/* Please use abootimg_addr() macro to obtain the boot image address */
+static ulong _abootimg_addr = -1;
+
+static int abootimg_get_ver(int argc, char * const argv[])
+{
+ const struct andr_img_hdr *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)) {
+ printf("Error: Boot Image header is incorrect\n");
+ res = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ if (argc == 0)
+ printf("%u\n", hdr->header_version);
+ else
+ env_set_ulong(argv[0], hdr->header_version);
+
+exit:
+ unmap_sysmem(hdr);
+ return res;
+}
+
+static int abootimg_get_recovery_dtbo(int argc, char * const argv[])
+{
+ ulong addr;
+ u32 size;
+
+ if (argc > 2)
+ return CMD_RET_USAGE;
+
+ if (!android_image_get_dtbo(abootimg_addr(), &addr, &size))
+ return CMD_RET_FAILURE;
+
+ if (argc == 0) {
+ printf("%lx\n", addr);
+ } else {
+ env_set_hex(argv[0], addr);
+ if (argc == 2)
+ env_set_hex(argv[1], size);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+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;
+
+ 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 (hdr->header_version < 2) {
+ printf("Error: header_version must be >= 2 for this\n");
+ res = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ if (argc == 0)
+ printf("%lx\n", (ulong)hdr->dtb_addr);
+ else
+ env_set_hex(argv[0], (ulong)hdr->dtb_addr);
+
+exit:
+ unmap_sysmem(hdr);
+ return res;
+}
+
+static int abootimg_get_dtb_by_index(int argc, char * const argv[])
+{
+ const char *index_str;
+ u32 num;
+ char *endp;
+ ulong addr;
+ u32 size;
+
+ if (argc < 1 || argc > 3)
+ return CMD_RET_USAGE;
+
+ index_str = argv[0] + strlen("--index=");
+ if (index_str[0] == '\0') {
+ printf("Error: Wrong index num\n");
+ return CMD_RET_FAILURE;
+ }
+
+ num = simple_strtoul(index_str, &endp, 0);
+ if (*endp != '\0') {
+ printf("Error: Wrong index num\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!android_image_get_dtb_by_index(abootimg_addr(), num,
+ &addr, &size)) {
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc == 1) {
+ printf("%lx\n", addr);
+ } else {
+ if (env_set_hex(argv[1], addr)) {
+ printf("Error: Can't set [addr_var]\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (argc == 3) {
+ if (env_set_hex(argv[2], size)) {
+ printf("Error: Can't set [size_var]\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int abootimg_get_dtb(int argc, char * const argv[])
+{
+ if (argc < 1)
+ return CMD_RET_USAGE;
+
+ if (strstr(argv[0], "--index="))
+ return abootimg_get_dtb_by_index(argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+static int do_abootimg_addr(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ char *endp;
+ ulong img_addr;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ img_addr = simple_strtoul(argv[1], &endp, 16);
+ if (*endp != '\0') {
+ printf("Error: Wrong image address\n");
+ return CMD_RET_FAILURE;
+ }
+
+ _abootimg_addr = img_addr;
+ return CMD_RET_SUCCESS;
+}
+
+static int do_abootimg_get(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ const char *param;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+
+ param = argv[1];
+ argc -= 2;
+ argv += 2;
+ if (!strcmp(param, "ver"))
+ return abootimg_get_ver(argc, argv);
+ else if (!strcmp(param, "recovery_dtbo"))
+ return abootimg_get_recovery_dtbo(argc, argv);
+ else if (!strcmp(param, "dtb_load_addr"))
+ return abootimg_get_dtb_load_addr(argc, argv);
+ else if (!strcmp(param, "dtb"))
+ return abootimg_get_dtb(argc, argv);
+
+ return CMD_RET_USAGE;
+}
+
+static int do_abootimg_dump(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ if (!strcmp(argv[1], "dtb")) {
+ if (android_image_print_dtb_contents(abootimg_addr()))
+ return CMD_RET_FAILURE;
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static cmd_tbl_t cmd_abootimg_sub[] = {
+ U_BOOT_CMD_MKENT(addr, 2, 1, do_abootimg_addr, "", ""),
+ U_BOOT_CMD_MKENT(dump, 2, 1, do_abootimg_dump, "", ""),
+ U_BOOT_CMD_MKENT(get, 5, 1, do_abootimg_get, "", ""),
+};
+
+static int do_abootimg(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ cmd_tbl_t *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_abootimg_sub,
+ ARRAY_SIZE(cmd_abootimg_sub));
+
+ /* Strip off leading 'abootimg' command argument */
+ argc--;
+ argv++;
+
+ if (!cp || argc > cp->maxargs)
+ return CMD_RET_USAGE;
+ if (flag == CMD_FLAG_REPEAT && !cmd_is_repeatable(cp))
+ return CMD_RET_SUCCESS;
+
+ return cp->cmd(cmdtp, flag, argc, argv);
+}
+
+U_BOOT_CMD(
+ abootimg, CONFIG_SYS_MAXARGS, 0, do_abootimg,
+ "manipulate Android Boot Image",
+ "addr <addr>\n"
+ " - set the address in RAM where boot image is located\n"
+ " ($loadaddr is used by default)\n"
+ "abootimg dump dtb\n"
+ " - print info for all DT blobs in DTB area\n"
+ "abootimg get ver [varname]\n"
+ " - get header version\n"
+ "abootimg get recovery_dtbo [addr_var [size_var]]\n"
+ " - get address and size (hex) of recovery DTBO area in the image\n"
+ " [addr_var]: variable name to contain DTBO area address\n"
+ " [size_var]: variable name to contain DTBO area size\n"
+ "abootimg get dtb_load_addr [varname]\n"
+ " - get load address (hex) of DTB, from image header\n"
+ "abootimg get dtb --index=<num> [addr_var [size_var]]\n"
+ " - get address and size (hex) of DT blob in the image by index\n"
+ " <num>: index number of desired DT blob in DTB area\n"
+ " [addr_var]: variable name to contain DT blob address\n"
+ " [size_var]: variable name to contain DT blob size"
+);