import-generator: add new option 'bootorigin' to derive URL from efi boot url
This commit is contained in:
@@ -127,6 +127,23 @@
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term>bootorigin</term>
|
||||
|
||||
<listitem><para>If this option is specified, in place of the URL a simple filename may be
|
||||
specified. If the system is booted via UEFI HTTP network booting the last component of the
|
||||
network boot origin URL is replaced by this filename and used as download source. This hence
|
||||
allows to automatically derive the URLs for disk images from the original boot URL used to invoke
|
||||
the kernel or boot loader.</para>
|
||||
|
||||
<para>If this option is used and the system is not actually booted via UEFI HTTP network booting,
|
||||
the download is gracefully skipped. Or in other words without other modifications it is possible
|
||||
to put together an initrd image that will boot from a local disk if available, or from downloaded
|
||||
disk image if used via network booting.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v257"/></listitem>
|
||||
@@ -203,6 +220,17 @@
|
||||
<literal>image</literal>, and attaches it to a loopback block device on completion. It then boots from
|
||||
the 2nd partition in the image.</para>
|
||||
</example>
|
||||
|
||||
<example>
|
||||
<title>Boot into disk image (raw), with URL derived from UEFI HTTP network booting</title>
|
||||
|
||||
<programlisting>rd.systemd.pull=raw,machine,verify=no,blockdev,bootorigin:rootdisk:image.raw.xz root=/dev/disk/by-loop-ref/rootdisk.raw-part2</programlisting>
|
||||
|
||||
<para>This is similar to the previous example, but this time the source URL is automatically derived
|
||||
from the UEFI HTTP network boot URL. For example, if an UKI is booted from an URL
|
||||
<literal>http://example.com/image.efi</literal> this would result in a root disk being downloaded from
|
||||
<literal>http://example.com/image.raw.xz</literal>.</para>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "creds-util.h"
|
||||
#include "discover-image.h"
|
||||
#include "efivars.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "generator.h"
|
||||
@@ -65,8 +66,6 @@ static int parse_pull_expression(const char *v) {
|
||||
if (r == 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No local string in pull expression '%s': %m", v);
|
||||
|
||||
if (!http_url_is_valid(p) && !file_url_is_valid(p))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid URL, refusing: %s", p);
|
||||
_cleanup_free_ char *remote = strdup(p);
|
||||
if (!remote)
|
||||
return log_oom();
|
||||
@@ -79,7 +78,7 @@ static int parse_pull_expression(const char *v) {
|
||||
ImportType type = _IMPORT_TYPE_INVALID;
|
||||
ImageClass class = _IMAGE_CLASS_INVALID;
|
||||
ImportVerify verify = IMPORT_VERIFY_SIGNATURE;
|
||||
bool ro = false, blockdev = false;
|
||||
bool ro = false, blockdev = false, bootorigin = false;
|
||||
|
||||
const char *o = options;
|
||||
for (;;) {
|
||||
@@ -99,8 +98,9 @@ static int parse_pull_expression(const char *v) {
|
||||
ro = false;
|
||||
else if (streq(opt, "blockdev"))
|
||||
blockdev = true;
|
||||
else if (streq(opt, "bootorigin"))
|
||||
bootorigin = true;
|
||||
else if ((suffix = startswith(opt, "verify="))) {
|
||||
|
||||
ImportVerify w = import_verify_from_string(suffix);
|
||||
|
||||
if (w < 0)
|
||||
@@ -124,6 +124,32 @@ static int parse_pull_expression(const char *v) {
|
||||
}
|
||||
}
|
||||
|
||||
if (bootorigin) {
|
||||
_cleanup_free_ char *stub_url = NULL;
|
||||
|
||||
r = efi_get_variable_string(EFI_LOADER_VARIABLE_STR("StubDeviceURL"), &stub_url);
|
||||
if (r == -ENOENT) {
|
||||
log_debug("Option 'bootorigin' specified, but StubDeviceURL EFI variable not set, not scheduling import job for '%s'.", remote);
|
||||
return 0;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read 'StubDeviceURL' EFI variable: %m");
|
||||
|
||||
if (!http_url_is_valid(stub_url))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Value of 'StubDeviceURL' is not a valid URL, refusing: %s", stub_url);
|
||||
|
||||
_cleanup_free_ char *result = NULL;
|
||||
r = import_url_change_last_component(stub_url, remote, &result);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to replace last component of URL '%s': %m", stub_url);
|
||||
|
||||
log_info("URL reported by StubDeviceURL is '%s', derived download URL '%s' from it.", stub_url, result);
|
||||
free_and_replace(remote, result);
|
||||
}
|
||||
|
||||
if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid URL, refusing: %s", remote);
|
||||
|
||||
if (type < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "No image type (raw, tar) specified in pull expression, refusing: %s", v);
|
||||
if (class < 0)
|
||||
|
||||
Reference in New Issue
Block a user