1925 Commits

Author SHA1 Message Date
AuxXxilium
80b1d77007 boot: only pass amd_iommu=off when an AMD GPU is present
amd_iommu has no graphics-only value. intel_iommu=igfx_off exempts just the
GPU and leaves the rest of the IOMMU working; the AMD driver has no equivalent
carve-out, so amd_iommu=off disables DMA remapping for the whole system -- and
with it VM device passthrough. Setting it for every platform in IGFXRL applied
that cost to Intel and GPU-less AMD boxes, which gain nothing from it.

Keep the platform gate and add a hardware one: emit amd_iommu=off only when a
1002 display device is actually on the bus.

It is needed on the boxes that do have one. The PSP fetches its TOC by DMA, and
with the IOMMU active the command never completes:

  psp gfx command ID_LOAD_TOC(0x20) failed and response status is (0x0)
  hw_init of IP block <psp> failed -22

amdgpu then aborts before drm_dev_register(), so no render node is created.
Confirmed on a Legion Go (Phoenix1, Radeon 780M): with amd_iommu=off the driver
probes and /dev/dri/renderD128 appears. amd_iommu=off alone is sufficient --
the broader iommu=off also works but is not needed here.

getAmdGpuId() mirrors the existing getIgpuId(), matching the whole PCI display
class rather than only VGA (0300) -- the Phoenix1 iGPU reports 0380.

Verified against synthetic sysfs trees: AMD-only and mixed Intel+AMD boxes
return the AMD id, while Intel-only and GPU-less boxes return nothing and so
keep their IOMMU.

Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-30 19:19:19 +02:00
AuxXxilium
c351550ee1 boot: highlight CPU thread warning in red 2026-08-30 17:15:09 +02:00
AuxXxilium
f6cba691e2 kernel: show selection menu directly without yes/no prompt 2026-08-30 11:32:10 +02:00
AuxXxilium
8bed01045b netfix: collapse "force" mode into "true"
The three-state toggle (false/true/force) had "force" as a strict
superset of "true". Merge them so "true" enables everything:

- boot.sh: R<bus>=<mac> pinning no longer needs the extra force branch
- boot.sh: network.* cmdline injection was force-only, now runs on true
- ramdisk-patch.sh: netfix system addon was force-only, now runs on true
- arc-functions.sh: menu is a plain enabled/disabled toggle again
2026-08-29 12:46:00 +02:00
AuxXxilium
2d8b5a08bf Revert "init: cleanup default addons"
This reverts commit 4d658feec2.
2026-08-29 12:43:03 +02:00
AuxXxilium
f1169c11f9 boot: always unload network drivers via modprobe -r 2026-08-27 23:07:44 +02:00
AuxXxilium
4d658feec2 init: cleanup default addons
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-27 17:44:45 +02:00
AuxXxilium
ef5c4acdaa getmapSelection: allow maxports on virtual machines
The maxports branch required MEV=physical, so a VM with a real HBA
carrying disks fell through to acports even when maxports was the right
answer. The gate goes back to at least 2024-06 and every commit touching
it since has been a rename or syntax change - no recorded reason for it.

Drop it from both the config recommendation and the automated write.
Only one case changes: external controller with disks on a VM now gets
maxports, matching what bare metal already got. The port-0 handling in
getmap() keeps its own MEV test and is untouched.
2026-08-25 22:56:20 +02:00
AuxXxilium
d0dbb7c524 getdiskinfo: only treat SAS/SCSI/RAID controllers with disks as external
The check marked a controller external on presence alone, so the empty
LSI 53C1030 that every VMware VM ships with set externalcontroller=true.
That disqualifies the sata_remap branch in getmapSelection and drops the
loader onto the SataPortMap path, which cannot describe controllers with
more than 8 ports or disks sitting on sparse ports.

Seen on a VM with three 30-port AHCI controllers holding 12 disks
(ata1-8, ata31-33, ata38) plus one diskless LSI adapter: SataPortMap
clamps 30 ports to 8, so DSM was told the disks live at indices the
kernel never used - empty bays and wrong numbering.

