[PATCH v5 0/3] Add support for booting into userspace fastboot

Android 10 adds support for dynamic partitions and in order to support them userspace fastboot must be used[1]. New tool called fastbootd is included into recovery image.
Userspace fastboot works from recovery and is launched if: 1) - Dynamic partitioning is enabled 2) - Boot control block has 'boot-fastboot' value into command field
The bootloader is expected[2] to load and boot into the recovery image upon seeing boot-fastboot in the BCB command. Recovery then parses the BCB message and switches to fastbootd mode.
Please note that boot script is expected to handle 'boot-fastboot' command in BCB and load into recovery mode.
Bootloader must support[3] 'reboot fastboot' command which should reboot device into userspace fastboot to accomodate those changes.
Another command that bootloader must support[3] is 'reboot recovery'. This command should simply reboot device into recovery mode.
Changes since v4[7]: * Moved BCB commands table next to reboot reasons enum to avoid issues in future with keeping them in sync * Changed command buffer size to 64 to fix issue with longer string in case of bootonce-bootloader command
Changes since v3[6]: * Fixed indentation in Kconfig * Fixed default value for FASTBOOT_USE_BCB_SET_REBOOT_FLAG * Extended help message for FASTBOOT_USE_BCB_SET_REBOOT_FLAG
Changes since v2[5]: * Split patch 1 into two separate patches: * Patch 1 extends fastboot_set_reboot_flag arguments with reboot reason * Patch 2 adds new reboot reasons for fastbootd and recovery * Added name for fastboot_rebot_reason enum * Replaced switch inside fastboot_set_reboot_flag with table lookup * Moved fastboot_set_reboot_flag BCB implementation to separate file
Changes since v1[4]: * Added missing handling of reboot commands for network protocol * Extended fastboot_set_reboot_flag command to accept reboot reason * Made former fastboot_set_flag function as an optional implementation of fastboot_set_reboot_flag which could be turned on by Kconfig
[1] - https://source.android.com/devices/bootloader/fastbootd [2] - https://source.android.com/devices/bootloader/fastbootd#unified_fastboot_and... [3] - https://source.android.com/devices/bootloader/fastbootd#modifications_to_the... [4] - http://patchwork.ozlabs.org/project/uboot/cover/cover.1590539734.git.roman.k... [5] - http://patchwork.ozlabs.org/project/uboot/cover/cover.1591254465.git.roman.k... [6] - http://patchwork.ozlabs.org/project/uboot/cover/cover.1591806433.git.roman.k... [7] - http://patchwork.ozlabs.org/project/uboot/cover/cover.1592871839.git.roman.k...
Roman Kovalivskyi (3): fastboot: Extend fastboot_set_reboot_flag with reboot reason fastboot: Add support for 'reboot fastboot' command fastboot: Add default fastboot_set_reboot_flag implementation
arch/arm/mach-meson/board-common.c | 6 ++++- arch/arm/mach-rockchip/board.c | 6 ++++- board/amazon/kc1/kc1.c | 6 ++++- board/lg/sniper/sniper.c | 6 ++++- board/ti/am57xx/board.c | 6 ++++- board/ti/dra7xx/evm.c | 6 ++++- drivers/fastboot/Kconfig | 12 +++++++++ drivers/fastboot/Makefile | 1 + drivers/fastboot/fb_bcb_impl.c | 43 ++++++++++++++++++++++++++++++ drivers/fastboot/fb_command.c | 40 ++++++++++++++++++++++++++- drivers/fastboot/fb_common.c | 2 +- drivers/usb/gadget/f_fastboot.c | 2 ++ include/fastboot.h | 23 +++++++++++++++- net/fastboot.c | 2 ++ 14 files changed, 152 insertions(+), 9 deletions(-) create mode 100644 drivers/fastboot/fb_bcb_impl.c

