#!/bin/sh
# auto/config - live-build configuration for the bty live env.
#
# live-build invokes this script when (re)configuring the build dir
# (typically the first ``lb build`` run, and again whenever ``lb build``
# itself calls ``lb config``). Encodes our lb config args: Debian
# trixie, no debian-installer, no memtest, no apt recommends, no
# security. Architecture + binary-image-shape + bootloader options
# are derived from the ``BTY_VARIANT`` environment variable.
#
# Variants:
#
#   - ``netboot-x86`` (default): amd64 kernel + initrd + squashfs
#     trio for the PXE flow. Server hosts these three files over
#     HTTP and clients chain into them via iPXE.
#   - ``usb-x86``: amd64 hybrid ISO image bootable from CD or USB
#     (BIOS + UEFI). Adds ``--bootloaders syslinux,grub-efi`` for
#     dual-firmware boot. No ``bty.*`` cmdline params: USB-local
#     boot has no bty-server URL or self-MAC to pin, and
#     ``bty-on-tty1.service`` fires unconditionally
#     (v0.22.10+ retired the ConditionKernelCommandLine gating).
#   - ``usb-rpi``: arm64 kernel + initrd + squashfs for a
#     Raspberry-Pi USB-flasher. lb produces the netboot trio; the
#     bty-media post-processing step (``pack_rpi_img.py``) assembles
#     a Pi-bootable raw disk image with a FAT32 firmware partition
#     and the squashfs on its own ext4 partition. The kernel
#     cmdline uses ``console=serial0,115200`` (Pi firmware overlays
#     the right ``ttyAMAx`` per board revision, so the same image
#     boots Pi4 / Pi5 / CM5 without per-board branching).
#
# All variants share the same chroot package set + hooks. Per-arch
# package divergence (linux-image-amd64 vs linux-image-arm64, the
# x86-only r8125 DKMS hook, the Pi firmware blobs from
# raspi-firmware) lives in arch-suffixed .list.chroot files that
# live-build only consumes when the matching ``--architectures`` is
# active.
#
# ``lb build`` re-runs this script during its internal ``lb config``
# step, so ``BTY_VARIANT`` must be set in the build invocation's
# environment, not just at the initial config call (sudo strips env
# by default; ``cijoe/scripts/usb_iso_build.py`` and the new
# ``usb_rpi_build.py`` use ``sudo env BTY_VARIANT=...``).
#
# Requires live-build 20240208+ (Debian trixie or newer) which
# fetches ``dists/<release>/main/Contents-<arch>.gz`` from the
# per-component layout Debian now publishes. Ubuntu's stock
# live-build 20230502 still uses the obsolete top-level URL and
# 404s on every active Debian release; ci-cd.yml's media build jobs
# pull the trixie .deb explicitly to work around that.
set -e

# Plymouth was retired in v0.22.1: the kernel-stage graphical splash
# wedged plymouth-quit-wait on several Intel iGPUs (MS-01, EPYC
# bring-up box) and the mascot-splash value didn't justify the
# multi-layer workaround stack (cmdline disable + package purge +
# variant split). The live env now boots to plain kernel + systemd
# init messages; ``/etc/issue`` (rendered by agetty on tty1) carries
# the bty identity. ``plymouth.enable=0`` stays on the cmdline as
# belt-and-braces in case plymouth ever gets pulled in transitively
# by a future package change: with no package installed it's a
# no-op.

# Transparency: NO ``quiet``, NO ``splash``. bty wants the full
# kernel + systemd boot stream visible on tty1/serial; a wedge
# between ``[ OK ] Started X`` and ``[ OK ] Started Y`` is
# immediately diagnostic. Same reason plymouth was retired (v0.22.1):
# hiding init output makes operator debugging harder, polish is not
# worth the opacity.

BTY_VARIANT="${BTY_VARIANT:-netboot-x86}"

case "${BTY_VARIANT}" in
    netboot-x86)
        ARCH=amd64
        BINARY_IMAGES=netboot
        BOOTLOADERS_OPTS=""
        # The PXE-flash chain (server's ipxe_flash.j2 / ipxe_tui.j2)
        # appends ``bty.server=...`` + ``bty.mac=...`` per-client at
        # render time, so the chroot's static bootappend doesn't carry
        # them.
        BOOTAPPEND="boot=live components plymouth.enable=0 modprobe.blacklist=nouveau nouveau.modeset=0 systemd.gpt_auto=0 bty.version=__BTY_VERSION__"
        ;;
    usb-x86)
        ARCH=amd64
        BINARY_IMAGES=iso-hybrid
        BOOTLOADERS_OPTS="--bootloaders syslinux,grub-efi"
        # ``console=tty0 console=ttyS0,115200``: kernel + systemd boot
        # messages go to BOTH the framebuffer (tty0, for real hardware
        # operators) and the serial port (ttyS0, for QEMU/IP-KVM/anything
        # capturing the serial). The LAST ``console=`` is the systemd
        # default-stdout sink; we list ttyS0 last so the auto-grow test
        # sees ``[ OK ] Started bty-usb-grow.service`` on its captured
        # serial log. Harmless on real USB sticks without a serial port:
        # writes are dropped.
        BOOTAPPEND="boot=live components noeject plymouth.enable=0 modprobe.blacklist=nouveau nouveau.modeset=0 systemd.gpt_auto=0 console=tty0 console=ttyS0,115200 bty.version=__BTY_VERSION__"
        ;;
    usb-rpi)
        ARCH=arm64
        # Pi firmware boots directly from FAT32 partition 1, no
        # bootloader binary involved. We use ``tar`` (not ``netboot``)
        # because lb's ``binary_netboot`` stage expects a ``tftpboot/``
        # directory that the x86-only syslinux/pxelinux pipeline
        # creates; on arm64 nothing populates it and the stage fails
        # with ``mv: cannot stat 'tftpboot'``. ``binary_tar`` is a
        # one-liner that tarballs ``binary/`` without needing any
        # bootloader machinery; the resulting tarball is unused, but
        # ``binary/live/{vmlinuz,initrd.img,filesystem.squashfs}``
        # lands where ``pack_rpi_img.py`` reads from.
        BINARY_IMAGES=tar
        BOOTLOADERS_OPTS=""
        # ``console=tty1 console=serial0,115200``: Pi firmware
        # overlays ``serial0`` onto the right ``ttyAMAx`` per board
        # revision (ttyAMA0 on Pi4, ttyAMA10 on Pi5/CM5), so one
        # cmdline boots every supported board. The bty-usb-grow
        # service is also live here so the BTY_IMAGES partition
        # auto-grows on first boot.
        BOOTAPPEND="boot=live components plymouth.enable=0 systemd.gpt_auto=0 console=tty1 console=serial0,115200 bty.version=__BTY_VERSION__"
        ;;
    *)
        echo "auto/config: unknown BTY_VARIANT=${BTY_VARIANT}" >&2
        echo "  valid: netboot-x86 | usb-x86 | usb-rpi" >&2
        exit 2
        ;;
