#!/bin/bash
# userland/installer/ainstall — AnotherOS installer core (non-interactive).
# Turns a blank disk into a standalone-bootable AnotherOS system:
#   1. partition:  FAT32 /boot (Limine + kernel) + ext2 root      (apart -b)
#   2. root fs:    mke2fs the root EMPTY (ext4 by default — see ROOTFS below;
#                  ext2 only if you ask for it), mount it read-write, and copy
#                  the live root straight into the mount — one pass, no /tmp
#                  staging. (With an explicit base-tree argument: mke2fs -d.)
#   3. boot fs:    mformat the FAT, copy kernel + Limine + the rescue initramfs
#                  + limine.conf (mtools)
#   4. bootloader: limine bios-install to the disk MBR
# The ncurses front-end drives this; it is also runnable directly.
#
#   ainstall <target-disk> [base-root-tree]
#   e.g.  ainstall /dev/sda /base
#
# UEFI / GPT MODE (#859) — the same install onto a GUID Partition Table:
#   1. partition:  protective MBR + GPT: an EFI System Partition (FAT) + a Linux
#                  filesystem partition                          (agpt create)
#                  --keep-table reuses an existing ESP + Linux entry instead
#   2. root fs:    as above (mount + copy), or with --offline, `mke2fs -d /`
#                  at a byte offset of the WHOLE-DISK node through
#                  /install/ainstfilter.so — no partition node, no mount
#   3. ESP:        kernel + rescue initramfs + limine.conf, and Limine's UEFI
#                  loader at \EFI\BOOT\BOOTX64.EFI (the removable-media path
#                  every UEFI firmware boots with no NVRAM entry)
#   4. NVRAM:      `aefiboot create ... --order first` when the tool exists and
#                  the boot exposes EFI variables; otherwise a logged no-op
#                  naming the command to run (--no-nvram skips it)
#   5. verify:     GPT CRCs, e2fsck -fn, the ESP files by sha256, and the root
#                  UUID limine.conf names against the superblock
#
#   ainstall --efi /dev/sda
#   ainstall --efi --keep-table --offline --payload /tmp/payload /dev/sda
#   ainstall --verify --efi --payload /tmp/payload /dev/sda
#
# Selected automatically when the booted system came up through UEFI
# (/sys/firmware/efi exists); --bios / --efi force either. The BIOS/MBR flow
# above is unchanged and stays the default everywhere else.
set -e
# UPGRADE MODE (`ainstall --upgrade <disk>`, or UPGRADE=1).
#
# Reinstalls the OS onto a disk that ALREADY holds AnotherOS without touching
# the partition table and without mke2fs. The farm layout is what makes this
# safe rather than clever: the OS and the configuration live in SEPARATE
# top-level trees, so an upgrade is "replace the store, regenerate the index,
# leave everything else alone" instead of a merge.
#
#   REPLACED   /Apps            the store -- the OS itself
#              /Applications    bundle links into the store
#              /System/Index    the symlink farm; REGENERATED by asymlink
#              /boot kernel     on the FAT partition
#
#   PRESERVED  /System/Settings  this IS /etc. Never overwritten.
#              /Users            accounts and home directories
#              /State            var, and the apkg database
#              /Files            user data
#
# NEW configuration files still ARRIVE: a file that is not on the target is
# copied, a file that IS on the target is left exactly as the user has it. That
# is dpkg's conffile rule, and it is the only behaviour that lets a release add
# a default without silently reverting somebody's edit.
UPGRADE="${UPGRADE:-0}"

# ROOT FILESYSTEM TYPE. ext4 is the DEFAULT: the kernel's ext4 writer is
# complete and e2fsck-clean -- extents, htree, metadata_csum, journal recovery
# and replay (docker/scripts/ext4mnt_gate.sh, ext4wr_gate, ext4rec_gate) -- and
# a disk root formatted ext4 boots by UUID and persists runtime writes
# (rootpivot64_gate). It is the format a filesystem Linux or e2fsck touches
# comes out as, so it is also the least surprising choice.
#
# ext2 is still available (`--fs ext2`) for a smaller, journalless root. The
# copy itself is filesystem-agnostic -- `mke2fs -t $ROOTFS` and `mount -t
# $ROOTFS` are the only lines that differ; busybox `cp -a` carries modes with
# chmod(PATH) and links with symlink(PATH), which the kernel persists for both
# (#520). ext3 is NOT offered: the kernel has no ext3 partition-mount entry
# point (fstab.c), so `mount -t ext3` of a target would fail, and a root the
# installer cannot mount is a root it cannot populate.
ROOTFS="${ROOTFS:-ext4}"

# A `--fs <type>` flag, before the disk, overrides the env. Kept order-tolerant
# with --upgrade so either can come first.
# UEFI/GPT knobs (#859). Every one is spelled out in the banner at the top.
MODE="${MODE:-auto}"            # auto | bios | efi
KEEP_TABLE=0                    # efi: reuse the existing GPT instead of rewriting it
ESP_N=""; ROOT_N=""             # efi: explicit entry numbers (default: first ESP / Linux entry)
ESP_MIB="${ESP_MIB:-256}"       # efi: size of a NEW ESP
ESP_FORMAT=""                   # efi: 1 mformat the ESP, 0 keep its files (default: keep iff --keep-table)
LOADER_ALIASES=""               # efi: extra ESP paths that also get BOOTX64.EFI
OFFLINE=0                       # efi: populate by byte offset, never via partition nodes
NVRAM="${NVRAM:-1}"             # efi: try aefiboot
VERIFY_ONLY=0
PAYLOAD="${PAYLOAD:-/install}"
while :; do
    case "${1:-}" in
        --upgrade|-u) UPGRADE=1; shift ;;
        --fs)         ROOTFS="${2:?--fs needs a type}"; shift 2 ;;
        --fs=*)       ROOTFS="${1#--fs=}"; shift ;;
        --efi|--gpt)  MODE=efi; shift ;;
        --bios|--mbr) MODE=bios; shift ;;
        --keep-table) KEEP_TABLE=1; shift ;;
        --esp-part)   ESP_N="${2:?--esp-part needs a number}"; shift 2 ;;
        --root-part)  ROOT_N="${2:?--root-part needs a number}"; shift 2 ;;
        --esp-mib)    ESP_MIB="${2:?--esp-mib needs a size}"; shift 2 ;;
        --keep-esp)   ESP_FORMAT=0; shift ;;
        --format-esp) ESP_FORMAT=1; shift ;;
        --efi-loader-alias) LOADER_ALIASES="$LOADER_ALIASES
${2:?--efi-loader-alias needs an ESP path}"; shift 2 ;;
        --offline)    OFFLINE=1; shift ;;
        --payload)    PAYLOAD="${2:?--payload needs a directory}"; shift 2 ;;
        --no-nvram)   NVRAM=0; shift ;;
        --verify)     VERIFY_ONLY=1; shift ;;
        *)            break ;;
    esac
done
if [ "$MODE" = auto ]; then
    # /sys/firmware/efi is the Linux convention for "this boot came through
    # UEFI", and the one the EFI-runtime work publishes. Its absence on a
    # kernel that does not publish it yet reads as BIOS, which is the safe
    # direction: the BIOS flow is the one every machine in the lab was
    # installed with.
    if [ -d /sys/firmware/efi ]; then MODE=efi; else MODE=bios; fi
fi
if [ "$MODE" != efi ]; then
    for _o in "$KEEP_TABLE:--keep-table" "$OFFLINE:--offline" "$VERIFY_ONLY:--verify"; do
        [ "${_o%%:*}" = 1 ] && { echo "!! ${_o#*:} is a UEFI/GPT option — add --efi"; exit 2; }
    done
fi
[ -n "$ESP_FORMAT" ] || { [ "$KEEP_TABLE" = 1 ] && ESP_FORMAT=0 || ESP_FORMAT=1; }
if [ "$OFFLINE" = 1 ] && [ "$UPGRADE" = 1 ]; then
    echo "!! --offline builds a NEW filesystem; it cannot upgrade one in place"; exit 2
fi
case "$ROOTFS" in
    ext2|ext4) ;;
    *) echo "!! unsupported root filesystem '$ROOTFS' (ext2 or ext4)"; exit 2 ;;
esac
DISK="${1:-/dev/sda}"
BASE="${2:-}"
export MTOOLS_SKIP_CHECK=1

base=$(basename "$DISK")            # sda
P1="${DISK}1"; P2="${DISK}2"

