#!/bin/sh
# nucleic-modsetup.sh — prepare the external kernel's modules on every boot (docs/LINUX_VM.md).
#
# The base boots an EXTERNAL Ubuntu kernel against the narOS rootfs into which the bootstrap baked
# the matching modules under the kernel's UNTAGGED release (e.g. /lib/modules/7.0.0-28-generic) —
# with no depmod indexes (the deb ships none; depmod normally runs in its postinst).
#
# Two narOS wrinkles this script absorbs (both learned from a real broken base — LINUX_VM.md
# §Debugging a failed base build):
#   1. naros-identity tags utsname.release (`uname -r` → …-generic-naros26.07), so kmod resolves
#      modules through the TAGGED path. naros-identity-modules.service symlinks the tagged name
#      onto the real directory, but it is a peer sysinit unit — even ordered After= it, this script
#      must not bet the control plane on another unit's presence, so it makes the same idempotent
#      symlink itself.
#   2. Failures here must be LOUD. A vsock transport that never loads surfaces minutes later as an
#      opaque host-side "agent never became reachable" timeout, so anything wrong is reported to
#      the journal AND the serial console (the host keeps that as provision.log / console.log).

REL="$(uname -r)"
REAL="$(NAROS_UNAME_PASSTHROUGH=1 uname -r 2>/dev/null)"
[ -n "$REAL" ] || REAL="$REL"

# Test hook (guest/linux-base/test/modsetup_test.sh): the module root is /lib/modules on a real
# guest, overridable so the logic is exercisable on any Linux without touching the host's modules.
MODROOT="${NUCLEIC_MODROOT:-/lib/modules}"

say() {
    echo "[nucleic-modsetup] $*"
    if [ -w /dev/hvc0 ]; then echo "[nucleic-modsetup] $*" > /dev/hvc0 2>/dev/null; fi
}

# Make $MODROOT/$(uname -r) resolve when the release is identity-tagged but the modules were
# baked under the real (passthrough) release. Same guards as naros-identity-modules.service, and
# safe to race it: both create the identical link, and ln -sfnT replaces atomically.
if [ ! -e "$MODROOT/$REL" ] && [ "$REL" != "$REAL" ] && [ -d "$MODROOT/$REAL" ]; then
    if ln -sfnT "$MODROOT/$REAL" "$MODROOT/$REL"; then
        say "aliased $MODROOT/$REL -> $REAL"
    else
        say "WARN: could not alias $MODROOT/$REL -> $REAL"
    fi
fi

if [ ! -d "$MODROOT/$REL" ]; then
    say "ERROR: no module directory for $REL (passthrough release: $REAL) — vsock/gpu cannot load"
    say "ERROR: $MODROOT contains: $(ls "$MODROOT" 2>/dev/null | tr '\n' ' ')"
    exit 0  # stay 'success': the agent unit keeps retrying and nucleic-bootdebug reports the state
fi

# The baked modules ship no depmod indexes; generate them for the release kmod resolves. stderr is
# deliberately NOT silenced — depmod problems must reach the journal.
depmod "$REL" || say "WARN: depmod $REL exited $?"

# vsock is the host<->guest control plane; without it the guest agent cannot bind AF_VSOCK.
if modprobe vmw_vsock_virtio_transport 2>/dev/null || modprobe vsock 2>/dev/null; then
    say "vsock transport loaded"
else
    say "ERROR: could not load a vsock transport — the guest agent cannot bind AF_VSOCK"
fi
# The desktop scanout; harmless to miss on headless boots.
modprobe virtio_gpu 2>/dev/null || say "WARN: virtio_gpu did not load"
exit 0
