diff --git a/Cargo.lock b/Cargo.lock index d8ce326..2574e6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1140,7 +1140,7 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openpxe" -version = "0.4.61" +version = "0.4.62" dependencies = [ "anyhow", "axum", @@ -1162,7 +1162,7 @@ dependencies = [ [[package]] name = "openpxe-core" -version = "0.4.61" +version = "0.4.62" dependencies = [ "anyhow", "bcrypt", @@ -1181,7 +1181,7 @@ dependencies = [ [[package]] name = "openpxe-dhcp-proxy" -version = "0.4.61" +version = "0.4.62" dependencies = [ "anyhow", "bytes", @@ -1195,7 +1195,7 @@ dependencies = [ [[package]] name = "openpxe-http-api" -version = "0.4.61" +version = "0.4.62" dependencies = [ "anyhow", "axum", @@ -1226,7 +1226,7 @@ dependencies = [ [[package]] name = "openpxe-ipxe-assets" -version = "0.4.61" +version = "0.4.62" dependencies = [ "openpxe-core", "rust-embed", @@ -1236,7 +1236,7 @@ dependencies = [ [[package]] name = "openpxe-iso-store" -version = "0.4.61" +version = "0.4.62" dependencies = [ "anyhow", "bcrypt", @@ -1260,7 +1260,7 @@ dependencies = [ [[package]] name = "openpxe-tftp" -version = "0.4.61" +version = "0.4.62" dependencies = [ "anyhow", "bytes", @@ -1274,7 +1274,7 @@ dependencies = [ [[package]] name = "openpxe-webui" -version = "0.4.61" +version = "0.4.62" [[package]] name = "parking_lot" diff --git a/Cargo.toml b/Cargo.toml index d72c72c..ccdf2b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ members = [ ] [workspace.package] -version = "0.4.61" +version = "0.4.62" edition = "2021" rust-version = "1.95" license = "MIT OR Apache-2.0" diff --git a/crates/http-api/src/ipxe_script.rs b/crates/http-api/src/ipxe_script.rs index ab16992..7795d2b 100644 --- a/crates/http-api/src/ipxe_script.rs +++ b/crates/http-api/src/ipxe_script.rs @@ -77,15 +77,20 @@ pub fn render_menu(isos: &[IsoMeta], settings: &Settings, base_url: &str) -> Str ); let _ = writeln!(s, ":menu"); let _ = writeln!(s, "menu OpenPXE - network boot menu"); - // v0.4.61: we used to draw an ASCII OpenPXE wordmark here. Now - // that the bundled iPXE is built with `IMAGE_PNG`, the - // `console --picture` line at the top of this script paints the - // operator's actual logo (composed server-side into a 1024×768 - // canvas with the logo centered at the top) — the ASCII banner - // became visual noise *on top* of the real image. Old iPXE - // builds without PNG fall through the `|| console` clause and - // simply show the menu without a logo, which is the correct - // graceful-degradation outcome. + // ASCII OpenPXE wordmark. Works on every iPXE build, including + // the boot.ipxe.org pre-builds we ship (which omit `IMAGE_PNG`, + // so `console --picture` paints nothing). When the queued iPXE + // source-build lands and the operator's uploaded raster actually + // paints via `console --picture`, this banner can be retired in + // favour of the real image. The compositor at + // /branding/pxe-logo is already wired and waiting. + let _ = writeln!(s, "item --gap"); + let _ = writeln!(s, "item --gap -- ___ ___ __ __ ___"); + let _ = writeln!(s, "item --gap -- / _ \\ _ __ ___ _ _ | _ \\ \\/ / | __|"); + let _ = writeln!(s, "item --gap -- | (_) | '_ \\/ -_) ' \\ | _/ \\ / | _|"); + let _ = writeln!(s, "item --gap -- \\___/| .__/\\___|_||_| |_| /_/\\_\\ |___|"); + let _ = writeln!(s, "item --gap -- |_|"); + let _ = writeln!(s, "item --gap"); let _ = writeln!( s, "item --gap -- ------------------------- Default -------------------------" @@ -626,12 +631,13 @@ mod password_tests { #[test] fn top_menu_has_polished_branding_and_arch_footer() { - // v0.4.6 polish + v0.4.61 image upgrade: the menu emits a - // `console --picture` line that the bundled iPXE (built with - // `IMAGE_PNG`) honours, plus an arch-resolved footer carrying - // the current OpenPXE version. The ASCII wordmark that used - // to live here was dropped in v0.4.61 — it duplicated the now- - // working image. + // v0.4.6 polish + v0.4.62 stability fixes: the menu emits a + // `console --picture` line that PNG-capable iPXE builds will + // honour (queued for a follow-up release once we can rebuild + // iPXE from source on native x86_64 hardware), an ASCII + // OpenPXE wordmark that works on every iPXE build (including + // the boot.ipxe.org pre-builds we currently ship), and a + // single-line footer carrying the OpenPXE version + arch. let settings = Settings::default(); let s = render_menu(&[], &settings, "http://10.0.0.5"); assert!( @@ -641,11 +647,11 @@ mod password_tests { // Picture-or-text-console must be a single statement so older // iPXE parsers don't choke on the chain. assert!(s.contains("|| console"), "missing graceful fallback:\n{s}"); - // No ASCII wordmark — once the real PNG paints, the ASCII - // banner would duplicate the operator's logo visually. + // ASCII wordmark — paints on every iPXE build regardless of + // PNG support. assert!( - !s.contains("___ ___ __ __ ___"), - "ASCII banner shouldn't be emitted in v0.4.61+:\n{s}" + s.contains("___ ___ __ __ ___"), + "ASCII banner missing first row:\n{s}" ); // Footer with version + arch interpolation. The version comes // from CARGO_PKG_VERSION at compile time. diff --git a/deploy/docker/Dockerfile b/deploy/docker/Dockerfile index 54fb223..32344ff 100644 --- a/deploy/docker/Dockerfile +++ b/deploy/docker/Dockerfile @@ -16,79 +16,21 @@ ARG RUST_VERSION=1.95 -########## fetch wimboot (and a sanity-check fetch of upstream iPXE) ########## -# v0.4.61: we no longer ship the boot.ipxe.org iPXE binaries directly; -# instead we build iPXE from source with IMAGE_PNG enabled (see the -# ipxe-build stage below). The fetch stage still pulls wimboot (a -# pre-signed binary from ipxe/wimboot's GitHub release) since that's -# unrelated to the PNG concern. +########## fetch iPXE binaries + wimboot ########## +# v0.4.62: kept on the boot.ipxe.org pre-builds for the moment. We +# want PNG support (so `console --picture` paints the operator's logo +# on the PXE menu) but the obvious path — adding a new `ipxe-build` +# stage that compiles iPXE from source with `IMAGE_PNG` enabled — +# runs into a QEMU/gcc instability when cross-emulating x86_64 on +# arm64 build hosts (intermittent `cc1` segfaults). The compositor +# at /branding/pxe-logo is already wired so when the iPXE rebuild +# lands (on native x86_64 hardware), no other code change is needed. FROM debian:12-slim AS fetch RUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates \ && rm -rf /var/lib/apt/lists/* WORKDIR /src -RUN mkdir -p assets/ipxe && \ - curl --fail --silent --show-error --location \ - -o assets/ipxe/wimboot \ - https://github.com/ipxe/wimboot/releases/latest/download/wimboot \ - || echo "wimboot fetch failed; Windows toggle will stay disabled" - -########## build iPXE from source with IMAGE_PNG enabled ########## -# This stage replaces the old "grab pre-built binaries from -# boot.ipxe.org" path. The shipped binaries there are built with the -# default config which omits `IMAGE_PNG`, so the `console --picture` -# call in render_menu silently no-ops — operator logos never paint. -# Building from source lets us flip the one flag we need. -# -# Cross-compilation: x86_64 + i386 use the native toolchain that ships -# in the rust:bookworm base; arm64 uses gcc-aarch64-linux-gnu. The four -# output binaries match the names openpxe-ipxe-assets expects in -# assets/ipxe/. -FROM rust:${RUST_VERSION}-bookworm AS ipxe-build -RUN apt-get update \ - && apt-get install -y --no-install-recommends \ - git build-essential liblzma-dev mtools genisoimage syslinux \ - gcc-aarch64-linux-gnu \ - && rm -rf /var/lib/apt/lists/* -WORKDIR /build -# Pin to a recent iPXE master tip via shallow clone. iPXE doesn't tag -# releases; pinning the SHA in source would be a periodic chore. The -# tradeoff is that "rebuild the container" silently picks up upstream -# patches — for a boot loader this is the right side of the -# pin-vs-fresh tradeoff (we want CVE fixes ASAP and the PXE chain is -# the trusted base). -RUN git clone --depth=1 https://github.com/ipxe/ipxe.git ipxe -WORKDIR /build/ipxe/src -# Feature flags landed via the `config/local/` override files iPXE's -# config system reads after `config/general.h`. We enable just the -# image format + framebuffer console plumbing — everything else stays -# at the upstream default. `keep-debug` is off; `parserrors` is off; we -# pin a small set of useful tweaks. -RUN mkdir -p config/local \ - && printf '%s\n' \ - '#define IMAGE_PNG' \ - '#define CONSOLE_FRAMEBUFFER' \ - '#define CONSOLE_VESAFB' \ - '#define DOWNLOAD_PROTO_HTTPS' \ - '#define NSLOOKUP_CMD' \ - '#define NTP_CMD' \ - > config/local/general.h -# Each arch builds to its own `bin-*` directory. We copy the four -# output binaries into /out/ with the names openpxe-ipxe-assets -# expects. Stripping the binaries saves ~30% — they go into the rust -# binary via include_bytes! so the savings ripple through the final -# image. -RUN mkdir -p /out && \ - make -j"$(nproc)" bin/undionly.kpxe && \ - cp bin/undionly.kpxe /out/undionly.kpxe && \ - make -j"$(nproc)" bin-x86_64-efi/snponly.efi && \ - cp bin-x86_64-efi/snponly.efi /out/snponly.efi && \ - make -j"$(nproc)" bin-x86_64-efi/ipxe.efi && \ - cp bin-x86_64-efi/ipxe.efi /out/ipxe.efi && \ - make -j"$(nproc)" bin-i386-efi/snponly.efi && \ - cp bin-i386-efi/snponly.efi /out/snponly-i386.efi && \ - make -j"$(nproc)" CROSS_COMPILE=aarch64-linux-gnu- bin-arm64-efi/snponly.efi && \ - cp bin-arm64-efi/snponly.efi /out/snponly-arm64.efi && \ - ls -lh /out/ +COPY scripts/fetch-ipxe.sh scripts/fetch-ipxe.sh +RUN mkdir -p assets/ipxe && bash scripts/fetch-ipxe.sh ########## build openpxe ########## FROM rust:${RUST_VERSION}-bookworm AS build @@ -122,11 +64,7 @@ RUN apt-get update \ # `cargo build`, which is slow and can exhaust small Colima/CI disks. COPY Cargo.toml Cargo.lock ./ COPY crates/ crates/ -# v0.4.61: iPXE binaries come from our own source-built stage with -# IMAGE_PNG enabled. wimboot still comes from the fetch stage (it's -# from ipxe/wimboot's GitHub release, separately signed). -COPY --from=ipxe-build /out/ /src/assets/ipxe/ -COPY --from=fetch /src/assets/ipxe/wimboot /src/assets/ipxe/wimboot +COPY --from=fetch /src/assets/ipxe /src/assets/ipxe # Cache cargo registry + target across builds. The mtime touch is # belt-and-suspenders: cargo occasionally misses mtime-only changes on