# ---- UEFI / GPT helpers (#859) -----------------------------------------------
#
# ESPI and ROOTSPEC are how every later step addresses the two partitions, so
# the online and offline paths differ in exactly these two strings:
#   online   ESPI=/dev/sdaN            ROOTSPEC=/dev/sdaM
#   offline  ESPI=/dev/sda@@<bytes>    ROOTSPEC=/dev/sda?offset=<bytes>
# mtools takes `image@@offset`; e2fsprogs' unix io manager takes `?offset=`
# (e2fsck/tune2fs/dumpe2fs parse it from the device name).
ESPI="$P1"; ROOTSPEC="$P2"
ROOT_OFF=0
_tool() { # the named helper: next to this script, in the payload, or on PATH
    for _t in "$(dirname "$0")/$1" "$PAYLOAD/$1" "/sbin/$1" "/bin/$1"; do
        [ -x "$_t" ] && { echo "$_t"; return 0; }
    done
    command -v "$1" 2>/dev/null || return 1
}
AGPT=""
efi_layout() {
    AGPT=$(_tool agpt) || { echo "!! agpt not found (next to ainstall, in $PAYLOAD, or /sbin)"; exit 1; }
    [ -n "$ESP_N" ]  || ESP_N=$("$AGPT" find "$DISK" esp)   || { echo "!! $DISK: no EFI System Partition entry"; exit 1; }
    [ -n "$ROOT_N" ] || ROOT_N=$("$AGPT" find "$DISK" linux) || { echo "!! $DISK: no Linux filesystem entry"; exit 1; }
    ESP_START=$("$AGPT" get "$DISK" "$ESP_N" start)
    ESP_SECS=$("$AGPT" get "$DISK" "$ESP_N" sectors)
    ESP_OFF=$("$AGPT" get "$DISK" "$ESP_N" offset)
    ROOT_START=$("$AGPT" get "$DISK" "$ROOT_N" start)
    ROOT_SECS=$("$AGPT" get "$DISK" "$ROOT_N" sectors)
    ROOT_OFF=$("$AGPT" get "$DISK" "$ROOT_N" offset)
    ROOT_PARTUUID=$("$AGPT" get "$DISK" "$ROOT_N" partuuid)
    p1sectors=$ESP_SECS
    if [ "$OFFLINE" = 1 ]; then
        ESPI="$DISK@@$ESP_OFF"
        ROOTSPEC="$DISK?offset=$ROOT_OFF"
    else
        P1="${DISK}${ESP_N}"; P2="${DISK}${ROOT_N}"
        ESPI="$P1"; ROOTSPEC="$P2"
    fi
    echo ">> GPT layout: ESP = entry $ESP_N (lba $ESP_START, $ESP_SECS sectors) -> $ESPI"
    echo ">>             root = entry $ROOT_N (lba $ROOT_START, $ROOT_SECS sectors, partuuid $ROOT_PARTUUID) -> $ROOTSPEC"
}
# The root superblock's s_uuid, read at the right place for either path.
# Self-contained (not sb_uuid, which is defined further down and so does not
# exist yet on the --verify path that exits early).
root_sb_uuid() {
    if [ "$OFFLINE" = 1 ]; then _rdev="$DISK"; _rsec=$((ROOT_START + 2))
    else _rdev="$P2"; _rsec=2; fi
    dd if="$_rdev" bs=512 skip="$_rsec" count=1 2>/dev/null |
        dd bs=1 skip=104 count=16 2>/dev/null | od -An -tx1 | tr -d " \n" |
        sed -e 's/^\(........\)\(....\)\(....\)\(....\)\(............\)$/\1-\2-\3-\4-\5/'
}
_sha() { sha256sum 2>/dev/null | cut -d' ' -f1; }
# Every file the ESP must carry, as "<source> <esp path>" lines.
esp_manifest() {
    printf '%s %s\n' "$PAYLOAD/kernel.elf" "/boot/kernel.elf"
    printf '%s %s\n' "$PAYLOAD/BOOTX64.EFI" "/EFI/BOOT/BOOTX64.EFI"
    [ -f "$PAYLOAD/initramfs-min.cpio" ] && printf '%s %s\n' "$PAYLOAD/initramfs-min.cpio" "/boot/initramfs-min.cpio"
    # limine.conf is compared with the file this run generated; a --verify run
    # generated none, and comparing the ESP's copy with itself would be a check
    # that cannot fail — its content is judged by the UUID check instead.
    [ "$VERIFY_ONLY" = 1 ] || printf '%s %s\n' "/tmp/limine.conf" "/limine.conf"
    printf '%s\n' "$LOADER_ALIASES" | while IFS= read -r _a; do
        [ -n "$_a" ] || continue
        printf '%s %s\n' "$PAYLOAD/BOOTX64.EFI" "$(printf '%s' "$_a" | tr '\\' '/')"
    done
}
# THE VERIFICATION, by content. Re-reads what is on the disk and compares it
# with the sources; nothing is taken from the install's own bookkeeping.
efi_verify() {
    _vf=0
    echo ">> VERIFY $DISK (re-reading the disk)"
    if "$AGPT" verify "$DISK"; then echo ">>   ok   GPT: protective MBR, both headers + entry arrays CRC-valid and identical"
    else echo "!!   FAIL GPT verification"; _vf=1; fi
    # `&& || ` and not `; _rc=$?`: under set -e a failing command substitution
    # in an assignment would end the script before the verdict is printed.
    _fsck=$(/sbin/e2fsck -fn "$ROOTSPEC" 2>&1) && _rc=0 || _rc=$?
    if [ "$_rc" = 0 ]; then echo ">>   ok   e2fsck -fn $ROOTSPEC: $(printf '%s\n' "$_fsck" | tail -1)"
    else echo "!!   FAIL e2fsck -fn $ROOTSPEC exit $_rc:"; printf '%s\n' "$_fsck" | tail -5 | sed 's/^/!!     /'; _vf=1; fi
    _tmpl=$(mktemp)
    esp_manifest > "$_tmpl"
    while read -r _src _dst; do
        _want=$(_sha < "$_src")
        _got=$(/bin/mtype -i "$ESPI" "::$_dst" 2>/dev/null | _sha)
        if [ -n "$_want" ] && [ "$_want" = "$_got" ]; then echo ">>   ok   ESP ::$_dst sha256 ${_got%"${_got#????????????}"}… = $_src"
        else echo "!!   FAIL ESP ::$_dst sha256 '${_got}' != $_src '${_want}'"; _vf=1; fi
    done < "$_tmpl"
    rm -f "$_tmpl"
    _wrote=$(/bin/mtype -i "$ESPI" ::/limine.conf 2>/dev/null |
             grep -o 'root=disk:UUID=[0-9a-fA-F-][0-9a-fA-F-]*' | head -1 | sed 's/^root=disk:UUID=//')
    _sb=$(root_sb_uuid)
    if [ -n "$_wrote" ] && [ "$_wrote" = "$_sb" ]; then echo ">>   ok   limine.conf root=disk:UUID=$_wrote = the root superblock"
    else echo "!!   FAIL limine.conf names '$_wrote', root superblock is '$_sb'"; _vf=1; fi
    if [ "$_vf" = 0 ]; then echo ">> VERIFY OK: $DISK"; else echo "!! VERIFY FAILED: $DISK"; fi
    return $_vf
}
# ---- --offline: the live root as a filtered view for `mke2fs -d /` ----------
#
# What the mount path LEAVES OUT or RECREATES EMPTY (see its `case "$n"` and
# the /State piecewise copy below) is expressed here as ainstfilter lists, so
# the two paths install the same tree:
#   skipped      /run /mnt /lost+found /install /State/tmp, /toolchain if SLIM=1,
#                and /etc/live-marker (false on an installed disk)
#   empty dirs   /proc /sys /dev /tmp /Media /Mount /State/run /State/log
# Target-specific files (hostname, diskmarker, accounts) are written into an
# OVERLAY directory that mirrors the root's top-level compat symlinks, so every
# `$BASE/etc/...` write below resolves exactly as it would on the target.
OVERLAY=""; AINST_SKIP_L=""; AINST_EMPTY_L=""; OFFLINE_WALK=""
offline_prepare() {
    CSV=$(readlink /Apps/CoreSystem/Current 2>/dev/null)
    [ -n "$CSV" ] || CSV="${COREVER:-1.0}"
    # The SAME shape assertions the mount path makes on its target, made on the
    # SOURCE: with --offline there is no mounted target to inspect, and a view
    # of a broken source is a broken install.
    for l in bin sbin lib usr etc; do
        [ -L "/$l" ] || { echo "!! /$l is not a compat symlink — not a farm root"; exit 1; }
        case "$(readlink "/$l")" in /*) echo "!! /$l -> $(readlink "/$l") is ABSOLUTE"; exit 1 ;; esac
    done
    _setrel=$(readlink /etc)
    _nset=$(ls -1 "/$_setrel" 2>/dev/null | wc -l)
    [ "$_nset" -ge 5 ] || { echo "!! /$_setrel holds only $_nset entries"; exit 1; }
    _nstore=$(ls -1 "/Apps/CoreSystem/$CSV/bin" 2>/dev/null | wc -l)
    [ "$_nstore" -ge 20 ] || { echo "!! CoreSystem store bin/ holds only $_nstore entries"; exit 1; }
    for probe in $(_boot_probe init) $(_boot_probe sh); do
        [ -s "/Apps/CoreSystem/$CSV/$probe" ] || { echo "!! $probe missing in the source store"; exit 1; }
    done
    echo ">> source verified: compat links relative, Settings=$_nset entries, store bin=$_nstore entries"
    OVERLAY=$(mktemp -d /tmp/ainst-overlay.XXXXXX)
    # Mirror the root's top-level compat symlinks (etc -> System/Settings,
    # root -> Users/root, home -> Users, ...) so a write to "$BASE/root/x"
    # lands at the overlay's Users/root/x, i.e. where the target will have it.
    # The link's TARGET directory is created in the overlay too: without it
    # the link dangles and `mkdir -p "$BASE/root"` fails — measured, the first
    # offline install died there ("can't create directory
    # '/tmp/ainst-overlay.X/root': No such file or directory"). An ABSOLUTE
    # link would resolve against the LIVE system and write into the machine
    # doing the install, so it is refused rather than mirrored.
    for _e in /*; do
        [ -L "$_e" ] || continue
        _t=$(readlink "$_e")
        case "$_t" in
            /*) echo "!! $_e -> $_t is an ABSOLUTE link; the offline view cannot mirror it safely"; exit 1 ;;
        esac
        cp -a "$_e" "$OVERLAY/"
        [ -d "$_e" ] && mkdir -p "$OVERLAY/$_t"
    done
    mkdir -p "$OVERLAY/$_setrel"
    AINST_SKIP_L="/run:/mnt:/lost+found:/install:/State/tmp:/$_setrel/live-marker"
    [ "${SLIM:-0}" = 1 ] && AINST_SKIP_L="$AINST_SKIP_L:/toolchain"
    AINST_EMPTY_L="/proc:/sys:/dev:/tmp:/Media:/Mount:/State/run:/State/log"
    BASE="$OVERLAY"
    echo "${HOSTNAME:-AnotherOS}" > "$BASE/etc/hostname"
    echo installed > "$BASE/etc/diskmarker"
    echo ">> offline view: overlay $OVERLAY"
    echo ">>   skip  $AINST_SKIP_L"
    echo ">>   empty $AINST_EMPTY_L"
}
offline_mkfs() {
    _blocks=$((ROOT_SECS / 8))
    _count=$(mktemp /tmp/ainst-count.XXXXXX)
    rm -f "$_count"
    echo ">> creating the $ROOTFS root at byte $ROOT_OFF of $DISK ($_blocks 4 KiB blocks) from / through $_flt [t+$(_el)s]"
    env LD_PRELOAD="$_flt" AINST_ROOT=/ AINST_SKIP="$AINST_SKIP_L" AINST_EMPTY="$AINST_EMPTY_L" \
        AINST_OVERLAY="$OVERLAY" AINST_COUNT="$_count" \
        /sbin/mke2fs -F -q -t "$ROOTFS" -L AnotherRoot -b 4096 \
        -E "offset=$ROOT_OFF,nodiscard" -d / "$DISK" "$_blocks" || {
            echo "!! mke2fs -d at offset $ROOT_OFF failed — the root is NOT installed"; exit 1; }
    # PROVE THE FILTER WAS IN THE PROCESS. Without it `mke2fs -d /` would copy
    # /proc, /Media and /Mount and could still exit 0; the count file is written
    # only by ainstfilter's destructor.
    [ -s "$_count" ] || { echo "!! ainstfilter never reported — mke2fs ran WITHOUT the filter"; exit 1; }
    OFFLINE_WALK=$(cat "$_count")
    echo ">> populated [t+$(_el)s]: $OFFLINE_WALK"
    sync
}

if [ "$VERIFY_ONLY" = 1 ]; then
    efi_layout
    ROOT_START=${ROOT_START:-0}
    efi_verify
    exit $?
fi

# --- populate: mount the target and copy ONCE ------------------------------
#
# The target root is mke2fs'd EMPTY, mounted read-write (mount(2) — the kernel
# grew a real sys_mount for exactly this), and the live root is copied straight
# into the mount: squashfs -> ext2, one pass, no intermediate.
#
# History, because two designs died here and the reasons must not be re-learned:
#   * `cp -a` into /tmp then `mke2fs -d`: /tmp is a tmpfs whose file bodies are
#     contiguous kmallocs out of the FIXED 160 MiB kernel-heap window, so a
#     live-root-sized staging copy could not succeed on any machine, however
#     much RAM it had — and while the livelock lasted it wedged the whole box
#     (kernel/mm/heap.c, issue #28).
#   * hard-link staging (`aclone`) fixed the wedge but kept the shadow tree and
#     the aliasing hazard: a staged name WAS the live file, so every file the
#     installer edits had to be carefully re-materialised first.
# Mounting the target removes the intermediate entirely: edits below touch real
# files on the TARGET, so there is nothing to alias and nothing to stage.

# Resolve $BASE/<name> through the farm's compat symlink to the real directory
# INSIDE $BASE (e.g. $BASE/etc -> System/Settings). Absolute link targets are
# rooted at the TARGET, not at /.
# Where does <name> actually live in the CoreSystem store: sbin or bin?
# Answers from the RUNNING system, which is the tree being copied, so the probe
# tracks the layout instead of asserting one. Falls back to bin/<name> so the
# caller still gets a definite path to report when neither exists.
# Copy $1 into $2 WITHOUT overwriting anything already there.
#
# The conffile rule: a file the target does not have is new and is installed; a
# file the target DOES have is the user's and is left untouched, whatever the
# image ships. Directories are descended into rather than replaced, so a new
# default deep inside an existing directory still arrives.
#
# `cp -a` cannot express this (busybox has no -n here), so the walk is explicit.
# It is also the only correct order: testing the destination first and copying
# second means a file that appears between the two is still not clobbered,
# because cp is only ever reached for a path that did not exist.
_merge_noclobber() { # _merge_noclobber <srcdir> <dstdir>
    [ -d "$1" ] || return 0
    mkdir -p "$2"
    for _s in "$1"/* "$1"/.[!.]*; do
        [ -e "$_s" ] || [ -L "$_s" ] || continue
        _n=$(basename "$_s")
        _d="$2/$_n"
        if [ -d "$_s" ] && [ ! -L "$_s" ]; then
            _merge_noclobber "$_s" "$_d" || return 1
        elif [ -e "$_d" ] || [ -L "$_d" ]; then
            _KEPT=$((_KEPT + 1))            # the user's copy wins, always
        else
            cp -a "$_s" "$_d" || {
                echo "!! copying $_s into the target failed"; return 1; }
            _ADDED=$((_ADDED + 1))
        fi
    done
    return 0
}

_boot_probe() {
    for _d in sbin bin; do
        [ -s "/Apps/CoreSystem/Current/$_d/$1" ] && { echo "$_d/$1"; return; }
    done
    echo "bin/$1"
}

in_base() {   # in_base <name> -> prints the real directory path under $BASE
    _p="$BASE/$1"
    if [ -L "$_p" ]; then
        _t=$(readlink "$_p")
        case "$_t" in
            /*) _p="$BASE$_t" ;;
            *)  _p="$BASE/$_t" ;;
        esac
    fi
    printf '%s\n' "$_p"
}

# --- self-profiling ---------------------------------------------------------
#
# Every progress line carries "t+<seconds>", and the copy reports per-entry
# wall time. An install is minutes long and "make it faster" is meaningless
# without knowing WHICH minutes: the first attempt to speed this up was aimed at
# the metadata write path on the strength of a guess, when the only number in
# evidence was one total. Timing lives in the installer itself, not in a
# separately instrumented build, so every ordinary run — including one a user
# reports from real hardware — is a profile.
_T0=$(date +%s 2>/dev/null || echo 0)
_el() { _n=$(date +%s 2>/dev/null || echo 0); echo $((_n - _T0)); }

echo "=== AnotherOS install -> $DISK ==="
if [ "$UPGRADE" = 1 ]; then
    # NOT apart. An upgrade that repartitions is a reinstall that ate the user's
    # data, and the difference is one flag -- so the partitioner is not merely
    # skipped here, it is unreachable in this mode.
    echo ">> UPGRADE: keeping the existing partition table on $DISK"
    [ "$MODE" = efi ] && efi_layout
elif [ "$MODE" = efi ]; then
    echo ">> UEFI/GPT install (ESP + $ROOTFS root)$([ "$OFFLINE" = 1 ] && echo ', OFFLINE: whole-disk node only')"
    for _p in kernel.elf BOOTX64.EFI limine.conf.tmpl; do
        [ -f "$PAYLOAD/$_p" ] || { echo "!! $PAYLOAD/$_p missing — the ESP would not boot"; exit 1; }
    done
    if [ "$OFFLINE" = 1 ]; then
        _flt=$(_tool ainstfilter.so) || { echo "!! --offline needs ainstfilter.so (in $PAYLOAD)"; exit 1; }
        [ -L /bin ] && [ -d /Apps/CoreSystem ] || {
            echo "!! --offline installs the running FARM root; this system is not one"; exit 1; }
    fi
    AGPT=$(_tool agpt) || { echo "!! agpt not found"; exit 1; }
    if [ "$KEEP_TABLE" = 1 ]; then
        echo ">> keeping the existing GPT on $DISK"
        "$AGPT" verify "$DISK" || { echo "!! $DISK's GPT does not verify — refusing to install onto it"; exit 1; }
    else
        _norescan=""; [ "$OFFLINE" = 1 ] && _norescan="--no-rescan"
        "$AGPT" create "$DISK" --esp-mib "$ESP_MIB" $_norescan
    fi
    "$AGPT" show "$DISK" | sed 's/^/   /'
    efi_layout
    if [ "$OFFLINE" = 0 ]; then
        # The kernel must now publish the entries as nodes (#852's reader via
        # BLKRRPART). Bounded: the rescan is synchronous, so a node that is
        # not there after a few seconds is not coming.
        _w=0
        while [ ! -e "$P2" ] || [ ! -e "$P1" ]; do
            _w=$((_w + 1))
            [ "$_w" -le 10 ] || { echo "!! $P1/$P2 never appeared — does this kernel read GPT? (use --offline)"; exit 1; }
            sleep 1
        done
    fi
else
    echo ">> partitioning (FAT /boot + $ROOTFS root)"
    /sbin/apart -b "$DISK" >/dev/null
fi

if [ "$MODE" != efi ]; then
# p1 sector count from /proc/partitions (blocks are 1 KiB -> x2 sectors); mtools
# needs it since our kernel has no disk-geometry ioctl.
p1blocks=0
while read -r maj min blocks name; do
    [ "$name" = "${base}1" ] && p1blocks=$blocks
done < /proc/partitions
# /proc/partitions zero-pads the block count (e.g. 0000065536); force base-10 or
# bash arithmetic reads the leading zero as OCTAL. blocks are 1 KiB -> x2 sectors.
p1sectors=$(( 10#$p1blocks * 2 ))
fi

# With no explicit base tree, install the LIVE system. Two layouts:
#
#   FARM (default): a GoboLinux-style versioned tree — the live binaries and
#   libraries are placed under /Apps/CoreSystem/<ver>/{bin,sbin,lib,share} and
#   farmed into /System/Index via absolute symlinks, with /bin,/sbin,/lib,/usr as
#   compat symlinks into /System/Index and /System/Settings -> /etc. The core boot path
#   (init, login, bash) is static musl, so booting only needs the kernel to
#   resolve the /bin/init -> /System/Index/bin/init -> /Apps/CoreSystem/Current/...
#   symlink chain at exec (verified: the ext2 path walker follows farm chains).
#
#   FLAT (FLAT=1): the legacy flat FHS copy (/bin,/sbin,/lib,/etc,/usr).
#
# HOSTNAME (from the caller) overrides /etc/hostname either way.
MOUNTED=0
if [ "$OFFLINE" = 1 ]; then
    offline_prepare
elif [ -z "$BASE" ]; then
    # The target partition becomes $BASE directly: mke2fs it EMPTY, mount it
    # read-write, copy into the mount. Every `$BASE/...` below is a real file
    # on the TARGET DISK — no staging tree, no aliasing, no /tmp.
    echo ">> creating root filesystem on $P2 (empty, $ROOTFS) [t+$(_el)s]"
    if [ "$UPGRADE" = 1 ]; then
        # No mke2fs: the filesystem and everything on it stays. Verify it looks
        # like an AnotherOS root before writing into it, because mounting the
        # WRONG partition and replacing /Apps on it would be indistinguishable
        # from a successful upgrade until the machine failed to boot.
        echo ">> UPGRADE: reusing the filesystem on $P2 (no mke2fs)"
    else
        # -t selects the feature set: ext2 -> no journal/extents; ext4 ->
        # extents, htree (dir_index), metadata_csum -- all of which the kernel
        # writer maintains. mke2fs picks the on-disk features from the type.
        /sbin/mke2fs -F -q -t "$ROOTFS" -L AnotherRoot "$P2"
    fi
    BASE=/Mount/target
    mkdir -p "$BASE"
    # busybox mount -> mount(2) -> the kernel's runtime ext2 mount
    # (kernel/fs/ext2.c ext2_mount_part_at). NOT silenced: a failed mount here
    # means every subsequent write would land in RAM and evaporate at reboot,
    # with the install reporting success — the worst possible failure shape.
    if ! /bin/mount -t "$ROOTFS" "$P2" "$BASE"; then
        echo "!! mounting $P2 at $BASE failed — cannot populate the target."
        echo "!!   (kernel without sys_mount, or $P2 is not a valid $ROOTFS?)"
        exit 1
    fi
    MOUNTED=1
    echo ">> mounted $P2 read-write at $BASE [t+$(_el)s]"
    if [ "${FLAT:-0}" = 1 ]; then
        echo ">> assembling base system (flat FHS layout)"
        for d in bin sbin lib etc usr; do [ -e "/$d" ] && cp -a "/$d" "$BASE/" 2>/dev/null; done
        mkdir -p "$BASE/dev"
    elif [ -L /bin ] && [ -d /Apps/CoreSystem ]; then
        # ------------------------------------------------------------------
        # THE RUNNING SYSTEM IS ALREADY THE FARM — copy it, do not rebuild it.
        # ------------------------------------------------------------------
        # This is the whole point of unifying the live and installed layouts
        # (layout/farmify.sh, kernel.mk's liveroot target): when the source tree
        # already has the shape the target wants, the installer has nothing to
        # convert. Assembling it again here would not merely be redundant, it
        # would be CATASTROPHIC and SILENT:
        #
        #   On the farm, /bin is System/Index/bin and every name in it is a
        #   symlink to /Apps/CoreSystem/Current/bin/<x>. `cp -a` preserves
        #   symlinks, so `cp -a /bin/. $BASE/Apps/CoreSystem/<ver>/bin/` copies
        #   those ABSOLUTE links into the very directory they resolve to:
        #   /Apps/CoreSystem/Current/bin/<x> IS /Apps/CoreSystem/<ver>/bin/<x>
        #   on the target. Every binary on the installed disk becomes a symlink
        #   to itself. cp exits 0, the install reports success, and the disk
        #   cannot execute a single program.
        #
        # So: a straight copy of the real top-level entries, plus the
        # target-specific bits (fstab/UUID, accounts, bootloader) further down.
        CSV=$(readlink /Apps/CoreSystem/Current 2>/dev/null)
        [ -n "$CSV" ] || CSV="${COREVER:-1.0}"
        echo ">> the live system is already the farm layout (CoreSystem $CSV) — copying it into the mounted target"

        # Pseudo-filesystems, RAM-only runtime dirs, and anything that may have
        # a MEDIUM mounted under it. /Media in particular holds the boot CD:
        # copying it would pull the entire ISO — including the SquashFS image
        # we are running from — onto the target. /Mount holds the TARGET
        # MOUNTPOINT itself: recursing into your own destination is an infinite
        # copy that fills the disk.
        #
        # /toolchain is the NATIVE self-hosting compiler (cc/gcc/g++/binutils +
        # the musl sysroot), built to run on-device (toolchain/anotheros-gcc/
        # build-native.sh) and staged into the live root by kernel.mk. The
        # owner's standing goal is that EVERY install self-hosts, so it is KEPT
        # BY DEFAULT — the ~270 MB is the price of a machine that can compile its
        # own software with no cross host. `SLIM=1 ainstall ...` opts OUT for a
        # runtime-only disk (KEEPDEV=1 is still honoured for back-compat and is
        # now a no-op, since keeping is the default). When a base image was built
        # WITHOUT the toolchain there is simply no /toolchain to copy and this
        # case never fires.
        for e in /*; do
            n=${e#/}
            case "$n" in
                proc|sys|dev|tmp|run|Media|Mount|mnt|lost+found) continue ;;
                # /install is the INSTALLER's payload -- the kernel, the rescue
                # cpio, limine-bios.sys and the boot template that THIS script
                # copies onto the target's FAT /boot a few dozen lines down.
                # The installed system has no use for a second copy of them: it
                # boots the kernel already on its own /boot, and asys(8) fetches
                # replacements from the repository rather than from here. Copying
                # it would put ~7 MB of build artefacts on every installed disk
                # and, worse, a SECOND kernel that nothing updates -- a stale one
                # sitting next to the live one is how the wrong kernel gets
                # picked up by hand later.
                install) continue ;;
                toolchain)
                    if [ "${SLIM:-0}" = 1 ]; then
                        echo ">>   /toolchain SKIPPED (SLIM=1) — the installed disk will NOT self-host"
                        continue
                    fi
                    echo ">>   /toolchain kept — the installed disk self-hosts (cc/gcc on-device)"
                    ;;
                System)
                    if [ "$UPGRADE" = 1 ]; then
                        # /System is the one tree that is BOTH. Settings is /etc
                        # and belongs to the user; Index is a generated symlink
                        # farm; Kernel and Fonts are payload. So it is walked
                        # per-child rather than replaced or skipped wholesale --
                        # doing either would lose configuration or leave a stale
                        # index behind.
                        mkdir -p "$BASE/System"
                        _KEPT=0; _ADDED=0
                        for sy in /System/*; do
                            syn=${sy#/System/}
                            case "$syn" in
                                Settings)
                                    _merge_noclobber "$sy" "$BASE/System/Settings" || exit 1
                                    ;;
                                Index)
                                    # Regenerated below by asymlink from the new
                                    # store; copying the live one would point the
                                    # target at THIS machine's paths.
                                    rm -rf "$BASE/System/Index"
                                    ;;
                                *)
                                    rm -rf "$BASE/System/$syn"
                                    cp -a "$sy" "$BASE/System/" || {
                                        echo "!! copying /System/$syn into the target failed"
                                        exit 1; }
                                    ;;
                            esac
                        done
                        echo ">>   /System merged (upgrade): Settings kept $_KEPT existing file(s), added $_ADDED new"
                        continue
                    fi ;;
                # ---- UPGRADE: the user's trees are not ours to replace -------
                # An upgrade reinstalls the OS. These hold what the OS is FOR,
                # so on this path they are not copied at all: whatever is on the
                # disk stays exactly as it is, byte for byte.
                Users|Files)
                    if [ "$UPGRADE" = 1 ]; then
                        echo ">>   /$n preserved (upgrade)"
                        continue
                    fi ;;
                State)
                    if [ "$UPGRADE" = 1 ]; then
                        # The apkg database lives here. Replacing it would tell
                        # the upgraded system it has none of the packages that
                        # are still sitting in /Apps.
                        echo ">>   /State preserved (upgrade — holds the package database)"
                        continue
                    fi
                    # /State piecewise: State/run holds LIVE runtime objects —
                    # on a desktop boot, the compositor's sockets — and busybox
                    # cp cannot recreate a socket, so a whole-tree `cp -a
                    # /State` aborts a GUI-session install. run/log/tmp are
                    # boot-time state anyway; they are recreated empty below.
                    mkdir -p "$BASE/State"
                    for se in /State/*; do
                        sn=${se#/State/}
                        case "$sn" in run|log|tmp) continue ;; esac
                        cp -a "$se" "$BASE/State/" || {
                            echo "!! copying /State/$sn into the target failed — refusing to continue"
                            exit 1; }
                    done
                    continue ;;
            esac
            # NOT silenced, and NOT `|| true`. A failed copy here is a broken
            # install; the whole reason the /etc bug survived for months is that
            # its failure was routed to /dev/null. (`cp -a` implies -d, so the
            # farm's compat symlinks — /bin, /etc, /usr — are copied AS
            # symlinks, which is exactly right: their targets under /System and
            # /Apps are real directories copied on their own turn.)
            _es=$(date +%s 2>/dev/null || echo 0)
            cp -a "$e" "$BASE/" || {
                echo "!! copying /$n into the target failed — refusing to continue"
                exit 1; }
            echo ">>   /$n in $(( $(date +%s 2>/dev/null || echo 0) - _es ))s (t+$(_el)s)"
        done
        # --- the copy itself must be VERIFIED, not assumed ------------------
        #
        # busybox `cp -a` on the farm root has four documented ways to go wrong
        # (symlink DESTINATIONS, dereferenced symlinks, order, busybox-vs-GNU
        # flag drift), and a broken copy here produces a target that LOOKS
        # installed and still boots partway — the failure mode that costs
        # sessions. The per-entry `cp -a /$name "$BASE/"` form never writes
        # THROUGH a symlink (each compat link is copied as itself), but that is
        # an argument, not evidence. These are the evidence, on the target, in
        # the live environment, before anything builds on the copy — the same
        # shape assertions farmify_test.sh makes for a staged tree:
        for l in bin sbin lib usr etc; do
            [ -L "$BASE/$l" ] || {
                echo "!! target /$l is NOT a symlink — cp dereferenced the compat"
                echo "!!   link (a duplicated runtime and no farm). Aborting."
                ls -ld "$BASE/$l" 2>&1; exit 1; }
            case "$(readlink "$BASE/$l")" in
                /*) echo "!! target /$l -> $(readlink "$BASE/$l") is ABSOLUTE —"
                    echo "!!   it would resolve against whatever system mounts the"
                    echo "!!   disk, not the disk itself. Aborting."; exit 1 ;;
            esac
        done
        _settings=$(in_base etc)
        _nset=$(ls -1 "$_settings" 2>/dev/null | wc -l)
        if [ "$_nset" -lt 5 ]; then
            echo "!! $_settings holds only $_nset entries after the copy — the"
            echo "!!   system configuration did not arrive. Aborting."
            exit 1
        fi
        _nstore=$(ls -1 "$BASE/Apps/CoreSystem/$CSV/bin" 2>/dev/null | wc -l)
        if [ "$_nstore" -lt 20 ]; then
            echo "!! CoreSystem store bin/ holds only $_nstore entries — the"
            echo "!!   runtime did not arrive. Aborting."
            exit 1
        fi
        echo ">> copy verified: compat links are relative symlinks, Settings=$_nset entries, store bin=$_nstore entries"

        # Mount points and pseudo-fs roots the copy deliberately skipped.
        mkdir -p "$BASE/dev" "$BASE/proc" "$BASE/sys" "$BASE/tmp" \
                 "$BASE/Mount" "$BASE/Media" "$BASE/State/run" "$BASE/State/log"
        chmod 1777 "$BASE/tmp" 2>/dev/null || true

        # Headers and static archives (~25 MB) are KEPT on this path — unlike
        # the old staged flow, which dropped them to keep the staging tree
        # small. Here they are already on the target, deleting ~20k files
        # through per-file ext2 unlinks would cost real minutes, the disk space
        # is negligible on any target the image fits, and keeping them keeps
        # /System/Index/include consistent without surgery. /toolchain (the
        # 270 MB cross toolchain) is still skipped at the source above.

        # Seed the apkg DB if the source did not carry one.
        dbi="$BASE/State/lib/apkg/installed/CoreSystem"
        mkdir -p "$dbi" 2>/dev/null || true
        [ -f "$dbi/version" ] || echo "$CSV" > "$dbi/version" 2>/dev/null || true
        [ -f "$dbi/type" ]    || echo "cli"  > "$dbi/type"    2>/dev/null || true
        echo ">> copied the farm ($(ls -1 "$BASE" | wc -l) top-level entries) [t+$(_el)s]"
    else
        echo ">> assembling base system (/Apps + /System/Index farm)"
        CSV="${COREVER:-1.0}"
        # Build the hierarchy with the CANONICAL, tested builder rather than
        # ad-hoc mkdir/ln. askeleton (layout/skeleton.sh) creates System/Index,
        # System/Settings, System/Fonts, State/lib/apkg/{installed,repo}, Users
        # and every compat symlink (/bin,/usr,/etc,...) idempotently — the same
        # skeleton pkgtest.sh exercises. The previous hand-rolled version built
        # the structure entry by entry and failed unpredictably (writes into
        # State/etc came back ENOENT part way through the install). One builder,
        # tested once, used everywhere.
        /sbin/askeleton "$BASE" || { echo "!! askeleton failed"; exit 1; }
        [ -d "$BASE/System/Index/bin" ] && [ -d "$BASE/State/lib/apkg/installed" ] || {
            echo "!! hierarchy incomplete after askeleton"; ls -la "$BASE" "$BASE/State" 2>&1; exit 1; }

        CS="$BASE/Apps/CoreSystem/$CSV"
        mkdir -p "$CS/bin" "$CS/sbin" "$CS/lib"
        echo ">> copying the runtime into CoreSystem"
        # RUNTIME only, not the dev toolchain: /usr/include (headers, ~22 MB) and
        # static /usr/lib/*.a are compile-time and are skipped — the same reason
        # slim-initramfs keeps them off the RAM image. A later `apkg install` can
        # add a toolchain. Applet symlinks (ls -> busybox) are relative so they
        # still resolve inside the copied bin/.
        #
        # These copies are NOT silenced. They used to be
        # `cp -a ... 2>/dev/null || true`, the exact construction that let the
        # /etc copy fail on every install for months without a word — the whole
        # runtime of the installed system passes through these six lines, and
        # discarding their errors means a half-populated disk reports success.
        # A source directory that is genuinely absent is fine and is skipped;
        # a copy that STARTS and fails is fatal.
        copy_into() {   # copy_into <src-dir> <dst-dir>
            [ -d "$1" ] || return 0
            mkdir -p "$2"
            if ! err=$(cp -a "$1/." "$2/" 2>&1); then
                echo "!! copying $1 into ${2#$BASE} failed:"
                printf '%s\n' "$err" | sed 's/^/!!   /' | head -n 5
                echo "!! the installed system would be missing part of its runtime; aborting"
                exit 1
            fi
        }
        for s in /bin /usr/bin;   do copy_into "$s" "$CS/bin";  done
        for s in /sbin /usr/sbin; do copy_into "$s" "$CS/sbin"; done
        for s in /lib /usr/lib;   do copy_into "$s" "$CS/lib";  done
        rm -f "$CS"/lib/*.a 2>/dev/null || true
        # LinuxKPI DRIVER MODULES (GPU: i915/radeon/nouveau + the DRM helpers).
        # The kernel autoloads these from /lib/modules on the pivoted root
        # (kernel/kern/main.c gpu64_autoload, matched by PCI vendor). They ride in
        # via the /lib copy above — but a display adapter with NO driver .ko is a
        # SILENT, miserable failure: the desktop falls back to fully-CPU rendering,
        # which on the Dell meant Firefox OOM-killing itself. So install them
        # EXPLICITLY and FAIL LOUD if none landed — never ship an installed disk
        # that cannot bring up its GPU. cp -a (not the conffile no-clobber walk):
        # a .ko must always match the kernel it ships beside, never be "kept".
        if [ -d /lib/modules ]; then
            mkdir -p "$CS/lib/modules"
            if ! err=$(cp -a /lib/modules/. "$CS/lib/modules/" 2>&1); then
                echo "!! installing /lib/modules failed:"; printf '%s\n' "$err" | sed 's/^/!!   /' | head -3
                echo "!! the installed system would have NO device drivers; aborting"; exit 1
            fi
            _nko=$(ls "$CS"/lib/modules/*.ko 2>/dev/null | wc -l)
            if [ "${_nko:-0}" -lt 1 ]; then
                echo "!! no driver modules (.ko) installed to /lib/modules — the GPU would run"
                echo "!! fully in software (and OOM); aborting rather than ship a crippled disk"
                exit 1
            fi
            echo ">> installed $_nko driver modules to /lib/modules (i915/radeon/nouveau + DRM helpers) [t+$(_el)s]"
        else
            echo "!! WARNING: the live root has no /lib/modules — the installed system will have NO GPU driver"
        fi
        copy_into /usr/share   "$CS/share"
        copy_into /usr/libexec "$CS/libexec"

        # Farm CoreSystem into the index with the SAME tool the package manager
        # uses (asymlink), so the installed disk's farm is built by proven code
        # rather than a second hand-rolled loop. $AROOT makes it target $BASE.
        echo ">> farming CoreSystem into /System/Index"
        AROOT="$BASE" /bin/asymlink CoreSystem "$CSV"

        # Config: /etc is a compat symlink to System/Settings (askeleton made it);
        # copy the live /etc through it. Seed the apkg DB so `apkg list` shows the
        # pre-installed CoreSystem.
        # NOT silenced. This used to be `cp -a /etc/. "$BASE/etc/" 2>/dev/null
        # || true`, and it was failing COMPLETELY: the installed system's /etc
        # held only the five files written by hand further down (diskmarker,
        # hostname, login, passwd, shadow) and none of the real configuration —
        # no fstab, no shells, no resolv.conf, no profile, no mke2fs.conf. Every
        # existing assertion happened to check one of those five, so a total
        # failure to install the system configuration looked exactly like
        # success. Report what happens instead of discarding it.
        # Copy into the symlink's TARGET, not through the symlink.
        #
        # askeleton makes $BASE/etc a compat SYMLINK to System/Settings, and
        # `cp -a` implies -d (no-dereference), so `cp -a /etc/. "$BASE/etc/"`
        # died with "target '$BASE/etc/.' is not a directory" on every single
        # install. Resolve it to the real directory first.
        etcdir="$BASE/etc"
        if [ -L "$etcdir" ]; then
            tgt=$(readlink "$etcdir")
            case "$tgt" in
                /*) etcdir="$BASE$tgt" ;;   # absolute: rooted at the TARGET, not at /
                *)  etcdir="$BASE/$tgt" ;;  # relative: to $BASE, where the link lives
            esac
        fi
        mkdir -p "$etcdir"
        if [ -d /etc ]; then
            echo ">> copying system configuration into $etcdir"
            if cp -a /etc/. "$etcdir/"; then
                echo ">> config copied ($(ls -1 "$etcdir" 2>/dev/null | wc -l) entries)"
            else
                echo "!! copying /etc failed (rc=$?) — the installed system would"
                echo "!! have no system configuration; refusing to continue"
                exit 1
            fi
        else
            echo "!! no /etc on the live system to copy"; exit 1
        fi
        # Seed the apkg DB. Re-create the dir defensively (askeleton made it, but
        # the copies above churn the ramfs and a missing DB seed must not abort a
        # good install) and guard the writes.
        dbi="$BASE/State/lib/apkg/installed/CoreSystem"
        mkdir -p "$dbi" 2>/dev/null || true
        if [ -d "$dbi" ]; then
            echo "$CSV" > "$dbi/version" 2>/dev/null || echo ">> note: DB version seed skipped"
            echo "cli"  > "$dbi/type"    2>/dev/null || true
        else
            echo ">> note: could not create $dbi — apkg DB seed skipped (non-fatal)"
        fi
    fi
    # /dev is needed for the console before /proc,/sys mount; the kernel makes
    # /proc,/sys and init makes /tmp at boot.
    mkdir -p "$BASE/dev"
    # These are TARGET-specific: remove whatever the copy brought and write the
    # target's own values. $BASE/etc is the farm's RELATIVE compat symlink
    # (etc -> System/Settings), so these writes resolve inside the target.
    rm -f "$BASE/etc/hostname" "$BASE/etc/diskmarker" "$BASE/etc/live-marker"
    echo "${HOSTNAME:-AnotherOS}" > "$BASE/etc/hostname"
    echo installed > "$BASE/etc/diskmarker"
    # /etc/live-marker says "this root is served read-only from
    # filesystem.squashfs" (kernel.mk's liveroot target writes it). On a disk
    # installed FROM that live root it is simply false, and it is the file the
    # acceptance test uses to tell the two apart.

    # --- the boot path must be REAL FILES, not links to themselves ----------
    #
    # Checked for BOTH farm branches, because the failure it catches is silent
    # in a way no other assertion here would notice: if the runtime copy landed
    # symlinks pointing at /Apps/CoreSystem/Current/... inside
    # /Apps/CoreSystem/<ver>/... itself, then every one of those links resolves
    # to the file it is supposed to BE. `ls` shows the expected names, the farm
    # links under /System/Index all exist and point where they should, `cp`
    # exited 0, and the installed disk cannot exec anything at all.
    #
    # Assert the END of the chain: a regular file, not a symlink, with content.
    if [ "${FLAT:-0}" != 1 ]; then
        csv=$(readlink "$BASE/Apps/CoreSystem/Current" 2>/dev/null)
        [ -n "$csv" ] || csv="${COREVER:-1.0}"
        # NOTE: "is it a symlink?" is the WRONG test, and this guard shipped with
        # it for exactly one test run. /bin/sh in the store is `sh -> busybox`,
        # a RELATIVE applet link that resolves inside the same directory and is
        # completely correct — the assertion rejected a good install.
        #
        # The failure being guarded is specific: a link INTO
        # /Apps/CoreSystem/Current/..., which from inside
        # /Apps/CoreSystem/<ver>/ resolves back to the file being defined. So
        # test for that target, and otherwise just require the name to resolve
        # to a non-empty file ([ -s ] follows the link, which is the point).
        # init lives in sbin, sh in bin. This list said `bin/init` and aborted an
        # otherwise-complete install with "bin/init missing, empty or
        # unresolvable" — measured 2026-08-22, after the whole 1.7 GB farm had
        # copied cleanly (25 top-level entries, 726 store binaries, compat links
        # verified). The file was never missing: it is at
        # Apps/CoreSystem/<ver>/sbin/init, 46504 bytes, which is where it
        # belongs — kern/main.c execs "/sbin/init". The CHECK was looking in the
        # wrong directory.
        #
        # Resolved per-probe rather than by listing both, so a future layout
        # that moves one of them fails loudly instead of being quietly excused
        # by the other.
        for probe in $(_boot_probe init) $(_boot_probe sh); do
            f="$BASE/Apps/CoreSystem/$csv/$probe"
            if [ -L "$f" ]; then
                case "$(readlink "$f")" in
                    /Apps/CoreSystem/*)
                        echo "!! $probe in the target's CoreSystem links to $(readlink "$f")"
                        echo "!! — that path IS this file on the target, so it points at itself."
                        echo "!! The runtime was copied out of the farm's index instead of its"
                        echo "!! store. The disk would not boot. Aborting."
                        exit 1 ;;
                esac
            fi
            [ -s "$f" ] || { echo "!! $probe missing, empty or unresolvable in the target ($f)"; exit 1; }
        done
        # And the chain the kernel actually walks: /bin -> index -> store.
        [ -L "$BASE/bin" ] || { echo "!! target /bin is not the compat symlink"; exit 1; }
        # Same directory question as the probe above: the index mirrors the
        # store, so init's link is under System/Index/sbin when the store keeps
        # it in sbin.
        _ip=$(_boot_probe init)
        il=$(readlink "$BASE/System/Index/$_ip" 2>/dev/null)
        case "$il" in
            /Apps/CoreSystem/Current/*) ;;
            *) echo "!! target /System/Index/$_ip -> ${il:-MISSING}, expected /Apps/CoreSystem/Current/..."; exit 1 ;;
        esac
        echo ">> boot path verified: /bin -> $(readlink "$BASE/bin"), index init -> $il, store file is real"
    fi
fi

# Accounts: when the front-end supplies passwords (ROOTPW / NEWUSER+USERPW),
# seed /etc/passwd + /etc/shadow on the TARGET and enable console login via the
# /etc/login marker (init runs /sbin/login when it exists). Passwords are hashed
# by /sbin/passwd (crypt $6$) into the target's shadow via SHADOW_FILE.
if [ -n "$ROOTPW" ] || [ -n "$NEWUSER" ]; then
    echo ">> configuring accounts"
    # Target-specific files: drop whatever the copy brought before writing the
    # target's own accounts.
    rm -f "$BASE/etc/passwd" "$BASE/etc/shadow" "$BASE/etc/login"
    printf 'root:x:0:0:root:/root:/bin/bash\n' > "$BASE/etc/passwd"
    mkdir -p "$BASE/root"; : > "$BASE/etc/shadow"
    # Disable set -e around passwd: on-device its exit status is unreliable
    # (it hashes and writes shadow correctly but can return non-zero), and a
    # non-fatal password step must not abort the whole install or skip the
    # /etc/login marker that actually enables console login.
    set +e
    # WHERE passwd IS, not where it was: the CoreSystem store keeps it in bin/,
    # so the old hardcoded /sbin/passwd exited 127 on every x86_64 install that
    # set a password — measured 2026-09-14 in an offline install log ("root
    # password set (passwd rc=127)") — and wrote /etc/login over an EMPTY
    # shadow. Same class as #609's /sbin/limine.
    PASSWD=
    for _p in /sbin/passwd /bin/passwd /usr/bin/passwd; do
        [ -x "$_p" ] && { PASSWD="$_p"; break; }
    done
    [ -n "$PASSWD" ] || { echo "!! no passwd binary — cannot set account passwords; refusing to enable a login with none"; exit 1; }
    if [ -n "$ROOTPW" ]; then
        printf '%s\n' "$ROOTPW" | SHADOW_FILE="$BASE/etc/shadow" "$PASSWD" -s root
        echo ">> root password set (passwd rc=$?)"
    fi
    if [ -n "$NEWUSER" ]; then
        printf '%s:x:1000:1000:%s:/home/%s:/bin/bash\n' "$NEWUSER" "$NEWUSER" "$NEWUSER" >> "$BASE/etc/passwd"
        mkdir -p "$BASE/home/$NEWUSER"
        if [ -n "$USERPW" ]; then
            printf '%s\n' "$USERPW" | SHADOW_FILE="$BASE/etc/shadow" "$PASSWD" -s "$NEWUSER"
            echo ">> user $NEWUSER password set (passwd rc=$?)"
        fi
    fi
    set -e
    : > "$BASE/etc/login"
    echo ">> configured accounts (login enabled): $(ls -1 "$BASE"/etc/login 2>&1)"
fi

# --- SELF-HOST wiring: confirm (and, cheaply, ENSURE) the disk can compile ----
#
# The native toolchain rides in from the live root's /toolchain (kept above
# unless SLIM=1). cc/gcc reach PATH two ways: the CoreSystem /bin symlinks baked
# by kernel.mk, and the /toolchain/bin entry in /etc/profile. This block asserts
# the END of that chain is a real compiler on the TARGET — reporting a broken or
# absent toolchain HERE, at install time, instead of leaving a user to discover
# it by typing `cc` on the installed machine. It also (idempotently) adds the
# /bin driver links if they are missing, so a toolchain delivered some other way
# (e.g. a future apkg) still lands on PATH. This runs while $BASE is still
# populated, i.e. BEFORE the umount below.
# --offline: the source of the view IS /, and $BASE is the overlay, so the
# toolchain is looked for on / and the driver links go into the overlay only
# where / lacks them.
_tcsrc="$BASE"; [ "$OFFLINE" = 1 ] && _tcsrc=""
if [ -e "$_tcsrc/toolchain/bin/cc" ] && { [ "$OFFLINE" = 0 ] || [ "${SLIM:-0}" != 1 ]; }; then
    _bindir="$BASE/bin"
    if [ -L "$_bindir" ]; then
        _bt=$(readlink "$_bindir")
        case "$_bt" in /*) _bindir="$BASE$_bt" ;; *) _bindir="$BASE/$_bt" ;; esac
    fi
    mkdir -p "$_bindir"
    for _d in cc gcc g++ c++ cpp; do
        [ -e "$_tcsrc/toolchain/bin/$_d" ] || continue
        [ -e "$_bindir/$_d" ] && continue
        [ "$OFFLINE" = 1 ] && [ -e "/bin/$_d" ] && continue
        ln -sfn "/toolchain/bin/$_d" "$_bindir/$_d"
    done
    _nh=$(find "$_tcsrc/toolchain" -name '*.h' 2>/dev/null | wc -l)
    echo ">> SELF-HOST: the installed disk carries the native toolchain (/toolchain/bin/cc, $_nh headers) — it compiles on-device [t+$(_el)s]"
else
    echo ">> SELF-HOST: no /toolchain on the target — the installed disk is runtime-only (SLIM=1, or the image shipped no native toolchain)"
fi

if [ "$MOUNTED" = 1 ]; then
    # Everything is on the target already (it was populated through the mount).
    # sync + umount BEFORE the bootloader work: umount flushes the batched ext2
    # metadata and the drive's write cache, so every byte of the copied system
    # is on stable storage before limine touches the MBR and before reboot.
    echo ">> unmounting the populated target (flushes batched metadata + drive cache) [t+$(_el)s]"
    sync
    /bin/umount "$BASE" || { echo "!! unmounting $BASE failed"; exit 1; }
elif [ "$OFFLINE" = 1 ]; then
    offline_mkfs
else
    # Legacy path: an explicit base tree was supplied — populate via mke2fs -d
    # as before (this is also the escape hatch if the mount path misbehaves:
    # prepare a tree and pass it as argument 2).
    echo ">> creating root filesystem on $P2 (from tree $BASE, $ROOTFS)"
    /sbin/mke2fs -F -q -t "$ROOTFS" -L AnotherRoot -d "$BASE" "$P2"
fi
# THE ROOT UUID, TAKEN FROM THE SUPERBLOCK AND NOT ONLY FROM blkid.
#
# THIS COST A MACHINE. An install completed with RC=0, reported 3726/3726 group
# descriptors valid, and produced a box that sat on the boot splash forever with
# no sshd and no desktop. The cause was one line in the generated limine.conf:
# it named `root=disk:UUID=d1f7d4f1-...` while the filesystem's actual UUID —
# in BOTH the primary and the backup superblock, with `Filesystem created` set
# to the install's own timestamp — was `43dbe7de-...`. The kernel could not
# resolve the partition, said so ("did not resolve to a partition — / stays the
# initramfs"), and fell back to the initramfs, which has no /etc/rc worth
# running. Every symptom after that was a consequence: no services, no ssh, a
# splash that never goes away.
#
# The installer had a guard for the WRONG THING. It proved the template
# substitution HAPPENED (no `@NAME@` survived) and never proved the VALUE was
# right — so a correct-looking config naming a nonexistent filesystem sailed
# through. Asserting the shape of a string is not asserting the fact it encodes.
#
# So: read s_uuid straight off the platter (superblock at byte 1024, s_uuid at
# +104 = byte 1128) and treat THAT as the truth. It is an outside authority
# relative to blkid — different code, different caches — and the two are
# compared rather than one being trusted. Where they disagree, the superblock
# wins, because it is what the kernel's own root_disk_resolve() reads.
sb_uuid() {
    dd if="$1" bs=1 skip=1128 count=16 2>/dev/null | od -An -tx1 | tr -d " \n" |
        sed -e 's/^\(........\)\(....\)\(....\)\(....\)\(............\)$/\1-\2-\3-\4-\5/'
}

UUID=$(root_sb_uuid)
if [ "$OFFLINE" = 1 ]; then
    # blkid cannot take an offset; dumpe2fs (libext2fs, a different reader
    # from the raw dd above) can, through the unix io manager's ?offset=.
    BLKID_UUID=$(/sbin/dumpe2fs -h "$ROOTSPEC" 2>/dev/null | sed -n 's/^Filesystem UUID:[[:space:]]*//p')
else
    BLKID_UUID=$(/sbin/blkid -s UUID -o value "$P2" 2>/dev/null)
fi
case "$UUID" in
    ????????-????-????-????-????????????) ;;
    *) echo "!! could not read a well-formed UUID from $P2's superblock (got '$UUID')"
       exit 1 ;;
