Skip to content

Commit f7b3b8c

Browse files
committed
v0.8.0
1 parent 2942fdb commit f7b3b8c

5 files changed

Lines changed: 97 additions & 45 deletions

File tree

.claude/settings.local.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(xargs cat -n)",
5+
"Bash(python3 *)",
6+
"Bash(grep \"\\\\.cs$\\\\|\\\\.xaml$\")",
7+
"Bash(grep -v \"^--$\")",
8+
"Bash(git *)",
9+
"Bash(nvidia-smi)",
10+
"Bash(grep \"\\\\.cs$\")",
11+
"Bash(gh api *)",
12+
"Bash(gh repo *)",
13+
"Read(//tmp/**)",
14+
"Bash(curl -s \"https://raw.githubusercontent.com/JamesCJ60/Universal-x86-Tuning-Utility/master/Universal%20x86%20Tuning%20Utility/Scripts/RyzenAdj_To_UXTU.cs\")",
15+
"Bash(xargs ls)",
16+
"Bash(bash -n /home/oxgorou/Documents/GitHub/UXTU4Linux/install.sh)",
17+
"Bash(grep -n -A2 -B2 \"install.sh\\\\|curl\\\\|First run\\\\|uxtu4linux$\" /home/oxgorou/Documents/GitHub/UXTU4Linux/Wiki/Linux-Installation.md)",
18+
"Bash(PYTHONPYCACHEPREFIX=/tmp/uxtu_pyc python3 -m py_compile UXTU4Linux/UXTU4Linux.py UXTU4Linux/Assets/Modules/*.py)",
19+
"Bash(PYTHONPYCACHEPREFIX=/tmp/uxtu_pyc python3 -m unittest discover -s tests)",
20+
"Bash(PYTHONPYCACHEPREFIX=/tmp/uxtu_pyc python3 -c ' *)",
21+
"Bash(PYTHONPYCACHEPREFIX=/tmp/uxtu_pyc python3 -m py_compile UXTU4Linux/Assets/Modules/ui.py)",
22+
"WebSearch",
23+
"WebFetch(domain:forums.developer.nvidia.com)",
24+
"Read(//home/oxgorou/Documents/**)",
25+
"Read(//home/oxgorou/Documents/g-helper-linux-master \\(1\\)/**)",
26+
"Bash(grep -vE \"^\\\\s*//|^\\\\s*$\")",
27+
"Bash(grep -vE \"^\\\\s*$\")",
28+
"Bash(PYTHONPYCACHEPREFIX=/tmp/uxtu_pyc python3 -m py_compile UXTU4Linux/Assets/Modules/*.py UXTU4Linux/UXTU4Linux.py)",
29+
"Bash(niri msg *)",
30+
"Bash(PYTHONPYCACHEPREFIX=/tmp/uxtu_pyc python3 *)",
31+
"Bash(sudo -n dnf install -y wlr-randr)",
32+
"Bash(sed -n '95,106p' UXTU4Linux/UXTU4Linux.py)",
33+
"Bash(sed -n '118,150p' UXTU4Linux/Assets/Modules/setup.py)",
34+
"Bash(sed -n '221,228p' UXTU4Linux/Assets/Modules/ui.py)",
35+
"Bash(sed -n '45,75p' UXTU4Linux/Assets/Modules/settings.py)",
36+
"Bash(bash -n install.sh)",
37+
"Bash(grep -n \"sys.exit\\\\|break$\\\\|return$\\\\|def run\\\\|def main\\\\|_sig_handler\\\\|shutdown\" UXTU4Linux/Assets/Modules/daemon.py)"
38+
]
39+
}
40+
}

UXTU4Linux/Assets/Modules/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
GITHUB_API_URL = "https://api.github.com/repos/HorizonUnix/UXTU4Linux/releases/latest"
1111
LATEST_VER_URL = "https://github.com/HorizonUnix/UXTU4Linux/releases/latest"
12+
RYZEN_SMU_WIKI_URL = "https://github.com/HorizonUnix/UXTU4Linux/wiki/Linux-Installation#2-install-the-ryzen_smu-kernel-module"
13+
INSTALL_WIKI_URL = "https://github.com/HorizonUnix/UXTU4Linux/wiki/Linux-Installation#3-install-uxtu4linux"
1214

1315
_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
1416
ASSETS_DIR = os.path.join(_ROOT, "Assets")

UXTU4Linux/Assets/Modules/daemon.py

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
_SUSPEND_MONITOR_POLL_S: int = 1
4040
_SUSPEND_GAP_THRESHOLD_S: float = 1.0
4141

42+
_RYZEN_SMU_WIKI = cfg.RYZEN_SMU_WIKI_URL
43+
4244
_DAEMON_LOCK_FILE = "/run/uxtu4linux_daemon.lock"
4345
_daemon_lock_fh: object = None
4446

@@ -150,13 +152,35 @@ def _fmt_duration(seconds: float) -> str:
150152
return f"{seconds / 3600:.1f}h"
151153