Count disks per controller with the same scsi_host + lsscsi idiom used
for sasdrives/scsidrives/raiddrives, and only set external when at least
one carries a disk.
2026-08-25 22:56:13 +02:00
AuxXxilium
6f46fd6cad readme: fix typo
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-25 19:23:51 +02:00
AuxXxilium
25f20933fd cpufreq: ship our own modules and drop the duplicate governor cmdline
modulelist: switch acpi_call, acpi_cpufreq and the seven cpufreq_* entries
from N to F. N is "copy but do not overwrite", so wherever DSM already ships
one of these, the stock Synology .ko stays and ours never lands -- even though
these link against the running kernel's cpufreq core and are exactly as
kernel-coupled as the kvm and network entries, which already use F.

boot.sh: drop the cpufreq.default_governor= cmdline for KVER >= 5. It set the
same value as the governor= parameter on the line above, which the
cpufreqscaling addon reads and applies from userspace once DSM is up. Without
it the kernel briefly uses its built-in default (CPU_FREQ_DEFAULT_GOV_PERFORMANCE
on these builds, since the schedutil default needs X86_INTEL_PSTATE) until
scaling.sh runs, and the end state is unchanged.

Neither change is a fix for the "scales for a few minutes, then pins to max"
report on an i7-8700: that box has scaling_driver=acpi-cpufreq,
scaling_governor=schedutil and scaling_min_freq at cpuinfo_min_freq, so the
driver, governor and limits are all correct and the frequency is being
requested, not clamped. These are consistency cleanups only.
2026-08-24 23:08:49 +02:00
AuxXxilium
0d96a4c658 cmdline: add gated MSI board fix for serial console port
MSI boards expose the serial console at 0x2e8 instead of the default
0x3f8. Add an arc.msifix config key, toggled from the Cmdline menu,
that switches syno_ttyS0 and earlycon to that address.

The choice is made where each value is assigned, so syno_ttyS0 stays
confined to the DT branch that owns it and is not introduced on
non-DT platforms.
2026-08-24 17:33:39 +02:00
AuxXxilium
d205b0b924 grub: update 2026-08-23 12:58:08 2026-08-23 12:58:08 +02:00
AuxXxilium
1fc70a00f2 grub: size image to 3700M to fit a 4GB device
bs=1M is MiB while stick capacity is advertised in decimal GB, so 3850
produced a 4.04 GB image that does not fit a 4GB device at all. 3700 MiB
is 3.88 GB, leaving a 3.0% margin under 4,000,000,000 B.

That is the same margin as the earlier seek=1850 (1.94 GB against a 2GB
device, 00409cfa), and it also clears real sticks that report less than
a full 4 GB. p3 ends up at 3600M.
2026-08-23 12:51:53 +02:00
AuxXxilium
b5cac17652 grub: reduce image size to 3750M
Trims 100M off the total, leaving p3 at 3649M since p1 and p2 stay at
50M each.
2026-08-23 12:49:50 +02:00
AuxXxilium
84d4b63c02 grub: update 2026-08-23 12:04:28 2026-08-23 12:04:28 +02:00
AuxXxilium
824faa4703 grub: strip locales and stock starfield theme from image
The locale prune was commented out in 617af555 and had the wrong path
anyway: grub-install copies from the staged share/grub tree, so removing
share/locale alone left the 42 .mo files (~6 MB, joke locales included)
that actually land in boot/grub/locale.

Also drop GRUB's bundled starfield example theme (~2.8 MB). It is never
referenced: grub.cfg points at ${prefix}/theme/theme.txt, which getTheme
fills from the arc-theme release at build time.
2026-08-23 11:57:44 +02:00
AuxXxilium
c6563f69c0 grub: update 2026-08-23 11:52:19 2026-08-23 11:52:19 +02:00
AuxXxilium
101d6c046b update: remove stale kernels and theme files on update
The cleanup removed bzImage-arc/initrd-arc, names the build stopped
producing when it moved to bzImage-<variant>, so it was a no-op and a
renamed variant could leave a stale image on p3 that grub kept booting.
Remove every shipped bzImage-*/initrd-* instead, skipping initrd-user,
which is generated on the device and has to survive.

