mirror of
https://github.com/theupriser/steamify-cachyos.git
synced 2026-10-03 17:41:58 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
986b3c8c07 | ||
|
|
afc05b0b23 | ||
|
|
b0553aecf7 | ||
|
|
69a420b8aa | ||
|
|
1c34a97598 | ||
|
|
be874b8594 | ||
|
|
f01aa93d0e | ||
|
|
852205317a | ||
|
|
77b94c29a2 | ||
|
|
c0014ee623 | ||
|
|
d39731a8b9 | ||
|
|
99a95abf1f | ||
|
|
429e840a9f | ||
|
|
45a8757f58 | ||
|
|
54fc9e362b | ||
|
|
b70c9d614f | ||
|
|
40c9ee638b | ||
|
|
2f9b2a54e1 |
No files matched your search
@@ -1,16 +1,16 @@
|
||||
#!/bin/bash
|
||||
# Build a single-file version of the wizard for `curl | bash` use:
|
||||
# .github/tools/bundle.sh [output] (default: dist/setup-gamescope-boot.sh)
|
||||
# .github/tools/bundle.sh [output] (default: dist/steamify.sh)
|
||||
#
|
||||
# Inlines lib/*.sh in the order setup-gamescope-boot.sh sources them and
|
||||
# Inlines lib/*.sh in the order steamify.sh sources them and
|
||||
# wraps the entry point's body in main(), so bash has read the whole file
|
||||
# before anything runs. That lets the bundle reattach stdin to the terminal
|
||||
# when it was piped in by curl, so the interactive menu still works.
|
||||
set -euo pipefail
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
out="${1:-dist/setup-gamescope-boot.sh}"
|
||||
entry=setup-gamescope-boot.sh
|
||||
out="${1:-dist/steamify.sh}"
|
||||
entry=steamify.sh
|
||||
mkdir -p "$(dirname "$out")"
|
||||
|
||||
# Library order, taken from the entry point's source loop.
|
||||
@@ -23,15 +23,15 @@ version="v$(grep -oP '^VERSION=\K.*' "$entry"), $(git describe --always --dirty
|
||||
# Header comment and `set` line of the entry point, up to the source loop.
|
||||
sed -n '1,/^SCRIPT_DIR=/p' "$entry" | sed '$d'
|
||||
echo "# Single-file build ($version), generated by .github/tools/bundle.sh - edit the"
|
||||
echo "# sources in the repository instead: https://github.com/theupriser/cachyos-gamescope-boot"
|
||||
echo "# sources in the repository instead: https://github.com/theupriser/steamify-cachyos"
|
||||
echo
|
||||
for lib in $libs; do
|
||||
echo "# ----- lib/$lib.sh -----"
|
||||
# Drop each module's shebang and its "Sourced by ..." boilerplate.
|
||||
sed -e '1{/^#!/d}' -e '/^# Sourced by setup-gamescope-boot.sh/d' "lib/$lib.sh"
|
||||
sed -e '1{/^#!/d}' -e '/^# Sourced by steamify.sh/d' "lib/$lib.sh"
|
||||
echo
|
||||
done
|
||||
echo "# ----- setup-gamescope-boot.sh -----"
|
||||
echo "# ----- steamify.sh -----"
|
||||
echo "main() {"
|
||||
# Everything after the source loop is the entry point's body.
|
||||
sed -n '/^for lib in /,$p' "$entry" | sed '1,/^done$/d' | sed 's/^/ /; s/^ $//'
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
# Builds the single-file wizard (.github/tools/bundle.sh) and publishes it as a
|
||||
# release per version: tag v$VERSION (VERSION in setup-gamescope-boot.sh),
|
||||
# release per version: tag v$VERSION (VERSION in steamify.sh),
|
||||
# with that version's CHANGELOG.md section as notes. A released version is
|
||||
# never overwritten; the newest one is marked latest, and the "latest" tag and
|
||||
# release are moved to it, so both of these always get the newest version:
|
||||
# curl -fsSL https://github.com/theupriser/cachyos-gamescope-boot/releases/latest/download/setup-gamescope-boot.sh | bash
|
||||
# curl -fsSL https://github.com/theupriser/cachyos-gamescope-boot/releases/download/latest/setup-gamescope-boot.sh | bash
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify.sh | bash
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/download/latest/steamify.sh | bash
|
||||
# The bundle is also published as setup-gamescope-boot.sh, its name before
|
||||
# 0.9.0, so older install commands keep working.
|
||||
# Pull requests only build and check it, and warn when VERSION is already released.
|
||||
name: Single-file build
|
||||
|
||||
@@ -26,29 +28,32 @@ jobs:
|
||||
fetch-depth: 0 # for the version in the bundle's header
|
||||
|
||||
- name: Build
|
||||
run: .github/tools/bundle.sh dist/setup-gamescope-boot.sh
|
||||
run: |
|
||||
.github/tools/bundle.sh dist/steamify.sh
|
||||
# Old name (before 0.9.0), for older install commands and links.
|
||||
cp dist/steamify.sh dist/setup-gamescope-boot.sh
|
||||
|
||||
- name: Check
|
||||
run: |
|
||||
bash -n dist/setup-gamescope-boot.sh
|
||||
bash -n dist/steamify.sh
|
||||
# SC2034/SC2154: variables used across the inlined modules.
|
||||
shellcheck -S warning -e SC2034,SC2154 dist/setup-gamescope-boot.sh
|
||||
shellcheck -S warning -e SC2034,SC2154 dist/steamify.sh
|
||||
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: setup-gamescope-boot
|
||||
path: dist/setup-gamescope-boot.sh
|
||||
name: steamify
|
||||
path: dist/steamify.sh
|
||||
|
||||
- name: Version
|
||||
id: version
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
version="$(grep -oP '^VERSION=\K.*' setup-gamescope-boot.sh)"
|
||||
version="$(grep -oP '^VERSION=\K.*' steamify.sh)"
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
if gh release view "v$version" >/dev/null 2>&1; then
|
||||
echo "released=true" >> "$GITHUB_OUTPUT"
|
||||
echo "::warning::v$version is already released and won't be overwritten. Bump VERSION in setup-gamescope-boot.sh and add a CHANGELOG.md section to release this."
|
||||
echo "::warning::v$version is already released and won't be overwritten. Bump VERSION in steamify.sh and add a CHANGELOG.md section to release this."
|
||||
else
|
||||
echo "released=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
@@ -68,12 +73,12 @@ jobs:
|
||||
notes="Single-file build of v$VERSION ($(git describe --always), $(git log -1 --format=%cs)).
|
||||
Run the newest version with:
|
||||
|
||||
curl -fsSL https://github.com/${{ github.repository }}/releases/latest/download/setup-gamescope-boot.sh | bash
|
||||
curl -fsSL https://github.com/${{ github.repository }}/releases/latest/download/steamify.sh | bash
|
||||
|
||||
## Changes in v$VERSION
|
||||
$changes"
|
||||
gh release create "v$VERSION" dist/setup-gamescope-boot.sh \
|
||||
--target "$GITHUB_SHA" --title "v$VERSION" --notes "$notes" --latest
|
||||
gh release create "v$VERSION" dist/steamify.sh dist/setup-gamescope-boot.sh assets/steam-gaming-settings.svg \
|
||||
--target "$GITHUB_SHA" --title "Steamify CachyOS v$VERSION" --notes "$notes" --latest
|
||||
|
||||
# "latest" follows the newest version tag, for the older install URL
|
||||
# (.../releases/download/latest/...). Only moved when a new version
|
||||
@@ -81,8 +86,8 @@ jobs:
|
||||
git tag -f latest "$GITHUB_SHA" && git push -f origin latest
|
||||
latest_notes="Always the newest version, currently v$VERSION (see its release for the changes)."
|
||||
if gh release view latest >/dev/null 2>&1; then
|
||||
gh release edit latest --title "Latest (v$VERSION)" --notes "$latest_notes" --latest=false
|
||||
gh release edit latest --title "Steamify CachyOS - latest (v$VERSION)" --notes "$latest_notes" --latest=false
|
||||
else
|
||||
gh release create latest --title "Latest (v$VERSION)" --notes "$latest_notes" --latest=false
|
||||
gh release create latest --title "Steamify CachyOS - latest (v$VERSION)" --notes "$latest_notes" --latest=false
|
||||
fi
|
||||
gh release upload latest dist/setup-gamescope-boot.sh --clobber
|
||||
gh release upload latest dist/steamify.sh dist/setup-gamescope-boot.sh assets/steam-gaming-settings.svg --clobber
|
||||
@@ -5,14 +5,14 @@ for what the script does from a user's point of view.
|
||||
|
||||
## Project overview
|
||||
|
||||
A bash wizard that makes CachyOS (KDE Plasma 6 + `plasma-login-manager`)
|
||||
**Steamify CachyOS**: a bash wizard that makes CachyOS (KDE Plasma 6 + `plasma-login-manager`)
|
||||
boot into a SteamOS-style gamescope session, with working switching between
|
||||
gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
(DMI `Valve`/`Fremont`) running CachyOS Desktop edition.
|
||||
|
||||
## Layout
|
||||
|
||||
- `setup-gamescope-boot.sh` - the only entry point. Pre-flight checks,
|
||||
- `steamify.sh` - the only entry point. Pre-flight checks,
|
||||
sources `lib/*.sh`, runs the menu and applies the plan. No component
|
||||
logic here.
|
||||
- `lib/*.sh` - one file per responsibility, each defining functions only
|
||||
@@ -59,7 +59,7 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
- Comments explain *why* (the CachyOS/Plasma quirk being worked around),
|
||||
not what the next line does.
|
||||
|
||||
- **Versioning and releases.** SemVer in `VERSION` (`setup-gamescope-boot.sh`,
|
||||
- **Versioning and releases.** SemVer in `VERSION` (`steamify.sh`,
|
||||
shown in the menu header and the bundle header).
|
||||
- Every commit gets an entry in `CHANGELOG.md` under its version (short hash
|
||||
+ subject; a commit can't contain its own hash, so fill it in with the
|
||||
@@ -70,7 +70,7 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
changelog section) and marks it latest. An existing version is never
|
||||
overwritten: without a bump nothing is released, and pull requests show
|
||||
a warning.
|
||||
- Users install through `releases/latest/download/setup-gamescope-boot.sh`
|
||||
- Users install through `releases/latest/download/steamify.sh`
|
||||
(GitHub's newest release). The `latest` tag and release follow the newest
|
||||
version tag too (moved, asset replaced, when a new version is released),
|
||||
so the older URL `releases/download/latest/...` keeps working.
|
||||
@@ -132,16 +132,48 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
and `ensure-kernel-headers.service` installs missing ones at boot (a
|
||||
pacman hook can't run pacman), which triggers DKMS's install hook. The module creates
|
||||
`/sys/class/leds/valve-leds*`.
|
||||
- `bios` is an *action* (`ACTIONS` in `lib/menu.sh`), not an on/off
|
||||
component: never preselected (not even on a first run), never re-applied
|
||||
by `a`, not listed in the state overview, and `bios_status` is always off.
|
||||
Only selectable when Valve's version differs from the installed one
|
||||
(`component_selectable`, greyed out otherwise). Download, SHA-256 and the
|
||||
fwupd device check (`get-details --json`: no `UpdateError`) come before the
|
||||
warnings. The warning box uses `█` for its frame: Konsole draws a long
|
||||
coloured row of `#` narrower, so the right edge wouldn't line up.
|
||||
Keep both confirmations (y/N, then typing `UPDATE`) and the warnings; the
|
||||
firmware comes from the newest `holo-X.Y` repo (`.files` db names the
|
||||
`.cab`, `.db` gives the SHA-256), and fwupd itself refuses non-Fremont
|
||||
hardware. In the VM, test it with `WIZARD_BIOS_DRY_RUN=1` (skips only the
|
||||
device check, never flashes) and a faked version (dev-env
|
||||
`BIOS_VERSION=F7F0107 ./run.sh --fremont`).
|
||||
- The entry point loops: menu, run, "back to the menu" (or `[m]`/`[r]` when a
|
||||
restart is needed), until `q`; the restart question is asked once at the
|
||||
end. Scripted input that runs out ends the loop like `q`.
|
||||
- Steamify shortcut (`launcher`): the icon runs `curl | bash` of
|
||||
`releases/latest/download/steamify.sh` in Konsole, so it's
|
||||
always the newest release. Its icon, `assets/steam-gaming-settings.svg`
|
||||
(Valve's GPL-2.0 return icon with a gear), is a release asset too, and is
|
||||
downloaded from there (Steam's icon if that fails). Desktop files are
|
||||
written with their mode already set (`install_executable`): Plasma opens a
|
||||
desktop icon it first saw non-executable in an editor.
|
||||
The start script closes its window after a 10-second countdown on success
|
||||
and waits for Enter after an error; it uses `pipefail`, or a failed
|
||||
download would run an empty script and count as success.
|
||||
- `Relogin=true` means a gamescope that fails to start is relaunched in a
|
||||
tight loop; keep that in mind when changing session handling.
|
||||
|
||||
## Checking changes
|
||||
|
||||
The bundle puts every module in one file, so shellcheck sees all their
|
||||
`local` variables together: don't reuse a name another module uses as an
|
||||
array (e.g. `g` in `lib/state.sh`), or CI's shellcheck on the bundle fails.
|
||||
|
||||
|
||||
There is no test suite. At minimum:
|
||||
|
||||
```bash
|
||||
for f in setup-gamescope-boot.sh lib/*.sh; do bash -n "$f"; done
|
||||
shellcheck -S warning setup-gamescope-boot.sh lib/*.sh # if available
|
||||
for f in steamify.sh lib/*.sh; do bash -n "$f"; done
|
||||
shellcheck -S warning steamify.sh lib/*.sh # if available
|
||||
```
|
||||
|
||||
Behaviour is verified in a CachyOS QEMU/KVM test VM. The VM scripts and a
|
||||
@@ -150,5 +182,5 @@ the wizard with scripted menu input such as `printf '2\n\ny\nn\n'`, the
|
||||
per-component checks; when stdin is not a terminal the menu falls back to a
|
||||
numbered prompt, which is what scripted runs use, reboot checks, the full test matrix, `--fremont` to
|
||||
fake Steam Machine hardware) live in
|
||||
[cachyos-gamescope-boot-dev-env](https://github.com/theupriser/cachyos-gamescope-boot-dev-env).
|
||||
[steamify-cachyos-dev](https://github.com/theupriser/steamify-cachyos-dev).
|
||||
Gamescope itself and the real LED bar can only be verified on hardware.
|
||||
+73
-3
@@ -2,10 +2,80 @@
|
||||
|
||||
All notable changes, per version and per commit. Versions follow
|
||||
[Semantic Versioning](https://semver.org/); the current one is `VERSION` in
|
||||
`setup-gamescope-boot.sh`. Versions before 0.7.0 were numbered afterwards,
|
||||
`steamify.sh`. Versions before 0.7.0 were numbered afterwards,
|
||||
one per merged pull request.
|
||||
|
||||
## 0.7.0 - 2026-09-24
|
||||
## 0.9.0 - 2026-09-24
|
||||
|
||||
The wizard is now called **Steamify CachyOS**, and can put a shortcut to
|
||||
itself on the desktop.
|
||||
|
||||
- `f01aa93` **feat: Wizard shortcut on the desktop and in the launcher**
|
||||
- New menu item: a desktop icon and app launcher entry
|
||||
that open the newest release of the wizard in Konsole (`curl | bash`).
|
||||
- Its icon: Valve's Return to Gaming Mode icon with a gear instead of the
|
||||
arrow (`assets/steam-gaming-settings.svg`), published with every release
|
||||
and downloaded from there.
|
||||
- Desktop files are written already executable, so Plasma runs them instead
|
||||
of opening them in an editor.
|
||||
- `be874b8` **feat: Rename to Steamify CachyOS**
|
||||
- Menu header, the shortcut ("Steamify CachyOS", menu item "Steamify
|
||||
shortcut"), release titles, README and AGENTS.md.
|
||||
- `1c34a97` **chore: Repository renamed to steamify-cachyos**
|
||||
- All URLs point to `github.com/theupriser/steamify-cachyos` (the old ones
|
||||
redirect). The script keeps its name, `setup-gamescope-boot.sh`, so the
|
||||
old download URL keeps working; internal names such as
|
||||
`~/.local/state/cachyos-gamescope-boot` stay, so existing installs can
|
||||
still be turned off.
|
||||
- `69a420b` **feat: The script is now steamify.sh**
|
||||
- `setup-gamescope-boot.sh` is renamed to `steamify.sh`; releases publish the
|
||||
bundle under both names, so `.../download/setup-gamescope-boot.sh` keeps
|
||||
working. The Steamify shortcut runs `steamify.sh`.
|
||||
- `b0553ae` **docs: Shorter README intro**
|
||||
- **feat: The shortcut's window closes itself after a countdown**
|
||||
- After the wizard ends, a 10-second countdown closes the Konsole window
|
||||
(Enter closes it right away); after an error it stays open until Enter.
|
||||
- A failed download now counts as an error (`pipefail`) instead of running
|
||||
an empty script.
|
||||
|
||||
## 0.8.0 - 2026-09-24 (#8)
|
||||
|
||||
An opt-in BIOS update for the Steam Machine, and a menu that comes back after
|
||||
every run.
|
||||
|
||||
- `2f9b2a5` **feat: Opt-in BIOS update for the Steam Machine**
|
||||
- New menu item (Steam Machine only, never ticked by default) showing the
|
||||
current BIOS version and the newest from Valve's `fremont-hw-support`.
|
||||
- Two large warnings and two confirmations (y/N, then typing `UPDATE`),
|
||||
checksum-verified download, installed with fwupd; the wizard then offers
|
||||
the restart that writes it, with a warning to keep the power on.
|
||||
- `40c9ee6` **fix: BIOS update only when newer, device check first, aligned warnings**
|
||||
- The item is greyed out and can't be ticked unless Valve has a newer BIOS.
|
||||
- Before any warning: SHA-256 of Valve's package, then fwupd confirms the
|
||||
firmware fits this machine's hardware; otherwise it stops.
|
||||
- Warning box drawn with a solid red frame whose edges line up, and the
|
||||
menu's "Now" column aligned.
|
||||
- `b70c9d6` **fix: shellcheck in the bundle, and the docs for the BIOS checks**
|
||||
- A variable name in `lib/bios.sh` clashed with `lib/state.sh` in the bundle
|
||||
(CI's shellcheck would fail); README, AGENTS.md and this changelog updated.
|
||||
- `54fc9e3` **feat: Menu comes back after each run, BIOS dry run, version 0.8.0**
|
||||
- After a run the menu returns with the new state; quit with `q`. When
|
||||
something needs a restart, choose between back to the menu (`m`) and
|
||||
restart now (`r`); quitting asks once more.
|
||||
- A staged BIOS update greys the item out until the restart.
|
||||
- `WIZARD_BIOS_DRY_RUN=1` walks through the whole BIOS update (download,
|
||||
checksum, both warnings) but only prints the install and never flashes.
|
||||
- README: the menu loop and the BIOS update step by step.
|
||||
- `45a8757` **fix: BIOS dry run also walks through the restart choices**
|
||||
- A dry run counts as staged, so `[m]`/`[r]` and the restart question on `q`
|
||||
show up; in dry-run mode restarting only prints what it would do.
|
||||
- `429e840` **fix: Shorter BIOS labels so the menu fits 80 columns**
|
||||
- "now F7F0107, newest F7F0108 (own risk)", "F7F0108 waits for a restart",
|
||||
"F7F0107 is up to date"; shorter dry-run line.
|
||||
- `99a95ab` **fix: Kernel legend only mentions the LEDs on a Steam Machine**
|
||||
- `c0014ee` **docs: Last commit hash in the changelog; 0.7.0 was released on its own (#6, #7)**
|
||||
|
||||
## 0.7.0 - 2026-09-24 (#6, #7)
|
||||
|
||||
The SteamOS theme comes from CachyOS's `cachyos-vapor` package, applied with
|
||||
Vapor's own desktop layout, and gains the SteamOS desktop extras. The Steam
|
||||
@@ -52,7 +122,7 @@ Machine LED driver works on every installed kernel and survives kernel updates.
|
||||
- Install with `.../releases/latest/download/setup-gamescope-boot.sh`, which
|
||||
always points to the newest release.
|
||||
- `1604ed1` **docs: Versioning and release rules in AGENTS.md**
|
||||
- **ci: The latest tag follows the newest version tag**
|
||||
- `6afef78` **ci: The latest tag follows the newest version tag**
|
||||
- When a new version is released, the `latest` tag and release move to it
|
||||
(bundle replaced), so the older `.../releases/download/latest/...` URL
|
||||
also always gives the newest version.
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
# CachyOS Gamescope Boot Wizard
|
||||
# Steamify CachyOS
|
||||
|
||||
Turn a CachyOS desktop PC into a SteamOS-style console: it boots straight
|
||||
into Steam's Big Picture (gamescope), and you can switch to the KDE Plasma
|
||||
desktop and back whenever you like - just like on a Steam Deck or Valve's
|
||||
Steam Machine.
|
||||
|
||||
Out of the box, CachyOS doesn't quite manage this: the switch to the desktop
|
||||
can hang, and the PC doesn't reliably boot back into gaming mode. This
|
||||
script fixes that and sets everything up for you.
|
||||
|
||||
## What you get
|
||||
|
||||
The wizard is a menu: pick what you want, and it turns each part on or off.
|
||||
@@ -24,9 +20,15 @@ Everything you turn off is put back the way it was.
|
||||
4. **Single user mode** - like SteamOS: never a login or lock screen, no
|
||||
user switching or logging out. Typing a password with a controller is no
|
||||
fun. (Needs 1.)
|
||||
5. **Steam Machine support** - only shown on a Valve Steam Machine: the
|
||||
5. **Steamify shortcut** - a "Steamify CachyOS" icon on the desktop and in
|
||||
the app launcher (the Steam logo with a gear) that opens the newest version
|
||||
of Steamify in Konsole, so you don't need the install command again.
|
||||
6. **Steam Machine support** - only shown on a Valve Steam Machine: the
|
||||
driver for the front LED bar, and the hardware settings in Steam (fan,
|
||||
TV control over HDMI-CEC).
|
||||
7. **Update BIOS** - only on a Steam Machine, opt-in and at your own risk:
|
||||
installs the newest Steam Machine BIOS from Valve (see
|
||||
[BIOS updates](#bios-updates-steam-machine)).
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -38,17 +40,19 @@ Everything you turn off is put back the way it was.
|
||||
Open **Konsole** on your Plasma desktop and run:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://github.com/theupriser/cachyos-gamescope-boot/releases/latest/download/setup-gamescope-boot.sh | bash
|
||||
curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify.sh | bash
|
||||
```
|
||||
|
||||
That downloads and runs the latest single-file version, and works in any
|
||||
(Before 0.9.0 the script was called `setup-gamescope-boot.sh`; that name
|
||||
still works in the download URL.) That downloads and runs the latest
|
||||
single-file version, and works in any
|
||||
shell, including fish (CachyOS's default). Prefer to keep a copy, or to look
|
||||
at the script first? Clone the repository instead:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/theupriser/cachyos-gamescope-boot.git
|
||||
cd cachyos-gamescope-boot
|
||||
./setup-gamescope-boot.sh
|
||||
git clone https://github.com/theupriser/steamify-cachyos.git
|
||||
cd steamify-cachyos
|
||||
./steamify.sh
|
||||
```
|
||||
|
||||
Run it as yourself, not as root. You'll see a checklist:
|
||||
@@ -74,6 +78,10 @@ it's loaded right now, so a kernel update is easy to check. The wizard then
|
||||
shows what it will change, asks your password once, and at the end offers
|
||||
to restart (needed for changes to how the PC starts).
|
||||
|
||||
After each run the menu comes back with the new state, so you can change more
|
||||
in one go; quit with **q**. When something needs a restart, you choose
|
||||
between going back to the menu and restarting now; quitting asks once more.
|
||||
|
||||
Run it again whenever you like - to change your choices, to turn things off
|
||||
again, or after a CachyOS update (press `a` in the menu to re-apply
|
||||
everything that's on).
|
||||
@@ -283,17 +291,41 @@ cat /var/lib/dkms/leds-valve-dkms/0.1/build/make.log
|
||||
journalctl --user -b | grep -i led
|
||||
```
|
||||
|
||||
**BIOS updates** are not part of the wizard. Valve ships the Steam Machine
|
||||
BIOS as `F7F0108.cab` in its `fremont-hw-support` package for fwupd. To
|
||||
install it by hand (keep the machine on mains power and don't interrupt it):
|
||||
### BIOS updates (Steam Machine)
|
||||
|
||||
The **Update BIOS** item is only shown on a Steam Machine and is never ticked
|
||||
by default. It shows the BIOS version you have now and the newest one Valve
|
||||
ships (the `.cab` file in its `fremont-hw-support` package, looked up on
|
||||
Valve's SteamOS mirror):
|
||||
|
||||
```bash
|
||||
sudo dmidecode -s bios-version # current version
|
||||
sudo pacman -S fwupd
|
||||
curl -LO https://steamdeck-packages.steamos.cloud/archlinux-mirror/holo-3.9/os/x86_64/fremont-hw-support-20260807.1-1-any.pkg.tar.zst
|
||||
mkdir fhw && tar -I zstd -xf fremont-hw-support-*.pkg.tar.zst -C fhw
|
||||
sudo fwupdmgr install fhw/usr/share/fwupd/remotes.d/fremont/firmware/F7F0108.cab
|
||||
```
|
||||
[ ] Update BIOS: now F7F0107, newest F7F0108 (own risk) (opt-in, runs once)
|
||||
```
|
||||
|
||||
It can only be ticked when Valve has a newer BIOS than yours; when you're up
|
||||
to date, when the newest version can't be looked up (offline), or when an
|
||||
update is already waiting for a restart, it's greyed out.
|
||||
|
||||
When you run it, the wizard:
|
||||
|
||||
1. downloads Valve's package and checks its **SHA-256** against Valve's
|
||||
repository, so it's exactly Valve's file;
|
||||
2. asks **fwupd** whether the firmware is for this very machine (fwupd compares
|
||||
the firmware's hardware IDs with the device) and stops if it isn't;
|
||||
3. shows a large red **warning** with the current and the new version, and asks
|
||||
whether you understand the risks (default: no);
|
||||
4. shows the warning **again** and only continues when you type `UPDATE`;
|
||||
5. hands the firmware to fwupd, which writes it during the **next restart**:
|
||||
choose "restart now" or restart later yourself.
|
||||
|
||||
**At your own risk:** a failed or interrupted BIOS update can leave the machine
|
||||
unable to start. Keep it on mains power, and never turn off the power, unplug
|
||||
it or press the power button while it updates, including during the restart;
|
||||
the screen can stay black for several minutes.
|
||||
|
||||
To walk through it without flashing anything, run the wizard with
|
||||
`WIZARD_BIOS_DRY_RUN=1`: it downloads and checks the package and shows both
|
||||
warnings, skips fwupd's device check, and only prints the install command.
|
||||
|
||||
### Manual session control
|
||||
|
||||
@@ -317,7 +349,7 @@ gamescope-session, ...) stay installed.
|
||||
|
||||
| File | Responsibility |
|
||||
|---|---|
|
||||
| `setup-gamescope-boot.sh` | Entry point: checks, menu, apply, summary, restart |
|
||||
| `steamify.sh` | Entry point: checks, menu, apply, summary, restart |
|
||||
| `lib/menu.sh` | The menu: detect, toggle, plan and apply changes |
|
||||
| `lib/state.sh` | Undo journal for KDE settings (`kset`/`krevert`) |
|
||||
| `lib/common.sh` | Output helpers, prompts, backups, plasmashell handling |
|
||||
@@ -328,8 +360,10 @@ gamescope-session, ...) stay installed.
|
||||
| `lib/vapor-theme.sh` | SteamOS theme: installs and switches to `cachyos-vapor` |
|
||||
| `lib/steamos-extras.sh` | SteamOS desktop extras from Valve's package (Add to Steam, Nested Desktop, icon, keyboard rule, KWallet) |
|
||||
| `lib/single-user.sh` | Single user mode: no lock screen, user switching or log out |
|
||||
| `lib/wizard-shortcut.sh` | Steamify shortcut: desktop icon and launcher entry that run the newest release |
|
||||
| `lib/bios.sh` | Update BIOS (Steam Machine, opt-in): current/newest version, double confirmation, fwupd |
|
||||
| `lib/steam-machine.sh` | Steam Machine support: LED driver, LED access, steamos-manager |
|
||||
| `.github/tools/bundle.sh` | Builds the single-file version (`dist/setup-gamescope-boot.sh`) |
|
||||
| `.github/tools/bundle.sh` | Builds the single-file version (`dist/steamify.sh`) |
|
||||
| `.github/workflows/bundle.yml` | Builds and checks it on every push; publishes it on `main` |
|
||||
|
||||
The single-file version is generated: on every push to `main`, GitHub
|
||||
|
||||
@@ -0,0 +1,224 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Icon for the "Steamify CachyOS" shortcut (cachyos-gamescope-boot).
|
||||
Derived from Valve's steam-gaming-return.svg (steamdeck-kde-presets,
|
||||
GPL-2.0): the Return to Gaming Mode arrow replaced by a gear. -->
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 48 48"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="steam-gaming-settings.svg"
|
||||
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="true"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="16.6875"
|
||||
inkscape:cy="16.4375"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1014"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg11">
|
||||
<inkscape:grid
|
||||
id="grid11"
|
||||
units="px"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingx="1"
|
||||
spacingy="1"
|
||||
empcolor="#3f3fff"
|
||||
empopacity="0.25098039"
|
||||
color="#3f3fff"
|
||||
opacity="0.1254902"
|
||||
empspacing="5"
|
||||
enabled="true"
|
||||
visible="true" />
|
||||
</sodipodi:namedview>
|
||||
<defs
|
||||
id="defs4">
|
||||
<linearGradient
|
||||
id="blue-gradient-5">
|
||||
<stop
|
||||
style="stop-color:#054e87;stop-opacity:1"
|
||||
offset="0"
|
||||
id="stop1" />
|
||||
<stop
|
||||
style="stop-color:#1d99f3;stop-opacity:1"
|
||||
offset="1"
|
||||
id="stop2" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="shadow-3">
|
||||
<stop
|
||||
style="stop-color:#31363b;stop-opacity:0.208"
|
||||
offset="0"
|
||||
id="stop3" />
|
||||
<stop
|
||||
style="stop-color:#31363b;stop-opacity:0;"
|
||||
offset="1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
xlink:href="#shadow-3"
|
||||
id="linearGradient4199"
|
||||
x1="21.969"
|
||||
y1="1035.362"
|
||||
x2="35.969"
|
||||
y2="1049.362"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(10,-1018.3622)" />
|
||||
<linearGradient
|
||||
xlink:href="#shadow-3"
|
||||
id="linearGradient4203"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="23"
|
||||
y1="1035.362"
|
||||
x2="36"
|
||||
y2="1048.362"
|
||||
gradientTransform="translate(13,-1021.3622)" />
|
||||
<linearGradient
|
||||
xlink:href="#shadow-3"
|
||||
id="linearGradient4227"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-15.75,-1005.8622)"
|
||||
x1="21.475"
|
||||
y1="1035.158"
|
||||
x2="34.475"
|
||||
y2="1048.158" />
|
||||
<linearGradient
|
||||
xlink:href="#blue-gradient-5"
|
||||
id="linearGradient4351"
|
||||
x1="24"
|
||||
y1="1008.362"
|
||||
x2="24"
|
||||
y2="1048.362"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(0,-1004.3622)" />
|
||||
<linearGradient
|
||||
xlink:href="#shadow-3"
|
||||
id="linearGradient4373"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(5.9783302,-1021.8757)"
|
||||
x1="21.085"
|
||||
y1="1036.975"
|
||||
x2="35.969"
|
||||
y2="1049.362" />
|
||||
<linearGradient
|
||||
xlink:href="#shadow-3"
|
||||
id="linearGradient4377"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-6.3297472,-1009.2141)"
|
||||
x1="21.085"
|
||||
y1="1036.975"
|
||||
x2="35.969"
|
||||
y2="1049.362" />
|
||||
<linearGradient
|
||||
xlink:href="#shadow-3"
|
||||
id="linearGradient4381"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(-2.8703079,-1005.5321)"
|
||||
x1="21.969"
|
||||
y1="1035.362"
|
||||
x2="35.969"
|
||||
y2="1049.362" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#blue-gradient-5"
|
||||
id="linearGradient12"
|
||||
x1="34.848072"
|
||||
y1="2.7402468"
|
||||
x2="35.248451"
|
||||
y2="46.980125"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#shadow-3"
|
||||
id="linearGradient14"
|
||||
x1="34.345119"
|
||||
y1="37.896885"
|
||||
x2="42.498322"
|
||||
y2="45.409893"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#shadow-3"
|
||||
id="linearGradient16"
|
||||
x1="3.5050631"
|
||||
y1="46.96999"
|
||||
x2="3.6629491"
|
||||
y2="50.93874"
|
||||
gradientUnits="userSpaceOnUse" />
|
||||
</defs>
|
||||
<circle
|
||||
style="fill:url(#linearGradient4351);fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
cx="24"
|
||||
cy="23.999861"
|
||||
r="20"
|
||||
id="circle4" />
|
||||
<circle
|
||||
id="path43518"
|
||||
cx="34.995033"
|
||||
cy="34.995033"
|
||||
style="fill:url(#linearGradient12);fill-rule:evenodd;stroke-width:0.999996;fill-opacity:1"
|
||||
r="12" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4203);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 35.923828,13.330078 C 37.206994,14.675942 38,16.493653 38,18.5 c -10e-7,4.142136 -3.357865,7.5 -7.5,7.5 -0.203438,-0.0015 -0.406734,-0.01127 -0.609375,-0.0293 l -5.896484,5.111328 c -0.0083,0.739616 -0.153346,1.471317 -0.427735,2.158203 -1.23712,3.074359 -4.732395,4.563589 -7.80664,3.326172 -0.24293,-0.09775 -0.470788,-0.215212 -0.69336,-0.339844 -0.04331,-0.0244 -0.08621,-0.04875 -0.128906,-0.07422 -0.211403,-0.125374 -0.414371,-0.260582 -0.605469,-0.408203 -0.0063,-0.0049 -0.01326,-0.0088 -0.01953,-0.01367 l -0.01172,0.002 8.19336,8.193359 C 22.994984,43.969391 23.497293,43.994196 24,44 a 20,20 0 0 0 1.310547,-0.04687 c 0.06663,-0.0043 0.132772,-0.01066 0.199219,-0.01563 a 20,20 0 0 0 1.845703,-0.222656 c 0.03199,-0.0054 0.06377,-0.01202 0.0957,-0.01758 a 20,20 0 0 0 1.396484,-0.3125 c 0.240477,-0.05998 0.481808,-0.116947 0.71875,-0.185547 A 20,20 0 0 0 30.7832,42.79492 c 0.221103,-0.07984 0.444706,-0.154851 0.662109,-0.242188 a 20,20 0 0 0 1.148441,-0.51367 C 32.813074,41.93437 33.035177,41.835015 33.25,41.722656 a 20,20 0 0 0 1.03125,-0.591797 c 0.231705,-0.139379 0.46789,-0.271541 0.693359,-0.419921 a 20,20 0 0 0 0.953125,-0.685547 c 0.206289,-0.153802 0.419094,-0.299475 0.619141,-0.460938 a 20,20 0 0 0 0.908203,-0.796875 c 0.190109,-0.173313 0.387023,-0.339092 0.570313,-0.519531 a 20,20 0 0 0 0.833984,-0.892578 c 0.163426,-0.181706 0.335418,-0.355335 0.492187,-0.542969 a 20,20 0 0 0 0.863282,-1.136719 c 0.102363,-0.141895 0.215754,-0.275269 0.314453,-0.419922 a 20,20 0 0 0 3.371094,-9.257812 c 6.3e-5,-6.43e-4 -6.4e-5,-0.0013 0,-0.002 a 20,20 0 0 0 0,-0.0059 A 20,20 0 0 0 44,24 20,20 0 0 0 43.779297,21.185547 Z"
|
||||
id="path6" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4227);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 5.7695312,29.3125 19.363281,43.431641 a 20,20 0 0 0 3.13086,0.49414 l -8.19336,-8.193359 -2.001953,-4.97461 z"
|
||||
id="path9" />
|
||||
<g
|
||||
id="g11">
|
||||
<path
|
||||
d="m 26.586,23.6632 8.104641,-0.4201 1.91027,-6.7552 -5.59099,-4.4419 -6.871493,5.8329 z"
|
||||
style="fill:url(#linearGradient4373);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path4" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4199);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 31.027515,23.9946 35,23 l 1.976562,-2.9766 -4,-4 -4.949047,4.9712 z"
|
||||
id="path5" />
|
||||
<path
|
||||
style="fill:url(#linearGradient4377);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="M 15.316486,35.7061 21.675457,35.065 23.0333,27.5143 16.403747,25.7462 12.603749,30.3195 Z"
|
||||
id="path7" />
|
||||
<path
|
||||
d="m 16.985332,35.8717 3.972485,-0.4165 2.210937,-3.4453 -3.0625,-3.1563 -6.933422,3.9868 z"
|
||||
style="fill:url(#linearGradient4381);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="path8" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="m 30.5,11 c -4.142135,0 -7.499999,3.357864 -7.5,7.5 0.0017,0.201484 0.01143,0.402819 0.0293,0.603516 -1.289636,1.575722 -4.80544,5.546997 -5.113281,5.902343 -2.416761,0.03284 -4.577852,1.51258 -5.482422,3.753907 -1.237432,3.074241 0.2518,6.569519 3.326172,7.80664 3.074245,1.237417 6.56952,-0.251813 7.80664,-3.326172 0.274389,-0.686886 0.419405,-1.418587 0.427735,-2.158203 l 5.896484,-5.111328 C 30.093269,25.98873 30.296562,25.998503 30.5,26 34.642135,26 37.999999,22.642136 38,18.5 37.999999,14.357864 34.642135,11 30.5,11 Z m 0,3 c 2.48528,0 4.499999,2.014718 4.5,4.5 -10e-7,2.485282 -2.01472,4.5 -4.5,4.5 -2.48528,0 -4.499999,-2.014718 -4.5,-4.5 1e-6,-2.485282 2.01472,-4.5 4.5,-4.5 z M 18.046875,27 c 0.496175,0.0058 0.986949,0.103774 1.447266,0.289062 2.049689,0.825003 3.042263,3.155585 2.216797,5.205079 -0.825003,2.049668 -3.155579,3.04224 -5.205079,2.216797 C 14.45617,33.885935 13.463596,31.555353 14.289062,29.505859 14.905127,27.975627 16.397393,26.980525 18.046875,27 Z"
|
||||
id="path10" />
|
||||
<circle
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
cx="30.5"
|
||||
cy="18.4998"
|
||||
id="ellipse10"
|
||||
r="3.5" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 5.0722656,22.564453 A 19,19 0 0 0 5,24 19,19 0 0 0 5.7695312,29.3125 l 11.1113278,4.470703 a 3,3 0 0 0 3.902344,-1.664062 3,3 0 0 0 -1.664062,-3.902344 z"
|
||||
id="path11" />
|
||||
</g>
|
||||
|
||||
|
||||
|
||||
<path id="gear" style="fill:#ffffff;fill-rule:evenodd;stroke:none" d="M 40.440,33.688 L 42.527,33.983 L 42.527,36.007 L 40.440,36.302 L 39.770,37.921 L 41.037,39.606 L 39.606,41.037 L 37.921,39.770 L 36.302,40.440 L 36.007,42.527 L 33.983,42.527 L 33.688,40.440 L 32.069,39.770 L 30.384,41.037 L 28.953,39.606 L 30.220,37.921 L 29.550,36.302 L 27.463,36.007 L 27.463,33.983 L 29.550,33.688 L 30.220,32.069 L 28.953,30.384 L 30.384,28.953 L 32.069,30.220 L 33.688,29.550 L 33.983,27.463 L 36.007,27.463 L 36.302,29.550 L 37.921,30.220 L 39.606,28.953 L 41.037,30.384 L 39.770,32.069 Z M 37.395,34.995 A 2.4,2.4 0 1 0 32.595,34.995 A 2.4,2.4 0 1 0 37.395,34.995 Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 11 KiB |
+203
@@ -0,0 +1,203 @@
|
||||
#!/bin/bash
|
||||
# "Update BIOS" menu item, only on a Steam Machine and always opt-in: flashes
|
||||
# the newest Steam Machine BIOS from Valve's fremont-hw-support package with
|
||||
# fwupd. It's an action, not an on/off component: never preselected, never
|
||||
# re-applied, and there is nothing to turn off afterwards.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
BIOS_REPO_PREFIX=holo
|
||||
# WIZARD_BIOS_DRY_RUN=1 walks through the whole BIOS update (download,
|
||||
# checksum, both warnings) but never flashes: fwupd's device check is
|
||||
# skipped and the install is only printed. For testing, e.g. in a VM.
|
||||
BIOS_DRY_RUN="${WIZARD_BIOS_DRY_RUN:-}"
|
||||
|
||||
bios_available() { detect_valve_fremont; }
|
||||
|
||||
bios_status() { return 1; }
|
||||
|
||||
bios_disable() { return 0; }
|
||||
|
||||
bios_current() {
|
||||
cat /sys/class/dmi/id/bios_version 2>/dev/null || echo unknown
|
||||
}
|
||||
|
||||
bios_lookup_newest() {
|
||||
# Sets BIOS_REPO, BIOS_PKG, BIOS_SHA256 and BIOS_NEWEST (e.g. F7F0108)
|
||||
# from the newest holo-X.Y repository on Valve's mirror: its .files
|
||||
# database names the firmware file, its .db gives the package checksum.
|
||||
# Only once per run, and with short timeouts so an offline machine
|
||||
# doesn't hold up the menu.
|
||||
[[ -n "${BIOS_LOOKED_UP:-}" ]] && return 0
|
||||
BIOS_LOOKED_UP=1; BIOS_NEWEST=""
|
||||
local tmp desc
|
||||
BIOS_REPO="$(curl -fsL --max-time 10 "$VALVE_MIRROR/" | grep -oE "$BIOS_REPO_PREFIX-[0-9]+\.[0-9]+/" | tr -d / | sort -uV | tail -n 1)"
|
||||
[[ -n "$BIOS_REPO" ]] || return 1
|
||||
tmp="$(mktemp -d)"
|
||||
if curl -fsL --max-time 30 "$VALVE_MIRROR/$BIOS_REPO/os/x86_64/$BIOS_REPO.files" -o "$tmp/files" &&
|
||||
curl -fsL --max-time 30 "$VALVE_MIRROR/$BIOS_REPO/os/x86_64/$BIOS_REPO.db" -o "$tmp/db"; then
|
||||
desc="$(tar -tf "$tmp/files" 2>/dev/null | grep -E '^fremont-hw-support-[0-9][^/]*/files$' | head -n 1)"
|
||||
[[ -n "$desc" ]] && BIOS_CAB="$(tar -xOf "$tmp/files" "$desc" | grep -E '^usr/share/fwupd/.*\.cab$' | head -n 1)"
|
||||
desc="${desc%/files}/desc"
|
||||
BIOS_PKG="$(tar -xOf "$tmp/db" "$desc" 2>/dev/null | awk '/^%FILENAME%$/ { getline; print }')"
|
||||
BIOS_SHA256="$(tar -xOf "$tmp/db" "$desc" 2>/dev/null | awk '/^%SHA256SUM%$/ { getline; print }')"
|
||||
[[ -n "${BIOS_CAB:-}" && -n "$BIOS_PKG" && -n "$BIOS_SHA256" ]] && BIOS_NEWEST="$(basename "$BIOS_CAB" .cab)"
|
||||
fi
|
||||
rm -rf "$tmp"
|
||||
[[ -n "$BIOS_NEWEST" ]]
|
||||
}
|
||||
|
||||
bios_selectable() {
|
||||
# Only when Valve has a newer BIOS than the one installed; the menu
|
||||
# greys the item out otherwise (up to date, or newest unknown/offline).
|
||||
[[ -z "${BIOS_NEEDS_RESTART:-}" && -n "${BIOS_NEWEST:-}" && "$BIOS_NEWEST" != "$(bios_current)" ]]
|
||||
}
|
||||
|
||||
bios_label() {
|
||||
# Menu label with the current and the newest version; kept short so the
|
||||
# row (with "(not available)" when greyed out) fits 80 columns.
|
||||
local current
|
||||
current="$(bios_current)"
|
||||
if [[ -n "${BIOS_NEEDS_RESTART:-}" ]]; then
|
||||
echo "Update BIOS: $BIOS_NEWEST waits for a restart"
|
||||
elif [[ -z "${BIOS_NEWEST:-}" ]]; then
|
||||
echo "Update BIOS: now $current, newest unknown (offline?)"
|
||||
elif [[ "$BIOS_NEWEST" == "$current" ]]; then
|
||||
echo "Update BIOS: $current is up to date"
|
||||
else
|
||||
echo "Update BIOS: now $current, newest $BIOS_NEWEST (own risk)"
|
||||
fi
|
||||
}
|
||||
|
||||
BIOS_BOX_WIDTH=68
|
||||
|
||||
bios_box_line() {
|
||||
# bios_box_line [text]: one line of the warning box, padded to the same
|
||||
# visible width (colour codes don't count) so the right edge lines up.
|
||||
local text="${1:-}" plain pad
|
||||
plain="$(printf '%b' "$text" | sed 's/\x1b\[[0-9;]*m//g')"
|
||||
pad=$(( BIOS_BOX_WIDTH - 6 - ${#plain} ))
|
||||
(( pad < 0 )) && pad=0
|
||||
printf ' %b██%b %b%*s%b██%b\n' "$c_red" "$c_reset" "$text" "$pad" "" "$c_red" "$c_reset"
|
||||
}
|
||||
|
||||
bios_box_border() {
|
||||
# Block characters: Konsole draws a long coloured row of # narrower
|
||||
# than the box's other lines, so its right edge wouldn't line up.
|
||||
printf ' %b%s%b\n' "$c_red" "$(printf '█%.0s' $(seq "$BIOS_BOX_WIDTH"))" "$c_reset"
|
||||
}
|
||||
|
||||
bios_disclaimer() {
|
||||
# bios_disclaimer <title> [line...]: the warning box; extra lines are
|
||||
# shown above the fixed risks.
|
||||
local title="$1" line b="$c_bold" n="$c_reset"
|
||||
shift
|
||||
echo
|
||||
bios_box_border
|
||||
bios_box_line
|
||||
bios_box_line "$c_red$b$title$n"
|
||||
bios_box_line
|
||||
bios_box_border
|
||||
for line in "$@"; do bios_box_line "$line"; done
|
||||
bios_box_line
|
||||
bios_box_line "- A failed or interrupted BIOS update can leave the machine"
|
||||
bios_box_line " unable to start (bricked). This wizard, CachyOS and Valve"
|
||||
bios_box_line " take no responsibility for that."
|
||||
bios_box_line "- ${b}NEVER turn off the power, unplug the machine or press${n}"
|
||||
bios_box_line " ${b}the power button while the update runs${n}, including the"
|
||||
bios_box_line " restart(s) afterwards, when the firmware is written."
|
||||
bios_box_line "- The screen can stay black for several minutes. Wait."
|
||||
bios_box_line "- Only on mains power, with all other programs closed."
|
||||
bios_box_line
|
||||
bios_box_border
|
||||
echo
|
||||
}
|
||||
|
||||
bios_fits_device() {
|
||||
# bios_fits_device <cab>: does fwupd match this firmware to a device in
|
||||
# this machine? It compares the file's hardware IDs (GUIDs) with the
|
||||
# hardware; for a file that doesn't fit it reports an UpdateError.
|
||||
local details
|
||||
details="$(sudo fwupdmgr get-details --json "$1" 2>/dev/null)" || return 1
|
||||
grep -q '"Guid"' <<< "$details" && ! grep -q '"UpdateError"' <<< "$details"
|
||||
}
|
||||
|
||||
bios_enable() {
|
||||
if ! bios_lookup_newest; then
|
||||
err "Couldn't find the newest Steam Machine BIOS on Valve's mirror ($VALVE_MIRROR)."
|
||||
return 1
|
||||
fi
|
||||
local current tmp compatible
|
||||
current="$(bios_current)"
|
||||
[[ -n "$BIOS_DRY_RUN" ]] && warn "DRY RUN (WIZARD_BIOS_DRY_RUN): nothing will be flashed."
|
||||
if [[ "$current" == "$BIOS_NEWEST" ]]; then
|
||||
ok "The BIOS is already the newest version ($current); nothing to do."
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Download and check everything before asking: the warnings only come
|
||||
# when the file is Valve's (SHA-256 from Valve's repo database) and fwupd
|
||||
# confirms it's firmware for this very machine.
|
||||
pacman -Q fwupd >/dev/null 2>&1 || sudo pacman -S --needed --noconfirm fwupd ||
|
||||
{ err "Installing fwupd failed."; return 1; }
|
||||
tmp="$(mktemp -d)"
|
||||
info "Downloading $BIOS_PKG ($BIOS_REPO)..."
|
||||
if ! curl -fsSL "$VALVE_MIRROR/$BIOS_REPO/os/x86_64/$BIOS_PKG" -o "$tmp/pkg.tar.zst" ||
|
||||
! echo "$BIOS_SHA256 $tmp/pkg.tar.zst" | sha256sum -c --quiet - ||
|
||||
! tar -I unzstd -xf "$tmp/pkg.tar.zst" -C "$tmp" "$BIOS_CAB"; then
|
||||
err "Downloading or verifying $BIOS_PKG failed; the BIOS was not touched."
|
||||
rm -rf "$tmp"
|
||||
return 1
|
||||
fi
|
||||
ok "Checksum OK: this is Valve's $BIOS_PKG."
|
||||
local yes="$c_green$c_bold" b="$c_bold" n="$c_reset"
|
||||
if [[ -n "$BIOS_DRY_RUN" ]]; then
|
||||
warn "Dry run: skipping fwupd's check that the firmware fits this machine."
|
||||
compatible="${c_yellow}${b}not checked${n} (dry run)"
|
||||
elif bios_fits_device "$tmp/$BIOS_CAB"; then
|
||||
ok "fwupd confirms BIOS $BIOS_NEWEST is firmware for this machine."
|
||||
compatible="${yes}yes${n} (checked by fwupd)"
|
||||
else
|
||||
err "fwupd says BIOS $BIOS_NEWEST is not for this machine's hardware; not installing it."
|
||||
rm -rf "$tmp"
|
||||
return 1
|
||||
fi
|
||||
|
||||
bios_disclaimer "WARNING: BIOS UPDATE - ENTIRELY AT YOUR OWN RISK" \
|
||||
"Current BIOS: ${b}$current${n}" \
|
||||
"New BIOS: ${b}$BIOS_NEWEST${n}" \
|
||||
"Checksum: ${yes}OK${n} (Valve's package)" \
|
||||
"Compatible: $compatible"
|
||||
if ! ask_yn "Do you understand the risks and want to continue?" n; then
|
||||
info "BIOS update cancelled; nothing was changed."; rm -rf "$tmp"; return 0
|
||||
fi
|
||||
bios_disclaimer "LAST CHANCE: THIS FLASHES BIOS $BIOS_NEWEST" \
|
||||
"After this, keep the power on until the machine has fully" \
|
||||
"started again. Don't touch it, even if the screen is black."
|
||||
local reply
|
||||
read -rp "$(echo -e "${c_red}${c_bold}Type UPDATE (in capitals) to flash the BIOS, anything else cancels:${c_reset} ")" reply
|
||||
if [[ "$reply" != UPDATE ]]; then
|
||||
info "BIOS update cancelled; nothing was changed."; rm -rf "$tmp"; return 0
|
||||
fi
|
||||
|
||||
if [[ -n "$BIOS_DRY_RUN" ]]; then
|
||||
ok "Dry run: would run: fwupdmgr install -y --no-reboot-check $(basename "$BIOS_CAB")"
|
||||
ok "Dry run finished; nothing was flashed."
|
||||
# Treated as staged, so the restart choices that follow a real
|
||||
# update show up too; restarting only prints (see restart_now).
|
||||
BIOS_NEEDS_RESTART=1
|
||||
rm -rf "$tmp"
|
||||
return 0
|
||||
fi
|
||||
info "Handing BIOS $BIOS_NEWEST to fwupd. Do NOT turn off the power from now on."
|
||||
# -y: we already asked twice; --no-reboot-check: the wizard's own
|
||||
# restart question comes at the end.
|
||||
if ! sudo fwupdmgr install -y --no-reboot-check "$tmp/$BIOS_CAB"; then
|
||||
err "fwupd could not install the BIOS update (see above); the BIOS was not changed."
|
||||
rm -rf "$tmp"
|
||||
return 1
|
||||
fi
|
||||
rm -rf "$tmp"
|
||||
BIOS_NEEDS_RESTART=1
|
||||
ok "BIOS $BIOS_NEWEST is staged. It is written during the next restart:"
|
||||
warn "keep the power on and don't touch the machine until it has fully started again."
|
||||
}
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
#!/bin/bash
|
||||
# Output helpers, prompts and small shared utilities.
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
c_reset="\033[0m"; c_bold="\033[1m"; c_green="\033[32m"; c_yellow="\033[33m"; c_red="\033[31m"; c_cyan="\033[36m"
|
||||
c_reset="\033[0m"; c_bold="\033[1m"; c_green="\033[32m"; c_yellow="\033[33m"; c_red="\033[31m"; c_cyan="\033[36m"; c_dim="\033[2m"
|
||||
|
||||
info() { echo -e "${c_cyan}[INFO]${c_reset} $*"; }
|
||||
ok() { echo -e "${c_green}[OK]${c_reset} $*"; }
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
# "Return to Gaming Mode" desktop shortcut and the sudoers rule it needs.
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
create_desktop_shortcut() {
|
||||
# Determine the home directory of the target user
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
# Booting into gaming mode: autologin into gamescope with SDDM or
|
||||
# plasma-login-manager (plus the session sync bridge the latter needs).
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
BASE_CONF="/etc/plasmalogin.conf"
|
||||
|
||||
|
||||
+50
-14
@@ -1,23 +1,40 @@
|
||||
#!/bin/bash
|
||||
# Interactive menu: detects which components are on, lets the user pick what
|
||||
# they want, then turns components on or off to match.
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
# Menu order. Components are turned on in this order and off in reverse;
|
||||
# gaming must come first (single user builds on it).
|
||||
COMPONENTS=(gaming theme glyphs single machine)
|
||||
COMPONENTS=(gaming theme glyphs single launcher machine bios)
|
||||
# One-off actions rather than on/off components: never preselected, never
|
||||
# re-applied, not listed as on or off.
|
||||
ACTIONS=(bios)
|
||||
|
||||
declare -A LABEL=(
|
||||
[gaming]="SteamOS conversion: boot into gaming mode, Steam on the desktop"
|
||||
[theme]="Install SteamOS theme: Vapor look (cachyos-vapor)"
|
||||
[glyphs]="Install Steam Deck/Machine icons: Deck button icons in gaming mode"
|
||||
[single]="Single user mode: no password, lock screen or log out (SDDM)"
|
||||
[launcher]="Steamify shortcut: desktop icon to run this again"
|
||||
[machine]="Steam Machine support: LED bar driver, hardware settings in Steam"
|
||||
[bios]="Update BIOS"
|
||||
)
|
||||
declare -A CURRENT WANTED
|
||||
|
||||
component_available() {
|
||||
[[ "$1" != machine ]] || machine_available
|
||||
case "$1" in
|
||||
machine) machine_available ;;
|
||||
bios) bios_available ;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_action() { [[ " ${ACTIONS[*]} " == *" $1 "* ]]; }
|
||||
|
||||
component_selectable() {
|
||||
# Greyed out and not tickable when it has nothing to do.
|
||||
case "$1" in
|
||||
bios) bios_selectable ;;
|
||||
esac
|
||||
}
|
||||
|
||||
detect_components() {
|
||||
@@ -27,16 +44,19 @@ detect_components() {
|
||||
if "${c}_status"; then CURRENT[$c]=1; any=true; else CURRENT[$c]=0; fi
|
||||
WANTED[$c]=${CURRENT[$c]}
|
||||
done
|
||||
# First run: preselect the full SteamOS experience.
|
||||
# Shows the current and newest BIOS version.
|
||||
bios_available && { bios_lookup_newest; LABEL[bios]="$(bios_label)"; }
|
||||
# First run: preselect the full SteamOS experience (never an action).
|
||||
if [[ "$any" == false ]]; then
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
component_available "$c" && WANTED[$c]=1
|
||||
component_available "$c" && ! is_action "$c" && WANTED[$c]=1
|
||||
done
|
||||
fi
|
||||
}
|
||||
|
||||
toggle_component() {
|
||||
local c="$1"
|
||||
component_selectable "$c" || return 1
|
||||
WANTED[$c]=$(( 1 - WANTED[$c] ))
|
||||
# Single user mode only makes sense on top of the SteamOS conversion.
|
||||
if [[ "$c" == single && "${WANTED[single]}" == 1 ]]; then WANTED[gaming]=1; fi
|
||||
@@ -51,9 +71,17 @@ show_menu() {
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
component_available "$c" || continue
|
||||
i=$((i + 1)); MENU_ITEMS[$i]=$c
|
||||
now="off"; [[ "${CURRENT[$c]}" == 1 ]] && now="${c_green}on${c_reset} "
|
||||
# Pad the plain word, then colour it: colour codes would count as width.
|
||||
now="off"; [[ "${CURRENT[$c]}" == 1 ]] && now="on"
|
||||
is_action "$c" && now="-"
|
||||
now="$(printf '%-6s' "$now")"
|
||||
[[ "${CURRENT[$c]}" == 1 ]] && now="${now/on/${c_green}on${c_reset}}"
|
||||
want="[ ]"; [[ "${WANTED[$c]}" == 1 ]] && want="[x]"
|
||||
printf " %-3s %-6b %-6s %s\n" "$i" "$now " "$want" "${LABEL[$c]}"
|
||||
if component_selectable "$c"; then
|
||||
printf " %-3s %b %-6s %s\n" "$i" "$now" "$want" "${LABEL[$c]}"
|
||||
else
|
||||
printf " %b%-3s %-6s %-6s %s (not available)%b\n" "$c_dim" "$i" "$now" "$want" "${LABEL[$c]}" "$c_reset"
|
||||
fi
|
||||
done
|
||||
echo
|
||||
echo -e "$KERNEL_OVERVIEW"
|
||||
@@ -76,7 +104,7 @@ run_menu() {
|
||||
draw_menu_tui() {
|
||||
local cursor="$1" i=0 c box state line
|
||||
printf '\033[H\033[2J'
|
||||
echo -e "${c_bold}CachyOS Steam Deck-style Gamescope Boot Wizard${c_reset} v$VERSION"
|
||||
echo -e "${c_bold}Steamify CachyOS${c_reset} v$VERSION"
|
||||
echo "Pick what you want. Anything you untick is put back the way it was."
|
||||
echo
|
||||
MENU_ITEMS=()
|
||||
@@ -84,13 +112,18 @@ draw_menu_tui() {
|
||||
component_available "$c" || continue
|
||||
MENU_ITEMS[$i]=$c
|
||||
box="[ ]"; [[ "${WANTED[$c]}" == 1 ]] && box="[${c_green}x${c_reset}]"
|
||||
state="off"; [[ "${CURRENT[$c]}" == 1 ]] && state="${c_green}on${c_reset}"
|
||||
state=" (now: off)"; [[ "${CURRENT[$c]}" == 1 ]] && state=" (now: ${c_green}on${c_reset})"
|
||||
is_action "$c" && state=" (opt-in, runs once)"
|
||||
line="$box ${LABEL[$c]}"
|
||||
if (( i == cursor )); then
|
||||
if ! component_selectable "$c"; then
|
||||
# Greyed out: nothing to do (e.g. BIOS already up to date).
|
||||
local mark=" "; (( i == cursor )) && mark=" ${c_cyan}>${c_reset} "
|
||||
echo -e "${mark}${c_dim}[ ] ${LABEL[$c]} (not available)${c_reset}"
|
||||
elif (( i == cursor )); then
|
||||
# The green x's reset would end the bold too: re-enable it after.
|
||||
echo -e " ${c_cyan}>${c_reset} ${c_bold}${line//"$c_reset"/"$c_reset$c_bold"}${c_reset} (now: ${state})"
|
||||
echo -e " ${c_cyan}>${c_reset} ${c_bold}${line//"$c_reset"/"$c_reset$c_bold"}${c_reset}${state}"
|
||||
else
|
||||
echo -e " ${line} (now: ${state})"
|
||||
echo -e " ${line}${state}"
|
||||
fi
|
||||
i=$((i + 1))
|
||||
done
|
||||
@@ -137,7 +170,8 @@ run_menu_lines() {
|
||||
q|Q) return 1 ;;
|
||||
*)
|
||||
if [[ "$reply" =~ ^[0-9]+$ && -n "${MENU_ITEMS[$reply]:-}" ]]; then
|
||||
toggle_component "${MENU_ITEMS[$reply]}"
|
||||
toggle_component "${MENU_ITEMS[$reply]}" ||
|
||||
warn "Not available: ${LABEL[${MENU_ITEMS[$reply]}]}"
|
||||
else
|
||||
warn "Unknown choice: $reply"
|
||||
fi
|
||||
@@ -160,6 +194,7 @@ plan_changes() {
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
component_available "$c" || continue
|
||||
[[ "${WANTED[$c]}" == 1 ]] || continue
|
||||
if is_action "$c"; then TO_ENABLE+=("$c"); continue; fi
|
||||
if [[ "${CURRENT[$c]}" == 0 || "$REAPPLY" == true ]] ||
|
||||
[[ "$c" == gaming && "${CURRENT[single]}" != "${WANTED[single]}" ]]; then
|
||||
TO_ENABLE+=("$c")
|
||||
@@ -177,7 +212,8 @@ apply_changes() {
|
||||
"${c}_disable" || failed+=("$c")
|
||||
done
|
||||
for c in "${TO_ENABLE[@]}"; do
|
||||
echo; echo -e "${c_bold}Turning on: ${LABEL[$c]}${c_reset}"
|
||||
if is_action "$c"; then echo; echo -e "${c_bold}Running: ${LABEL[$c]%%:*}${c_reset}"
|
||||
else echo; echo -e "${c_bold}Turning on: ${LABEL[$c]}${c_reset}"; fi
|
||||
"${c}_enable" || failed+=("$c")
|
||||
done
|
||||
FAILED=("${failed[@]}")
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
# Required packages and AUR helper handling.
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
aur_noninteractive_flags() {
|
||||
# Fully non-interactive install flags for the given AUR helper: no
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
# log out, since typing a password with a controller is miserable. Goes
|
||||
# together with SDDM (see lib/login-manager.sh). All changes are journaled
|
||||
# per user (lib/state.sh), so turning it off restores KDE's previous state.
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
single_status() {
|
||||
[[ "$(kreadconfig6 --file kdeglobals --group "KDE Action Restrictions" --key action/lock_screen)" == false ]]
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
# off again exactly: the first time a component changes a key, the key's
|
||||
# previous value is recorded, and reverting the component puts it back (or
|
||||
# deletes the key if it didn't exist before).
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/cachyos-gamescope-boot"
|
||||
UNSET=$'\x01'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
# Steam in the Plasma desktop session: gamepad UI args, virtual keyboard,
|
||||
# autostart. Part of the SteamOS conversion (gaming_enable/gaming_disable).
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
steam_enable() {
|
||||
info "Applying non-optional SteamOS environment & keyboard fixes..."
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
# "Steam Machine support" menu item, only on Valve Fremont hardware: the
|
||||
# front LED bar driver, LED access for Steam, and steamos-manager.
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
detect_valve_fremont() {
|
||||
# Valve Steam Machine (Fremont) boards. The leds-valve driver's own DMI
|
||||
@@ -163,7 +163,9 @@ kernel_overview() {
|
||||
local mark="${c_green}yes${c_reset}" miss="${c_red}no ${c_reset}" leds=false
|
||||
detect_valve_fremont && command -v dkms >/dev/null 2>&1 && leds=true
|
||||
local kdir k pkg headers hid led running line
|
||||
echo -e " ${c_bold}Kernels${c_reset} (> = running; controller = Steam controller driver, LEDs = LED bar driver built)"
|
||||
local legend="> = running; controller = Steam controller driver"
|
||||
[[ "$leds" == true ]] && legend+=", LEDs = LED bar driver built"
|
||||
echo -e " ${c_bold}Kernels${c_reset} ($legend)"
|
||||
for kdir in /usr/lib/modules/*/; do
|
||||
k="$(basename "$kdir")"
|
||||
[[ -f "$kdir/pkgbase" ]] || continue
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
# rule and an empty KWallet. Part of the SteamOS theme component
|
||||
# (lib/vapor-theme.sh). System files go to /usr/local (nothing
|
||||
# package-owned); per-user settings go through the undo journal.
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
VALVE_MIRROR="https://steamdeck-packages.steamos.cloud/archlinux-mirror"
|
||||
NESTED_DIR=/usr/local/share/applications/steam/holo-nested-desktop
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
# SteamOS Vapor desktop theme, from CachyOS's cachyos-vapor package.
|
||||
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
VAPOR_LOOKANDFEEL=com.valve.vapor.desktop
|
||||
VAPOR_DEFAULTS=/usr/share/plasma/look-and-feel/$VAPOR_LOOKANDFEEL/contents/defaults
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#!/bin/bash
|
||||
# "Steamify shortcut" menu item: a desktop icon and an app launcher entry that
|
||||
# open the newest release of Steamify CachyOS in Konsole (curl | bash, like the
|
||||
# install command in the README), so it's never out of date.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
WIZARD_RELEASE="https://github.com/theupriser/steamify-cachyos/releases/latest/download"
|
||||
WIZARD_URL="$WIZARD_RELEASE/steamify.sh"
|
||||
# Steam logo with a gear (assets/ in the repo, published with every release).
|
||||
WIZARD_ICON="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor/scalable/apps/cachyos-gamescope-boot-wizard.svg"
|
||||
WIZARD_LAUNCHER="${XDG_DATA_HOME:-$HOME/.local/share}/cachyos-gamescope-boot/run-wizard"
|
||||
WIZARD_DESKTOP_NAME="cachyos-gamescope-boot-wizard.desktop"
|
||||
WIZARD_APP_ENTRY="${XDG_DATA_HOME:-$HOME/.local/share}/applications/$WIZARD_DESKTOP_NAME"
|
||||
|
||||
wizard_desktop_file() {
|
||||
echo "$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")/$WIZARD_DESKTOP_NAME"
|
||||
}
|
||||
|
||||
install_executable() {
|
||||
# install_executable <dest> <mode>: stdin to <dest>, with its mode set
|
||||
# before it appears. Plasma treats a desktop icon it saw while it wasn't
|
||||
# executable yet as untrusted and opens it in an editor.
|
||||
local dest="$1" tmp
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
tmp="$(mktemp "$(dirname "$dest")/.tmp.XXXXXX")"
|
||||
cat > "$tmp"
|
||||
chmod "$2" "$tmp"
|
||||
mv -f "$tmp" "$dest"
|
||||
}
|
||||
|
||||
launcher_status() {
|
||||
[[ -x "$WIZARD_LAUNCHER" && -f "$WIZARD_APP_ENTRY" ]]
|
||||
}
|
||||
|
||||
launcher_enable() {
|
||||
info "Adding the Steamify shortcut (desktop icon and app launcher entry)..."
|
||||
install_executable "$WIZARD_LAUNCHER" 755 << EOF
|
||||
#!/bin/bash
|
||||
# Installed by Steamify CachyOS: run its newest release.
|
||||
# pipefail: a failed download must count as a failure, not an empty script.
|
||||
set -o pipefail
|
||||
if ! curl -fsSL --max-time 30 "$WIZARD_URL" | bash; then
|
||||
echo
|
||||
echo "Couldn't download or run the wizard. Are you connected to the internet?"
|
||||
echo
|
||||
read -rp "Press Enter to close this window... " _
|
||||
exit 1
|
||||
fi
|
||||
# Done: close the window after a countdown (Enter closes it right away).
|
||||
echo
|
||||
for (( i = 10; i > 0; i-- )); do
|
||||
printf '\rClosing this window in %2d seconds (Enter to close now)... ' "\$i"
|
||||
read -rs -t 1 _ && break
|
||||
done
|
||||
echo
|
||||
EOF
|
||||
|
||||
# The icon comes with the release; without it, Steam's own icon.
|
||||
local icon=steam tmp
|
||||
tmp="$(mktemp)"
|
||||
if curl -fsSL --max-time 20 "$WIZARD_RELEASE/steam-gaming-settings.svg" -o "$tmp" && grep -q '<svg' "$tmp"; then
|
||||
install -D -m 644 "$tmp" "$WIZARD_ICON"
|
||||
icon=cachyos-gamescope-boot-wizard
|
||||
gtk-update-icon-cache -q -f -t "${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor" 2>/dev/null || true
|
||||
else
|
||||
warn "Couldn't download the shortcut's icon; using Steam's icon instead."
|
||||
fi
|
||||
rm -f "$tmp"
|
||||
|
||||
local entry
|
||||
entry="[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Steamify CachyOS
|
||||
Comment=Turn the SteamOS-style parts of this PC on or off
|
||||
Exec=konsole -e $WIZARD_LAUNCHER
|
||||
Icon=$icon
|
||||
Terminal=false
|
||||
Categories=Game;System;Settings;"
|
||||
printf '%s\n' "$entry" | install_executable "$WIZARD_APP_ENTRY" 644
|
||||
printf '%s\n' "$entry" | install_executable "$(wizard_desktop_file)" 755
|
||||
kbuildsycoca6 >/dev/null 2>&1 || true
|
||||
ok "Steamify shortcut added: \"Steamify CachyOS\" on the desktop and in the launcher."
|
||||
}
|
||||
|
||||
launcher_disable() {
|
||||
rm -f "$(wizard_desktop_file)" "$WIZARD_APP_ENTRY" "$WIZARD_LAUNCHER" "$WIZARD_ICON"
|
||||
rmdir "$(dirname "$WIZARD_LAUNCHER")" 2>/dev/null || true
|
||||
kbuildsycoca6 >/dev/null 2>&1 || true
|
||||
ok "Steamify shortcut removed."
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# setup-gamescope-boot.sh
|
||||
#
|
||||
# Wizard that makes a CachyOS (KDE Plasma) install behave like SteamOS:
|
||||
# boot into a Steam Deck-style gamescope session, switch to the Plasma
|
||||
# desktop and back, and reset to gamescope on the next boot/logout.
|
||||
#
|
||||
# It opens with a menu that detects which components are on and turns
|
||||
# them on or off to match what the user picks; turning one off restores
|
||||
# what was there before (system files from .bak-gamescope-wizard backups,
|
||||
# KDE settings from the undo journal in lib/state.sh). Components live in
|
||||
# lib/, see README.md. Safe to re-run.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# Release version, see CHANGELOG.md.
|
||||
VERSION=0.7.0
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
for lib in common state packages login-manager single-user steam-desktop steam-machine vapor-theme steamos-extras desktop-shortcut menu; do
|
||||
# shellcheck source=/dev/null
|
||||
source "$SCRIPT_DIR/lib/$lib.sh"
|
||||
done
|
||||
|
||||
require_root_helper
|
||||
|
||||
echo -e "${c_bold}CachyOS Steam Deck-style Gamescope Boot Wizard${c_reset} v$VERSION"
|
||||
echo "Turn the SteamOS-style parts on or off. The menu shows what is on now;"
|
||||
echo "anything you turn off is put back the way it was."
|
||||
|
||||
if ! command -v pacman >/dev/null 2>&1; then
|
||||
err "This doesn't look like an Arch/CachyOS system (no pacman found). Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Everything per-user (autologin user, Steam, theme, shortcut) is for the
|
||||
# user running the script.
|
||||
TARGET_USER="$(id -un)"
|
||||
|
||||
detect_components
|
||||
run_menu || { info "Nothing changed."; exit 0; }
|
||||
plan_changes
|
||||
|
||||
if [[ ${#TO_DISABLE[@]} -eq 0 && ${#TO_ENABLE[@]} -eq 0 ]]; then
|
||||
ok "Everything is already the way you want it."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "${c_bold}This will:${c_reset}"
|
||||
for c in "${TO_DISABLE[@]}"; do echo " - turn off: ${LABEL[$c]}"; done
|
||||
for c in "${TO_ENABLE[@]}"; do
|
||||
if [[ "${CURRENT[$c]}" == 1 ]]; then echo " - re-apply: ${LABEL[$c]}"; else echo " - turn on: ${LABEL[$c]}"; fi
|
||||
done
|
||||
ask_yn "Go ahead?" y || { info "Nothing changed."; exit 0; }
|
||||
|
||||
# Ask for the sudo password once and keep it fresh, instead of prompting at
|
||||
# random points during the run.
|
||||
sudo -n true 2>/dev/null || sudo -v || exit 1
|
||||
while true; do sudo -n true; sleep 50; kill -0 "$$" 2>/dev/null || exit; done 2>/dev/null &
|
||||
|
||||
apply_changes
|
||||
|
||||
echo
|
||||
detect_components
|
||||
echo -e "${c_bold}Done. Current state:${c_reset}"
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
component_available "$c" || continue
|
||||
if [[ "${CURRENT[$c]}" == 1 ]]; then echo -e " ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " off ${LABEL[$c]}"; fi
|
||||
done
|
||||
if [[ ${#FAILED[@]} -gt 0 ]]; then
|
||||
warn "These had problems (see above): ${FAILED[*]}"
|
||||
fi
|
||||
echo
|
||||
|
||||
# Login manager changes only take effect after a restart.
|
||||
if [[ " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " == *" gaming "* || " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " == *" single "* ]]; then
|
||||
if ask_yn "Restart now so the changes take effect?" n; then
|
||||
sudo reboot
|
||||
else
|
||||
info "Restart whenever you're ready."
|
||||
fi
|
||||
fi
|
||||
Executable
+150
@@ -0,0 +1,150 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# steamify.sh - Steamify CachyOS
|
||||
#
|
||||
# Wizard that makes a CachyOS (KDE Plasma) install behave like SteamOS:
|
||||
# boot into a Steam Deck-style gamescope session, switch to the Plasma
|
||||
# desktop and back, and reset to gamescope on the next boot/logout.
|
||||
#
|
||||
# It opens with a menu that detects which components are on and turns
|
||||
# them on or off to match what the user picks; turning one off restores
|
||||
# what was there before (system files from .bak-gamescope-wizard backups,
|
||||
# KDE settings from the undo journal in lib/state.sh). Components live in
|
||||
# lib/, see README.md. Safe to re-run.
|
||||
|
||||
set -uo pipefail
|
||||
|
||||
# Release version, see CHANGELOG.md.
|
||||
VERSION=0.9.0
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
for lib in common state packages login-manager single-user steam-desktop steam-machine vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut menu; do
|
||||
# shellcheck source=/dev/null
|
||||
source "$SCRIPT_DIR/lib/$lib.sh"
|
||||
done
|
||||
|
||||
require_root_helper
|
||||
|
||||
echo -e "${c_bold}Steamify CachyOS${c_reset} v$VERSION"
|
||||
echo "Turn the SteamOS-style parts on or off. The menu shows what is on now;"
|
||||
echo "anything you turn off is put back the way it was."
|
||||
|
||||
if ! command -v pacman >/dev/null 2>&1; then
|
||||
err "This doesn't look like an Arch/CachyOS system (no pacman found). Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Everything per-user (autologin user, Steam, theme, shortcut) is for the
|
||||
# user running the script.
|
||||
TARGET_USER="$(id -un)"
|
||||
|
||||
restart_needed() { [[ -n "${BIOS_NEEDS_RESTART:-}" || "$RESTART_FOR_LOGIN" == true ]]; }
|
||||
|
||||
restart_now() {
|
||||
if [[ -n "${BIOS_NEEDS_RESTART:-}" ]]; then
|
||||
warn "The BIOS update is written during this restart. Keep the power on and don't"
|
||||
warn "touch the machine until it has fully started again, even if the screen stays black."
|
||||
fi
|
||||
if [[ -n "${BIOS_DRY_RUN:-}" ]]; then
|
||||
ok "Dry run: would restart now (sudo reboot); not restarting."
|
||||
exit 0
|
||||
fi
|
||||
info "Restarting..."
|
||||
sudo reboot
|
||||
exit 0
|
||||
}
|
||||
|
||||
after_run() {
|
||||
# After a run: back to the menu, or restart right away when something
|
||||
# that just ran needs it. Returns 1 when input has ended (scripted runs).
|
||||
local reply
|
||||
if ! restart_needed; then
|
||||
read -rp "Press Enter to go back to the menu... " _ || return 1
|
||||
return 0
|
||||
fi
|
||||
if [[ -n "${BIOS_NEEDS_RESTART:-}" ]]; then
|
||||
warn "The BIOS update is installed at the next restart."
|
||||
else
|
||||
info "The login changes take effect after a restart."
|
||||
fi
|
||||
while true; do
|
||||
read -rp "$(echo -e "${c_bold}[m]${c_reset} back to the menu ${c_bold}[r]${c_reset} restart now: ")" reply || return 1
|
||||
case "$reply" in
|
||||
m|M|"") return 0 ;;
|
||||
r|R) restart_now ;;
|
||||
*) warn "Type m or r." ;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Menu loop: after each run the menu comes back with the new state, until
|
||||
# the user quits; the restart question comes then, once, for everything.
|
||||
RESTART_FOR_LOGIN=false
|
||||
SUDO_KEEPALIVE=false
|
||||
while true; do
|
||||
detect_components
|
||||
run_menu || break
|
||||
plan_changes
|
||||
|
||||
if [[ ${#TO_DISABLE[@]} -eq 0 && ${#TO_ENABLE[@]} -eq 0 ]]; then
|
||||
ok "Everything is already the way you want it."
|
||||
read -rp "Press Enter to go back to the menu... " _ || break
|
||||
continue
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "${c_bold}This will:${c_reset}"
|
||||
for c in "${TO_DISABLE[@]}"; do echo " - turn off: ${LABEL[$c]}"; done
|
||||
for c in "${TO_ENABLE[@]}"; do
|
||||
if is_action "$c"; then echo " - run: ${LABEL[$c]%%:*} at your own risk (checks, then asks twice more)"
|
||||
elif [[ "${CURRENT[$c]}" == 1 ]]; then echo " - re-apply: ${LABEL[$c]}"; else echo " - turn on: ${LABEL[$c]}"; fi
|
||||
done
|
||||
ask_yn "Go ahead?" y || { info "Nothing changed."; continue; }
|
||||
|
||||
# Ask for the sudo password once and keep it fresh, instead of prompting
|
||||
# at random points during the run.
|
||||
sudo -n true 2>/dev/null || sudo -v || exit 1
|
||||
if [[ "$SUDO_KEEPALIVE" == false ]]; then
|
||||
SUDO_KEEPALIVE=true
|
||||
while true; do sudo -n true; sleep 50; kill -0 "$$" 2>/dev/null || exit; done 2>/dev/null &
|
||||
fi
|
||||
|
||||
apply_changes
|
||||
# Login manager changes only take effect after a restart.
|
||||
[[ " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " == *" gaming "* || " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " == *" single "* ]] &&
|
||||
RESTART_FOR_LOGIN=true
|
||||
|
||||
echo
|
||||
detect_components
|
||||
echo -e "${c_bold}Done. Current state:${c_reset}"
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
component_available "$c" && ! is_action "$c" || continue
|
||||
if [[ "${CURRENT[$c]}" == 1 ]]; then echo -e " ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " off ${LABEL[$c]}"; fi
|
||||
done
|
||||
if [[ ${#FAILED[@]} -gt 0 ]]; then
|
||||
warn "These had problems (see above): ${FAILED[*]}"
|
||||
fi
|
||||
echo
|
||||
after_run || break
|
||||
done
|
||||
echo
|
||||
|
||||
# A staged BIOS update is written during the restart.
|
||||
if [[ -n "${BIOS_NEEDS_RESTART:-}" ]]; then
|
||||
warn "The BIOS update is written during the next restart. Keep the power on and"
|
||||
warn "don't touch the machine until it has fully started again, even if the screen stays black."
|
||||
if ask_yn "Restart now to install the BIOS update?" n; then
|
||||
restart_now
|
||||
else
|
||||
info "The BIOS update installs at your next restart."
|
||||
fi
|
||||
elif [[ "$RESTART_FOR_LOGIN" == true ]]; then
|
||||
if ask_yn "Restart now so the changes take effect?" n; then
|
||||
restart_now
|
||||
else
|
||||
info "Restart whenever you're ready."
|
||||
fi
|
||||
else
|
||||
info "Bye."
|
||||
fi
|
||||
Reference in new issue
Block a user