* [PATCH 0/4] Qualcomm: expand capsule update support
@ 2025-03-26 17:40 Caleb Connolly
2025-03-26 17:40 ` [PATCH 1/4] mach-snapdragon: track boot source Caleb Connolly
` (4 more replies)
0 siblings, 5 replies; 16+ messages in thread
From: Caleb Connolly @ 2025-03-26 17:40 UTC (permalink / raw)
To: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Caleb Connolly,
Neil Armstrong, Sumit Garg
Cc: u-boot, u-boot-qcom
The initial capsule update support only worked on the RB3 Gen 2 and made
a lot of assumptions specific to that board.
Implement the logic necessary to update U-Boot no matter where it was
flashed to, independent of any particular board.
First, we keep track of how U-Boot was loaded, specifically if we had a
valid external FDT (even if we didn't use it) this indicates that we
were booted via the Android bootloader, in this case the target for
capsule updates is the boot partition. Otherwise, we target the uefi
partition (if it exists) or the xbl partition. We handle A/B support for
all 3 (currently we always flash to the currently active partition with
a minor exception for the uefi partition).
We introduce two new fw_name strings to differentiate the GUIDs based on
the target partition, this means one board can support multiple boot
methods with capsule update support for all of them (typically this
would be chainloading OR flashing U-Boot to XBL).
Lastly, the call to scsi_scan() in dfu_scsi.c is removed. Since
scsi_scan() unbinds all scsi devices it breaks device handles maintained
in the EFI layer for the duration of the capsule update process and
causes the EFI filesystem access to delete the capsule file after the
update to fail.
Boards should instead be responsible for calling scsi_scan() before
initiating DFU.
---
Caleb Connolly (4):
mach-snapdragon: track boot source
mach-snapdragon: CapsuleUpdate: support all boot methods
dfu: scsi: don't call scsi_scan()
qcom_defconfig: enable capsule update support
arch/arm/mach-snapdragon/board.c | 25 +++
arch/arm/mach-snapdragon/capsule_update.c | 256 +++++++++++++++++++++++-------
arch/arm/mach-snapdragon/qcom-priv.h | 14 ++
configs/qcm6490_defconfig | 6 -
configs/qcom_defconfig | 3 +
drivers/dfu/dfu_scsi.c | 5 -
6 files changed, 245 insertions(+), 64 deletions(-)
---
base-commit: 68ac813c70d991ec518d0fd815efdb10a05958c0
Caleb Connolly <caleb.connolly@linaro.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/4] mach-snapdragon: track boot source
2025-03-26 17:40 [PATCH 0/4] Qualcomm: expand capsule update support Caleb Connolly
@ 2025-03-26 17:40 ` Caleb Connolly
2025-03-31 13:52 ` Neil Armstrong
2025-03-26 17:40 ` [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods Caleb Connolly
` (3 subsequent siblings)
4 siblings, 1 reply; 16+ messages in thread
From: Caleb Connolly @ 2025-03-26 17:40 UTC (permalink / raw)
To: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Caleb Connolly,
Neil Armstrong, Sumit Garg
Cc: u-boot, u-boot-qcom
Keep track of whether we were loaded via ABL or if U-Boot is running as
a first-stage bootloader.
For now we set this based on if we have a valid external FDT or not,
since it isn't possible to chainload U-Boot from ABL without there being
an external FDT.
This will be used to inform the capsule update logic which partition
U-Boot is flashed to.
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
---
arch/arm/mach-snapdragon/board.c | 25 +++++++++++++++++++++++++
arch/arm/mach-snapdragon/qcom-priv.h | 14 ++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index deae4d323789eab75d5fe735159b4cd820c02c45..245a963f5321bda3030d3809e1b108f280b3c2b5 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -36,8 +36,10 @@
#include "qcom-priv.h"
DECLARE_GLOBAL_DATA_PTR;
+enum qcom_boot_source qcom_boot_source __section(".data") = 0;
+
static struct mm_region rbx_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { { 0 } };
struct mm_region *mem_map = rbx_mem_map;
@@ -237,8 +239,14 @@ int board_fdt_blob_setup(void **fdtp)
if (ret < 0)
panic("No valid memory ranges found!\n");
+ /* If we have an external FDT, it can only have come from the Android bootloader. */
+ if (external_valid)
+ qcom_boot_source = QCOM_BOOT_SOURCE_ANDROID;
+ else
+ qcom_boot_source = QCOM_BOOT_SOURCE_XBL;
+
debug("ram_base = %#011lx, ram_size = %#011llx\n",
gd->ram_base, gd->ram_size);
if (internal_valid) {
@@ -472,8 +480,24 @@ static void configure_env(void)
qcom_set_serialno();
}
+void qcom_show_boot_source(void)
+{
+ const char *name = "UNKNOWN";
+
+ switch (qcom_boot_source) {
+ case QCOM_BOOT_SOURCE_ANDROID:
+ name = "ABL";
+ break;
+ case QCOM_BOOT_SOURCE_XBL:
+ name = "XBL";
+ break;
+ }
+
+ log_info("U-Boot loaded from %s\n", name);
+}
+
void __weak qcom_late_init(void)
{
}
@@ -515,8 +539,9 @@ int board_late_init(void)
configure_env();
qcom_late_init();
+ qcom_show_boot_source();
/* Configure the dfu_string for capsule updates */
qcom_configure_capsule_updates();
return 0;
diff --git a/arch/arm/mach-snapdragon/qcom-priv.h b/arch/arm/mach-snapdragon/qcom-priv.h
index 74d39197b89f4e769299b06214c26ee829ecdce0..e5eb4cfbc2b752de799b1407ede69683c81474c1 100644
--- a/arch/arm/mach-snapdragon/qcom-priv.h
+++ b/arch/arm/mach-snapdragon/qcom-priv.h
@@ -2,8 +2,22 @@
#ifndef __QCOM_PRIV_H__
#define __QCOM_PRIV_H__
+/**
+ * enum qcom_boot_source - Track where we got loaded from.
+ * Used for capsule update logic.
+ *
+ * @QCOM_BOOT_SOURCE_ANDROID: chainloaded (typically from ABL)
+ * @QCOM_BOOT_SOURCE_XBL: flashed to the XBL or UEFI partition
+ */
+enum qcom_boot_source {
+ QCOM_BOOT_SOURCE_ANDROID = 1,
+ QCOM_BOOT_SOURCE_XBL,
+};
+
+extern enum qcom_boot_source qcom_boot_source;
+
#if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
void qcom_configure_capsule_updates(void);
#else
void qcom_configure_capsule_updates(void) {}
--
2.49.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods
2025-03-26 17:40 [PATCH 0/4] Qualcomm: expand capsule update support Caleb Connolly
2025-03-26 17:40 ` [PATCH 1/4] mach-snapdragon: track boot source Caleb Connolly
@ 2025-03-26 17:40 ` Caleb Connolly
2025-04-01 8:45 ` Neil Armstrong
2025-04-01 12:42 ` Ilias Apalodimas
2025-03-26 17:40 ` [PATCH 3/4] dfu: scsi: don't call scsi_scan() Caleb Connolly
` (2 subsequent siblings)
4 siblings, 2 replies; 16+ messages in thread
From: Caleb Connolly @ 2025-03-26 17:40 UTC (permalink / raw)
To: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Caleb Connolly,
Neil Armstrong, Sumit Garg
Cc: u-boot, u-boot-qcom
Expand capsule update support to correctly identify which partition
U-Boot is flashed to (between xbl, uefi, and boot including A/B
variants).
Use qcom_boot_source to determine if we were chainloaded from ABL,
meaning U-Boot is on the boot partition, otherwise we assume uefi if
it's available, finally leaving the xbl partition.
Set a different fw_name based on the target partition to prevent GUID
collisions, since a board may support U-Boot flashed to boot or XBL we
need to differentiate them since the U-Boot binary must be built
differently.
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
---
arch/arm/mach-snapdragon/capsule_update.c | 256 +++++++++++++++++++++++-------
1 file changed, 203 insertions(+), 53 deletions(-)
diff --git a/arch/arm/mach-snapdragon/capsule_update.c b/arch/arm/mach-snapdragon/capsule_update.c
index bf75a9a1b24c714792bae3712b83b96353b1df8f..eedfc40004c06aa6271c685aaca32ccab8f5c491 100644
--- a/arch/arm/mach-snapdragon/capsule_update.c
+++ b/arch/arm/mach-snapdragon/capsule_update.c
@@ -19,24 +19,21 @@
#include "qcom-priv.h"
/*
- * NOTE: for now this implementation only supports the rb3gen2. Supporting other
- * boards that boot in different ways (e.g. chainloaded from ABL) will require
- * additional complexity to properly create the dfu string and fw_images array.
- */
-
-/*
- * To handle different variants like chainloaded U-Boot here we'll need to
- * build the fw_images array dynamically at runtime. It looks like
- * mach-rockchip is a good example for how to do this.
- * Detecting which image types a board uses is TBD, hence for now we only
- * support the one new board that runs U-Boot as its primary bootloader.
+ * To handle different variants like chainloaded U-Boot here we need to
+ * build the fw_images array dynamically at runtime. These are the possible
+ * implementations:
+ *
+ * - Devices with U-Boot on the uefi_a/b partition
+ * - Devices with U-Boot on the boot (a/b) partition
+ * - Devices with U-Boot on the xbl (a/b) partition
+ *
+ * Which partition actually has U-Boot on it is determined based on the
+ * qcom_boot_source variable and additional logic in find_target_partition().
*/
struct efi_fw_image fw_images[] = {
{
- /* U-Boot flashed to the uefi_X partition (e.g. rb3gen2) */
- .fw_name = u"UBOOT_UEFI_PARTITION",
.image_index = 1,
},
};
@@ -46,8 +43,14 @@ struct efi_capsule_update_info update_info = {
.num_images = ARRAY_SIZE(fw_images),
.images = fw_images,
};
+enum target_part_type {
+ TARGET_PART_UEFI = 1,
+ TARGET_PART_XBL,
+ TARGET_PART_BOOT,
+};
+
/* LSB first */
struct part_slot_status {
u16: 2;
u16 active : 1;
@@ -56,37 +59,182 @@ struct part_slot_status {
u16 unbootable : 1;
u16 tries_remaining : 4;
};
-static int find_boot_partition(const char *partname, struct blk_desc *blk_dev, char *name)
+enum ab_slot {
+ SLOT_NONE,
+ SLOT_A,
+ SLOT_B,
+};
+
+static enum ab_slot get_part_slot(const char *partname)
+{
+ int len = strlen(partname);
+
+ if (partname[len - 2] != '_')
+ return SLOT_NONE;
+ if (partname[len - 1] == 'a')
+ return SLOT_A;
+ if (partname[len - 1] == 'b')
+ return SLOT_B;
+
+ return SLOT_NONE;
+}
+
+/*
+ * Determine which partition U-Boot is flashed to based on the boot source (ABL/XBL),
+ * the slot status, and prioritising the uefi partition over xbl if found.
+ */
+static int find_target_partition(int *devnum, enum uclass_id *uclass,
+ enum target_part_type *target_part_type)
{
int ret;
- int partnum;
+ int partnum, uefi_partnum = -1, xbl_partnum = -1;
struct disk_partition info;
struct part_slot_status *slot_status;
+ struct udevice *dev = NULL;
+ struct blk_desc *desc = NULL, *xbl_desc = NULL;
+ uchar ptn_name[32] = { 0 };
- for (partnum = 1;; partnum++) {
- ret = part_get_info(blk_dev, partnum, &info);
- if (ret)
- return ret;
+ uclass_foreach_dev_probe(UCLASS_BLK, dev) {
+ if (device_get_uclass_id(dev) != UCLASS_BLK)
+ continue;
- slot_status = (struct part_slot_status *)&info.type_flags;
- log_io("%16s: Active: %1d, Successful: %1d, Unbootable: %1d, Tries left: %1d\n",
- info.name, slot_status->active,
- slot_status->successful, slot_status->unbootable,
- slot_status->tries_remaining);
- /*
- * FIXME: eventually we'll want to find the active/inactive variant of the partition
- * but on the rb3gen2 these values might all be 0
- */
- if (!strncmp(info.name, partname, strlen(partname))) {
- log_debug("Found active %s partition: '%s'!\n", partname, info.name);
- strlcpy(name, info.name, sizeof(info.name));
- return partnum;
+ desc = dev_get_uclass_plat(dev);
+ if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
+ continue;
+ for (partnum = 1;; partnum++) {
+ ret = part_get_info(desc, partnum, &info);
+ if (ret)
+ break;
+
+ slot_status = (struct part_slot_status *)&info.type_flags;
+
+ /*
+ * Qualcomm Linux devices have a "uefi" partition, it's A/B but the
+ * flags might not be set so we assume the A partition unless the B
+ * partition is active.
+ */
+ if (!strncmp(info.name, "uefi", strlen("uefi"))) {
+ /*
+ * If U-Boot was chainloaded somehow we can't be flashed to
+ * the uefi partition
+ */
+ if (qcom_boot_source != QCOM_BOOT_SOURCE_XBL)
+ continue;
+
+ *target_part_type = TARGET_PART_UEFI;
+ /*
+ * Found an active UEFI partition, this is where U-Boot is
+ * flashed.
+ */
+ if (slot_status->active)
+ goto found;
+
+ /* Prefer A slot if it's not marked active */
+ if (get_part_slot(info.name) == SLOT_A) {
+ /*
+ * If we found the A slot after the B slot (both
+ * inactive) then we assume U-Boot is on the A slot.
+ */
+ if (uefi_partnum >= 0)
+ goto found;
+
+ /* Didn't find the B slot yet */
+ uefi_partnum = partnum;
+ strlcpy(ptn_name, info.name, 32);
+ } else {
+ /*
+ * Found inactive B slot after inactive A slot, return
+ * the A slot
+ */
+ if (uefi_partnum >= 0) {
+ partnum = uefi_partnum;
+ goto found;
+ }
+
+ /*
+ * Didn't find the A slot yet. Record that we found the
+ * B slot
+ */
+ uefi_partnum = partnum;
+ strlcpy(ptn_name, info.name, 32);
+ }
+ /* xbl and aboot are effectively the same */
+ } else if ((!strncmp(info.name, "xbl", strlen("xbl")) &&
+ strlen(info.name) == 5) ||
+ !strncmp(info.name, "aboot", strlen("aboot"))) {
+ /*
+ * If U-Boot was booted via ABL, we can't be flashed to the
+ * XBL partition
+ */
+ if (qcom_boot_source != QCOM_BOOT_SOURCE_XBL)
+ continue;
+
+ /*
+ * ignore xbl partition if we have uefi partitions, U-Boot will
+ * always be on the UEFI partition in this case.
+ */
+ if (*target_part_type == TARGET_PART_UEFI)
+ continue;
+
+ /* Either non-A/B or find the active XBL partition */
+ if (slot_status->active || !get_part_slot(info.name)) {
+ /*
+ * No quick return since we might find a uefi partition
+ * later
+ */
+ xbl_partnum = partnum;
+ *target_part_type = TARGET_PART_XBL;
+ xbl_desc = desc;
+ strlcpy(ptn_name, info.name, 32);
+ }
+
+ /*
+ * No fast return since we might also have a uefi partition which
+ * will take priority.
+ */
+ } else if (!strncmp(info.name, "boot", strlen("boot"))) {
+ /* We can only be flashed to boot if we were chainloaded */
+ if (qcom_boot_source != QCOM_BOOT_SOURCE_ANDROID)
+ continue;
+
+ /*
+ * Either non-A/B or find the active partition. We can return
+ * immediately here since we've narrowed it down to a single option
+ */
+ if (slot_status->active || !get_part_slot(info.name)) {
+ *target_part_type = TARGET_PART_BOOT;
+ goto found;
+ }
+ }
}
}
+ /*
+ * Now we've exhausted all options, if we didn't find a uefi partition
+ * then we are indeed flashed to the xbl partition.
+ */
+ if (*target_part_type == TARGET_PART_XBL) {
+ partnum = xbl_partnum;
+ desc = xbl_desc;
+ goto found;
+ }
+
+ /* Found no candidate partitions */
return -1;
+
+found:
+ if (desc) {
+ *devnum = desc->devnum;
+ *uclass = desc->uclass_id;
+ }
+
+ /* info won't match for XBL hence the copy. */
+ log_info("Capsule update target: %s (disk %d:%d)\n",
+ *target_part_type == TARGET_PART_BOOT ? info.name : ptn_name,
+ *devnum, partnum);
+ return partnum;
}
/**
* qcom_configure_capsule_updates() - Configure the DFU string for capsule updates
@@ -100,14 +248,12 @@ static int find_boot_partition(const char *partname, struct blk_desc *blk_dev, c
* in the GPT partition vendor attribute bits.
*/
void qcom_configure_capsule_updates(void)
{
- struct blk_desc *desc;
int ret = 0, partnum = -1, devnum;
static char dfu_string[32] = { 0 };
- char name[32]; /* GPT partition name */
- char *partname = "uefi_a";
- struct udevice *dev = NULL;
+ enum target_part_type target_part_type = 0;
+ enum uclass_id dev_uclass;
if (IS_ENABLED(CONFIG_SCSI)) {
/* Scan for SCSI devices */
ret = scsi_scan(false);
@@ -116,38 +262,42 @@ void qcom_configure_capsule_updates(void)
return;
}
}
- uclass_foreach_dev_probe(UCLASS_BLK, dev) {
- if (device_get_uclass_id(dev) != UCLASS_BLK)
- continue;
-
- desc = dev_get_uclass_plat(dev);
- if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
- continue;
- devnum = desc->devnum;
- partnum = find_boot_partition(partname, desc,
- name);
- if (partnum >= 0)
- break;
- }
-
+ partnum = find_target_partition(&devnum, &dev_uclass, &target_part_type);
if (partnum < 0) {
log_err("Failed to find boot partition\n");
return;
}
- switch (desc->uclass_id) {
+ /*
+ * Set the fw_name based on the partition type. This causes the GUID to be different
+ * so we will never accidentally flash a U-Boot image intended for XBL to the boot
+ * partition.
+ */
+ switch (target_part_type) {
+ case TARGET_PART_UEFI:
+ fw_images[0].fw_name = u"UBOOT_UEFI_PARTITION";
+ break;
+ case TARGET_PART_XBL:
+ fw_images[0].fw_name = u"UBOOT_XBL_PARTITION";
+ break;
+ case TARGET_PART_BOOT:
+ fw_images[0].fw_name = u"UBOOT_BOOT_PARTITION";
+ break;
+ }
+
+ switch (dev_uclass) {
case UCLASS_SCSI:
snprintf(dfu_string, 32, "scsi %d=u-boot.bin part %d", devnum, partnum);
break;
case UCLASS_MMC:
snprintf(dfu_string, 32, "mmc 0=u-boot.bin part %d %d", devnum, partnum);
break;
default:
- debug("Unsupported storage uclass: %d\n", desc->uclass_id);
+ debug("Unsupported storage uclass: %d\n", dev_uclass);
return;
}
- log_debug("boot partition is %s, DFU string: '%s'\n", name, dfu_string);
+ log_debug("DFU string: '%s'\n", dfu_string);
update_info.dfu_string = dfu_string;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 3/4] dfu: scsi: don't call scsi_scan()
2025-03-26 17:40 [PATCH 0/4] Qualcomm: expand capsule update support Caleb Connolly
2025-03-26 17:40 ` [PATCH 1/4] mach-snapdragon: track boot source Caleb Connolly
2025-03-26 17:40 ` [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods Caleb Connolly
@ 2025-03-26 17:40 ` Caleb Connolly
2025-03-31 13:52 ` Neil Armstrong
2025-03-31 13:53 ` Ilias Apalodimas
2025-03-26 17:40 ` [PATCH 4/4] qcom_defconfig: enable capsule update support Caleb Connolly
2025-03-26 17:44 ` [PATCH 0/4] Qualcomm: expand " Caleb Connolly
4 siblings, 2 replies; 16+ messages in thread
From: Caleb Connolly @ 2025-03-26 17:40 UTC (permalink / raw)
To: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Caleb Connolly,
Neil Armstrong, Sumit Garg
Cc: u-boot, u-boot-qcom
Calling scsi_scan() results in all the block devices (and EFI block
devices) being destroyed and re-created. This breaks the EFI filesystem
drivers during capsule update.
Remove the call, since boards really should be calling scsi_scan()
themselves during board_init().
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
---
drivers/dfu/dfu_scsi.c | 5 -----
1 file changed, 5 deletions(-)
diff --git a/drivers/dfu/dfu_scsi.c b/drivers/dfu/dfu_scsi.c
index 9f95194784c1de00458843276872b1d23d023444..a234548ae46dc2a6ae1ca5770accb58f43782239 100644
--- a/drivers/dfu/dfu_scsi.c
+++ b/drivers/dfu/dfu_scsi.c
@@ -341,13 +341,8 @@ int dfu_fill_entity_scsi(struct dfu_entity *dfu, char *devstr, char **argv, int
if (*s)
return -EINVAL;
}
- if (scsi_scan(false)) {
- pr_err("Couldn't init scsi device.\n");
- return -ENODEV;
- }
-
ret = find_scsi_device(dfu->data.scsi.lun, &scsi);
if (ret < 0) {
pr_err("Couldn't find scsi device no. %d.\n", dfu->data.scsi.lun);
return -ENODEV;
--
2.49.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 4/4] qcom_defconfig: enable capsule update support
2025-03-26 17:40 [PATCH 0/4] Qualcomm: expand capsule update support Caleb Connolly
` (2 preceding siblings ...)
2025-03-26 17:40 ` [PATCH 3/4] dfu: scsi: don't call scsi_scan() Caleb Connolly
@ 2025-03-26 17:40 ` Caleb Connolly
2025-03-27 8:46 ` Peng Fan
2025-03-31 13:52 ` Ilias Apalodimas
2025-03-26 17:44 ` [PATCH 0/4] Qualcomm: expand " Caleb Connolly
4 siblings, 2 replies; 16+ messages in thread
From: Caleb Connolly @ 2025-03-26 17:40 UTC (permalink / raw)
To: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Caleb Connolly,
Neil Armstrong, Sumit Garg
Cc: u-boot, u-boot-qcom
We can now correctly identify which partition U-Boot is flashed to
between uefi, xbl, and boot (including A/B support) so enable capsule
update support for all boards.
Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
---
configs/qcm6490_defconfig | 6 ------
configs/qcom_defconfig | 3 +++
2 files changed, 3 insertions(+), 6 deletions(-)
diff --git a/configs/qcm6490_defconfig b/configs/qcm6490_defconfig
index ba26924da161b1c4b5378955185f314b05cb1006..5ddc5ab3ef8cfe8f9cc09eb573c1a8130b394b43 100644
--- a/configs/qcm6490_defconfig
+++ b/configs/qcm6490_defconfig
@@ -18,10 +18,4 @@ CONFIG_DEBUG_UART_CLOCK=14745600
CONFIG_TEXT_BASE=0x9fc00000
CONFIG_REMAKE_ELF=y
CONFIG_DEFAULT_DEVICE_TREE="qcom/qcs6490-rb3gen2"
-
-# Enable capsule updates
-CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
-CONFIG_EFI_CAPSULE_ON_DISK=y
-CONFIG_EFI_IGNORE_OSINDICATIONS=y
-CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
index ba4d38d100e053e3708ee2623bf3530787b6b94f..d69185f3c2f0452e6757b785a023cf612bfa3839 100644
--- a/configs/qcom_defconfig
+++ b/configs/qcom_defconfig
@@ -5,8 +5,11 @@ CONFIG_SYS_INIT_SP_BSS_OFFSET=1572864
CONFIG_ARCH_SNAPDRAGON=y
CONFIG_NR_DRAM_BANKS=24
CONFIG_DEFAULT_DEVICE_TREE="qcom/sdm845-db845c"
CONFIG_SYS_LOAD_ADDR=0xA0000000
+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
+CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
CONFIG_BUTTON_CMD=y
CONFIG_FIT=y
CONFIG_FIT_VERBOSE=y
CONFIG_BOOTSTD_FULL=y
--
2.49.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 0/4] Qualcomm: expand capsule update support
2025-03-26 17:40 [PATCH 0/4] Qualcomm: expand capsule update support Caleb Connolly
` (3 preceding siblings ...)
2025-03-26 17:40 ` [PATCH 4/4] qcom_defconfig: enable capsule update support Caleb Connolly
@ 2025-03-26 17:44 ` Caleb Connolly
4 siblings, 0 replies; 16+ messages in thread
From: Caleb Connolly @ 2025-03-26 17:44 UTC (permalink / raw)
To: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Neil Armstrong,
Sumit Garg
Cc: u-boot, u-boot-qcom
On 3/26/25 18:40, Caleb Connolly wrote:
> The initial capsule update support only worked on the RB3 Gen 2 and made
> a lot of assumptions specific to that board.
>
> Implement the logic necessary to update U-Boot no matter where it was
> flashed to, independent of any particular board.
>
> First, we keep track of how U-Boot was loaded, specifically if we had a
> valid external FDT (even if we didn't use it) this indicates that we
> were booted via the Android bootloader, in this case the target for
> capsule updates is the boot partition. Otherwise, we target the uefi
> partition (if it exists) or the xbl partition. We handle A/B support for
> all 3 (currently we always flash to the currently active partition with
> a minor exception for the uefi partition).
>
> We introduce two new fw_name strings to differentiate the GUIDs based on
> the target partition, this means one board can support multiple boot
> methods with capsule update support for all of them (typically this
> would be chainloading OR flashing U-Boot to XBL).
>
> Lastly, the call to scsi_scan() in dfu_scsi.c is removed. Since
> scsi_scan() unbinds all scsi devices it breaks device handles maintained
> in the EFI layer for the duration of the capsule update process and
> causes the EFI filesystem access to delete the capsule file after the
> update to fail.
>
> Boards should instead be responsible for calling scsi_scan() before
> initiating DFU.
Forgot to mention: this has been tested on the OnePlus 6 (with U-Boot in
the boot partition - chainloaded), the rb3 (with U-Boot flashed to xbl),
and the rb3gen2 (With u-boot flashed to uefi).
More testing is very welcome!
>
> ---
> Caleb Connolly (4):
> mach-snapdragon: track boot source
> mach-snapdragon: CapsuleUpdate: support all boot methods
> dfu: scsi: don't call scsi_scan()
> qcom_defconfig: enable capsule update support
>
> arch/arm/mach-snapdragon/board.c | 25 +++
> arch/arm/mach-snapdragon/capsule_update.c | 256 +++++++++++++++++++++++-------
> arch/arm/mach-snapdragon/qcom-priv.h | 14 ++
> configs/qcm6490_defconfig | 6 -
> configs/qcom_defconfig | 3 +
> drivers/dfu/dfu_scsi.c | 5 -
> 6 files changed, 245 insertions(+), 64 deletions(-)
> ---
> base-commit: 68ac813c70d991ec518d0fd815efdb10a05958c0
>
> Caleb Connolly <caleb.connolly@linaro.org>
>
--
Caleb (they/them)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 4/4] qcom_defconfig: enable capsule update support
2025-03-26 17:40 ` [PATCH 4/4] qcom_defconfig: enable capsule update support Caleb Connolly
@ 2025-03-27 8:46 ` Peng Fan
2025-03-27 12:30 ` Caleb Connolly
2025-03-31 13:52 ` Ilias Apalodimas
1 sibling, 1 reply; 16+ messages in thread
From: Peng Fan @ 2025-03-27 8:46 UTC (permalink / raw)
To: Caleb Connolly
Cc: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Neil Armstrong,
Sumit Garg, u-boot, u-boot-qcom
On Wed, Mar 26, 2025 at 06:40:37PM +0100, Caleb Connolly wrote:
>We can now correctly identify which partition U-Boot is flashed to
>between uefi, xbl, and boot (including A/B support) so enable capsule
>update support for all boards.
>
>Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
>---
> configs/qcm6490_defconfig | 6 ------
> configs/qcom_defconfig | 3 +++
> 2 files changed, 3 insertions(+), 6 deletions(-)
>
>diff --git a/configs/qcm6490_defconfig b/configs/qcm6490_defconfig
>index ba26924da161b1c4b5378955185f314b05cb1006..5ddc5ab3ef8cfe8f9cc09eb573c1a8130b394b43 100644
>--- a/configs/qcm6490_defconfig
>+++ b/configs/qcm6490_defconfig
>@@ -18,10 +18,4 @@ CONFIG_DEBUG_UART_CLOCK=14745600
> CONFIG_TEXT_BASE=0x9fc00000
> CONFIG_REMAKE_ELF=y
>
> CONFIG_DEFAULT_DEVICE_TREE="qcom/qcs6490-rb3gen2"
>-
>-# Enable capsule updates
>-CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
>-CONFIG_EFI_CAPSULE_ON_DISK=y
>-CONFIG_EFI_IGNORE_OSINDICATIONS=y
>-CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
>diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
>index ba4d38d100e053e3708ee2623bf3530787b6b94f..d69185f3c2f0452e6757b785a023cf612bfa3839 100644
>--- a/configs/qcom_defconfig
>+++ b/configs/qcom_defconfig
>@@ -5,8 +5,11 @@ CONFIG_SYS_INIT_SP_BSS_OFFSET=1572864
> CONFIG_ARCH_SNAPDRAGON=y
> CONFIG_NR_DRAM_BANKS=24
> CONFIG_DEFAULT_DEVICE_TREE="qcom/sdm845-db845c"
> CONFIG_SYS_LOAD_ADDR=0xA0000000
>+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
>+CONFIG_EFI_CAPSULE_ON_DISK=y
>+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
> CONFIG_BUTTON_CMD=y
> CONFIG_FIT=y
> CONFIG_FIT_VERBOSE=y
> CONFIG_BOOTSTD_FULL=y
For capsule update, CONFIG_EFI_MM_COMM_TEE is not needed?
Regards,
Peng
>
>--
>2.49.0
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 4/4] qcom_defconfig: enable capsule update support
2025-03-27 8:46 ` Peng Fan
@ 2025-03-27 12:30 ` Caleb Connolly
0 siblings, 0 replies; 16+ messages in thread
From: Caleb Connolly @ 2025-03-27 12:30 UTC (permalink / raw)
To: Peng Fan
Cc: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Neil Armstrong,
Sumit Garg, u-boot, u-boot-qcom
On 3/27/25 09:46, Peng Fan wrote:
> On Wed, Mar 26, 2025 at 06:40:37PM +0100, Caleb Connolly wrote:
>> We can now correctly identify which partition U-Boot is flashed to
>> between uefi, xbl, and boot (including A/B support) so enable capsule
>> update support for all boards.
>>
>> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
>> ---
>> configs/qcm6490_defconfig | 6 ------
>> configs/qcom_defconfig | 3 +++
>> 2 files changed, 3 insertions(+), 6 deletions(-)
>>
>> diff --git a/configs/qcm6490_defconfig b/configs/qcm6490_defconfig
>> index ba26924da161b1c4b5378955185f314b05cb1006..5ddc5ab3ef8cfe8f9cc09eb573c1a8130b394b43 100644
>> --- a/configs/qcm6490_defconfig
>> +++ b/configs/qcm6490_defconfig
>> @@ -18,10 +18,4 @@ CONFIG_DEBUG_UART_CLOCK=14745600
>> CONFIG_TEXT_BASE=0x9fc00000
>> CONFIG_REMAKE_ELF=y
>>
>> CONFIG_DEFAULT_DEVICE_TREE="qcom/qcs6490-rb3gen2"
>> -
>> -# Enable capsule updates
>> -CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
>> -CONFIG_EFI_CAPSULE_ON_DISK=y
>> -CONFIG_EFI_IGNORE_OSINDICATIONS=y
>> -CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
>> diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
>> index ba4d38d100e053e3708ee2623bf3530787b6b94f..d69185f3c2f0452e6757b785a023cf612bfa3839 100644
>> --- a/configs/qcom_defconfig
>> +++ b/configs/qcom_defconfig
>> @@ -5,8 +5,11 @@ CONFIG_SYS_INIT_SP_BSS_OFFSET=1572864
>> CONFIG_ARCH_SNAPDRAGON=y
>> CONFIG_NR_DRAM_BANKS=24
>> CONFIG_DEFAULT_DEVICE_TREE="qcom/sdm845-db845c"
>> CONFIG_SYS_LOAD_ADDR=0xA0000000
>> +CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
>> +CONFIG_EFI_CAPSULE_ON_DISK=y
>> +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
>> CONFIG_BUTTON_CMD=y
>> CONFIG_FIT=y
>> CONFIG_FIT_VERBOSE=y
>> CONFIG_BOOTSTD_FULL=y
>
> For capsule update, CONFIG_EFI_MM_COMM_TEE is not needed?
No, Qualcomm have a proprietary TEE. We rely on storing EFI variables in
a file on the ESP. There does seem to be an issue where capsule updates
don't occur unless that file already exists though...
>
> Regards,
> Peng
>>
>> --
>> 2.49.0
>>
--
Caleb (they/them)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/4] mach-snapdragon: track boot source
2025-03-26 17:40 ` [PATCH 1/4] mach-snapdragon: track boot source Caleb Connolly
@ 2025-03-31 13:52 ` Neil Armstrong
0 siblings, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2025-03-31 13:52 UTC (permalink / raw)
To: Caleb Connolly, Lukasz Majewski, Mattijs Korpershoek, Tom Rini,
Sumit Garg
Cc: u-boot, u-boot-qcom
On 26/03/2025 18:40, Caleb Connolly wrote:
> Keep track of whether we were loaded via ABL or if U-Boot is running as
> a first-stage bootloader.
>
> For now we set this based on if we have a valid external FDT or not,
> since it isn't possible to chainload U-Boot from ABL without there being
> an external FDT.
>
> This will be used to inform the capsule update logic which partition
> U-Boot is flashed to.
>
> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> ---
> arch/arm/mach-snapdragon/board.c | 25 +++++++++++++++++++++++++
> arch/arm/mach-snapdragon/qcom-priv.h | 14 ++++++++++++++
> 2 files changed, 39 insertions(+)
>
> diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
> index deae4d323789eab75d5fe735159b4cd820c02c45..245a963f5321bda3030d3809e1b108f280b3c2b5 100644
> --- a/arch/arm/mach-snapdragon/board.c
> +++ b/arch/arm/mach-snapdragon/board.c
> @@ -36,8 +36,10 @@
> #include "qcom-priv.h"
>
> DECLARE_GLOBAL_DATA_PTR;
>
> +enum qcom_boot_source qcom_boot_source __section(".data") = 0;
> +
> static struct mm_region rbx_mem_map[CONFIG_NR_DRAM_BANKS + 2] = { { 0 } };
>
> struct mm_region *mem_map = rbx_mem_map;
>
> @@ -237,8 +239,14 @@ int board_fdt_blob_setup(void **fdtp)
>
> if (ret < 0)
> panic("No valid memory ranges found!\n");
>
> + /* If we have an external FDT, it can only have come from the Android bootloader. */
> + if (external_valid)
> + qcom_boot_source = QCOM_BOOT_SOURCE_ANDROID;
> + else
> + qcom_boot_source = QCOM_BOOT_SOURCE_XBL;
> +
> debug("ram_base = %#011lx, ram_size = %#011llx\n",
> gd->ram_base, gd->ram_size);
>
> if (internal_valid) {
> @@ -472,8 +480,24 @@ static void configure_env(void)
>
> qcom_set_serialno();
> }
>
> +void qcom_show_boot_source(void)
> +{
> + const char *name = "UNKNOWN";
> +
> + switch (qcom_boot_source) {
> + case QCOM_BOOT_SOURCE_ANDROID:
> + name = "ABL";
> + break;
> + case QCOM_BOOT_SOURCE_XBL:
> + name = "XBL";
> + break;
> + }
> +
> + log_info("U-Boot loaded from %s\n", name);
Can you write to a boot_source env variable ?
> +}
> +
> void __weak qcom_late_init(void)
> {
> }
>
> @@ -515,8 +539,9 @@ int board_late_init(void)
>
> configure_env();
> qcom_late_init();
>
> + qcom_show_boot_source();
> /* Configure the dfu_string for capsule updates */
> qcom_configure_capsule_updates();
>
> return 0;
> diff --git a/arch/arm/mach-snapdragon/qcom-priv.h b/arch/arm/mach-snapdragon/qcom-priv.h
> index 74d39197b89f4e769299b06214c26ee829ecdce0..e5eb4cfbc2b752de799b1407ede69683c81474c1 100644
> --- a/arch/arm/mach-snapdragon/qcom-priv.h
> +++ b/arch/arm/mach-snapdragon/qcom-priv.h
> @@ -2,8 +2,22 @@
>
> #ifndef __QCOM_PRIV_H__
> #define __QCOM_PRIV_H__
>
> +/**
> + * enum qcom_boot_source - Track where we got loaded from.
> + * Used for capsule update logic.
> + *
> + * @QCOM_BOOT_SOURCE_ANDROID: chainloaded (typically from ABL)
> + * @QCOM_BOOT_SOURCE_XBL: flashed to the XBL or UEFI partition
> + */
> +enum qcom_boot_source {
> + QCOM_BOOT_SOURCE_ANDROID = 1,
> + QCOM_BOOT_SOURCE_XBL,
> +};
> +
> +extern enum qcom_boot_source qcom_boot_source;
> +
> #if IS_ENABLED(CONFIG_EFI_HAVE_CAPSULE_SUPPORT)
> void qcom_configure_capsule_updates(void);
> #else
> void qcom_configure_capsule_updates(void) {}
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] dfu: scsi: don't call scsi_scan()
2025-03-26 17:40 ` [PATCH 3/4] dfu: scsi: don't call scsi_scan() Caleb Connolly
@ 2025-03-31 13:52 ` Neil Armstrong
2025-03-31 13:53 ` Ilias Apalodimas
1 sibling, 0 replies; 16+ messages in thread
From: Neil Armstrong @ 2025-03-31 13:52 UTC (permalink / raw)
To: Caleb Connolly, Lukasz Majewski, Mattijs Korpershoek, Tom Rini,
Sumit Garg
Cc: u-boot, u-boot-qcom
On 26/03/2025 18:40, Caleb Connolly wrote:
> Calling scsi_scan() results in all the block devices (and EFI block
> devices) being destroyed and re-created. This breaks the EFI filesystem
> drivers during capsule update.
>
> Remove the call, since boards really should be calling scsi_scan()
> themselves during board_init().
>
> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> ---
> drivers/dfu/dfu_scsi.c | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff --git a/drivers/dfu/dfu_scsi.c b/drivers/dfu/dfu_scsi.c
> index 9f95194784c1de00458843276872b1d23d023444..a234548ae46dc2a6ae1ca5770accb58f43782239 100644
> --- a/drivers/dfu/dfu_scsi.c
> +++ b/drivers/dfu/dfu_scsi.c
> @@ -341,13 +341,8 @@ int dfu_fill_entity_scsi(struct dfu_entity *dfu, char *devstr, char **argv, int
> if (*s)
> return -EINVAL;
> }
>
> - if (scsi_scan(false)) {
> - pr_err("Couldn't init scsi device.\n");
> - return -ENODEV;
> - }
> -
> ret = find_scsi_device(dfu->data.scsi.lun, &scsi);
> if (ret < 0) {
> pr_err("Couldn't find scsi device no. %d.\n", dfu->data.scsi.lun);
> return -ENODEV;
>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 4/4] qcom_defconfig: enable capsule update support
2025-03-26 17:40 ` [PATCH 4/4] qcom_defconfig: enable capsule update support Caleb Connolly
2025-03-27 8:46 ` Peng Fan
@ 2025-03-31 13:52 ` Ilias Apalodimas
1 sibling, 0 replies; 16+ messages in thread
From: Ilias Apalodimas @ 2025-03-31 13:52 UTC (permalink / raw)
To: Caleb Connolly
Cc: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Neil Armstrong,
Sumit Garg, u-boot, u-boot-qcom
On Wed, 26 Mar 2025 at 19:41, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>
> We can now correctly identify which partition U-Boot is flashed to
> between uefi, xbl, and boot (including A/B support) so enable capsule
> update support for all boards.
>
> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> ---
> configs/qcm6490_defconfig | 6 ------
> configs/qcom_defconfig | 3 +++
> 2 files changed, 3 insertions(+), 6 deletions(-)
>
> diff --git a/configs/qcm6490_defconfig b/configs/qcm6490_defconfig
> index ba26924da161b1c4b5378955185f314b05cb1006..5ddc5ab3ef8cfe8f9cc09eb573c1a8130b394b43 100644
> --- a/configs/qcm6490_defconfig
> +++ b/configs/qcm6490_defconfig
> @@ -18,10 +18,4 @@ CONFIG_DEBUG_UART_CLOCK=14745600
> CONFIG_TEXT_BASE=0x9fc00000
> CONFIG_REMAKE_ELF=y
>
> CONFIG_DEFAULT_DEVICE_TREE="qcom/qcs6490-rb3gen2"
> -
> -# Enable capsule updates
> -CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
> -CONFIG_EFI_CAPSULE_ON_DISK=y
> -CONFIG_EFI_IGNORE_OSINDICATIONS=y
> -CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
> diff --git a/configs/qcom_defconfig b/configs/qcom_defconfig
> index ba4d38d100e053e3708ee2623bf3530787b6b94f..d69185f3c2f0452e6757b785a023cf612bfa3839 100644
> --- a/configs/qcom_defconfig
> +++ b/configs/qcom_defconfig
> @@ -5,8 +5,11 @@ CONFIG_SYS_INIT_SP_BSS_OFFSET=1572864
> CONFIG_ARCH_SNAPDRAGON=y
> CONFIG_NR_DRAM_BANKS=24
> CONFIG_DEFAULT_DEVICE_TREE="qcom/sdm845-db845c"
> CONFIG_SYS_LOAD_ADDR=0xA0000000
> +CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
> +CONFIG_EFI_CAPSULE_ON_DISK=y
> +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
> CONFIG_BUTTON_CMD=y
> CONFIG_FIT=y
> CONFIG_FIT_VERBOSE=y
> CONFIG_BOOTSTD_FULL=y
>
> --
> 2.49.0
>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/4] dfu: scsi: don't call scsi_scan()
2025-03-26 17:40 ` [PATCH 3/4] dfu: scsi: don't call scsi_scan() Caleb Connolly
2025-03-31 13:52 ` Neil Armstrong
@ 2025-03-31 13:53 ` Ilias Apalodimas
1 sibling, 0 replies; 16+ messages in thread
From: Ilias Apalodimas @ 2025-03-31 13:53 UTC (permalink / raw)
To: Caleb Connolly
Cc: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Neil Armstrong,
Sumit Garg, u-boot, u-boot-qcom
On Wed, 26 Mar 2025 at 19:41, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>
> Calling scsi_scan() results in all the block devices (and EFI block
> devices) being destroyed and re-created. This breaks the EFI filesystem
> drivers during capsule update.
>
> Remove the call, since boards really should be calling scsi_scan()
> themselves during board_init().
>
> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> ---
> drivers/dfu/dfu_scsi.c | 5 -----
> 1 file changed, 5 deletions(-)
>
> diff --git a/drivers/dfu/dfu_scsi.c b/drivers/dfu/dfu_scsi.c
> index 9f95194784c1de00458843276872b1d23d023444..a234548ae46dc2a6ae1ca5770accb58f43782239 100644
> --- a/drivers/dfu/dfu_scsi.c
> +++ b/drivers/dfu/dfu_scsi.c
> @@ -341,13 +341,8 @@ int dfu_fill_entity_scsi(struct dfu_entity *dfu, char *devstr, char **argv, int
> if (*s)
> return -EINVAL;
> }
>
> - if (scsi_scan(false)) {
> - pr_err("Couldn't init scsi device.\n");
> - return -ENODEV;
> - }
> -
> ret = find_scsi_device(dfu->data.scsi.lun, &scsi);
> if (ret < 0) {
> pr_err("Couldn't find scsi device no. %d.\n", dfu->data.scsi.lun);
> return -ENODEV;
>
> --
> 2.49.0
>
Reviewed-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods
2025-03-26 17:40 ` [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods Caleb Connolly
@ 2025-04-01 8:45 ` Neil Armstrong
2025-04-11 14:48 ` Caleb Connolly
2025-04-01 12:42 ` Ilias Apalodimas
1 sibling, 1 reply; 16+ messages in thread
From: Neil Armstrong @ 2025-04-01 8:45 UTC (permalink / raw)
To: Caleb Connolly, Lukasz Majewski, Mattijs Korpershoek, Tom Rini,
Sumit Garg
Cc: u-boot, u-boot-qcom
On 26/03/2025 18:40, Caleb Connolly wrote:
> Expand capsule update support to correctly identify which partition
> U-Boot is flashed to (between xbl, uefi, and boot including A/B
> variants).
>
> Use qcom_boot_source to determine if we were chainloaded from ABL,
> meaning U-Boot is on the boot partition, otherwise we assume uefi if
> it's available, finally leaving the xbl partition.
>
> Set a different fw_name based on the target partition to prevent GUID
> collisions, since a board may support U-Boot flashed to boot or XBL we
> need to differentiate them since the U-Boot binary must be built
> differently.
>
> Signed-off-by: Caleb Connolly <caleb.connolly@linaro.org>
> ---
> arch/arm/mach-snapdragon/capsule_update.c | 256 +++++++++++++++++++++++-------
> 1 file changed, 203 insertions(+), 53 deletions(-)
>
> diff --git a/arch/arm/mach-snapdragon/capsule_update.c b/arch/arm/mach-snapdragon/capsule_update.c
> index bf75a9a1b24c714792bae3712b83b96353b1df8f..eedfc40004c06aa6271c685aaca32ccab8f5c491 100644
> --- a/arch/arm/mach-snapdragon/capsule_update.c
> +++ b/arch/arm/mach-snapdragon/capsule_update.c
> @@ -19,24 +19,21 @@
>
> #include "qcom-priv.h"
>
> /*
> - * NOTE: for now this implementation only supports the rb3gen2. Supporting other
> - * boards that boot in different ways (e.g. chainloaded from ABL) will require
> - * additional complexity to properly create the dfu string and fw_images array.
> - */
> -
> -/*
> - * To handle different variants like chainloaded U-Boot here we'll need to
> - * build the fw_images array dynamically at runtime. It looks like
> - * mach-rockchip is a good example for how to do this.
> - * Detecting which image types a board uses is TBD, hence for now we only
> - * support the one new board that runs U-Boot as its primary bootloader.
> + * To handle different variants like chainloaded U-Boot here we need to
> + * build the fw_images array dynamically at runtime. These are the possible
> + * implementations:
> + *
> + * - Devices with U-Boot on the uefi_a/b partition
> + * - Devices with U-Boot on the boot (a/b) partition
> + * - Devices with U-Boot on the xbl (a/b) partition
> + *
> + * Which partition actually has U-Boot on it is determined based on the
> + * qcom_boot_source variable and additional logic in find_target_partition().
> */
> struct efi_fw_image fw_images[] = {
> {
> - /* U-Boot flashed to the uefi_X partition (e.g. rb3gen2) */
> - .fw_name = u"UBOOT_UEFI_PARTITION",
> .image_index = 1,
> },
> };
>
> @@ -46,8 +43,14 @@ struct efi_capsule_update_info update_info = {
> .num_images = ARRAY_SIZE(fw_images),
> .images = fw_images,
> };
>
> +enum target_part_type {
> + TARGET_PART_UEFI = 1,
> + TARGET_PART_XBL,
> + TARGET_PART_BOOT,
> +};
> +
> /* LSB first */
> struct part_slot_status {
> u16: 2;
> u16 active : 1;
> @@ -56,37 +59,182 @@ struct part_slot_status {
> u16 unbootable : 1;
> u16 tries_remaining : 4;
> };
>
> -static int find_boot_partition(const char *partname, struct blk_desc *blk_dev, char *name)
> +enum ab_slot {
> + SLOT_NONE,
> + SLOT_A,
> + SLOT_B,
> +};
> +
> +static enum ab_slot get_part_slot(const char *partname)
> +{
> + int len = strlen(partname);
> +
> + if (partname[len - 2] != '_')
> + return SLOT_NONE;
> + if (partname[len - 1] == 'a')
> + return SLOT_A;
> + if (partname[len - 1] == 'b')
> + return SLOT_B;
> +
> + return SLOT_NONE;
> +}
> +
> +/*
> + * Determine which partition U-Boot is flashed to based on the boot source (ABL/XBL),
> + * the slot status, and prioritising the uefi partition over xbl if found.
prioritizing
> + */
> +static int find_target_partition(int *devnum, enum uclass_id *uclass,
> + enum target_part_type *target_part_type)
> {
> int ret;
> - int partnum;
> + int partnum, uefi_partnum = -1, xbl_partnum = -1;
> struct disk_partition info;
> struct part_slot_status *slot_status;
> + struct udevice *dev = NULL;
> + struct blk_desc *desc = NULL, *xbl_desc = NULL;
> + uchar ptn_name[32] = { 0 };
>
> - for (partnum = 1;; partnum++) {
> - ret = part_get_info(blk_dev, partnum, &info);
> - if (ret)
> - return ret;
> + uclass_foreach_dev_probe(UCLASS_BLK, dev) {
> + if (device_get_uclass_id(dev) != UCLASS_BLK)
> + continue;
>
> - slot_status = (struct part_slot_status *)&info.type_flags;
> - log_io("%16s: Active: %1d, Successful: %1d, Unbootable: %1d, Tries left: %1d\n",
> - info.name, slot_status->active,
> - slot_status->successful, slot_status->unbootable,
> - slot_status->tries_remaining);
> - /*
> - * FIXME: eventually we'll want to find the active/inactive variant of the partition
> - * but on the rb3gen2 these values might all be 0
> - */
> - if (!strncmp(info.name, partname, strlen(partname))) {
> - log_debug("Found active %s partition: '%s'!\n", partname, info.name);
> - strlcpy(name, info.name, sizeof(info.name));
> - return partnum;
> + desc = dev_get_uclass_plat(dev);
> + if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
> + continue;
> + for (partnum = 1;; partnum++) {
> + ret = part_get_info(desc, partnum, &info);
> + if (ret)
> + break;
> +
> + slot_status = (struct part_slot_status *)&info.type_flags;
> +
> + /*
> + * Qualcomm Linux devices have a "uefi" partition, it's A/B but the
> + * flags might not be set so we assume the A partition unless the B
> + * partition is active.
> + */
> + if (!strncmp(info.name, "uefi", strlen("uefi"))) {
> + /*
> + * If U-Boot was chainloaded somehow we can't be flashed to
> + * the uefi partition
> + */
> + if (qcom_boot_source != QCOM_BOOT_SOURCE_XBL)
> + continue;
> +
> + *target_part_type = TARGET_PART_UEFI;
> + /*
> + * Found an active UEFI partition, this is where U-Boot is
> + * flashed.
> + */
> + if (slot_status->active)
> + goto found;
> +
> + /* Prefer A slot if it's not marked active */
> + if (get_part_slot(info.name) == SLOT_A) {
> + /*
> + * If we found the A slot after the B slot (both
> + * inactive) then we assume U-Boot is on the A slot.
> + */
> + if (uefi_partnum >= 0)
> + goto found;
> +
> + /* Didn't find the B slot yet */
> + uefi_partnum = partnum;
> + strlcpy(ptn_name, info.name, 32);
> + } else {
> + /*
> + * Found inactive B slot after inactive A slot, return
> + * the A slot
> + */
> + if (uefi_partnum >= 0) {
> + partnum = uefi_partnum;
> + goto found;
> + }
> +
> + /*
> + * Didn't find the A slot yet. Record that we found the
> + * B slot
> + */
> + uefi_partnum = partnum;
> + strlcpy(ptn_name, info.name, 32);
> + }
> + /* xbl and aboot are effectively the same */
> + } else if ((!strncmp(info.name, "xbl", strlen("xbl")) &&
> + strlen(info.name) == 5) ||
> + !strncmp(info.name, "aboot", strlen("aboot"))) {
> + /*
> + * If U-Boot was booted via ABL, we can't be flashed to the
> + * XBL partition
> + */
> + if (qcom_boot_source != QCOM_BOOT_SOURCE_XBL)
> + continue;
> +
> + /*
> + * ignore xbl partition if we have uefi partitions, U-Boot will
> + * always be on the UEFI partition in this case.
> + */
> + if (*target_part_type == TARGET_PART_UEFI)
> + continue;
> +
> + /* Either non-A/B or find the active XBL partition */
> + if (slot_status->active || !get_part_slot(info.name)) {
> + /*
> + * No quick return since we might find a uefi partition
> + * later
> + */
> + xbl_partnum = partnum;
> + *target_part_type = TARGET_PART_XBL;
> + xbl_desc = desc;
> + strlcpy(ptn_name, info.name, 32);
> + }
> +
> + /*
> + * No fast return since we might also have a uefi partition which
> + * will take priority.
> + */
> + } else if (!strncmp(info.name, "boot", strlen("boot"))) {
> + /* We can only be flashed to boot if we were chainloaded */
> + if (qcom_boot_source != QCOM_BOOT_SOURCE_ANDROID)
> + continue;
> +
> + /*
> + * Either non-A/B or find the active partition. We can return
> + * immediately here since we've narrowed it down to a single option
> + */
> + if (slot_status->active || !get_part_slot(info.name)) {
> + *target_part_type = TARGET_PART_BOOT;
> + goto found;
> + }
> + }
> }
> }
>
> + /*
> + * Now we've exhausted all options, if we didn't find a uefi partition
> + * then we are indeed flashed to the xbl partition.
> + */
> + if (*target_part_type == TARGET_PART_XBL) {
> + partnum = xbl_partnum;
> + desc = xbl_desc;
> + goto found;
> + }
> +
> + /* Found no candidate partitions */
> return -1;
> +
> +found:
> + if (desc) {
> + *devnum = desc->devnum;
> + *uclass = desc->uclass_id;
> + }
> +
> + /* info won't match for XBL hence the copy. */
> + log_info("Capsule update target: %s (disk %d:%d)\n",
> + *target_part_type == TARGET_PART_BOOT ? info.name : ptn_name,
> + *devnum, partnum);
> + return partnum;
> }
>
> /**
> * qcom_configure_capsule_updates() - Configure the DFU string for capsule updates
> @@ -100,14 +248,12 @@ static int find_boot_partition(const char *partname, struct blk_desc *blk_dev, c
> * in the GPT partition vendor attribute bits.
> */
> void qcom_configure_capsule_updates(void)
> {
> - struct blk_desc *desc;
> int ret = 0, partnum = -1, devnum;
> static char dfu_string[32] = { 0 };
> - char name[32]; /* GPT partition name */
> - char *partname = "uefi_a";
> - struct udevice *dev = NULL;
> + enum target_part_type target_part_type = 0;
> + enum uclass_id dev_uclass;
>
> if (IS_ENABLED(CONFIG_SCSI)) {
> /* Scan for SCSI devices */
> ret = scsi_scan(false);
> @@ -116,38 +262,42 @@ void qcom_configure_capsule_updates(void)
> return;
> }
> }
>
> - uclass_foreach_dev_probe(UCLASS_BLK, dev) {
> - if (device_get_uclass_id(dev) != UCLASS_BLK)
> - continue;
> -
> - desc = dev_get_uclass_plat(dev);
> - if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
> - continue;
> - devnum = desc->devnum;
> - partnum = find_boot_partition(partname, desc,
> - name);
> - if (partnum >= 0)
> - break;
> - }
> -
> + partnum = find_target_partition(&devnum, &dev_uclass, &target_part_type);
> if (partnum < 0) {
> log_err("Failed to find boot partition\n");
> return;
> }
>
> - switch (desc->uclass_id) {
> + /*
> + * Set the fw_name based on the partition type. This causes the GUID to be different
> + * so we will never accidentally flash a U-Boot image intended for XBL to the boot
> + * partition.
> + */
> + switch (target_part_type) {
> + case TARGET_PART_UEFI:
> + fw_images[0].fw_name = u"UBOOT_UEFI_PARTITION";
> + break;
> + case TARGET_PART_XBL:
> + fw_images[0].fw_name = u"UBOOT_XBL_PARTITION";
> + break;
> + case TARGET_PART_BOOT:
> + fw_images[0].fw_name = u"UBOOT_BOOT_PARTITION";
> + break;
> + }
> +
> + switch (dev_uclass) {
> case UCLASS_SCSI:
> snprintf(dfu_string, 32, "scsi %d=u-boot.bin part %d", devnum, partnum);
> break;
> case UCLASS_MMC:
> snprintf(dfu_string, 32, "mmc 0=u-boot.bin part %d %d", devnum, partnum);
> break;
> default:
> - debug("Unsupported storage uclass: %d\n", desc->uclass_id);
> + debug("Unsupported storage uclass: %d\n", dev_uclass);
> return;
> }
> - log_debug("boot partition is %s, DFU string: '%s'\n", name, dfu_string);
> + log_debug("DFU string: '%s'\n", dfu_string);
>
> update_info.dfu_string = dfu_string;
> }
>
The logic is complex but looks to be good.
What would happen if we plug an eMMC with conflicting partitions names ?
Is there a way to get the boot media from xBL ?
Anyway, with the typo fix:
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Neil
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods
2025-03-26 17:40 ` [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods Caleb Connolly
2025-04-01 8:45 ` Neil Armstrong
@ 2025-04-01 12:42 ` Ilias Apalodimas
2025-04-03 12:47 ` Caleb Connolly
1 sibling, 1 reply; 16+ messages in thread
From: Ilias Apalodimas @ 2025-04-01 12:42 UTC (permalink / raw)
To: Caleb Connolly
Cc: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Neil Armstrong,
Sumit Garg, u-boot, u-boot-qcom
Hi Caleb
On Wed, 26 Mar 2025 at 19:41, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>
> Expand capsule update support to correctly identify which partition
> U-Boot is flashed to (between xbl, uefi, and boot including A/B
> variants).
>
> Use qcom_boot_source to determine if we were chainloaded from ABL,
> meaning U-Boot is on the boot partition, otherwise we assume uefi if
> it's available, finally leaving the xbl partition.
>
> Set a different fw_name based on the target partition to prevent GUID
> collisions, since a board may support U-Boot flashed to boot or XBL we
> need to differentiate them since the U-Boot binary must be built
> differently.
>
[...]
> - if (!strncmp(info.name, partname, strlen(partname))) {
> - log_debug("Found active %s partition: '%s'!\n", partname, info.name);
> - strlcpy(name, info.name, sizeof(info.name));
> - return partnum;
> + desc = dev_get_uclass_plat(dev);
> + if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
> + continue;
> + for (partnum = 1;; partnum++) {
> + ret = part_get_info(desc, partnum, &info);
> + if (ret)
> + break;
> +
> + slot_status = (struct part_slot_status *)&info.type_flags;
> +
> + /*
> + * Qualcomm Linux devices have a "uefi" partition, it's A/B but the
> + * flags might not be set so we assume the A partition unless the B
> + * partition is active.
> + */
> + if (!strncmp(info.name, "uefi", strlen("uefi")))
since it's a static string, use sizeof() to compute it at build time.
I get what you are trying to do here and automatically detect the boot
partition, I'll have a closer look in case we can somehow make this
loop shorter.
{
> + /*
> + * If U-Boot was chainloaded somehow we can't be flashed to
> + * the uefi partition
> + */
> + if (qcom_boot_source != QCOM_BOOT_SOURCE_XBL)
> + continue;
> +
> + *target_part_type = TARGET_PART_UEFI;
> + /*
> + * Found an active UEFI partition, this is where U-Boot is
> + * flashed.
> + */
> + if (slot_status->active)
> + goto found;
> +
> + /* Prefer A slot if it's not marked active */
> + if (get_part_slot(info.name) == SLOT_A) {
SLOT_NONE only applies to non-uefi partitions?
> + /*
> + * If we found the A slot after the B slot (both
> + * inactive) then we assume U-Boot is on the A slot.
> + */
> + if (uefi_partnum >= 0)
> + goto found;
> +
> + /* Didn't find the B slot yet */
> + uefi_partnum = partnum;
> + strlcpy(ptn_name, info.name, 32);
sizeof(ptn_name)
> + } else {
> + /*
> + * Found inactive B slot after inactive A slot, return
> + * the A slot
> + */
> + if (uefi_partnum >= 0) {
> + partnum = uefi_partnum;
> + goto found;
> + }
> +
> + /*
> + * Didn't find the A slot yet. Record that we found the
> + * B slot
[...]
Cheers
/Ilias
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods
2025-04-01 12:42 ` Ilias Apalodimas
@ 2025-04-03 12:47 ` Caleb Connolly
0 siblings, 0 replies; 16+ messages in thread
From: Caleb Connolly @ 2025-04-03 12:47 UTC (permalink / raw)
To: Ilias Apalodimas
Cc: Lukasz Majewski, Mattijs Korpershoek, Tom Rini, Neil Armstrong,
Sumit Garg, u-boot, u-boot-qcom
On 4/1/25 14:42, Ilias Apalodimas wrote:
> Hi Caleb
>
> On Wed, 26 Mar 2025 at 19:41, Caleb Connolly <caleb.connolly@linaro.org> wrote:
>>
>> Expand capsule update support to correctly identify which partition
>> U-Boot is flashed to (between xbl, uefi, and boot including A/B
>> variants).
>>
>> Use qcom_boot_source to determine if we were chainloaded from ABL,
>> meaning U-Boot is on the boot partition, otherwise we assume uefi if
>> it's available, finally leaving the xbl partition.
>>
>> Set a different fw_name based on the target partition to prevent GUID
>> collisions, since a board may support U-Boot flashed to boot or XBL we
>> need to differentiate them since the U-Boot binary must be built
>> differently.
>>
>
> [...]
>
>
>> - if (!strncmp(info.name, partname, strlen(partname))) {
>> - log_debug("Found active %s partition: '%s'!\n", partname, info.name);
>> - strlcpy(name, info.name, sizeof(info.name));
>> - return partnum;
>> + desc = dev_get_uclass_plat(dev);
>> + if (!desc || desc->part_type == PART_TYPE_UNKNOWN)
>> + continue;
>> + for (partnum = 1;; partnum++) {
>> + ret = part_get_info(desc, partnum, &info);
>> + if (ret)
>> + break;
>> +
>> + slot_status = (struct part_slot_status *)&info.type_flags;
>> +
>> + /*
>> + * Qualcomm Linux devices have a "uefi" partition, it's A/B but the
>> + * flags might not be set so we assume the A partition unless the B
>> + * partition is active.
>> + */
>> + if (!strncmp(info.name, "uefi", strlen("uefi")))
>
> since it's a static string, use sizeof() to compute it at build time.
Ahh nice, I'll do that.
> I get what you are trying to do here and automatically detect the boot
> partition, I'll have a closer look in case we can somehow make this
> loop shorter.
>
> {
>> + /*
>> + * If U-Boot was chainloaded somehow we can't be flashed to
>> + * the uefi partition
>> + */
>> + if (qcom_boot_source != QCOM_BOOT_SOURCE_XBL)
>> + continue;
>> +
>> + *target_part_type = TARGET_PART_UEFI;
>> + /*
>> + * Found an active UEFI partition, this is where U-Boot is
>> + * flashed.
>> + */
>> + if (slot_status->active)
>> + goto found;
>> +
>> + /* Prefer A slot if it's not marked active */
>> + if (get_part_slot(info.name) == SLOT_A) {
>
> SLOT_NONE only applies to non-uefi partitions?
Yes, having a "uefi" partition is only the case on 2 boards that I'm
aware of, and both have a/b variants. The xbl and boot partitions exist
on A/B and non-A/B devices so we have to handle all variants there.
>
>> + /*
>> + * If we found the A slot after the B slot (both
>> + * inactive) then we assume U-Boot is on the A slot.
>> + */
>> + if (uefi_partnum >= 0)
>> + goto found;
>> +
>> + /* Didn't find the B slot yet */
>> + uefi_partnum = partnum;
>> + strlcpy(ptn_name, info.name, 32);
>
> sizeof(ptn_name)
Thanks
>
>> + } else {
>> + /*
>> + * Found inactive B slot after inactive A slot, return
>> + * the A slot
>> + */
>> + if (uefi_partnum >= 0) {
>> + partnum = uefi_partnum;
>> + goto found;
>> + }
>> +
>> + /*
>> + * Didn't find the A slot yet. Record that we found the
>> + * B slot
>
> [...]
>
> Cheers
> /Ilias
--
Caleb (they/them)
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods
2025-04-01 8:45 ` Neil Armstrong
@ 2025-04-11 14:48 ` Caleb Connolly
0 siblings, 0 replies; 16+ messages in thread
From: Caleb Connolly @ 2025-04-11 14:48 UTC (permalink / raw)
To: neil.armstrong, Lukasz Majewski, Mattijs Korpershoek, Tom Rini,
Sumit Garg
Cc: u-boot, u-boot-qcom
Hi Neil,
> The logic is complex but looks to be good.
>
> What would happen if we plug an eMMC with conflicting partitions names ?
That would cause issues... Probably the more correct way to do things
here would be to use part UUIDs, but it's not clear how consistent those
are.
>
> Is there a way to get the boot media from xBL ?
In the chainloaded case we could i think map some DT path from the
kernel cmdline to the boot device, but I think just checking that if we
have SCSI then the partition we find MUST be on a SCSI device would be
enough.
In the non-chainloaded case, we actually do get handed a pointer to a
shared data structure from sbl1 which has all kinds of goodies in but
the whole thing is proprietary :(
>
> Anyway, with the typo fix:
Ack, seems like the 'z' is how U-Boot tends to do it, though it pains me
so :P
> Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Thanks>
> Neil
--
Caleb (they/them)
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2025-04-11 14:48 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-26 17:40 [PATCH 0/4] Qualcomm: expand capsule update support Caleb Connolly
2025-03-26 17:40 ` [PATCH 1/4] mach-snapdragon: track boot source Caleb Connolly
2025-03-31 13:52 ` Neil Armstrong
2025-03-26 17:40 ` [PATCH 2/4] mach-snapdragon: CapsuleUpdate: support all boot methods Caleb Connolly
2025-04-01 8:45 ` Neil Armstrong
2025-04-11 14:48 ` Caleb Connolly
2025-04-01 12:42 ` Ilias Apalodimas
2025-04-03 12:47 ` Caleb Connolly
2025-03-26 17:40 ` [PATCH 3/4] dfu: scsi: don't call scsi_scan() Caleb Connolly
2025-03-31 13:52 ` Neil Armstrong
2025-03-31 13:53 ` Ilias Apalodimas
2025-03-26 17:40 ` [PATCH 4/4] qcom_defconfig: enable capsule update support Caleb Connolly
2025-03-27 8:46 ` Peng Fan
2025-03-27 12:30 ` Caleb Connolly
2025-03-31 13:52 ` Ilias Apalodimas
2025-03-26 17:44 ` [PATCH 0/4] Qualcomm: expand " Caleb Connolly
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox