<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>
<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>
#include "creds-util.h"
#include "discover-image.h"
+#include "efivars.h"
#include "fd-util.h"
#include "fileio.h"
#include "generator.h"
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();
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 (;;) {
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)
}
}
+ 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)