With this we can now do: systemd-vmspawn -n -i foobar.raw -s io.systemd.boot.entries-extra:particleos-current.conf=$'title ParticleOS Current\nuki-url http://example.com/somedir/uki.efi' Assuming sd-boot is available inside the ESP of foobar.raw a new item will show up in the boot menu that allows booting directly into the specified UKI.
This commit is contained in:
@@ -74,6 +74,16 @@
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>io.systemd.boot-entries.extra:</varname><replaceable>ID=DEFINITION</replaceable></term>
|
||||
|
||||
<listitem><para>This allows inserting additional entries into the <command>systemd-boot</command>
|
||||
menu. For details see
|
||||
<citerefentry><refentrytitle>systemd-boot</refentrytitle><manvolnum>7</manvolnum></citerefentry></para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
@@ -594,6 +594,28 @@
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>io.systemd.boot-entries.extra:</varname><replaceable>ID=DEFINITION</replaceable></term>
|
||||
|
||||
<listitem><para>This allows inserting additional entries into the <command>systemd-boot</command>
|
||||
menu. Take a pair of menu entry identifier and menu entry definition string. The former should be
|
||||
suitable for use as a filename of a Boot Loader Specification Type #1 entry filename (note that it is
|
||||
used for identification purposes only, no file of this name is actually accessed), the latter shall
|
||||
follow the syntax of the contents of a Type #1 entry. Any menu entry defined this way is processed
|
||||
and shown in pretty much the same way as a Type #1 entry read from the ESP or XBOOTLDR
|
||||
partition. Example:</para>
|
||||
|
||||
<programlisting>io.systemd.boot-entries.extra:fooos-current.conf=title FooOS (Current)
|
||||
uki-url http://example.com/somedir/fooos.efi</programlisting>
|
||||
|
||||
<para>Note that this example contains a newline character. When generating this string from a shell
|
||||
care must be taken to encode it correctly.</para>
|
||||
|
||||
<para>Pass multiple strings formatted this way to generate multiple menu entries.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</refsect1>
|
||||
|
||||
|
||||
+55
-8
@@ -1464,7 +1464,6 @@ static void boot_entry_add_type1(
|
||||
assert(config);
|
||||
assert(device);
|
||||
assert(root_dir);
|
||||
assert(path);
|
||||
assert(file);
|
||||
assert(content);
|
||||
|
||||
@@ -1607,7 +1606,8 @@ static void boot_entry_add_type1(
|
||||
|
||||
config_add_entry(config, entry);
|
||||
|
||||
boot_entry_parse_tries(entry, path, file, u".conf");
|
||||
if (path)
|
||||
boot_entry_parse_tries(entry, path, file, u".conf");
|
||||
TAKE_PTR(entry);
|
||||
}
|
||||
|
||||
@@ -1717,6 +1717,19 @@ static void config_load_defaults(Config *config, EFI_FILE *root_dir) {
|
||||
(void) efivar_get_str16(MAKE_GUID_PTR(LOADER), u"LoaderEntryLastBooted", &config->entry_saved);
|
||||
}
|
||||
|
||||
static bool valid_type1_filename(const char16_t *fname) {
|
||||
assert(fname);
|
||||
|
||||
if (IN_SET(fname[0], u'.', u'\0'))
|
||||
return false;
|
||||
if (!endswith_no_case(fname, u".conf"))
|
||||
return false;
|
||||
if (startswith_no_case(fname, u"auto-"))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void config_load_type1_entries(
|
||||
Config *config,
|
||||
EFI_HANDLE *device,
|
||||
@@ -1747,13 +1760,9 @@ static void config_load_type1_entries(
|
||||
if (err != EFI_SUCCESS || !f)
|
||||
break;
|
||||
|
||||
if (f->FileName[0] == '.')
|
||||
continue;
|
||||
if (FLAGS_SET(f->Attribute, EFI_FILE_DIRECTORY))
|
||||
continue;
|
||||
if (!endswith_no_case(f->FileName, u".conf"))
|
||||
continue;
|
||||
if (startswith_no_case(f->FileName, u"auto-"))
|
||||
if (!valid_type1_filename(f->FileName))
|
||||
continue;
|
||||
|
||||
err = file_read(entries_dir,
|
||||
@@ -1769,6 +1778,41 @@ static void config_load_type1_entries(
|
||||
}
|
||||
}
|
||||
|
||||
static void config_load_smbios_entries(
|
||||
Config *config,
|
||||
EFI_HANDLE *device,
|
||||
EFI_FILE *root_dir,
|
||||
const char16_t *loaded_image_path) {
|
||||
|
||||
assert(config);
|
||||
assert(device);
|
||||
assert(root_dir);
|
||||
|
||||
/* Loads Boot Loader Type #1 entries from SMBIOS 11 */
|
||||
|
||||
if (is_confidential_vm())
|
||||
return; /* Don't consume SMBIOS in CoCo contexts */
|
||||
|
||||
for (const char *after = NULL, *extra;; after = extra) {
|
||||
extra = smbios_find_oem_string("io.systemd.boot.entries-extra:", after);
|
||||
if (!extra)
|
||||
break;
|
||||
|
||||
const char *eq = strchr8(extra, '=');
|
||||
if (!eq)
|
||||
continue;
|
||||
|
||||
_cleanup_free_ char16_t *fname = xstrn8_to_16(extra, eq - extra);
|
||||
if (!valid_type1_filename(fname))
|
||||
continue;
|
||||
|
||||
/* Make a copy, since boot_entry_add_type1() wants to modify it */
|
||||
_cleanup_free_ char *contents = xstrdup8(eq + 1);
|
||||
|
||||
boot_entry_add_type1(config, device, root_dir, /* path= */ NULL, fname, contents, loaded_image_path);
|
||||
}
|
||||
}
|
||||
|
||||
static int boot_entry_compare(const BootEntry *a, const BootEntry *b) {
|
||||
int r;
|
||||
|
||||
@@ -2775,7 +2819,7 @@ static EFI_STATUS image_start(
|
||||
_cleanup_free_ char16_t *options = xstrdup16(options_initrd ?: entry->options_implied ? NULL : entry->options);
|
||||
|
||||
if (entry->type == LOADER_LINUX && !is_confidential_vm()) {
|
||||
const char *extra = smbios_find_oem_string("io.systemd.boot.kernel-cmdline-extra");
|
||||
const char *extra = smbios_find_oem_string("io.systemd.boot.kernel-cmdline-extra=", /* after= */ NULL);
|
||||
if (extra) {
|
||||
_cleanup_free_ char16_t *tmp = TAKE_PTR(options), *extra16 = xstr8_to_16(extra);
|
||||
if (isempty(tmp))
|
||||
@@ -2989,6 +3033,9 @@ static void config_load_all_entries(
|
||||
/* Similar, but on any XBOOTLDR partition */
|
||||
config_load_xbootldr(config, loaded_image->DeviceHandle);
|
||||
|
||||
/* Pick up entries defined via SMBIOS Type #11 */
|
||||
config_load_smbios_entries(config, loaded_image->DeviceHandle, root_dir, loaded_image_path);
|
||||
|
||||
/* Sort entries after version number */
|
||||
sort_pointer_array((void **) config->entries, config->n_entries, (compare_pointer_func_t) boot_entry_compare);
|
||||
|
||||
|
||||
+4
-4
@@ -182,7 +182,7 @@ bool smbios_in_hypervisor(void) {
|
||||
return FLAGS_SET(type0->bios_characteristics_ext[1], 1 << 4);
|
||||
}
|
||||
|
||||
const char* smbios_find_oem_string(const char *name) {
|
||||
const char* smbios_find_oem_string(const char *name, const char *after) {
|
||||
uint64_t left;
|
||||
|
||||
assert(name);
|
||||
@@ -199,9 +199,9 @@ const char* smbios_find_oem_string(const char *name) {
|
||||
if (!e || e == p) /* Double NUL byte means we've reached the end of the OEM strings. */
|
||||
break;
|
||||
|
||||
const char *eq = startswith8(p, name);
|
||||
if (eq && *eq == '=')
|
||||
return eq + 1;
|
||||
const char *suffix = startswith8(p, name);
|
||||
if (suffix && (!after || suffix > after))
|
||||
return suffix;
|
||||
|
||||
p = e + 1;
|
||||
}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
bool smbios_in_hypervisor(void);
|
||||
|
||||
const char* smbios_find_oem_string(const char *name);
|
||||
const char* smbios_find_oem_string(const char *name, const char *after);
|
||||
|
||||
typedef struct RawSmbiosInfo {
|
||||
const char *manufacturer;
|
||||
|
||||
+1
-1
@@ -783,7 +783,7 @@ static void cmdline_append_and_measure_smbios(char16_t **cmdline, int *parameter
|
||||
if (is_confidential_vm())
|
||||
return;
|
||||
|
||||
const char *extra = smbios_find_oem_string("io.systemd.stub.kernel-cmdline-extra");
|
||||
const char *extra = smbios_find_oem_string("io.systemd.stub.kernel-cmdline-extra=", /* after= */ NULL);
|
||||
if (!extra)
|
||||
return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user