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 <caleb@connolly.tech>
This commit is contained in:
Caleb Connolly 2023-09-27 18:56:43 +01:00
parent 3390f642e3
commit b8d2248914
No known key found for this signature in database
GPG Key ID: 7930459FB9303217
6 changed files with 28 additions and 22 deletions

View File

@ -34,6 +34,7 @@ qbootctl [-c|-m|-s|-u|-b|-n|-x] [SLOT]
-s SLOT set to active slot to SLOT -s SLOT set to active slot to SLOT
-m [SLOT] mark a boot as successful (default: current) -m [SLOT] mark a boot as successful (default: current)
-u [SLOT] mark SLOT as unbootable (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 ## Debugging

View File

@ -69,7 +69,7 @@ struct boot_control_module {
* setSlotAsUnbootable. * setSlotAsUnbootable.
* Returns 0 on success, -errno on error. * 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 * (*setSlotAsUnbootable)() marks the slot passed in parameter as

View File

@ -560,7 +560,7 @@ unsigned get_active_boot_slot()
return 0; 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; enum boot_chain chain = (enum boot_chain)slot;
struct gpt_disk disk = { 0 }; struct gpt_disk disk = { 0 };
@ -576,7 +576,7 @@ int set_active_boot_slot(unsigned slot)
// Do this *before* updating all the slot attributes // Do this *before* updating all the slot attributes
// to make sure we can // to make sure we can
if (!ismmc && ufs_bsg_dev_open() < 0) { if (!ismmc && !ignore_missing_bsg && ufs_bsg_dev_open() < 0) {
return -1; return -1;
} }
@ -599,8 +599,10 @@ int set_active_boot_slot(unsigned slot)
rc = gpt_utils_set_xbl_boot_partition(chain); rc = gpt_utils_set_xbl_boot_partition(chain);
if (rc) { if (rc) {
fprintf(stderr, "%s: Failed to switch xbl boot partition\n", __func__); if (ignore_missing_bsg && rc == -ENODEV)
goto out; rc = 0;
else
fprintf(stderr, "%s: Failed to switch xbl boot partition\n", __func__);
} }
out: out:

View File

@ -216,7 +216,7 @@ static uint8_t *gpt_pentry_seek(const char *ptn_name, const uint8_t *pentries_st
// Defined in ufs-bsg.cpp // Defined in ufs-bsg.cpp
int32_t set_boot_lun(uint8_t lun_id); 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 // boot LUN for boot. This is required since UFS boot partitions
// cannot have a backup GPT which is what we use for failsafe // cannot have a backup GPT which is what we use for failsafe
// updates of the other 'critical' partitions. This function will // 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; struct stat st;
uint8_t boot_lun_id = 0; uint8_t boot_lun_id = 0;
const char *boot_dev = NULL; const char *boot_dev = NULL;
int ret = -1;
(void)st; (void)st;
(void)boot_dev; (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); LOGD("%s: setting %s lun as boot lun\n", __func__, boot_dev);
if (set_boot_lun(boot_lun_id)) { if (set_boot_lun(boot_lun_id)) {
ret = -ENODEV;
goto error; goto error;
} }
return 0; return 0;
error: error:
return -1; return ret;
} }
// Given a parttion name(eg: rpm) get the path to the block device that // Given a parttion name(eg: rpm) get the path to the block device that

View File

@ -74,6 +74,7 @@ fail:
int usage() int usage()
{ {
// clang-format off
fprintf(stderr, "qbootctl: qcom bootctrl HAL port for Linux\n"); fprintf(stderr, "qbootctl: qcom bootctrl HAL port for Linux\n");
fprintf(stderr, "-------------------------------------------\n"); fprintf(stderr, "-------------------------------------------\n");
fprintf(stderr, "qbootctl [-c|-m|-s|-u|-b|-n|-x] [SLOT]\n\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, " -h this help text\n");
fprintf(stderr, " -c get the current slot\n"); fprintf(stderr, " -c get the current slot\n");
fprintf(stderr, " -a get the active slot\n"); fprintf(stderr, " -a get the active slot\n");
fprintf(stderr, fprintf(stderr, " -b SLOT check if SLOT is marked as bootable\n");
" -b SLOT check if SLOT is marked as bootable\n"); fprintf(stderr, " -n SLOT check if SLOT is marked as successful\n");
fprintf(stderr, fprintf(stderr, " -x [SLOT] get the slot suffix for SLOT (default: current)\n");
" -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, " -s SLOT set to active slot to SLOT\n");
fprintf(stderr, fprintf(stderr, " -m [SLOT] mark a boot as successful (default: current)\n");
" -m [SLOT] mark a boot as successful (default: current)\n"); fprintf(stderr, " -u [SLOT] mark SLOT as unbootable (default: current)\n");
fprintf(stderr, fprintf(stderr, " -i still write the GPT headers even if the UFS bLun can't be changed (default: false)\n");
" -u [SLOT] mark SLOT as unbootable (default: current)\n"); // clang-format on
return 1; return 1;
} }
@ -139,6 +137,7 @@ int main(int argc, char **argv)
int optflag; int optflag;
int slot = -1; int slot = -1;
int rc; int rc;
bool ignore_missing_bsg = false;
if(geteuid() != 0) { if(geteuid() != 0) {
fprintf(stderr, "This program must be run as root!\n"); 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)); printf("%s\n", impl->getSuffix(slot));
return 0; return 0;
case 's': case 's':
rc = impl->setActiveBootSlot(slot); rc = impl->setActiveBootSlot(slot, ignore_missing_bsg);
if (rc < 0) { if (rc < 0) {
fprintf(stderr, "SLOT %s: Failed to set active\n", fprintf(stderr, "SLOT %s: Failed to set active\n",
impl->getSuffix(slot)); impl->getSuffix(slot));
@ -210,6 +209,9 @@ int main(int argc, char **argv)
} }
printf("SLOT %s: Set as unbootable\n", impl->getSuffix(slot)); printf("SLOT %s: Set as unbootable\n", impl->getSuffix(slot));
return 0; return 0;
case 'i':
ignore_missing_bsg = true;
break;
case 'h': case 'h':
default: default:
usage(); usage();

View File

@ -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, 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, QUERY_REQ_OP_WRITE_ATTR, QUERY_ATTR_IDN_BOOT_LU_EN,
0, 0); 0, 0);
if (ret) { if (ret)
fprintf(stderr, fprintf(stderr,
"Error requesting ufs attr idn %d via query ioctl (return value: %d, error no: %d)", "Error requesting ufs attr idn %d via query ioctl (return value: %d, error no: %d)",
QUERY_ATTR_IDN_BOOT_LU_EN, ret, errno); QUERY_ATTR_IDN_BOOT_LU_EN, ret, errno);
goto out;
}
out:
ufs_bsg_dev_close(); ufs_bsg_dev_close();
return ret; return ret;
} }