esac
if [ "$UUID" != "$BLKID_UUID" ]; then
    echo "!! blkid and the superblock DISAGREE about $P2's UUID:"
    echo "!!   superblock: $UUID   <- using this one"
    echo "!!   blkid:      $BLKID_UUID"
    echo "!! this is the failure that produced an unbootable install; continuing"
    echo "!! with the superblock's value, which is what the kernel resolves."
fi
echo ">> root UUID = $UUID (from the superblock; blkid said '$BLKID_UUID')"

MCOPY_O=""
if [ "$MODE" = efi ]; then
    # THE ESP. Formatted only when this install created it (or --format-esp):
    # --keep-table defaults to KEEPING the ESP's files, because an ESP is
    # shared — another OS's loader, or the firmware's own recovery tools, live
    # there — and our files only ever need to be ADDED. `mcopy -o` overwrites
    # our own names without prompting (a prompt on a serial console is a hang).
    MCOPY_O="-o"
    if [ "$ESP_FORMAT" = 1 ]; then
        echo ">> formatting the ESP ($ESPI, $p1sectors sectors, FAT) [t+$(_el)s]"
        # FAT32 when the ESP is big enough to hold one (UEFI 2.x says the ESP
        # "should" be FAT32; mformat refuses -F below ~65525 clusters), else
        # the width mformat picks — the same rule tools/mkefiboot.sh uses.
        if [ "$p1sectors" -ge 524288 ]; then _fat=-F; else _fat=; fi
        /bin/mformat -i "$ESPI" -T "$p1sectors" $_fat -v ANOTHEROS ::
    else
        echo ">> keeping the ESP's existing files ($ESPI); adding AnotherOS's [t+$(_el)s]"
        /bin/mdir -i "$ESPI" :: >/dev/null 2>&1 || { echo "!! $ESPI is not a readable FAT filesystem — use --format-esp"; exit 1; }
    fi
    for _d in /boot /EFI /EFI/BOOT; do
        /bin/mdir -i "$ESPI" "::$_d" >/dev/null 2>&1 || /bin/mmd -i "$ESPI" "::$_d"
    done
    /bin/mcopy $MCOPY_O -i "$ESPI" "$PAYLOAD/kernel.elf" ::/boot/kernel.elf
    # Limine's UEFI loader at the REMOVABLE-MEDIA path. Every UEFI firmware
    # boots \EFI\BOOT\BOOTX64.EFI from a disk with no Boot#### variable at all,
    # so this is what makes the disk bootable before (and without) any NVRAM
    # write. boot():/ in limine.conf is then this partition.
    /bin/mcopy $MCOPY_O -i "$ESPI" "$PAYLOAD/BOOTX64.EFI" ::/EFI/BOOT/BOOTX64.EFI
    # --efi-loader-alias: the SAME binary at another path, for firmware whose
    # NVRAM still names an old loader (a MacBook whose Boot0000 points at
    # \EFI\ubuntu\shimx64.efi). A compatibility aid, never the default: it
    # overwrites whatever that path held.
    printf '%s\n' "$LOADER_ALIASES" | while IFS= read -r _a; do
        [ -n "$_a" ] || continue
        _ap=$(printf '%s' "$_a" | tr '\\' '/')
        _acc=""
        for _seg in $(dirname "$_ap" | tr '/' ' '); do
            _acc="$_acc/$_seg"
            /bin/mdir -i "$ESPI" "::$_acc" >/dev/null 2>&1 || /bin/mmd -i "$ESPI" "::$_acc"
        done
        /bin/mcopy -o -i "$ESPI" "$PAYLOAD/BOOTX64.EFI" "::$_ap"
        echo ">> loader alias: ::$_ap = BOOTX64.EFI"
    done