Also drop boot/grub/theme first: unzip only overwrites, so files dropped
or renamed between theme releases piled up.
2026-08-23 11:45:26 +02:00
AuxXxilium
28a5410c9a grub: increase image size to 3850M
Grows partition 3, which holds the kernels, modules and the DSM cache,
since p1 and p2 stay fixed at 50M each.
2026-08-23 11:44:59 +02:00
AuxXxilium
1b20437a75 arc-functions: reset model warn file once per menu rebuild
The per-model warn file was only cleared inside the DT branch, so non-DT
models in restricted mode appended to a stale file on every menu rebuild,
duplicating warnings such as the CPU threads notice.
2026-08-23 11:17:29 +02:00
AuxXxilium
6b8b260a8a boot: cleanup
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-22 15:27:47 +02:00
AuxXxilium
c36822dc34 modulelist: revert to old copy logic
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-22 15:20:58 +02:00
AuxXxilium
9a63368334 arc-functions: run hard compatibility checks before warnings
Move the model/platform allowlist and CPU flag checks to the top of the
RESTRICT block so COMPATIBLE is settled before the warning heuristics
run. Also check bmi2 for 7.4 independently of the movbe check, which was
skipped whenever movbe already failed.
2026-08-21 23:42:49 +02:00
AuxXxilium
4999aa7175 kernel: restore full as a separate variant
Bring back the full kernel alongside legacy instead of folding its core
cap into legacy. Both kernel menus list it again, gated on the bzImage
being present as before.

Move the 64 PLTCNT cap in boot.sh back from legacy to full, so legacy
falls through to the platform ccnt again, and drop full from the init.sh
migration case so a stored "full" config stays full rather than being
rewritten to legacy.

Reword both menus to describe the variants by what they offer: legacy is
"hybrid cpu support, better hardware support, optimized" and full is
"same as legacy + 64 thread support".

This reverts the substance of f7f8292a.
2026-08-21 00:19:29 +02:00
AuxXxilium
f7f8292a8f kernel: drop the full variant and cap legacy at 64 cores
The full kernel existed only to raise the core cap above what legacy
supported. legacy now carries that cap directly, so the separate variant
is redundant.

Remove full from both kernel menus, move the 64-core PLTCNT cap in
boot.sh from full to legacy, and migrate stored "full" configs to
"legacy" on init alongside the existing "custom" case -- without that,
zimage-patch.sh would look for a bzImage-*-full.gz that no longer ships
and die on boot.
2026-08-16 13:13:52 +02:00
AuxXxilium
82d6eb7619 grub: drop ieee1275_fb from the BIOS video path
ieee1275_fb is the Open Firmware framebuffer driver, built only for
sparc64-ieee1275 and powerpc-ieee1275 targets. Our builds target
i386-pc, i386-efi and x86_64-efi, so the module was never present and
every legacy-BIOS boot printed "i386-pc/ieee1275_fb.mod not found".

Boot still worked, since load_video returns the status of the last
insmod and vbe succeeds, but the error hit the bare console before
terminal_output switched to gfxterm. The remaining modules are the
correct BIOS set: vbe for hardware and most hypervisors, vga as
fallback, video_bochs and video_cirrus for QEMU/Proxmox adapters.
2026-08-15 21:58:34 +02:00
AuxXxilium
7399afdd39 kernel: lower the full kernel core cap to 64 2026-08-14 18:22:26 +02:00
AuxXxilium
42cc639457 fancontrol: follow hwmon symlinks when probing for PWM
The entries under /sys/class/hwmon are symlinks into /sys/devices, and
find does not descend into symlinks by default. checkPWMSignal() therefore
matched nothing even on hardware with a working controller - an nct6775
board exposing pwm1-pwm7 returned a count of 0, which hid the fan control
menu entry and made boot.sh reset a valid fancontrol=true back to false.

