2026-03-24 00:17:36 +00:00
|
|
|
#!/bin/sh
|
2026-03-26 12:36:00 +00:00
|
|
|
# Clawdie Shell — GPU Detection Module
|
|
|
|
|
# Purpose: Detect GPU and configure appropriate kernel modules
|
|
|
|
|
# POSIX-compliant (no bash-isms)
|
|
|
|
|
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
# Configuration (can be overridden for testing)
|
|
|
|
|
RC_CONF="${RC_CONF:-/etc/rc.conf}"
|
|
|
|
|
LOG_FILE="${LOG_FILE:-/var/log/clawdie-firstboot.log}"
|
|
|
|
|
PROGRESS_FILE="${PROGRESS_FILE:-/var/log/clawdie-firstboot.progress}"
|
|
|
|
|
|
|
|
|
|
# ============================================================================
|
|
|
|
|
# MAIN ENTRY POINT
|
|
|
|
|
# ============================================================================
|
|
|
|
|
|
|
|
|
|
clawdie_shell_gpu_detect() {
|
|
|
|
|
# Main orchestrator: detect GPU and write rc.conf
|
|
|
|
|
# Sets DETECTED_GPU for use by other modules
|
|
|
|
|
|
|
|
|
|
log_msg "[gpu] Starting GPU detection"
|
|
|
|
|
|
|
|
|
|
# Query pciconf for GPU vendor
|
|
|
|
|
gpu_vendor=$(clawdie_shell_gpu_detect_pci)
|
|
|
|
|
|
|
|
|
|
if [ -z "$gpu_vendor" ]; then
|
|
|
|
|
log_msg "[gpu] No GPU detected — using VESA fallback"
|
|
|
|
|
DETECTED_GPU="vesa"
|
|
|
|
|
echo "[GPU] VESA" >> "$PROGRESS_FILE"
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
log_msg "[gpu] Detected GPU vendor: $gpu_vendor"
|
|
|
|
|
|
|
|
|
|
# Convert vendor to driver module list
|
|
|
|
|
kld_list=$(clawdie_shell_gpu_match_driver "$gpu_vendor")
|
|
|
|
|
DETECTED_GPU="$gpu_vendor"
|
|
|
|
|
|
|
|
|
|
if [ -z "$kld_list" ]; then
|
|
|
|
|
log_msg "[gpu] Vendor '$gpu_vendor' has no driver — using VESA fallback"
|
|
|
|
|
DETECTED_GPU="vesa"
|
|
|
|
|
echo "[GPU] VESA (unknown vendor)" >> "$PROGRESS_FILE"
|
|
|
|
|
return 0
|
2026-03-24 00:17:36 +00:00
|
|
|
fi
|
2026-03-26 12:36:00 +00:00
|
|
|
|
|
|
|
|
log_msg "[gpu] Matched driver: $kld_list"
|
|
|
|
|
|
|
|
|
|
# Write to rc.conf
|
|
|
|
|
clawdie_shell_gpu_write_rcconf "$kld_list"
|
|
|
|
|
log_msg "[gpu] Updated rc.conf with kld_list"
|
|
|
|
|
|
|
|
|
|
echo "[GPU] $DETECTED_GPU ($kld_list)" >> "$PROGRESS_FILE"
|
|
|
|
|
log_msg "[gpu] GPU detection complete"
|
2026-03-24 00:17:36 +00:00
|
|
|
}
|
|
|
|
|
|
2026-03-26 12:36:00 +00:00
|
|
|
# ============================================================================
|
|
|
|
|
# GPU DETECTION VIA PCICONF
|
|
|
|
|
# ============================================================================
|
|
|
|
|
|
|
|
|
|
clawdie_shell_gpu_detect_pci() {
|
|
|
|
|
# Query pciconf for GPU vendor
|
|
|
|
|
# Returns: intel, amd, nvidia, vmware, or empty string
|
|
|
|
|
|
|
|
|
|
local pciconf_out
|
|
|
|
|
|
|
|
|
|
# Get pciconf output (filter to VGA device)
|
|
|
|
|
pciconf_out=$(pciconf -lv 2>/dev/null | grep -i "class=0x030000" | head -1 || true)
|
|
|
|
|
|
|
|
|
|
if [ -z "$pciconf_out" ]; then
|
|
|
|
|
return
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Extract vendor string
|
|
|
|
|
if echo "$pciconf_out" | grep -iq "Intel"; then
|
|
|
|
|
echo "intel"
|
|
|
|
|
elif echo "$pciconf_out" | grep -iq "AMD\|ATI"; then
|
|
|
|
|
echo "amd"
|
|
|
|
|
elif echo "$pciconf_out" | grep -iq "NVIDIA"; then
|
|
|
|
|
echo "nvidia"
|
|
|
|
|
elif echo "$pciconf_out" | grep -iq "VMware"; then
|
|
|
|
|
echo "vmware"
|
2026-03-24 00:17:36 +00:00
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ============================================================================
|
2026-03-26 12:36:00 +00:00
|
|
|
# DRIVER LOOKUP TABLE
|
2026-03-24 00:17:36 +00:00
|
|
|
# ============================================================================
|
|
|
|
|
|
2026-03-26 12:36:00 +00:00
|
|
|
clawdie_shell_gpu_match_driver() {
|
|
|
|
|
# Convert vendor to kernel module list
|
|
|
|
|
# Input: intel, amd, nvidia, vmware, or vendor string
|
|
|
|
|
# Output: space-separated kld module names (e.g., "i915kms" or "nvidia-modeset nvidia")
|
|
|
|
|
|
|
|
|
|
local vendor="$1"
|
|
|
|
|
|
|
|
|
|
case "$vendor" in
|
|
|
|
|
intel)
|
|
|
|
|
echo "i915kms"
|
|
|
|
|
;;
|
|
|
|
|
amd)
|
|
|
|
|
echo "amdgpu"
|
|
|
|
|
;;
|
|
|
|
|
nvidia)
|
|
|
|
|
# NVIDIA driver is set separately by clawdie_shell_nvidia_detect()
|
|
|
|
|
# This module just returns the base driver name
|
|
|
|
|
echo "nvidia-modeset nvidia"
|
|
|
|
|
;;
|
|
|
|
|
vmware)
|
|
|
|
|
echo "vmwgfx"
|
|
|
|
|
;;
|
|
|
|
|
*)
|
|
|
|
|
# Unknown vendor — no driver
|
|
|
|
|
return
|
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
}
|
2026-03-24 00:17:36 +00:00
|
|
|
|
2026-03-26 12:36:00 +00:00
|
|
|
# ============================================================================
|
|
|
|
|
# RC.CONF WRITING
|
|
|
|
|
# ============================================================================
|
|
|
|
|
|
|
|
|
|
clawdie_shell_gpu_write_rcconf() {
|
|
|
|
|
# Write kld_list to rc.conf
|
|
|
|
|
# Input: space-separated module list (e.g., "i915kms" or "nvidia-modeset nvidia")
|
|
|
|
|
|
|
|
|
|
local kld_list="$1"
|
|
|
|
|
|
|
|
|
|
if [ ! -f "$RC_CONF" ]; then
|
|
|
|
|
log_msg "[gpu] Creating $RC_CONF"
|
|
|
|
|
touch "$RC_CONF"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# If kld_list is empty (VESA), skip writing anything
|
|
|
|
|
if [ -z "$kld_list" ]; then
|
|
|
|
|
log_msg "[gpu] No driver — skipping kld_list (VESA fallback)"
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Remove existing kld_list if present
|
|
|
|
|
if grep -q "^kld_list=" "$RC_CONF" 2>/dev/null; then
|
|
|
|
|
sed -i.bak '/^kld_list=/d' "$RC_CONF"
|
|
|
|
|
rm -f "$RC_CONF.bak"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# Append new kld_list
|
|
|
|
|
echo "kld_list=\"$kld_list\"" >> "$RC_CONF"
|
|
|
|
|
log_msg "[gpu] Wrote kld_list=$kld_list to $RC_CONF"
|
|
|
|
|
}
|
2026-03-24 00:17:36 +00:00
|
|
|
|
|
|
|
|
# ============================================================================
|
2026-03-26 12:36:00 +00:00
|
|
|
# VALIDATION
|
2026-03-24 00:17:36 +00:00
|
|
|
# ============================================================================
|
|
|
|
|
|
2026-03-26 12:36:00 +00:00
|
|
|
clawdie_shell_gpu_validate() {
|
|
|
|
|
# Verify rc.conf has valid kld_list (if GPU detected)
|
|
|
|
|
|
|
|
|
|
if [ ! -f "$RC_CONF" ]; then
|
|
|
|
|
log_msg "[gpu] ERROR: $RC_CONF not found"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
if grep -q "^kld_list=" "$RC_CONF" 2>/dev/null; then
|
|
|
|
|
local kld=$(grep "^kld_list=" "$RC_CONF" | cut -d= -f2 | tr -d '"' | head -1)
|
|
|
|
|
if [ -z "$kld" ]; then
|
|
|
|
|
log_msg "[gpu] ERROR: kld_list is empty"
|
|
|
|
|
return 1
|
|
|
|
|
fi
|
|
|
|
|
fi
|
2026-03-24 00:17:36 +00:00
|
|
|
|
2026-03-26 12:36:00 +00:00
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ============================================================================
|
|
|
|
|
# LOGGING HELPER
|
|
|
|
|
# ============================================================================
|
|
|
|
|
|
|
|
|
|
log_msg() {
|
|
|
|
|
echo "$(date '+%H:%M:%S') $1" | tee -a "$LOG_FILE" 2>/dev/null || true
|
|
|
|
|
}
|
2026-03-24 00:17:36 +00:00
|
|
|
|
2026-03-26 12:36:00 +00:00
|
|
|
# Only run if sourced directly (not during test)
|
|
|
|
|
if [ "${SHELL_GPU_TEST:-0}" -eq 0 ]; then
|
|
|
|
|
clawdie_shell_gpu_detect
|
2026-03-24 00:17:36 +00:00
|
|
|
fi
|