else
echo ">> creating FAT /boot on $P1 ($p1sectors sectors) + copying kernel + Limine [t+$(_el)s]"
/bin/mformat -i "$P1" -T "$p1sectors" ::
/bin/mmd   -i "$P1" ::/boot
/bin/mcopy -i "$P1" "$PAYLOAD/kernel.elf"      ::/boot/kernel.elf
/bin/mcopy -i "$P1" "$PAYLOAD/limine-bios.sys" ::/limine-bios.sys
fi
# The rescue initramfs. A healthy installed boot never reads it — with
# `root=disk:UUID=` the kernel resolves the partition by UUID and pivots /
# cpio_load() — but it is what stands between "the root UUID no longer resolves"
# and a kernel with no root at all. The template's entries name it, so if it is
# NOT there the module lines have to go: Limine refuses to boot an entry whose
# module_path points at a missing file, which would turn a missing rescue image
# into an unbootable disk.
# DIAGNOSTIC PARAMETERS ARE CARRIED FROM THE LIVE SYSTEM INTO THE INSTALLED
# ONE, AND THAT IS THE WHOLE FIX FOR A REAL DEFECT.
#
# Until 2026-09-07 the installer wrote the template verbatim, so a machine
# installed from a live system booted with `logserver=` came up with NO remote
# logging and NO `panic=`. On the Dell that was measured twice: the install
# silently dropped both, the desktop then failed to start for an unrelated
# reason, and the one thing that would have explained it from off-machine --
# the netlog -- had been switched off by the install itself. The next person to
# hit it loses exactly the evidence they need, and nothing anywhere says so.
#
# WHY CARRY RATHER THAN HARDCODE. `logserver=10.1.14.10:5141` is one lab's
# address; baking it into the template would ship it to every user and send
# their kernel log to a host they have never heard of. Propagating what the
# INSTALLING system was booted with is the general rule: install from a box
# that logs to X and you get a box that logs to X; install from one that does
# not and nothing is added.
#
# WHAT IS CARRIED, and nothing else: `logserver=`, `fzlog=` and `panic=`. Every
# other word on the live cmdline is either about THIS boot (root=, nfsroot=,
# init=, nextgen, quiet, splash, debug) or a per-entry choice the template
# already makes, and copying those across would break the entries outright --
# an installed disk carrying the live boot's `root=squashfs:...` would not boot
# at all.
CARRY=""
for _tok in $(cat /proc/cmdline 2>/dev/null); do
    case "$_tok" in
        logserver=*|fzlog=*|panic=*) CARRY="$CARRY $_tok" ;;
    esac