Add -L so find follows the symlinks, and bound the walk with -maxdepth 2.
The attributes sit directly below the hwmonN symlink, while sysfs symlink
cycles (device/wakeup/device/...) would otherwise send find on a long walk
through the device tree - slowest precisely in the no-PWM case that has to
return quickly.
2026-08-13 21:41:23 +02:00
AuxXxilium
7c29249aa3 addons: drop dead fancontrol term from the VM filter
The VM filter in availableAddons() matched fancontrol, but arc-addons has
no addon by that name - it was folded into the sensors addon, which reads
the fancontrol cmdline flag and still carries cleanup for the old addon's
remnants. Since ADDON is a basename under ADDONS_PATH, the term could
never match, so the branch was dead for fancontrol.

cpufreqscaling and ledcontrol are real addons and stay filtered.
2026-08-13 20:25:27 +02:00
AuxXxilium
603ef41de0 fancontrol: gate on PWM signals instead of temp sensors
Fan control was enabled whenever a CPU temperature sensor (coretemp,
k10temp, zenpower) was present, which says nothing about whether a fan
can actually be driven. Systems with no PWM controller still got the
bare fancontrol flag appended to the kernel cmdline.

Add checkPWMSignal(), which accepts either a pwm[0-9] control channel or
a fan[0-9]_input tach signal. The loader only autoloads modules by
modalias, so ISA/superio hwmon chips are never bound at detection time;
probe sysfs first and fall back to loading the superio drivers so boards
that do have fan control are not missed.

Gate all three call sites on it: the config/automated decision, the menu
entry, and boot.sh. The boot.sh check also rewrites a stale true back to
false, so configs written by the old sensor-only logic self-heal instead
of re-arming the flag on every boot.
2026-08-13 20:11:05 +02:00
AuxXxilium
05ed4b35f3 boot.sh: set cpufreq.default_governor on 5.x kernels
cpufreq_init_policy() picks a policy's governor by name: last_governor,
then the cpufreq.default_governor= module parameter, then the
compiled-in default. Passing the selected governor there sets it when
each policy is created, before userspace runs at all.

That removes the dependency on the cpufreqscaling addon winning a race
at multi-user.target, where the cpufreq policies may not exist yet.

Gated on 5.x: the parameter only exists on 5.9 and later, so 4.x keeps
relying on the addon reading the existing governor= entry, which is left
in place for both.
2026-08-13 01:47:59 +02:00
AuxXxilium
0005cf4804 webui: recover from a stale thttpd pidfile
thttpd does not remove its pidfile when it dies, so a crash left the
file behind pointing at a dead pid. The boot guard only tested that the
file existed, concluded the server was up and skipped the restart, so
nothing was listening while the loader carried on and reported an ip.
That is the connection refused on a running system. Test the pid with
kill -0 instead and clear the file before restarting.

The shipped init script had no monitor loop to catch this later, and its
stop() bailed out with FAIL when the pidfile was missing, so restart
could not recover a thttpd that was running without one. Fall back to
killall in that case, and never signal a recorded pid that is no longer
alive since the number may have been recycled.

loaderPorts compared the new port against HTTPPORT, which arc.conf had
already been rewritten to hold, so the restart was skipped on a real
change. Capture the running port before the rewrite.
2026-08-11 20:59:22 +02:00
AuxXxilium
2c7bd64d76 boot: drop the maxcpus cmdline entry, warn instead
CONFIG_NR_CPUS is compiled into the kernel image, so it refuses any CPU
past its ceiling during SMP bring-up on its own. maxcpus only moved
where that cap happened and did not change the resulting online count,
so ccnt now just drives a warning.

Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-11 20:26:02 +02:00
AuxXxilium
f8a62460fc boot: scope the 128 thread ceiling to the full kernel
The cap raised PLTCNT to 128 for every non-official kernel, but only
full is built for that many threads. legacy and upstreamed were left
effectively uncapped, so they now fall back to the platform ccnt.

Guard the ceiling against a missing or non-numeric ccnt as well; the
value went straight into -gt, which errors on anything but an integer.
2026-08-11 20:25:13 +02:00
AuxXxilium
3748a47c12 kernel: detect the full variant and describe each option
The kernel menus only probed for -legacy and -upstreamed, so a -full
image on the loader was never offered. Probe for it too, and replace the
bare option labels with what each kernel actually is.

Three gates tested for legacy or upstreamed by name to decide whether to
read from CUSTOM_PATH. Selecting full would have fallen through to the
official branch and booted the stock kernel with stock modules. Test for
official instead, as boot.sh already does, so further variants need no
change here.