esac

# Per-architecture package list, written here rather than in a
# ``.list.chroot_<arch>``-suffixed file under ``config/package-lists/``
# because Debian live-build 3.0~a57 (Ubuntu trixie/jammy runners) does
# NOT consume the underscore-suffix form; the docs imply it should
# but the runner build that ships with the GHA image does not. To
# avoid version-specific guesswork, generate a plain
# ``bty-arch.list.chroot`` based on the resolved ``${ARCH}``. live-
# build always consumes unsuffixed ``*.list.chroot`` files.
mkdir -p config/package-lists
case "${ARCH}" in
    amd64)
        # amd64 kernel + Intel/AMD microcode + r8125 DKMS build env.
        # Why microcode: PXE-booted bare metal has no host-loaded
        # ucode, and modern Ryzen + recent Intel cores ship factory
        # microcode missing Spectre/SRBDS/Reptar/Inception mitigations.
        # Pinned to trixie-backports via
        # ``config/preferences/backports.pref.chroot``.
        cat >config/package-lists/bty-arch.list.chroot <<'PKGS'
linux-image-amd64
intel-microcode
amd64-microcode
dkms
build-essential
linux-headers-amd64
PKGS
        ;;
    arm64)
        # arm64 kernel + raspi-firmware (the Pi boot chain bootcode.bin
        # + start*.elf + fixup*.dat + Pi DTBs in /usr/lib/raspi-firmware/)
        # + Pi WiFi/BT firmware (brcm80211 + misc-nonfree). No x86
        # microcode, no DKMS build env (the r8125 driver is x86-only
        # and the hook early-exits on non-amd64).
        cat >config/package-lists/bty-arch.list.chroot <<'PKGS'
linux-image-arm64
raspi-firmware
firmware-brcm80211
firmware-misc-nonfree
PKGS
        ;;
    *)
        echo "auto/config: no per-arch package list for ARCH=${ARCH}" >&2
        exit 2
        ;;
esac

# shellcheck disable=SC2086 # BOOTLOADERS_OPTS is intentionally word-split
lb config noauto \
    --mode debian \
    --distribution trixie \
    --architectures "${ARCH}" \
    --archive-areas "main non-free-firmware" \
    --firmware-chroot true \
    --binary-images "${BINARY_IMAGES}" \
    --debian-installer none \
    --memtest none \
    --apt-recommends false \
    --security false \
    ${BOOTLOADERS_OPTS} \
    --bootappend-live "${BOOTAPPEND}" \
    "${@}"
# ``--archive-areas "main non-free-firmware"`` unlocks the
# ``firmware-*`` packages. Default areas are just ``main``, which
# silently drops every firmware blob and produces a live env where
# i915 wedges the GPU on probe and certain NIC / WiFi chipsets fail
# to load. Debian split ``non-free-firmware`` out of ``non-free``
# in bookworm precisely so this archive can be enabled on its own.
#
# ``--firmware-chroot true`` pulls ``firmware-linux-nonfree`` (a
# metapackage that Depends on EVERY individual nonfree ``firmware-*``
# package: realtek, iwlwifi, atheros, brcm80211, mediatek, ath11k,
# bnx2/bnx2x, netronome, nvidia-graphics, amd-graphics, and a long
# tail of server-NIC + old-WiFi blobs). The size cost (~300 MiB
# compressed) buys "boots on whatever bare-metal box the operator
# points it at"; the alternative is the operator hits a missing
# firmware -> driver init failure -> dead NIC and can't proceed.
# A curated list is too narrow: Realtek WiFi/BT chipsets alone
# span half a dozen firmware packages and consumer mini-PCs cycle
# them quickly.
# The trixie-backports archive layered via
# ``config/archives/backports.list.chroot`` plus the pin in
# ``config/preferences/backports.pref.chroot`` makes apt pull the
# newest kernel + firmware Debian ships, not just trixie's.
# Bootloader-menu suppression: see
# ``hooks/binary/0500-bty-skip-bootloader-menu.hook.binary``. Don't
# add ``--syslinux-timeout`` here; live-build trixie doesn't
# recognise that flag and ``lb config`` errors out.