152154

155+
_smu_blocked_warned = False
156+
157+
158+
def _smu_blocked() -> str | None:
159+
from Assets.Modules import smu
160+
if not smu.is_available():
161+
return "ryzen_smu is not available"
162+
if not smu.version_ok():
163+
return f"ryzen_smu {smu.get_version()} is too old (minimum: {smu.version_str(smu.MIN_VERSION)})"
164+
return None
165+
166+
153167
def _apply_via_smu(args: str, mode: str) -> tuple[str, bool]:
168+
global _smu_blocked_warned
154169
family = cfg.get("Info", "Family")
155170
if not args.strip():
156171
return "", False
157172
if not family:
158173
log.error("Cannot apply preset: CPU family not set in config — was hardware detected?")
159174
return "", False
175+
blocked = _smu_blocked()
176+
if blocked:
177+
if not _smu_blocked_warned:
178+
_smu_blocked_warned = True
179+
log.error("%s — presets cannot be applied.\nInstall guide: %s", blocked, cfg.RYZEN_SMU_WIKI_URL)
180+
return f"{blocked} — preset not applied", False
181+
if _smu_blocked_warned:
182+
_smu_blocked_warned = False
183+
log.info("ryzen_smu is available again — presets can be applied.")
160184
try:
161185
from Assets.Modules import runner
162186
output, rejected = runner.apply_args(args, family)
@@ -776,8 +800,7 @@ def main() -> None:
776800
log.info("UXTU4Linux daemon v%s", cfg.LOCAL_VERSION)
777801

778802
if cfg.get("Info", "Type") == "Intel":
779-
log.error("Intel CPUs are not supported — exiting.")
780-
sys.exit(1)
803+
log.warning("Intel CPU detected — SMU control is not supported; presets will not be applied.")
781804

782805
from Assets.Modules.hardware import _find_dmidecode, secure_boot_enabled
783806
from Assets.Modules import smu
@@ -799,24 +822,21 @@ def main() -> None:
799822
installed = ryzen_smu_installed()
800823
sb = secure_boot_enabled()
801824
if not installed:
802-
log.error("ryzen_smu not installed. Install: git clone https://github.com/amkillam/ryzen_smu && cd ryzen_smu && sudo make dkms-install")
803-
log.error("Then enroll the DKMS signing key: sudo mokutil --import /var/lib/dkms/mok.pub")
825+
log.error("ryzen_smu not installed.\nInstall guide: %s", _RYZEN_SMU_WIKI)
804826
elif sb and not ryzen_smu_signed():
805-
log.error("ryzen_smu installed but not signed for Secure Boot.")
806-
log.error("Enroll the DKMS signing key: sudo mokutil --import /var/lib/dkms/mok.pub — then reboot.")
827+
log.error("ryzen_smu installed but not signed for Secure Boot.\nInstall guide: %s", _RYZEN_SMU_WIKI)
807828
else:
808-
log.error("ryzen_smu installed but not loaded. Run: sudo modprobe ryzen_smu")
809-
sys.exit(1)
810-
811-
if not smu.version_ok():
829+
log.error("ryzen_smu installed but not loaded.\nInstall guide: %s", _RYZEN_SMU_WIKI)
830+
log.warning("Running without SMU access — presets will not be applied until ryzen_smu is working.")
831+
elif not smu.version_ok():
812832
log.error(
813-
"ryzen_smu version %s is too old (minimum: %s). Update: git clone https://github.com/amkillam/ryzen_smu && cd ryzen_smu && sudo make dkms-install",
814-
smu.get_version(), smu.version_str(smu.MIN_VERSION),
833+
"ryzen_smu version %s is too old (minimum: %s).\nInstall guide: %s",
834+
smu.get_version(), smu.version_str(smu.MIN_VERSION), _RYZEN_SMU_WIKI,
815835
)
816-
sys.exit(1)
817-
818-
log.info("ryzen_smu driver ready (version %s).", smu.get_version())
819-
log.debug("SMN interface available: %s", smu.has_smn())
836+
log.warning("Running without SMU access — presets will not be applied until ryzen_smu is updated.")
837+
else:
838+
log.info("ryzen_smu driver ready (version %s).", smu.get_version())
839+
log.debug("SMN interface available: %s", smu.has_smn())
820840

821841
daemon = PowerDaemon()
822842
on_ready = (

UXTU4Linux/Assets/Modules/hardware.py

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,17 @@ def check_binaries() -> None:
2121
f" Debian/Ubuntu : {_B}sudo apt install dmidecode{_R}\n"
2222
f" Fedora/RHEL : {_B}sudo dnf install dmidecode{_R}\n"
2323
f" Arch : {_B}sudo pacman -S dmidecode{_R}\n"
24-
f" openSUSE : {_B}sudo zypper install dmidecode{_R}\n"
24+
f" openSUSE : {_B}sudo zypper install dmidecode{_R}\n\n"
25+
f" Install guide: {_B}{cfg.INSTALL_WIKI_URL}{_R}\n"
2526
)
2627
raise SystemExit(1)
2728
cfg.DMIDECODE = dmi
28-
_check_ryzen_smu()
2929

