* [U-Boot] [PATCH v5 1/6] disk: part: Extend API to get partition info
2019-07-05 12:37 [U-Boot] [PATCH v5 0/6] android: implement A/B boot process Igor Opaniuk
@ 2019-07-05 12:37 ` Igor Opaniuk
2019-07-24 20:06 ` Tom Rini
2019-07-05 12:37 ` [U-Boot] [PATCH v5 2/6] common: Implement A/B metadata Igor Opaniuk
` (5 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Igor Opaniuk @ 2019-07-05 12:37 UTC (permalink / raw)
To: u-boot
From: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
This patch adds part_get_info_by_dev_and_name_or_num() function which
allows us to get partition info from its number or name. Partition of
interest is specified by string like "device_num:partition_number" or
"device_num#partition_name".
The patch was extracted from [1].
[1] https://android-review.googlesource.com/c/platform/external/u-boot/+/729880/2
Signed-off-by: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Reviewed-by: Alistair Strachan <astrachan@google.com>
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
disk/part.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/part.h | 21 ++++++++++++++++
2 files changed, 89 insertions(+)
diff --git a/disk/part.c b/disk/part.c
index f14bc22b6d..7e84214731 100644
--- a/disk/part.c
+++ b/disk/part.c
@@ -674,6 +674,74 @@ int part_get_info_by_name(struct blk_desc *dev_desc, const char *name,
return part_get_info_by_name_type(dev_desc, name, info, PART_TYPE_ALL);
}
+/**
+ * Get partition info from device number and partition name.
+ *
+ * Parse a device number and partition name string in the form of
+ * "device_num#partition_name", for example "0#misc". If the partition
+ * is found, sets dev_desc and part_info accordingly with the information
+ * of the partition with the given partition_name.
+ *
+ * @param[in] dev_iface Device interface
+ * @param[in] dev_part_str Input string argument, like "0#misc"
+ * @param[out] dev_desc Place to store the device description pointer
+ * @param[out] part_info Place to store the partition information
+ * @return 0 on success, or a negative on error
+ */
+static int part_get_info_by_dev_and_name(const char *dev_iface,
+ const char *dev_part_str,
+ struct blk_desc **dev_desc,
+ disk_partition_t *part_info)
+{
+ char *ep;
+ const char *part_str;
+ int dev_num;
+
+ part_str = strchr(dev_part_str, '#');
+ if (!part_str || part_str == dev_part_str)
+ return -EINVAL;
+
+ dev_num = simple_strtoul(dev_part_str, &ep, 16);
+ if (ep != part_str) {
+ /* Not all the first part before the # was parsed. */
+ return -EINVAL;
+ }
+ part_str++;
+
+ *dev_desc = blk_get_dev(dev_iface, dev_num);
+ if (!*dev_desc) {
+ printf("Could not find %s %d\n", dev_iface, dev_num);
+ return -EINVAL;
+ }
+ if (part_get_info_by_name(*dev_desc, part_str, part_info) < 0) {
+ printf("Could not find \"%s\" partition\n", part_str);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int part_get_info_by_dev_and_name_or_num(const char *dev_iface,
+ const char *dev_part_str,
+ struct blk_desc **dev_desc,
+ disk_partition_t *part_info)
+{
+ /* Split the part_name if passed as "$dev_num#part_name". */
+ if (!part_get_info_by_dev_and_name(dev_iface, dev_part_str,
+ dev_desc, part_info))
+ return 0;
+ /*
+ * Couldn't lookup by name, try looking up the partition description
+ * directly.
+ */
+ if (blk_get_device_part_str(dev_iface, dev_part_str,
+ dev_desc, part_info, 1) < 0) {
+ printf("Couldn't find partition %s %s\n",
+ dev_iface, dev_part_str);
+ return -EINVAL;
+ }
+ return 0;
+}
+
void part_set_generic_name(const struct blk_desc *dev_desc,
int part_num, char *name)
{
diff --git a/include/part.h b/include/part.h
index ebca546db5..0b5cf3d5e8 100644
--- a/include/part.h
+++ b/include/part.h
@@ -201,6 +201,27 @@ int part_get_info_by_name_type(struct blk_desc *dev_desc, const char *name,
int part_get_info_by_name(struct blk_desc *dev_desc,
const char *name, disk_partition_t *info);
+/**
+ * Get partition info from dev number + part name, or dev number + part number.
+ *
+ * Parse a device number and partition description (either name or number)
+ * in the form of device number plus partition name separated by a "#"
+ * (like "device_num#partition_name") or a device number plus a partition number
+ * separated by a ":". For example both "0#misc" and "0:1" can be valid
+ * partition descriptions for a given interface. If the partition is found, sets
+ * dev_desc and part_info accordingly with the information of the partition.
+ *
+ * @param[in] dev_iface Device interface
+ * @param[in] dev_part_str Input partition description, like "0#misc" or "0:1"
+ * @param[out] dev_desc Place to store the device description pointer
+ * @param[out] part_info Place to store the partition information
+ * @return 0 on success, or a negative on error
+ */
+int part_get_info_by_dev_and_name_or_num(const char *dev_iface,
+ const char *dev_part_str,
+ struct blk_desc **dev_desc,
+ disk_partition_t *part_info);
+
/**
* part_set_generic_name() - create generic partition like hda1 or sdb2
*
--
2.17.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [U-Boot] [PATCH v5 2/6] common: Implement A/B metadata
2019-07-05 12:37 [U-Boot] [PATCH v5 0/6] android: implement A/B boot process Igor Opaniuk
2019-07-05 12:37 ` [U-Boot] [PATCH v5 1/6] disk: part: Extend API to get partition info Igor Opaniuk
@ 2019-07-05 12:37 ` Igor Opaniuk
2019-07-24 20:06 ` Tom Rini
2019-07-05 12:37 ` [U-Boot] [PATCH v5 3/6] cmd: Add 'ab_select' command Igor Opaniuk
` (4 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Igor Opaniuk @ 2019-07-05 12:37 UTC (permalink / raw)
To: u-boot
From: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
This patch determines the A/B-specific bootloader message structure
that is the basis for implementation of recovery and A/B update
functions. A/B metadata is stored in this structure and used to decide
which slot should we use to boot the device. Also some basic functions
for A/B metadata manipulation are implemented (like slot selection).
The patch was extracted from commits [1], [2] with some coding style
fixes.
[1] https://android-review.googlesource.com/c/platform/external/u-boot/+/729878/2
[2] https://android-review.googlesource.com/c/platform/external/u-boot/+/729880/2
Signed-off-by: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
common/Kconfig | 10 ++
common/Makefile | 1 +
common/android_ab.c | 300 +++++++++++++++++++++++++++++++++++++++++++
include/android_ab.h | 34 +++++
4 files changed, 345 insertions(+)
create mode 100644 common/android_ab.c
create mode 100644 include/android_ab.h
diff --git a/common/Kconfig b/common/Kconfig
index af66496e75..63287865ef 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -814,6 +814,16 @@ config UPDATE_TFTP_MSEC_MAX
default 100
depends on UPDATE_TFTP
+config ANDROID_AB
+ bool "Android A/B updates"
+ default n
+ help
+ If enabled, adds support for the new Android A/B update model. This
+ allows the bootloader to select which slot to boot from based on the
+ information provided by userspace via the Android boot_ctrl HAL. This
+ allows a bootloader to try a new version of the system but roll back
+ to previous version if the new one didn't boot all the way.
+
endmenu
menu "Blob list"
diff --git a/common/Makefile b/common/Makefile
index c7e41ef307..302d8beaf3 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -107,6 +107,7 @@ endif
endif
obj-y += image.o
+obj-$(CONFIG_ANDROID_AB) += android_ab.o
obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o
obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o
obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o
diff --git a/common/android_ab.c b/common/android_ab.c
new file mode 100644
index 0000000000..05ffc6f4e5
--- /dev/null
+++ b/common/android_ab.c
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ */
+#include <common.h>
+#include <android_ab.h>
+#include <android_bootloader_message.h>
+#include <linux/err.h>
+#include <memalign.h>
+#include <u-boot/crc.h>
+
+/**
+ * Compute the CRC-32 of the bootloader control struct.
+ *
+ * Only the bytes up to the crc32_le field are considered for the CRC-32
+ * calculation.
+ *
+ * @param[in] abc bootloader control block
+ *
+ * @return crc32 sum
+ */
+static uint32_t ab_control_compute_crc(struct bootloader_control *abc)
+{
+ return crc32(0, (void *)abc, offsetof(typeof(*abc), crc32_le));
+}
+
+/**
+ * Initialize bootloader_control to the default value.
+ *
+ * It allows us to boot all slots in order from the first one. This value
+ * should be used when the bootloader message is corrupted, but not when
+ * a valid message indicates that all slots are unbootable.
+ *
+ * @param[in] abc bootloader control block
+ *
+ * @return 0 on success and a negative on error
+ */
+static int ab_control_default(struct bootloader_control *abc)
+{
+ int i;
+ const struct slot_metadata metadata = {
+ .priority = 15,
+ .tries_remaining = 7,
+ .successful_boot = 0,
+ .verity_corrupted = 0,
+ .reserved = 0
+ };
+
+ if (!abc)
+ return -EFAULT;
+
+ memcpy(abc->slot_suffix, "a\0\0\0", 4);
+ abc->magic = BOOT_CTRL_MAGIC;
+ abc->version = BOOT_CTRL_VERSION;
+ abc->nb_slot = NUM_SLOTS;
+ memset(abc->reserved0, 0, sizeof(abc->reserved0));
+ for (i = 0; i < abc->nb_slot; ++i)
+ abc->slot_info[i] = metadata;
+
+ memset(abc->reserved1, 0, sizeof(abc->reserved1));
+ abc->crc32_le = ab_control_compute_crc(abc);
+
+ return 0;
+}
+
+/**
+ * Load the boot_control struct from disk into newly allocated memory.
+ *
+ * This function allocates and returns an integer number of disk blocks,
+ * based on the block size of the passed device to help performing a
+ * read-modify-write operation on the boot_control struct.
+ * The boot_control struct offset (2 KiB) must be a multiple of the device
+ * block size, for simplicity.
+ *
+ * @param[in] dev_desc Device where to read the boot_control struct from
+ * @param[in] part_info Partition in 'dev_desc' where to read from, normally
+ * the "misc" partition should be used
+ * @param[out] pointer to pointer to bootloader_control data
+ * @return 0 on success and a negative on error
+ */
+static int ab_control_create_from_disk(struct blk_desc *dev_desc,
+ const disk_partition_t *part_info,
+ struct bootloader_control **abc)
+{
+ ulong abc_offset, abc_blocks, ret;
+
+ abc_offset = offsetof(struct bootloader_message_ab, slot_suffix);
+ if (abc_offset % part_info->blksz) {
+ log_err("ANDROID: Boot control block not block aligned.\n");
+ return -EINVAL;
+ }
+ abc_offset /= part_info->blksz;
+
+ abc_blocks = DIV_ROUND_UP(sizeof(struct bootloader_control),
+ part_info->blksz);
+ if (abc_offset + abc_blocks > part_info->size) {
+ log_err("ANDROID: boot control partition too small. Need at");
+ log_err(" least %lu blocks but have %lu blocks.\n",
+ abc_offset + abc_blocks, part_info->size);
+ return -EINVAL;
+ }
+ *abc = malloc_cache_aligned(abc_blocks * part_info->blksz);
+ if (!*abc)
+ return -ENOMEM;
+
+ ret = blk_dread(dev_desc, part_info->start + abc_offset, abc_blocks,
+ *abc);
+ if (IS_ERR_VALUE(ret)) {
+ log_err("ANDROID: Could not read from boot ctrl partition\n");
+ free(*abc);
+ return -EIO;
+ }
+
+ log_debug("ANDROID: Loaded ABC, %lu blocks\n", abc_blocks);
+
+ return 0;
+}
+
+/**
+ * Store the loaded boot_control block.
+ *
+ * Store back to the same location it was read from with
+ * ab_control_create_from_misc().
+ *
+ * @param[in] dev_desc Device where we should write the boot_control struct
+ * @param[in] part_info Partition on the 'dev_desc' where to write
+ * @param[in] abc Pointer to the boot control struct and the extra bytes after
+ * it up to the nearest block boundary
+ * @return 0 on success and a negative on error
+ */
+static int ab_control_store(struct blk_desc *dev_desc,
+ const disk_partition_t *part_info,
+ struct bootloader_control *abc)
+{
+ ulong abc_offset, abc_blocks, ret;
+
+ abc_offset = offsetof(struct bootloader_message_ab, slot_suffix) /
+ part_info->blksz;
+ abc_blocks = DIV_ROUND_UP(sizeof(struct bootloader_control),
+ part_info->blksz);
+ ret = blk_dwrite(dev_desc, part_info->start + abc_offset, abc_blocks,
+ abc);
+ if (IS_ERR_VALUE(ret)) {
+ log_err("ANDROID: Could not write back the misc partition\n");
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * Compare two slots.
+ *
+ * The function determines slot which is should we boot from among the two.
+ *
+ * @param[in] a The first bootable slot metadata
+ * @param[in] b The second bootable slot metadata
+ * @return Negative if the slot "a" is better, positive of the slot "b" is
+ * better or 0 if they are equally good.
+ */
+static int ab_compare_slots(const struct slot_metadata *a,
+ const struct slot_metadata *b)
+{
+ /* Higher priority is better */
+ if (a->priority != b->priority)
+ return b->priority - a->priority;
+
+ /* Higher successful_boot value is better, in case of same priority */
+ if (a->successful_boot != b->successful_boot)
+ return b->successful_boot - a->successful_boot;
+
+ /* Higher tries_remaining is better to ensure round-robin */
+ if (a->tries_remaining != b->tries_remaining)
+ return b->tries_remaining - a->tries_remaining;
+
+ return 0;
+}
+
+int ab_select_slot(struct blk_desc *dev_desc, disk_partition_t *part_info)
+{
+ struct bootloader_control *abc = NULL;
+ u32 crc32_le;
+ int slot, i, ret;
+ bool store_needed = false;
+ char slot_suffix[4];
+
+ ret = ab_control_create_from_disk(dev_desc, part_info, &abc);
+ if (ret < 0) {
+ /*
+ * This condition represents an actual problem with the code or
+ * the board setup, like an invalid partition information.
+ * Signal a repair mode and do not try to boot from either slot.
+ */
+ return ret;
+ }
+
+ crc32_le = ab_control_compute_crc(abc);
+ if (abc->crc32_le != crc32_le) {
+ log_err("ANDROID: Invalid CRC-32 (expected %.8x, found %.8x),",
+ crc32_le, abc->crc32_le);
+ log_err("re-initializing A/B metadata.\n");
+
+ ret = ab_control_default(abc);
+ if (ret < 0) {
+ free(abc);
+ return -ENODATA;
+ }
+ store_needed = true;
+ }
+
+ if (abc->magic != BOOT_CTRL_MAGIC) {
+ log_err("ANDROID: Unknown A/B metadata: %.8x\n", abc->magic);
+ free(abc);
+ return -ENODATA;
+ }
+
+ if (abc->version > BOOT_CTRL_VERSION) {
+ log_err("ANDROID: Unsupported A/B metadata version: %.8x\n",
+ abc->version);
+ free(abc);
+ return -ENODATA;
+ }
+
+ /*
+ * At this point a valid boot control metadata is stored in abc,
+ * followed by other reserved data in the same block. We select a with
+ * the higher priority slot that
+ * - is not marked as corrupted and
+ * - either has tries_remaining > 0 or successful_boot is true.
+ * If the selected slot has a false successful_boot, we also decrement
+ * the tries_remaining until it eventually becomes unbootable because
+ * tries_remaining reaches 0. This mechanism produces a bootloader
+ * induced rollback, typically right after a failed update.
+ */
+
+ /* Safety check: limit the number of slots. */
+ if (abc->nb_slot > ARRAY_SIZE(abc->slot_info)) {
+ abc->nb_slot = ARRAY_SIZE(abc->slot_info);
+ store_needed = true;
+ }
+
+ slot = -1;
+ for (i = 0; i < abc->nb_slot; ++i) {
+ if (abc->slot_info[i].verity_corrupted ||
+ !abc->slot_info[i].tries_remaining) {
+ log_debug("ANDROID: unbootable slot %d tries: %d, ",
+ i, abc->slot_info[i].tries_remaining);
+ log_debug("corrupt: %d\n",
+ abc->slot_info[i].verity_corrupted);
+ continue;
+ }
+ log_debug("ANDROID: bootable slot %d pri: %d, tries: %d, ",
+ i, abc->slot_info[i].priority,
+ abc->slot_info[i].tries_remaining);
+ log_debug("corrupt: %d, successful: %d\n",
+ abc->slot_info[i].verity_corrupted,
+ abc->slot_info[i].successful_boot);
+
+ if (slot < 0 ||
+ ab_compare_slots(&abc->slot_info[i],
+ &abc->slot_info[slot]) < 0) {
+ slot = i;
+ }
+ }
+
+ if (slot >= 0 && !abc->slot_info[slot].successful_boot) {
+ log_err("ANDROID: Attempting slot %c, tries remaining %d\n",
+ BOOT_SLOT_NAME(slot),
+ abc->slot_info[slot].tries_remaining);
+ abc->slot_info[slot].tries_remaining--;
+ store_needed = true;
+ }
+
+ if (slot >= 0) {
+ /*
+ * Legacy user-space requires this field to be set in the BCB.
+ * Newer releases load this slot suffix from the command line
+ * or the device tree.
+ */
+ memset(slot_suffix, 0, sizeof(slot_suffix));
+ slot_suffix[0] = BOOT_SLOT_NAME(slot);
+ if (memcmp(abc->slot_suffix, slot_suffix,
+ sizeof(slot_suffix))) {
+ memcpy(abc->slot_suffix, slot_suffix,
+ sizeof(slot_suffix));
+ store_needed = true;
+ }
+ }
+
+ if (store_needed) {
+ abc->crc32_le = ab_control_compute_crc(abc);
+ ab_control_store(dev_desc, part_info, abc);
+ }
+ free(abc);
+
+ if (slot < 0)
+ return -EINVAL;
+
+ return slot;
+}
diff --git a/include/android_ab.h b/include/android_ab.h
new file mode 100644
index 0000000000..810906d22b
--- /dev/null
+++ b/include/android_ab.h
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ */
+
+#ifndef __ANDROID_AB_H
+#define __ANDROID_AB_H
+
+#include <common.h>
+
+/* Android standard boot slot names are 'a', 'b', 'c', ... */
+#define BOOT_SLOT_NAME(slot_num) ('a' + (slot_num))
+
+/* Number of slots */
+#define NUM_SLOTS 2
+
+/**
+ * Select the slot where to boot from.
+ *
+ * On Android devices with more than one boot slot (multiple copies of the
+ * kernel and system images) selects which slot should be used to boot from and
+ * registers the boot attempt. This is used in by the new A/B update model where
+ * one slot is updated in the background while running from the other slot. If
+ * the selected slot did not successfully boot in the past, a boot attempt is
+ * registered before returning from this function so it isn't selected
+ * indefinitely.
+ *
+ * @param[in] dev_desc Place to store the device description pointer
+ * @param[in] part_info Place to store the partition information
+ * @return The slot number (>= 0) on success, or a negative on error
+ */
+int ab_select_slot(struct blk_desc *dev_desc, disk_partition_t *part_info);
+
+#endif /* __ANDROID_AB_H */
--
2.17.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [U-Boot] [PATCH v5 3/6] cmd: Add 'ab_select' command
2019-07-05 12:37 [U-Boot] [PATCH v5 0/6] android: implement A/B boot process Igor Opaniuk
2019-07-05 12:37 ` [U-Boot] [PATCH v5 1/6] disk: part: Extend API to get partition info Igor Opaniuk
2019-07-05 12:37 ` [U-Boot] [PATCH v5 2/6] common: Implement A/B metadata Igor Opaniuk
@ 2019-07-05 12:37 ` Igor Opaniuk
2019-07-24 20:06 ` Tom Rini
2019-07-05 12:37 ` [U-Boot] [PATCH v5 4/6] test/py: Add base test case for A/B updates Igor Opaniuk
` (3 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Igor Opaniuk @ 2019-07-05 12:37 UTC (permalink / raw)
To: u-boot
From: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
For A/B system update support the Android boot process requires to send
'androidboot.slot_suffix' parameter as a command line argument. This
patch implementes 'ab_select' command which allows us to obtain current
slot by processing the A/B metadata.
The patch was extracted from commit [1] with one modification: the
separator for specifying the name of metadata partition was changed
from ';' to '#', because ';' is used for commands separation.
[1] https://android-review.googlesource.com/c/platform/external/u-boot/+/729880/2
Signed-off-by: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Reviewed-by: Alistair Strachan <astrachan@google.com>
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
cmd/Kconfig | 15 ++++++++++++++
cmd/Makefile | 1 +
cmd/ab_select.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+)
create mode 100644 cmd/ab_select.c
diff --git a/cmd/Kconfig b/cmd/Kconfig
index 3afb760a81..380edd0136 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -1179,6 +1179,21 @@ config CMD_SETEXPR
endmenu
+menu "Android support commands"
+
+config CMD_AB_SELECT
+ bool "ab_select"
+ default n
+ depends on ANDROID_AB
+ help
+ On Android devices with more than one boot slot (multiple copies of
+ the kernel and system images) this provides a command to select which
+ slot should be used to boot from and register the boot attempt. This
+ is used by the new A/B update model where one slot is updated in the
+ background while running from the other slot.
+
+endmenu
+
if NET
menuconfig CMD_NET
diff --git a/cmd/Makefile b/cmd/Makefile
index 49e64cde1d..500147a2ac 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -12,6 +12,7 @@ obj-y += version.o
# command
obj-$(CONFIG_CMD_AES) += aes.o
+obj-$(CONFIG_CMD_AB_SELECT) += ab_select.o
obj-$(CONFIG_CMD_ADC) += adc.o
obj-$(CONFIG_CMD_ARMFLASH) += armflash.o
obj-y += blk_common.o
diff --git a/cmd/ab_select.c b/cmd/ab_select.c
new file mode 100644
index 0000000000..7c8f2ee8eb
--- /dev/null
+++ b/cmd/ab_select.c
@@ -0,0 +1,52 @@
+// SPDX-License-Identifier: BSD-2-Clause
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ */
+
+#include <android_ab.h>
+#include <command.h>
+
+static int do_ab_select(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ int ret;
+ struct blk_desc *dev_desc;
+ disk_partition_t part_info;
+ char slot[2];
+
+ if (argc != 4)
+ return CMD_RET_USAGE;
+
+ /* Lookup the "misc" partition from argv[2] and argv[3] */
+ if (part_get_info_by_dev_and_name_or_num(argv[2], argv[3],
+ &dev_desc, &part_info) < 0) {
+ return CMD_RET_FAILURE;
+ }
+
+ ret = ab_select_slot(dev_desc, &part_info);
+ if (ret < 0) {
+ printf("Android boot failed, error %d.\n", ret);
+ return CMD_RET_FAILURE;
+ }
+
+ /* Android standard slot names are 'a', 'b', ... */
+ slot[0] = BOOT_SLOT_NAME(ret);
+ slot[1] = '\0';
+ env_set(argv[1], slot);
+ printf("ANDROID: Booting slot: %s\n", slot);
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(ab_select, 4, 0, do_ab_select,
+ "Select the slot used to boot from and register the boot attempt.",
+ "<slot_var_name> <interface> <dev[:part|#part_name]>\n"
+ " - Load the slot metadata from the partition 'part' on\n"
+ " device type 'interface' instance 'dev' and store the active\n"
+ " slot in the 'slot_var_name' variable. This also updates the\n"
+ " Android slot metadata with a boot attempt, which can cause\n"
+ " successive calls to this function to return a different result\n"
+ " if the returned slot runs out of boot attempts.\n"
+ " - If 'part_name' is passed, preceded with a # instead of :, the\n"
+ " partition name whose label is 'part_name' will be looked up in\n"
+ " the partition table. This is commonly the \"misc\" partition.\n"
+);
--
2.17.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [U-Boot] [PATCH v5 4/6] test/py: Add base test case for A/B updates
2019-07-05 12:37 [U-Boot] [PATCH v5 0/6] android: implement A/B boot process Igor Opaniuk
` (2 preceding siblings ...)
2019-07-05 12:37 ` [U-Boot] [PATCH v5 3/6] cmd: Add 'ab_select' command Igor Opaniuk
@ 2019-07-05 12:37 ` Igor Opaniuk
2019-07-24 20:06 ` Tom Rini
2019-07-05 12:37 ` [U-Boot] [PATCH v5 5/6] doc: android: Add simple guide " Igor Opaniuk
` (2 subsequent siblings)
6 siblings, 1 reply; 17+ messages in thread
From: Igor Opaniuk @ 2019-07-05 12:37 UTC (permalink / raw)
To: u-boot
From: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Add sandbox test for 'ab_select' command.
Test: ./test/py/test.py --bd sandbox --build -k test_ab
Signed-off-by: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Alistair Strachan <astrachan@google.com>
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
configs/sandbox_defconfig | 2 +
test/py/tests/test_android/test_ab.py | 75 +++++++++++++++++++++++++++
2 files changed, 77 insertions(+)
create mode 100644 test/py/tests/test_android/test_ab.py
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 6894262b89..fd51a75b01 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -20,6 +20,7 @@ CONFIG_PRE_CON_BUF_ADDR=0xf0000
CONFIG_LOG_MAX_LEVEL=6
CONFIG_LOG_ERROR_RETURN=y
CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_ANDROID_AB=y
CONFIG_CMD_CPU=y
CONFIG_CMD_LICENSE=y
CONFIG_CMD_BOOTZ=y
@@ -47,6 +48,7 @@ CONFIG_CMD_REMOTEPROC=y
CONFIG_CMD_SPI=y
CONFIG_CMD_USB=y
CONFIG_CMD_AXI=y
+CONFIG_CMD_AB_SELECT=y
CONFIG_CMD_TFTPPUT=y
CONFIG_CMD_TFTPSRV=y
CONFIG_CMD_RARP=y
diff --git a/test/py/tests/test_android/test_ab.py b/test/py/tests/test_android/test_ab.py
new file mode 100644
index 0000000000..c79cb07fda
--- /dev/null
+++ b/test/py/tests/test_android/test_ab.py
@@ -0,0 +1,75 @@
+# SPDX-License-Identifier: GPL-2.0
+# (C) Copyright 2018 Texas Instruments, <www.ti.com>
+
+# Test A/B update commands.
+
+import os
+import pytest
+import u_boot_utils
+
+class ABTestDiskImage(object):
+ """Disk Image used by the A/B tests."""
+
+ def __init__(self, u_boot_console):
+ """Initialize a new ABTestDiskImage object.
+
+ Args:
+ u_boot_console: A U-Boot console.
+
+ Returns:
+ Nothing.
+ """
+
+ filename = 'test_ab_disk_image.bin'
+
+ persistent = u_boot_console.config.persistent_data_dir + '/' + filename
+ self.path = u_boot_console.config.result_dir + '/' + filename
+
+ with u_boot_utils.persistent_file_helper(u_boot_console.log, persistent):
+ if os.path.exists(persistent):
+ u_boot_console.log.action('Disk image file ' + persistent +
+ ' already exists')
+ else:
+ u_boot_console.log.action('Generating ' + persistent)
+ fd = os.open(persistent, os.O_RDWR | os.O_CREAT)
+ os.ftruncate(fd, 524288)
+ os.close(fd)
+ cmd = ('sgdisk', persistent)
+ u_boot_utils.run_and_log(u_boot_console, cmd)
+
+ cmd = ('sgdisk', '--new=1:64:512', '--change-name=1:misc',
+ persistent)
+ u_boot_utils.run_and_log(u_boot_console, cmd)
+ cmd = ('sgdisk', '--load-backup=' + persistent)
+ u_boot_utils.run_and_log(u_boot_console, cmd)
+
+ cmd = ('cp', persistent, self.path)
+ u_boot_utils.run_and_log(u_boot_console, cmd)
+
+di = None
+ at pytest.fixture(scope='function')
+def ab_disk_image(u_boot_console):
+ global di
+ if not di:
+ di = ABTestDiskImage(u_boot_console)
+ return di
+
+ at pytest.mark.boardspec('sandbox')
+ at pytest.mark.buildconfigspec('android_ab')
+ at pytest.mark.buildconfigspec('cmd_ab_select')
+ at pytest.mark.requiredtool('sgdisk')
+def test_ab(ab_disk_image, u_boot_console):
+ """Test the 'ab_select' command."""
+
+ u_boot_console.run_command('host bind 0 ' + ab_disk_image.path)
+
+ output = u_boot_console.run_command('ab_select slot_name host 0#misc')
+ assert 're-initializing A/B metadata' in output
+ assert 'Attempting slot a, tries remaining 7' in output
+ output = u_boot_console.run_command('printenv slot_name')
+ assert 'slot_name=a' in output
+
+ output = u_boot_console.run_command('ab_select slot_name host 0:1')
+ assert 'Attempting slot b, tries remaining 7' in output
+ output = u_boot_console.run_command('printenv slot_name')
+ assert 'slot_name=b' in output
--
2.17.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [U-Boot] [PATCH v5 5/6] doc: android: Add simple guide for A/B updates
2019-07-05 12:37 [U-Boot] [PATCH v5 0/6] android: implement A/B boot process Igor Opaniuk
` (3 preceding siblings ...)
2019-07-05 12:37 ` [U-Boot] [PATCH v5 4/6] test/py: Add base test case for A/B updates Igor Opaniuk
@ 2019-07-05 12:37 ` Igor Opaniuk
2019-07-24 20:06 ` Tom Rini
2019-07-05 12:37 ` [U-Boot] [PATCH v5 6/6] env: am57xx: Implement A/B boot process Igor Opaniuk
2019-07-12 9:48 ` [U-Boot] [PATCH v5 0/6] android: implement " Igor Opaniuk
6 siblings, 1 reply; 17+ messages in thread
From: Igor Opaniuk @ 2019-07-05 12:37 UTC (permalink / raw)
To: u-boot
From: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Add a short documentation for A/B enablement and 'ab_select' command
usage.
Signed-off-by: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Alistair Strachan <astrachan@google.com>
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
doc/android/ab.txt | 67 ++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 doc/android/ab.txt
diff --git a/doc/android/ab.txt b/doc/android/ab.txt
new file mode 100644
index 0000000000..9f37ed5c58
--- /dev/null
+++ b/doc/android/ab.txt
@@ -0,0 +1,67 @@
+Android A/B updates
+===================
+
+Overview
+--------
+
+A/B system updates ensures modern approach for system update. This feature
+allows one to use two sets (or more) of partitions referred to as slots
+(normally slot A and slot B). The system runs from the current slot while the
+partitions in the unused slot can be updated [1].
+
+A/B enablement
+--------------
+
+The A/B updates support can be activated by specifying next options in
+your board configuration file:
+
+ CONFIG_ANDROID_AB=y
+ CONFIG_CMD_AB_SELECT=y
+
+The disk space on target device must be partitioned in a way so that each
+partition which needs to be updated has two or more instances. The name of
+each instance must be formed by adding suffixes: _a, _b, _c, etc.
+For example: boot_a, boot_b, system_a, system_b, vendor_a, vendor_b.
+
+As a result you can use 'ab_select' command to ensure A/B boot process in your
+boot script. This command analyzes and processes A/B metadata stored on a
+special partition (e.g. "misc") and determines which slot should be used for
+booting up.
+
+Command usage
+-------------
+
+ ab_select <slot_var_name> <interface> <dev[:part_number|#part_name]>
+
+for example:
+
+ => ab_select slot_name mmc 1:4
+
+or
+
+ => ab_select slot_name mmc 1#misc
+
+Result:
+
+ => printenv slot_name
+ slot_name=a
+
+Based on this slot information, the current boot partition should be defined,
+and next kernel command line parameters should be generated:
+
+ - androidboot.slot_suffix=
+ - root=
+
+For example:
+
+ androidboot.slot_suffix=_a root=/dev/mmcblk1p12
+
+A/B metadata is organized according to AOSP reference [2]. On the first system
+start with A/B enabled, when 'misc' partition doesn't contain required data,
+the default A/B metadata will be created and written to 'misc' partition.
+
+References
+----------
+
+[1] https://source.android.com/devices/tech/ota/ab
+[2] bootable/recovery/bootloader_message/include/bootloader_message/bootloader_message.h
--
2.17.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [U-Boot] [PATCH v5 6/6] env: am57xx: Implement A/B boot process
2019-07-05 12:37 [U-Boot] [PATCH v5 0/6] android: implement A/B boot process Igor Opaniuk
` (4 preceding siblings ...)
2019-07-05 12:37 ` [U-Boot] [PATCH v5 5/6] doc: android: Add simple guide " Igor Opaniuk
@ 2019-07-05 12:37 ` Igor Opaniuk
2019-07-05 18:51 ` Eugeniu Rosca
2019-07-24 20:06 ` Tom Rini
2019-07-12 9:48 ` [U-Boot] [PATCH v5 0/6] android: implement " Igor Opaniuk
6 siblings, 2 replies; 17+ messages in thread
From: Igor Opaniuk @ 2019-07-05 12:37 UTC (permalink / raw)
To: u-boot
From: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Add support for A/B boot process on AM57xx based boards:
1. Define 'slot_suffix' variable (using 'ab_select' command)
2. Extend 'emmc_android_boot' boot command (add commands for A/B boot
process)
'ab_select' command is used to decide which slot should be used for
booting up. A/B metadata resides in 'misc' partition.
To activate the A/B boot process, the following config options must be
set:
CONFIG_ANDROID_AB=y
CONFIG_CMD_AB_SELECT=y
For successful A/B boot, the corresponding A/B infrastructure must be
involved on Android side [1] (including mounting system as root), and
disk must be partitioned accordingly.
When A/B boot is enabled, there are some known limitations currently
exist (not related to A/B patches, need to be implemented later):
1. The 'Verified Boot' sequence is not supported
2. dev path to system partition (system_a or system_b) is passed via
'bootargs' as 'root=' argument like 'root=/dev/mmcblk1p12', but
further we'll need to rework it with respect to dm-verity
requirements [2]
In case when A/B partitions are not present in system (and A/B boot is
enabled), boot up process will be terminated and next message will be
shown:
"boot_a(b) partition not found"
[1] https://source.android.com/devices/tech/ota/ab
[2] https://source.android.com/devices/tech/ota/ab/ab_implement#kernel
Signed-off-by: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Alistair Strachan <astrachan@google.com>
Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
include/environment/ti/boot.h | 58 +++++++++++++++++++++++++++++++----
1 file changed, 52 insertions(+), 6 deletions(-)
diff --git a/include/environment/ti/boot.h b/include/environment/ti/boot.h
index 943adcad40..db6e7513c0 100644
--- a/include/environment/ti/boot.h
+++ b/include/environment/ti/boot.h
@@ -23,6 +23,18 @@
#define VBMETA_PART ""
#endif
+#if defined(CONFIG_CMD_AB_SELECT)
+#define COMMON_PARTS \
+ "name=boot_a,size=20M,uuid=${uuid_gpt_boot_a};" \
+ "name=boot_b,size=20M,uuid=${uuid_gpt_boot_b};" \
+ "name=system_a,size=1024M,uuid=${uuid_gpt_system_a};" \
+ "name=system_b,size=1024M,uuid=${uuid_gpt_system_b};"
+#else
+#define COMMON_PARTS \
+ "name=boot,size=20M,uuid=${uuid_gpt_boot};" \
+ "name=system,size=1024M,uuid=${uuid_gpt_system};"
+#endif
+
#ifndef PARTS_DEFAULT
/* Define the default GPT table for eMMC */
#define PARTS_DEFAULT \
@@ -38,8 +50,7 @@
"name=uboot-env,start=2432K,size=256K,uuid=${uuid_gpt_reserved};" \
"name=misc,size=128K,uuid=${uuid_gpt_misc};" \
"name=recovery,size=40M,uuid=${uuid_gpt_recovery};" \
- "name=boot,size=20M,uuid=${uuid_gpt_boot};" \
- "name=system,size=1024M,uuid=${uuid_gpt_system};" \
+ COMMON_PARTS \
"name=vendor,size=256M,uuid=${uuid_gpt_vendor};" \
VBMETA_PART \
"name=userdata,size=-,uuid=${uuid_gpt_userdata}"
@@ -58,6 +69,35 @@
#define AVB_VERIFY_CMD ""
#endif
+#define CONTROL_PARTITION "misc"
+
+#if defined(CONFIG_CMD_AB_SELECT)
+#define AB_SELECT \
+ "if part number mmc 1 " CONTROL_PARTITION " control_part_number; " \
+ "then " \
+ "echo " CONTROL_PARTITION \
+ " partition number:${control_part_number};" \
+ "ab_select slot_name mmc ${mmcdev}:${control_part_number};" \
+ "else " \
+ "echo " CONTROL_PARTITION " partition not found;" \
+ "exit;" \
+ "fi;" \
+ "setenv slot_suffix _${slot_name};" \
+ "if part number mmc ${mmcdev} system${slot_suffix} " \
+ "system_part_number; then " \
+ "setenv bootargs_ab " \
+ "ro root=/dev/mmcblk${mmcdev}p${system_part_number} " \
+ "rootwait init=/init skip_initramfs " \
+ "androidboot.slot_suffix=${slot_suffix};" \
+ "echo A/B cmdline addition: ${bootargs_ab};" \
+ "setenv bootargs ${bootargs} ${bootargs_ab};" \
+ "else " \
+ "echo system${slot_suffix} partition not found;" \
+ "fi;"
+#else
+#define AB_SELECT ""
+#endif
+
#define DEFAULT_COMMON_BOOT_TI_ARGS \
"console=" CONSOLEDEV ",115200n8\0" \
"fdtfile=undefined\0" \
@@ -86,10 +126,16 @@
"mmc dev $mmcdev; " \
"mmc rescan; " \
AVB_VERIFY_CHECK \
- "part start mmc ${mmcdev} boot boot_start; " \
- "part size mmc ${mmcdev} boot boot_size; " \
- "mmc read ${loadaddr} ${boot_start} ${boot_size}; " \
- "bootm ${loadaddr}#${fdtfile};\0 "
+ AB_SELECT \
+ "if part start mmc ${mmcdev} boot${slot_suffix} boot_start; " \
+ "then " \
+ "part size mmc ${mmcdev} boot${slot_suffix} " \
+ "boot_size; " \
+ "mmc read ${loadaddr} ${boot_start} ${boot_size}; " \
+ "bootm ${loadaddr}#${fdtfile}; " \
+ "else " \
+ "echo boot${slot_suffix} partition not found; " \
+ "fi;\0"
#ifdef CONFIG_OMAP54XX
--
2.17.1
^ permalink raw reply related [flat|nested] 17+ messages in thread* [U-Boot] [PATCH v5 6/6] env: am57xx: Implement A/B boot process
2019-07-05 12:37 ` [U-Boot] [PATCH v5 6/6] env: am57xx: Implement A/B boot process Igor Opaniuk
@ 2019-07-05 18:51 ` Eugeniu Rosca
2019-07-06 10:06 ` Sam Protsenko
2019-07-24 20:06 ` Tom Rini
1 sibling, 1 reply; 17+ messages in thread
From: Eugeniu Rosca @ 2019-07-05 18:51 UTC (permalink / raw)
To: u-boot
Hi Igor,
On Fri, Jul 05, 2019 at 03:37:36PM +0300, Igor Opaniuk wrote:
[..]
> include/environment/ti/boot.h | 58 +++++++++++++++++++++++++++++++----
[..]
> - "name=boot,size=20M,uuid=${uuid_gpt_boot};" \
FWIW this patch doesn't apply to u-boot/master due to the above line.
FWIW the size of the boot partition defined in this file has always
been equal to 10M in u-boot/master, so most likely this patch depends
on a local 10M->20M increase of the boot partition size.
--
Best Regards,
Eugeniu.
^ permalink raw reply [flat|nested] 17+ messages in thread* [U-Boot] [PATCH v5 6/6] env: am57xx: Implement A/B boot process
2019-07-05 18:51 ` Eugeniu Rosca
@ 2019-07-06 10:06 ` Sam Protsenko
2019-07-07 14:20 ` Eugeniu Rosca
0 siblings, 1 reply; 17+ messages in thread
From: Sam Protsenko @ 2019-07-06 10:06 UTC (permalink / raw)
To: u-boot
Hi Eugeniu,
On Fri, Jul 5, 2019 at 9:52 PM Eugeniu Rosca <roscaeugeniu@gmail.com> wrote:
>
> Hi Igor,
>
> On Fri, Jul 05, 2019 at 03:37:36PM +0300, Igor Opaniuk wrote:
> [..]
> > include/environment/ti/boot.h | 58 +++++++++++++++++++++++++++++++----
> [..]
> > - "name=boot,size=20M,uuid=${uuid_gpt_boot};" \
>
> FWIW this patch doesn't apply to u-boot/master due to the above line.
> FWIW the size of the boot partition defined in this file has always
> been equal to 10M in u-boot/master, so most likely this patch depends
> on a local 10M->20M increase of the boot partition size.
>
It was me who asked Igor to do so, as I suggest this patch will be
applied on top of [1], and I guess it's specified in PATCH #0. I have
an integration branch [2] which contains all Android-related patch I
want to be merged during the merge window, and A/B series is applied
on top of [1] there. There is inevitable dependency clash between
patches, so I figured it doesn't matter what the order is, we just
should keep that order somewhere, and for me it's [2], for Igor it's
PATCH #0 which mentions dependency patches for this series. Otherwise
we risk this patch to overwrite the changes I did in [1], and I'd like
to avoid it.
Not sure what is the commonly adopted mechanism for this (specifying
dependencies), but in this case I guess I will ask the custodians to
apply patches in correct order, or apply patches according to [2],
that's the best I came up with. Please tell me if you see more
standard/wise choice for this.
[1] https://patchwork.ozlabs.org/patch/1126434/
[2] https://github.com/joe-skb7/u-boot-misc/commits/android-next
> --
> Best Regards,
> Eugeniu.
^ permalink raw reply [flat|nested] 17+ messages in thread
* [U-Boot] [PATCH v5 6/6] env: am57xx: Implement A/B boot process
2019-07-05 12:37 ` [U-Boot] [PATCH v5 6/6] env: am57xx: Implement A/B boot process Igor Opaniuk
2019-07-05 18:51 ` Eugeniu Rosca
@ 2019-07-24 20:06 ` Tom Rini
1 sibling, 0 replies; 17+ messages in thread
From: Tom Rini @ 2019-07-24 20:06 UTC (permalink / raw)
To: u-boot
On Fri, Jul 05, 2019 at 03:37:36PM +0300, Igor Opaniuk wrote:
> From: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
>
> Add support for A/B boot process on AM57xx based boards:
>
> 1. Define 'slot_suffix' variable (using 'ab_select' command)
> 2. Extend 'emmc_android_boot' boot command (add commands for A/B boot
> process)
>
> 'ab_select' command is used to decide which slot should be used for
> booting up. A/B metadata resides in 'misc' partition.
>
> To activate the A/B boot process, the following config options must be
> set:
>
> CONFIG_ANDROID_AB=y
> CONFIG_CMD_AB_SELECT=y
>
> For successful A/B boot, the corresponding A/B infrastructure must be
> involved on Android side [1] (including mounting system as root), and
> disk must be partitioned accordingly.
>
> When A/B boot is enabled, there are some known limitations currently
> exist (not related to A/B patches, need to be implemented later):
>
> 1. The 'Verified Boot' sequence is not supported
> 2. dev path to system partition (system_a or system_b) is passed via
> 'bootargs' as 'root=' argument like 'root=/dev/mmcblk1p12', but
> further we'll need to rework it with respect to dm-verity
> requirements [2]
>
> In case when A/B partitions are not present in system (and A/B boot is
> enabled), boot up process will be terminated and next message will be
> shown:
>
> "boot_a(b) partition not found"
>
> [1] https://source.android.com/devices/tech/ota/ab
> [2] https://source.android.com/devices/tech/ota/ab/ab_implement#kernel
>
> Signed-off-by: Ruslan Trofymenko <ruslan.trofymenko@linaro.org>
> Signed-off-by: Igor Opaniuk <igor.opaniuk@gmail.com>
> Signed-off-by: Sam Protsenko <semen.protsenko@linaro.org>
> Reviewed-by: Alistair Strachan <astrachan@google.com>
> Reviewed-by: Sam Protsenko <semen.protsenko@linaro.org>
> Reviewed-by: Simon Glass <sjg@chromium.org>
Applied to u-boot/master, thanks!
--
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20190724/ec4aa684/attachment-0001.sig>
^ permalink raw reply [flat|nested] 17+ messages in thread
* [U-Boot] [PATCH v5 0/6] android: implement A/B boot process
2019-07-05 12:37 [U-Boot] [PATCH v5 0/6] android: implement A/B boot process Igor Opaniuk
` (5 preceding siblings ...)
2019-07-05 12:37 ` [U-Boot] [PATCH v5 6/6] env: am57xx: Implement A/B boot process Igor Opaniuk
@ 2019-07-12 9:48 ` Igor Opaniuk
6 siblings, 0 replies; 17+ messages in thread
From: Igor Opaniuk @ 2019-07-12 9:48 UTC (permalink / raw)
To: u-boot
On Fri, Jul 5, 2019 at 3:37 PM Igor Opaniuk <igor.opaniuk@gmail.com> wrote:
>
> *** This patch series depends on [4], [5], [6] and should be
> applied after these paticular patches.
>
> This patch series adds support for Android A/B boot process [1].
> Main steps of A/B boot process are:
> - A/B metadata integrity check
> - looking for the current slot (where the system should be
> booting from)
> - getting the name of the current boot partition (boot_a or boot_b)
> and loading the corresponding Android boot image
> - getting the name of the current system partition (system_a or
> system_b) and passing of its full name via kernel command line
> (like 'root=/dev/mmcblk1p11')
> - passing current slot via kernel command line (like
> 'androidboot.slot_suffix=_a') and via A/B metadata (e.g. via
> misc partition)
> - A/B metadata processing: setting the boot success flag for
> current slot, handling the retry counter, etc
>
> A/B metadata is organized according to Android reference [2] and stored
> on 'misc' partition. On the first A/B boot process, when 'misc'
> partition doesn't contain required data, default A/B metadata will be
> created and stored in 'misc' partition. In the end of the Android boot,
> 'update_verifier' and 'update_engine' services are processing the
> A/B metadata through the Boot Control HAL. To confirm the boot was
> successful using current slot, "boot success" flag must be set on
> Android side.
>
> To enable Android A/B support in U-Boot:
> 1. Set the following config options:
>
> CONFIG_ANDROID_AB=y
> CONFIG_CMD_AB_SELECT=y
>
> 2. Change the disk layout so that it has sloted boot partitions.
> E.g. instead of 'boot' and 'system' partitions there should be
> 'boot_a', 'boot_b', 'system_a' and 'system_b' partitions.
>
> To be able to actually test this patch series, the A/B features must
> be implemented and enabled in Android as well (see [1] for details).
>
> Documentation and corresponding test for A/B boot is present here. The
> last patch in this series integrates A/B boot support on AM57xx based
> boards (though it's not enabled by default). Future users of A/B boot
> feature can use it as a reference.
>
> This series is a part of previous submission [3] by Alex Deymo. It
> contains only A/B feature that was stripped out from there with some
> modifications for using with "bootm" command preferred in upstream.
>
> Changes in v5:
> * Move tests to android subdir
> * In new version of sgdisk (0.8.10.2) short options don't work. That can
> be a regression in sgdisk, but anyway let's use long options, because
> otherwise the test fails.
> * Fix boot part size (preserve the new value).
> * Move doc to proper place
> * Handle ret values properly for blk_dread()/blk_dwrite properly using
> IS_ERR_VALUE() macro
>
> Changes in v4:
> * Removed android_bl_msg.h and re-used the one, which was
> introduced by Eugeniu Rosca in [4] and [5].
> * Initially we had intention to use "bcb" command and scripting for
> providing proper boot sequence logic (slot selection, decrementing the
> counter for each slot), but found out that it's better to keep using
> a dedicated command ab_select to avoid huge amount of scripting in
> the headers in includes/config for each platform.
> * Removed ANDROID_ prefix in multiple macros.
> * Addressed comments from Simon
>
> Changes in v3:
> * Minor fixes in the ab metadata handling (added additional sanity checks).
> * As Ruslan Trofymenko left Linaro and won't address comments anymore,
> continue (added my S-b tag) upstreaming patches on my own.
>
> Changes in v2:
> * 'android_ab_select' command is renamed to 'ab_select' command and
> moved to separate 'Android support commands' menu
> * For am57xx boards slotted sections (e.g. system_a and system_b) are
> added to the default sections if CONFIG_CMD_AB_SELECT flag is
> defined
> * Returned function error codes are clarified (errno using)
> * Some types constants and files are renamed
> * Assertion condition is clarified in test case
> * 'debug' calls are changed to 'log_debug'
> * The Guide is clarified by the results of changes
>
> [1] https://source.android.com/devices/tech/ota/ab/ab_implement
> [2] bootable/recovery/bootloader_message/include/bootloader_message/bootloader_message.h
> [3] https://lists.denx.de/pipermail/u-boot/2017-April/285841.html
> [4] https://patchwork.ozlabs.org/patch/1080394/
> [5] https://patchwork.ozlabs.org/patch/1104243/
> [6] https://patchwork.ozlabs.org/patch/1116012/
>
>
> Ruslan Trofymenko (6):
> disk: part: Extend API to get partition info
> common: Implement A/B metadata
> cmd: Add 'ab_select' command
> test/py: Add base test case for A/B updates
> doc: android: Add simple guide for A/B updates
> env: am57xx: Implement A/B boot process
>
> cmd/Kconfig | 15 ++
> cmd/Makefile | 1 +
> cmd/ab_select.c | 52 +++++
> common/Kconfig | 10 +
> common/Makefile | 1 +
> common/android_ab.c | 300 ++++++++++++++++++++++++++
> configs/sandbox_defconfig | 2 +
> disk/part.c | 68 ++++++
> doc/android/ab.txt | 67 ++++++
> include/android_ab.h | 34 +++
> include/environment/ti/boot.h | 58 ++++-
> include/part.h | 21 ++
> test/py/tests/test_android/test_ab.py | 75 +++++++
> 13 files changed, 698 insertions(+), 6 deletions(-)
> create mode 100644 cmd/ab_select.c
> create mode 100644 common/android_ab.c
> create mode 100644 doc/android/ab.txt
> create mode 100644 include/android_ab.h
> create mode 100644 test/py/tests/test_android/test_ab.py
>
> --
> 2.17.1
>
FYI:
I've checked the latest master today, almost all needed dependent patches
are merged, except [1] and [2]. I've just left my R-b tag for Sam's
patch, so now
we will be ready to go with A/B patch series after these two are merged.
[1] https://patchwork.ozlabs.org/patch/1126434/
[2] https://patchwork.ozlabs.org/patch/1116012/
--
Best regards - Freundliche Grüsse - Meilleures salutations
Igor Opaniuk
mailto: igor.opaniuk at gmail.com
skype: igor.opanyuk
+380 (93) 836 40 67
http://ua.linkedin.com/in/iopaniuk
^ permalink raw reply [flat|nested] 17+ messages in thread