Widen both menus to auto width; the descriptions do not fit in 50 cols.
2026-08-11 20:12:35 +02:00
AuxXxilium
5ba316d8c7 notify: reset buildstatus only on real changes
Opening the notification menu, pressing Test or cancelling out no longer
invalidates the build. The webhook/discord flags and the webhook url are
snapshotted on entry and compared on exit, so a rebuild is only forced
when a value that gets baked into the ramdisk actually changed.

registerAccessToken keeps forcing a rebuild, but via resetBuildstatus so
it no longer writes the build flag into CONFDONE.
2026-08-10 21:10:31 +02:00
AuxXxilium
62172ed2ef modules: respect the update folder of the modules tgz
The modules tgz of the igpu platforms ships a backported i915 stack in
an update/ folder, 11 modules for epyc7002 and geminilakenk. Five of
them (drm, ttm, drm_kms_helper, intel-gtt,
drm_panel_orientation_quirks) also exist in the root folder as an older
build, update/ overrides those the same way the kernel does.

getdepends only looked at the root folder, so "getdepends i915"
returned nothing but i915 itself: i915.ko does not exist in root, and
even a prefixed name broke the recursion because dmabuf, drm_buddy,
drm_display_helper and i915-compat are update/ only. Deps that do exist
in both were read from the stale root copy. As a result the i915
deselect menu left all dependencies selected.

Add MODULE_DIRS as the single search order plus resolveModule() and
moduleName() to resolve a module to its file and to its list name.
getdepends now follows dependencies across both folders, returns folder
prefixed names and guards against cycles. addToModules replaces a
module in place so an update/ ko keeps precedence, delToModules drops
every copy so the older root module does not come back.

Match module names as exact tokens in installModules and in the i915
deselect, "grep -w" treats the slash as a word boundary and let a
selected update/drm pull in the older root drm as well.

Also fix the packagModules typo in addToModules and delToModules, both
never repacked the tgz.
2026-08-08 21:23:15 +02:00
AuxXxilium
1b819267a1 sysinfo: detect gpus in all display subclasses
lspci -d ::300 only matches the VGA subclass (0300), so display
devices reporting 0301 (XGA), 0302 (3D controller) or 0380 (other)
were missing from sysinfo. This hid NVIDIA compute cards and the
discrete GPU of hybrid setups.

