All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/5] bootstd: Add Android support
@ 2024-06-13 10:13 Mattijs Korpershoek
  2024-06-13 10:13 ` [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() Mattijs Korpershoek
                   ` (7 more replies)
  0 siblings, 8 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-13 10:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek

Android boot flow is a bit different than a regular Linux distro.
Android relies on multiple partitions in order to boot.

A typical boot flow would be:
1. Parse the Bootloader Control Block (BCB, misc partition)
2. If BCB requested bootonce-bootloader, start fastboot and wait.
3. If BCB requested recovery or normal android, run the following:
   a. Get slot (A/B) from BCB
   b. Run AVB (Android Verified Boot) on boot partitions
   c. Load boot and vendor_boot partitions
   d. Load device-tree, ramdisk and boot

The AOSP documentation has more details at [1], [2], [3]

This has been implemented via complex boot scripts such as [4].
However, these boot script are neither very maintainable nor generic.
Moreover, DISTRO_DEFAULTS is being deprecated [5].

Add a generic Android bootflow implementation for bootstd.

For this initial version, only boot image v4 is supported.

This has been tested on sandbox using:
$ ./test/py/test.py --bd sandbox --build -k test_ut

This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
To test on TI board, the following (WIP) patch is needed as well:
https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04

[1] https://source.android.com/docs/core/architecture/bootloader
[2] https://source.android.com/docs/core/architecture/partitions
[3] https://source.android.com/docs/core/architecture/partitions/generic-boot
[4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
[5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
[6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html

Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
---
Changes in v2:
- Dropped patch 2/6 boot: android: Add image_android_get_version() (Igor)
- Fixed multi-line comment style (Igor, Simon)
- Added dependency on CMD_FASTBOOT for BOOTMETH_ANDROID (Igor)
- Fixed various resource leaks (Igor)
- Fixed bootmeth_priv dangling pointer on error cases (Igor)
- Updated test instructions in commit message for patch 6/6
- Added __weak impl of get_avendor_bootimg_addr() in patch 1 (dropped
  Igor's review because of this change)
- Added extra info in Kconfig to detail MMC limitation (Simon)
- Fixed typo Bootmethod->Bootmeth (Simon)
- Documented android_priv structure (Simon)
- Demoted various messages from printf() to log_debug (Simon)
- Fixed some lines too long (Simon)
- Added function documentation to read_slotted_partition() (Simon)
- Added some doc about avb extra_args being modified (Simon)
- Link to v1: https://lore.kernel.org/r/20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com

---
Mattijs Korpershoek (5):
      boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
      bootstd: Add bootflow_iter_check_mmc() helper
      android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
      bootstd: Add a bootmeth for Android
      bootstd: Add test for bootmeth_android

 MAINTAINERS               |   7 +
 arch/sandbox/dts/test.dts |   8 +
 boot/Kconfig              |  16 ++
 boot/Makefile             |   2 +
 boot/bootflow.c           |  12 +
 boot/bootmeth_android.c   | 553 ++++++++++++++++++++++++++++++++++++++++++++++
 boot/bootmeth_android.h   |  29 +++
 boot/image-android.c      |   5 +
 boot/image-fdt.c          |   2 +-
 cmd/abootimg.c            |  10 +
 configs/sandbox_defconfig |   2 +-
 doc/develop/bootstd.rst   |   6 +
 include/bootflow.h        |   9 +
 include/image.h           |  14 ++
 test/boot/bootflow.c      |  65 +++++-
 test/py/tests/test_ut.py  |  76 +++++++
 16 files changed, 811 insertions(+), 5 deletions(-)
---
base-commit: f9886bc60f42d5bcfcfa4e474af7dc230400b6be
change-id: 20240605-bootmeth-android-bfc8596e9367

Best regards,
-- 
Mattijs Korpershoek <mkorpershoek@baylibre.com>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
  2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
@ 2024-06-13 10:13 ` Mattijs Korpershoek
  2024-06-13 15:22   ` Simon Glass
                     ` (3 more replies)
  2024-06-13 10:13 ` [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper Mattijs Korpershoek
                   ` (6 subsequent siblings)
  7 siblings, 4 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-13 10:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek

When calling android_image_get_dtb_by_index() using boot image v3+,
we should also pass the vendor_boot ramdisk address.

Use get_avendor_bootimg_addr() to do so.

Notes: on boot image v2, this is harmless since get_avendor_bootimg_addr()
       returns -1.
       for legacy implementations that don't have CMD_ABOOTIMG, add a weak
       implementation to avoid linking errors.

Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
---
 boot/image-android.c | 5 +++++
 boot/image-fdt.c     | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/boot/image-android.c b/boot/image-android.c
index ee626972c114..09c7a44e058a 100644
--- a/boot/image-android.c
+++ b/boot/image-android.c
@@ -56,6 +56,11 @@ static ulong add_trailer(ulong bootconfig_start_addr, ulong bootconfig_size)
 	return BOOTCONFIG_TRAILER_SIZE;
 }
 
+__weak ulong get_avendor_bootimg_addr(void)
+{
+	return -1;
+}
+
 static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 *hdr,
 					       struct andr_image_data *data)
 {
diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index 56dd7687f51c..8332792b8e80 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -502,7 +502,7 @@ int boot_get_fdt(void *buf, const char *select, uint arch,
 		 * Firstly check if this android boot image has dtb field.
 		 */
 		dtb_idx = (u32)env_get_ulong("adtb_idx", 10, 0);
-		if (android_image_get_dtb_by_index((ulong)hdr, 0,
+		if (android_image_get_dtb_by_index((ulong)hdr, get_avendor_bootimg_addr(),
 						   dtb_idx, &fdt_addr, &fdt_size)) {
 			fdt_blob = (char *)map_sysmem(fdt_addr, 0);
 			if (fdt_check_header(fdt_blob))

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper
  2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
  2024-06-13 10:13 ` [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() Mattijs Korpershoek
@ 2024-06-13 10:13 ` Mattijs Korpershoek
  2024-06-13 14:16   ` Julien Masson
  2024-06-13 18:44   ` Guillaume LA ROQUE
  2024-06-13 10:13 ` [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr() Mattijs Korpershoek
                   ` (5 subsequent siblings)
  7 siblings, 2 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-13 10:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek

Some bootflows might be able to only boot from MMC devices.

Add a helper function these bootflows can use.

Reviewed-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
---
 boot/bootflow.c    | 12 ++++++++++++
 include/bootflow.h |  9 +++++++++
 2 files changed, 21 insertions(+)

diff --git a/boot/bootflow.c b/boot/bootflow.c
index 9aa3179c3881..59d77d2385f4 100644
--- a/boot/bootflow.c
+++ b/boot/bootflow.c
@@ -575,6 +575,18 @@ int bootflow_iter_check_blk(const struct bootflow_iter *iter)
 	return -ENOTSUPP;
 }
 
+int bootflow_iter_check_mmc(const struct bootflow_iter *iter)
+{
+	const struct udevice *media = dev_get_parent(iter->dev);
+	enum uclass_id id = device_get_uclass_id(media);
+
+	log_debug("uclass %d: %s\n", id, uclass_get_name(id));
+	if (id == UCLASS_MMC)
+		return 0;
+
+	return -ENOTSUPP;
+}
+
 int bootflow_iter_check_sf(const struct bootflow_iter *iter)
 {
 	const struct udevice *media = dev_get_parent(iter->dev);
diff --git a/include/bootflow.h b/include/bootflow.h
index 080ee8501225..6058ddd89b16 100644
--- a/include/bootflow.h
+++ b/include/bootflow.h
@@ -407,6 +407,15 @@ void bootflow_remove(struct bootflow *bflow);
  */
 int bootflow_iter_check_blk(const struct bootflow_iter *iter);
 
+/**
+ * bootflow_iter_check_mmc() - Check that a bootflow uses a MMC device
+ *
+ * This checks the bootdev in the bootflow to make sure it uses a mmc device
+ *
+ * Return: 0 if OK, -ENOTSUPP if some other device is used (e.g. ethernet)
+ */
+int bootflow_iter_check_mmc(const struct bootflow_iter *iter);
+
 /**
  * bootflow_iter_check_sf() - Check that a bootflow uses SPI FLASH
  *

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
  2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
  2024-06-13 10:13 ` [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() Mattijs Korpershoek
  2024-06-13 10:13 ` [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper Mattijs Korpershoek
@ 2024-06-13 10:13 ` Mattijs Korpershoek
  2024-06-13 14:16   ` Julien Masson
                     ` (2 more replies)
  2024-06-13 10:13 ` [PATCH v2 4/5] bootstd: Add a bootmeth for Android Mattijs Korpershoek
                   ` (4 subsequent siblings)
  7 siblings, 3 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-13 10:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek

The only way to configure the load addresses for both bootimg and
vendor_bootimg is by using the "abootimg" command.
If we want to use the C API, there is no equivalent.

Add set_abootimg_addr() and set_avendor_bootimg_addr() so that we can
specify the load address from C.

This can be useful for implementing an Android bootmethod.

Reviewed-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
---
 cmd/abootimg.c  | 10 ++++++++++
 include/image.h | 14 ++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/cmd/abootimg.c b/cmd/abootimg.c
index 327712a536c0..ae7a1a7c83b0 100644
--- a/cmd/abootimg.c
+++ b/cmd/abootimg.c
@@ -22,6 +22,11 @@ ulong get_abootimg_addr(void)
 	return (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr);
 }
 
+void set_abootimg_addr(ulong addr)
+{
+	_abootimg_addr = addr;
+}
+
 ulong get_ainit_bootimg_addr(void)
 {
 	return _ainit_bootimg_addr;
@@ -32,6 +37,11 @@ ulong get_avendor_bootimg_addr(void)
 	return _avendor_bootimg_addr;
 }
 
+void set_avendor_bootimg_addr(ulong addr)
+{
+	_avendor_bootimg_addr = addr;
+}
+
 static int abootimg_get_ver(int argc, char *const argv[])
 {
 	const struct andr_boot_img_hdr_v0 *hdr;
diff --git a/include/image.h b/include/image.h
index c5b288f62b44..df2decbf5c2a 100644
--- a/include/image.h
+++ b/include/image.h
@@ -1970,6 +1970,13 @@ bool is_android_vendor_boot_image_header(const void *vendor_boot_img);
  */
 ulong get_abootimg_addr(void);
 
+/**
+ * set_abootimg_addr() - Set Android boot image address
+ *
+ * Return: no returned results
+ */
+void set_abootimg_addr(ulong addr);
+
 /**
  * get_ainit_bootimg_addr() - Get Android init boot image address
  *
@@ -1984,6 +1991,13 @@ ulong get_ainit_bootimg_addr(void);
  */
 ulong get_avendor_bootimg_addr(void);
 
+/**
+ * set_abootimg_addr() - Set Android vendor boot image address
+ *
+ * Return: no returned results
+ */
+void set_avendor_bootimg_addr(ulong addr);
+
 /**
  * board_fit_config_name_match() - Check for a matching board name
  *

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 4/5] bootstd: Add a bootmeth for Android
  2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
                   ` (2 preceding siblings ...)
  2024-06-13 10:13 ` [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr() Mattijs Korpershoek
@ 2024-06-13 10:13 ` Mattijs Korpershoek
  2024-06-13 14:19   ` Julien Masson
  2024-06-13 10:13 ` [PATCH v2 5/5] bootstd: Add test for bootmeth_android Mattijs Korpershoek
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-13 10:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek

Android boot flow is a bit different than a regular Linux distro.
Android relies on multiple partitions in order to boot.

A typical boot flow would be:
1. Parse the Bootloader Control Block (BCB, misc partition)
2. If BCB requested bootonce-bootloader, start fastboot and wait.
3. If BCB requested recovery or normal android, run the following:
3.a. Get slot (A/B) from BCB
3.b. Run AVB (Android Verified Boot) on boot partitions
3.c. Load boot and vendor_boot partitions
3.d. Load device-tree, ramdisk and boot

The AOSP documentation has more details at [1], [2], [3]

This has been implemented via complex boot scripts such as [4].
However, these boot script are neither very maintainable nor generic.
Moreover, DISTRO_DEFAULTS is being deprecated [5].

Add a generic Android bootflow implementation for bootstd.
For this initial version, only boot image v4 is supported.

[1] https://source.android.com/docs/core/architecture/bootloader
[2] https://source.android.com/docs/core/architecture/partitions
[3] https://source.android.com/docs/core/architecture/partitions/generic-boot
[4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
[5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
---
 MAINTAINERS             |   7 +
 boot/Kconfig            |  16 ++
 boot/Makefile           |   2 +
 boot/bootmeth_android.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++++
 boot/bootmeth_android.h |  29 +++
 doc/develop/bootstd.rst |   6 +
 6 files changed, 613 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 66783d636e3d..6d2b87720565 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -939,6 +939,13 @@ F:	include/bootstd.h
 F:	net/eth_bootdevice.c
 F:	test/boot/
 
+BOOTMETH_ANDROID
+M:	Mattijs Korpershoek <mkorpershoek@baylibre.com>
+S:	Maintained
+T:	git https://source.denx.de/u-boot/custodians/u-boot-dfu.git
+F:	boot/bootmeth_android.c
+F:	boot/bootmeth_android.h
+
 BTRFS
 M:	Marek Behún <kabel@kernel.org>
 R:	Qu Wenruo <wqu@suse.com>
diff --git a/boot/Kconfig b/boot/Kconfig
index 6f3096c15a6f..88266c8d2ed3 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -494,6 +494,22 @@ config BOOTMETH_GLOBAL
 	  EFI bootmgr, since they take full control over which bootdevs are
 	  selected to boot.
 
+config BOOTMETH_ANDROID
+	bool "Bootdev support for Android"
+	depends on X86 || ARM || SANDBOX
+	select ANDROID_AB
+	select ANDROID_BOOT_IMAGE
+	select CMD_BCB
+	select CMD_FASTBOOT
+	select PARTITION_TYPE_GUID
+	select PARTITION_UUIDS
+	help
+	  Enables support for booting Android using bootstd. Android requires
+	  multiple partitions (misc, boot, vbmeta, ...) in storage for booting.
+
+	  Note that only MMC bootdevs are supported at present. This is caused
+	  by AVB being limited to MMC devices only.
+
 config BOOTMETH_CROS
 	bool "Bootdev support for Chromium OS"
 	depends on X86 || ARM || SANDBOX
diff --git a/boot/Makefile b/boot/Makefile
index 84ccfeaecec4..75d1cd46fabf 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -66,3 +66,5 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_REQUEST) += vbe_request.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE) += vbe_simple.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE_FW) += vbe_simple_fw.o
 obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE_OS) += vbe_simple_os.o
+
+obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_ANDROID) += bootmeth_android.o
diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
new file mode 100644
index 000000000000..6e8d3e615db0
--- /dev/null
+++ b/boot/bootmeth_android.c
@@ -0,0 +1,553 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmeth for Android
+ *
+ * Copyright (C) 2024 BayLibre, SAS
+ * Written by Mattijs Korpershoek <mkorpershoek@baylibre.com>
+ */
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include <android_ab.h>
+#include <android_image.h>
+#if CONFIG_IS_ENABLED(AVB_VERIFY)
+#include <avb_verify.h>
+#endif
+#include <bcb.h>
+#include <blk.h>
+#include <bootflow.h>
+#include <bootm.h>
+#include <bootmeth.h>
+#include <dm.h>
+#include <image.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <part.h>
+#include "bootmeth_android.h"
+
+#define BCB_FIELD_COMMAND_SZ 32
+#define BCB_PART_NAME "misc"
+#define BOOT_PART_NAME "boot"
+#define VENDOR_BOOT_PART_NAME "vendor_boot"
+
+/**
+ * struct android_priv - Private data
+ *
+ * This is read from the disk and recorded for use when the full Android
+ * kernel must be loaded and booted
+ *
+ * @boot_mode: Requested boot mode (normal, recovery, bootloader)
+ * @slot: Nul-terminated partition slot suffix read from BCB ("a\0" or "b\0")
+ * @header_version: Android boot image header version
+ */
+struct android_priv {
+	enum android_boot_mode boot_mode;
+	char slot[2];
+	u32 header_version;
+};
+
+static int android_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+	/* This only works on mmc devices */
+	if (bootflow_iter_check_mmc(iter))
+		return log_msg_ret("mmc", -ENOTSUPP);
+
+	/*
+	 * This only works on whole devices, as multiple
+	 * partitions are needed to boot Android
+	 */
+	if (iter->part != 0)
+		return log_msg_ret("mmc part", -ENOTSUPP);
+
+	return 0;
+}
+
+static int scan_boot_part(struct udevice *blk, struct android_priv *priv)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(blk);
+	struct disk_partition partition;
+	char partname[PART_NAME_LEN];
+	ulong num_blks, bufsz;
+	char *buf;
+	int ret;
+
+	sprintf(partname, BOOT_PART_NAME "_%s", priv->slot);
+	ret = part_get_info_by_name(desc, partname, &partition);
+	if (ret < 0)
+		return log_msg_ret("part info", ret);
+
+	num_blks = DIV_ROUND_UP(sizeof(struct andr_boot_img_hdr_v0), desc->blksz);
+	bufsz = num_blks * desc->blksz;
+	buf = malloc(bufsz);
+	if (!buf)
+		return log_msg_ret("buf", -ENOMEM);
+
+	ret = blk_read(blk, partition.start, num_blks, buf);
+	if (ret != num_blks) {
+		free(buf);
+		return log_msg_ret("part read", -EIO);
+	}
+
+	if (!is_android_boot_image_header(buf)) {
+		free(buf);
+		return log_msg_ret("header", -ENOENT);
+	}
+
+	priv->header_version = ((struct andr_boot_img_hdr_v0 *)buf)->header_version;
+	free(buf);
+
+	return 0;
+}
+
+static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(blk);
+	struct disk_partition partition;
+	char partname[PART_NAME_LEN];
+	ulong num_blks, bufsz;
+	char *buf;
+	int ret;
+
+	sprintf(partname, VENDOR_BOOT_PART_NAME "_%s", priv->slot);
+	ret = part_get_info_by_name(desc, partname, &partition);
+	if (ret < 0)
+		return log_msg_ret("part info", ret);
+
+	num_blks = DIV_ROUND_UP(sizeof(struct andr_vnd_boot_img_hdr), desc->blksz);
+	bufsz = num_blks * desc->blksz;
+	buf = malloc(bufsz);
+	if (!buf)
+		return log_msg_ret("buf", -ENOMEM);
+
+	ret = blk_read(blk, partition.start, num_blks, buf);
+	if (ret != num_blks) {
+		free(buf);
+		return log_msg_ret("part read", -EIO);
+	}
+
+	if (!is_android_vendor_boot_image_header(buf)) {
+		free(buf);
+		return log_msg_ret("header", -ENOENT);
+	}
+	free(buf);
+
+	return 0;
+}
+
+static int android_read_slot_from_bcb(struct bootflow *bflow, bool decrement)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	struct android_priv *priv = bflow->bootmeth_priv;
+	struct disk_partition misc;
+	char slot_suffix[3];
+	int ret;
+
+	ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc);
+	if (ret < 0)
+		return log_msg_ret("part", ret);
+
+	ret = ab_select_slot(desc, &misc, decrement);
+	if (ret < 0)
+		return log_msg_ret("slot", ret);
+
+	priv->slot[0] = BOOT_SLOT_NAME(ret);
+	priv->slot[1] = '\0';
+
+	sprintf(slot_suffix, "_%s", priv->slot);
+	ret = bootflow_cmdline_set_arg(bflow, "androidboot.slot_suffix",
+				       slot_suffix, false);
+	if (ret < 0)
+		return log_msg_ret("cmdl", ret);
+
+	return 0;
+}
+
+static int configure_serialno(struct bootflow *bflow)
+{
+	char *serialno = env_get("serial#");
+
+	if (!serialno)
+		return log_msg_ret("serial", -ENOENT);
+
+	return bootflow_cmdline_set_arg(bflow, "androidboot.serialno", serialno, false);
+}
+
+static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	struct disk_partition misc;
+	struct android_priv *priv;
+	char command[BCB_FIELD_COMMAND_SZ];
+	int ret;
+
+	bflow->state = BOOTFLOWST_MEDIA;
+
+	/*
+	 * bcb_find_partition_and_load() will print errors to stdout
+	 * if BCB_PART_NAME is not found. To avoid that, check if the
+	 * partition exists first.
+	 */
+	ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc);
+	if (ret < 0)
+		return log_msg_ret("part", ret);
+
+	ret = bcb_find_partition_and_load("mmc", desc->devnum, BCB_PART_NAME);
+	if (ret < 0)
+		return log_msg_ret("bcb load", ret);
+
+	ret = bcb_get(BCB_FIELD_COMMAND, command, sizeof(command));
+	if (ret < 0)
+		return log_msg_ret("bcb read", ret);
+
+	priv = malloc(sizeof(struct android_priv));
+	if (!priv)
+		return log_msg_ret("buf", -ENOMEM);
+
+	if (!strcmp("bootonce-bootloader", command)) {
+		priv->boot_mode = ANDROID_BOOT_MODE_BOOTLOADER;
+		bflow->os_name = strdup("Android (bootloader)");
+	} else if (!strcmp("boot-fastboot", command)) {
+		priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY;
+		bflow->os_name = strdup("Android (fastbootd)");
+	} else if (!strcmp("boot-recovery", command)) {
+		priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY;
+		bflow->os_name = strdup("Android (recovery)");
+	} else {
+		priv->boot_mode = ANDROID_BOOT_MODE_NORMAL;
+		bflow->os_name = strdup("Android");
+	}
+	if (!bflow->os_name)
+		return log_msg_ret("os", -ENOMEM);
+
+	if (priv->boot_mode == ANDROID_BOOT_MODE_BOOTLOADER) {
+		/* Clear BCB */
+		memset(command, 0, sizeof(command));
+		ret = bcb_set(BCB_FIELD_COMMAND, command);
+		if (ret < 0) {
+			free(priv);
+			return log_msg_ret("bcb set", ret);
+		}
+		ret = bcb_store();
+		if (ret < 0) {
+			free(priv);
+			return log_msg_ret("bcb store", ret);
+		}
+
+		bflow->bootmeth_priv = priv;
+		bflow->state = BOOTFLOWST_READY;
+		return 0;
+	}
+
+	bflow->bootmeth_priv = priv;
+
+	/* For recovery and normal boot, we need to scan the partitions */
+	ret = android_read_slot_from_bcb(bflow, false);
+	if (ret < 0) {
+		log_err("read slot: %d", ret);
+		goto free_priv;
+	}
+
+	ret = scan_boot_part(bflow->blk, priv);
+	if (ret < 0) {
+		log_debug("scan boot failed: err=%d\n", ret);
+		goto free_priv;
+	}
+
+	if (priv->header_version != 4) {
+		log_debug("only boot.img v4 is supported %u\n", priv->header_version);
+		ret = -EINVAL;
+		goto free_priv;
+	}
+
+	ret = scan_vendor_boot_part(bflow->blk, priv);
+	if (ret < 0) {
+		log_debug("scan vendor_boot failed: err=%d\n", ret);
+		goto free_priv;
+	}
+
+	/* Ignoring return code: setting serial number is not mandatory for booting */
+	configure_serialno(bflow);
+
+	if (priv->boot_mode == ANDROID_BOOT_MODE_NORMAL) {
+		ret = bootflow_cmdline_set_arg(bflow, "androidboot.force_normal_boot",
+					       "1", false);
+		if (ret < 0) {
+			log_debug("normal_boot %d", ret);
+			goto free_priv;
+		}
+	}
+
+	bflow->state = BOOTFLOWST_READY;
+
+	return 0;
+
+ free_priv:
+	free(priv);
+	bflow->bootmeth_priv = NULL;
+	return ret;
+}
+
+static int android_read_file(struct udevice *dev, struct bootflow *bflow,
+			     const char *file_path, ulong addr, ulong *sizep)
+{
+	/*
+	 * Reading individual files is not supported since we only
+	 * operate on whole mmc devices (because we require multiple partitions)
+	 */
+	return log_msg_ret("Unsupported", -ENOSYS);
+}
+
+/**
+ * read_slotted_partition() - Read a partition by appending a slot suffix
+ *
+ * Most modern Android devices use Seamless Updates, where each partition
+ * is duplicated. For example, the boot partition has boot_a and boot_b.
+ * For more information, see:
+ * https://source.android.com/docs/core/ota/ab
+ * https://source.android.com/docs/core/ota/ab/ab_implement
+ *
+ * @blk: Block device to read
+ * @name: Partition name to read
+ * @slot: Nul-terminated slot suffixed to partition name ("a\0" or "b\0")
+ * @addr: Address where the partition content is loaded into
+ * Return: 0 if OK, negative errno on failure.
+ */
+static int read_slotted_partition(struct blk_desc *desc, const char *const name,
+				  const char slot[2], ulong addr)
+{
+	struct disk_partition partition;
+	char partname[PART_NAME_LEN];
+	int ret;
+	u32 n;
+
+	/* Ensure name fits in partname it should be: <name>_<slot>\0 */
+	if (strlen(name) > (PART_NAME_LEN - 2 - 1))
+		return log_msg_ret("name too long", -EINVAL);
+
+	sprintf(partname, "%s_%s", name, slot);
+	ret = part_get_info_by_name(desc, partname, &partition);
+	if (ret < 0)
+		return log_msg_ret("part", ret);
+
+	n = blk_dread(desc, partition.start, partition.size, map_sysmem(addr, 0));
+	if (n < partition.size)
+		return log_msg_ret("part read", -EIO);
+
+	return 0;
+}
+
+#if CONFIG_IS_ENABLED(AVB_VERIFY)
+static int avb_append_commandline_arg(struct bootflow *bflow, char *arg)
+{
+	char *key = strsep(&arg, "=");
+	char *value = arg;
+	int ret;
+
+	ret = bootflow_cmdline_set_arg(bflow, key, value, false);
+	if (ret < 0)
+		return log_msg_ret("avb cmdline", ret);
+
+	return 0;
+}
+
+static int avb_append_commandline(struct bootflow *bflow, char *cmdline)
+{
+	char *arg = strsep(&cmdline, " ");
+	int ret;
+
+	while (arg) {
+		ret = avb_append_commandline_arg(bflow, arg);
+		if (ret < 0)
+			return ret;
+
+		arg = strsep(&cmdline, " ");
+	}
+
+	return 0;
+}
+
+static int run_avb_verification(struct bootflow *bflow)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	struct android_priv *priv = bflow->bootmeth_priv;
+	const char * const requested_partitions[] = {"boot", "vendor_boot"};
+	struct AvbOps *avb_ops;
+	AvbSlotVerifyResult result;
+	AvbSlotVerifyData *out_data;
+	enum avb_boot_state boot_state;
+	char *extra_args;
+	char slot_suffix[3];
+	bool unlocked = false;
+	int ret;
+
+	avb_ops = avb_ops_alloc(desc->devnum);
+	if (!avb_ops)
+		return log_msg_ret("avb ops", -ENOMEM);
+
+	sprintf(slot_suffix, "_%s", priv->slot);
+
+	ret = avb_ops->read_is_device_unlocked(avb_ops, &unlocked);
+	if (ret != AVB_IO_RESULT_OK)
+		return log_msg_ret("avb lock", -EIO);
+
+	result = avb_slot_verify(avb_ops,
+				 requested_partitions,
+				 slot_suffix,
+				 unlocked,
+				 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
+				 &out_data);
+
+	if (result != AVB_SLOT_VERIFY_RESULT_OK) {
+		printf("Verification failed, reason: %s\n",
+		       str_avb_slot_error(result));
+		avb_slot_verify_data_free(out_data);
+		return log_msg_ret("avb verify", -EIO);
+	}
+
+	if (unlocked)
+		boot_state = AVB_ORANGE;
+	else
+		boot_state = AVB_GREEN;
+
+	extra_args = avb_set_state(avb_ops, boot_state);
+	if (extra_args) {
+		/* extra_args will be modified after this. This is fine */
+		ret = avb_append_commandline_arg(bflow, extra_args);
+		if (ret < 0)
+			goto free_out_data;
+	}
+
+	ret = avb_append_commandline(bflow, out_data->cmdline);
+	if (ret < 0)
+		goto free_out_data;
+
+	return 0;
+
+ free_out_data:
+	if (out_data)
+		avb_slot_verify_data_free(out_data);
+
+	return log_msg_ret("avb cmdline", ret);
+}
+#else
+static int run_avb_verification(struct bootflow *bflow)
+{
+	int ret;
+
+	/* When AVB is unsupported, pass ORANGE state  */
+	ret = bootflow_cmdline_set_arg(bflow,
+				       "androidboot.verifiedbootstate",
+				       "orange", false);
+	if (ret < 0)
+		return log_msg_ret("avb cmdline", ret);
+
+	return 0;
+}
+#endif /* AVB_VERIFY */
+
+static int boot_android_normal(struct bootflow *bflow)
+{
+	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
+	struct android_priv *priv = bflow->bootmeth_priv;
+	int ret;
+	ulong loadaddr = env_get_hex("loadaddr", 0);
+	ulong vloadaddr = env_get_hex("vendor_boot_comp_addr_r", 0);
+
+	ret = run_avb_verification(bflow);
+	if (ret < 0)
+		return log_msg_ret("avb", ret);
+
+	/* Read slot once more to decrement counter from BCB */
+	ret = android_read_slot_from_bcb(bflow, true);
+	if (ret < 0)
+		return log_msg_ret("read slot", ret);
+
+	ret = read_slotted_partition(desc, "boot", priv->slot, loadaddr);
+	if (ret < 0)
+		return log_msg_ret("read boot", ret);
+
+	ret = read_slotted_partition(desc, "vendor_boot", priv->slot, vloadaddr);
+	if (ret < 0)
+		return log_msg_ret("read vendor_boot", ret);
+
+	set_abootimg_addr(loadaddr);
+	set_avendor_bootimg_addr(vloadaddr);
+
+	ret = bootm_boot_start(loadaddr, bflow->cmdline);
+
+	return log_msg_ret("boot", ret);
+}
+
+static int boot_android_recovery(struct bootflow *bflow)
+{
+	int ret;
+
+	ret = boot_android_normal(bflow);
+
+	return log_msg_ret("boot", ret);
+}
+
+static int boot_android_bootloader(struct bootflow *bflow)
+{
+	int ret;
+
+	ret = run_command("fastboot usb 0", 0);
+	do_reset(NULL, 0, 0, NULL);
+
+	return log_msg_ret("boot", ret);
+}
+
+static int android_boot(struct udevice *dev, struct bootflow *bflow)
+{
+	struct android_priv *priv = bflow->bootmeth_priv;
+	int ret;
+
+	switch (priv->boot_mode) {
+	case ANDROID_BOOT_MODE_NORMAL:
+		ret = boot_android_normal(bflow);
+		break;
+	case ANDROID_BOOT_MODE_RECOVERY:
+		ret = boot_android_recovery(bflow);
+		break;
+	case ANDROID_BOOT_MODE_BOOTLOADER:
+		ret = boot_android_bootloader(bflow);
+		break;
+	default:
+		printf("ANDROID: Unknown boot mode %d. Running fastboot...\n",
+		       priv->boot_mode);
+		boot_android_bootloader(bflow);
+		/* Tell we failed to boot since boot mode is unknown */
+		ret = -EFAULT;
+	}
+
+	return ret;
+}
+
+static int android_bootmeth_bind(struct udevice *dev)
+{
+	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+	plat->desc = "Android boot";
+	plat->flags = BOOTMETHF_ANY_PART;
+
+	return 0;
+}
+
+static struct bootmeth_ops android_bootmeth_ops = {
+	.check		= android_check,
+	.read_bootflow	= android_read_bootflow,
+	.read_file	= android_read_file,
+	.boot		= android_boot,
+};
+
+static const struct udevice_id android_bootmeth_ids[] = {
+	{ .compatible = "u-boot,android" },
+	{ }
+};
+
+U_BOOT_DRIVER(bootmeth_android) = {
+	.name		= "bootmeth_android",
+	.id		= UCLASS_BOOTMETH,
+	.of_match	= android_bootmeth_ids,
+	.ops		= &android_bootmeth_ops,
+	.bind		= android_bootmeth_bind,
+};
diff --git a/boot/bootmeth_android.h b/boot/bootmeth_android.h
new file mode 100644
index 000000000000..a57fad9f0113
--- /dev/null
+++ b/boot/bootmeth_android.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Bootmethod for Android
+ *
+ * Copyright (C) 2024 BayLibre, SAS
+ * Written by Mattijs Korpershoek <mkorpershoek@baylibre.com>
+ */
+
+enum android_boot_mode {
+	ANDROID_BOOT_MODE_NORMAL = 0,
+
+	/*
+	 * Android "recovery" is a special boot mode that uses another ramdisk.
+	 * It can be used to "factory reset" a board or to flash logical partitions
+	 * It operates in 2 modes: adb or fastbootd
+	 * To enter recovery from Android, we can do:
+	 * $ adb reboot recovery
+	 * $ adb reboot fastboot
+	 */
+	ANDROID_BOOT_MODE_RECOVERY,
+
+	/*
+	 * Android "bootloader" is for accessing/reflashing physical partitions
+	 * Typically, this will launch a fastboot process in U-Boot.
+	 * To enter "bootloader" from Android, we can do:
+	 * $ adb reboot bootloader
+	 */
+	ANDROID_BOOT_MODE_BOOTLOADER,
+};
diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst
index a07a72581e7a..709fa9e64ff3 100644
--- a/doc/develop/bootstd.rst
+++ b/doc/develop/bootstd.rst
@@ -95,6 +95,7 @@ bootflows.
 
 Note: it is possible to have a bootmeth that uses a partition or a whole device
 directly, but it is more common to use a filesystem.