done

# panic= DEFAULTS ON when the live system did not set one. A kernel that HALTS
# on panic needs someone to walk to the machine; one that reboots comes back and
# can be looked at. The Dell is a remote box behind a fingerbot that misses
# presses silently, so "halt" there costs a physical round trip -- but the
# reasoning is not lab-specific, it is true of any machine nobody is sitting at.
# INSTALL_PANIC=0 restores the halt for anyone who wants a panic to freeze the
# screen for a photograph.
case "$CARRY" in
    *panic=*) ;;
    *) CARRY="$CARRY panic=${INSTALL_PANIC:-20}" ;;
esac

# The menu timeout. 3 s was chosen so an entry is "selectable by hand", and that
# is too tight for a machine with no keyboard: the Dell is driven through a
# LanTester HID gadget over HTTP, and a request has to be dispatched, land, and
# be seen by Limine inside the window. 12 s is what the Dell's own config was
# hand-edited to, twice, for exactly this reason -- so it is the default rather
# than a thing every operator rediscovers. INSTALL_TIMEOUT overrides it.
INSTALL_TIMEOUT="${INSTALL_TIMEOUT:-12}"

# `|` as the sed delimiter: CARRY holds paths (fzlog=/run/fasadas.log) and `/`
# would end the expression. Same for the timeout line.
sed -e "s/@ROOTUUID@/$UUID/" \
    -e "s|@CARRY@|$CARRY|" \
    -e "s|^timeout: .*|timeout: $INSTALL_TIMEOUT|" \
    "$PAYLOAD/limine.conf.tmpl" > /tmp/limine.conf