3030

31-
_SMU_INSTALL_GUIDE = (
32-
f" {_B}git clone https://github.com/amkillam/ryzen_smu{_R}\n"
33-
f" {_B}cd ryzen_smu{_R}\n"
34-
f" {_B}sudo make dkms-install{_R}\n\n"
35-
f" Then enroll the DKMS signing key:\n"
36-
f" {_B}sudo mokutil --import /var/lib/dkms/mok.pub{_R}\n\n"
37-
f" Reboot, accept the key in MOK manager, then restart the service:\n"
38-
f" {_B}sudo systemctl restart uxtu4linux.service{_R}\n"
39-
)
31+
_SMU_INSTALL_GUIDE = f" Install guide: {_B}{cfg.RYZEN_SMU_WIKI_URL}{_R}\n"
4032

4133

42-
def _check_ryzen_smu() -> None:
34+
def check_ryzen_smu() -> None:
4335
from . import smu
4436

4537
if smu.is_available():
@@ -48,7 +40,7 @@ def _check_ryzen_smu() -> None:
4840
req = smu.version_str(smu.MIN_VERSION)
4941
print(
5042
f"\n ryzen_smu version {ver} is too old (minimum required: {req}).\n\n"
51-
f" Update it:\n\n{_SMU_INSTALL_GUIDE}"
43+
f"{_SMU_INSTALL_GUIDE}"
5244
)
5345
raise SystemExit(1)
5446
return
@@ -58,24 +50,19 @@ def _check_ryzen_smu() -> None:
5850
sb = secure_boot_enabled()
5951

6052
if not installed:
61-
print(f"\n ryzen_smu kernel module is not installed.\n\n Install it:\n\n{_SMU_INSTALL_GUIDE}")
53+
print(f"\n ryzen_smu kernel module is not installed.\n\n{_SMU_INSTALL_GUIDE}")
6254
raise SystemExit(1)
6355

6456
if sb and not signed:
6557
print(
6658
f"\n ryzen_smu is installed but not signed for Secure Boot.\n\n"
67-
f" Enroll the DKMS signing key:\n"
68-
f" {_B}sudo mokutil --import /var/lib/dkms/mok.pub{_R}\n\n"
69-
f" Reboot, accept the key in MOK manager, then restart the service:\n"
70-
f" {_B}sudo systemctl restart uxtu4linux.service{_R}\n"
59+
f"{_SMU_INSTALL_GUIDE}"
7160
)
7261
raise SystemExit(1)
7362

7463
print(
7564
f"\n ryzen_smu is installed but not loaded.\n\n"
76-
f" Load it with : {_B}sudo modprobe ryzen_smu{_R}\n\n"
77-
f" Then restart the service:\n"
78-
f" {_B}sudo systemctl restart uxtu4linux.service{_R}\n"
65+
f"{_SMU_INSTALL_GUIDE}"
7966
)
8067
raise SystemExit(1)
8168

UXTU4Linux/UXTU4Linux.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import fcntl as _fcntl
99
from Assets.Modules import config as cfg
10-
from Assets.Modules.hardware import check_binaries, show_info as hardware_info
10+
from Assets.Modules.hardware import check_binaries, check_ryzen_smu, show_info as hardware_info
1111
from Assets.Modules.power import get_presets, preset_menu
1212
from Assets.Modules.settings import settings_menu, ensure_config_files
1313
from Assets.Modules.automations import automations_menu
@@ -71,6 +71,16 @@ def main() -> None:
7171
check_binaries()
7272
check_integrity()
7373
cfg.load()
74+
75+
cpu_type = cfg.get("Info", "Type")
76+
if cpu_type == "Intel":
77+
print("\n Intel CPUs are not supported.\n")
78+
sys.exit(1)
79+
if cpu_type == "Unknown":
80+
print("\n Your hardware was not recognised. UXTU4Linux supports AMD Ryzen APUs and desktop CPUs only.\n")
81+
sys.exit(1)
82+
check_ryzen_smu()
83+
7484
verify_service_path()
7585
_require_daemon()
7686

@@ -84,13 +94,6 @@ def main() -> None:
8494
pause()
8595

8696
_apply_if_idle()
87-
cpu_type = cfg.get("Info", "Type")
88-
if cpu_type == "Intel":
89-
print("\n Intel CPUs are not supported.\n")
90-
sys.exit(1)
91-
if cpu_type == "Unknown":
92-
print("\n Your hardware was not recognised. UXTU4Linux supports AMD Ryzen APUs and desktop CPUs only.\n")
93-
sys.exit(1)
9497

9598
entries: list[tuple[str, str, object]] = [
9699
("Power Management", "power", preset_menu),

0 commit comments

Comments
 (0)