Add getPciClass() to match a PCI class prefix via
/sys/bus/pci/devices/*/class, so 03 covers every display subclass,
and getIgpuId() to find the first Intel display device regardless of
subclass. Use them for the TUI and web GPU lists as well as the
iGPU/i915 detection for the model feature matrix and default addons.
2026-08-08 21:02:53 +02:00
AuxXxilium
d018171c7b boot: reduce and fix boot cmdline entries
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-08 13:21:46 +02:00
AuxXxilium
d4c6b89bee tui: reword custom kernel prompt as an available option
The Linux 5.x / DSM 7.3+ dialog framed the custom kernel as a fix for
boot issues. Present it as an available choice instead and retitle the
dialog from "DSM 7.3+ Warning" to "Custom Kernel".
2026-08-05 21:38:19 +02:00
AuxXxilium
bf4def9f59 sysinfo: show vendor:device ids for nics and controllers
Add getPciId/getNicId helpers and append the vendor:device id to the
NIC driver line and to every controller entry (SATA, RAID, HBA, SCSI,
USB, MMC, NVME) in both the TUI and the WebUI sysinfo output.

getNicId resolves ids from sysfs, falling back to the parent node for
USB nics where idVendor/idProduct live one level up.
2026-08-05 20:43:55 +02:00
AuxXxilium
761d6cc3e2 modules: always take firmware from the modules package
The legacy/upstreamed branch extracted ${CUSTOM_PATH}/firmware.tgz, but
arc-custom only ships kernel-flavor artifacts (bzImage-*-legacy.gz,
bzImage-*-upstreamed.gz, modules-*-${KERNEL}.tgz) -- it has never
contained a firmware.tgz. That path read a nonexistent file, and because
the $? check below tested the if/else rather than tar, the failure was
silent.

Firmware blobs are kernel-flavor independent, so one package serves all
flavors. Modules stay split per flavor in unpackModules/packModules,
matching the gate in updateModules that already requires firmware.tgz
under ${MODULES_PATH}.

Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-05 20:43:55 +02:00
AuxXxilium
dcc170eac8 modulelist: add missing sensors, drop unused entries
dme1737, lm95245 and w83781d ship in arc-modules on all 45 platforms
and are already modprobed by the eudev addon, but were never listed
here - so on official kernels they were loaded during install and then
lost, since installModules only copies what this file names.

Also drops acpi_cpufreq.ko (the file is built as acpi-cpufreq.ko, so
the entry never matched anything), the cpufreq governors, dca and
rfkill, and adds button.ko.

Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-05 20:43:55 +02:00
AuxXxilium
f38a3aaae2 workflow: point release notes link at view.php renderer
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-05 20:43:55 +02:00
AuxXxilium
90ea97c564 webui: rewrite auth.cgi in bash to fix thttpd crash on login
auth.cgi was the only Python CGI in the image and failed at import
time on cgi, cgitb and crypt, all removed from the stdlib in Python
3.13 by PEP 594. The import sits at the top of the file, so the script
died before emitting any headers and thttpd received a zero-byte CGI
response, killing the connection. A wrong password was simply the
path that made this visible; the verify path hit the same wall but was
swallowed by a catch in app.js.

Rewrite in bash to match the other seven CGIs. The JSON contract
consumed by app.js is unchanged, so no frontend changes are needed.

- Verify passwords with openssl passwd using the id and salt parsed
  from the stored hash, the same primitive loaderPassword uses to
  write it, so the two cannot drift.
- Always emit a valid header block via an ERR trap, so the webserver
  never sees an empty response.
- Generate tokens with openssl rand -hex 32.

Also fixes a path traversal: the previous version joined the
attacker-controlled token straight into a filesystem path, so
action=logout&token=../../../etc/shadow reached os.remove() as root.
Tokens are now rejected unless they are pure lowercase hex before any
rm. Locked accounts of the form !$6$... are now detected too; the old
membership test against ['*', '!', '!!'] missed them.
2026-08-05 20:43:55 +02:00
AuxXxilium
d1abecf01a boot/netfix: cap CPU threads per kernel, add netfix "force" mode
- boot.sh: cap kernel-visible CPU threads via maxcpus= cmdline when the
  detected thread count exceeds what the platform (or custom/legacy/
  upstreamed kernel, capped at 128) supports.
- netfix now cycles true -> force -> false; static IP network.* cmdline
  values are only injected when netfix is set to "force", while the MAC
  remap and driver unload fixes apply for both true and force.

Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-05 20:43:55 +02:00
AuxXxilium
d4c301f56a boot: add sanity check
Signed-off-by: AuxXxilium <info@auxxxilium.tech>
2026-08-05 20:43:55 +02:00
AuxXxilium
b1d909b001 kernel/fancontrol/netfix/automated: fix marker path, live-patch PAT lookup, and menu toggles
- automated boot marker: write/clean on p1 (grub reads /automated from p1) instead of p3
- livepatch: rebuild PAT url/hash lookup from stored config instead of unset $resp, fall back to existing values when no match
- arcVersion: offer custom kernel selection on DSM 7.3+ warning for 5.x platforms (now includes r1000nk/v1000nk), reset kernel to official on version change
- fancontrol: gate on physical MEV first, require detected sensor before offering/enabling
- ledcontrol: skip UGREEN *GT* models
- netfix: convert submenu to a direct toggle, matching other arc.sh options
2026-08-05 20:43:55 +02:00
AuxXxilium
ac9213a0c3 kernel: only offer legacy/upstreamed if their bzImage exists
The Kernel dialog in arc.sh now checks CUSTOM_PATH for a matching
bzImage-<platform>-<kpre->-<kver>-<variant>.gz before listing
legacy/upstreamed, so users can't pick a variant that has no build
for the current platform/DSM version. official/legacy labels show
the platform's real kver instead of a hardcoded version.
2026-08-05 20:43:55 +02:00