typedef struct InstallParameters {
InstallContext context;
unsigned root_fd_index;
+ char *esp_path;
+ char *xbootldr_path;
} InstallParameters;
static void install_parameters_done(InstallParameters *p) {
assert(p);
install_context_done(&p->context);
+ free(p->esp_path);
+ free(p->xbootldr_path);
}
int vl_method_install(
{ "graceful", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, voffsetof(p, context.graceful), 0 },
{ "rootFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, voffsetof(p, root_fd_index), 0 },
{ "rootDirectory", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, context.root), 0 },
+ { "espPath", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, esp_path), 0 },
+ { "xbootldrPath", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, xbootldr_path), 0 },
{ "bootEntryTokenType", SD_JSON_VARIANT_STRING, json_dispatch_boot_entry_token_type, voffsetof(p, context.entry_token_type), 0 },
{ "touchVariables", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_tristate, voffsetof(p, context.touch_variables), 0 },
{},
r = find_esp_and_warn_at_full(
p.context.root_fd,
- /* path= */ NULL,
+ p.esp_path,
/* unprivileged_mode= */ false,
&p.context.esp_path,
&p.context.esp_fd,
r = find_xbootldr_and_warn_at(
p.context.root_fd,
- /* path= */ NULL,
+ p.xbootldr_path,
/* unprivileged_mode= */ false,
&p.context.xbootldr_path,
&p.context.xbootldr_fd);
LinkContext context;
unsigned root_fd_index;
unsigned kernel_fd_index;
+ char *esp_path;
+ char *xbootldr_path;
sd_varlink *link;
} LinkParameters;
assert(p);
link_context_done(&p->context);
+ free(p->esp_path);
+ free(p->xbootldr_path);
}
typedef struct ExtraParameters {
r = find_xbootldr_and_warn_at(
p->context.root_fd,
- /* path= */ NULL,
+ p->xbootldr_path,
/* unprivileged_mode= */ false,
&p->context.dollar_boot_path,
&p->context.dollar_boot_fd);
r = find_esp_and_warn_at(
p->context.root_fd,
- /* path= */ NULL,
+ p->esp_path,
/* unprivileged_mode= */ false,
&p->context.dollar_boot_path,
&p->context.dollar_boot_fd);
static const sd_json_dispatch_field dispatch_table[] = {
{ "rootFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, voffsetof(p, root_fd_index), 0 },
{ "rootDirectory", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, context.root), 0 },
+ { "espPath", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, esp_path), 0 },
+ { "xbootldrPath", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, xbootldr_path), 0 },
{ "bootEntryTokenType", SD_JSON_VARIANT_STRING, json_dispatch_boot_entry_token_type, voffsetof(p, context.entry_token_type), 0 },
{ "entryTitle", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, voffsetof(p, context.entry_title), 0 },
{ "entryVersion", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, voffsetof(p, context.entry_version), 0 },
static const sd_json_dispatch_field dispatch_table[] = {
{ "rootFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, voffsetof(p, root_fd_index), 0 },
{ "rootDirectory", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, context.root), 0 },
+ { "espPath", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, esp_path), 0 },
+ { "xbootldrPath", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, xbootldr_path), 0 },
{ "bootEntryTokenType", SD_JSON_VARIANT_STRING, json_dispatch_boot_entry_token_type, voffsetof(p, context.entry_token_type), 0 },
{ "entryTitle", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, voffsetof(p, context.entry_title), 0 },
{ "entryVersion", SD_JSON_VARIANT_STRING, sd_json_dispatch_string, voffsetof(p, context.entry_version), 0 },
typedef struct UnlinkParameters {
UnlinkContext context;
unsigned root_fd_index;
+ char *esp_path;
+ char *xbootldr_path;
const char *id;
bool oldest;
} UnlinkParameters;
assert(p);
unlink_context_done(&p->context);
+ free(p->esp_path);
+ free(p->xbootldr_path);
}
int vl_method_unlink(
static const sd_json_dispatch_field dispatch_table[] = {
{ "rootFileDescriptor", _SD_JSON_VARIANT_TYPE_INVALID, sd_json_dispatch_uint, voffsetof(p, root_fd_index), 0 },
{ "rootDirectory", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, context.root), 0 },
+ { "espPath", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, esp_path), 0 },
+ { "xbootldrPath", SD_JSON_VARIANT_STRING, json_dispatch_path, voffsetof(p, xbootldr_path), 0 },
{ "bootEntryTokenType", SD_JSON_VARIANT_STRING, json_dispatch_boot_entry_token_type, voffsetof(p, context.entry_token_type), 0 },
{ "id", SD_JSON_VARIANT_STRING, sd_json_dispatch_const_string, voffsetof(p, id), 0 },
{ "oldest", SD_JSON_VARIANT_BOOLEAN, sd_json_dispatch_stdbool, voffsetof(p, oldest), 0 },
r = find_esp_and_warn_at_full(
p.context.root_fd,
- /* path= */ NULL,
+ p.esp_path,
/* unprivileged_mode= */ false,
&p.context.esp_path,
&p.context.esp_fd,
return r;
r = find_xbootldr_and_warn_at_full(
p.context.root_fd,
- /* path= */ NULL,
+ p.xbootldr_path,
/* unprivileged_mode= */ false,
&p.context.xbootldr_path,
&p.context.xbootldr_fd,
SD_VARLINK_DEFINE_INPUT(rootFileDescriptor, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Root directory to operate relative to. If both this and rootFileDescriptor is specified, this is purely informational. If only this is specified, it is what will be used."),
SD_VARLINK_DEFINE_INPUT(rootDirectory, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path to the EFI System Partition mount point, resolved relative to rootDirectory/rootFileDescriptor if either is set. If not specified the ESP is auto-discovered."),
+ SD_VARLINK_DEFINE_INPUT(espPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path to the XBOOTLDR partition mount point, resolved relative to rootDirectory/rootFileDescriptor if either is set. If not specified the XBOOTLDR partition is auto-discovered."),
+ SD_VARLINK_DEFINE_INPUT(xbootldrPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Selects how to identify boot entries"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(bootEntryTokenType, BootEntryTokenType, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("If true the boot loader will be registered in an EFI boot entry via EFI variables, otherwise this is omitted"),
SD_VARLINK_DEFINE_INPUT(rootFileDescriptor, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Root directory to operate relative to. If both this and rootFileDescriptor is specified, this is purely informational. If only this is specified, it is what will be used."),
SD_VARLINK_DEFINE_INPUT(rootDirectory, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path to the EFI System Partition mount point, resolved relative to rootDirectory/rootFileDescriptor if either is set. If not specified the ESP is auto-discovered."),
+ SD_VARLINK_DEFINE_INPUT(espPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path to the XBOOTLDR partition mount point, resolved relative to rootDirectory/rootFileDescriptor if either is set. If not specified the XBOOTLDR partition is auto-discovered."),
+ SD_VARLINK_DEFINE_INPUT(xbootldrPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Selects how to identify boot entries"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(bootEntryTokenType, BootEntryTokenType, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The ID of the boot loader entry to remove."),
SD_VARLINK_DEFINE_INPUT(rootFileDescriptor, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Root directory to operate relative to. If both this and rootFileDescriptor is specified, this is purely informational. If only this is specified, it is what will be used."),
SD_VARLINK_DEFINE_INPUT(rootDirectory, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path to the EFI System Partition mount point, resolved relative to rootDirectory/rootFileDescriptor if either is set. If not specified the ESP is auto-discovered."),
+ SD_VARLINK_DEFINE_INPUT(espPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path to the XBOOTLDR partition mount point, resolved relative to rootDirectory/rootFileDescriptor if either is set. If not specified the XBOOTLDR partition is auto-discovered."),
+ SD_VARLINK_DEFINE_INPUT(xbootldrPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Selects how to identify boot entries"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(bootEntryTokenType, BootEntryTokenType, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The entry title for the newly created boot menu entry"),
SD_VARLINK_DEFINE_INPUT(rootFileDescriptor, SD_VARLINK_INT, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Root directory to operate relative to. If both this and rootFileDescriptor is specified, this is purely informational. If only this is specified, it is what will be used."),
SD_VARLINK_DEFINE_INPUT(rootDirectory, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path to the EFI System Partition mount point, resolved relative to rootDirectory/rootFileDescriptor if either is set. If not specified the ESP is auto-discovered."),
+ SD_VARLINK_DEFINE_INPUT(espPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
+ SD_VARLINK_FIELD_COMMENT("Path to the XBOOTLDR partition mount point, resolved relative to rootDirectory/rootFileDescriptor if either is set. If not specified the XBOOTLDR partition is auto-discovered."),
+ SD_VARLINK_DEFINE_INPUT(xbootldrPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("Selects how to identify boot entries"),
SD_VARLINK_DEFINE_INPUT_BY_TYPE(bootEntryTokenType, BootEntryTokenType, SD_VARLINK_NULLABLE),
SD_VARLINK_FIELD_COMMENT("The entry title for the newly created boot menu entry"),
rm -rf "$ROOTDIR"
}
+cleanup_install_varlink() {
+ if [[ -n "${FAKE_ESP:-}" ]]; then
+ rm -rf "$FAKE_ESP"
+ unset FAKE_ESP
+ fi
+ if [[ -n "${FAKE_BOOT:-}" ]]; then
+ rm -rf "$FAKE_BOOT"
+ unset FAKE_BOOT
+ fi
+ restore_esp
+}
+
testcase_install_varlink() {
varlinkctl introspect "$(type -p bootctl)"
if [ $# -eq 0 ]; then
backup_esp
- trap restore_esp RETURN ERR
+ trap cleanup_install_varlink RETURN ERR
fi
(! bootctl is-installed )
SYSTEMD_LOG_TARGET=console varlinkctl call "$(type -p bootctl)" io.systemd.BootControl.Install "{\"operation\":\"new\",\"touchVariables\":false}"
bootctl is-installed
+
+ # Verify that espPath/xbootldrPath override auto-discovery: install into fresh empty
+ # directories (with relaxed checks so verify_esp()/verify_xbootldr() accept a non-vfat
+ # non-mountpoint path) and check the loader files land there. If the parameters were ignored
+ # the call would auto-discover the real partitions instead and the directories would stay
+ # empty.
+ FAKE_ESP="$(mktemp --directory /tmp/test-bootctl-esp.XXXXXXXXXX)"
+ FAKE_BOOT="$(mktemp --directory /tmp/test-bootctl-boot.XXXXXXXXXX)"
+ SYSTEMD_RELAX_ESP_CHECKS=yes SYSTEMD_RELAX_XBOOTLDR_CHECKS=yes SYSTEMD_LOG_TARGET=console \
+ varlinkctl call --quiet "$(type -p bootctl)" io.systemd.BootControl.Install \
+ "{\"operation\":\"new\",\"touchVariables\":false,\"espPath\":\"$FAKE_ESP\",\"xbootldrPath\":\"$FAKE_BOOT\"}"
+ test -f "$FAKE_ESP/EFI/systemd/systemd-boot$(bootctl --print-efi-architecture).efi"
+ test -f "$FAKE_BOOT/loader/entries.srel"
}
cleanup_link() {