[U-Boot] [PATCH v2 3/8] cmd: bootimg: Add bootimg command
Sam Protsenko
semen.protsenko at linaro.org
Wed Oct 23 14:34:22 UTC 2019
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 file 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. It can be further parsed using
'dtimg' command and merged into dtb file (for non-A/B devices only, see
[1,2] for details).
[1] https://source.android.com/devices/bootloader/boot-image-header
[2] https://source.android.com/devices/architecture/dto/partitions
Signed-off-by: Sam Protsenko <semen.protsenko at linaro.org>
---
Changes in v2:
- add "set_addr" sub-command
- provide mem mappings for sandbox
- rebase on top of master
cmd/Kconfig | 8 ++
cmd/Makefile | 1 +
cmd/bootimg.c | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 219 insertions(+)
create mode 100644 cmd/bootimg.c
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 07060c63a7..d89a91cde4 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -356,6 +356,14 @@ config CMD_DTIMG
files should be merged in one dtb further, which needs to be passed to
the kernel, as part of a boot process.
+config CMD_BOOTIMG
+ bool "bootimg"
+ 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 ac843b4b16..bf15e38f41 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -48,6 +48,7 @@ ifdef CONFIG_POST
obj-$(CONFIG_CMD_DIAG) += diag.o
endif
obj-$(CONFIG_CMD_DTIMG) += dtimg.o
+obj-$(CONFIG_CMD_BOOTIMG) += bootimg.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/bootimg.c b/cmd/bootimg.c
new file mode 100644
index 0000000000..a26a74f124
--- /dev/null
+++ b/cmd/bootimg.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * (C) Copyright 2018 Linaro Ltd.
+ * Sam Protsenko <semen.protsenko at linaro.org>
+ */
+
+#include <android_image.h>
+#include <common.h>
+#include <mapmem.h>
+
+#define bootimg_addr() (_bootimg_addr == -1 ? load_addr : _bootimg_addr)
+
+/* Please use bootimg_addr() macro to obtain the boot image address */
+static ulong _bootimg_addr = -1;
+
+static int do_bootimg_set_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;
+ }
+
+ _bootimg_addr = img_addr;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_bootimg_ver(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ const struct andr_img_hdr *hdr;
+ char buf[65];
+ int res = CMD_RET_SUCCESS;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ hdr = map_sysmem(bootimg_addr(), sizeof(*hdr));
+ if (android_image_check_header(hdr)) {
+ printf("Error: Boot Image header is incorrect\n");
+ res = CMD_RET_FAILURE;
+ goto exit;
+ }
+
+ snprintf(buf, sizeof(buf), "%u", hdr->header_version);
+ env_set(argv[1], buf);
+
+exit:
+ unmap_sysmem(hdr);
+ return res;
+}
+
+static int do_bootimg_get_dtbo(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ char buf[65];
+ ulong addr;
+ u32 size;
+
+ if (argc < 2 || argc > 3)
+ return CMD_RET_USAGE;
+
+ if (!android_image_get_dtbo(bootimg_addr(), &addr, &size))
+ return CMD_RET_FAILURE;
+
+ snprintf(buf, sizeof(buf), "%lx", addr);
+ env_set(argv[1], buf);
+
+ if (argc == 3) {
+ snprintf(buf, sizeof(buf), "%x", size);
+ env_set(argv[2], buf);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_bootimg_dtb_dump(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ if (argc != 1)
+ return CMD_RET_USAGE;
+
+ if (android_image_print_dtb_contents(bootimg_addr()))
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_bootimg_dtb_load_addr(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ const struct andr_img_hdr *hdr;
+ char buf[65];
+ int res = CMD_RET_SUCCESS;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ hdr = map_sysmem(bootimg_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;
+ }
+
+ snprintf(buf, sizeof(buf), "%lx", (ulong)hdr->dtb_addr);
+ env_set(argv[1], buf);
+
+exit:
+ unmap_sysmem(hdr);
+ return res;
+}
+
+static int do_bootimg_get_dtb_file(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ char *endp;
+ char buf[65];
+ u32 index;
+ ulong addr;
+ u32 size;
+
+ if (argc < 3 || argc > 4)
+ return CMD_RET_USAGE;
+
+ index = simple_strtoul(argv[1], &endp, 0);
+ if (*endp != '\0') {
+ printf("Error: Wrong index\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!android_image_get_dtb_by_index(bootimg_addr(), index, &addr,
+ &size))
+ return CMD_RET_FAILURE;
+
+ snprintf(buf, sizeof(buf), "%lx", addr);
+ env_set(argv[2], buf);
+
+ if (argc == 4) {
+ snprintf(buf, sizeof(buf), "%x", size);
+ env_set(argv[3], buf);
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static cmd_tbl_t cmd_bootimg_sub[] = {
+ U_BOOT_CMD_MKENT(set_addr, 2, 1, do_bootimg_set_addr, "", ""),
+ U_BOOT_CMD_MKENT(ver, 2, 1, do_bootimg_ver, "", ""),
+ U_BOOT_CMD_MKENT(get_dtbo, 3, 1, do_bootimg_get_dtbo, "", ""),
+ U_BOOT_CMD_MKENT(dtb_dump, 1, 1, do_bootimg_dtb_dump, "", ""),
+ U_BOOT_CMD_MKENT(dtb_load_addr, 2, 1, do_bootimg_dtb_load_addr, "", ""),
+ U_BOOT_CMD_MKENT(get_dtb_file, 4, 1, do_bootimg_get_dtb_file, "", ""),
+};
+
+static int do_bootimg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ cmd_tbl_t *cp;
+
+ cp = find_cmd_tbl(argv[1], cmd_bootimg_sub,
+ ARRAY_SIZE(cmd_bootimg_sub));
+
+ /* Strip off leading 'bootimg' 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(
+ bootimg, CONFIG_SYS_MAXARGS, 0, do_bootimg,
+ "manipulate Android Boot Image",
+ "set_addr <addr>\n"
+ " - set the address in RAM where boot image is located\n"
+ " ($loadaddr is used by default)\n"
+ "bootimg ver <varname>\n"
+ " - get header version\n"
+ "bootimg get_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"
+ "bootimg dtb_dump\n"
+ " - print info for all files in DTB area\n"
+ "bootimg dtb_load_addr <varname>\n"
+ " - get load address (hex) of DTB\n"
+ "bootimg get_dtb_file <index> <addr_var> [size_var]\n"
+ " - get address and size (hex) of DTB file in the image\n"
+ " <index>: index of desired DTB file in DTB area\n"
+ " <addr_var>: variable name to contain DTB file address\n"
+ " [size_var]: variable name to contain DTB file size\n"
+);
--
2.23.0
More information about the U-Boot
mailing list