# PROVE THE SUBSTITUTION HAPPENED. A template that gains a placeholder the
# installer does not know about would otherwise ship it verbatim onto the boot
# partition, and `@CARRY@` on a kernel command line is not a parse error -- the
# kernel would ignore it and the disk would boot, silently missing whatever the
# placeholder stood for. Refusing here is the difference between a loud failure
# and a machine that quietly lost its logging again.
# COMMENTS ARE EXCLUDED, and that was found by testing rather than by reading:
# the template's own documentation explains the placeholder mechanism and so
# CONTAINS the word `@NAME@`, which made the first version of this guard refuse
# every install. A check that fires on the prose describing it is worse than no
# check -- it would have sent the next person hunting a template bug that is not
# there. Only live config lines are scanned.
if grep -v '^[[:space:]]*#' /tmp/limine.conf | grep -q '@[A-Z][A-Z]*@'; then
    echo "!! limine.conf still holds an unsubstituted placeholder:" >&2
    grep -v '^[[:space:]]*#' /tmp/limine.conf \
        | grep -o '@[A-Z][A-Z]*@' | sort -u | sed 's/^/!!   /' >&2
    echo "!! refusing to write a boot config the installer does not fully understand" >&2
    exit 1
fi
if [ -f "$PAYLOAD/initramfs-min.cpio" ]; then
    /bin/mcopy $MCOPY_O -i "$ESPI" "$PAYLOAD/initramfs-min.cpio" ::/boot/initramfs-min.cpio
    echo ">> copied the rescue initramfs to /boot/initramfs-min.cpio"
