Tidy up pxe flow

This commit is contained in:
Audiobuzz
2026-06-20 09:19:01 +00:00
parent fb69068980
commit 33583bb4d8
2 changed files with 36 additions and 41 deletions
+19 -36
View File
@@ -23,8 +23,12 @@
set -eu
mkdir -p /srv/tftp
# User-supplied iPXE binary (ipxe.efi) from the read-only source mount.
# User-supplied iPXE binary (snponly.efi) from the read-only source mount.
cp -f /tftp-src/*.efi /srv/tftp/ 2>/dev/null || true
# autoexec.ipxe was an STP-era workaround (ifopen+retry before autoboot); it's no
# longer rendered — PortFast on the switch port is the real fix. Remove any stale
# copy left in a long-lived container's writable layer.
rm -f /srv/tftp/autoexec.ipxe
extract_cmdline() { # $1 = UKI path; echoes the cleaned cmdline (empty on failure)
uki="$1"
@@ -47,49 +51,28 @@ render_boot_ipxe() {
echo " hit a dracut shell under Secure Boot OFF (no embedded cmdline)." >&2
echo " Check the /artifacts mount + binutils, or enable Secure Boot." >&2
fi
# Render the SAME boot logic to two files:
# autoexec.ipxe — iPXE fetches + runs this at STARTUP (before autoboot). The
# leading `ifopen net0` brings the link UP on NICs whose NII/UNDI link iPXE
# can't establish during autoboot — e.g. EliteBook 820 G4 / Intel I219-LM,
# which sits at link:down ("No configurable methods") until ifopen. Without
# this, autoboot fails before it can even DHCP for boot.ipxe.
# boot.ipxe — the DHCP-bootfile fallback (tag:ipxe) for firmware that DOES
# autoboot-DHCP fine; harmless to carry the same ifopen.
# Both feed iPXE the UKI's REAL cmdline via imgargs (Secure Boot OFF; see top).
for f in /srv/tftp/autoexec.ipxe /srv/tftp/boot.ipxe; do
cat > "$f" <<EOF
# boot.ipxe is fetched as the DHCP bootfile (dnsmasq tag:ipxe) AFTER iPXE's
# normal autoboot DHCP has already configured the link, so it just fetches and
# boots the UKI. `imgargs` feeds the UKI's REAL cmdline (Secure Boot OFF — see
# top); without it iPXE would pass the image name as the cmdline and dracut
# would drop to an emergency shell. (every fallible step is '||'-guarded — a
# bare failure aborts the iPXE script.)
#
# REQUIRES PortFast/edge on the switch port: iPXE's autoboot opens the NIC,
# which bounces the PHY; without PortFast the switch's STP forwarding delay
# (~30s) drops the DHCP and the boot fails. (We removed the old ifopen+retry
# workaround now that PortFast is the documented requirement — serving/tftp/README.)
cat > /srv/tftp/boot.ipxe <<EOF
#!ipxe
# NOTE: in iPXE a bare failing command aborts the script (-> iPXE exits -> the
# firmware restarts PXE), so EVERY step that can fail is guarded with '||'.
#
# The link is already up + forwarding here (the TFTP fetch of this script just
# succeeded), so try DHCP FIRST without touching the PHY — on a PortFast/edge
# port this succeeds immediately with no delay.
dhcp net0 && goto have_ip || echo initial DHCP failed; will reset link and retry
# Fallback: reset the link, then retry DHCP long enough to outlast the switch's
# STP forwarding delay (~30s) that the ifopen bounce triggers. A single ifopen
# (held open across the loop) means the PHY bounces ONCE; STP then converges and
# a later DHCP gets through. PROPER fix is PortFast/edge on the switch port so
# there's no delay at all — see serving/tftp/README.md.
ifopen net0 || goto err
set tries 0
:dhcp_retry
dhcp net0 && goto have_ip || echo DHCP retry \${tries}
inc tries || goto err
iseq \${tries} 30 && goto no_ip || sleep 3
goto dhcp_retry
:have_ip
dhcp net0 || goto err
imgfetch http://${SERVER_IP}/${uki} || goto err
imgargs ${uki} ${cmdline}
boot ${uki} || goto err
:no_ip
echo No DHCP after ~90s on net0 - enable PortFast/edge on the switch port (STP delay).
:err
echo Fleet iPXE chain failed (\${errno}) - dropping to iPXE shell
shell
EOF
done
echo "rendered autoexec.ipxe + boot.ipxe -> ${uki} (cmdline: ${cmdline:-<MISSING>})"
echo "rendered /srv/tftp/boot.ipxe -> ${uki} (cmdline: ${cmdline:-<MISSING>})"
}
if [ -n "${SERVER_IP:-}" ] && [ -n "${IMAGE_VERSION:-}" ]; then