diff options
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | cmd/Kconfig | 10 | ||||
-rw-r--r-- | cmd/Makefile | 1 | ||||
-rw-r--r-- | cmd/boot_android.c | 74 | ||||
-rw-r--r-- | common/android_bootloader.c | 25 | ||||
-rw-r--r-- | include/android_bootloader.h | 6 |
6 files changed, 116 insertions, 6 deletions
@@ -1136,6 +1136,12 @@ The following options need to be configured: "bootloader", which often means reboot to fastboot but may also include a UI with a menu. + CONFIG_CMD_BOOT_ANDROID + This enables the command "boot_android" which executes the + Android Bootloader flow. Enabling CONFIG_CMD_FASTBOOT is + recommended to support the Android Fastboot protocol as part + of the bootloader. + - Journaling Flash filesystem support: CONFIG_JFFS2_NAND Define these for a default partition on a NAND device diff --git a/cmd/Kconfig b/cmd/Kconfig index 0c984d735d..71761d409c 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1463,6 +1463,16 @@ config CMD_AB_SELECT is used by the new A/B update model where one slot is updated in the background while running from the other slot. +config CMD_BOOT_ANDROID + bool "boot_android" + default n + depends on ANDROID_BOOTLOADER + help + Performs the Android Bootloader boot flow, loading the appropriate + Android image (normal kernel, recovery kernel or "bootloader" mode) + and booting it. The boot mode is determined by the contents of the + Android Bootloader Message. + endmenu if NET diff --git a/cmd/Makefile b/cmd/Makefile index 3a9c9747c9..9b93ecee25 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_CMD_BIND) += bind.o obj-$(CONFIG_CMD_BINOP) += binop.o obj-$(CONFIG_CMD_BLOCK_CACHE) += blkcache.o obj-$(CONFIG_CMD_BMP) += bmp.o +obj-$(CONFIG_CMD_BOOT_ANDROID) += boot_android.o obj-$(CONFIG_CMD_BOOTCOUNT) += bootcount.o obj-$(CONFIG_CMD_BOOTEFI) += bootefi.o obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o diff --git a/cmd/boot_android.c b/cmd/boot_android.c new file mode 100644 index 0000000000..964168946f --- /dev/null +++ b/cmd/boot_android.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (C) 2016 The Android Open Source Project + */ + +#include <android_bootloader.h> +#include <common.h> +#include <command.h> +#include <part.h> + +static int do_boot_android(struct cmd_tbl *cmdtp, int flag, int argc, + char * const argv[]) +{ + unsigned long load_address; + int ret = CMD_RET_SUCCESS; + char *addr_arg_endp, *addr_str; + struct blk_desc *dev_desc; + struct disk_partition part_info; + const char *misc_part_iface; + const char *misc_part_desc; + + if (argc < 4) + return CMD_RET_USAGE; + if (argc > 5) + return CMD_RET_USAGE; + + if (argc >= 5) { + load_address = simple_strtoul(argv[4], &addr_arg_endp, 16); + if (addr_arg_endp == argv[4] || *addr_arg_endp != '\0') + return CMD_RET_USAGE; + } else { + addr_str = env_get("loadaddr"); + if (addr_str) + load_address = simple_strtoul(addr_str, NULL, 16); + else + load_address = CONFIG_SYS_LOAD_ADDR; + } + + /* Lookup the "misc" partition from argv[1] and argv[2] */ + misc_part_iface = argv[1]; + misc_part_desc = argv[2]; + /* Split the part_name if passed as "$dev_num;part_name". */ + if (part_get_info_by_dev_and_name_or_num(misc_part_iface, + misc_part_desc, + &dev_desc, &part_info) < 0) + return CMD_RET_FAILURE; + + ret = android_bootloader_boot_flow(dev_desc, &part_info, argv[3], + load_address); + if (ret < 0) { + printf("Android boot failed, error %d.\n", ret); + return CMD_RET_FAILURE; + } + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + boot_android, 5, 0, do_boot_android, + "Execute the Android Bootloader flow.", + "<interface> <dev[:part|;part_name]> <slot> [<kernel_addr>]\n" + " - Load the Boot Control Block (BCB) from the partition 'part' on\n" + " device type 'interface' instance 'dev' to determine the boot\n" + " mode, and load and execute the appropriate kernel.\n" + " In normal and recovery mode, the kernel will be loaded from\n" + " the corresponding \"boot\" partition. In bootloader mode, the\n" + " command defined in the \"fastbootcmd\" variable will be\n" + " executed.\n" + " On Android devices with multiple slots, the pass 'slot' is\n" + " used to load the appropriate kernel. The standard slot names\n" + " are 'a' and 'b'.\n" + " - If 'part_name' is passed, preceded with a ; instead of :, the\n" + " partition name whose label is 'part_name' will be looked up in\n" + " the partition table. This is commonly the \"misc\" partition.\n" +); diff --git a/common/android_bootloader.c b/common/android_bootloader.c index 770c40b297..46dd282d5e 100644 --- a/common/android_bootloader.c +++ b/common/android_bootloader.c @@ -130,12 +130,17 @@ static int android_part_get_info_by_name_suffix(struct blk_desc *dev_desc, { char *part_name; int part_num; + size_t part_name_len; - part_name = malloc(strlen(base_name) + strlen(slot_suffix) + 1); + part_name_len = strlen(base_name) + 1; + if (slot_suffix) + part_name_len += strlen(slot_suffix); + part_name = malloc(part_name_len); if (!part_name) return -1; strcpy(part_name, base_name); - strcat(part_name, slot_suffix); + if (slot_suffix) + strcat(part_name, slot_suffix); part_num = part_get_info_by_name(dev_desc, part_name, part_info); if (part_num < 0) { @@ -159,8 +164,9 @@ static int android_bootloader_boot_bootloader(void) static int android_bootloader_boot_kernel(unsigned long kernel_address) { char kernel_addr_str[12]; - char *fdt_addr = env_get("fdt_addr"); - char *bootm_args[] = { "bootm", kernel_addr_str, "-", fdt_addr, NULL }; + char *fdt_addr = env_get("fdtaddr"); + char *bootm_args[] = { + "bootm", kernel_addr_str, kernel_addr_str, fdt_addr, NULL }; sprintf(kernel_addr_str, "0x%lx", kernel_address); @@ -260,6 +266,7 @@ static char *android_assemble_cmdline(const char *slot_suffix, int android_bootloader_boot_flow(struct blk_desc *dev_desc, const struct disk_partition *misc_part_info, + const char *slot, unsigned long kernel_address) { enum android_boot_mode mode; @@ -268,8 +275,7 @@ int android_bootloader_boot_flow(struct blk_desc *dev_desc, int boot_part_num, system_part_num; int ret; char *command_line; - /* TODO: lookup the slot_suffix based on the BCB. */ - const char *slot_suffix = "_a"; + char slot_suffix[3]; const char *mode_cmdline = NULL; /* Determine the boot mode and clear its value for the next boot if @@ -299,6 +305,13 @@ int android_bootloader_boot_flow(struct blk_desc *dev_desc, return android_bootloader_boot_bootloader(); } + slot_suffix[0] = '\0'; + if (slot && slot[0]) { + slot_suffix[0] = '_'; + slot_suffix[1] = slot[0]; + slot_suffix[2] = '\0'; + } + /* Load the kernel from the desired "boot" partition. */ boot_part_num = android_part_get_info_by_name_suffix(dev_desc, diff --git a/include/android_bootloader.h b/include/android_bootloader.h index d9cfdd589b..114ca5ddcf 100644 --- a/include/android_bootloader.h +++ b/include/android_bootloader.h @@ -36,10 +36,16 @@ struct disk_partition; * The boot mode is determined by the contents of the Android Bootloader * Message. On success it doesn't return. * + * @dev_desc: device where to load the kernel and system to boot from. + * @misc_part_info: the "misc" partition descriptor in 'dev_desc'. + * @slot: the boot slot to boot from. + * @kernel_address: address where to load the kernel if needed. + * * @return a negative number in case of error, otherwise it doesn't return. */ int android_bootloader_boot_flow(struct blk_desc *dev_desc, const struct disk_partition *misc_part_info, + const char *slot, unsigned long kernel_address); #endif /* __ANDROID_BOOTLOADER_H */ |