From nobody Fri Sep 11 05:04:29 2026 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4hh2XF3zdBz6rbVl for ; Fri, 11 Sep 2026 05:04:29 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hh2XF1Z6Bz4CLn for ; Fri, 11 Sep 2026 05:04:29 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789103069; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Hx59Z/TAPDC+b6CczdZck+eBKVohT2PYvXtnI6xX+5M=; b=qmjT4gllR7gIkyIjKooUcgn/VXfuWZuCjYQxHUwao08zVM7R3vei23SHIwJ53ihWl+pVqr pw9OCkrFOhR3V+5tPP70ZRSm5UMuVwPW0Ma1P1P1mrDHB8hPQfxdVQ3sp/7Quhi7bxS4xT 2owZcObwvaTAd0JzXHunk/eOvLfrMGARLKm371dn0diEq67mmbsQBJnue/bY4VtHmbEjya 2jkKxLj/lDqKGjP/KABMD3QsI+fpaxyIs9z1EXW8zkVwTgnTBU6ycWYKaWofCtiK8Oa4T5 /HyaZ94hm/Kh+q5vC6UOEsWBUk8ZDw1BUZvrRTT4AGOUxBPfxuTNnyfdD0gV9Q== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789103069; b=uUt34JZHQxzvbgoOUShgYfptX5EzOaoHXbuRDy/O9l/4ubxvYb8DoPkqMrNSVB23OfCSNW 5E1/Oug/gOFtsKvAWc1q7H49oveeVDyAA4vIz2kdEVODn4OPj/uWU8DwySO1OLLpaEwxtN 5pzkL4HhTjql01d11ZD11kanZD8CqdbSu8mAySDxp+dCb6DmTbiRkkiUVtjs12KYO2AE/c 7AxnYI7mFHS2owCEdKiFlUVr9Y1MtAQ/fMYClnlme7L/LSxaMTGmGJ5POuUymfQS6FmPEq ULu0qEWb069J+PfVPeJUqMxXTfUPuLyjpxD5hfKyJYt+9xdgk2G/pWTTeMWP3w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789103069; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Hx59Z/TAPDC+b6CczdZck+eBKVohT2PYvXtnI6xX+5M=; b=shA2F6et10qw1WDapo9oiU//XpVj2K5op4aD7hMDFgvaXIAMgnCO7uKpcaQP5dSBHwuUNK He6G/O0alQHPk28aTjulaEgqZY0sN6rrWSWil8RYGbtLiXkbp2QHfN33FotTRee3wHcfqz 9JlZhiNwsL7CECKzuMTJaQZlhk5TkYGurTtEsy4zF8QgMhrvm/oCJYwhlkOZqW38PsYbj6 aLCSGQ6itoywVewgjINaC2XRADfA0eUhC/3aQ3dTEo2OiZpVi3WJL3RbGdRkpv12uhlxNo SZ6CTQaUnPsPP669YnVt+eURCiuiN0/BuGCUTKsS3JBUAMneRfxMoYZ5uaTADQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hh2XF0MWlzyx2 for ; Fri, 11 Sep 2026 05:04:29 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 3c5c9 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Fri, 11 Sep 2026 05:04:29 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Warner Losh Subject: git: 25b58eb37a79 - main - loader.efi: download md images through file API List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: imp X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 25b58eb37a7971f94f61f3a001b0d2c47228f08e Auto-Submitted: auto-generated Date: Fri, 11 Sep 2026 05:04:29 +0000 Message-Id: <6aa38bdd.3c5c9.1fc6fa0a@gitrepo.freebsd.org> The branch main has been updated by imp: URL: https://cgit.FreeBSD.org/src/commit/?id=25b58eb37a7971f94f61f3a001b0d2c47228f08e commit 25b58eb37a7971f94f61f3a001b0d2c47228f08e Author: Warner Losh AuthorDate: 2026-09-11 04:14:18 +0000 Commit: Warner Losh CommitDate: 2026-09-11 04:15:29 +0000 loader.efi: download md images through file API Feed the existing decompressor from loader file descriptors as well as iPXE callbacks, allowing arbitrary HTTP filesystem URLs to become kernel-exportable memory disks. Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D59431 --- stand/efi/loader/loader_efi.h | 1 + stand/efi/loader/memdisk.c | 102 +++++++++++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 15 deletions(-) diff --git a/stand/efi/loader/loader_efi.h b/stand/efi/loader/loader_efi.h index c53edb639ad5..6fe547b83453 100644 --- a/stand/efi/loader/loader_efi.h +++ b/stand/efi/loader/loader_efi.h @@ -60,6 +60,7 @@ void efi_copy_finish(void); void efi_copy_finish_nop(void); void maybe_download_ramdisk(int argc, CHAR16 **argv); +int download_md_image(const char *url); #if defined(__amd64__) || defined(__i386__) /* Need this to setup page tables */ diff --git a/stand/efi/loader/memdisk.c b/stand/efi/loader/memdisk.c index a425d628a85f..d02b99a0677c 100644 --- a/stand/efi/loader/memdisk.c +++ b/stand/efi/loader/memdisk.c @@ -17,6 +17,7 @@ #include #define ULL(x) ((unsigned long long)(x)) +#define DOWNLOAD_BUFSIZE (64 * 1024) static EFI_GUID ipxeGuid = IPXE_DOWNLOAD_PROTOCOL_GUID; static EFI_GUID ramdiskGuid = EFI_RAM_DISK_PROTOCOL_GUID; @@ -35,6 +36,7 @@ static struct dl_state size_t size; EFI_STATUS status; decomp_state *dctx; + bool complete; } dl; static void @@ -45,13 +47,13 @@ download_cleanup(dl_state *ctx) ctx->in_progress = false; } -static EFI_STATUS EFIAPI -download_data(IN VOID *Context, IN VOID *Buffer, IN UINTN BufferLength, IN UINTN FileOffset) +static EFI_STATUS +download_chunk(dl_state *ctx, void *buffer, size_t length, size_t offset) { - dl_state *ctx = Context; decomp_state *dctx = ctx->dctx; + enum step_return sr; - if (FileOffset == 0 && BufferLength == 0) { + if (offset == 0 && length == 0) { printf("Staritng the download\n"); return (EFI_SUCCESS); } @@ -59,9 +61,9 @@ download_data(IN VOID *Context, IN VOID *Buffer, IN UINTN BufferLength, IN UINTN /* * Make a note of the size when we're hinted about it. */ - if (BufferLength == 0) { - printf("We know we will download %llu bytes\n", ULL(FileOffset)); - ctx->size = FileOffset; + if (length == 0) { + printf("We know we will download %llu bytes\n", ULL(offset)); + ctx->size = offset; ctx->status = EFI_SUCCESS; return (EFI_SUCCESS); } @@ -69,8 +71,8 @@ download_data(IN VOID *Context, IN VOID *Buffer, IN UINTN BufferLength, IN UINTN /* * Peek into the first chunk to see the format of the data. */ - if (FileOffset == 0) { - dctx = decomp_init((uint8_t *)Buffer, (size_t)BufferLength, ctx->size); + if (offset == 0) { + dctx = decomp_init(buffer, length, ctx->size); if (dctx == NULL) { ctx->in_progress = false; ctx->status = EFI_VOLUME_CORRUPTED; @@ -79,16 +81,16 @@ download_data(IN VOID *Context, IN VOID *Buffer, IN UINTN BufferLength, IN UINTN ctx->dctx = dctx; } - enum step_return sr = decomp_step(dctx, Buffer, BufferLength, FileOffset); + sr = decomp_step(dctx, buffer, length, offset); if (sr == err) { printf("Error on download\n"); - decomp_fini(dctx, true); return (EFI_VOLUME_CORRUPTED); } + ctx->complete = (sr == done); - unsigned long long sofar = FileOffset + BufferLength; + unsigned long long sofar = offset + length; #define MB 1000000 - if (sofar / MB != FileOffset / MB) { + if (sofar / MB != offset / MB) { if (ctx->size) printf("%dMB / %dMB (%d%%)\r", (int)(sofar / MB), @@ -100,6 +102,14 @@ download_data(IN VOID *Context, IN VOID *Buffer, IN UINTN BufferLength, IN UINTN return (EFI_SUCCESS); } +static EFI_STATUS EFIAPI +download_data(IN VOID *Context, IN VOID *Buffer, IN UINTN BufferLength, + IN UINTN FileOffset) +{ + + return (download_chunk(Context, Buffer, BufferLength, FileOffset)); +} + static void EFIAPI download_finish(IN VOID *Context, IN EFI_STATUS Status) { @@ -111,7 +121,7 @@ download_finish(IN VOID *Context, IN EFI_STATUS Status) decomp_fini(ctx->dctx, EFI_ERROR(Status)); } -static void +static int fallback_to_md(EFI_PHYSICAL_ADDRESS pa, size_t len) { int unit; @@ -120,9 +130,71 @@ fallback_to_md(EFI_PHYSICAL_ADDRESS pa, size_t len) if (unit < 0) { printf("Could not register downloaded image as an md: %s\n", strerror(errno)); - return; + return (errno); } setenv("uefi_ignore_boot_mgr", "true", 1); + return (0); +} + +int +download_md_image(const char *url) +{ + struct stat sb; + dl_state ctx; + uint8_t *buf; + size_t offset; + ssize_t nread; + int error, fd; + + fd = open(url, O_RDONLY); + if (fd < 0) + return (errno); + if (fstat(fd, &sb) != 0) { + error = errno; + goto out_close; + } + if (sb.st_size <= 0 || (uintmax_t)sb.st_size > SIZE_MAX) { + error = EINVAL; + goto out_close; + } + + buf = malloc(DOWNLOAD_BUFSIZE); + if (buf == NULL) { + error = ENOMEM; + goto out_close; + } + memset(&ctx, 0, sizeof(ctx)); + ctx.size = sb.st_size; + offset = 0; + while ((nread = read(fd, buf, DOWNLOAD_BUFSIZE)) > 0) { + if (EFI_ERROR(download_chunk(&ctx, buf, nread, offset))) { + error = EIO; + goto out_decomp; + } + offset += nread; + } + if (nread < 0) { + error = errno; + goto out_decomp; + } + if (offset != ctx.size || !ctx.complete) { + error = EIO; + goto out_decomp; + } + + decomp_fini(ctx.dctx, false); + error = fallback_to_md(decomp_buffer(ctx.dctx), + decomp_buffer_length(ctx.dctx)); + goto out_free; + +out_decomp: + if (ctx.dctx != NULL) + decomp_fini(ctx.dctx, true); +out_free: + free(buf); +out_close: + close(fd); + return (error); } static void