Re: [PATCH v2 4/5] bootstd: Add a bootmeth for Android

2024-06-13 Thread Julien Masson


On Thu 13 Jun 2024 at 16:18, 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:
> 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-...@chromium.org/
> 
> Reviewed-by: Simon Glass 
> Signed-off-by: Mattijs Korpershoek 
> ---
>  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 
> +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 
>  R:   Qu Wenruo 
> 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 ..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 
> + */
> +#define LOG_CATEGORY UCLASS_BOOTSTD
> +
> +#include 
> +#include 
> +#if CONFIG_IS_ENABLED(AVB_VERIFY)
> +#include 
> +#endif
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#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 

[PATCH v2 4/5] bootstd: Add a bootmeth for Android

2024-06-13 Thread 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-...@chromium.org/

Reviewed-by: Simon Glass 
Signed-off-by: Mattijs Korpershoek 
---
 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 
+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 
 R: Qu Wenruo 
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 ..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 
+ */
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include 
+#include 
+#if CONFIG_IS_ENABLED(AVB_VERIFY)
+#include 
+#endif
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#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