else
    echo "!! $PAYLOAD/initramfs-min.cpio missing — writing a limine.conf with no"
    echo "!!   rescue module (the installed system still boots; a root that fails"
    echo "!!   to resolve will have no fallback shell)."
    grep -v '^ *module_path:\|^ *module_string:' /tmp/limine.conf > /tmp/limine.conf.nomod
    mv /tmp/limine.conf.nomod /tmp/limine.conf
fi
/bin/mcopy $MCOPY_O -i "$ESPI" /tmp/limine.conf         ::/limine.conf

# THE END-TO-END ASSERTION: does the config that actually landed on the boot
# partition name the filesystem that actually exists?
#
# This is the check whose absence produced an unbootable install (see the long
# note at the UUID read above). Every earlier guard tested a PROXY — the
# substitution happened, no placeholder survived, the descriptors validated —
# and every one of them passed over a config naming a UUID no partition had.
# The only check that could have caught it is this one: read the UUID back OUT
# of the written file, read the UUID back OUT of the superblock, and compare the
# two facts. Nothing derived, nothing cached, both sides re-read.
#
# It also covers the write itself: an mcopy that silently truncated, or a config
# whose sed produced a subtly different string, fails here rather than three
# reboots later on a machine with no way in.
WROTE=$(/bin/mtype -i "$ESPI" ::/limine.conf 2>/dev/null |
        grep -o 'root=disk:UUID=[0-9a-fA-F-][0-9a-fA-F-]*' | head -1 |
        sed 's/^root=disk:UUID=//')
