All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v5 0/6] android: implement A/B boot process
@ 2019-07-05 12:37 Igor Opaniuk
  2019-07-05 12:37 ` [U-Boot] [PATCH v5 1/6] disk: part: Extend API to get partition info Igor Opaniuk
                   ` (6 more replies)
  0 siblings, 7 replies; 17+ messages in thread
From: Igor Opaniuk @ 2019-07-05 12:37 UTC (permalink / raw)
  To: u-boot

*** 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

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

* [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-06 10:06     ` Sam Protsenko
@ 2019-07-07 14:20       ` Eugeniu Rosca
  0 siblings, 0 replies; 17+ messages in thread
From: Eugeniu Rosca @ 2019-07-07 14:20 UTC (permalink / raw)
  To: u-boot

Hello Sam,

On Sat, Jul 06, 2019 at 01:06:27PM +0300, Sam Protsenko wrote:
> On Fri, Jul 5, 2019 at 9:52 PM Eugeniu Rosca <roscaeugeniu@gmail.com> wrote:
[..]
> > FWIW this patch doesn't apply to u-boot/master due to the above line.
[..]
> this patch will be
> applied on top of [1], and I guess it's specified in PATCH #0.

Oops. My bad. I didn't pay enough attention to the cover letter.
Sorry for the noise.

> [1] https://patchwork.ozlabs.org/patch/1126434/

-- 
Best Regards,
Eugeniu.

^ 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

* [U-Boot] [PATCH v5 1/6] disk: part: Extend API to get partition info
  2019-07-05 12:37 ` [U-Boot] [PATCH v5 1/6] disk: part: Extend API to get partition info Igor Opaniuk
@ 2019-07-24 20:06   ` Tom Rini
  0 siblings, 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:31PM +0300, Igor Opaniuk wrote:

> 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>

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/613d2bdc/attachment.sig>

^ permalink raw reply	[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 2/6] common: Implement A/B metadata Igor Opaniuk
@ 2019-07-24 20:06   ` Tom Rini
  0 siblings, 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:32PM +0300, Igor Opaniuk wrote:

> 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>

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/47d787cb/attachment.sig>

^ permalink raw reply	[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 3/6] cmd: Add 'ab_select' command Igor Opaniuk
@ 2019-07-24 20:06   ` Tom Rini
  0 siblings, 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:33PM +0300, Igor Opaniuk wrote:

> 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>

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/b3cc6846/attachment.sig>

^ permalink raw reply	[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 4/6] test/py: Add base test case for A/B updates Igor Opaniuk
@ 2019-07-24 20:06   ` Tom Rini
  0 siblings, 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:34PM +0300, Igor Opaniuk wrote:

> 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>

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/de51923c/attachment.sig>

^ permalink raw reply	[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 5/6] doc: android: Add simple guide " Igor Opaniuk
@ 2019-07-24 20:06   ` Tom Rini
  0 siblings, 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:35PM +0300, Igor Opaniuk wrote:

> 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>

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/222d7ecc/attachment.sig>

^ 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

end of thread, other threads:[~2019-07-24 20:06 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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-24 20:06   ` Tom Rini
2019-07-05 12:37 ` [U-Boot] [PATCH v5 2/6] common: Implement A/B metadata 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
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
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
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-05 18:51   ` Eugeniu Rosca
2019-07-06 10:06     ` Sam Protsenko
2019-07-07 14:20       ` Eugeniu Rosca
2019-07-24 20:06   ` Tom Rini
2019-07-12  9:48 ` [U-Boot] [PATCH v5 0/6] android: implement " Igor Opaniuk

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.