[U-Boot] [PATCH 6/6] cmd: Add "boot_android" command.

Stanislas BERTRAND sbertrand at witekio.com
Thu Apr 19 17:21:33 UTC 2018


Hi Alex,

I used work available in https://android.googlesource.com/platform/external/u-boot/+/android-o-mr1-iot-preview-7.
I selected the n-iot-preview-4 because it is U-Boot version 2017.01 which is compatible with TI U-Boot work.

One quick feedback about the boot_android :

> The new "boot_android" command simply executes the Android Bootloader
> flow. This receives the location (interface, dev, partition) of the
> Android "misc" partition which is then used to lookup and infer the
> kernel and system images that should be booted from the passed slot.
> 
> Test: Booted a rpi3 build with Android Things.
> Signed-off-by: Alex Deymo <deymo at google.com>
> ---
>  README             |   6 +++
>  cmd/Kconfig        |  10 +++++
>  cmd/Makefile       |   1 +
>  cmd/boot_android.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 143 insertions(+)
>  create mode 100644 cmd/boot_android.c
> 
> diff --git a/README b/README
> index 384cc6aabb..5f62e14d94 100644
> --- a/README
> +++ b/README
> @@ -1484,6 +1484,12 @@ The following options need to be configured:
>  		sending again an USB request to the device.
>  
>  - Android Bootloader support:
> +		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.
> +
>  		CONFIG_ANDROID_BOOTLOADER
>  		This enables support for the Android bootloader flow. Android
>  		devices can boot in normal mode, recovery mode or bootloader
> diff --git a/cmd/Kconfig b/cmd/Kconfig
> index 87a445d269..c4c22464b1 100644
> --- a/cmd/Kconfig
> +++ b/cmd/Kconfig
> @@ -431,6 +431,16 @@ config CMD_LOAD_ANDROID
>  	  define the size and kernel address on the header, which are used by
>  	  this command.
>  
> +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.
> +
>  config CMD_FLASH
>  	bool "flinfo, erase, protect"
>  	default y
> diff --git a/cmd/Makefile b/cmd/Makefile
> index 2f75dab040..348cf75386 100644
> --- a/cmd/Makefile
> +++ b/cmd/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_CMD_BDI) += bdinfo.o
>  obj-$(CONFIG_CMD_BEDBUG) += bedbug.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_BOOTEFI) += bootefi.o
>  obj-$(CONFIG_CMD_BOOTMENU) += bootmenu.o
>  obj-$(CONFIG_CMD_BOOTLDR) += bootldr.o
> diff --git a/cmd/boot_android.c b/cmd/boot_android.c
> new file mode 100644
> index 0000000000..067d9c7637
> --- /dev/null
> +++ b/cmd/boot_android.c
> @@ -0,0 +1,126 @@
> +/*
> + * Copyright (C) 2016 The Android Open Source Project
> + *
> + * SPDX-License-Identifier: BSD-2-Clause
> + */
> +
> +#include <android_bootloader.h>
> +#include <common.h>
> +#include <command.h>
> +
> +/**
> + * part_get_info_by_dev_and_name - Parse a device number and partition name
> + * string in the form of "device_num;partition_name", for example "0;misc".
> + * If the partition is found, sets dev_desc and part_info accordingly with the
> + * information of the partition with the given partition_name.
> + *
> + * @dev_iface:		Device interface.
> + * @dev_part_str:	Input string argument, like "0;misc".
> + * @dev_desc:		Place to put the device description pointer.
> + * @part_info:		Place to put the partition information.
> + * @return 0 on success, or -1 on error
> + */
> +static int part_get_info_by_dev_and_name(const char *dev_iface,
> +					 const char *dev_part_str,
> +					 struct blk_desc **dev_desc,
> +					 disk_partition_t *part_info)
> +{
> +	char *ep;
> +	const char *part_str;
> +	int dev_num;
> +
> +	part_str = strchr(dev_part_str, ';');
> +	if (!part_str)
> +		return -1;
> +
> +	dev_num = simple_strtoul(dev_part_str, &ep, 16);
> +	if (ep != part_str) {
> +		/* Not all the first part before the ; was parsed. */
> +		return -1;
> +	}
> +	part_str++;
> +
> +	*dev_desc = blk_get_dev(dev_iface, dev_num);
> +	if (!*dev_desc) {
> +		printf("Could not find %s %d\n", dev_iface, dev_num);
> +		return -1;
> +	}
> +	if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) {
> +		printf("Could not find \"%s\" partition\n", part_str);
> +		return -1;
> +	}
> +	return 0;
> +}
> +
> +static int do_boot_android(cmd_tbl_t *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;
> +	disk_partition_t 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 = getenv("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(misc_part_iface, misc_part_desc,
> +					  &dev_desc, &part_info) < 0) {
> +		/* Couldn't lookup by name from mmc, try looking up the
> +		 * partition description directly.
> +		 */
> +		if (blk_get_device_part_str(misc_part_iface, misc_part_desc,
> +					    &dev_desc, &part_info, 1) < 0) {
> +			printf("Couldn't find partition %s %s\n",
> +			       misc_part_iface, misc_part_desc);
> +			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"

The part name will be used to find the partition if `;` is used. `;` is the command delimiter
for u-boot commands. When using it with the `boot` partition, the `boot` command would
be executed and boot_android would return a failure. 

Could part number and part name be handle in software, if name lookup fails, try a
number conversion.

> +	"    - 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"
> +);
> --
>


More information about the U-Boot mailing list