Skip to content

Instantly share code, notes, and snippets.

@ajmasia
Last active April 25, 2026 16:20
Show Gist options
  • Select an option

  • Save ajmasia/ac629b2d62a7536fe6c69bf387c67c1d to your computer and use it in GitHub Desktop.

Select an option

Save ajmasia/ac629b2d62a7536fe6c69bf387c67c1d to your computer and use it in GitHub Desktop.
MPU Setup for Slimbook EVO AMD Ryzen AI 9 365
#!/usr/bin/env bash
# install-npu-amd.sh
# Installer for AMD Ryzen AI NPU driver (XRT + amdxdna) on Debian/Ubuntu.
# Tested on: Debian 13 trixie + kernel 6.19 backports + Ryzen AI 9 365 (Strix Point).
set -euo pipefail
IFS=$'\n\t'
# =============================================================================
# Constants
# =============================================================================
readonly SCRIPT_VERSION="0.2.1"
readonly SCRIPT_NAME="$(basename "$0")"
readonly REPO_URL="https://github.com/amd/xdna-driver.git"
readonly XRT_PREFIX="/opt/xilinx/xrt"
readonly LIMITS_FILE="/etc/security/limits.d/99-xrt.conf"
readonly UDEV_RULES_FILE="/etc/udev/rules.d/99-amdxdna.rules"
readonly DKMS_MODULE="xrt-amdxdna"
readonly RC_MARKER="# AMD XRT (Ryzen AI NPU) — load XRT environment on demand: run \`npu-env\`"
# Ensure /usr/sbin is in PATH (modinfo, dkms, prlimit live there on Debian for non-root)
case ":$PATH:" in *:/usr/sbin:*) ;; *) export PATH="$PATH:/usr/sbin" ;; esac
# =============================================================================
# Mutable options (overridden by flags)
# =============================================================================
LANG_CODE="" # auto-detected from $LANG / $LC_* if empty after parse_args
BUILD_DIR="${HOME}/npu-build"
DRY_RUN=0
SKIP_TESTS=0
NO_CLEANUP=0
ASSUME_YES=0
ACTION="install" # install | uninstall | check
CURRENT_STEP=""
LOG_FILE="" # set by init_log_file
NO_LOG=0
SUDO_KEEPALIVE_PID="" # tracks the background sudo refresh process for cleanup
# Capture args as a space-joined string. We can't use "$*" here because IFS=$'\n\t' joins with newlines.
ORIG_ARGS="$(printf '%s ' "$@")"
ORIG_ARGS="${ORIG_ARGS% }"
# Allowed characters for user-supplied paths (--build-dir, --log-file).
# Restrictive on purpose: rules out shell metacharacters and substitution.
readonly PATH_REGEX='^[a-zA-Z0-9._/~+:-]+$'
# =============================================================================
# Catppuccin Mocha palette (24-bit ANSI). Only used for tags; body text white.
# =============================================================================
if [[ -t 1 ]]; then
C_BLUE=$'\033[38;2;137;180;250m' # blue — info
C_GREEN=$'\033[38;2;166;227;161m' # green — ok
C_RED=$'\033[38;2;243;139;168m' # red — err
C_YELLOW=$'\033[38;2;249;226;175m' # yellow — warn
C_LAVENDER=$'\033[38;2;180;190;254m' # lav — step
C_PINK=$'\033[38;2;245;194;231m' # pink — ask
C_MAUVE=$'\033[38;2;203;166;247m' # mauve — title
C_TEAL=$'\033[38;2;148;226;213m' # teal — run
C_SUBTEXT=$'\033[38;2;166;173;200m' # subtxt — skip / dim
C_TEXT=$'\033[38;2;205;214;244m' # text body
C_BOLD=$'\033[1m'
C_DIM=$'\033[2m'
C_RESET=$'\033[0m'
else
C_BLUE="" C_GREEN="" C_RED="" C_YELLOW="" C_LAVENDER=""
C_PINK="" C_MAUVE="" C_TEAL="" C_SUBTEXT="" C_TEXT=""
C_BOLD="" C_DIM="" C_RESET=""
fi
# =============================================================================
# Logging — tags colored on terminal, plain (uncolored) text mirrored to LOG_FILE
# =============================================================================
log_to_file() {
# Append a timestamped, color-free line to the log file if logging is enabled.
[[ -z "${LOG_FILE:-}" ]] && return 0
printf "[%s] %s\n" "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >> "$LOG_FILE"
}
log_info() { printf "%s[info]%s %s%s%s\n" "$C_BLUE" "$C_RESET" "$C_TEXT" "$*" "$C_RESET"; log_to_file "[info] $*"; }
log_ok() { printf "%s[ok]%s %s%s%s\n" "$C_GREEN" "$C_RESET" "$C_TEXT" "$*" "$C_RESET"; log_to_file "[ok] $*"; }
log_warn() { printf "%s[warn]%s %s%s%s\n" "$C_YELLOW" "$C_RESET" "$C_TEXT" "$*" "$C_RESET"; log_to_file "[warn] $*"; }
log_err() { printf "%s[err]%s %s%s%s\n" "$C_RED" "$C_RESET" "$C_TEXT" "$*" "$C_RESET" >&2; log_to_file "[err] $*"; }
log_step() { printf "\n%s[step]%s %s%s%s%s\n" "$C_LAVENDER" "$C_RESET" "$C_TEXT$C_BOLD" "$*" "$C_RESET" ""; log_to_file "[step] $*"; }
log_skip() { printf "%s[skip]%s %s%s%s\n" "$C_SUBTEXT" "$C_RESET" "$C_TEXT" "$*" "$C_RESET"; log_to_file "[skip] $*"; }
log_run() { printf "%s[run]%s %s%s%s\n" "$C_TEAL" "$C_RESET" "$C_DIM$C_TEXT" "$*" "$C_RESET"; log_to_file "[run] $*"; }
log_title() { printf "\n%s%s%s%s\n" "$C_MAUVE$C_BOLD" "$*" "$C_RESET" ""; log_to_file "**** $* ****"; }
# =============================================================================
# i18n — keep keys short, fallback to EN if missing in ES
# =============================================================================
declare -A T_EN T_ES
# --- English strings ---
T_EN[help_summary]="Installer for the AMD Ryzen AI NPU driver (XRT + amdxdna)."
T_EN[help_options]="Options:"
T_EN[help_lang]=" --es, --spanish Use Spanish output"
T_EN[help_dry]=" --dry-run Print actions without executing them"
T_EN[help_skip_tests]=" --skip-tests Do not run xrt-smi validate at the end"
T_EN[help_no_cleanup]=" --no-cleanup Keep build directory after install"
T_EN[help_yes]=" -y, --yes Answer yes to all prompts"
T_EN[help_check]=" --check Only show current install state"
T_EN[help_uninstall]=" --uninstall Remove the NPU stack"
T_EN[help_build_dir]=" --build-dir <path> Use custom build directory (default: ~/npu-build)"
T_EN[help_log_file]=" --log-file <path> Write a timestamped log to <path> (default: /tmp/install-npu-amd-<ts>.log)"
T_EN[help_no_log]=" --no-log Disable file logging"
T_EN[help_help]=" -h, --help Show this help"
T_EN[help_version]=" --version Show script version"
T_EN[intro_what]="What is this driver?"
T_EN[intro_what_body]="The amdxdna driver exposes the NPU (XDNA / AI Engine) embedded in AMD Ryzen AI CPUs as a Linux DRM accel device. XRT (AMD/Xilinx RunTime) is the userspace runtime that talks to it. Together they enable hardware acceleration for AI inference workloads (~50 TOPS INT8 in Strix Point)."
T_EN[intro_what_will]="What this script will do"
T_EN[intro_steps]=" - Pre-flight checks: hardware, kernel, network, disk, current state.\n - Install DKMS via apt (if missing).\n - Clone the AMD xdna-driver repository.\n - Run AMD's xrtdeps.sh to install repo-based build deps.\n - Build XRT (~5–10 min) and install the base .deb.\n - Build the amdxdna plugin (~1–3 min) and install it (DKMS).\n - Configure memlock limit (udev rule comes from the plugin's postinst).\n - Add an 'npu-env' helper to your shell rc.\n - Verify module path, device permissions, udev rule.\n - Activate XRT and run validation tests."
T_EN[intro_disk]="Disk: ~4 GB during build, ~70 MB after cleanup. Network: required (clone + apt)."
T_EN[intro_sudo]="The script will request sudo only when needed and cache it for the rest of the run."
T_EN[ask_proceed]="Proceed with installation?"
T_EN[ask_continue]="Continue?"
T_EN[abort_user]="Aborted by user."
T_EN[prompt_sudo]="Requesting sudo credentials (cached for the rest of the script)..."
T_EN[check_title]="Pre-flight checks"
T_EN[check_arch_ok]="Architecture is x86_64."
T_EN[check_arch_fail]="Unsupported architecture: %s. Only x86_64 is supported."
T_EN[check_distro_ok]="Distribution: %s %s (apt-based)."
T_EN[check_distro_fail]="Unsupported distribution: %s. Only Debian/Ubuntu are supported."
T_EN[check_kernel]="Kernel: %s"
T_EN[check_kmod_ok]="amdxdna module is available in kernel (CONFIG_DRM_ACCEL_AMDXDNA=m)."
T_EN[check_kmod_fail]="amdxdna kernel support not found. Need kernel >= 6.14 with CONFIG_DRM_ACCEL_AMDXDNA enabled."
T_EN[check_headers_ok]="linux-headers-%s is installed (DKMS can build modules)."
T_EN[check_headers_fail]="linux-headers-%s is not installed. DKMS would fail to build the amdxdna module after a long XRT compile. Install it first with: sudo apt install linux-headers-%s"
T_EN[check_cpu_ok]="CPU detected: %s"
T_EN[check_cpu_warn]="CPU does not look like a Ryzen AI / Strix / Phoenix / Hawk Point. Continuing anyway."
T_EN[check_dev_ok]="NPU device present at /dev/accel/accel0."
T_EN[check_dev_warn]="No /dev/accel/accel0 found yet. Module may need to be loaded after install."
T_EN[check_disk_ok]="Free disk space: %s GB (need at least 4 GB)."
T_EN[check_disk_fail]="Insufficient disk space at %s: %s GB free, need at least 4 GB."
T_EN[check_net_ok]="Network reachable (github.com)."
T_EN[check_net_fail]="Cannot reach github.com. Check your network."
T_EN[check_dkms_ok]="dkms is installed (%s)."
T_EN[check_dkms_missing]="dkms is not installed. Will install it."
T_EN[check_secureboot_on]="Secure Boot is ENABLED. DKMS will sign the module with the system MOK; if no MOK is enrolled the module won't load. Consider 'mokutil --list-enrolled'."
T_EN[check_secureboot_off]="Secure Boot is disabled."
T_EN[state_title]="Current installation state"
T_EN[state_xrt_installed]="xrt-base is installed: %s"
T_EN[state_xrt_missing]="xrt-base is not installed."
T_EN[state_plugin_installed]="xrt_plugin-amdxdna is installed: %s"
T_EN[state_plugin_missing]="xrt_plugin-amdxdna is not installed."
T_EN[state_dkms_active]="DKMS module active: %s"
T_EN[state_dkms_inactive]="DKMS module not registered."
T_EN[state_limits_ok]="memlock limits configured at %s."
T_EN[state_limits_missing]="memlock limits file %s missing."
T_EN[state_udev_ok]="udev rule present at %s."
T_EN[state_udev_missing]="udev rule %s missing."
T_EN[state_rc_ok]="npu-env helper present in %s."
T_EN[state_rc_missing]="npu-env helper not in any shell rc."
T_EN[state_dev_perms_ok]="/dev/accel/accel0 mode is %s (udev rule applied)."
T_EN[state_dev_perms_warn]="/dev/accel/accel0 mode is %s (expected 666 — try: sudo udevadm control --reload-rules && sudo udevadm trigger)."
T_EN[state_all_ok]="Everything is already installed and configured."
T_EN[state_partial]="Partial installation detected — re-running will fill the gaps."
T_EN[step_deps]="Install DKMS (if missing)"
T_EN[step_clone]="Clone xdna-driver repository (with submodules)"
T_EN[step_amd_deps]="Install AMD repo-based build dependencies (xrtdeps.sh)"
T_EN[step_build_xrt]="Build XRT base"
T_EN[step_install_xrt]="Install XRT base .deb"
T_EN[step_build_plugin]="Build amdxdna plugin"
T_EN[step_install_plugin]="Install amdxdna plugin .deb (registers DKMS)"
T_EN[step_memlock]="Configure memlock limits and apply to current session"
T_EN[step_shell]="Configure shell helper (npu-env)"
T_EN[step_verify]="Verify post-install (module path, device permissions, udev rule)"
T_EN[step_validate]="Activate XRT and run validation tests"
T_EN[skip_xrt]="xrt-base already installed — skipping build and install."
T_EN[skip_plugin]="xrt_plugin-amdxdna already installed — skipping build and install."
T_EN[skip_limits]="memlock limits already configured — skipping."
T_EN[skip_rc]="npu-env helper already present — skipping."
T_EN[final_title]="Final verification"
T_EN[final_ok]="Installation complete. The NPU is operational."
T_EN[final_partial]="Installation finished with warnings — review the messages above."
T_EN[useful_title]="Useful commands"
T_EN[useful_activate]="Activate XRT in a new terminal:"
T_EN[useful_examine]="Show NPU info and detected devices:"
T_EN[useful_validate]="Run validation tests (gemm, latency, throughput):"
T_EN[useful_turbo]="Switch NPU to performance (turbo) mode:"
T_EN[useful_status]="Check DKMS module after a kernel update:"
T_EN[useful_uninstall]="Uninstall everything:"
T_EN[uninstall_confirm]="This will remove XRT, the plugin, DKMS module, limits, udev rule and the npu-env helper. Continue?"
T_EN[uninstall_done]="Uninstall complete. Reboot recommended."
# --- Spanish strings ---
T_ES[help_summary]="Instalador del driver NPU AMD Ryzen AI (XRT + amdxdna)."
T_ES[help_options]="Opciones:"
T_ES[help_lang]=" --es, --spanish Mostrar mensajes en español"
T_ES[help_dry]=" --dry-run Imprimir acciones sin ejecutarlas"
T_ES[help_skip_tests]=" --skip-tests No ejecutar xrt-smi validate al final"
T_ES[help_no_cleanup]=" --no-cleanup Conservar el directorio de build tras instalar"
T_ES[help_yes]=" -y, --yes Responder sí a todas las preguntas"
T_ES[help_check]=" --check Solo mostrar el estado actual de la instalación"
T_ES[help_uninstall]=" --uninstall Desinstalar el stack NPU"
T_ES[help_build_dir]=" --build-dir <ruta> Usar un directorio de build distinto (por defecto: ~/npu-build)"
T_ES[help_log_file]=" --log-file <ruta> Escribir log con timestamps en <ruta> (por defecto: /tmp/install-npu-amd-<ts>.log)"
T_ES[help_no_log]=" --no-log Desactivar el log a fichero"
T_ES[help_help]=" -h, --help Mostrar esta ayuda"
T_ES[help_version]=" --version Mostrar versión del script"
T_ES[intro_what]="¿Qué es este driver?"
T_ES[intro_what_body]="El driver amdxdna expone la NPU (XDNA / AI Engine) integrada en los procesadores AMD Ryzen AI como un dispositivo Linux DRM accel. XRT (AMD/Xilinx RunTime) es el runtime userspace que se comunica con él. Juntos permiten acelerar inferencia de IA por hardware (~50 TOPS INT8 en Strix Point)."
T_ES[intro_what_will]="Qué hará este script"
T_ES[intro_steps]=" - Comprobaciones previas: hardware, kernel, red, disco, estado actual.\n - Instalar DKMS via apt (si falta).\n - Clonar el repositorio xdna-driver de AMD.\n - Ejecutar xrtdeps.sh de AMD para instalar deps de build del repo.\n - Compilar XRT (~5–10 min) e instalar el .deb base.\n - Compilar el plugin amdxdna (~1–3 min) e instalarlo (DKMS).\n - Configurar el límite memlock (la regla udev la añade el postinst del plugin).\n - Añadir la función 'npu-env' a tu shell rc.\n - Verificar ruta del módulo, permisos del device y regla udev.\n - Activar XRT y ejecutar tests de validación."
T_ES[intro_disk]="Disco: ~4 GB durante el build, ~70 MB tras limpieza. Red: necesaria (clone + apt)."
T_ES[intro_sudo]="El script solicitará sudo solo cuando haga falta y lo cachea durante toda la ejecución."
T_ES[ask_proceed]="¿Proceder con la instalación?"
T_ES[ask_continue]="¿Continuar?"
T_ES[abort_user]="Cancelado por el usuario."
T_ES[prompt_sudo]="Solicitando credenciales sudo (se cachean durante el resto del script)..."
T_ES[check_title]="Comprobaciones previas"
T_ES[check_arch_ok]="Arquitectura: x86_64."
T_ES[check_arch_fail]="Arquitectura no soportada: %s. Solo se soporta x86_64."
T_ES[check_distro_ok]="Distribución: %s %s (basada en apt)."
T_ES[check_distro_fail]="Distribución no soportada: %s. Solo Debian/Ubuntu."
T_ES[check_kernel]="Kernel: %s"
T_ES[check_kmod_ok]="Módulo amdxdna disponible en el kernel (CONFIG_DRM_ACCEL_AMDXDNA=m)."
T_ES[check_kmod_fail]="No se encuentra soporte de amdxdna en el kernel. Se necesita kernel >= 6.14 con CONFIG_DRM_ACCEL_AMDXDNA habilitado."
T_ES[check_headers_ok]="linux-headers-%s instalado (DKMS puede compilar módulos)."
T_ES[check_headers_fail]="linux-headers-%s no instalado. DKMS fallaría al compilar el módulo amdxdna tras una compilación larga de XRT. Instálalo antes con: sudo apt install linux-headers-%s"
T_ES[check_cpu_ok]="CPU detectada: %s"
T_ES[check_cpu_warn]="La CPU no parece Ryzen AI / Strix / Phoenix / Hawk Point. Se continúa de todas formas."
T_ES[check_dev_ok]="Dispositivo NPU presente en /dev/accel/accel0."
T_ES[check_dev_warn]="No se encuentra /dev/accel/accel0 todavía. El módulo puede necesitar cargarse tras instalar."
T_ES[check_disk_ok]="Espacio libre: %s GB (mínimo 4 GB)."
T_ES[check_disk_fail]="Espacio insuficiente en %s: %s GB libres, se necesitan al menos 4 GB."
T_ES[check_net_ok]="Red accesible (github.com)."
T_ES[check_net_fail]="No se puede acceder a github.com. Revisa tu conexión."
T_ES[check_dkms_ok]="dkms instalado (%s)."
T_ES[check_dkms_missing]="dkms no está instalado. Se instalará."
T_ES[check_secureboot_on]="Secure Boot está ACTIVADO. DKMS firmará el módulo con la MOK del sistema; si no hay MOK enrolada, el módulo no cargará. Considera 'mokutil --list-enrolled'."
T_ES[check_secureboot_off]="Secure Boot está desactivado."
T_ES[state_title]="Estado actual de la instalación"
T_ES[state_xrt_installed]="xrt-base instalado: %s"
T_ES[state_xrt_missing]="xrt-base no instalado."
T_ES[state_plugin_installed]="xrt_plugin-amdxdna instalado: %s"
T_ES[state_plugin_missing]="xrt_plugin-amdxdna no instalado."
T_ES[state_dkms_active]="Módulo DKMS activo: %s"
T_ES[state_dkms_inactive]="Módulo DKMS no registrado."
T_ES[state_limits_ok]="Límites memlock configurados en %s."
T_ES[state_limits_missing]="Falta el archivo de límites %s."
T_ES[state_udev_ok]="Regla udev presente en %s."
T_ES[state_udev_missing]="Falta la regla udev %s."
T_ES[state_rc_ok]="Función npu-env presente en %s."
T_ES[state_rc_missing]="Función npu-env no encontrada en ningún shell rc."
T_ES[state_dev_perms_ok]="/dev/accel/accel0 con permisos %s (regla udev aplicada)."
T_ES[state_dev_perms_warn]="/dev/accel/accel0 con permisos %s (esperado 666 — prueba: sudo udevadm control --reload-rules && sudo udevadm trigger)."
T_ES[state_all_ok]="Todo está ya instalado y configurado."
T_ES[state_partial]="Instalación parcial detectada — reejecutar completará lo que falte."
T_ES[step_deps]="Instalar DKMS (si falta)"
T_ES[step_clone]="Clonar el repositorio xdna-driver (con submódulos)"
T_ES[step_amd_deps]="Instalar dependencias de build del repo de AMD (xrtdeps.sh)"
T_ES[step_build_xrt]="Compilar XRT base"
T_ES[step_install_xrt]="Instalar el .deb base de XRT"
T_ES[step_build_plugin]="Compilar el plugin amdxdna"
T_ES[step_install_plugin]="Instalar el .deb del plugin amdxdna (registra DKMS)"
T_ES[step_memlock]="Configurar el límite memlock y aplicarlo a la sesión actual"
T_ES[step_shell]="Configurar el helper de shell (npu-env)"
T_ES[step_verify]="Verificar post-instalación (ruta del módulo, permisos del device, regla udev)"
T_ES[step_validate]="Activar XRT y ejecutar tests de validación"
T_ES[skip_xrt]="xrt-base ya está instalado — se omite build e instalación."
T_ES[skip_plugin]="xrt_plugin-amdxdna ya está instalado — se omite build e instalación."
T_ES[skip_limits]="Límites memlock ya configurados — se omite."
T_ES[skip_rc]="Helper npu-env ya presente — se omite."
T_ES[final_title]="Verificación final"
T_ES[final_ok]="Instalación completada. La NPU está operativa."
T_ES[final_partial]="Instalación finalizada con avisos — revisa los mensajes anteriores."
T_ES[useful_title]="Comandos útiles"
T_ES[useful_activate]="Activar XRT en una terminal nueva:"
T_ES[useful_examine]="Mostrar info de la NPU y dispositivos detectados:"
T_ES[useful_validate]="Ejecutar tests de validación (gemm, latency, throughput):"
T_ES[useful_turbo]="Pasar la NPU a modo rendimiento (turbo):"
T_ES[useful_status]="Comprobar el módulo DKMS tras una actualización de kernel:"
T_ES[useful_uninstall]="Desinstalar todo:"
T_ES[uninstall_confirm]="Esto eliminará XRT, el plugin, el módulo DKMS, los límites, la regla udev y el helper npu-env. ¿Continuar?"
T_ES[uninstall_done]="Desinstalación completa. Se recomienda reiniciar."
detect_default_lang() {
# Pick Spanish if any locale env var starts with "es" (es_ES, es_MX, etc.).
local v="${LC_ALL:-${LC_MESSAGES:-${LANG:-}}}"
if [[ "$v" =~ ^es([_.@-]|$) ]]; then
echo "es"
else
echo "en"
fi
}
t() {
local key="$1"
if [[ "$LANG_CODE" == "es" ]]; then
printf "%s" "${T_ES[$key]:-${T_EN[$key]:-???$key???}}"
else
printf "%s" "${T_EN[$key]:-???$key???}"
fi
}
# =============================================================================
# Helpers
# =============================================================================
ask_yes_no() {
local prompt="$1"
local default="${2:-Y}"
local yn
if (( ASSUME_YES )); then
return 0
fi
if [[ "$default" == "Y" ]]; then
printf "%s[ask]%s %s%s [Y/n]:%s " "$C_PINK" "$C_RESET" "$C_TEXT" "$prompt" "$C_RESET"
else
printf "%s[ask]%s %s%s [y/N]:%s " "$C_PINK" "$C_RESET" "$C_TEXT" "$prompt" "$C_RESET"
fi
read -r yn
yn="${yn:-$default}"
[[ "$yn" =~ ^[YySs]$ ]]
}
fmt_cmd() {
# Join args with spaces for human-readable display (independent of IFS).
local out=""
local arg
for arg in "$@"; do
out+="$arg "
done
printf "%s" "${out% }"
}
run_cmd() {
# Execute a command as an argv array — NO eval, no shell interpretation.
# Use run_in_dir() if you need to cd before executing.
log_run "$(fmt_cmd "$@")"
if (( DRY_RUN )); then
return 0
fi
if [[ -n "${LOG_FILE:-}" ]]; then
"$@" 2>&1 | tee -a "$LOG_FILE"
return "${PIPESTATUS[0]}"
fi
"$@"
}
run_in_dir() {
# Run a command inside a subshell after cd-ing to a directory. Avoids `cd && cmd` via eval.
local dir="$1"; shift
log_run "(cd $dir && $(fmt_cmd "$@"))"
if (( DRY_RUN )); then
return 0
fi
if [[ -n "${LOG_FILE:-}" ]]; then
( cd "$dir" && "$@" ) 2>&1 | tee -a "$LOG_FILE"
return "${PIPESTATUS[0]}"
fi
( cd "$dir" && "$@" )
}
validate_path() {
# Reject user-supplied paths containing shell metacharacters.
local label="$1" value="$2"
if [[ -z "$value" ]]; then
log_err "Empty value for $label."
exit 2
fi
if [[ ! "$value" =~ $PATH_REGEX ]]; then
log_err "Invalid characters in $label: $value (allowed: letters, digits, . _ / ~ + : -)"
exit 2
fi
}
init_log_file() {
if (( NO_LOG )); then
LOG_FILE=""
return 0
fi
if [[ -z "${LOG_FILE:-}" ]]; then
LOG_FILE="${TMPDIR:-/tmp}/install-npu-amd-$(date +%Y%m%d-%H%M%S).log"
fi
# Ensure directory exists, then create/truncate the file
local log_dir
log_dir="$(dirname "$LOG_FILE")"
mkdir -p "$log_dir"
if ! : > "$LOG_FILE" 2>/dev/null; then
printf "%s[warn]%s %sCould not write to %s — disabling file logging.%s\n" \
"$C_YELLOW" "$C_RESET" "$C_TEXT" "$LOG_FILE" "$C_RESET" >&2
LOG_FILE=""
return 0
fi
{
echo "***** install-npu-amd.sh log *****"
echo "Started: $(date -Iseconds)"
echo "Version: $SCRIPT_VERSION"
echo "Args: $ORIG_ARGS"
echo "Host: $(hostname)"
echo "User: $USER"
echo "Kernel: $(uname -r)"
echo "Machine: $(uname -m)"
echo "**********************************"
echo
} >> "$LOG_FILE"
}
require_sudo() {
if (( DRY_RUN )); then
return 0
fi
if ! sudo -n true 2>/dev/null; then
log_info "$(t prompt_sudo)"
sudo -v
fi
# Start keep-alive only once per script run, track its PID so the trap can clean it up
if [[ -z "$SUDO_KEEPALIVE_PID" ]]; then
( while true; do sudo -n true; sleep 60; kill -0 "$$" 2>/dev/null || exit; done ) 2>/dev/null &
SUDO_KEEPALIVE_PID=$!
disown 2>/dev/null || true
fi
}
cleanup_on_exit() {
local rc=$?
# Stop the sudo keep-alive subshell if still running
if [[ -n "$SUDO_KEEPALIVE_PID" ]] && kill -0 "$SUDO_KEEPALIVE_PID" 2>/dev/null; then
kill "$SUDO_KEEPALIVE_PID" 2>/dev/null || true
wait "$SUDO_KEEPALIVE_PID" 2>/dev/null || true
fi
if (( rc != 0 )); then
log_err "Failed at: ${CURRENT_STEP:-unknown step}"
if [[ -n "${LOG_FILE:-}" ]]; then
log_err "Full log saved to: $LOG_FILE"
log_err "Inspect it with: tail -n 100 \"$LOG_FILE\""
fi
fi
return $rc
}
trap cleanup_on_exit EXIT
trap 'log_err "Interrupted."; exit 130' INT TERM
# =============================================================================
# Help / version
# =============================================================================
show_help() {
# Show the figlet banner if available; otherwise fall back to a plain title.
# Never prompts to install figlet from --help.
if command -v figlet >/dev/null 2>&1; then
printf "%s" "$C_MAUVE"
figlet -w 100 "NPU Setup"
printf "%s\n" "$C_RESET"
else
log_title "***** NPU Setup *****"
fi
cat <<EOF
$(t help_summary)
Usage: $SCRIPT_NAME [OPTIONS]
$(t help_options)
$(t help_lang)
$(t help_dry)
$(t help_skip_tests)
$(t help_no_cleanup)
$(t help_yes)
$(t help_check)
$(t help_uninstall)
$(t help_build_dir)
$(t help_log_file)
$(t help_no_log)
$(t help_help)
$(t help_version)
EOF
}
show_version() {
printf "%s %s\n" "$SCRIPT_NAME" "$SCRIPT_VERSION"
}
# =============================================================================
# Welcome banner (figlet)
# =============================================================================
ensure_figlet() {
if command -v figlet >/dev/null 2>&1; then
return 0
fi
# In read-only modes (check) skip the install prompt entirely
if [[ "$ACTION" == "check" ]]; then
return 1
fi
log_warn "figlet is not installed."
if ask_yes_no "Install figlet now (sudo apt install figlet)?" "Y"; then
require_sudo
run_cmd sudo apt-get install -y figlet
else
log_info "Continuing without figlet banner."
return 1
fi
}
show_welcome() {
if ensure_figlet; then
printf "%s" "$C_MAUVE"
figlet -w 100 "NPU Setup"
printf "%s\n" "$C_RESET"
else
log_title "***** NPU Setup *****"
fi
log_info "Version: $SCRIPT_VERSION | Language: $LANG_CODE | Action: $ACTION"
if (( DRY_RUN )); then
log_warn "Dry-run mode — no changes will be made."
fi
}
# =============================================================================
# Introduction shown before user confirms
# =============================================================================
show_introduction() {
log_title "$(t intro_what)"
printf "%s%s%s\n" "$C_TEXT" "$(t intro_what_body)" "$C_RESET"
log_title "$(t intro_what_will)"
# printf '%b' lets the embedded \n in the i18n string render correctly
printf "%s%b%s\n" "$C_TEXT" "$(t intro_steps)" "$C_RESET"
printf "\n"
log_info "$(t intro_disk)"
log_info "$(t intro_sudo)"
printf "\n"
}
# =============================================================================
# Pre-flight checks
# =============================================================================
preflight_checks() {
log_step "$(t check_title)"
local arch distro_id distro_ver kernel cpu free_gb
arch="$(uname -m)"
if [[ "$arch" != "x86_64" ]]; then
log_err "$(printf "$(t check_arch_fail)" "$arch")"
exit 1
fi
log_ok "$(t check_arch_ok)"
if [[ ! -r /etc/os-release ]]; then
log_err "Cannot read /etc/os-release."
exit 1
fi
# Parse without sourcing to avoid executing arbitrary code from a system file.
distro_id="$(grep -E '^ID=' /etc/os-release | head -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
distro_ver="$(grep -E '^VERSION_ID=' /etc/os-release | head -n1 | cut -d= -f2- | tr -d '"' | tr -d "'")"
distro_ver="${distro_ver:-unknown}"
case "$distro_id" in
debian|ubuntu|linuxmint)
log_ok "$(printf "$(t check_distro_ok)" "$distro_id" "$distro_ver")" ;;
*)
log_err "$(printf "$(t check_distro_fail)" "$distro_id")"
exit 1 ;;
esac
kernel="$(uname -r)"
log_info "$(printf "$(t check_kernel)" "$kernel")"
local kconfig="/boot/config-$kernel"
if [[ -r "$kconfig" ]] && grep -q "^CONFIG_DRM_ACCEL_AMDXDNA=" "$kconfig"; then
log_ok "$(t check_kmod_ok)"
elif [[ -r "/proc/config.gz" ]] && zcat /proc/config.gz 2>/dev/null | grep -q "^CONFIG_DRM_ACCEL_AMDXDNA="; then
log_ok "$(t check_kmod_ok)"
else
log_err "$(t check_kmod_fail)"
exit 1
fi
# Kernel headers check — DKMS needs them to build the amdxdna module during the plugin postinst.
# Without this gate, the user discovers the failure after a 5–10 min XRT compile.
if dpkg-query -W -f='${Status}' "linux-headers-$kernel" 2>/dev/null | grep -q "install ok installed"; then
log_ok "$(printf "$(t check_headers_ok)" "$kernel")"
else
log_err "$(printf "$(t check_headers_fail)" "$kernel" "$kernel")"
exit 1
fi
cpu="$(awk -F: '/^model name/ {print $2; exit}' /proc/cpuinfo | sed 's/^[ \t]*//')"
log_ok "$(printf "$(t check_cpu_ok)" "$cpu")"
if ! echo "$cpu" | grep -qiE "Ryzen AI|Strix|Phoenix|Hawk|Krackan"; then
log_warn "$(t check_cpu_warn)"
fi
if [[ -e /dev/accel/accel0 ]]; then
log_ok "$(t check_dev_ok)"
else
log_warn "$(t check_dev_warn)"
fi
free_gb="$(df -BG --output=avail "$HOME" | tail -n1 | tr -dc '0-9')"
if (( free_gb < 4 )); then
log_err "$(printf "$(t check_disk_fail)" "$HOME" "$free_gb")"
exit 1
fi
log_ok "$(printf "$(t check_disk_ok)" "$free_gb")"
if curl -fsSL --connect-timeout 5 https://github.com >/dev/null 2>&1; then
log_ok "$(t check_net_ok)"
else
log_err "$(t check_net_fail)"
exit 1
fi
if dpkg-query -W -f='${Version}' dkms >/dev/null 2>&1; then
local dkms_ver
dkms_ver="$(dpkg-query -W -f='${Version}' dkms)"
log_ok "$(printf "$(t check_dkms_ok)" "$dkms_ver")"
else
log_warn "$(t check_dkms_missing)"
fi
if [[ -d /sys/firmware/efi ]] && command -v mokutil >/dev/null 2>&1 \
&& mokutil --sb-state 2>/dev/null | grep -q "SecureBoot enabled"; then
log_warn "$(t check_secureboot_on)"
else
log_info "$(t check_secureboot_off)"
fi
}
# =============================================================================
# Detect current install state
# =============================================================================
detect_state() {
log_step "$(t state_title)"
local missing=0
local xrt_ver plugin_ver dkms_state target_rc
if xrt_ver="$(dpkg-query -W -f='${Version}' xrt-base 2>/dev/null)"; then
log_ok "$(printf "$(t state_xrt_installed)" "$xrt_ver")"
XRT_INSTALLED=1
else
log_info "$(t state_xrt_missing)"
XRT_INSTALLED=0
missing=$((missing+1))
fi
if plugin_ver="$(dpkg-query -W -f='${Version}' xrt_plugin-amdxdna 2>/dev/null)"; then
log_ok "$(printf "$(t state_plugin_installed)" "$plugin_ver")"
PLUGIN_INSTALLED=1
else
log_info "$(t state_plugin_missing)"
PLUGIN_INSTALLED=0
missing=$((missing+1))
fi
if command -v dkms >/dev/null 2>&1 \
&& dkms_state="$(dkms status "$DKMS_MODULE" 2>/dev/null | head -n1)" \
&& [[ -n "$dkms_state" ]]; then
log_ok "$(printf "$(t state_dkms_active)" "$dkms_state")"
else
log_info "$(t state_dkms_inactive)"
fi
if [[ -f "$LIMITS_FILE" ]]; then
log_ok "$(printf "$(t state_limits_ok)" "$LIMITS_FILE")"
LIMITS_OK=1
else
log_info "$(printf "$(t state_limits_missing)" "$LIMITS_FILE")"
LIMITS_OK=0
missing=$((missing+1))
fi
if [[ -f "$UDEV_RULES_FILE" ]]; then
log_ok "$(printf "$(t state_udev_ok)" "$UDEV_RULES_FILE")"
else
log_info "$(printf "$(t state_udev_missing)" "$UDEV_RULES_FILE")"
fi
# Device permission check: confirms the udev rule is actually applied to /dev/accel/accel0.
if [[ -e /dev/accel/accel0 ]]; then
local dev_mode
dev_mode="$(stat -c '%a' /dev/accel/accel0 2>/dev/null || echo "?")"
if [[ "$dev_mode" == "666" ]]; then
log_ok "$(printf "$(t state_dev_perms_ok)" "$dev_mode")"
else
log_warn "$(printf "$(t state_dev_perms_warn)" "$dev_mode")"
fi
fi
target_rc="$(detect_shell_rc)"
if [[ -n "$target_rc" ]] && grep -Fq "npu-env()" "$target_rc" 2>/dev/null; then
log_ok "$(printf "$(t state_rc_ok)" "$target_rc")"
RC_OK=1
else
log_info "$(t state_rc_missing)"
RC_OK=0
missing=$((missing+1))
fi
if (( missing == 0 )); then
log_ok "$(t state_all_ok)"
else
log_info "$(t state_partial)"
fi
}
detect_shell_rc() {
# Prefer the rc matching the user's $SHELL; fall back by existence.
local shell_basename
shell_basename="$(basename "${SHELL:-}")"
case "$shell_basename" in
zsh) echo "$HOME/.zshrc" ;;
bash) echo "$HOME/.bashrc" ;;
*)
if [[ -f "$HOME/.bashrc" ]]; then echo "$HOME/.bashrc"
elif [[ -f "$HOME/.zshrc" ]]; then echo "$HOME/.zshrc"
else echo "$HOME/.bashrc"; fi
;;
esac
}
# =============================================================================
# Installation steps
# =============================================================================
step_install_deps() {
CURRENT_STEP="install-deps"
log_step "$(t step_deps)"
require_sudo
if ! command -v dkms >/dev/null 2>&1; then
run_cmd sudo apt-get update
run_cmd sudo apt-get install -y dkms
fi
# Repo-based deps (libpybind11-dev, libeigen3-dev, etc.) are installed by step_run_amd_deps.
}
step_clone_repo() {
CURRENT_STEP="clone"
log_step "$(t step_clone)"
if [[ -d "$BUILD_DIR/xdna-driver/.git" ]]; then
log_skip "Repository already cloned at $BUILD_DIR/xdna-driver"
return 0
fi
run_cmd mkdir -p "$BUILD_DIR"
run_cmd git clone --recursive "$REPO_URL" "$BUILD_DIR/xdna-driver"
}
step_run_amd_deps() {
CURRENT_STEP="amd-deps"
log_step "$(t step_amd_deps)"
require_sudo
if [[ ! -f "$BUILD_DIR/xdna-driver/tools/amdxdna_deps.sh" ]]; then
log_err "amdxdna_deps.sh not found — run clone first."
return 1
fi
run_in_dir "$BUILD_DIR/xdna-driver" sudo ./tools/amdxdna_deps.sh
}
step_build_xrt() {
CURRENT_STEP="build-xrt"
log_step "$(t step_build_xrt)"
if (( XRT_INSTALLED )); then
log_skip "$(t skip_xrt)"
return 0
fi
run_in_dir "$BUILD_DIR/xdna-driver/xrt/build" ./build.sh -npu -opt
}
step_install_xrt_base() {
CURRENT_STEP="install-xrt-base"
log_step "$(t step_install_xrt)"
if (( XRT_INSTALLED )); then
log_skip "$(t skip_xrt)"
return 0
fi
require_sudo
# Glob expansion happens here in the caller, not inside run_cmd, so no eval is needed.
local debs=( "$BUILD_DIR/xdna-driver/xrt/build/Release/"xrt_*-amd64-base.deb )
if (( ! DRY_RUN )) && [[ ! -e "${debs[0]}" ]]; then
log_err "Expected XRT base .deb not found in $BUILD_DIR/xdna-driver/xrt/build/Release/"
return 1
fi
run_cmd sudo apt-get install -y "${debs[@]}"
XRT_INSTALLED=1
}
step_build_plugin() {
CURRENT_STEP="build-plugin"
log_step "$(t step_build_plugin)"
if (( PLUGIN_INSTALLED )); then
log_skip "$(t skip_plugin)"
return 0
fi
run_in_dir "$BUILD_DIR/xdna-driver/build" ./build.sh -release
}
step_install_plugin() {
CURRENT_STEP="install-plugin"
log_step "$(t step_install_plugin)"
if (( PLUGIN_INSTALLED )); then
log_skip "$(t skip_plugin)"
return 0
fi
require_sudo
local debs=( "$BUILD_DIR/xdna-driver/build/Release/"xrt_plugin.*-x86_64-amdxdna.deb )
if (( ! DRY_RUN )) && [[ ! -e "${debs[0]}" ]]; then
log_err "Expected amdxdna plugin .deb not found in $BUILD_DIR/xdna-driver/build/Release/"
return 1
fi
run_cmd sudo apt-get install -y "${debs[@]}"
PLUGIN_INSTALLED=1
}
step_configure_memlock() {
CURRENT_STEP="memlock"
log_step "$(t step_memlock)"
if [[ -f "$LIMITS_FILE" ]]; then
log_skip "$(t skip_limits)"
else
require_sudo
log_run "write memlock limits to $LIMITS_FILE"
if (( ! DRY_RUN )); then
printf '* soft memlock unlimited\n* hard memlock unlimited\n' \
| sudo tee "$LIMITS_FILE" >/dev/null
fi
LIMITS_OK=1
fi
# Apply to the current shell so xrt-smi can run right after
if (( ! DRY_RUN )); then
sudo prlimit --pid $$ --memlock=unlimited:unlimited 2>/dev/null || \
log_warn "Could not raise memlock for current shell — open a new login session if xrt-smi reports mmap errors."
fi
}
step_configure_shell() {
CURRENT_STEP="shell-rc"
log_step "$(t step_shell)"
local rc
rc="$(detect_shell_rc)"
if grep -Fq "npu-env()" "$rc" 2>/dev/null; then
log_skip "$(t skip_rc)"
return 0
fi
if (( ! DRY_RUN )) && [[ -f "$rc" ]]; then
cp -a "$rc" "${rc}.bak.$(date +%Y%m%d-%H%M%S)"
log_info "Backed up $rc"
fi
log_run "append npu-env() helper to $rc"
if (( ! DRY_RUN )); then
{
printf '\n%s\n' "$RC_MARKER"
printf 'npu-env() { source %s/setup.sh; }\n' "$XRT_PREFIX"
} >> "$rc"
fi
log_ok "Updated $rc"
RC_OK=1
}
step_post_install_verify() {
# Explicit verification of: DKMS module path, /dev/accel/accel0 permissions, udev rule.
CURRENT_STEP="post-verify"
log_step "$(t step_verify)"
local modfile mode
if command -v modinfo >/dev/null 2>&1; then
modfile="$(modinfo amdxdna 2>/dev/null | awk '/^filename:/ {print $2; exit}')"
if [[ -z "$modfile" ]]; then
log_warn "modinfo amdxdna returned no filename — module may not be loadable."
elif [[ "$modfile" == *"/updates/dkms/"* ]]; then
log_ok "amdxdna module loaded from DKMS: $modfile"
else
log_warn "amdxdna found at $modfile (expected DKMS path /updates/dkms/)."
fi
fi
if [[ -e /dev/accel/accel0 ]]; then
mode="$(stat -c '%a' /dev/accel/accel0 2>/dev/null || echo "?")"
if [[ "$mode" == "666" ]]; then
log_ok "/dev/accel/accel0 present, mode 0666 (udev rule applied)."
else
log_warn "/dev/accel/accel0 present but mode is $mode (expected 666 from udev rule). You may need: sudo udevadm control --reload-rules && sudo udevadm trigger"
fi
else
log_warn "/dev/accel/accel0 missing — the kernel module may not be loaded."
fi
if [[ -f "$UDEV_RULES_FILE" ]]; then
log_ok "udev rule present: $UDEV_RULES_FILE"
else
log_warn "udev rule missing: $UDEV_RULES_FILE"
fi
}
step_run_validation() {
CURRENT_STEP="validate"
log_step "$(t step_validate)"
if (( SKIP_TESTS )); then
log_skip "Tests skipped (--skip-tests)."
return 0
fi
# shellcheck disable=SC1091
if (( ! DRY_RUN )); then
# Activate XRT in this shell (variables don't persist after the script ends, that's fine).
source "$XRT_PREFIX/setup.sh" >/dev/null 2>&1 || true
fi
run_cmd "$XRT_PREFIX/bin/xrt-smi" --version
run_cmd "$XRT_PREFIX/bin/xrt-smi" examine
run_cmd "$XRT_PREFIX/bin/xrt-smi" validate
}
# =============================================================================
# Final summary
# =============================================================================
show_useful_commands() {
log_title "$(t useful_title)"
printf "%s%s%s\n" "$C_TEXT" "$(t useful_activate)" "$C_RESET"
printf " npu-env\n\n"
printf "%s%s%s\n" "$C_TEXT" "$(t useful_examine)" "$C_RESET"
printf " xrt-smi examine\n\n"
printf "%s%s%s\n" "$C_TEXT" "$(t useful_validate)" "$C_RESET"
printf " xrt-smi validate\n\n"
printf "%s%s%s\n" "$C_TEXT" "$(t useful_turbo)" "$C_RESET"
printf " sudo xrt-smi configure --pmode turbo\n\n"
printf "%s%s%s\n" "$C_TEXT" "$(t useful_status)" "$C_RESET"
printf " sudo dkms status %s\n sudo modinfo amdxdna | grep filename\n\n" "$DKMS_MODULE"
printf "%s%s%s\n" "$C_TEXT" "$(t useful_uninstall)" "$C_RESET"
printf " %s --uninstall\n" "$SCRIPT_NAME"
}
show_final_summary() {
log_step "$(t final_title)"
if (( XRT_INSTALLED && PLUGIN_INSTALLED && LIMITS_OK && RC_OK )); then
log_ok "$(t final_ok)"
else
log_warn "$(t final_partial)"
fi
show_useful_commands
if (( ! NO_CLEANUP )) && [[ -d "$BUILD_DIR" ]]; then
printf "\n"
if ask_yes_no "Remove build directory ($BUILD_DIR, ~3 GB)? DKMS keeps the sources separately, so this is safe." "Y"; then
run_cmd rm -rf "$BUILD_DIR"
log_ok "Build directory cleaned."
fi
fi
if [[ -n "${LOG_FILE:-}" ]]; then
printf "\n"
log_info "Full log written to: $LOG_FILE"
fi
}
# =============================================================================
# Uninstall
# =============================================================================
do_uninstall() {
log_step "Uninstall"
if ! ask_yes_no "$(t uninstall_confirm)" "N"; then
log_info "$(t abort_user)"
exit 0
fi
require_sudo
# Only call apt-get purge for packages that are actually installed.
if dpkg-query -W -f='${Version}' xrt_plugin-amdxdna >/dev/null 2>&1; then
run_cmd sudo apt-get purge -y xrt_plugin-amdxdna
fi
if dpkg-query -W -f='${Version}' xrt-base >/dev/null 2>&1; then
run_cmd sudo apt-get purge -y xrt-base
fi
run_cmd sudo rm -f "$LIMITS_FILE" "$UDEV_RULES_FILE"
run_cmd sudo rm -rf "$XRT_PREFIX"
local rc marker_escaped
rc="$(detect_shell_rc)"
if [[ -f "$rc" ]] && grep -Fq "npu-env()" "$rc"; then
# Escape characters that are special to sed BRE in the marker.
marker_escaped="$(printf '%s' "$RC_MARKER" | sed 's/[\/&.*[^$]/\\&/g')"
run_cmd sed -i.bak "/$marker_escaped/,/^npu-env/d" "$rc"
log_ok "Removed npu-env helper from $rc (backup at ${rc}.bak)"
fi
log_ok "$(t uninstall_done)"
}
# =============================================================================
# Argument parsing
# =============================================================================
parse_args() {
# Auto-detect locale first so --help/--version respect $LANG when no explicit flag is given.
if [[ -z "$LANG_CODE" ]]; then
LANG_CODE="$(detect_default_lang)"
fi
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help) show_help; exit 0 ;;
--version) show_version; exit 0 ;;
--es|--spanish) LANG_CODE="es" ;;
--en|--english) LANG_CODE="en" ;;
--dry-run) DRY_RUN=1 ;;
--skip-tests) SKIP_TESTS=1 ;;
--no-cleanup) NO_CLEANUP=1 ;;
-y|--yes) ASSUME_YES=1 ;;
--check) ACTION="check" ;;
--uninstall) ACTION="uninstall" ;;
--build-dir) shift; validate_path "--build-dir" "${1:-}"; BUILD_DIR="$1" ;;
--log-file) shift; validate_path "--log-file" "${1:-}"; LOG_FILE="$1" ;;
--no-log) NO_LOG=1 ;;
*)
log_err "Unknown option: $1"
show_help
exit 2 ;;
esac
shift
done
}
# =============================================================================
# Main
# =============================================================================
main() {
parse_args "$@"
# Resolve language: explicit flag wins, else auto-detect from locale, else English.
if [[ -z "$LANG_CODE" ]]; then
LANG_CODE="$(detect_default_lang)"
fi
init_log_file
# Globals tracking install state (set by detect_state, used by skip logic)
XRT_INSTALLED=0
PLUGIN_INSTALLED=0
LIMITS_OK=0
RC_OK=0
show_welcome
if [[ -n "${LOG_FILE:-}" ]]; then
log_info "Logging to: $LOG_FILE"
fi
case "$ACTION" in
check)
preflight_checks
detect_state
exit 0
;;
uninstall)
do_uninstall
exit 0
;;
install)
show_introduction
if ! ask_yes_no "$(t ask_proceed)" "Y"; then
log_info "$(t abort_user)"
exit 0
fi
preflight_checks
detect_state
if (( XRT_INSTALLED && PLUGIN_INSTALLED && LIMITS_OK && RC_OK )); then
log_ok "$(t state_all_ok)"
if ! ask_yes_no "Run validation tests anyway?" "Y"; then
exit 0
fi
step_run_validation
show_useful_commands
exit 0
fi
require_sudo
step_install_deps
step_clone_repo
step_run_amd_deps
step_build_xrt
step_install_xrt_base
step_build_plugin
step_install_plugin
step_configure_memlock
step_configure_shell
step_post_install_verify
step_run_validation
show_final_summary
;;
esac
}
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment