From b8d22489141b2904dd1ab3d18912876b6dbe8284 Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Wed, 27 Sep 2023 18:56:43 +0100 Subject: [PATCH] add a flag to continue when ufs bsg device is missing For some usecases it is desired to still update the GPT headers even if the UFS BSG device is missing. Add a new flag which implements this behaviour. It isn't made the default because on some platforms this could result in an unbootable device, there it's preferable to defer to the user by just bailing out if the UFS BSG device is unavailable. Signed-off-by: Caleb Connolly --- README.md | 1 + bootctrl.h | 2 +- bootctrl_impl.c | 10 ++++++---- gpt-utils.c | 6 ++++-- qbootctl.c | 24 +++++++++++++----------- ufs-bsg.c | 7 +++---- 6 files changed, 28 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index e20b9fa..36fdd45 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,7 @@ qbootctl [-c|-m|-s|-u|-b|-n|-x] [SLOT] -s SLOT set to active slot to SLOT -m [SLOT] mark a boot as successful (default: current) -u [SLOT] mark SLOT as unbootable (default: current) + -i still write the GPT headers even if the UFS bLun can't be changed (default: false) ``` ## Debugging diff --git a/bootctrl.h b/bootctrl.h index 1489c5f..beb9d23 100644 --- a/bootctrl.h +++ b/bootctrl.h @@ -69,7 +69,7 @@ struct boot_control_module { * setSlotAsUnbootable. * Returns 0 on success, -errno on error. */ - int (*setActiveBootSlot)(unsigned slot); + int (*setActiveBootSlot)(unsigned slot, bool ignore_missing_bsg); /* * (*setSlotAsUnbootable)() marks the slot passed in parameter as diff --git a/bootctrl_impl.c b/bootctrl_impl.c index 04d5f59..05876f6 100644 --- a/bootctrl_impl.c +++ b/bootctrl_impl.c @@ -560,7 +560,7 @@ unsigned get_active_boot_slot() return 0; } -int set_active_boot_slot(unsigned slot) +int set_active_boot_slot(unsigned slot, bool ignore_missing_bsg) { enum boot_chain chain = (enum boot_chain)slot; struct gpt_disk disk = { 0 }; @@ -576,7 +576,7 @@ int set_active_boot_slot(unsigned slot) // Do this *before* updating all the slot attributes // to make sure we can - if (!ismmc && ufs_bsg_dev_open() < 0) { + if (!ismmc && !ignore_missing_bsg && ufs_bsg_dev_open() < 0) { return -1; } @@ -599,8 +599,10 @@ int set_active_boot_slot(unsigned slot) rc = gpt_utils_set_xbl_boot_partition(chain); if (rc) { - fprintf(stderr, "%s: Failed to switch xbl boot partition\n", __func__); - goto out; + if (ignore_missing_bsg && rc == -ENODEV) + rc = 0; + else + fprintf(stderr, "%s: Failed to switch xbl boot partition\n", __func__); } out: diff --git a/gpt-utils.c b/gpt-utils.c index 097fede..b0fda61 100644 --- a/gpt-utils.c +++ b/gpt-utils.c @@ -216,7 +216,7 @@ static uint8_t *gpt_pentry_seek(const char *ptn_name, const uint8_t *pentries_st // Defined in ufs-bsg.cpp int32_t set_boot_lun(uint8_t lun_id); - // Swtich betwieen using either the primary or the backup +// Switch between using either the primary or the backup // boot LUN for boot. This is required since UFS boot partitions // cannot have a backup GPT which is what we use for failsafe // updates of the other 'critical' partitions. This function will @@ -238,6 +238,7 @@ int gpt_utils_set_xbl_boot_partition(enum boot_chain chain) struct stat st; uint8_t boot_lun_id = 0; const char *boot_dev = NULL; + int ret = -1; (void)st; (void)boot_dev; @@ -277,11 +278,12 @@ int gpt_utils_set_xbl_boot_partition(enum boot_chain chain) LOGD("%s: setting %s lun as boot lun\n", __func__, boot_dev); if (set_boot_lun(boot_lun_id)) { + ret = -ENODEV; goto error; } return 0; error: - return -1; + return ret; } // Given a parttion name(eg: rpm) get the path to the block device that diff --git a/qbootctl.c b/qbootctl.c index c0769f4..463ff25 100644 --- a/qbootctl.c +++ b/qbootctl.c @@ -74,6 +74,7 @@ fail: int usage() { + // clang-format off fprintf(stderr, "qbootctl: qcom bootctrl HAL port for Linux\n"); fprintf(stderr, "-------------------------------------------\n"); fprintf(stderr, "qbootctl [-c|-m|-s|-u|-b|-n|-x] [SLOT]\n\n"); @@ -81,17 +82,14 @@ int usage() fprintf(stderr, " -h this help text\n"); fprintf(stderr, " -c get the current slot\n"); fprintf(stderr, " -a get the active slot\n"); - fprintf(stderr, - " -b SLOT check if SLOT is marked as bootable\n"); - fprintf(stderr, - " -n SLOT check if SLOT is marked as successful\n"); - fprintf(stderr, - " -x [SLOT] get the slot suffix for SLOT (default: current)\n"); + fprintf(stderr, " -b SLOT check if SLOT is marked as bootable\n"); + fprintf(stderr, " -n SLOT check if SLOT is marked as successful\n"); + fprintf(stderr, " -x [SLOT] get the slot suffix for SLOT (default: current)\n"); fprintf(stderr, " -s SLOT set to active slot to SLOT\n"); - fprintf(stderr, - " -m [SLOT] mark a boot as successful (default: current)\n"); - fprintf(stderr, - " -u [SLOT] mark SLOT as unbootable (default: current)\n"); + fprintf(stderr, " -m [SLOT] mark a boot as successful (default: current)\n"); + fprintf(stderr, " -u [SLOT] mark SLOT as unbootable (default: current)\n"); + fprintf(stderr, " -i still write the GPT headers even if the UFS bLun can't be changed (default: false)\n"); + // clang-format on return 1; } @@ -139,6 +137,7 @@ int main(int argc, char **argv) int optflag; int slot = -1; int rc; + bool ignore_missing_bsg = false; if(geteuid() != 0) { fprintf(stderr, "This program must be run as root!\n"); @@ -185,7 +184,7 @@ int main(int argc, char **argv) printf("%s\n", impl->getSuffix(slot)); return 0; case 's': - rc = impl->setActiveBootSlot(slot); + rc = impl->setActiveBootSlot(slot, ignore_missing_bsg); if (rc < 0) { fprintf(stderr, "SLOT %s: Failed to set active\n", impl->getSuffix(slot)); @@ -210,6 +209,9 @@ int main(int argc, char **argv) } printf("SLOT %s: Set as unbootable\n", impl->getSuffix(slot)); return 0; + case 'i': + ignore_missing_bsg = true; + break; case 'h': default: usage(); diff --git a/ufs-bsg.c b/ufs-bsg.c index 05c8885..22c8da8 100644 --- a/ufs-bsg.c +++ b/ufs-bsg.c @@ -174,13 +174,12 @@ int32_t set_boot_lun(__u8 lun_id) ret = ufs_query_attr(fd_ufs_bsg, boot_lun_id, QUERY_REQ_FUNC_STD_WRITE, QUERY_REQ_OP_WRITE_ATTR, QUERY_ATTR_IDN_BOOT_LU_EN, 0, 0); - if (ret) { + if (ret) fprintf(stderr, "Error requesting ufs attr idn %d via query ioctl (return value: %d, error no: %d)", QUERY_ATTR_IDN_BOOT_LU_EN, ret, errno); - goto out; - } -out: + + ufs_bsg_dev_close(); return ret; }