clawdie-iso/live/operator-session/clawdie-live-gpu

206 lines
6.1 KiB
Text
Raw Normal View History

#!/bin/sh
# Clawdie operator USB live GPU setup.
# Detect display hardware and load a conservative KMS module before SDDM.
# Prefer integrated/open drivers so hybrid laptops boot the broadest path first;
# keep NVIDIA proprietary loading opt-in by requiring an installed nvidia.ko.
# Dedicated NVIDIA-target images can override that preference in rc.conf.
# PROVIDE: clawdie_live_gpu
# REQUIRE: FILESYSTEMS devfs
# BEFORE: sddm
# KEYWORD: nojail
. /etc/rc.subr
name="clawdie_live_gpu"
rcvar="clawdie_live_gpu_enable"
start_cmd="clawdie_live_gpu_start"
LOG_FILE="/var/log/clawdie-live-gpu.log"
clawdie_live_gpu_log()
{
echo "$(date '+%H:%M:%S') $*" >> "$LOG_FILE" 2>/dev/null || true
}
clawdie_live_gpu_display_blocks()
{
pciconf -lv 2>/dev/null | awk '
BEGIN { RS = ""; IGNORECASE = 1 }
/class=0x03/ { print }
'
}
clawdie_live_gpu_nvidia_block()
{
echo "$1" | awk '
BEGIN { RS = ""; IGNORECASE = 1 }
/(^|[[:space:]])vendor=0x10de([[:space:]]|$)/ { print; exit }
'
}
clawdie_live_gpu_nvidia_device_id()
{
_block=$(clawdie_live_gpu_nvidia_block "$1")
[ -n "$_block" ] || return 1
echo "$_block" | grep -Eo 'chip=0x10de[0-9a-fA-F]+' | head -1 | cut -c11-14
}
clawdie_live_gpu_nvidia_branch_for_device()
{
_device_id="$1"
[ -n "$_device_id" ] || return 1
_device_num=$(printf '%d' "0x$_device_id" 2>/dev/null || echo "0")
if [ "$_device_num" -ge 8288 ]; then
echo "590"
return 0
fi
if [ "$_device_num" -ge 4928 ] && [ "$_device_num" -le 8582 ]; then
echo "470"
return 0
fi
if [ "$_device_num" -ge 4480 ] && [ "$_device_num" -le 5100 ]; then
echo "390"
return 0
fi
echo "590"
}
clawdie_live_gpu_has_pci_vendor()
{
_blocks="$1"
_vendor_id="$2"
# Match the numeric PCI vendor on display-class blocks only. Do not use
# broad text matches like "Intel" here: unrelated vendor strings or
# subdevices can make an AMD system select i915kms and fail before SDDM.
echo "$_blocks" | awk -v vendor="$_vendor_id" '
BEGIN { RS = ""; IGNORECASE = 1; found = 0 }
$0 ~ ("(^|[[:space:]])vendor=" vendor "([[:space:]]|$)") { found = 1 }
END { exit(found ? 0 : 1) }
'
}
clawdie_live_gpu_select_modules()
{
_blocks="$1"
_mode="${clawdie_live_gpu_mode:-auto}"
_nvidia_branch="${clawdie_live_gpu_nvidia_branch:-}"
if [ "$_mode" = "safe" ]; then
clawdie_live_gpu_log "safe graphics mode requested; skipping KMS modules"
return 0
fi
if clawdie_live_gpu_has_pci_vendor "$_blocks" "0x10de"; then
_device_id=$(clawdie_live_gpu_nvidia_device_id "$_blocks" || true)
_detected_branch=""
if [ -n "$_device_id" ]; then
_detected_branch=$(clawdie_live_gpu_nvidia_branch_for_device "$_device_id" || true)
clawdie_live_gpu_log "detected NVIDIA device id: ${_device_id} (recommended branch: ${_detected_branch:-unknown})"
fi
if [ -e /boot/modules/nvidia.ko ]; then
if [ -n "$_nvidia_branch" ] && [ -n "$_detected_branch" ] && [ "$_nvidia_branch" != "$_detected_branch" ]; then
clawdie_live_gpu_log "WARN: staged NVIDIA branch ${_nvidia_branch} does not match detected device recommendation ${_detected_branch}; skipping proprietary load"
elif [ "$_mode" = "nvidia" ]; then
echo "nvidia-modeset nvidia"
return 0
fi
elif [ "$_mode" = "nvidia" ]; then
clawdie_live_gpu_log "WARN: NVIDIA mode requested but /boot/modules/nvidia.ko is missing"
fi
elif [ "$_mode" = "nvidia" ]; then
clawdie_live_gpu_log "WARN: NVIDIA mode requested but no NVIDIA display device was detected"
fi
# Hybrid laptops often expose Intel or AMD integrated graphics plus a
# discrete NVIDIA GPU. Prefer the integrated/open KMS path for live boot.
if clawdie_live_gpu_has_pci_vendor "$_blocks" "0x1002"; then
# amdgpu covers modern AMD; radeonkms is a best-effort fallback for
# older Radeon hardware only if amdgpu does not load.
echo "amdgpu radeonkms"
return 0
fi
if clawdie_live_gpu_has_pci_vendor "$_blocks" "0x8086"; then
echo "i915kms"
return 0
fi
if clawdie_live_gpu_has_pci_vendor "$_blocks" "0x15ad"; then
echo "vmwgfx"
return 0
fi
if clawdie_live_gpu_has_pci_vendor "$_blocks" "0x10de"; then
# NVIDIA packages are bundled in the offline repo, but the live image
# only loads a concrete branch when one was explicitly staged.
if [ -e /boot/modules/nvidia.ko ]; then
echo "nvidia-modeset nvidia"
fi
return 0
fi
return 0
}
clawdie_live_gpu_load_module()
{
_module="$1"
if [ "$_module" = "radeonkms" ] && kldstat -n amdgpu.ko >/dev/null 2>&1; then
clawdie_live_gpu_log "skipping radeonkms because amdgpu is already loaded"
return 0
fi
if kldstat -n "${_module}.ko" >/dev/null 2>&1; then
clawdie_live_gpu_log "module already loaded: ${_module}"
return 0
fi
if kldload "$_module" >/dev/null 2>&1; then
clawdie_live_gpu_log "loaded module: ${_module}"
return 0
fi
clawdie_live_gpu_log "WARN: failed to load module: ${_module}"
return 1
}
clawdie_live_gpu_start()
{
_blocks=$(clawdie_live_gpu_display_blocks)
if [ -z "$_blocks" ]; then
clawdie_live_gpu_log "no display-class PCI device detected; using scfb/vesa fallback"
return 0
fi
clawdie_live_gpu_log "detected display devices: $(echo "$_blocks" | grep -i '^vgapci' | tr '\n' ' ')"
_modules=$(clawdie_live_gpu_select_modules "$_blocks")
if [ -z "$_modules" ]; then
clawdie_live_gpu_log "no live KMS module selected; using scfb/vesa fallback"
return 0
fi
clawdie_live_gpu_log "selected live KMS modules: ${_modules}"
for _module in $_modules; do
clawdie_live_gpu_load_module "$_module" || true
done
return 0
}
load_rc_config "$name"
: ${clawdie_live_gpu_enable:="NO"}
: ${clawdie_live_gpu_mode:="auto"}
: ${clawdie_live_gpu_nvidia_branch:=""}
run_rc_command "$1"