#!/usr/bin/env bash # Hardware and configuration detection for Strix Halo # Find the amdgpu DRM card path find_gpu_card() { local card for card in /sys/class/drm/card*/device/vendor; do if [[ -f "$card" ]] && [[ "$(cat "$card")" == "0x1002" ]]; then echo "$(dirname "$card")" return 0 fi done # Fallback: try any card with mem_info_vram_total (i.e., an amdgpu device) for card in /sys/class/drm/card*/device/mem_info_vram_total; do if [[ -f "$card" ]]; then echo "$(dirname "$card")" return 0 fi done echo "/sys/class/drm/card1/device" # last resort } GPU_SYSFS="$(find_gpu_card)" # --- CPU --- detect_cpu_model() { grep -m1 'model name' /proc/cpuinfo | cut -d: -f2 | xargs; } detect_cpu_cores() { grep -c '^processor' /proc/cpuinfo; } detect_cpu_physical() { grep 'cpu cores' /proc/cpuinfo | head -1 | cut -d: -f2 | xargs; } # --- GPU --- detect_gpu_name() { lspci | grep -i 'Display\|VGA' | grep -i 'AMD' | head -1 | sed 's/.*: //' } detect_gpu_device_id() { cat "$GPU_SYSFS/device" 2>/dev/null | sed 's/^0x//' } # --- Memory (bytes) --- detect_vram_total() { cat "$GPU_SYSFS/mem_info_vram_total" 2>/dev/null || echo 0; } detect_vram_used() { cat "$GPU_SYSFS/mem_info_vram_used" 2>/dev/null || echo 0; } detect_gtt_total() { cat "$GPU_SYSFS/mem_info_gtt_total" 2>/dev/null || echo 0; } detect_gtt_used() { cat "$GPU_SYSFS/mem_info_gtt_used" 2>/dev/null || echo 0; } detect_system_ram_kb() { local kb kb="$(grep MemTotal /proc/meminfo 2>/dev/null | awk '{print $2}')" echo "${kb:-0}" } detect_system_ram_bytes() { echo $(( $(detect_system_ram_kb) * 1024 )); } # --- Kernel --- detect_kernel_version() { uname -r; } detect_kernel_param() { # Returns the value of a kernel param, or empty if not present local param="$1" local cmdline cmdline="$(cat /proc/cmdline)" # Escape dots for regex and anchor with word boundary (space or start-of-string) local pattern="${param//./\\.}" if [[ "$cmdline" =~ (^|[[:space:]])${pattern}=([^ ]+) ]]; then echo "${BASH_REMATCH[2]}" elif [[ "$cmdline" =~ (^|[[:space:]])${pattern}([[:space:]]|$) ]]; then echo "present" fi } detect_has_iommu_pt() { local val val="$(detect_kernel_param 'iommu')" [[ "$val" == "pt" ]] } detect_gttsize_param() { detect_kernel_param 'amdgpu.gttsize'; } detect_pages_limit_param() { detect_kernel_param 'ttm.pages_limit'; } # --- Tuned --- detect_tuned_profile() { if is_cmd tuned-adm; then tuned-adm active 2>/dev/null | sed 's/Current active profile: //' else echo "tuned not installed" fi } # --- Firmware --- detect_firmware_version() { rpm -q linux-firmware 2>/dev/null | sed 's/linux-firmware-//' | sed 's/\.fc.*//' || echo "unknown" } detect_firmware_bad() { # Returns 0 (true) if firmware is the known-bad version local fw fw="$(detect_firmware_version)" [[ "$fw" == *"20251125"* ]] } # --- ROCm --- detect_rocm_version() { if [[ -f /opt/rocm/.info/version ]]; then cat /opt/rocm/.info/version else rpm -qa 2>/dev/null | grep '^rocm-core-' | head -1 | sed 's/rocm-core-//' | sed 's/-.*//' || echo "not installed" fi } detect_rocm_packages() { rpm -qa 2>/dev/null | grep -i rocm | sort } # --- Vulkan --- detect_vulkan_driver() { if is_cmd vulkaninfo; then vulkaninfo --summary 2>/dev/null | grep 'driverName' | head -1 | awk '{print $NF}' else echo "vulkaninfo not available" fi } detect_vulkan_version() { if is_cmd vulkaninfo; then vulkaninfo --summary 2>/dev/null | grep 'apiVersion' | head -1 | awk '{print $NF}' fi } # --- Toolbox containers --- detect_toolboxes() { if is_cmd toolbox; then toolbox list --containers 2>/dev/null | tail -n +2 fi } detect_toolbox_names() { detect_toolboxes | awk '{print $2}' 2>/dev/null } # --- LLM stacks --- detect_stack_ollama() { is_cmd ollama && echo "installed" || echo "missing"; } detect_stack_lmstudio() { is_cmd lms && echo "installed" || echo "missing"; } detect_stack_llamacpp() { (is_cmd llama-cli || is_cmd llama-bench) && echo "installed" || echo "missing"; } detect_stack_opencode() { is_cmd opencode && echo "installed" || echo "missing"; } # --- Sensors --- detect_gpu_temp() { # Returns temperature in millidegrees C local hwmon for hwmon in "$GPU_SYSFS"/hwmon/hwmon*/temp1_input; do if [[ -f "$hwmon" ]]; then cat "$hwmon" return fi done echo 0 } detect_gpu_power() { # Returns power in microwatts local hwmon for hwmon in "$GPU_SYSFS"/hwmon/hwmon*/power1_average; do if [[ -f "$hwmon" ]]; then cat "$hwmon" return fi done echo 0 } detect_gpu_busy() { cat "$GPU_SYSFS/gpu_busy_percent" 2>/dev/null || echo 0 } # --- Total physical memory (visible + VRAM dedicated) --- detect_total_physical_ram_kb() { local visible_kb vram_bytes vram_kb visible_kb="$(detect_system_ram_kb)" vram_bytes="$(detect_vram_total)" vram_kb=$(( vram_bytes / 1024 )) echo $(( visible_kb + vram_kb )) } # --- Recommended values for this system --- recommended_gttsize_mib() { # Total physical RAM (including VRAM allocation) minus 4 GiB reserve, in MiB local total_kb total_kb="$(detect_total_physical_ram_kb)" local total_gib=$(( total_kb / 1024 / 1024 )) local gtt_gib=$(( total_gib - 4 )) echo $(( gtt_gib * 1024 )) } recommended_pages_limit() { # GTT GiB * 1024 MiB/GiB * 256 pages/MiB local gtt_mib gtt_mib="$(recommended_gttsize_mib)" echo $(( gtt_mib * 256 )) }