DISK_UUID=$(root_sb_uuid)
if [ -z "$WROTE" ]; then
    echo "!! the limine.conf on $P1 carries no root=disk:UUID= line at all" >&2
    echo "!! refusing to finish: this disk would boot to the initramfs and sit" >&2
    echo "!! on the splash with no services" >&2
    exit 1
fi
if [ "$WROTE" != "$DISK_UUID" ]; then
    echo "!! THE BOOT CONFIG NAMES A FILESYSTEM THAT DOES NOT EXIST." >&2
    echo "!!   limine.conf says: $WROTE" >&2
    echo "!!   $P2 superblock:   $DISK_UUID" >&2
    echo "!! The kernel would print 'did not resolve to a partition — / stays" >&2
    echo "!! the initramfs' and the machine would sit on the boot splash with" >&2
    echo "!! no ssh and no desktop. Refusing to call this install complete." >&2
    exit 1
fi
echo ">> boot config verified: root=disk:UUID=$WROTE matches $P2's superblock"
echo ">> installed boot menu (default: the Fasadas desktop; a console entry is second):"
grep '^/\|^default_entry\|^ *cmdline:' /tmp/limine.conf | sed 's/^/     /'

if [ "$MODE" = efi ]; then
    # ---- NVRAM (#859) -------------------------------------------------------
    # A Boot#### entry is a convenience on top of \EFI\BOOT\BOOTX64.EFI, never
    # a requirement, so its absence is a LOGGED no-op with the exact command,
    # not a failure. `aefiboot` is the EFI-runtime work's boot-manager tool;
    # it is only called when the running system exposes EFI variables.
    _efib=$(_tool aefiboot 2>/dev/null || true)
    _loader='\EFI\BOOT\BOOTX64.EFI'
    _cmd="aefiboot create --disk $DISK --part $ESP_N --loader '$_loader' --label AnotherOS --order first"
    if [ "$NVRAM" != 1 ]; then
        echo ">> NVRAM: skipped (--no-nvram). To add the entry later: $_cmd"
    elif [ -z "$_efib" ]; then
        echo ">> NVRAM: NOT written — no aefiboot on this system. The disk boots through"
        echo ">>        $_loader regardless; to add a named, first-in-BootOrder entry run:"
        echo ">>          $_cmd"
    else
        # aefiboot validates the GPT, the ESP type and that the loader file is
        # really on that FAT before writing, and reads every variable back.
        # Exit 2 means "no EFI interface" (a BIOS boot, or `noefi`) — a no-op,
        # not a failure; anything else non-zero is reported and does not undo
        # an install that boots through the removable-media path anyway.
        echo ">> NVRAM: $_efib create --disk $DISK --part $ESP_N --loader '$_loader' --label AnotherOS --order first"
        _erc=0
        "$_efib" create --disk "$DISK" --part "$ESP_N" --loader "$_loader" --label AnotherOS --order first || _erc=$?
        case "$_erc" in
            0) echo ">> NVRAM: boot entry written and read back" ;;
            2) echo ">> NVRAM: NOT written — no EFI variable interface on this boot (BIOS boot or \`noefi\`)."
               echo ">>        The disk boots through $_loader regardless; later: $_cmd" ;;
            *) echo "!! NVRAM: aefiboot exited $_erc — no entry; the disk still boots through $_loader" ;;
        esac
    fi
    efi_verify || { echo "!! the installed disk did not verify — NOT calling this install complete"; exit 1; }
    echo "=== install complete: $DISK boots AnotherOS via UEFI (ESP entry $ESP_N, root=$UUID, root partuuid $ROOT_PARTUUID) — TOTAL $(_el)s ==="
    exit 0
fi

echo ">> installing Limine BIOS bootloader to $DISK [t+$(_el)s]"
# Resolve the limine binary. It installs into /Apps/limine/Current/bin and is
# symlinked from /usr/bin/limine and /bin/limine — NOT /sbin. A hardcoded
# `/sbin/limine` here left the Dell's freshly-installed disk unbootable on
# 2026-08-30 (#609): the root copy, the FAT /boot and the boot menu all
# succeeded, `set -e` then killed the script on "/sbin/limine: No such file",
# and the MBR bootcode was never written — a 99%-done install that silently
# produced a non-booting disk.
LIMINE=
for _l in /usr/bin/limine /bin/limine /sbin/limine; do
    [ -x "$_l" ] && { LIMINE="$_l"; break; }
done
[ -n "$LIMINE" ] || LIMINE=$(command -v limine 2>/dev/null || true)
[ -n "$LIMINE" ] || { echo "!! limine binary not found (looked in /usr/bin, /bin, /sbin and PATH) — disk is NOT bootable"; exit 1; }
"$LIMINE" bios-install "$DISK" >/dev/null || { echo "!! '$LIMINE bios-install $DISK' FAILED — disk is NOT bootable"; exit 1; }

echo "=== install complete: $DISK boots AnotherOS (root=$UUID) — TOTAL $(_el)s ==="
