Merge pull request 'feat(gpu): universal NVIDIA lane — detect + install branch at boot (C&C)' (#31) from nvidia-universal-lane into main

This commit is contained in:
clawdie 2026-06-04 22:22:22 +02:00
commit 972474e65a
4 changed files with 194 additions and 0 deletions

View file

@ -43,6 +43,14 @@ DEFAULT_DESKTOP="xfce" # operator USB desktop
# intel | amd | nvidia-590 | nvidia-470 | nvidia-390 | vesa | "" (auto-detect)
GPU_DRIVER=""
# Universal NVIDIA lane (opt-in). When YES, the image carries an on-image NVIDIA
# pkg repo for all three branches (390/470/580), does NOT bake a single branch,
# and clawdie_live_gpu runs in "nvidia-auto": at boot it detects the GPU, installs
# the matching branch from the on-image repo, and kldloads it before SDDM. On any
# failure it falls back to the integrated/scfb path (never worse than today).
# Builds a larger image. Leave NO for single-branch GPU_DRIVER=nvidia-* builds.
NVIDIA_UNIVERSAL="${NVIDIA_UNIVERSAL:-NO}"
# Deploy target
TARGET="baremetal" # vps | baremetal

View file

@ -119,6 +119,7 @@ echo " Clawdie : ${CLAWDIE_REF}"
echo " Desktop : ${DEFAULT_DESKTOP}"
echo " Pkg : ${DEFAULT_PKG_BRANCH}"
echo " GPU : ${GPU_DRIVER:-auto-detect}"
echo " NVIDIA universal : ${NVIDIA_UNIVERSAL:-NO}"
echo " Target : ${TARGET:-baremetal}"
echo " Colibri : ${FEATURE_COLIBRI:-NO}"
echo " Clawdie agent : ${FEATURE_CLAWDIE:-NO}"
@ -906,6 +907,48 @@ install_clawdie_service() {
fi
}
# Stage an on-image NVIDIA pkg repo (all branches) so clawdie_live_gpu can
# `pkg install` the detected branch at boot (NVIDIA_UNIVERSAL lane).
#
# FreeBSD-build-host step (authored on Linux; runs + must be validated on
# FreeBSD). Verify on the build host: (1) the `pkg fetch -o` layout matches what
# `pkg repo` expects, (2) the dependency closure is complete for offline boot
# install, (3) image size headroom, (4) `pkg install -r clawdie-nvidia` resolves
# from file:// at boot. See doc handoff.
install_nvidia_universal_repo() {
[ "${NVIDIA_UNIVERSAL:-NO}" = "YES" ] || {
echo " NVIDIA universal repo staging disabled (NVIDIA_UNIVERSAL=${NVIDIA_UNIVERSAL:-NO})"
return 0
}
echo " Staging universal NVIDIA repo (all branches) into image..."
_nv_repo="${MOUNT_POINT}/usr/local/share/clawdie/nvidia-repo"
mkdir -p "${_nv_repo}"
# Fetch all three branches + deps into the on-image repo dir, then build repo
# metadata. Uses pkg's own dependency resolution so the closure is complete.
if ! env ASSUME_ALWAYS_YES=yes pkg fetch -y -o "${_nv_repo}" -d \
nvidia-driver-390 nvidia-driver-470 nvidia-driver-580 nvidia-settings nvidia-xconfig; then
echo "ERROR: failed to fetch NVIDIA packages for universal repo"
exit 1
fi
if ! pkg repo "${_nv_repo}"; then
echo "ERROR: failed to generate NVIDIA universal repo metadata"
exit 1
fi
mkdir -p "${MOUNT_POINT}/usr/local/etc/pkg/repos"
cat > "${MOUNT_POINT}/usr/local/etc/pkg/repos/clawdie-nvidia.conf" <<'EOF'
# On-image NVIDIA package repo for the universal GPU lane. Consumed at boot by
# clawdie_live_gpu (nvidia-auto mode) via: pkg install -r clawdie-nvidia ...
clawdie-nvidia: {
url: "file:///usr/local/share/clawdie/nvidia-repo",
enabled: yes
}
EOF
echo " NVIDIA universal repo staged at /usr/local/share/clawdie/nvidia-repo"
}
install_live_npm_globals() {
echo " Installing bundled npm globals into live image..."
@ -1561,6 +1604,15 @@ EOF
;;
esac
# Universal NVIDIA lane: no branch is baked; clawdie_live_gpu installs the
# matching one from the on-image repo at boot. Overrides the mode set above.
# kld_list intentionally does NOT preload nvidia (it is not installed yet at
# first boot); the rc.d service kldloads it after install.
if [ "${NVIDIA_UNIVERSAL:-NO}" = "YES" ]; then
set_config_line "${MOUNT_POINT}/etc/rc.conf" 'clawdie_live_gpu_mode="nvidia-auto"'
set_config_line "${MOUNT_POINT}/etc/rc.conf" 'clawdie_live_gpu_nvidia_branch=""'
fi
mkdir -p "${MOUNT_POINT}/etc/ssh/sshd_config.d"
install -m 0644 "${LIVE_SESSION_DIR}/sshd-live.conf" \
"${MOUNT_POINT}/etc/ssh/sshd_config.d/clawdie-live.conf"
@ -2158,6 +2210,7 @@ install_live_runtime_packages
configure_live_operator_session
install_colibri_service
install_clawdie_service
install_nvidia_universal_repo
# Copy payload
# Rebuild payload paths from scratch inside the reusable work image. A failed

View file

@ -0,0 +1,74 @@
# NVIDIA universal lane — Codex build + hardware validation handoff
**From:** Claude (Linux) · **To:** Codex ISO Builder (FreeBSD 15 host)
**Goal:** one ISO that boots on any NVIDIA machine — detect the GPU pre-SDDM,
install the matching branch from an on-image repo, kldload it, then SDDM/XFCE.
Authored on Linux (sh -n clean; detector + branch/pkg map unit-tested). The
package/boot behavior **must be built and proven on FreeBSD + real NVIDIA
hardware** — it cannot be validated from Linux.
## What landed (behind `NVIDIA_UNIVERSAL`, default NO — normal builds unaffected)
- `build.cfg`: `NVIDIA_UNIVERSAL` flag.
- `build.sh`:
- `install_nvidia_universal_repo()``pkg fetch -d` the three families
(`nvidia-driver-390/470/580` + settings) into
`/usr/local/share/clawdie/nvidia-repo`, `pkg repo` it, write
`/usr/local/etc/pkg/repos/clawdie-nvidia.conf` (file:// , enabled).
- In universal mode: no branch baked into the root; rc.conf
`clawdie_live_gpu_mode="nvidia-auto"`.
- `live/operator-session/clawdie-live-gpu` (`nvidia-auto` mode): detect device id
→ branch {390,470,590} → `pkg install -r clawdie-nvidia nvidia-driver-<n>
nvidia-settings` → kldload via existing select/load. **Best-effort:** any
failure falls through to the integrated/scfb path — never worse than today.
## Must verify on the FreeBSD build host
1. **`pkg fetch -o` / `pkg repo` layout** — confirm `pkg fetch -y -o DIR -d ...`
places archives where `pkg repo DIR` expects them; adjust if `pkg repo` needs
`DIR/All`. Confirm the dependency closure is complete (offline boot install
must not reach the network).
2. **Boot install command** — `pkg install -y -r clawdie-nvidia nvidia-driver-470
nvidia-settings` resolves purely from the file:// repo with no network.
3. **Writable root at boot** — the USB-root install must allow `pkg install`
before SDDM (it does on a real on-USB FreeBSD; confirm).
4. **Kernel ABI** — the staged kmod packages must match the image's kernel.
5. **Image size** — three branches + deps add several hundred MB; confirm
headroom against `IMAGE_SIZE`.
6. **Exactly one branch** installed at boot (no mixing).
## Build commands
```sh
# colibri artifacts first (do NOT cargo clean after)
cd /home/clawdie/colibri && git fetch origin && git reset --hard origin/main
cargo build --workspace --release
# universal image (set COLIBRI_REPO explicitly if building from a tmp worktree)
cd /home/clawdie/clawdie-iso && git fetch origin && git reset --hard origin/main
sudo env NVIDIA_UNIVERSAL=YES FEATURE_CLAWDIE=YES \
COLIBRI_REPO=/home/clawdie/colibri \
CLAWDIE_ARTIFACT_DIR=/home/clawdie/colibri/target/release \
./build.sh --skip-memstick-fetch --live-default-password
```
## Hardware acceptance
1. Boot on the NVIDIA target.
2. `cat /var/log/clawdie-live-gpu.log` — expect: detected device id, chosen
branch + pkg, "installed nvidia-driver-<n>", selected/loaded modules.
3. `kldstat | grep nvidia` and SDDM → XFCE comes up accelerated.
4. If install/load failed, the log shows the fallback and the desktop still
comes up on integrated/scfb (no hard failure).
## Deletion criteria
Delete this handoff once a `NVIDIA_UNIVERSAL=YES` image has, on real NVIDIA
hardware, auto-installed the correct branch and reached XFCE — with the result
recorded below.
## Results
_(Codex: build host, GPU model + device id, branch chosen, pkg install outcome,
image size delta, SDDM/XFCE result.)_

View file

@ -79,6 +79,57 @@ clawdie_live_gpu_nvidia_branch_for_device()
fi
}
# Map a branch label {390,470,590} to the on-image pkg name. The "590" lane is
# the current driver, which is the nvidia-driver-580 package.
clawdie_live_gpu_nvidia_pkg_for_branch()
{
case "$1" in
390) echo "nvidia-driver-390" ;;
470) echo "nvidia-driver-470" ;;
590) echo "nvidia-driver-580" ;;
*) return 1 ;;
esac
}
# nvidia-auto mode: detect the GPU, install the matching branch from the on-image
# clawdie-nvidia repo, and leave /boot/modules/nvidia.ko in place for select to
# load. Fully best-effort: any failure just logs and returns, so the caller falls
# back to the integrated/scfb path. Never blocks boot.
clawdie_live_gpu_install_nvidia()
{
_blocks="$1"
# Already installed (e.g. a previous boot) — nothing to do.
if [ -e /boot/modules/nvidia.ko ]; then
clawdie_live_gpu_log "nvidia.ko already present; skipping auto-install"
return 0
fi
_device_id=$(clawdie_live_gpu_nvidia_device_id "$_blocks" || true)
_branch=$(clawdie_live_gpu_nvidia_branch_for_device "$_device_id")
_pkg=$(clawdie_live_gpu_nvidia_pkg_for_branch "$_branch") || {
clawdie_live_gpu_log "WARN: no package mapping for branch ${_branch}; skipping NVIDIA auto-install"
return 1
}
clawdie_live_gpu_log "nvidia-auto: device ${_device_id:-unknown} -> branch ${_branch} (${_pkg})"
if ! command -v pkg >/dev/null 2>&1; then
clawdie_live_gpu_log "WARN: pkg not available; cannot auto-install NVIDIA"
return 1
fi
# Install only from the on-image repo so this works offline and never reaches
# the network during boot.
if env ASSUME_ALWAYS_YES=yes pkg install -y -r clawdie-nvidia "${_pkg}" nvidia-settings \
>> "$LOG_FILE" 2>&1; then
clawdie_live_gpu_log "nvidia-auto: installed ${_pkg}"
return 0
fi
clawdie_live_gpu_log "WARN: nvidia-auto install of ${_pkg} failed; falling back to integrated/scfb"
return 1
}
clawdie_live_gpu_has_pci_vendor()
{
_blocks="$1"
@ -190,6 +241,14 @@ clawdie_live_gpu_start()
fi
clawdie_live_gpu_log "detected display devices: $(echo "$_blocks" | grep -i '^vgapci' | tr '\n' ' ')"
# Universal lane: install the matching NVIDIA branch before module selection.
# Best-effort — on failure select_modules just falls through to integrated.
if [ "${clawdie_live_gpu_mode:-auto}" = "nvidia-auto" ] &&
clawdie_live_gpu_has_pci_vendor "$_blocks" "0x10de"; then
clawdie_live_gpu_install_nvidia "$_blocks" || true
fi
_modules=$(clawdie_live_gpu_select_modules "$_blocks")
if [ -z "$_modules" ]; then
clawdie_live_gpu_log "no live KMS module selected; using scfb/vesa fallback"