NixDaemon

NixOS pentest workstation as one flake — IceBreaker's successor
git clone https://git.daemon-sec.xyz/NixDaemon.git
Log | Files | Refs | README

fan-ctl (2344B)


      1 #!/usr/bin/env bash
      2 # fan-ctl — root-side actions for the daemon-sec.fans bar widget (run via
      3 # pkexec; the shell's polkit plugin presents the auth dialog). Thin dispatcher
      4 # over ~/.local/bin/fanfix, except `cap`, which re-applies the clock cap
      5 # without fanfix's built-in 20 s stress test so a panel click stays instant.
      6 set -uo pipefail
      7 
      8 FANFIX=/home/daemon-sec/.local/bin/fanfix
      9 CONF=/etc/tmpfiles.d/99-cpu-freq-cap.conf
     10 CPU0=/sys/devices/system/cpu/cpu0/cpufreq
     11 
     12 [ "$(id -u)" = 0 ] || { echo "fan-ctl must run as root (pkexec)" >&2; exit 1; }
     13 
     14 case "${1:-}" in
     15   auto|max)
     16     exec "$FANFIX" fan "$1" ;;
     17   set)
     18     pct="${2:?usage: fan-ctl set <30-100>}"
     19     exec "$FANFIX" fan "$pct" ;;
     20   curve)
     21     case "${2:-}" in
     22       on|off) exec "$FANFIX" fan curve "$2" ;;
     23       *) echo "usage: fan-ctl curve on|off" >&2; exit 2 ;;
     24     esac ;;
     25   drivers)
     26     exec "$FANFIX" fans --persist ;;
     27   cap)
     28     mhz="${2:-3200}"
     29     [[ "$mhz" =~ ^[0-9]+$ ]] || { echo "cap must be a number (MHz)" >&2; exit 2; }
     30     khz=$(( mhz < 100000 ? mhz * 1000 : mhz ))
     31     hwmax=$(cat "$CPU0/cpuinfo_max_freq")
     32     { [ "$khz" -ge 1500000 ] && [ "$khz" -le "$hwmax" ]; } \
     33       || { echo "cap out of range (1500-$(( hwmax / 1000 )) MHz)" >&2; exit 2; }
     34     cat > "$CONF" <<EOF
     35 # fanfix: broken GPU fan -> EC pins CPU at 399 MHz at ~79 C. Cap every core so it never gets there.
     36 # Remove with: fanfix uninstall   (after the fan is replaced)
     37 w /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq - - - - ${khz}
     38 EOF
     39     systemd-tmpfiles --create "$CONF"
     40     powerprofilesctl set performance 2>/dev/null || true
     41     systemd-tmpfiles --create "$CONF"   # profile switches toggle boost; re-assert
     42     echo "cap = $(( $(cat "$CPU0/scaling_max_freq") / 1000 )) MHz, persisted in $CONF" ;;
     43   uncap)
     44     # Full boost. The EC's fan-abnormal policy still stalls the CPU at ~79 C,
     45     # so sustained all-core loads may hit the 400 MHz clamp — deliberate choice.
     46     rm -f "$CONF"
     47     echo 1 > /sys/devices/system/cpu/cpufreq/boost
     48     for f in /sys/devices/system/cpu/cpu*/cpufreq/scaling_max_freq; do
     49       cat "${f%scaling_max_freq}cpuinfo_max_freq" > "$f"
     50     done
     51     echo "uncapped: max = $(( $(cat "$CPU0/scaling_max_freq") / 1000 )) MHz, turbo boost on" ;;
     52   *)
     53     echo "usage: fan-ctl auto|max|set <pct>|curve on|off|drivers|cap [MHz]|uncap" >&2
     54     exit 2 ;;
     55 esac