+For example, the Android bootmeth uses a whole device.
 
 Note that some bootmeths are 'global', meaning that they select the bootdev
 themselves. Examples include VBE and EFI boot manager. In this case, they
@@ -277,6 +278,9 @@ script_offset_f
 script_size_f
     Size of the script to load, e.g. 0x2000
 
+vendor_boot_comp_addr_r
+    Address to which to load the vendor_boot Android image, e.g. 0xe0000000
+
 Some variables are set by script bootmeth:
 
 devtype
@@ -418,6 +422,7 @@ Bootmeth drivers are provided for:
    - EFI boot using bootefi from disk
    - VBE
    - EFI boot using boot manager
+   - Android bootflow (boot image v4)
 
 
 Command interface
@@ -786,6 +791,7 @@ To do
 Some things that need to be done to completely replace the distro-boot scripts:
 
 - implement extensions (devicetree overlays with add-on boards)
+- implement legacy (boot image v2) android boot flow
 
 Other ideas:
 

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* [PATCH v2 5/5] bootstd: Add test for bootmeth_android
  2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
                   ` (3 preceding siblings ...)
  2024-06-13 10:13 ` [PATCH v2 4/5] bootstd: Add a bootmeth for Android Mattijs Korpershoek
@ 2024-06-13 10:13 ` Mattijs Korpershoek
  2024-06-13 14:19   ` Julien Masson
  2024-06-13 18:47   ` Guillaume LA ROQUE
  2024-06-14  9:53 ` [PATCH v2 0/5] bootstd: Add Android support Guillaume LA ROQUE
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-13 10:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek

Add a unit test for testing the Android bootmethod.

This requires another mmc image (mmc7) to contain the following partitions:
- misc: contains the Bootloader Control Block (BCB)
- boot_a: contains a fake generic kernel image
- vendor_boot_a: contains a fake vendor_boot image

Also add BOOTMETH_ANDROID as a dependency on sandbox so that we can test
this with:

$ ./test/py/test.py --bd sandbox --build -k test_abootimg # build bootv4.img
$ ./test/py/test.py --bd sandbox --build -k test_ut # build the mmc7.img
$ ./test/py/test.py --bd sandbox --build -k bootflow_android

Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
---
 arch/sandbox/dts/test.dts |  8 +++++
 configs/sandbox_defconfig |  2 +-
 test/boot/bootflow.c      | 65 ++++++++++++++++++++++++++++++++++++++--
 test/py/tests/test_ut.py  | 76 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 147 insertions(+), 4 deletions(-)

diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index a012f5c4c9ba..5fb5eac862ec 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -43,6 +43,7 @@
 		mmc4 = "/mmc4";
 		mmc5 = "/mmc5";
 		mmc6 = "/mmc6";
+		mmc7 = "/mmc7";
 		pci0 = &pci0;
 		pci1 = &pci1;
 		pci2 = &pci2;
@@ -1129,6 +1130,13 @@
 		filename = "mmc6.img";
 	};
 
+	/* This is used for Android tests */
+	mmc7 {
+		status = "disabled";
+		compatible = "sandbox,mmc";
+		filename = "mmc7.img";
+	};
+
 	pch {
 		compatible = "sandbox,pch";
 	};
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 93b52f2de5cf..bc4398f101a7 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -15,6 +15,7 @@ CONFIG_FIT=y
 CONFIG_FIT_RSASSA_PSS=y
 CONFIG_FIT_CIPHER=y
 CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTMETH_ANDROID=y
 CONFIG_LEGACY_IMAGE_FORMAT=y
 CONFIG_MEASURED_BOOT=y
 CONFIG_BOOTSTAGE=y
@@ -40,7 +41,6 @@ CONFIG_LOG_MAX_LEVEL=9
 CONFIG_LOG_DEFAULT_LEVEL=6
 CONFIG_DISPLAY_BOARDINFO_LATE=y
 CONFIG_STACKPROTECTOR=y
-CONFIG_ANDROID_AB=y
 CONFIG_CMD_CPU=y
 CONFIG_CMD_LICENSE=y
 CONFIG_CMD_SMBIOS=y
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index 4511cfa7f9bf..934c4dcbad2b 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -27,6 +27,7 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
+extern U_BOOT_DRIVER(bootmeth_android);
 extern U_BOOT_DRIVER(bootmeth_cros);
 extern U_BOOT_DRIVER(bootmeth_2script);
 
@@ -518,12 +519,12 @@ BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
  * @uts: Unit test state
  * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid
  *	in the caller until
- * @bind_cros: true to bind the ChromiumOS bootmeth
+ * @bind_cros: true to bind the ChromiumOS and Android bootmeths
  * @old_orderp: Returns the original bootdev order, which must be restored
  * Returns 0 on success, -ve on failure
  */
 static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
-			    bool bind_cros, const char ***old_orderp)
+			    bool bind_cros_android, const char ***old_orderp)
 {
 	static const char *order[] = {"mmc2", "mmc1", NULL, NULL};
 	struct udevice *dev, *bootstd;
@@ -545,12 +546,19 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
 				"bootmeth_script", 0, ofnode_null(), &dev));
 
 	/* Enable the cros bootmeth if needed */
-	if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros) {
+	if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) {
 		ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
 		ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros),
 					"cros", 0, ofnode_null(), &dev));
 	}
 
+	/* Enable the android bootmeths if needed */
+	if (IS_ENABLED(CONFIG_BOOTMETH_ANDROID) && bind_cros_android) {
+		ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+		ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_android),
+					"android", 0, ofnode_null(), &dev));
+	}
+
 	/* Change the order to include the device */
 	std = dev_get_priv(bootstd);
 	old_order = std->bootdev_order;
@@ -589,6 +597,37 @@ static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
 	return 0;
 }
 
+/**
+ * scan_mmc_android_bootdev() - Set up an mmc bootdev so we can access other
+ * distros. Android bootflow might print "ANDROID:*" while scanning
+ *
+ * @uts: Unit test state
+ * @mmc_dev: MMC device to use, e.g. "mmc4"
+ * Returns 0 on success, -ve on failure
+ */
+static int scan_mmc_android_bootdev(struct unit_test_state *uts, const char *mmc_dev)
+{
+	struct bootstd_priv *std;
+	struct udevice *bootstd;
+	const char **old_order;
+
+	ut_assertok(prep_mmc_bootdev(uts, mmc_dev, true, &old_order));
+
+	console_record_reset_enable();
+	ut_assertok(run_command("bootflow scan", 0));
+	/* Android bootflow might print one or two 'ANDROID:*' logs */
+	ut_check_skipline(uts);
+	ut_check_skipline(uts);
+	ut_assert_console_end();
+
+	/* Restore the order used by the device tree */
+	ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+	std = dev_get_priv(bootstd);
+	std->bootdev_order = old_order;
+
+	return 0;
+}
+
 /**
  * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian
  *
@@ -1160,3 +1199,23 @@ static int bootflow_cros(struct unit_test_state *uts)
 	return 0;
 }
 BOOTSTD_TEST(bootflow_cros, 0);
+
+/* Test Android bootmeth  */
+static int bootflow_android(struct unit_test_state *uts)
+{
+	ut_assertok(scan_mmc_android_bootdev(uts, "mmc7"));
+	ut_assertok(run_command("bootflow list", 0));
+
+	ut_assert_nextlinen("Showing all");
+	ut_assert_nextlinen("Seq");
+	ut_assert_nextlinen("---");
+	ut_assert_nextlinen("  0  extlinux");
+	ut_assert_nextlinen("  1  android      ready   mmc          0  mmc7.bootdev.whole        ");
+	ut_assert_nextlinen("---");
+	ut_assert_skip_to_line("(2 bootflows, 2 valid)");
+
+	ut_assert_console_end();
+
+	return 0;
+}
+BOOTSTD_TEST(bootflow_android, 0);
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index c169c835e38a..39e1abe02a68 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -423,6 +423,81 @@ def setup_cros_image(cons):
 
     return fname
 