Extend fastboot_set_reboot_flag arguments with reboot reason so that it could handle different reboot cases in future.
Signed-off-by: Roman Kovalivskyi roman.kovalivskyi@globallogic.com --- arch/arm/mach-meson/board-common.c | 6 +++++- arch/arm/mach-rockchip/board.c | 6 +++++- board/amazon/kc1/kc1.c | 6 +++++- board/lg/sniper/sniper.c | 6 +++++- board/ti/am57xx/board.c | 6 +++++- board/ti/dra7xx/evm.c | 6 +++++- drivers/fastboot/fb_command.c | 2 +- drivers/fastboot/fb_common.c | 2 +- include/fastboot.h | 10 +++++++++- 9 files changed, 41 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-meson/board-common.c b/arch/arm/mach-meson/board-common.c index 19e5bfd3660c..a1f08bb98c6f 100644 --- a/arch/arm/mach-meson/board-common.c +++ b/arch/arm/mach-meson/board-common.c @@ -5,6 +5,7 @@
#include <common.h> #include <cpu_func.h> +#include <fastboot.h> #include <init.h> #include <net.h> #include <asm/arch/boot.h> @@ -153,8 +154,11 @@ int board_late_init(void) #if CONFIG_IS_ENABLED(FASTBOOT) static unsigned int reboot_reason = REBOOT_REASON_NORMAL;
-int fastboot_set_reboot_flag() +int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) { + if (reason != FASTBOOT_REBOOT_REASON_BOOTLOADER) + return -ENOTSUPP; + reboot_reason = REBOOT_REASON_BOOTLOADER;
printf("Using reboot reason: 0x%x\n", reboot_reason); diff --git a/arch/arm/mach-rockchip/board.c b/arch/arm/mach-rockchip/board.c index 430c0cbf41e4..ba4da72b3910 100644 --- a/arch/arm/mach-rockchip/board.c +++ b/arch/arm/mach-rockchip/board.c @@ -6,6 +6,7 @@ #include <clk.h> #include <cpu_func.h> #include <dm.h> +#include <fastboot.h> #include <init.h> #include <log.h> #include <ram.h> @@ -152,8 +153,11 @@ int board_usb_init(int index, enum usb_init_type init) #endif /* CONFIG_USB_GADGET */
#if CONFIG_IS_ENABLED(FASTBOOT) -int fastboot_set_reboot_flag(void) +int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) { + if (reason != FASTBOOT_REBOOT_REASON_BOOTLOADER) + return -ENOTSUPP; + printf("Setting reboot to fastboot flag ...\n"); /* Set boot mode to fastboot */ writel(BOOT_FASTBOOT, CONFIG_ROCKCHIP_BOOT_MODE_REG); diff --git a/board/amazon/kc1/kc1.c b/board/amazon/kc1/kc1.c index fb1828ff44da..445980f16e62 100644 --- a/board/amazon/kc1/kc1.c +++ b/board/amazon/kc1/kc1.c @@ -8,6 +8,7 @@ #include <config.h> #include <common.h> #include <env.h> +#include <fastboot.h> #include <init.h> #include <linux/ctype.h> #include <linux/usb/musb.h> @@ -163,8 +164,11 @@ void get_board_serial(struct tag_serialnr *serialnr) omap_die_id_get_board_serial(serialnr); }
-int fastboot_set_reboot_flag(void) +int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) { + if (reason != FASTBOOT_REBOOT_REASON_BOOTLOADER) + return -ENOTSUPP; + return omap_reboot_mode_store("b"); }
diff --git a/board/lg/sniper/sniper.c b/board/lg/sniper/sniper.c index 2825eccc035a..99b832fe601b 100644 --- a/board/lg/sniper/sniper.c +++ b/board/lg/sniper/sniper.c @@ -9,6 +9,7 @@ #include <common.h> #include <dm.h> #include <env.h> +#include <fastboot.h> #include <init.h> #include <linux/ctype.h> #include <linux/usb/musb.h> @@ -175,8 +176,11 @@ void reset_misc(void) omap_reboot_mode_store(reboot_mode); }
-int fastboot_set_reboot_flag(void) +int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) { + if (reason != FASTBOOT_REBOOT_REASON_BOOTLOADER) + return -ENOTSUPP; + return omap_reboot_mode_store("b"); }
diff --git a/board/ti/am57xx/board.c b/board/ti/am57xx/board.c index 8720eb87a55d..49afd3bc927b 100644 --- a/board/ti/am57xx/board.c +++ b/board/ti/am57xx/board.c @@ -9,6 +9,7 @@
#include <common.h> #include <env.h> +#include <fastboot.h> #include <fdt_support.h> #include <image.h> #include <init.h> @@ -1169,8 +1170,11 @@ int board_fit_config_name_match(const char *name) #endif
#if CONFIG_IS_ENABLED(FASTBOOT) && !CONFIG_IS_ENABLED(ENV_IS_NOWHERE) -int fastboot_set_reboot_flag(void) +int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) { + if (reason != FASTBOOT_REBOOT_REASON_BOOTLOADER) + return -ENOTSUPP; + printf("Setting reboot to fastboot flag ...\n"); env_set("dofastboot", "1"); env_save(); diff --git a/board/ti/dra7xx/evm.c b/board/ti/dra7xx/evm.c index acf7ff169170..3bc40c721146 100644 --- a/board/ti/dra7xx/evm.c +++ b/board/ti/dra7xx/evm.c @@ -12,6 +12,7 @@ #include <common.h> #include <env.h> #include <fdt_support.h> +#include <fastboot.h> #include <image.h> #include <init.h> #include <spl.h> @@ -1050,8 +1051,11 @@ int board_fit_config_name_match(const char *name) #endif
#if CONFIG_IS_ENABLED(FASTBOOT) && !CONFIG_IS_ENABLED(ENV_IS_NOWHERE) -int fastboot_set_reboot_flag(void) +int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) { + if (reason != FASTBOOT_REBOOT_REASON_BOOTLOADER) + return -ENOTSUPP; + printf("Setting reboot to fastboot flag ...\n"); env_set("dofastboot", "1"); env_save(); diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c index 49f6a61c3745..8ce5d32fb2ba 100644 --- a/drivers/fastboot/fb_command.c +++ b/drivers/fastboot/fb_command.c @@ -307,7 +307,7 @@ static void erase(char *cmd_parameter, char *response) */ static void reboot_bootloader(char *cmd_parameter, char *response) { - if (fastboot_set_reboot_flag()) + if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_BOOTLOADER)) fastboot_fail("Cannot set reboot flag", response); else fastboot_okay(NULL, response); diff --git a/drivers/fastboot/fb_common.c b/drivers/fastboot/fb_common.c index c3735a44af74..736ce1cd024f 100644 --- a/drivers/fastboot/fb_common.c +++ b/drivers/fastboot/fb_common.c @@ -88,7 +88,7 @@ void fastboot_okay(const char *reason, char *response) * which sets whatever flag your board specific Android bootloader flow * requires in order to re-enter the bootloader. */ -int __weak fastboot_set_reboot_flag(void) +int __weak fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) { return -ENOSYS; } diff --git a/include/fastboot.h b/include/fastboot.h index 1933b1d98e3b..14f4c68868d8 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -40,6 +40,14 @@ enum { FASTBOOT_COMMAND_COUNT };
+/** + * Reboot reasons + */ +enum fastboot_reboot_reason { + FASTBOOT_REBOOT_REASON_BOOTLOADER, + FASTBOOT_REBOOT_REASONS_COUNT +}; + /** * fastboot_response() - Writes a response of the form "$tag$reason". * @@ -77,7 +85,7 @@ void fastboot_okay(const char *reason, char *response); * which sets whatever flag your board specific Android bootloader flow * requires in order to re-enter the bootloader. */ -int fastboot_set_reboot_flag(void); +int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason);
/** * fastboot_set_progress_callback() - set progress callback

Android 10 adds support for dynamic partitions and in order to support this userspace fastboot must be used[1]. New tool fastbootd is included into recovery.
Userspace fastboot works from recovery and is launched if: 1) - Dynamic partitioning is enabled 2) - Boot control block has 'boot-fastboot' value into command field The bootloader is expected to load and boot into the recovery image upon seeing boot-fastboot in the BCB command. Recovery then parses the BCB message and switches to fastbootd mode[2].
Please note that boot script is expected to handle 'boot-fastboot' command in BCB and load into recovery mode.
Bootloader must support 'reboot fastboot' command which should reboot device into userspace fastboot to accomodate those changes[3].
Another command that bootloader must support[3] is 'reboot recovery'. This command should simply reboot device into recovery mode.
[1] - https://source.android.com/devices/bootloader/fastbootd [2] - https://source.android.com/devices/bootloader/fastbootd#unified_fastboot_and... [3] - https://source.android.com/devices/bootloader/fastbootd#modifications_to_the...
Signed-off-by: Roman Kovalivskyi roman.kovalivskyi@globallogic.com Signed-off-by: Roman Stratiienko r.stratiienko@gmail.com Change-Id: I9d2bdc9a6f6f31ea98572fe155e1cc8341e9af76 --- drivers/fastboot/fb_command.c | 38 +++++++++++++++++++++++++++++++++ drivers/usb/gadget/f_fastboot.c | 2 ++ include/fastboot.h | 4 ++++ net/fastboot.c | 2 ++ 4 files changed, 46 insertions(+)
diff --git a/drivers/fastboot/fb_command.c b/drivers/fastboot/fb_command.c index 8ce5d32fb2ba..d3c578672dc6 100644 --- a/drivers/fastboot/fb_command.c +++ b/drivers/fastboot/fb_command.c @@ -37,6 +37,8 @@ static void flash(char *, char *); static void erase(char *, char *); #endif static void reboot_bootloader(char *, char *); +static void reboot_fastbootd(char *, char *); +static void reboot_recovery(char *, char *); #if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT) static void oem_format(char *, char *); #endif @@ -79,6 +81,14 @@ static const struct { .command = "reboot-bootloader", .dispatch = reboot_bootloader }, + [FASTBOOT_COMMAND_REBOOT_FASTBOOTD] = { + .command = "reboot-fastboot", + .dispatch = reboot_fastbootd + }, + [FASTBOOT_COMMAND_REBOOT_RECOVERY] = { + .command = "reboot-recovery", + .dispatch = reboot_recovery + }, [FASTBOOT_COMMAND_SET_ACTIVE] = { .command = "set_active", .dispatch = okay @@ -313,6 +323,34 @@ static void reboot_bootloader(char *cmd_parameter, char *response) fastboot_okay(NULL, response); }
+/** + * reboot_fastbootd() - Sets reboot fastboot flag. + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + */ +static void reboot_fastbootd(char *cmd_parameter, char *response) +{ + if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_FASTBOOTD)) + fastboot_fail("Cannot set fastboot flag", response); + else + fastboot_okay(NULL, response); +} + +/** + * reboot_recovery() - Sets reboot recovery flag. + * + * @cmd_parameter: Pointer to command parameter + * @response: Pointer to fastboot response buffer + */ +static void reboot_recovery(char *cmd_parameter, char *response) +{ + if (fastboot_set_reboot_flag(FASTBOOT_REBOOT_REASON_RECOVERY)) + fastboot_fail("Cannot set recovery flag", response); + else + fastboot_okay(NULL, response); +} + #if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT) /** * oem_format() - Execute the OEM format command diff --git a/drivers/usb/gadget/f_fastboot.c b/drivers/usb/gadget/f_fastboot.c index 384c0f6f6e27..30f7a52087fc 100644 --- a/drivers/usb/gadget/f_fastboot.c +++ b/drivers/usb/gadget/f_fastboot.c @@ -455,6 +455,8 @@ static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
case FASTBOOT_COMMAND_REBOOT: case FASTBOOT_COMMAND_REBOOT_BOOTLOADER: + case FASTBOOT_COMMAND_REBOOT_FASTBOOTD: + case FASTBOOT_COMMAND_REBOOT_RECOVERY: fastboot_func->in_req->complete = compl_do_reset; break; } diff --git a/include/fastboot.h b/include/fastboot.h index 14f4c68868d8..b86b508e69fd 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -32,6 +32,8 @@ enum { FASTBOOT_COMMAND_CONTINUE, FASTBOOT_COMMAND_REBOOT, FASTBOOT_COMMAND_REBOOT_BOOTLOADER, + FASTBOOT_COMMAND_REBOOT_FASTBOOTD, + FASTBOOT_COMMAND_REBOOT_RECOVERY, FASTBOOT_COMMAND_SET_ACTIVE, #if CONFIG_IS_ENABLED(FASTBOOT_CMD_OEM_FORMAT) FASTBOOT_COMMAND_OEM_FORMAT, @@ -45,6 +47,8 @@ enum { */ enum fastboot_reboot_reason { FASTBOOT_REBOOT_REASON_BOOTLOADER, + FASTBOOT_REBOOT_REASON_FASTBOOTD, + FASTBOOT_REBOOT_REASON_RECOVERY, FASTBOOT_REBOOT_REASONS_COUNT };
diff --git a/net/fastboot.c b/net/fastboot.c index 0c57fb9947df..7e7a601b9fe6 100644 --- a/net/fastboot.c +++ b/net/fastboot.c @@ -227,6 +227,8 @@ static void fastboot_send(struct fastboot_header header, char *fastboot_data,
case FASTBOOT_COMMAND_REBOOT: case FASTBOOT_COMMAND_REBOOT_BOOTLOADER: + case FASTBOOT_COMMAND_REBOOT_FASTBOOTD: + case FASTBOOT_COMMAND_REBOOT_RECOVERY: do_reset(NULL, 0, 0, NULL); break; }

Default implementation of fastboot_set_reboot_flag function that depends on "bcb" commands could be used in general case if there are no need to make any platform-specific implementation, otherwise it could be disabled via Kconfig option FASTBOOT_USE_BCB_SET_REBOOT_FLAG.
Please note that FASTBOOT_USE_BCB_SET_REBOOT_FLAG is mutually exclusive with some platforms which already have their own implementation of this function.
Signed-off-by: Roman Kovalivskyi roman.kovalivskyi@globallogic.com --- drivers/fastboot/Kconfig | 12 ++++++++++ drivers/fastboot/Makefile | 1 + drivers/fastboot/fb_bcb_impl.c | 43 ++++++++++++++++++++++++++++++++++ include/fastboot.h | 9 +++++++ 4 files changed, 65 insertions(+) create mode 100644 drivers/fastboot/fb_bcb_impl.c
diff --git a/drivers/fastboot/Kconfig b/drivers/fastboot/Kconfig index d4436dfc9173..4352ba67a713 100644 --- a/drivers/fastboot/Kconfig +++ b/drivers/fastboot/Kconfig @@ -165,6 +165,18 @@ config FASTBOOT_CMD_OEM_FORMAT relies on the env variable partitions to contain the list of partitions as required by the gpt command.
+config FASTBOOT_USE_BCB_SET_REBOOT_FLAG + bool "Use BCB by fastboot to set boot reason" + depends on CMD_BCB && !ARCH_MESON && !ARCH_ROCKCHIP && !TARGET_KC1 && \ + !TARGET_SNIPER && !TARGET_AM57XX_EVM && !TARGET_DRA7XX_EVM + default y + help + Fastboot could implement setting of reboot reason in a generic fashion + via BCB commands. BCB commands are able to write reboot reason into + command field of boot control block. In general case it is sufficient + implementation if your platform supports BCB commands and doesn't + require any specific reboot reason handling. + endif # FASTBOOT
endmenu diff --git a/drivers/fastboot/Makefile b/drivers/fastboot/Makefile index 048af5aa8234..2b2c390fe4de 100644 --- a/drivers/fastboot/Makefile +++ b/drivers/fastboot/Makefile @@ -5,3 +5,4 @@ obj-y += fb_getvar.o obj-y += fb_command.o obj-$(CONFIG_FASTBOOT_FLASH_MMC) += fb_mmc.o obj-$(CONFIG_FASTBOOT_FLASH_NAND) += fb_nand.o +obj-$(CONFIG_FASTBOOT_USE_BCB_SET_REBOOT_FLAG) += fb_bcb_impl.o diff --git a/drivers/fastboot/fb_bcb_impl.c b/drivers/fastboot/fb_bcb_impl.c new file mode 100644 index 000000000000..89ec3601b6f6 --- /dev/null +++ b/drivers/fastboot/fb_bcb_impl.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2020 GlobalLogic. + * Roman Kovalivskyi roman.kovalivskyi@globallogic.com + */ + +#include <common.h> +#include <fastboot.h> + +/** + * fastboot_set_reboot_flag() - Set flag to indicate reboot-bootloader + * + * Set flag which indicates that we should reboot into the bootloader + * following the reboot that fastboot executes after this function. + * + * This function should be overridden in your board file with one + * which sets whatever flag your board specific Android bootloader flow + * requires in order to re-enter the bootloader. + */ +int fastboot_set_reboot_flag(enum fastboot_reboot_reason reason) +{ + char cmd[64]; + + if (reason >= FASTBOOT_REBOOT_REASONS_COUNT) + return -EINVAL; + + snprintf(cmd, sizeof(cmd), "bcb load %d misc", + CONFIG_FASTBOOT_FLASH_MMC_DEV); + + if (run_command(cmd, 0)) + return -ENODEV; + + snprintf(cmd, sizeof(cmd), "bcb set command %s", + fastboot_boot_cmds[reason]); + + if (run_command(cmd, 0)) + return -ENOEXEC; + + if (run_command("bcb store", 0)) + return -EIO; + + return 0; +} diff --git a/include/fastboot.h b/include/fastboot.h index b86b508e69fd..8e9ee80907df 100644 --- a/include/fastboot.h +++ b/include/fastboot.h @@ -52,6 +52,15 @@ enum fastboot_reboot_reason { FASTBOOT_REBOOT_REASONS_COUNT };
+/** + * BCB boot commands + */ +static const char * const fastboot_boot_cmds[] = { + [FASTBOOT_REBOOT_REASON_BOOTLOADER] = "bootonce-bootloader", + [FASTBOOT_REBOOT_REASON_FASTBOOTD] = "boot-fastboot", + [FASTBOOT_REBOOT_REASON_RECOVERY] = "boot-recovery" +}; + /** * fastboot_response() - Writes a response of the form "$tag$reason". *
participants (1)
-
Roman Kovalivskyi