bootctl: add after_slot parameter to insert_into_order()

This adds an after_slot parameter that, when not set to UINT16_MAX,
requests that the new slot be placed immediately after the given slot in
BootOrder. When after_slot is set and the new slot already exists in
BootOrder, it will leave its position alone. This is so that if a user
reorders it, we don't stomp on their changes.
This commit is contained in:
Clayton Craft
2026-05-21 11:26:59 -07:00
parent bb520fd6a5
commit 6c356b6a8b
+25 -3
View File
@@ -1233,7 +1233,7 @@ static int find_slot(sd_id128_t uuid, const char *path, uint16_t *id) {
return 0;
}
static int insert_into_order(InstallContext *c, uint16_t slot) {
static int insert_into_order(InstallContext *c, uint16_t slot, uint16_t after_slot) {
_cleanup_free_ uint16_t *order = NULL;
uint16_t *t;
int n;
@@ -1255,7 +1255,8 @@ static int insert_into_order(InstallContext *c, uint16_t slot) {
continue;
/* we do not require to be the first one, all is fine */
if (c->operation != INSTALL_NEW)
/* if after_slot is set, leave existing position alone to preserve user reordering. */
if (i == 0 || c->operation != INSTALL_NEW || after_slot != UINT16_MAX)
return 0;
/* move us to the first slot */
@@ -1264,6 +1265,27 @@ static int insert_into_order(InstallContext *c, uint16_t slot) {
return efi_set_boot_order(order, n);
}
/* slot is not yet in the order, so insert after a specific slot if requested */
if (after_slot != UINT16_MAX) {
t = reallocarray(order, n + 1, sizeof(uint16_t));
if (!t)
return -ENOMEM;
order = t;
for (int i = 0; i < n; i++) {
if (order[i] != after_slot)
continue;
memmove(order + i + 2, order + i + 1, (n - i - 1) * sizeof(uint16_t));
order[i + 1] = slot;
return efi_set_boot_order(order, n + 1);
}
log_warning("Boot entry %04" PRIx16 " not found in BootOrder, appending new entry at the end.", after_slot);
order[n] = slot;
return efi_set_boot_order(order, n + 1);
}
/* extend array */
t = reallocarray(order, n + 1, sizeof(uint16_t));
if (!t)
@@ -1422,7 +1444,7 @@ static int install_boot_option(
description);
}
r = insert_into_order(c, slot);
r = insert_into_order(c, slot, /* after_slot= */ UINT16_MAX);
if (r < 0)
return r;