+def setup_android_image(cons):
+    """Create a 20MB disk image with Android partitions"""
+    Partition = collections.namedtuple('part', 'start,size,name')
+    parts = {}
+    disk_data = None
+
+    def set_part_data(partnum, data):
+        """Set the contents of a disk partition
+
+        This updates disk_data by putting data in the right place
+
+        Args:
+            partnum (int): Partition number to set
+            data (bytes): Data for that partition
+        """
+        nonlocal disk_data
+
+        start = parts[partnum].start * sect_size
+        disk_data = disk_data[:start] + data + disk_data[start + len(data):]
+
+    mmc_dev = 7
+    fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img')
+    u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname)
+    u_boot_utils.run_and_log(cons, f'cgpt create {fname}')
+
+    ptr = 40
+
+    # Number of sectors in 1MB
+    sect_size = 512
+    sect_1mb = (1 << 20) // sect_size
+
+    required_parts = [
+        {'num': 1, 'label':'misc', 'size': '1M'},
+        {'num': 2, 'label':'boot_a', 'size': '4M'},
+        {'num': 3, 'label':'boot_b', 'size': '4M'},
+        {'num': 4, 'label':'vendor_boot_a', 'size': '4M'},
+        {'num': 5, 'label':'vendor_boot_b', 'size': '4M'},
+    ]
+
+    for part in required_parts:
+        size_str = part['size']
+        if 'M' in size_str:
+            size = int(size_str[:-1]) * sect_1mb
+        else:
+            size = int(size_str)
+        u_boot_utils.run_and_log(
+            cons,
+            f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}")
+        ptr += size
+
+    u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}')
+    out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}')
+
+    # Create a dict (indexed by partition number) containing the above info
+    for line in out.splitlines():
+        start, size, num, name = line.split(maxsplit=3)
+        parts[int(num)] = Partition(int(start), int(size), name)
+
+    with open(fname, 'rb') as inf:
+        disk_data = inf.read()
+
+    boot_img = os.path.join(cons.config.result_dir, 'bootv4.img')
+    with open(boot_img, 'rb') as inf:
+        set_part_data(2, inf.read())
+
+    vendor_boot_img = os.path.join(cons.config.result_dir, 'vendor_boot.img')
+    with open(vendor_boot_img, 'rb') as inf:
+        set_part_data(4, inf.read())
+
+    with open(fname, 'wb') as outf:
+        outf.write(disk_data)
+
+    print('wrote to {}'.format(fname))
+
+    return fname
 
 def setup_cedit_file(cons):
     infname = os.path.join(cons.config.source_dir,
@@ -477,6 +552,7 @@ def test_ut_dm_init_bootstd(u_boot_console):
     setup_bootmenu_image(u_boot_console)
     setup_cedit_file(u_boot_console)
     setup_cros_image(u_boot_console)
+    setup_android_image(u_boot_console)
 
     # Restart so that the new mmc1.img is picked up
     u_boot_console.restart_uboot()

-- 
2.45.2


^ permalink raw reply related	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper
  2024-06-13 10:13 ` [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper Mattijs Korpershoek
@ 2024-06-13 14:16   ` Julien Masson
  2024-06-13 18:44   ` Guillaume LA ROQUE
  1 sibling, 0 replies; 27+ messages in thread
From: Julien Masson @ 2024-06-13 14:16 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek


On Thu 13 Jun 2024 at 16:15, Mattijs Korpershoek <mkorpershoek@baylibre.com> wrote:

> Some bootflows might be able to only boot from MMC devices.
> 
> Add a helper function these bootflows can use.
> 
> Reviewed-by: Igor Opaniuk <igor.opaniuk@gmail.com>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>  boot/bootflow.c    | 12 ++++++++++++
>  include/bootflow.h |  9 +++++++++
>  2 files changed, 21 insertions(+)
> 
> diff --git a/boot/bootflow.c b/boot/bootflow.c
> index 9aa3179c3881..59d77d2385f4 100644
> --- a/boot/bootflow.c
> +++ b/boot/bootflow.c
> @@ -575,6 +575,18 @@ int bootflow_iter_check_blk(const struct bootflow_iter *iter)
>  	return -ENOTSUPP;
>  }
>  
> +int bootflow_iter_check_mmc(const struct bootflow_iter *iter)
> +{
> +	const struct udevice *media = dev_get_parent(iter->dev);
> +	enum uclass_id id = device_get_uclass_id(media);
> +
> +	log_debug("uclass %d: %s\n", id, uclass_get_name(id));
> +	if (id == UCLASS_MMC)
> +		return 0;
> +
> +	return -ENOTSUPP;
> +}
> +
>  int bootflow_iter_check_sf(const struct bootflow_iter *iter)
>  {
>  	const struct udevice *media = dev_get_parent(iter->dev);
> diff --git a/include/bootflow.h b/include/bootflow.h
> index 080ee8501225..6058ddd89b16 100644
> --- a/include/bootflow.h
> +++ b/include/bootflow.h
> @@ -407,6 +407,15 @@ void bootflow_remove(struct bootflow *bflow);
>   */
>  int bootflow_iter_check_blk(const struct bootflow_iter *iter);
>  
> +/**
> + * bootflow_iter_check_mmc() - Check that a bootflow uses a MMC device
> + *
> + * This checks the bootdev in the bootflow to make sure it uses a mmc device
> + *
> + * Return: 0 if OK, -ENOTSUPP if some other device is used (e.g. ethernet)
> + */
> +int bootflow_iter_check_mmc(const struct bootflow_iter *iter);
> +
>  /**
>   * bootflow_iter_check_sf() - Check that a bootflow uses SPI FLASH
>   *
> 
> -- 
> 2.45.2
> 

Reviewed-by: Julien Masson <jmasson@baylibre.com>
-- 
Julien Masson

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
  2024-06-13 10:13 ` [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr() Mattijs Korpershoek
@ 2024-06-13 14:16   ` Julien Masson
  2024-06-13 15:20   ` Simon Glass
  2024-06-13 18:45   ` Guillaume LA ROQUE
  2 siblings, 0 replies; 27+ messages in thread
From: Julien Masson @ 2024-06-13 14:16 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek


On Thu 13 Jun 2024 at 16:16, Mattijs Korpershoek <mkorpershoek@baylibre.com> wrote:

> The only way to configure the load addresses for both bootimg and
> vendor_bootimg is by using the "abootimg" command.
> If we want to use the C API, there is no equivalent.
> 
> Add set_abootimg_addr() and set_avendor_bootimg_addr() so that we can
> specify the load address from C.
> 
> This can be useful for implementing an Android bootmethod.
> 
> Reviewed-by: Igor Opaniuk <igor.opaniuk@gmail.com>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>  cmd/abootimg.c  | 10 ++++++++++
>  include/image.h | 14 ++++++++++++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/cmd/abootimg.c b/cmd/abootimg.c
> index 327712a536c0..ae7a1a7c83b0 100644
> --- a/cmd/abootimg.c
> +++ b/cmd/abootimg.c
> @@ -22,6 +22,11 @@ ulong get_abootimg_addr(void)
>  	return (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr);
>  }
>  
> +void set_abootimg_addr(ulong addr)
> +{
> +	_abootimg_addr = addr;
> +}
> +
>  ulong get_ainit_bootimg_addr(void)
>  {
>  	return _ainit_bootimg_addr;
> @@ -32,6 +37,11 @@ ulong get_avendor_bootimg_addr(void)
>  	return _avendor_bootimg_addr;
>  }
>  
> +void set_avendor_bootimg_addr(ulong addr)
> +{
> +	_avendor_bootimg_addr = addr;
> +}
> +
>  static int abootimg_get_ver(int argc, char *const argv[])
>  {
>  	const struct andr_boot_img_hdr_v0 *hdr;
> diff --git a/include/image.h b/include/image.h
> index c5b288f62b44..df2decbf5c2a 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -1970,6 +1970,13 @@ bool is_android_vendor_boot_image_header(const void *vendor_boot_img);
>   */
>  ulong get_abootimg_addr(void);
>  
> +/**
> + * set_abootimg_addr() - Set Android boot image address
> + *
> + * Return: no returned results
> + */
> +void set_abootimg_addr(ulong addr);
> +
>  /**
>   * get_ainit_bootimg_addr() - Get Android init boot image address
>   *
> @@ -1984,6 +1991,13 @@ ulong get_ainit_bootimg_addr(void);
>   */
>  ulong get_avendor_bootimg_addr(void);
>  
> +/**
> + * set_abootimg_addr() - Set Android vendor boot image address
> + *
> + * Return: no returned results
> + */
> +void set_avendor_bootimg_addr(ulong addr);
> +
>  /**
>   * board_fit_config_name_match() - Check for a matching board name
>   *
> 
> -- 
> 2.45.2
> 

Reviewed-by: Julien Masson <jmasson@baylibre.com>
-- 
Julien Masson

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 4/5] bootstd: Add a bootmeth for Android
  2024-06-13 10:13 ` [PATCH v2 4/5] bootstd: Add a bootmeth for Android Mattijs Korpershoek
@ 2024-06-13 14:19   ` Julien Masson
  0 siblings, 0 replies; 27+ messages in thread
From: Julien Masson @ 2024-06-13 14:19 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek


On Thu 13 Jun 2024 at 16:18, Mattijs Korpershoek <mkorpershoek@baylibre.com> wrote:

> Android boot flow is a bit different than a regular Linux distro.
> Android relies on multiple partitions in order to boot.
> 
> A typical boot flow would be:
> 1. Parse the Bootloader Control Block (BCB, misc partition)
> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
> 3. If BCB requested recovery or normal android, run the following:
> 3.a. Get slot (A/B) from BCB
> 3.b. Run AVB (Android Verified Boot) on boot partitions
> 3.c. Load boot and vendor_boot partitions
> 3.d. Load device-tree, ramdisk and boot
> 
> The AOSP documentation has more details at [1], [2], [3]
> 
> This has been implemented via complex boot scripts such as [4].
> However, these boot script are neither very maintainable nor generic.
> Moreover, DISTRO_DEFAULTS is being deprecated [5].
> 
> Add a generic Android bootflow implementation for bootstd.
> For this initial version, only boot image v4 is supported.
> 
> [1] https://source.android.com/docs/core/architecture/bootloader
> [2] https://source.android.com/docs/core/architecture/partitions
> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>  MAINTAINERS             |   7 +
>  boot/Kconfig            |  16 ++
>  boot/Makefile           |   2 +
>  boot/bootmeth_android.c | 553 ++++++++++++++++++++++++++++++++++++++++++++++++
>  boot/bootmeth_android.h |  29 +++
>  doc/develop/bootstd.rst |   6 +
>  6 files changed, 613 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 66783d636e3d..6d2b87720565 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -939,6 +939,13 @@ F:	include/bootstd.h
>  F:	net/eth_bootdevice.c
>  F:	test/boot/
>  
> +BOOTMETH_ANDROID
> +M:	Mattijs Korpershoek <mkorpershoek@baylibre.com>
> +S:	Maintained
> +T:	git https://source.denx.de/u-boot/custodians/u-boot-dfu.git
> +F:	boot/bootmeth_android.c
> +F:	boot/bootmeth_android.h
> +
>  BTRFS
>  M:	Marek Beh.n <kabel@kernel.org>
>  R:	Qu Wenruo <wqu@suse.com>
> diff --git a/boot/Kconfig b/boot/Kconfig
> index 6f3096c15a6f..88266c8d2ed3 100644
> --- a/boot/Kconfig
> +++ b/boot/Kconfig
> @@ -494,6 +494,22 @@ config BOOTMETH_GLOBAL
>  	  EFI bootmgr, since they take full control over which bootdevs are
>  	  selected to boot.
>  
> +config BOOTMETH_ANDROID
> +	bool "Bootdev support for Android"
> +	depends on X86 || ARM || SANDBOX
> +	select ANDROID_AB
> +	select ANDROID_BOOT_IMAGE
> +	select CMD_BCB
> +	select CMD_FASTBOOT
> +	select PARTITION_TYPE_GUID
> +	select PARTITION_UUIDS
> +	help
> +	  Enables support for booting Android using bootstd. Android requires
> +	  multiple partitions (misc, boot, vbmeta, ...) in storage for booting.
> +
> +	  Note that only MMC bootdevs are supported at present. This is caused
> +	  by AVB being limited to MMC devices only.
> +
>  config BOOTMETH_CROS
>  	bool "Bootdev support for Chromium OS"
>  	depends on X86 || ARM || SANDBOX
> diff --git a/boot/Makefile b/boot/Makefile
> index 84ccfeaecec4..75d1cd46fabf 100644
> --- a/boot/Makefile
> +++ b/boot/Makefile
> @@ -66,3 +66,5 @@ obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_REQUEST) += vbe_request.o
>  obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE) += vbe_simple.o
>  obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE_FW) += vbe_simple_fw.o
>  obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_VBE_SIMPLE_OS) += vbe_simple_os.o
> +
> +obj-$(CONFIG_$(SPL_TPL_)BOOTMETH_ANDROID) += bootmeth_android.o
> diff --git a/boot/bootmeth_android.c b/boot/bootmeth_android.c
> new file mode 100644
> index 000000000000..6e8d3e615db0
> --- /dev/null
> +++ b/boot/bootmeth_android.c
> @@ -0,0 +1,553 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Bootmeth for Android
> + *
> + * Copyright (C) 2024 BayLibre, SAS
> + * Written by Mattijs Korpershoek <mkorpershoek@baylibre.com>
> + */
> +#define LOG_CATEGORY UCLASS_BOOTSTD
> +
> +#include <android_ab.h>
> +#include <android_image.h>
> +#if CONFIG_IS_ENABLED(AVB_VERIFY)
> +#include <avb_verify.h>
> +#endif
> +#include <bcb.h>
> +#include <blk.h>
> +#include <bootflow.h>
> +#include <bootm.h>
> +#include <bootmeth.h>
> +#include <dm.h>
> +#include <image.h>
> +#include <malloc.h>
> +#include <mapmem.h>
> +#include <part.h>
> +#include "bootmeth_android.h"
> +
> +#define BCB_FIELD_COMMAND_SZ 32
> +#define BCB_PART_NAME "misc"
> +#define BOOT_PART_NAME "boot"
> +#define VENDOR_BOOT_PART_NAME "vendor_boot"
> +
> +/**
> + * struct android_priv - Private data
> + *
> + * This is read from the disk and recorded for use when the full Android
> + * kernel must be loaded and booted
> + *
> + * @boot_mode: Requested boot mode (normal, recovery, bootloader)
> + * @slot: Nul-terminated partition slot suffix read from BCB ("a\0" or "b\0")
> + * @header_version: Android boot image header version
> + */
> +struct android_priv {
> +	enum android_boot_mode boot_mode;
> +	char slot[2];
> +	u32 header_version;
> +};
> +
> +static int android_check(struct udevice *dev, struct bootflow_iter *iter)
> +{
> +	/* This only works on mmc devices */
> +	if (bootflow_iter_check_mmc(iter))
> +		return log_msg_ret("mmc", -ENOTSUPP);
> +
> +	/*
> +	 * This only works on whole devices, as multiple
> +	 * partitions are needed to boot Android
> +	 */
> +	if (iter->part != 0)
> +		return log_msg_ret("mmc part", -ENOTSUPP);
> +
> +	return 0;
> +}
> +
> +static int scan_boot_part(struct udevice *blk, struct android_priv *priv)
> +{
> +	struct blk_desc *desc = dev_get_uclass_plat(blk);
> +	struct disk_partition partition;
> +	char partname[PART_NAME_LEN];
> +	ulong num_blks, bufsz;
> +	char *buf;
> +	int ret;
> +
> +	sprintf(partname, BOOT_PART_NAME "_%s", priv->slot);
> +	ret = part_get_info_by_name(desc, partname, &partition);
> +	if (ret < 0)
> +		return log_msg_ret("part info", ret);
> +
> +	num_blks = DIV_ROUND_UP(sizeof(struct andr_boot_img_hdr_v0), desc->blksz);
> +	bufsz = num_blks * desc->blksz;
> +	buf = malloc(bufsz);
> +	if (!buf)
> +		return log_msg_ret("buf", -ENOMEM);
> +
> +	ret = blk_read(blk, partition.start, num_blks, buf);
> +	if (ret != num_blks) {
> +		free(buf);
> +		return log_msg_ret("part read", -EIO);
> +	}
> +
> +	if (!is_android_boot_image_header(buf)) {
> +		free(buf);
> +		return log_msg_ret("header", -ENOENT);
> +	}
> +
> +	priv->header_version = ((struct andr_boot_img_hdr_v0 *)buf)->header_version;
> +	free(buf);
> +
> +	return 0;
> +}
> +
> +static int scan_vendor_boot_part(struct udevice *blk, struct android_priv *priv)
> +{
> +	struct blk_desc *desc = dev_get_uclass_plat(blk);
> +	struct disk_partition partition;
> +	char partname[PART_NAME_LEN];
> +	ulong num_blks, bufsz;
> +	char *buf;
> +	int ret;
> +
> +	sprintf(partname, VENDOR_BOOT_PART_NAME "_%s", priv->slot);
> +	ret = part_get_info_by_name(desc, partname, &partition);
> +	if (ret < 0)
> +		return log_msg_ret("part info", ret);
> +
> +	num_blks = DIV_ROUND_UP(sizeof(struct andr_vnd_boot_img_hdr), desc->blksz);
> +	bufsz = num_blks * desc->blksz;
> +	buf = malloc(bufsz);
> +	if (!buf)
> +		return log_msg_ret("buf", -ENOMEM);
> +
> +	ret = blk_read(blk, partition.start, num_blks, buf);
> +	if (ret != num_blks) {
> +		free(buf);
> +		return log_msg_ret("part read", -EIO);
> +	}
> +
> +	if (!is_android_vendor_boot_image_header(buf)) {
> +		free(buf);
> +		return log_msg_ret("header", -ENOENT);
> +	}
> +	free(buf);
> +
> +	return 0;
> +}
> +
> +static int android_read_slot_from_bcb(struct bootflow *bflow, bool decrement)
> +{
> +	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
> +	struct android_priv *priv = bflow->bootmeth_priv;
> +	struct disk_partition misc;
> +	char slot_suffix[3];
> +	int ret;
> +
> +	ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc);
> +	if (ret < 0)
> +		return log_msg_ret("part", ret);
> +
> +	ret = ab_select_slot(desc, &misc, decrement);
> +	if (ret < 0)
> +		return log_msg_ret("slot", ret);
> +
> +	priv->slot[0] = BOOT_SLOT_NAME(ret);
> +	priv->slot[1] = '\0';
> +
> +	sprintf(slot_suffix, "_%s", priv->slot);
> +	ret = bootflow_cmdline_set_arg(bflow, "androidboot.slot_suffix",
> +				       slot_suffix, false);
> +	if (ret < 0)
> +		return log_msg_ret("cmdl", ret);
> +
> +	return 0;
> +}
> +
> +static int configure_serialno(struct bootflow *bflow)
> +{
> +	char *serialno = env_get("serial#");
> +
> +	if (!serialno)
> +		return log_msg_ret("serial", -ENOENT);
> +
> +	return bootflow_cmdline_set_arg(bflow, "androidboot.serialno", serialno, false);
> +}
> +
> +static int android_read_bootflow(struct udevice *dev, struct bootflow *bflow)
> +{
> +	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
> +	struct disk_partition misc;
> +	struct android_priv *priv;
> +	char command[BCB_FIELD_COMMAND_SZ];
> +	int ret;
> +
> +	bflow->state = BOOTFLOWST_MEDIA;
> +
> +	/*
> +	 * bcb_find_partition_and_load() will print errors to stdout
> +	 * if BCB_PART_NAME is not found. To avoid that, check if the
> +	 * partition exists first.
> +	 */
> +	ret = part_get_info_by_name(desc, BCB_PART_NAME, &misc);
> +	if (ret < 0)
> +		return log_msg_ret("part", ret);
> +
> +	ret = bcb_find_partition_and_load("mmc", desc->devnum, BCB_PART_NAME);
> +	if (ret < 0)
> +		return log_msg_ret("bcb load", ret);
> +
> +	ret = bcb_get(BCB_FIELD_COMMAND, command, sizeof(command));
> +	if (ret < 0)
> +		return log_msg_ret("bcb read", ret);
> +
> +	priv = malloc(sizeof(struct android_priv));
> +	if (!priv)
> +		return log_msg_ret("buf", -ENOMEM);
> +
> +	if (!strcmp("bootonce-bootloader", command)) {
> +		priv->boot_mode = ANDROID_BOOT_MODE_BOOTLOADER;
> +		bflow->os_name = strdup("Android (bootloader)");
> +	} else if (!strcmp("boot-fastboot", command)) {
> +		priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY;
> +		bflow->os_name = strdup("Android (fastbootd)");
> +	} else if (!strcmp("boot-recovery", command)) {
> +		priv->boot_mode = ANDROID_BOOT_MODE_RECOVERY;
> +		bflow->os_name = strdup("Android (recovery)");
> +	} else {
> +		priv->boot_mode = ANDROID_BOOT_MODE_NORMAL;
> +		bflow->os_name = strdup("Android");
> +	}
> +	if (!bflow->os_name)
> +		return log_msg_ret("os", -ENOMEM);
> +
> +	if (priv->boot_mode == ANDROID_BOOT_MODE_BOOTLOADER) {
> +		/* Clear BCB */
> +		memset(command, 0, sizeof(command));
> +		ret = bcb_set(BCB_FIELD_COMMAND, command);
> +		if (ret < 0) {
> +			free(priv);
> +			return log_msg_ret("bcb set", ret);
> +		}
> +		ret = bcb_store();
> +		if (ret < 0) {
> +			free(priv);
> +			return log_msg_ret("bcb store", ret);
> +		}
> +
> +		bflow->bootmeth_priv = priv;
> +		bflow->state = BOOTFLOWST_READY;
> +		return 0;
> +	}
> +
> +	bflow->bootmeth_priv = priv;
> +
> +	/* For recovery and normal boot, we need to scan the partitions */
> +	ret = android_read_slot_from_bcb(bflow, false);
> +	if (ret < 0) {
> +		log_err("read slot: %d", ret);
> +		goto free_priv;
> +	}
> +
> +	ret = scan_boot_part(bflow->blk, priv);
> +	if (ret < 0) {
> +		log_debug("scan boot failed: err=%d\n", ret);
> +		goto free_priv;
> +	}
> +
> +	if (priv->header_version != 4) {
> +		log_debug("only boot.img v4 is supported %u\n", priv->header_version);
> +		ret = -EINVAL;
> +		goto free_priv;
> +	}
> +
> +	ret = scan_vendor_boot_part(bflow->blk, priv);
> +	if (ret < 0) {
> +		log_debug("scan vendor_boot failed: err=%d\n", ret);
> +		goto free_priv;
> +	}
> +
> +	/* Ignoring return code: setting serial number is not mandatory for booting */
> +	configure_serialno(bflow);
> +
> +	if (priv->boot_mode == ANDROID_BOOT_MODE_NORMAL) {
> +		ret = bootflow_cmdline_set_arg(bflow, "androidboot.force_normal_boot",
> +					       "1", false);
> +		if (ret < 0) {
> +			log_debug("normal_boot %d", ret);
> +			goto free_priv;
> +		}
> +	}
> +
> +	bflow->state = BOOTFLOWST_READY;
> +
> +	return 0;
> +
> + free_priv:
> +	free(priv);
> +	bflow->bootmeth_priv = NULL;
> +	return ret;
> +}
> +
> +static int android_read_file(struct udevice *dev, struct bootflow *bflow,
> +			     const char *file_path, ulong addr, ulong *sizep)
> +{
> +	/*
> +	 * Reading individual files is not supported since we only
> +	 * operate on whole mmc devices (because we require multiple partitions)
> +	 */
> +	return log_msg_ret("Unsupported", -ENOSYS);
> +}
> +
> +/**
> + * read_slotted_partition() - Read a partition by appending a slot suffix
> + *
> + * Most modern Android devices use Seamless Updates, where each partition
> + * is duplicated. For example, the boot partition has boot_a and boot_b.
> + * For more information, see:
> + * https://source.android.com/docs/core/ota/ab
> + * https://source.android.com/docs/core/ota/ab/ab_implement
> + *
> + * @blk: Block device to read
> + * @name: Partition name to read
> + * @slot: Nul-terminated slot suffixed to partition name ("a\0" or "b\0")
> + * @addr: Address where the partition content is loaded into
> + * Return: 0 if OK, negative errno on failure.
> + */
> +static int read_slotted_partition(struct blk_desc *desc, const char *const name,
> +				  const char slot[2], ulong addr)
> +{
> +	struct disk_partition partition;
> +	char partname[PART_NAME_LEN];
> +	int ret;
> +	u32 n;
> +
> +	/* Ensure name fits in partname it should be: <name>_<slot>\0 */
> +	if (strlen(name) > (PART_NAME_LEN - 2 - 1))
> +		return log_msg_ret("name too long", -EINVAL);
> +
> +	sprintf(partname, "%s_%s", name, slot);
> +	ret = part_get_info_by_name(desc, partname, &partition);
> +	if (ret < 0)
> +		return log_msg_ret("part", ret);
> +
> +	n = blk_dread(desc, partition.start, partition.size, map_sysmem(addr, 0));
> +	if (n < partition.size)
> +		return log_msg_ret("part read", -EIO);
> +
> +	return 0;
> +}
> +
> +#if CONFIG_IS_ENABLED(AVB_VERIFY)
> +static int avb_append_commandline_arg(struct bootflow *bflow, char *arg)
> +{
> +	char *key = strsep(&arg, "=");
> +	char *value = arg;
> +	int ret;
> +
> +	ret = bootflow_cmdline_set_arg(bflow, key, value, false);
> +	if (ret < 0)
> +		return log_msg_ret("avb cmdline", ret);
> +
> +	return 0;
> +}
> +
> +static int avb_append_commandline(struct bootflow *bflow, char *cmdline)
> +{
> +	char *arg = strsep(&cmdline, " ");
> +	int ret;
> +
> +	while (arg) {
> +		ret = avb_append_commandline_arg(bflow, arg);
> +		if (ret < 0)
> +			return ret;
> +
> +		arg = strsep(&cmdline, " ");
> +	}
> +
> +	return 0;
> +}
> +
> +static int run_avb_verification(struct bootflow *bflow)
> +{
> +	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
> +	struct android_priv *priv = bflow->bootmeth_priv;
> +	const char * const requested_partitions[] = {"boot", "vendor_boot"};
> +	struct AvbOps *avb_ops;
> +	AvbSlotVerifyResult result;
> +	AvbSlotVerifyData *out_data;
> +	enum avb_boot_state boot_state;
> +	char *extra_args;
> +	char slot_suffix[3];
> +	bool unlocked = false;
> +	int ret;
> +
> +	avb_ops = avb_ops_alloc(desc->devnum);
> +	if (!avb_ops)
> +		return log_msg_ret("avb ops", -ENOMEM);
> +
> +	sprintf(slot_suffix, "_%s", priv->slot);
> +
> +	ret = avb_ops->read_is_device_unlocked(avb_ops, &unlocked);
> +	if (ret != AVB_IO_RESULT_OK)
> +		return log_msg_ret("avb lock", -EIO);
> +
> +	result = avb_slot_verify(avb_ops,
> +				 requested_partitions,
> +				 slot_suffix,
> +				 unlocked,
> +				 AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE,
> +				 &out_data);
> +
> +	if (result != AVB_SLOT_VERIFY_RESULT_OK) {
> +		printf("Verification failed, reason: %s\n",
> +		       str_avb_slot_error(result));
> +		avb_slot_verify_data_free(out_data);
> +		return log_msg_ret("avb verify", -EIO);
> +	}
> +
> +	if (unlocked)
> +		boot_state = AVB_ORANGE;
> +	else
> +		boot_state = AVB_GREEN;
> +
> +	extra_args = avb_set_state(avb_ops, boot_state);
> +	if (extra_args) {
> +		/* extra_args will be modified after this. This is fine */
> +		ret = avb_append_commandline_arg(bflow, extra_args);
> +		if (ret < 0)
> +			goto free_out_data;
> +	}
> +
> +	ret = avb_append_commandline(bflow, out_data->cmdline);
> +	if (ret < 0)
> +		goto free_out_data;
> +
> +	return 0;
> +
> + free_out_data:
> +	if (out_data)
> +		avb_slot_verify_data_free(out_data);
> +
> +	return log_msg_ret("avb cmdline", ret);
> +}
> +#else
> +static int run_avb_verification(struct bootflow *bflow)
> +{
> +	int ret;
> +
> +	/* When AVB is unsupported, pass ORANGE state  */
> +	ret = bootflow_cmdline_set_arg(bflow,
> +				       "androidboot.verifiedbootstate",
> +				       "orange", false);
> +	if (ret < 0)
> +		return log_msg_ret("avb cmdline", ret);
> +
> +	return 0;
> +}
> +#endif /* AVB_VERIFY */
> +
> +static int boot_android_normal(struct bootflow *bflow)
> +{
> +	struct blk_desc *desc = dev_get_uclass_plat(bflow->blk);
> +	struct android_priv *priv = bflow->bootmeth_priv;
> +	int ret;
> +	ulong loadaddr = env_get_hex("loadaddr", 0);
> +	ulong vloadaddr = env_get_hex("vendor_boot_comp_addr_r", 0);
> +
> +	ret = run_avb_verification(bflow);
> +	if (ret < 0)
> +		return log_msg_ret("avb", ret);
> +
> +	/* Read slot once more to decrement counter from BCB */
> +	ret = android_read_slot_from_bcb(bflow, true);
> +	if (ret < 0)
> +		return log_msg_ret("read slot", ret);
> +
> +	ret = read_slotted_partition(desc, "boot", priv->slot, loadaddr);
> +	if (ret < 0)
> +		return log_msg_ret("read boot", ret);
> +
> +	ret = read_slotted_partition(desc, "vendor_boot", priv->slot, vloadaddr);
> +	if (ret < 0)
> +		return log_msg_ret("read vendor_boot", ret);
> +
> +	set_abootimg_addr(loadaddr);
> +	set_avendor_bootimg_addr(vloadaddr);
> +
> +	ret = bootm_boot_start(loadaddr, bflow->cmdline);
> +
> +	return log_msg_ret("boot", ret);
> +}
> +
> +static int boot_android_recovery(struct bootflow *bflow)
> +{
> +	int ret;
> +
> +	ret = boot_android_normal(bflow);
> +
> +	return log_msg_ret("boot", ret);
> +}
> +
> +static int boot_android_bootloader(struct bootflow *bflow)
> +{
> +	int ret;
> +
> +	ret = run_command("fastboot usb 0", 0);
> +	do_reset(NULL, 0, 0, NULL);
> +
> +	return log_msg_ret("boot", ret);
> +}
> +
> +static int android_boot(struct udevice *dev, struct bootflow *bflow)
> +{
> +	struct android_priv *priv = bflow->bootmeth_priv;
> +	int ret;
> +
> +	switch (priv->boot_mode) {
> +	case ANDROID_BOOT_MODE_NORMAL:
> +		ret = boot_android_normal(bflow);
> +		break;
> +	case ANDROID_BOOT_MODE_RECOVERY:
> +		ret = boot_android_recovery(bflow);
> +		break;
> +	case ANDROID_BOOT_MODE_BOOTLOADER:
> +		ret = boot_android_bootloader(bflow);
> +		break;
> +	default:
> +		printf("ANDROID: Unknown boot mode %d. Running fastboot...\n",
> +		       priv->boot_mode);
> +		boot_android_bootloader(bflow);
> +		/* Tell we failed to boot since boot mode is unknown */
> +		ret = -EFAULT;
> +	}
> +
> +	return ret;
> +}
> +
> +static int android_bootmeth_bind(struct udevice *dev)
> +{
> +	struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
> +
> +	plat->desc = "Android boot";
> +	plat->flags = BOOTMETHF_ANY_PART;
> +
> +	return 0;
> +}
> +
> +static struct bootmeth_ops android_bootmeth_ops = {
> +	.check		= android_check,
> +	.read_bootflow	= android_read_bootflow,
> +	.read_file	= android_read_file,
> +	.boot		= android_boot,
> +};
> +
> +static const struct udevice_id android_bootmeth_ids[] = {
> +	{ .compatible = "u-boot,android" },
> +	{ }
> +};
> +
> +U_BOOT_DRIVER(bootmeth_android) = {
> +	.name		= "bootmeth_android",
> +	.id		= UCLASS_BOOTMETH,
> +	.of_match	= android_bootmeth_ids,
> +	.ops		= &android_bootmeth_ops,
> +	.bind		= android_bootmeth_bind,
> +};
> diff --git a/boot/bootmeth_android.h b/boot/bootmeth_android.h
> new file mode 100644
> index 000000000000..a57fad9f0113
> --- /dev/null
> +++ b/boot/bootmeth_android.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0+ */
> +/*
> + * Bootmethod for Android
> + *
> + * Copyright (C) 2024 BayLibre, SAS
> + * Written by Mattijs Korpershoek <mkorpershoek@baylibre.com>
> + */
> +
> +enum android_boot_mode {
> +	ANDROID_BOOT_MODE_NORMAL = 0,
> +
> +	/*
> +	 * Android "recovery" is a special boot mode that uses another ramdisk.
> +	 * It can be used to "factory reset" a board or to flash logical partitions
> +	 * It operates in 2 modes: adb or fastbootd
> +	 * To enter recovery from Android, we can do:
> +	 * $ adb reboot recovery
> +	 * $ adb reboot fastboot
> +	 */
> +	ANDROID_BOOT_MODE_RECOVERY,
> +
> +	/*
> +	 * Android "bootloader" is for accessing/reflashing physical partitions
> +	 * Typically, this will launch a fastboot process in U-Boot.
> +	 * To enter "bootloader" from Android, we can do:
> +	 * $ adb reboot bootloader
> +	 */
> +	ANDROID_BOOT_MODE_BOOTLOADER,
> +};
> diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst
> index a07a72581e7a..709fa9e64ff3 100644
> --- a/doc/develop/bootstd.rst
> +++ b/doc/develop/bootstd.rst
> @@ -95,6 +95,7 @@ bootflows.
>  
>  Note: it is possible to have a bootmeth that uses a partition or a whole device
>  directly, but it is more common to use a filesystem.
> +For example, the Android bootmeth uses a whole device.
>  
>  Note that some bootmeths are 'global', meaning that they select the bootdev
>  themselves. Examples include VBE and EFI boot manager. In this case, they
> @@ -277,6 +278,9 @@ script_offset_f
>  script_size_f
>      Size of the script to load, e.g. 0x2000
>  
> +vendor_boot_comp_addr_r
> +    Address to which to load the vendor_boot Android image, e.g. 0xe0000000
> +
>  Some variables are set by script bootmeth:
>  
>  devtype
> @@ -418,6 +422,7 @@ Bootmeth drivers are provided for:
>     - EFI boot using bootefi from disk
>     - VBE
>     - EFI boot using boot manager
> +   - Android bootflow (boot image v4)
>  
>  
>  Command interface
> @@ -786,6 +791,7 @@ To do
>  Some things that need to be done to completely replace the distro-boot scripts:
>  
>  - implement extensions (devicetree overlays with add-on boards)
> +- implement legacy (boot image v2) android boot flow
>  
>  Other ideas:
>  
> 
> -- 
> 2.45.2
> 

Reviewed-by: Julien Masson <jmasson@baylibre.com>
-- 
Julien Masson

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 5/5] bootstd: Add test for bootmeth_android
  2024-06-13 10:13 ` [PATCH v2 5/5] bootstd: Add test for bootmeth_android Mattijs Korpershoek
@ 2024-06-13 14:19   ` Julien Masson
  2024-06-13 18:47   ` Guillaume LA ROQUE
  1 sibling, 0 replies; 27+ messages in thread
From: Julien Masson @ 2024-06-13 14:19 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek


On Thu 13 Jun 2024 at 16:19, Mattijs Korpershoek <mkorpershoek@baylibre.com> wrote:

> Add a unit test for testing the Android bootmethod.
> 
> This requires another mmc image (mmc7) to contain the following partitions:
> - misc: contains the Bootloader Control Block (BCB)
> - boot_a: contains a fake generic kernel image
> - vendor_boot_a: contains a fake vendor_boot image
> 
> Also add BOOTMETH_ANDROID as a dependency on sandbox so that we can test
> this with:
> 
> $ ./test/py/test.py --bd sandbox --build -k test_abootimg # build bootv4.img
> $ ./test/py/test.py --bd sandbox --build -k test_ut # build the mmc7.img
> $ ./test/py/test.py --bd sandbox --build -k bootflow_android
> 
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>  arch/sandbox/dts/test.dts |  8 +++++
>  configs/sandbox_defconfig |  2 +-
>  test/boot/bootflow.c      | 65 ++++++++++++++++++++++++++++++++++++++--
>  test/py/tests/test_ut.py  | 76 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 147 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index a012f5c4c9ba..5fb5eac862ec 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -43,6 +43,7 @@
>  		mmc4 = "/mmc4";
>  		mmc5 = "/mmc5";
>  		mmc6 = "/mmc6";
> +		mmc7 = "/mmc7";
>  		pci0 = &pci0;
>  		pci1 = &pci1;
>  		pci2 = &pci2;
> @@ -1129,6 +1130,13 @@
>  		filename = "mmc6.img";
>  	};
>  
> +	/* This is used for Android tests */
> +	mmc7 {
> +		status = "disabled";
> +		compatible = "sandbox,mmc";
> +		filename = "mmc7.img";
> +	};
> +
>  	pch {
>  		compatible = "sandbox,pch";
>  	};
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index 93b52f2de5cf..bc4398f101a7 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -15,6 +15,7 @@ CONFIG_FIT=y
>  CONFIG_FIT_RSASSA_PSS=y
>  CONFIG_FIT_CIPHER=y
>  CONFIG_FIT_VERBOSE=y
> +CONFIG_BOOTMETH_ANDROID=y
>  CONFIG_LEGACY_IMAGE_FORMAT=y
>  CONFIG_MEASURED_BOOT=y
>  CONFIG_BOOTSTAGE=y
> @@ -40,7 +41,6 @@ CONFIG_LOG_MAX_LEVEL=9
>  CONFIG_LOG_DEFAULT_LEVEL=6
>  CONFIG_DISPLAY_BOARDINFO_LATE=y
>  CONFIG_STACKPROTECTOR=y
> -CONFIG_ANDROID_AB=y
>  CONFIG_CMD_CPU=y
>  CONFIG_CMD_LICENSE=y
>  CONFIG_CMD_SMBIOS=y
> diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
> index 4511cfa7f9bf..934c4dcbad2b 100644
> --- a/test/boot/bootflow.c
> +++ b/test/boot/bootflow.c
> @@ -27,6 +27,7 @@
>  
>  DECLARE_GLOBAL_DATA_PTR;
>  
> +extern U_BOOT_DRIVER(bootmeth_android);
>  extern U_BOOT_DRIVER(bootmeth_cros);
>  extern U_BOOT_DRIVER(bootmeth_2script);
>  
> @@ -518,12 +519,12 @@ BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
>   * @uts: Unit test state
>   * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid
>   *	in the caller until
> - * @bind_cros: true to bind the ChromiumOS bootmeth
> + * @bind_cros: true to bind the ChromiumOS and Android bootmeths
>   * @old_orderp: Returns the original bootdev order, which must be restored
>   * Returns 0 on success, -ve on failure
>   */
>  static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
> -			    bool bind_cros, const char ***old_orderp)
> +			    bool bind_cros_android, const char ***old_orderp)
>  {
>  	static const char *order[] = {"mmc2", "mmc1", NULL, NULL};
>  	struct udevice *dev, *bootstd;
> @@ -545,12 +546,19 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
>  				"bootmeth_script", 0, ofnode_null(), &dev));
>  
>  	/* Enable the cros bootmeth if needed */
> -	if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros) {
> +	if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) {
>  		ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
>  		ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros),
>  					"cros", 0, ofnode_null(), &dev));
>  	}
>  
> +	/* Enable the android bootmeths if needed */
> +	if (IS_ENABLED(CONFIG_BOOTMETH_ANDROID) && bind_cros_android) {
> +		ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
> +		ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_android),
> +					"android", 0, ofnode_null(), &dev));
> +	}
> +
>  	/* Change the order to include the device */
>  	std = dev_get_priv(bootstd);
>  	old_order = std->bootdev_order;
> @@ -589,6 +597,37 @@ static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
>  	return 0;
>  }
>  
> +/**
> + * scan_mmc_android_bootdev() - Set up an mmc bootdev so we can access other
> + * distros. Android bootflow might print "ANDROID:*" while scanning
> + *
> + * @uts: Unit test state
> + * @mmc_dev: MMC device to use, e.g. "mmc4"
> + * Returns 0 on success, -ve on failure
> + */
> +static int scan_mmc_android_bootdev(struct unit_test_state *uts, const char *mmc_dev)
> +{
> +	struct bootstd_priv *std;
> +	struct udevice *bootstd;
> +	const char **old_order;
> +
> +	ut_assertok(prep_mmc_bootdev(uts, mmc_dev, true, &old_order));
> +
> +	console_record_reset_enable();
> +	ut_assertok(run_command("bootflow scan", 0));
> +	/* Android bootflow might print one or two 'ANDROID:*' logs */
> +	ut_check_skipline(uts);
> +	ut_check_skipline(uts);
> +	ut_assert_console_end();
> +
> +	/* Restore the order used by the device tree */
> +	ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
> +	std = dev_get_priv(bootstd);
> +	std->bootdev_order = old_order;
> +
> +	return 0;
> +}
> +
>  /**
>   * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian
>   *
> @@ -1160,3 +1199,23 @@ static int bootflow_cros(struct unit_test_state *uts)
>  	return 0;
>  }
>  BOOTSTD_TEST(bootflow_cros, 0);
> +
> +/* Test Android bootmeth  */
> +static int bootflow_android(struct unit_test_state *uts)
> +{
> +	ut_assertok(scan_mmc_android_bootdev(uts, "mmc7"));
> +	ut_assertok(run_command("bootflow list", 0));
> +
> +	ut_assert_nextlinen("Showing all");
> +	ut_assert_nextlinen("Seq");
> +	ut_assert_nextlinen("---");
> +	ut_assert_nextlinen("  0  extlinux");
> +	ut_assert_nextlinen("  1  android      ready   mmc          0  mmc7.bootdev.whole        ");
> +	ut_assert_nextlinen("---");
> +	ut_assert_skip_to_line("(2 bootflows, 2 valid)");
> +
> +	ut_assert_console_end();
> +
> +	return 0;
> +}
> +BOOTSTD_TEST(bootflow_android, 0);
> diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
> index c169c835e38a..39e1abe02a68 100644
> --- a/test/py/tests/test_ut.py
> +++ b/test/py/tests/test_ut.py
> @@ -423,6 +423,81 @@ def setup_cros_image(cons):
>  
>      return fname
>  
> +def setup_android_image(cons):
> +    """Create a 20MB disk image with Android partitions"""
> +    Partition = collections.namedtuple('part', 'start,size,name')
> +    parts = {}
> +    disk_data = None
> +
> +    def set_part_data(partnum, data):
> +        """Set the contents of a disk partition
> +
> +        This updates disk_data by putting data in the right place
> +
> +        Args:
> +            partnum (int): Partition number to set
> +            data (bytes): Data for that partition
> +        """
> +        nonlocal disk_data
> +
> +        start = parts[partnum].start * sect_size
> +        disk_data = disk_data[:start] + data + disk_data[start + len(data):]
> +
> +    mmc_dev = 7
> +    fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img')
> +    u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname)
> +    u_boot_utils.run_and_log(cons, f'cgpt create {fname}')
> +
> +    ptr = 40
> +
> +    # Number of sectors in 1MB
> +    sect_size = 512
> +    sect_1mb = (1 << 20) // sect_size
> +
> +    required_parts = [
> +        {'num': 1, 'label':'misc', 'size': '1M'},
> +        {'num': 2, 'label':'boot_a', 'size': '4M'},
> +        {'num': 3, 'label':'boot_b', 'size': '4M'},
> +        {'num': 4, 'label':'vendor_boot_a', 'size': '4M'},
> +        {'num': 5, 'label':'vendor_boot_b', 'size': '4M'},
> +    ]
> +
> +    for part in required_parts:
> +        size_str = part['size']
> +        if 'M' in size_str:
> +            size = int(size_str[:-1]) * sect_1mb
> +        else:
> +            size = int(size_str)
> +        u_boot_utils.run_and_log(
> +            cons,
> +            f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}")
> +        ptr += size
> +
> +    u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}')
> +    out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}')
> +
> +    # Create a dict (indexed by partition number) containing the above info
> +    for line in out.splitlines():
> +        start, size, num, name = line.split(maxsplit=3)
> +        parts[int(num)] = Partition(int(start), int(size), name)
> +
> +    with open(fname, 'rb') as inf:
> +        disk_data = inf.read()
> +
> +    boot_img = os.path.join(cons.config.result_dir, 'bootv4.img')
> +    with open(boot_img, 'rb') as inf:
> +        set_part_data(2, inf.read())
> +
> +    vendor_boot_img = os.path.join(cons.config.result_dir, 'vendor_boot.img')
> +    with open(vendor_boot_img, 'rb') as inf:
> +        set_part_data(4, inf.read())
> +
> +    with open(fname, 'wb') as outf:
> +        outf.write(disk_data)
> +
> +    print('wrote to {}'.format(fname))
> +
> +    return fname
>  
>  def setup_cedit_file(cons):
>      infname = os.path.join(cons.config.source_dir,
> @@ -477,6 +552,7 @@ def test_ut_dm_init_bootstd(u_boot_console):
>      setup_bootmenu_image(u_boot_console)
>      setup_cedit_file(u_boot_console)
>      setup_cros_image(u_boot_console)
> +    setup_android_image(u_boot_console)
>  
>      # Restart so that the new mmc1.img is picked up
>      u_boot_console.restart_uboot()
> 
> -- 
> 2.45.2
> 

Reviewed-by: Julien Masson <jmasson@baylibre.com>
-- 
Julien Masson

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
  2024-06-13 10:13 ` [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr() Mattijs Korpershoek
  2024-06-13 14:16   ` Julien Masson
@ 2024-06-13 15:20   ` Simon Glass
  2024-06-13 18:45   ` Guillaume LA ROQUE
  2 siblings, 0 replies; 27+ messages in thread
From: Simon Glass @ 2024-06-13 15:20 UTC (permalink / raw)
  To: Mattijs Korpershoek
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

On Thu, 13 Jun 2024 at 04:13, Mattijs Korpershoek
<mkorpershoek@baylibre.com> wrote:
>
> The only way to configure the load addresses for both bootimg and
> vendor_bootimg is by using the "abootimg" command.
> If we want to use the C API, there is no equivalent.
>
> Add set_abootimg_addr() and set_avendor_bootimg_addr() so that we can
> specify the load address from C.
>
> This can be useful for implementing an Android bootmethod.
>
> Reviewed-by: Igor Opaniuk <igor.opaniuk@gmail.com>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>  cmd/abootimg.c  | 10 ++++++++++
>  include/image.h | 14 ++++++++++++++
>  2 files changed, 24 insertions(+)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
  2024-06-13 10:13 ` [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() Mattijs Korpershoek
@ 2024-06-13 15:22   ` Simon Glass
  2024-06-13 15:42   ` Julien Masson
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 27+ messages in thread
From: Simon Glass @ 2024-06-13 15:22 UTC (permalink / raw)
  To: Mattijs Korpershoek
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

On Thu, 13 Jun 2024 at 04:13, Mattijs Korpershoek
<mkorpershoek@baylibre.com> wrote:
>
> When calling android_image_get_dtb_by_index() using boot image v3+,
> we should also pass the vendor_boot ramdisk address.
>
> Use get_avendor_bootimg_addr() to do so.
>
> Notes: on boot image v2, this is harmless since get_avendor_bootimg_addr()
>        returns -1.
>        for legacy implementations that don't have CMD_ABOOTIMG, add a weak
>        implementation to avoid linking errors.
>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>  boot/image-android.c | 5 +++++
>  boot/image-fdt.c     | 2 +-
>  2 files changed, 6 insertions(+), 1 deletion(-)

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
  2024-06-13 10:13 ` [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() Mattijs Korpershoek
  2024-06-13 15:22   ` Simon Glass
@ 2024-06-13 15:42   ` Julien Masson
  2024-06-13 17:10   ` Igor Opaniuk
  2024-06-13 18:43   ` Guillaume LA ROQUE
  3 siblings, 0 replies; 27+ messages in thread
From: Julien Masson @ 2024-06-13 15:42 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot, Mattijs Korpershoek


On Thu 13 Jun 2024 at 17:42, Mattijs Korpershoek <mkorpershoek@baylibre.com> wrote:

> When calling android_image_get_dtb_by_index() using boot image v3+,
> we should also pass the vendor_boot ramdisk address.
> 
> Use get_avendor_bootimg_addr() to do so.
> 
> Notes: on boot image v2, this is harmless since get_avendor_bootimg_addr()
>        returns -1.
>        for legacy implementations that don't have CMD_ABOOTIMG, add a weak
>        implementation to avoid linking errors.
> 
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>  boot/image-android.c | 5 +++++
>  boot/image-fdt.c     | 2 +-
>  2 files changed, 6 insertions(+), 1 deletion(-)
> 
> diff --git a/boot/image-android.c b/boot/image-android.c
> index ee626972c114..09c7a44e058a 100644
> --- a/boot/image-android.c
> +++ b/boot/image-android.c
> @@ -56,6 +56,11 @@ static ulong add_trailer(ulong bootconfig_start_addr, ulong bootconfig_size)
>  	return BOOTCONFIG_TRAILER_SIZE;
>  }
>  
> +__weak ulong get_avendor_bootimg_addr(void)
> +{
> +	return -1;
> +}
> +
>  static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 *hdr,
>  					       struct andr_image_data *data)
>  {
> diff --git a/boot/image-fdt.c b/boot/image-fdt.c
> index 56dd7687f51c..8332792b8e80 100644
> --- a/boot/image-fdt.c
> +++ b/boot/image-fdt.c
> @@ -502,7 +502,7 @@ int boot_get_fdt(void *buf, const char *select, uint arch,
>  		 * Firstly check if this android boot image has dtb field.
>  		 */
>  		dtb_idx = (u32)env_get_ulong("adtb_idx", 10, 0);
> -		if (android_image_get_dtb_by_index((ulong)hdr, 0,
> +		if (android_image_get_dtb_by_index((ulong)hdr, get_avendor_bootimg_addr(),
>  						   dtb_idx, &fdt_addr, &fdt_size)) {
>  			fdt_blob = (char *)map_sysmem(fdt_addr, 0);
>  			if (fdt_check_header(fdt_blob))
> 
> -- 
> 2.45.2
> 

Reviewed-by: Julien Masson <jmasson@baylibre.com>
-- 
Julien Masson

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
  2024-06-13 10:13 ` [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() Mattijs Korpershoek
  2024-06-13 15:22   ` Simon Glass
  2024-06-13 15:42   ` Julien Masson
@ 2024-06-13 17:10   ` Igor Opaniuk
  2024-06-13 18:43   ` Guillaume LA ROQUE
  3 siblings, 0 replies; 27+ messages in thread
From: Igor Opaniuk @ 2024-06-13 17:10 UTC (permalink / raw)
  To: Mattijs Korpershoek
  Cc: Simon Glass, Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, u-boot

On Thu, Jun 13, 2024 at 12:13 PM Mattijs Korpershoek
<mkorpershoek@baylibre.com> wrote:
>
> When calling android_image_get_dtb_by_index() using boot image v3+,
> we should also pass the vendor_boot ramdisk address.
>
> Use get_avendor_bootimg_addr() to do so.
>
> Notes: on boot image v2, this is harmless since get_avendor_bootimg_addr()
>        returns -1.
>        for legacy implementations that don't have CMD_ABOOTIMG, add a weak
>        implementation to avoid linking errors.
>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>  boot/image-android.c | 5 +++++
>  boot/image-fdt.c     | 2 +-
>  2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/boot/image-android.c b/boot/image-android.c
> index ee626972c114..09c7a44e058a 100644
> --- a/boot/image-android.c
> +++ b/boot/image-android.c
> @@ -56,6 +56,11 @@ static ulong add_trailer(ulong bootconfig_start_addr, ulong bootconfig_size)
>         return BOOTCONFIG_TRAILER_SIZE;
>  }
>
> +__weak ulong get_avendor_bootimg_addr(void)
> +{
> +       return -1;
> +}
> +
>  static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 *hdr,
>                                                struct andr_image_data *data)
>  {
> diff --git a/boot/image-fdt.c b/boot/image-fdt.c
> index 56dd7687f51c..8332792b8e80 100644
> --- a/boot/image-fdt.c
> +++ b/boot/image-fdt.c
> @@ -502,7 +502,7 @@ int boot_get_fdt(void *buf, const char *select, uint arch,
>                  * Firstly check if this android boot image has dtb field.
>                  */
>                 dtb_idx = (u32)env_get_ulong("adtb_idx", 10, 0);
> -               if (android_image_get_dtb_by_index((ulong)hdr, 0,
> +               if (android_image_get_dtb_by_index((ulong)hdr, get_avendor_bootimg_addr(),
>                                                    dtb_idx, &fdt_addr, &fdt_size)) {
>                         fdt_blob = (char *)map_sysmem(fdt_addr, 0);
>                         if (fdt_check_header(fdt_blob))
>
> --
> 2.45.2
>
Reviewed-by: Igor Opaniuk <igor.opaniuk@gmail.com>

-- 
Best regards - Atentamente - Meilleures salutations

Igor Opaniuk

mailto: igor.opaniuk@gmail.com
skype: igor.opanyuk
https://www.linkedin.com/in/iopaniuk

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
  2024-06-13 10:13 ` [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() Mattijs Korpershoek
                     ` (2 preceding siblings ...)
  2024-06-13 17:10   ` Igor Opaniuk
@ 2024-06-13 18:43   ` Guillaume LA ROQUE
  3 siblings, 0 replies; 27+ messages in thread
From: Guillaume LA ROQUE @ 2024-06-13 18:43 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Dmitrii Merkurev, Roman Stratiienko, Igor Opaniuk,
	u-boot

Hi,

Le 13/06/2024 à 12:13, Mattijs Korpershoek a écrit :
> When calling android_image_get_dtb_by_index() using boot image v3+,
> we should also pass the vendor_boot ramdisk address.
>
> Use get_avendor_bootimg_addr() to do so.
>
> Notes: on boot image v2, this is harmless since get_avendor_bootimg_addr()
>         returns -1.
>         for legacy implementations that don't have CMD_ABOOTIMG, add a weak
>         implementation to avoid linking errors.
>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>   boot/image-android.c | 5 +++++
>   boot/image-fdt.c     | 2 +-
>   2 files changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/boot/image-android.c b/boot/image-android.c
> index ee626972c114..09c7a44e058a 100644
> --- a/boot/image-android.c
> +++ b/boot/image-android.c
> @@ -56,6 +56,11 @@ static ulong add_trailer(ulong bootconfig_start_addr, ulong bootconfig_size)
>   	return BOOTCONFIG_TRAILER_SIZE;
>   }
>   
> +__weak ulong get_avendor_bootimg_addr(void)
> +{
> +	return -1;
> +}
> +
>   static void android_boot_image_v3_v4_parse_hdr(const struct andr_boot_img_hdr_v3 *hdr,
>   					       struct andr_image_data *data)
>   {
> diff --git a/boot/image-fdt.c b/boot/image-fdt.c
> index 56dd7687f51c..8332792b8e80 100644
> --- a/boot/image-fdt.c
> +++ b/boot/image-fdt.c
> @@ -502,7 +502,7 @@ int boot_get_fdt(void *buf, const char *select, uint arch,
>   		 * Firstly check if this android boot image has dtb field.
>   		 */
>   		dtb_idx = (u32)env_get_ulong("adtb_idx", 10, 0);
> -		if (android_image_get_dtb_by_index((ulong)hdr, 0,
> +		if (android_image_get_dtb_by_index((ulong)hdr, get_avendor_bootimg_addr(),
>   						   dtb_idx, &fdt_addr, &fdt_size)) {
>   			fdt_blob = (char *)map_sysmem(fdt_addr, 0);
>   			if (fdt_check_header(fdt_blob))
>
Reviewed-by: Guillaume La Roque <glaroque@baylibre.com>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper
  2024-06-13 10:13 ` [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper Mattijs Korpershoek
  2024-06-13 14:16   ` Julien Masson
@ 2024-06-13 18:44   ` Guillaume LA ROQUE
  1 sibling, 0 replies; 27+ messages in thread
From: Guillaume LA ROQUE @ 2024-06-13 18:44 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Dmitrii Merkurev, Roman Stratiienko, Igor Opaniuk,
	u-boot

Le 13/06/2024 à 12:13, Mattijs Korpershoek a écrit :
> Some bootflows might be able to only boot from MMC devices.
>
> Add a helper function these bootflows can use.
>
> Reviewed-by: Igor Opaniuk <igor.opaniuk@gmail.com>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>   boot/bootflow.c    | 12 ++++++++++++
>   include/bootflow.h |  9 +++++++++
>   2 files changed, 21 insertions(+)
>
> diff --git a/boot/bootflow.c b/boot/bootflow.c
> index 9aa3179c3881..59d77d2385f4 100644
> --- a/boot/bootflow.c
> +++ b/boot/bootflow.c
> @@ -575,6 +575,18 @@ int bootflow_iter_check_blk(const struct bootflow_iter *iter)
>   	return -ENOTSUPP;
>   }
>   
> +int bootflow_iter_check_mmc(const struct bootflow_iter *iter)
> +{
> +	const struct udevice *media = dev_get_parent(iter->dev);
> +	enum uclass_id id = device_get_uclass_id(media);
> +
> +	log_debug("uclass %d: %s\n", id, uclass_get_name(id));
> +	if (id == UCLASS_MMC)
> +		return 0;
> +
> +	return -ENOTSUPP;
> +}
> +
>   int bootflow_iter_check_sf(const struct bootflow_iter *iter)
>   {
>   	const struct udevice *media = dev_get_parent(iter->dev);
> diff --git a/include/bootflow.h b/include/bootflow.h
> index 080ee8501225..6058ddd89b16 100644
> --- a/include/bootflow.h
> +++ b/include/bootflow.h
> @@ -407,6 +407,15 @@ void bootflow_remove(struct bootflow *bflow);
>    */
>   int bootflow_iter_check_blk(const struct bootflow_iter *iter);
>   
> +/**
> + * bootflow_iter_check_mmc() - Check that a bootflow uses a MMC device
> + *
> + * This checks the bootdev in the bootflow to make sure it uses a mmc device
> + *
> + * Return: 0 if OK, -ENOTSUPP if some other device is used (e.g. ethernet)
> + */
> +int bootflow_iter_check_mmc(const struct bootflow_iter *iter);
> +
>   /**
>    * bootflow_iter_check_sf() - Check that a bootflow uses SPI FLASH
>    *
>
Reviewed-by: Guillaume La Roque <glaroque@baylibre.com>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
  2024-06-13 10:13 ` [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr() Mattijs Korpershoek
  2024-06-13 14:16   ` Julien Masson
  2024-06-13 15:20   ` Simon Glass
@ 2024-06-13 18:45   ` Guillaume LA ROQUE
  2 siblings, 0 replies; 27+ messages in thread
From: Guillaume LA ROQUE @ 2024-06-13 18:45 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Dmitrii Merkurev, Roman Stratiienko, Igor Opaniuk,
	u-boot

Le 13/06/2024 à 12:13, Mattijs Korpershoek a écrit :
> The only way to configure the load addresses for both bootimg and
> vendor_bootimg is by using the "abootimg" command.
> If we want to use the C API, there is no equivalent.
>
> Add set_abootimg_addr() and set_avendor_bootimg_addr() so that we can
> specify the load address from C.
>
> This can be useful for implementing an Android bootmethod.
>
> Reviewed-by: Igor Opaniuk <igor.opaniuk@gmail.com>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>   cmd/abootimg.c  | 10 ++++++++++
>   include/image.h | 14 ++++++++++++++
>   2 files changed, 24 insertions(+)
>
> diff --git a/cmd/abootimg.c b/cmd/abootimg.c
> index 327712a536c0..ae7a1a7c83b0 100644
> --- a/cmd/abootimg.c
> +++ b/cmd/abootimg.c
> @@ -22,6 +22,11 @@ ulong get_abootimg_addr(void)
>   	return (_abootimg_addr == -1 ? image_load_addr : _abootimg_addr);
>   }
>   
> +void set_abootimg_addr(ulong addr)
> +{
> +	_abootimg_addr = addr;
> +}
> +
>   ulong get_ainit_bootimg_addr(void)
>   {
>   	return _ainit_bootimg_addr;
> @@ -32,6 +37,11 @@ ulong get_avendor_bootimg_addr(void)
>   	return _avendor_bootimg_addr;
>   }
>   
> +void set_avendor_bootimg_addr(ulong addr)
> +{
> +	_avendor_bootimg_addr = addr;
> +}
> +
>   static int abootimg_get_ver(int argc, char *const argv[])
>   {
>   	const struct andr_boot_img_hdr_v0 *hdr;
> diff --git a/include/image.h b/include/image.h
> index c5b288f62b44..df2decbf5c2a 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -1970,6 +1970,13 @@ bool is_android_vendor_boot_image_header(const void *vendor_boot_img);
>    */
>   ulong get_abootimg_addr(void);
>   
> +/**
> + * set_abootimg_addr() - Set Android boot image address
> + *
> + * Return: no returned results
> + */
> +void set_abootimg_addr(ulong addr);
> +
>   /**
>    * get_ainit_bootimg_addr() - Get Android init boot image address
>    *
> @@ -1984,6 +1991,13 @@ ulong get_ainit_bootimg_addr(void);
>    */
>   ulong get_avendor_bootimg_addr(void);
>   
> +/**
> + * set_abootimg_addr() - Set Android vendor boot image address
> + *
> + * Return: no returned results
> + */
> +void set_avendor_bootimg_addr(ulong addr);
> +
>   /**
>    * board_fit_config_name_match() - Check for a matching board name
>    *
>
Reviewed-by: Guillaume La Roque <glaroque@baylibre.com>


^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 5/5] bootstd: Add test for bootmeth_android
  2024-06-13 10:13 ` [PATCH v2 5/5] bootstd: Add test for bootmeth_android Mattijs Korpershoek
  2024-06-13 14:19   ` Julien Masson
@ 2024-06-13 18:47   ` Guillaume LA ROQUE
  1 sibling, 0 replies; 27+ messages in thread
From: Guillaume LA ROQUE @ 2024-06-13 18:47 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Dmitrii Merkurev, Roman Stratiienko, Igor Opaniuk,
	u-boot

Le 13/06/2024 à 12:13, Mattijs Korpershoek a écrit :
> Add a unit test for testing the Android bootmethod.
>
> This requires another mmc image (mmc7) to contain the following partitions:
> - misc: contains the Bootloader Control Block (BCB)
> - boot_a: contains a fake generic kernel image
> - vendor_boot_a: contains a fake vendor_boot image
>
> Also add BOOTMETH_ANDROID as a dependency on sandbox so that we can test
> this with:
>
> $ ./test/py/test.py --bd sandbox --build -k test_abootimg # build bootv4.img
> $ ./test/py/test.py --bd sandbox --build -k test_ut # build the mmc7.img
> $ ./test/py/test.py --bd sandbox --build -k bootflow_android
>
> Reviewed-by: Simon Glass <sjg@chromium.org>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
>   arch/sandbox/dts/test.dts |  8 +++++
>   configs/sandbox_defconfig |  2 +-
>   test/boot/bootflow.c      | 65 ++++++++++++++++++++++++++++++++++++++--
>   test/py/tests/test_ut.py  | 76 +++++++++++++++++++++++++++++++++++++++++++++++
>   4 files changed, 147 insertions(+), 4 deletions(-)
>
> diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
> index a012f5c4c9ba..5fb5eac862ec 100644
> --- a/arch/sandbox/dts/test.dts
> +++ b/arch/sandbox/dts/test.dts
> @@ -43,6 +43,7 @@
>   		mmc4 = "/mmc4";
>   		mmc5 = "/mmc5";
>   		mmc6 = "/mmc6";
> +		mmc7 = "/mmc7";
>   		pci0 = &pci0;
>   		pci1 = &pci1;
>   		pci2 = &pci2;
> @@ -1129,6 +1130,13 @@
>   		filename = "mmc6.img";
>   	};
>   
> +	/* This is used for Android tests */
> +	mmc7 {
> +		status = "disabled";
> +		compatible = "sandbox,mmc";
> +		filename = "mmc7.img";
> +	};
> +
>   	pch {
>   		compatible = "sandbox,pch";
>   	};
> diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
> index 93b52f2de5cf..bc4398f101a7 100644
> --- a/configs/sandbox_defconfig
> +++ b/configs/sandbox_defconfig
> @@ -15,6 +15,7 @@ CONFIG_FIT=y
>   CONFIG_FIT_RSASSA_PSS=y
>   CONFIG_FIT_CIPHER=y
>   CONFIG_FIT_VERBOSE=y
> +CONFIG_BOOTMETH_ANDROID=y
>   CONFIG_LEGACY_IMAGE_FORMAT=y
>   CONFIG_MEASURED_BOOT=y
>   CONFIG_BOOTSTAGE=y
> @@ -40,7 +41,6 @@ CONFIG_LOG_MAX_LEVEL=9
>   CONFIG_LOG_DEFAULT_LEVEL=6
>   CONFIG_DISPLAY_BOARDINFO_LATE=y
>   CONFIG_STACKPROTECTOR=y
> -CONFIG_ANDROID_AB=y
>   CONFIG_CMD_CPU=y
>   CONFIG_CMD_LICENSE=y
>   CONFIG_CMD_SMBIOS=y
> diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
> index 4511cfa7f9bf..934c4dcbad2b 100644
> --- a/test/boot/bootflow.c
> +++ b/test/boot/bootflow.c
> @@ -27,6 +27,7 @@
>   
>   DECLARE_GLOBAL_DATA_PTR;
>   
> +extern U_BOOT_DRIVER(bootmeth_android);
>   extern U_BOOT_DRIVER(bootmeth_cros);
>   extern U_BOOT_DRIVER(bootmeth_2script);
>   
> @@ -518,12 +519,12 @@ BOOTSTD_TEST(bootflow_cmd_boot, UT_TESTF_DM | UT_TESTF_SCAN_FDT);
>    * @uts: Unit test state
>    * @mmc_dev: MMC device to use, e.g. "mmc4". Note that this must remain valid
>    *	in the caller until
> - * @bind_cros: true to bind the ChromiumOS bootmeth
> + * @bind_cros: true to bind the ChromiumOS and Android bootmeths
>    * @old_orderp: Returns the original bootdev order, which must be restored
>    * Returns 0 on success, -ve on failure
>    */
>   static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
> -			    bool bind_cros, const char ***old_orderp)
> +			    bool bind_cros_android, const char ***old_orderp)
>   {
>   	static const char *order[] = {"mmc2", "mmc1", NULL, NULL};
>   	struct udevice *dev, *bootstd;
> @@ -545,12 +546,19 @@ static int prep_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
>   				"bootmeth_script", 0, ofnode_null(), &dev));
>   
>   	/* Enable the cros bootmeth if needed */
> -	if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros) {
> +	if (IS_ENABLED(CONFIG_BOOTMETH_CROS) && bind_cros_android) {
>   		ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
>   		ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_cros),
>   					"cros", 0, ofnode_null(), &dev));
>   	}
>   
> +	/* Enable the android bootmeths if needed */
> +	if (IS_ENABLED(CONFIG_BOOTMETH_ANDROID) && bind_cros_android) {
> +		ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
> +		ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_android),
> +					"android", 0, ofnode_null(), &dev));
> +	}
> +
>   	/* Change the order to include the device */
>   	std = dev_get_priv(bootstd);
>   	old_order = std->bootdev_order;
> @@ -589,6 +597,37 @@ static int scan_mmc_bootdev(struct unit_test_state *uts, const char *mmc_dev,
>   	return 0;
>   }
>   
> +/**
> + * scan_mmc_android_bootdev() - Set up an mmc bootdev so we can access other
> + * distros. Android bootflow might print "ANDROID:*" while scanning
> + *
> + * @uts: Unit test state
> + * @mmc_dev: MMC device to use, e.g. "mmc4"
> + * Returns 0 on success, -ve on failure
> + */
> +static int scan_mmc_android_bootdev(struct unit_test_state *uts, const char *mmc_dev)
> +{
> +	struct bootstd_priv *std;
> +	struct udevice *bootstd;
> +	const char **old_order;
> +
> +	ut_assertok(prep_mmc_bootdev(uts, mmc_dev, true, &old_order));
> +
> +	console_record_reset_enable();
> +	ut_assertok(run_command("bootflow scan", 0));
> +	/* Android bootflow might print one or two 'ANDROID:*' logs */
> +	ut_check_skipline(uts);
> +	ut_check_skipline(uts);
> +	ut_assert_console_end();
> +
> +	/* Restore the order used by the device tree */
> +	ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
> +	std = dev_get_priv(bootstd);
> +	std->bootdev_order = old_order;
> +
> +	return 0;
> +}
> +
>   /**
>    * scan_mmc4_bootdev() - Set up the mmc4 bootdev so we can access a fake Armbian
>    *
> @@ -1160,3 +1199,23 @@ static int bootflow_cros(struct unit_test_state *uts)
>   	return 0;
>   }
>   BOOTSTD_TEST(bootflow_cros, 0);
> +
> +/* Test Android bootmeth  */
> +static int bootflow_android(struct unit_test_state *uts)
> +{
> +	ut_assertok(scan_mmc_android_bootdev(uts, "mmc7"));
> +	ut_assertok(run_command("bootflow list", 0));
> +
> +	ut_assert_nextlinen("Showing all");
> +	ut_assert_nextlinen("Seq");
> +	ut_assert_nextlinen("---");
> +	ut_assert_nextlinen("  0  extlinux");
> +	ut_assert_nextlinen("  1  android      ready   mmc          0  mmc7.bootdev.whole        ");
> +	ut_assert_nextlinen("---");
> +	ut_assert_skip_to_line("(2 bootflows, 2 valid)");
> +
> +	ut_assert_console_end();
> +
> +	return 0;
> +}
> +BOOTSTD_TEST(bootflow_android, 0);
> diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
> index c169c835e38a..39e1abe02a68 100644
> --- a/test/py/tests/test_ut.py
> +++ b/test/py/tests/test_ut.py
> @@ -423,6 +423,81 @@ def setup_cros_image(cons):
>   
>       return fname
>   
> +def setup_android_image(cons):
> +    """Create a 20MB disk image with Android partitions"""
> +    Partition = collections.namedtuple('part', 'start,size,name')
> +    parts = {}
> +    disk_data = None
> +
> +    def set_part_data(partnum, data):
> +        """Set the contents of a disk partition
> +
> +        This updates disk_data by putting data in the right place
> +
> +        Args:
> +            partnum (int): Partition number to set
> +            data (bytes): Data for that partition
> +        """
> +        nonlocal disk_data
> +
> +        start = parts[partnum].start * sect_size
> +        disk_data = disk_data[:start] + data + disk_data[start + len(data):]
> +
> +    mmc_dev = 7
> +    fname = os.path.join(cons.config.source_dir, f'mmc{mmc_dev}.img')
> +    u_boot_utils.run_and_log(cons, 'qemu-img create %s 20M' % fname)
> +    u_boot_utils.run_and_log(cons, f'cgpt create {fname}')
> +
> +    ptr = 40
> +
> +    # Number of sectors in 1MB
> +    sect_size = 512
> +    sect_1mb = (1 << 20) // sect_size
> +
> +    required_parts = [
> +        {'num': 1, 'label':'misc', 'size': '1M'},
> +        {'num': 2, 'label':'boot_a', 'size': '4M'},
> +        {'num': 3, 'label':'boot_b', 'size': '4M'},
> +        {'num': 4, 'label':'vendor_boot_a', 'size': '4M'},
> +        {'num': 5, 'label':'vendor_boot_b', 'size': '4M'},
> +    ]
> +
> +    for part in required_parts:
> +        size_str = part['size']
> +        if 'M' in size_str:
> +            size = int(size_str[:-1]) * sect_1mb
> +        else:
> +            size = int(size_str)
> +        u_boot_utils.run_and_log(
> +            cons,
> +            f"cgpt add -i {part['num']} -b {ptr} -s {size} -l {part['label']} -t basicdata {fname}")
> +        ptr += size
> +
> +    u_boot_utils.run_and_log(cons, f'cgpt boot -p {fname}')
> +    out = u_boot_utils.run_and_log(cons, f'cgpt show -q {fname}')
> +
> +    # Create a dict (indexed by partition number) containing the above info
> +    for line in out.splitlines():
> +        start, size, num, name = line.split(maxsplit=3)
> +        parts[int(num)] = Partition(int(start), int(size), name)
> +
> +    with open(fname, 'rb') as inf:
> +        disk_data = inf.read()
> +
> +    boot_img = os.path.join(cons.config.result_dir, 'bootv4.img')
> +    with open(boot_img, 'rb') as inf:
> +        set_part_data(2, inf.read())
> +
> +    vendor_boot_img = os.path.join(cons.config.result_dir, 'vendor_boot.img')
> +    with open(vendor_boot_img, 'rb') as inf:
> +        set_part_data(4, inf.read())
> +
> +    with open(fname, 'wb') as outf:
> +        outf.write(disk_data)
> +
> +    print('wrote to {}'.format(fname))
> +
> +    return fname
>   
>   def setup_cedit_file(cons):
>       infname = os.path.join(cons.config.source_dir,
> @@ -477,6 +552,7 @@ def test_ut_dm_init_bootstd(u_boot_console):
>       setup_bootmenu_image(u_boot_console)
>       setup_cedit_file(u_boot_console)
>       setup_cros_image(u_boot_console)
> +    setup_android_image(u_boot_console)
>   
>       # Restart so that the new mmc1.img is picked up
>       u_boot_console.restart_uboot()
>
Reviewed-by: Guillaume La Roque <glaroque@baylibre.com>



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
                   ` (4 preceding siblings ...)
  2024-06-13 10:13 ` [PATCH v2 5/5] bootstd: Add test for bootmeth_android Mattijs Korpershoek
@ 2024-06-14  9:53 ` Guillaume LA ROQUE
  2024-06-14 11:44   ` Mattijs Korpershoek
  2024-06-17 13:53 ` Simon Glass
  2024-06-20 14:23 ` Tom Rini
  7 siblings, 1 reply; 27+ messages in thread
From: Guillaume LA ROQUE @ 2024-06-14  9:53 UTC (permalink / raw)
  To: Mattijs Korpershoek, Simon Glass
  Cc: Julien Masson, Dmitrii Merkurev, Roman Stratiienko, Igor Opaniuk,
	u-boot

Hi,

i apply  patch series with commit you give in cover letter and test on 
TI AM62S-SK board.
Android boot properly , just with a small changes in uboot eenv

setenv vendor_boot_comp_addr_r 0xd0000000

this changes is need link to patch done by roman on ramdisk and vendor 
boot loading.

so you can add for this series:

Tested-by: Guillaume La Roque <glaroque@baylibre.com>


Guillaume

Le 13/06/2024 à 12:13, Mattijs Korpershoek a écrit :
> Android boot flow is a bit different than a regular Linux distro.
> Android relies on multiple partitions in order to boot.
>
> A typical boot flow would be:
> 1. Parse the Bootloader Control Block (BCB, misc partition)
> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
> 3. If BCB requested recovery or normal android, run the following:
>     a. Get slot (A/B) from BCB
>     b. Run AVB (Android Verified Boot) on boot partitions
>     c. Load boot and vendor_boot partitions
>     d. Load device-tree, ramdisk and boot
>
> The AOSP documentation has more details at [1], [2], [3]
>
> This has been implemented via complex boot scripts such as [4].
> However, these boot script are neither very maintainable nor generic.
> Moreover, DISTRO_DEFAULTS is being deprecated [5].
>
> Add a generic Android bootflow implementation for bootstd.
>
> For this initial version, only boot image v4 is supported.
>
> This has been tested on sandbox using:
> $ ./test/py/test.py --bd sandbox --build -k test_ut
>
> This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
> To test on TI board, the following (WIP) patch is needed as well:
> https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04
>
> [1] https://source.android.com/docs/core/architecture/bootloader
> [2] https://source.android.com/docs/core/architecture/partitions
> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
> [6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html
>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
> Changes in v2:
> - Dropped patch 2/6 boot: android: Add image_android_get_version() (Igor)
> - Fixed multi-line comment style (Igor, Simon)
> - Added dependency on CMD_FASTBOOT for BOOTMETH_ANDROID (Igor)
> - Fixed various resource leaks (Igor)
> - Fixed bootmeth_priv dangling pointer on error cases (Igor)
> - Updated test instructions in commit message for patch 6/6
> - Added __weak impl of get_avendor_bootimg_addr() in patch 1 (dropped
>    Igor's review because of this change)
> - Added extra info in Kconfig to detail MMC limitation (Simon)
> - Fixed typo Bootmethod->Bootmeth (Simon)
> - Documented android_priv structure (Simon)
> - Demoted various messages from printf() to log_debug (Simon)
> - Fixed some lines too long (Simon)
> - Added function documentation to read_slotted_partition() (Simon)
> - Added some doc about avb extra_args being modified (Simon)
> - Link to v1: https://lore.kernel.org/r/20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com
>
> ---
> Mattijs Korpershoek (5):
>        boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
>        bootstd: Add bootflow_iter_check_mmc() helper
>        android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
>        bootstd: Add a bootmeth for Android
>        bootstd: Add test for bootmeth_android
>
>   MAINTAINERS               |   7 +
>   arch/sandbox/dts/test.dts |   8 +
>   boot/Kconfig              |  16 ++
>   boot/Makefile             |   2 +
>   boot/bootflow.c           |  12 +
>   boot/bootmeth_android.c   | 553 ++++++++++++++++++++++++++++++++++++++++++++++
>   boot/bootmeth_android.h   |  29 +++
>   boot/image-android.c      |   5 +
>   boot/image-fdt.c          |   2 +-
>   cmd/abootimg.c            |  10 +
>   configs/sandbox_defconfig |   2 +-
>   doc/develop/bootstd.rst   |   6 +
>   include/bootflow.h        |   9 +
>   include/image.h           |  14 ++
>   test/boot/bootflow.c      |  65 +++++-
>   test/py/tests/test_ut.py  |  76 +++++++
>   16 files changed, 811 insertions(+), 5 deletions(-)
> ---
> base-commit: f9886bc60f42d5bcfcfa4e474af7dc230400b6be
> change-id: 20240605-bootmeth-android-bfc8596e9367
>
> Best regards,



^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-14  9:53 ` [PATCH v2 0/5] bootstd: Add Android support Guillaume LA ROQUE
@ 2024-06-14 11:44   ` Mattijs Korpershoek
  0 siblings, 0 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-14 11:44 UTC (permalink / raw)
  To: Guillaume LA ROQUE, Simon Glass
  Cc: Julien Masson, Dmitrii Merkurev, Roman Stratiienko, Igor Opaniuk,
	u-boot

Hi Guillaume,

Thank you for testing.

On ven., juin 14, 2024 at 11:53, Guillaume LA ROQUE <glaroque@baylibre.com> wrote:

> Hi,
>
> i apply  patch series with commit you give in cover letter and test on 
> TI AM62S-SK board.
> Android boot properly , just with a small changes in uboot eenv
>
> setenv vendor_boot_comp_addr_r 0xd0000000

I see.

Thank you for sharing this.

I can confirm that this is indeed needed on next since
da3447d09fa0 ("android: Fix ramdisk loading for bootimage v3+").

Will take that into account when sending board support using bootmeth_android

>
> this changes is need link to patch done by roman on ramdisk and vendor 
> boot loading.
>
> so you can add for this series:
>
> Tested-by: Guillaume La Roque <glaroque@baylibre.com>
>
>

[...]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
                   ` (5 preceding siblings ...)
  2024-06-14  9:53 ` [PATCH v2 0/5] bootstd: Add Android support Guillaume LA ROQUE
@ 2024-06-17 13:53 ` Simon Glass
  2024-06-17 15:15   ` Mattijs Korpershoek
  2024-06-20 14:23 ` Tom Rini
  7 siblings, 1 reply; 27+ messages in thread
From: Simon Glass @ 2024-06-17 13:53 UTC (permalink / raw)
  To: Mattijs Korpershoek
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

Hi Mattijs,

On Thu, 13 Jun 2024 at 04:13, Mattijs Korpershoek
<mkorpershoek@baylibre.com> wrote:
>
> Android boot flow is a bit different than a regular Linux distro.
> Android relies on multiple partitions in order to boot.
>
> A typical boot flow would be:
> 1. Parse the Bootloader Control Block (BCB, misc partition)
> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
> 3. If BCB requested recovery or normal android, run the following:
>    a. Get slot (A/B) from BCB
>    b. Run AVB (Android Verified Boot) on boot partitions
>    c. Load boot and vendor_boot partitions
>    d. Load device-tree, ramdisk and boot
>
> The AOSP documentation has more details at [1], [2], [3]
>
> This has been implemented via complex boot scripts such as [4].
> However, these boot script are neither very maintainable nor generic.
> Moreover, DISTRO_DEFAULTS is being deprecated [5].
>
> Add a generic Android bootflow implementation for bootstd.
>
> For this initial version, only boot image v4 is supported.
>
> This has been tested on sandbox using:
> $ ./test/py/test.py --bd sandbox --build -k test_ut
>
> This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
> To test on TI board, the following (WIP) patch is needed as well:
> https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04
>
> [1] https://source.android.com/docs/core/architecture/bootloader
> [2] https://source.android.com/docs/core/architecture/partitions
> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
> [6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html
>
> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> ---
> Changes in v2:
> - Dropped patch 2/6 boot: android: Add image_android_get_version() (Igor)
> - Fixed multi-line comment style (Igor, Simon)
> - Added dependency on CMD_FASTBOOT for BOOTMETH_ANDROID (Igor)
> - Fixed various resource leaks (Igor)
> - Fixed bootmeth_priv dangling pointer on error cases (Igor)
> - Updated test instructions in commit message for patch 6/6
> - Added __weak impl of get_avendor_bootimg_addr() in patch 1 (dropped
>   Igor's review because of this change)
> - Added extra info in Kconfig to detail MMC limitation (Simon)
> - Fixed typo Bootmethod->Bootmeth (Simon)
> - Documented android_priv structure (Simon)
> - Demoted various messages from printf() to log_debug (Simon)
> - Fixed some lines too long (Simon)
> - Added function documentation to read_slotted_partition() (Simon)
> - Added some doc about avb extra_args being modified (Simon)
> - Link to v1: https://lore.kernel.org/r/20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com
>
> ---
> Mattijs Korpershoek (5):
>       boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
>       bootstd: Add bootflow_iter_check_mmc() helper
>       android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
>       bootstd: Add a bootmeth for Android
>       bootstd: Add test for bootmeth_android
>
>  MAINTAINERS               |   7 +
>  arch/sandbox/dts/test.dts |   8 +
>  boot/Kconfig              |  16 ++
>  boot/Makefile             |   2 +
>  boot/bootflow.c           |  12 +
>  boot/bootmeth_android.c   | 553 ++++++++++++++++++++++++++++++++++++++++++++++
>  boot/bootmeth_android.h   |  29 +++
>  boot/image-android.c      |   5 +
>  boot/image-fdt.c          |   2 +-
>  cmd/abootimg.c            |  10 +
>  configs/sandbox_defconfig |   2 +-
>  doc/develop/bootstd.rst   |   6 +
>  include/bootflow.h        |   9 +
>  include/image.h           |  14 ++
>  test/boot/bootflow.c      |  65 +++++-
>  test/py/tests/test_ut.py  |  76 +++++++
>  16 files changed, 811 insertions(+), 5 deletions(-)
> ---
> base-commit: f9886bc60f42d5bcfcfa4e474af7dc230400b6be
> change-id: 20240605-bootmeth-android-bfc8596e9367
>
> Best regards,
> --
> Mattijs Korpershoek <mkorpershoek@baylibre.com>
>

Thinking about this, I believe we should start having docs about the
individual bootmeths themselves.

Can you add a section about your new bootmeth? I will come up with a
patch for the others that I know about. Perhaps
doc/develop/bootstd.rst would be a suitable place for now?

Regards,
Simon

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-17 13:53 ` Simon Glass
@ 2024-06-17 15:15   ` Mattijs Korpershoek
  2024-06-19  3:03     ` Simon Glass
  0 siblings, 1 reply; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-17 15:15 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

Hi Simon,

On lun., juin 17, 2024 at 07:53, Simon Glass <sjg@chromium.org> wrote:

> Hi Mattijs,
>
> On Thu, 13 Jun 2024 at 04:13, Mattijs Korpershoek
> <mkorpershoek@baylibre.com> wrote:
>>
>> Android boot flow is a bit different than a regular Linux distro.
>> Android relies on multiple partitions in order to boot.
>>
>> A typical boot flow would be:
>> 1. Parse the Bootloader Control Block (BCB, misc partition)
>> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
>> 3. If BCB requested recovery or normal android, run the following:
>>    a. Get slot (A/B) from BCB
>>    b. Run AVB (Android Verified Boot) on boot partitions
>>    c. Load boot and vendor_boot partitions
>>    d. Load device-tree, ramdisk and boot
>>
>> The AOSP documentation has more details at [1], [2], [3]
>>
>> This has been implemented via complex boot scripts such as [4].
>> However, these boot script are neither very maintainable nor generic.
>> Moreover, DISTRO_DEFAULTS is being deprecated [5].
>>
>> Add a generic Android bootflow implementation for bootstd.
>>
>> For this initial version, only boot image v4 is supported.
>>
>> This has been tested on sandbox using:
>> $ ./test/py/test.py --bd sandbox --build -k test_ut
>>
>> This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
>> To test on TI board, the following (WIP) patch is needed as well:
>> https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04
>>
>> [1] https://source.android.com/docs/core/architecture/bootloader
>> [2] https://source.android.com/docs/core/architecture/partitions
>> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
>> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
>> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
>> [6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html
>>
>> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
>> ---
>> Changes in v2:
>> - Dropped patch 2/6 boot: android: Add image_android_get_version() (Igor)
>> - Fixed multi-line comment style (Igor, Simon)
>> - Added dependency on CMD_FASTBOOT for BOOTMETH_ANDROID (Igor)
>> - Fixed various resource leaks (Igor)
>> - Fixed bootmeth_priv dangling pointer on error cases (Igor)
>> - Updated test instructions in commit message for patch 6/6
>> - Added __weak impl of get_avendor_bootimg_addr() in patch 1 (dropped
>>   Igor's review because of this change)
>> - Added extra info in Kconfig to detail MMC limitation (Simon)
>> - Fixed typo Bootmethod->Bootmeth (Simon)
>> - Documented android_priv structure (Simon)
>> - Demoted various messages from printf() to log_debug (Simon)
>> - Fixed some lines too long (Simon)
>> - Added function documentation to read_slotted_partition() (Simon)
>> - Added some doc about avb extra_args being modified (Simon)
>> - Link to v1: https://lore.kernel.org/r/20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com
>>
>> ---
>> Mattijs Korpershoek (5):
>>       boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
>>       bootstd: Add bootflow_iter_check_mmc() helper
>>       android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
>>       bootstd: Add a bootmeth for Android
>>       bootstd: Add test for bootmeth_android
>>
>>  MAINTAINERS               |   7 +
>>  arch/sandbox/dts/test.dts |   8 +
>>  boot/Kconfig              |  16 ++
>>  boot/Makefile             |   2 +
>>  boot/bootflow.c           |  12 +
>>  boot/bootmeth_android.c   | 553 ++++++++++++++++++++++++++++++++++++++++++++++
>>  boot/bootmeth_android.h   |  29 +++
>>  boot/image-android.c      |   5 +
>>  boot/image-fdt.c          |   2 +-
>>  cmd/abootimg.c            |  10 +
>>  configs/sandbox_defconfig |   2 +-
>>  doc/develop/bootstd.rst   |   6 +
>>  include/bootflow.h        |   9 +
>>  include/image.h           |  14 ++
>>  test/boot/bootflow.c      |  65 +++++-
>>  test/py/tests/test_ut.py  |  76 +++++++
>>  16 files changed, 811 insertions(+), 5 deletions(-)
>> ---
>> base-commit: f9886bc60f42d5bcfcfa4e474af7dc230400b6be
>> change-id: 20240605-bootmeth-android-bfc8596e9367
>>
>> Best regards,
>> --
>> Mattijs Korpershoek <mkorpershoek@baylibre.com>
>>
>
> Thinking about this, I believe we should start having docs about the
> individual bootmeths themselves.

Yes.

>
> Can you add a section about your new bootmeth? I will come up with a
> patch for the others that I know about. Perhaps
> doc/develop/bootstd.rst would be a suitable place for now?

Yes I can add a section. I would have preferred to have an example to
work from there, but I can start writing docs as well.

I'm leaving on vacation soon (without computer), so I'll be able to
send a v3 with docs included in at earliest a 2-3 weeks from now.

If you make a patch for the other bootmeths in the mean-time, please cc
me so that I can help review and have an example for Android.

Thanks!
Mattijs

>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-17 15:15   ` Mattijs Korpershoek
@ 2024-06-19  3:03     ` Simon Glass
  2024-06-19  9:25       ` Mattijs Korpershoek
  2024-07-24 12:43       ` Mattijs Korpershoek
  0 siblings, 2 replies; 27+ messages in thread
From: Simon Glass @ 2024-06-19  3:03 UTC (permalink / raw)
  To: Mattijs Korpershoek
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

Hi Mattijs,

On Mon, 17 Jun 2024 at 09:15, Mattijs Korpershoek
<mkorpershoek@baylibre.com> wrote:
>
> Hi Simon,
>
> On lun., juin 17, 2024 at 07:53, Simon Glass <sjg@chromium.org> wrote:
>
> > Hi Mattijs,
> >
> > On Thu, 13 Jun 2024 at 04:13, Mattijs Korpershoek
> > <mkorpershoek@baylibre.com> wrote:
> >>
> >> Android boot flow is a bit different than a regular Linux distro.
> >> Android relies on multiple partitions in order to boot.
> >>
> >> A typical boot flow would be:
> >> 1. Parse the Bootloader Control Block (BCB, misc partition)
> >> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
> >> 3. If BCB requested recovery or normal android, run the following:
> >>    a. Get slot (A/B) from BCB
> >>    b. Run AVB (Android Verified Boot) on boot partitions
> >>    c. Load boot and vendor_boot partitions
> >>    d. Load device-tree, ramdisk and boot
> >>
> >> The AOSP documentation has more details at [1], [2], [3]
> >>
> >> This has been implemented via complex boot scripts such as [4].
> >> However, these boot script are neither very maintainable nor generic.
> >> Moreover, DISTRO_DEFAULTS is being deprecated [5].
> >>
> >> Add a generic Android bootflow implementation for bootstd.
> >>
> >> For this initial version, only boot image v4 is supported.
> >>
> >> This has been tested on sandbox using:
> >> $ ./test/py/test.py --bd sandbox --build -k test_ut
> >>
> >> This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
> >> To test on TI board, the following (WIP) patch is needed as well:
> >> https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04
> >>
> >> [1] https://source.android.com/docs/core/architecture/bootloader
> >> [2] https://source.android.com/docs/core/architecture/partitions
> >> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
> >> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
> >> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
> >> [6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html
> >>
> >> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
> >> ---
> >> Changes in v2:
> >> - Dropped patch 2/6 boot: android: Add image_android_get_version() (Igor)
> >> - Fixed multi-line comment style (Igor, Simon)
> >> - Added dependency on CMD_FASTBOOT for BOOTMETH_ANDROID (Igor)
> >> - Fixed various resource leaks (Igor)
> >> - Fixed bootmeth_priv dangling pointer on error cases (Igor)
> >> - Updated test instructions in commit message for patch 6/6
> >> - Added __weak impl of get_avendor_bootimg_addr() in patch 1 (dropped
> >>   Igor's review because of this change)
> >> - Added extra info in Kconfig to detail MMC limitation (Simon)
> >> - Fixed typo Bootmethod->Bootmeth (Simon)
> >> - Documented android_priv structure (Simon)
> >> - Demoted various messages from printf() to log_debug (Simon)
> >> - Fixed some lines too long (Simon)
> >> - Added function documentation to read_slotted_partition() (Simon)
> >> - Added some doc about avb extra_args being modified (Simon)
> >> - Link to v1: https://lore.kernel.org/r/20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com
> >>
> >> ---
> >> Mattijs Korpershoek (5):
> >>       boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
> >>       bootstd: Add bootflow_iter_check_mmc() helper
> >>       android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
> >>       bootstd: Add a bootmeth for Android
> >>       bootstd: Add test for bootmeth_android
> >>
> >>  MAINTAINERS               |   7 +
> >>  arch/sandbox/dts/test.dts |   8 +
> >>  boot/Kconfig              |  16 ++
> >>  boot/Makefile             |   2 +
> >>  boot/bootflow.c           |  12 +
> >>  boot/bootmeth_android.c   | 553 ++++++++++++++++++++++++++++++++++++++++++++++
> >>  boot/bootmeth_android.h   |  29 +++
> >>  boot/image-android.c      |   5 +
> >>  boot/image-fdt.c          |   2 +-
> >>  cmd/abootimg.c            |  10 +
> >>  configs/sandbox_defconfig |   2 +-
> >>  doc/develop/bootstd.rst   |   6 +
> >>  include/bootflow.h        |   9 +
> >>  include/image.h           |  14 ++
> >>  test/boot/bootflow.c      |  65 +++++-
> >>  test/py/tests/test_ut.py  |  76 +++++++
> >>  16 files changed, 811 insertions(+), 5 deletions(-)
> >> ---
> >> base-commit: f9886bc60f42d5bcfcfa4e474af7dc230400b6be
> >> change-id: 20240605-bootmeth-android-bfc8596e9367
> >>
> >> Best regards,
> >> --
> >> Mattijs Korpershoek <mkorpershoek@baylibre.com>
> >>
> >
> > Thinking about this, I believe we should start having docs about the
> > individual bootmeths themselves.
>
> Yes.
>
> >
> > Can you add a section about your new bootmeth? I will come up with a
> > patch for the others that I know about. Perhaps
> > doc/develop/bootstd.rst would be a suitable place for now?
>
> Yes I can add a section. I would have preferred to have an example to
> work from there, but I can start writing docs as well.
>
> I'm leaving on vacation soon (without computer), so I'll be able to
> send a v3 with docs included in at earliest a 2-3 weeks from now.

It isn't a blocker for this series, just something I thought of.

>
> If you make a patch for the other bootmeths in the mean-time, please cc
> me so that I can help review and have an example for Android.

Yes, will do, if I do.

Regards,
Simon

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-19  3:03     ` Simon Glass
@ 2024-06-19  9:25       ` Mattijs Korpershoek
  2024-07-24 12:43       ` Mattijs Korpershoek
  1 sibling, 0 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-06-19  9:25 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

Hi Simon.

On mar., juin 18, 2024 at 21:03, Simon Glass <sjg@chromium.org> wrote:

> Hi Mattijs,
>
> On Mon, 17 Jun 2024 at 09:15, Mattijs Korpershoek
> <mkorpershoek@baylibre.com> wrote:
>>
>> Hi Simon,
>>
>> On lun., juin 17, 2024 at 07:53, Simon Glass <sjg@chromium.org> wrote:
>>
>> > Hi Mattijs,
>> >
>> > On Thu, 13 Jun 2024 at 04:13, Mattijs Korpershoek
>> > <mkorpershoek@baylibre.com> wrote:
>> >>
>> >> Android boot flow is a bit different than a regular Linux distro.
>> >> Android relies on multiple partitions in order to boot.
>> >>
>> >> A typical boot flow would be:
>> >> 1. Parse the Bootloader Control Block (BCB, misc partition)
>> >> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
>> >> 3. If BCB requested recovery or normal android, run the following:
>> >>    a. Get slot (A/B) from BCB
>> >>    b. Run AVB (Android Verified Boot) on boot partitions
>> >>    c. Load boot and vendor_boot partitions
>> >>    d. Load device-tree, ramdisk and boot
>> >>
>> >> The AOSP documentation has more details at [1], [2], [3]
>> >>
>> >> This has been implemented via complex boot scripts such as [4].
>> >> However, these boot script are neither very maintainable nor generic.
>> >> Moreover, DISTRO_DEFAULTS is being deprecated [5].
>> >>
>> >> Add a generic Android bootflow implementation for bootstd.
>> >>
>> >> For this initial version, only boot image v4 is supported.
>> >>
>> >> This has been tested on sandbox using:
>> >> $ ./test/py/test.py --bd sandbox --build -k test_ut
>> >>
>> >> This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
>> >> To test on TI board, the following (WIP) patch is needed as well:
>> >> https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04
>> >>
>> >> [1] https://source.android.com/docs/core/architecture/bootloader
>> >> [2] https://source.android.com/docs/core/architecture/partitions
>> >> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
>> >> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
>> >> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
>> >> [6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html
>> >>
>> >> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
>> >> ---
>> >> Changes in v2:
>> >> - Dropped patch 2/6 boot: android: Add image_android_get_version() (Igor)
>> >> - Fixed multi-line comment style (Igor, Simon)
>> >> - Added dependency on CMD_FASTBOOT for BOOTMETH_ANDROID (Igor)
>> >> - Fixed various resource leaks (Igor)
>> >> - Fixed bootmeth_priv dangling pointer on error cases (Igor)
>> >> - Updated test instructions in commit message for patch 6/6
>> >> - Added __weak impl of get_avendor_bootimg_addr() in patch 1 (dropped
>> >>   Igor's review because of this change)
>> >> - Added extra info in Kconfig to detail MMC limitation (Simon)
>> >> - Fixed typo Bootmethod->Bootmeth (Simon)
>> >> - Documented android_priv structure (Simon)
>> >> - Demoted various messages from printf() to log_debug (Simon)
>> >> - Fixed some lines too long (Simon)
>> >> - Added function documentation to read_slotted_partition() (Simon)
>> >> - Added some doc about avb extra_args being modified (Simon)
>> >> - Link to v1: https://lore.kernel.org/r/20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com
>> >>
>> >> ---
>> >> Mattijs Korpershoek (5):
>> >>       boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
>> >>       bootstd: Add bootflow_iter_check_mmc() helper
>> >>       android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
>> >>       bootstd: Add a bootmeth for Android
>> >>       bootstd: Add test for bootmeth_android
>> >>
>> >>  MAINTAINERS               |   7 +
>> >>  arch/sandbox/dts/test.dts |   8 +
>> >>  boot/Kconfig              |  16 ++
>> >>  boot/Makefile             |   2 +
>> >>  boot/bootflow.c           |  12 +
>> >>  boot/bootmeth_android.c   | 553 ++++++++++++++++++++++++++++++++++++++++++++++
>> >>  boot/bootmeth_android.h   |  29 +++
>> >>  boot/image-android.c      |   5 +
>> >>  boot/image-fdt.c          |   2 +-
>> >>  cmd/abootimg.c            |  10 +
>> >>  configs/sandbox_defconfig |   2 +-
>> >>  doc/develop/bootstd.rst   |   6 +
>> >>  include/bootflow.h        |   9 +
>> >>  include/image.h           |  14 ++
>> >>  test/boot/bootflow.c      |  65 +++++-
>> >>  test/py/tests/test_ut.py  |  76 +++++++
>> >>  16 files changed, 811 insertions(+), 5 deletions(-)
>> >> ---
>> >> base-commit: f9886bc60f42d5bcfcfa4e474af7dc230400b6be
>> >> change-id: 20240605-bootmeth-android-bfc8596e9367
>> >>
>> >> Best regards,
>> >> --
>> >> Mattijs Korpershoek <mkorpershoek@baylibre.com>
>> >>
>> >
>> > Thinking about this, I believe we should start having docs about the
>> > individual bootmeths themselves.
>>
>> Yes.
>>
>> >
>> > Can you add a section about your new bootmeth? I will come up with a
>> > patch for the others that I know about. Perhaps
>> > doc/develop/bootstd.rst would be a suitable place for now?
>>
>> Yes I can add a section. I would have preferred to have an example to
>> work from there, but I can start writing docs as well.
>>
>> I'm leaving on vacation soon (without computer), so I'll be able to
>> send a v3 with docs included in at earliest a 2-3 weeks from now.
>
> It isn't a blocker for this series, just something I thought of.

Understood. In that case if there are no other remarks on this series,
I'd prefer to submit a separate documentation patch once this is applied!

>
>>
>> If you make a patch for the other bootmeths in the mean-time, please cc
>> me so that I can help review and have an example for Android.
>
> Yes, will do, if I do.
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
                   ` (6 preceding siblings ...)
  2024-06-17 13:53 ` Simon Glass
@ 2024-06-20 14:23 ` Tom Rini
  2024-07-04  9:09   ` Mattijs Korpershoek
  7 siblings, 1 reply; 27+ messages in thread
From: Tom Rini @ 2024-06-20 14:23 UTC (permalink / raw)
  To: Mattijs Korpershoek
  Cc: Simon Glass, Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

[-- Attachment #1: Type: text/plain, Size: 2444 bytes --]

On Thu, Jun 13, 2024 at 12:13:07PM +0200, Mattijs Korpershoek wrote:

> Android boot flow is a bit different than a regular Linux distro.
> Android relies on multiple partitions in order to boot.
> 
> A typical boot flow would be:
> 1. Parse the Bootloader Control Block (BCB, misc partition)
> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
> 3. If BCB requested recovery or normal android, run the following:
>    a. Get slot (A/B) from BCB
>    b. Run AVB (Android Verified Boot) on boot partitions
>    c. Load boot and vendor_boot partitions
>    d. Load device-tree, ramdisk and boot
> 
> The AOSP documentation has more details at [1], [2], [3]
> 
> This has been implemented via complex boot scripts such as [4].
> However, these boot script are neither very maintainable nor generic.
> Moreover, DISTRO_DEFAULTS is being deprecated [5].
> 
> Add a generic Android bootflow implementation for bootstd.
> 
> For this initial version, only boot image v4 is supported.
> 
> This has been tested on sandbox using:
> $ ./test/py/test.py --bd sandbox --build -k test_ut
> 
> This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
> To test on TI board, the following (WIP) patch is needed as well:
> https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04
> 
> [1] https://source.android.com/docs/core/architecture/bootloader
> [2] https://source.android.com/docs/core/architecture/partitions
> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
> [6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html

This leads to failures in CI such as:
=================================== FAILURES ===================================
___________________________ test_ut_dm_init_bootstd ____________________________
test/py/tests/test_ut.py:555: in test_ut_dm_init_bootstd
    setup_android_image(u_boot_console)
test/py/tests/test_ut.py:488: in setup_android_image
    with open(boot_img, 'rb') as inf:
E   FileNotFoundError: [Errno 2] No such file or directory: '/tmp/malta64el/bootv4.img'
----------------------------- Captured stdout call -----------------------------

-- 
Tom

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 659 bytes --]

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-20 14:23 ` Tom Rini
@ 2024-07-04  9:09   ` Mattijs Korpershoek
  0 siblings, 0 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-07-04  9:09 UTC (permalink / raw)
  To: Tom Rini
  Cc: Simon Glass, Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

Hi Tom,

On jeu., juin 20, 2024 at 08:23, Tom Rini <trini@konsulko.com> wrote:

> On Thu, Jun 13, 2024 at 12:13:07PM +0200, Mattijs Korpershoek wrote:
>
>> Android boot flow is a bit different than a regular Linux distro.
>> Android relies on multiple partitions in order to boot.
>> 
>> A typical boot flow would be:
>> 1. Parse the Bootloader Control Block (BCB, misc partition)
>> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
>> 3. If BCB requested recovery or normal android, run the following:
>>    a. Get slot (A/B) from BCB
>>    b. Run AVB (Android Verified Boot) on boot partitions
>>    c. Load boot and vendor_boot partitions
>>    d. Load device-tree, ramdisk and boot
>> 
>> The AOSP documentation has more details at [1], [2], [3]
>> 
>> This has been implemented via complex boot scripts such as [4].
>> However, these boot script are neither very maintainable nor generic.
>> Moreover, DISTRO_DEFAULTS is being deprecated [5].
>> 
>> Add a generic Android bootflow implementation for bootstd.
>> 
>> For this initial version, only boot image v4 is supported.
>> 
>> This has been tested on sandbox using:
>> $ ./test/py/test.py --bd sandbox --build -k test_ut
>> 
>> This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
>> To test on TI board, the following (WIP) patch is needed as well:
>> https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04
>> 
>> [1] https://source.android.com/docs/core/architecture/bootloader
>> [2] https://source.android.com/docs/core/architecture/partitions
>> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
>> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
>> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
>> [6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html
>
> This leads to failures in CI such as:
> =================================== FAILURES ===================================
> ___________________________ test_ut_dm_init_bootstd ____________________________
> test/py/tests/test_ut.py:555: in test_ut_dm_init_bootstd
>     setup_android_image(u_boot_console)
> test/py/tests/test_ut.py:488: in setup_android_image
>     with open(boot_img, 'rb') as inf:
> E   FileNotFoundError: [Errno 2] No such file or directory: '/tmp/malta64el/bootv4.img'
> ----------------------------- Captured stdout call -----------------------------

Thank you for reporting, and sorry about the CI failure.
I think I need to somehow declare a dependency on the bootv4.img file.

I will send a v3 to fix this.

>
> -- 
> Tom

^ permalink raw reply	[flat|nested] 27+ messages in thread

* Re: [PATCH v2 0/5] bootstd: Add Android support
  2024-06-19  3:03     ` Simon Glass
  2024-06-19  9:25       ` Mattijs Korpershoek
@ 2024-07-24 12:43       ` Mattijs Korpershoek
  1 sibling, 0 replies; 27+ messages in thread
From: Mattijs Korpershoek @ 2024-07-24 12:43 UTC (permalink / raw)
  To: Simon Glass
  Cc: Julien Masson, Guillaume La Roque, Dmitrii Merkurev,
	Roman Stratiienko, Igor Opaniuk, u-boot

On mar., juin 18, 2024 at 21:03, Simon Glass <sjg@chromium.org> wrote:

> Hi Mattijs,
>
> On Mon, 17 Jun 2024 at 09:15, Mattijs Korpershoek
> <mkorpershoek@baylibre.com> wrote:
>>
>> Hi Simon,
>>
>> On lun., juin 17, 2024 at 07:53, Simon Glass <sjg@chromium.org> wrote:
>>
>> > Hi Mattijs,
>> >
>> > On Thu, 13 Jun 2024 at 04:13, Mattijs Korpershoek
>> > <mkorpershoek@baylibre.com> wrote:
>> >>
>> >> Android boot flow is a bit different than a regular Linux distro.
>> >> Android relies on multiple partitions in order to boot.
>> >>
>> >> A typical boot flow would be:
>> >> 1. Parse the Bootloader Control Block (BCB, misc partition)
>> >> 2. If BCB requested bootonce-bootloader, start fastboot and wait.
>> >> 3. If BCB requested recovery or normal android, run the following:
>> >>    a. Get slot (A/B) from BCB
>> >>    b. Run AVB (Android Verified Boot) on boot partitions
>> >>    c. Load boot and vendor_boot partitions
>> >>    d. Load device-tree, ramdisk and boot
>> >>
>> >> The AOSP documentation has more details at [1], [2], [3]
>> >>
>> >> This has been implemented via complex boot scripts such as [4].
>> >> However, these boot script are neither very maintainable nor generic.
>> >> Moreover, DISTRO_DEFAULTS is being deprecated [5].
>> >>
>> >> Add a generic Android bootflow implementation for bootstd.
>> >>
>> >> For this initial version, only boot image v4 is supported.
>> >>
>> >> This has been tested on sandbox using:
>> >> $ ./test/py/test.py --bd sandbox --build -k test_ut
>> >>
>> >> This has also been tested on the AM62X SK EVM using TI's Android SDK[6]
>> >> To test on TI board, the following (WIP) patch is needed as well:
>> >> https://gitlab.baylibre.com/baylibre/ti/ti-u-boot/-/commit/84cceb912bccd7cdd7f9dd69bca0e5d987a1fd04
>> >>
>> >> [1] https://source.android.com/docs/core/architecture/bootloader
>> >> [2] https://source.android.com/docs/core/architecture/partitions
>> >> [3] https://source.android.com/docs/core/architecture/partitions/generic-boot
>> >> [4] https://source.denx.de/u-boot/u-boot/-/blob/master/include/configs/meson64_android.h
>> >> [5] https://lore.kernel.org/r/all/20230914165615.1058529-17-sjg@chromium.org/
>> >> [6] https://software-dl.ti.com/processor-sdk-android/esd/AM62X/09_02_00/docs/android/Overview.html
>> >>
>> >> Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
>> >> ---
>> >> Changes in v2:
>> >> - Dropped patch 2/6 boot: android: Add image_android_get_version() (Igor)
>> >> - Fixed multi-line comment style (Igor, Simon)
>> >> - Added dependency on CMD_FASTBOOT for BOOTMETH_ANDROID (Igor)
>> >> - Fixed various resource leaks (Igor)
>> >> - Fixed bootmeth_priv dangling pointer on error cases (Igor)
>> >> - Updated test instructions in commit message for patch 6/6
>> >> - Added __weak impl of get_avendor_bootimg_addr() in patch 1 (dropped
>> >>   Igor's review because of this change)
>> >> - Added extra info in Kconfig to detail MMC limitation (Simon)
>> >> - Fixed typo Bootmethod->Bootmeth (Simon)
>> >> - Documented android_priv structure (Simon)
>> >> - Demoted various messages from printf() to log_debug (Simon)
>> >> - Fixed some lines too long (Simon)
>> >> - Added function documentation to read_slotted_partition() (Simon)
>> >> - Added some doc about avb extra_args being modified (Simon)
>> >> - Link to v1: https://lore.kernel.org/r/20240606-bootmeth-android-v1-0-0c69d4457cc5@baylibre.com
>> >>
>> >> ---
>> >> Mattijs Korpershoek (5):
>> >>       boot: android: Provide vendor_bootimg_addr in boot_get_fdt()
>> >>       bootstd: Add bootflow_iter_check_mmc() helper
>> >>       android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr()
>> >>       bootstd: Add a bootmeth for Android
>> >>       bootstd: Add test for bootmeth_android
>> >>
>> >>  MAINTAINERS               |   7 +
>> >>  arch/sandbox/dts/test.dts |   8 +
>> >>  boot/Kconfig              |  16 ++
>> >>  boot/Makefile             |   2 +
>> >>  boot/bootflow.c           |  12 +
>> >>  boot/bootmeth_android.c   | 553 ++++++++++++++++++++++++++++++++++++++++++++++
>> >>  boot/bootmeth_android.h   |  29 +++
>> >>  boot/image-android.c      |   5 +
>> >>  boot/image-fdt.c          |   2 +-
>> >>  cmd/abootimg.c            |  10 +
>> >>  configs/sandbox_defconfig |   2 +-
>> >>  doc/develop/bootstd.rst   |   6 +
>> >>  include/bootflow.h        |   9 +
>> >>  include/image.h           |  14 ++
>> >>  test/boot/bootflow.c      |  65 +++++-
>> >>  test/py/tests/test_ut.py  |  76 +++++++
>> >>  16 files changed, 811 insertions(+), 5 deletions(-)
>> >> ---
>> >> base-commit: f9886bc60f42d5bcfcfa4e474af7dc230400b6be
>> >> change-id: 20240605-bootmeth-android-bfc8596e9367
>> >>
>> >> Best regards,
>> >> --
>> >> Mattijs Korpershoek <mkorpershoek@baylibre.com>
>> >>
>> >
>> > Thinking about this, I believe we should start having docs about the
>> > individual bootmeths themselves.
>>
>> Yes.
>>
>> >
>> > Can you add a section about your new bootmeth? I will come up with a
>> > patch for the others that I know about. Perhaps
>> > doc/develop/bootstd.rst would be a suitable place for now?
>>
>> Yes I can add a section. I would have preferred to have an example to
>> work from there, but I can start writing docs as well.
>>
>> I'm leaving on vacation soon (without computer), so I'll be able to
>> send a v3 with docs included in at earliest a 2-3 weeks from now.
>
> It isn't a blocker for this series, just something I thought of.

For future reference, the doc has been submitted here:

https://lore.kernel.org/all/20240724-doc-bootstd-android-v1-1-03a55b7a7c92@baylibre.com/

>
>>
>> If you make a patch for the other bootmeths in the mean-time, please cc
>> me so that I can help review and have an example for Android.
>
> Yes, will do, if I do.
>
> Regards,
> Simon

^ permalink raw reply	[flat|nested] 27+ messages in thread

end of thread, other threads:[~2024-07-24 12:43 UTC | newest]

Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-06-13 10:13 [PATCH v2 0/5] bootstd: Add Android support Mattijs Korpershoek
2024-06-13 10:13 ` [PATCH v2 1/5] boot: android: Provide vendor_bootimg_addr in boot_get_fdt() Mattijs Korpershoek
2024-06-13 15:22   ` Simon Glass
2024-06-13 15:42   ` Julien Masson
2024-06-13 17:10   ` Igor Opaniuk
2024-06-13 18:43   ` Guillaume LA ROQUE
2024-06-13 10:13 ` [PATCH v2 2/5] bootstd: Add bootflow_iter_check_mmc() helper Mattijs Korpershoek
2024-06-13 14:16   ` Julien Masson
2024-06-13 18:44   ` Guillaume LA ROQUE
2024-06-13 10:13 ` [PATCH v2 3/5] android: boot: Add set_abootimg_addr() and set_avendor_bootimg_addr() Mattijs Korpershoek
2024-06-13 14:16   ` Julien Masson
2024-06-13 15:20   ` Simon Glass
2024-06-13 18:45   ` Guillaume LA ROQUE
2024-06-13 10:13 ` [PATCH v2 4/5] bootstd: Add a bootmeth for Android Mattijs Korpershoek
2024-06-13 14:19   ` Julien Masson
2024-06-13 10:13 ` [PATCH v2 5/5] bootstd: Add test for bootmeth_android Mattijs Korpershoek
2024-06-13 14:19   ` Julien Masson
2024-06-13 18:47   ` Guillaume LA ROQUE
2024-06-14  9:53 ` [PATCH v2 0/5] bootstd: Add Android support Guillaume LA ROQUE
2024-06-14 11:44   ` Mattijs Korpershoek
2024-06-17 13:53 ` Simon Glass
2024-06-17 15:15   ` Mattijs Korpershoek
2024-06-19  3:03     ` Simon Glass
2024-06-19  9:25       ` Mattijs Korpershoek
2024-07-24 12:43       ` Mattijs Korpershoek
2024-06-20 14:23 ` Tom Rini
2024-07-04  9:09   ` Mattijs Korpershoek

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.