mirror of
https://github.com/theupriser/steamify-cachyos.git
synced 2026-10-03 17:41:58 +02:00
Compare commits
109
Commits
v2.5.1
...
ae238ff383
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae238ff383 | ||
|
|
c1217bcea3 | ||
|
|
f3d67fbe52 | ||
|
|
84cf0959e4 | ||
|
|
7caefb7da6 | ||
|
|
453656a0a2 | ||
|
|
6aa1377e16 | ||
|
|
6bcae8af18 | ||
|
|
3cbeb58211 | ||
|
|
83561bb214 | ||
|
|
ca027cb607 | ||
|
|
d93f9ea56c | ||
|
|
761f921e40 | ||
|
|
7a54a2fa59 | ||
|
|
9eab3978a9 | ||
|
|
9602d9d00b | ||
|
|
9a2965d339 | ||
|
|
c42d5454bf | ||
|
|
b3bed43854 | ||
|
|
3e79451244 | ||
|
|
971e792054 | ||
|
|
6557320c81 | ||
|
|
692e3fcbad | ||
|
|
70ecb563fd | ||
|
|
a7276cfd9a | ||
|
|
b3549d4eea | ||
|
|
a232a55bef | ||
|
|
397b3cb607 | ||
|
|
bda1d3ebbe | ||
|
|
3676c64c90 | ||
|
|
d44f29956a | ||
|
|
2858d13429 | ||
|
|
48cf3c7c7c | ||
|
|
619ef1f714 | ||
|
|
b6240539e6 | ||
|
|
7d6df21627 | ||
|
|
3cad70dcc4 | ||
|
|
b8742a5642 | ||
|
|
7f5d29c997 | ||
|
|
cfe3ce7bd0 | ||
|
|
3e4133c14a | ||
|
|
c4b8db85dc | ||
|
|
350011877b | ||
|
|
b1d79d48a6 | ||
|
|
5b42036786 | ||
|
|
4a64232fad | ||
|
|
4ec92f4d89 | ||
|
|
fe4f3f43be | ||
|
|
4bacc3b2e6 | ||
|
|
cc0ca1c35e | ||
|
|
580cc71b57 | ||
|
|
c87e6c763f | ||
|
|
fc05725a91 | ||
|
|
90bc5e4408 | ||
|
|
d99ff652dc | ||
|
|
2aa3068b60 | ||
|
|
1a6ddcfc0d | ||
|
|
11668db91c | ||
|
|
3316c1de28 | ||
|
|
d9365dac81 | ||
|
|
853a3926ee | ||
|
|
66ea63cf7e | ||
|
|
f560f332a9 | ||
|
|
9b86cd1a6c | ||
|
|
a72a4def71 | ||
|
|
ea051c77f6 | ||
|
|
4e829c6111 | ||
|
|
d73e71d4eb | ||
|
|
8f2d2be2aa | ||
|
|
53b72c8e33 | ||
|
|
3b4f3b2313 | ||
|
|
a72d848e78 | ||
|
|
3a58c72d16 | ||
|
|
27a40702ce | ||
|
|
8ab066f034 | ||
|
|
44bfe071d6 | ||
|
|
e281d5e879 | ||
|
|
435f69c151 | ||
|
|
9319cbca1e | ||
|
|
cf6bee1c86 | ||
|
|
16487ba00c | ||
|
|
07a94cd274 | ||
|
|
ce71b34b0d | ||
|
|
d30d505f7d | ||
|
|
9755cc3ac3 | ||
|
|
6f26e74229 | ||
|
|
2a01583b8f | ||
|
|
c40aa1f7d9 | ||
|
|
d204efb59d | ||
|
|
12f6cc0b3a | ||
|
|
b01e2c5221 | ||
|
|
affb5f79b0 | ||
|
|
58e43d4c4a | ||
|
|
23f265b02f | ||
|
|
ced4a45d2f | ||
|
|
6ad686a8b2 | ||
|
|
b1adacbcb3 | ||
|
|
8dd2db3a97 | ||
|
|
501c0ba425 | ||
|
|
bee18b76a8 | ||
|
|
eadbdda271 | ||
|
|
c4ec755a4a | ||
|
|
14aa7c0b54 | ||
|
|
5bf9da411d | ||
|
|
4f6e6fd0aa | ||
|
|
a79eeedbc4 | ||
|
|
b948c2020b | ||
|
|
0c96bed448 | ||
|
|
e3f7cc9773 |
No files matched your search
+112
-23
@@ -5,18 +5,16 @@
|
||||
# release are moved to it, so both of these always get the newest version:
|
||||
# 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
|
||||
# Each release also has the app (v2): steamify-app.tar.gz (ui/, steamify.sh,
|
||||
# Each release also has the app: steamify-app.tar.gz (ui/, steamify.sh,
|
||||
# lib/, patches/, services/, the icon) and its launcher, run with:
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify-app.sh | bash
|
||||
# A push to feat/v2-ui (the app, not released yet) updates the pre-release
|
||||
# v2-ui-preview instead, whose launcher gets that build:
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/download/v2-ui-preview/steamify-app.sh | bash
|
||||
# Pushes to release/** build and check it like pull requests; only main publishes.
|
||||
# Pull requests only build and check it, and warn when VERSION is already released.
|
||||
name: Single-file build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, feat/v2-ui]
|
||||
branches: [main, 'release/**']
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -42,12 +40,39 @@ jobs:
|
||||
- name: Check
|
||||
run: |
|
||||
bash -n dist/steamify.sh
|
||||
# SC2034/SC2154: variables used across the inlined modules.
|
||||
shellcheck -S warning -e SC2034,SC2154 dist/steamify.sh
|
||||
shellcheck -S warning dist/steamify-app.sh
|
||||
python3 -m py_compile ui/steamify-ui
|
||||
|
||||
# shellcheck through an action that brings its own binary: GitHub's runner has it installed,
|
||||
# Gitea's act_runner image doesn't. One file per run, as before (the exceptions are the bundle's).
|
||||
- name: shellcheck the bundle
|
||||
uses: ludeeus/action-shellcheck@2.0.0
|
||||
env:
|
||||
# SC2034/SC2154: variables used across the inlined modules.
|
||||
SHELLCHECK_OPTS: -e SC2034 -e SC2154
|
||||
with:
|
||||
severity: warning
|
||||
scandir: dist
|
||||
ignore_names: steamify-app.sh
|
||||
- name: shellcheck the app launcher
|
||||
uses: ludeeus/action-shellcheck@2.0.0
|
||||
with:
|
||||
severity: warning
|
||||
scandir: dist
|
||||
ignore_names: steamify.sh
|
||||
|
||||
# The build as an artifact on GitHub and on the mirror (Gitea); releases stay GitHub's.
|
||||
# Gitea's artifact server doesn't speak upload-artifact@v4's protocol, and GitHub fails a workflow
|
||||
# that merely mentions the deprecated @v3: Gitea gets christopherhx's fork of v4 for Gitea.
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: github.server_url == 'https://github.com'
|
||||
with:
|
||||
name: steamify
|
||||
path: |
|
||||
dist/steamify.sh
|
||||
dist/steamify-app.tar.gz
|
||||
dist/steamify-app.sh
|
||||
- uses: christopherhx/gitea-upload-artifact@v4
|
||||
if: github.server_url != 'https://github.com'
|
||||
with:
|
||||
name: steamify
|
||||
path: |
|
||||
@@ -57,6 +82,7 @@ jobs:
|
||||
|
||||
- name: Version
|
||||
id: version
|
||||
if: github.server_url == 'https://github.com'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
@@ -71,6 +97,7 @@ jobs:
|
||||
|
||||
- name: Publish the v${{ steps.version.outputs.version }} release
|
||||
if: >-
|
||||
github.server_url == 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.version.outputs.released == 'false'
|
||||
env:
|
||||
@@ -107,22 +134,84 @@ jobs:
|
||||
fi
|
||||
gh release upload latest dist/steamify.sh dist/steamify-app.sh dist/steamify-app.tar.gz assets/steam-gaming-settings.svg --clobber
|
||||
|
||||
- name: Publish the v2-ui-preview pre-release
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/feat/v2-ui'
|
||||
# The mirror (Gitea) publishes its own release per version too, the same way: never overwrites one,
|
||||
# notes from the changelog. gh can't talk to Gitea: its API for the check, a Gitea release action to
|
||||
# publish. The token is the run's own (repository write); a secret RELEASE_TOKEN overrides it.
|
||||
- name: Version (mirror)
|
||||
id: mirror_version
|
||||
if: github.server_url != 'https://github.com'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN || github.token }}
|
||||
run: |
|
||||
# Its launcher downloads this pre-release, not the newest release.
|
||||
sed -i 's/STEAMIFY_RELEASE:-latest/STEAMIFY_RELEASE:-v2-ui-preview/' dist/steamify-app.sh
|
||||
grep -q 'STEAMIFY_RELEASE:-v2-ui-preview' dist/steamify-app.sh
|
||||
git tag -f v2-ui-preview "$GITHUB_SHA" && git push -f origin v2-ui-preview
|
||||
notes="Preview of the Steamify app (v2) from feat/v2-ui ($(git describe --always), $(git log -1 --format='%cs %s')). Not a release.
|
||||
Run it with:
|
||||
|
||||
curl -fsSL https://github.com/${{ github.repository }}/releases/download/v2-ui-preview/steamify-app.sh | bash"
|
||||
if gh release view v2-ui-preview >/dev/null 2>&1; then
|
||||
gh release edit v2-ui-preview --title "Steamify app (v2) preview" --notes "$notes" --prerelease --latest=false
|
||||
version="$(grep -oP '^VERSION=\K.*' steamify.sh)"
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
if curl -fsS -o /dev/null -H "Authorization: token $TOKEN" \
|
||||
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/tags/v$version"; then
|
||||
echo "released=true" >> "$GITHUB_OUTPUT"
|
||||
echo "::warning::v$version is already released on this server and won't be overwritten."
|
||||
else
|
||||
gh release create v2-ui-preview --target "$GITHUB_SHA" --title "Steamify app (v2) preview" --notes "$notes" --prerelease --latest=false
|
||||
echo "released=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
gh release upload v2-ui-preview dist/steamify-app.sh dist/steamify-app.tar.gz --clobber
|
||||
|
||||
- name: Release notes (mirror)
|
||||
if: >-
|
||||
github.server_url != 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.mirror_version.outputs.released == 'false'
|
||||
env:
|
||||
VERSION: ${{ steps.mirror_version.outputs.version }}
|
||||
run: |
|
||||
changes="$(awk -v v="$VERSION" '
|
||||
$0 ~ "^## " { if (found) exit; if (index($0, "## " v " ") == 1) { found = 1; next } }
|
||||
found' CHANGELOG.md)"
|
||||
cat > dist/release-notes.md <<NOTES
|
||||
Single-file build of v$VERSION ($(git describe --always), $(git log -1 --format=%cs)).
|
||||
Run this version with:
|
||||
|
||||
curl -fsSL ${{ github.server_url }}/${{ github.repository }}/releases/download/v$VERSION/steamify.sh | bash
|
||||
|
||||
## Changes in v$VERSION
|
||||
$changes
|
||||
NOTES
|
||||
|
||||
- name: Publish the v${{ steps.mirror_version.outputs.version }} release (mirror)
|
||||
if: >-
|
||||
github.server_url != 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.mirror_version.outputs.released == 'false'
|
||||
uses: akkuman/gitea-release-action@v1.3.7
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_TOKEN || github.token }}
|
||||
tag_name: v${{ steps.mirror_version.outputs.version }}
|
||||
target_commitish: ${{ github.sha }}
|
||||
name: Steamify CachyOS v${{ steps.mirror_version.outputs.version }}
|
||||
body_path: dist/release-notes.md
|
||||
files: |
|
||||
dist/steamify.sh
|
||||
dist/steamify-app.sh
|
||||
dist/steamify-app.tar.gz
|
||||
assets/steam-gaming-settings.svg
|
||||
|
||||
# A new version starts the Steamify ISO's release of the ISO repo: its iso-1-github-tag.yml (always run from
|
||||
# master) names the ISO after the newest Steamify release, tags it, and the Gitea mirror builds and attaches the ISO.
|
||||
# The branch here decides the kind of build (the workflow's input `kind`):
|
||||
# main (publishes the release) -> release: a real ISO (tag v<steamify>-<date>)
|
||||
# release/** (a version not yet released) -> dev: a pre-release (tag v<steamify>-dev.<date>)
|
||||
# Needs a fine-grained token for that repo (Actions: read and write) as the secret ISO_DISPATCH_TOKEN;
|
||||
# without it, this is skipped.
|
||||
- name: Start the Steamify ISO's release
|
||||
if: >-
|
||||
github.server_url == 'https://github.com' &&
|
||||
github.event_name != 'pull_request' &&
|
||||
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) &&
|
||||
steps.version.outputs.released == 'false'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.ISO_DISPATCH_TOKEN }}
|
||||
run: |
|
||||
if [ -z "$GH_TOKEN" ]; then
|
||||
echo "::notice::No ISO_DISPATCH_TOKEN: the Steamify ISO isn't released with this version."; exit 0
|
||||
fi
|
||||
# A release branch builds the ISO with its own code (and VERSION): steamify_ref. main builds the release it just published.
|
||||
if [ "$GITHUB_REF" = refs/heads/main ]; then kind=release; sref=""; else kind=dev; sref="$GITHUB_REF_NAME"; fi
|
||||
gh workflow run iso-1-github-tag.yml -R theupriser/steamify-cachyos-live-iso --ref master -f kind="$kind" -f steamify_ref="$sref"
|
||||
echo "Started the Steamify ISO's release (theupriser/steamify-cachyos-live-iso, master, kind $kind, Steamify ${sref:-the newest release})"
|
||||
@@ -0,0 +1,26 @@
|
||||
name: Sync git.upriser.nl mirror
|
||||
|
||||
# Trigger the Gitea pull-mirror immediately instead of waiting for its interval,
|
||||
# so Gitea builds/tests right after any branch or tag lands on GitHub (the mirror has no sync interval of its own).
|
||||
on:
|
||||
push:
|
||||
branches: ['**']
|
||||
tags: ['*']
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
sync:
|
||||
# Gitea also reads .github/workflows on the mirror; only run on GitHub
|
||||
if: github.server_url == 'https://github.com'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger mirror-sync
|
||||
env:
|
||||
GITEA_URL: ${{ secrets.GIT_UPRISER_URL }}
|
||||
GIT_UPRISER_TOKEN: ${{ secrets.GIT_UPRISER_TOKEN }}
|
||||
# Gitea "owner/repo"; defaults to the same path as on GitHub
|
||||
GITEA_REPO: ${{ vars.GITEA_REPO || github.repository }}
|
||||
run: |
|
||||
curl --fail-with-body -sS --retry 5 --retry-delay 10 --retry-all-errors -X POST \
|
||||
-H "Authorization: token ${GIT_UPRISER_TOKEN}" \
|
||||
"${GITEA_URL%/}/api/v1/repos/${GITEA_REPO}/mirror-sync"
|
||||
@@ -0,0 +1,5 @@
|
||||
This branch is not ready to be released: do not merge it into the release branch.
|
||||
When the feature is complete and tested, ask the user whether it may be released;
|
||||
on a yes, delete this file, then open the pull request into the release branch.
|
||||
Open work, research and the test instructions for the NVIDIA PC are NOT in this repo:
|
||||
see steamify-cachyos-dev, folder nvidia/ (github.com/theupriser/steamify-cachyos-dev).
|
||||
@@ -48,6 +48,13 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
`<id>_available` is checked via `component_available` (e.g. `machine`
|
||||
only on Fremont). Turn-on order is `COMPONENTS` order, turn-off reverse;
|
||||
`gaming` must stay first. Dependencies live in `toggle_component`.
|
||||
- **Hardware-specific fixes** that belong to a component but aren't a menu
|
||||
row (e.g. `lib/nvidia.sh`: NVIDIA's kernel parameters and early modules
|
||||
for gaming mode, called from `gaming_enable`/`gaming_disable`) detect the
|
||||
hardware themselves, change only what's missing, and undo it on disable.
|
||||
Add them to the source loop in `steamify.sh` and the table in
|
||||
`TECHNICAL.md`. They can't be tested without the hardware: say so in the
|
||||
changelog and keep the branch behind `.no-release-yet` until it was.
|
||||
- **Feature versions.** Set `FEATURE_VERSION[<id>]` (`lib/menu.sh`) to the new
|
||||
`VERSION` whenever what `<id>_enable` sets up changes (a new component gets
|
||||
one too): installs recorded with an older version
|
||||
@@ -68,6 +75,13 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
the entry point's `for lib in ...; do` source loop and wraps everything
|
||||
after that loop in `main()`. Keep that loop on one line, keep all logic in
|
||||
functions, and don't rely on `SCRIPT_DIR` for anything but sourcing.
|
||||
The workflow is one file for GitHub and a Gitea mirror (`github.server_url`): build and check run on both
|
||||
(shellcheck through `ludeeus/action-shellcheck`, which brings its own binary; the artifact with
|
||||
`upload-artifact@v4` on GitHub and `christopherhx/gitea-upload-artifact@v4` elsewhere: never mention
|
||||
`upload-artifact@v3`, GitHub fails a workflow for a deprecated version even in a skipped step); the
|
||||
release is `gh` on GitHub and `akkuman/gitea-release-action` on Gitea. A new release on GitHub also starts the
|
||||
Steamify ISO's release (`gh workflow run iso-1-github-tag.yml` in steamify-cachyos-live-iso, secret
|
||||
`ISO_DISPATCH_TOKEN`; skipped without it): the ISO repo's GitHub tag names it, the Gitea mirror builds it.
|
||||
CI (`.github/workflows/bundle.yml`) publishes the bundle as release
|
||||
`v$VERSION` on pushes to `main`; an existing version is never overwritten,
|
||||
so bump `VERSION` for every release.
|
||||
@@ -98,11 +112,49 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
+ subject; a commit can't contain its own hash, so fill it in with the
|
||||
next commit). The section heading must be `## <VERSION> - <date>`: CI
|
||||
cuts the release notes out of the changelog by that heading.
|
||||
- Every PR that should be released bumps `VERSION` and adds its section.
|
||||
A push to `main` publishes release `v$VERSION` (tag + bundle + that
|
||||
- **Branches: one release branch per version.** Work for a release goes
|
||||
into `release/X.Y.Z` (e.g. `release/2.7.0`), branched from `main` when
|
||||
that version starts. That branch bumps `VERSION` to `X.Y.Z` and adds the
|
||||
`## X.Y.Z - <date>` changelog section (first commit on it).
|
||||
- Every change gets its own branch from the release branch:
|
||||
`feature/<name>` (new behaviour) or `bugfix/<name>` (a fix), and a
|
||||
pull request **into the release branch**, not into `main`. Its commits
|
||||
add their changelog lines to that version's section.
|
||||
- When the release is done and tested (the test plan in
|
||||
steamify-cachyos-dev, `TESTPLAN.md`), the release branch gets a pull
|
||||
request **into `main`**. Merging it publishes the release (below).
|
||||
- A fix for a released version: a new `release/X.Y.Z+1` from `main`,
|
||||
with the `bugfix/` branch into it; don't reopen an old release branch.
|
||||
- Up to the release branch, the agent manages it: create the
|
||||
`feature/`/`bugfix/` branches, commit, push, and merge them into the
|
||||
release branch itself once tested (with `gh`: `gh pr create --base
|
||||
release/X.Y.Z` + `gh pr merge --merge`; no review needed). Without
|
||||
`gh` (`command -v gh`), ask the user to install it (Ubuntu:
|
||||
`sudo apt install gh`, then `gh auth login`) instead of working around
|
||||
it. Only the
|
||||
release branch's pull request into `main` is the user's: never commit
|
||||
or merge to `main`, the user merges that one. Never work directly on
|
||||
`main` or a `release/*` branch either: edits, even uncommitted ones,
|
||||
go on a `feature/`/`bugfix/` branch (create it before editing; the
|
||||
release branch only gets the version-bump commit and merged PRs).
|
||||
Don't push a new `release/*` branch before it's needed: a push can
|
||||
start CI builds (a dev ISO).
|
||||
A machine without a git identity: pass the repo's author per command
|
||||
(`git -c user.name=... -c user.email=... commit`, taken from `git
|
||||
log`) instead of changing the git config.
|
||||
A `.no-release-yet` file at the root of a feature/bugfix branch means
|
||||
it must not be merged into the release branch yet (work in progress,
|
||||
untested on hardware). When the feature is complete, ask the user
|
||||
whether it may be released; on a yes, delete the file, then open the
|
||||
pull request and merge it.
|
||||
Keep a feature/bugfix branch up to date by merging (or rebasing on)
|
||||
its release branch, the release branch by merging `main` when that
|
||||
moved.
|
||||
- A push to `main` publishes release `v$VERSION` (tag + bundle + that
|
||||
changelog section) and marks it latest. An existing version is never
|
||||
overwritten: without a bump nothing is released, and pull requests show
|
||||
a warning.
|
||||
a warning when `VERSION` is a version that's already released (so a
|
||||
release branch that forgot its bump shows it on every PR).
|
||||
- A release that adds, removes or renames a menu row also retakes the
|
||||
README screenshot (`assets/screenshot-menu.png`): the app from the
|
||||
branch on a Steam Machine, every row visible (window 1280 wide, tall
|
||||
@@ -227,6 +279,11 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
kernel only pairs that with a named lookup ("Port C") when the CEC driver
|
||||
registered first, which never happens since amdgpu loads from the
|
||||
initramfs. Without it `/dev/cec0` exists but stays at `f.f.f.f`.
|
||||
The source comes from one raw.githubusercontent.com download, which GitHub rate-limits (HTTP 429 after a
|
||||
day of test installs, per address): it's kept in `/var/cache/steamify/cros-ec-cec-<sha256:12>.c` and reused
|
||||
while its checksum matches. The name carries the checksum, so a new pin (commit + SHA-256 in `lib/cec.sh`)
|
||||
downloads its own file once and removes the old one. The repo is an unofficial mirror of Valve's kernel
|
||||
without releases: if it ever disappears, ship the file with Steamify. The test VMs share the host's cache.
|
||||
- Power-off fix (`poweroff`, `lib/fremont-poweroff.sh`, a default sub-option
|
||||
of `machine`): recent kernels (7.2 and the 6.x/7.0/7.1 updates with the
|
||||
backport) keep the firmware's S4/S5 wake bit on GPIO
|
||||
@@ -269,6 +326,38 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
latter only starts with `kcgroupsrc [Foreground Booster] autostart=true`
|
||||
(set with `kset`). Disable removes only the packages it installed
|
||||
(`state_get vram installed_pkgs`).
|
||||
- Install-time mode (`steamify.sh --defaults`, 2.6.0): applies what the menu
|
||||
would preselect, no menu or prompts (needs passwordless sudo). The Steam
|
||||
Machine ISO ([steamify-cachyos-live-iso](https://github.com/theupriser/steamify-cachyos-live-iso))
|
||||
runs it in the installer for a user who has never logged in: no session
|
||||
bus, user systemd or plasmashell. So every `systemctl --user` goes through
|
||||
`user_systemctl` (`lib/common.sh`; without a session only unit files change,
|
||||
via `--root=/`), and the theme, when the layout is still `/etc/skel`'s,
|
||||
removes it so Plasma builds Vapor's layout at the first login. What needs
|
||||
that layout (single user's launcher) runs then, from a one-time autostart
|
||||
(`lib/first-login.sh`, `--first-login`) that also opens the app.
|
||||
`--options <id>,...` (exactly these on, the rest off; an item on brings its
|
||||
parent) and `--boot gamescope|desktop` (desktop only with `gaming`) (2.7.0,
|
||||
`defaults_options` in `lib/menu.sh`); the ISO's installer page passes them.
|
||||
Items this PC can't use are left off with a warning, not an error.
|
||||
`steamify.sh --boot gamescope|desktop` on its own (2.7.0, for scripts) only
|
||||
switches `boot` on an installed conversion: `WANTED` is `CURRENT` plus
|
||||
that, so no updates or removals a normal run would pick.
|
||||
- What Steam's System settings show (SteamOS conversion, 2.9.0): the OS name
|
||||
stays CachyOS's everywhere (legal clarity; Steam's OS Name is
|
||||
`lsb_release -d`, not touched). `/etc/os-release` gets `VERSION_ID=steamos-X.Y`
|
||||
(Steam's OS Version: Valve's newest jupiter repo; offline, the previous
|
||||
value), `VERSION_CODENAME=steam-machine`, `VARIANT="Steamify <version>"` and
|
||||
`VARIANT_ID=steamify-<version>` (Steam shows VARIANT_ID as OS Variant),
|
||||
refreshed by `os_version_refresh` after every run that changes something; a
|
||||
pacman hook (`zz-steamify-os-release`) runs after cachyos-hooks. KDE's About
|
||||
this System would show VERSION_ID after the name: `kcm-about-distrorc`
|
||||
`UseOSReleaseVersion=true` (kset) makes it show os-release's VERSION, which
|
||||
CachyOS doesn't have. Never `NAME` or `PRETTY_NAME`: limine-snapper-sync
|
||||
finds the boot entries by the OS name ("Target OS name ... not found in
|
||||
/boot/limine.conf"); `/etc/default/limine` gets `TARGET_OS_NAME="CachyOS"`
|
||||
when it has none, as a guard. The serial number (tmpfiles rule) is Steam
|
||||
Machine support's, so Fremont only.
|
||||
- `Relogin=true` means a gamescope that fails to start is relaunched in a
|
||||
tight loop; keep that in mind when changing session handling.
|
||||
|
||||
|
||||
@@ -5,6 +5,94 @@ All notable changes, per version and per commit. Versions follow
|
||||
`steamify.sh`. Versions before 0.7.0 were numbered afterwards,
|
||||
one per merged pull request.
|
||||
|
||||
## 2.9.7 - 2026-10-01
|
||||
|
||||
- **feat: the SteamOS conversion fixes a corrupted gaming mode screen with an NVIDIA GPU: nvidia-drm.modeset=1 and fbdev=1 on the kernel command line, NVIDIA modules in the initramfs (lib/nvidia.sh)**
|
||||
- **test: tests/nvidia-test.sh runs the NVIDIA fix against a fake RTX 5080 beside an iGPU, a stub modinfo and temp copies of the Limine, systemd-boot and GRUB files (no root, VM or hardware); NVIDIA_DRM_DIR points detection at a fake sysfs tree**
|
||||
- **fix: NVIDIA fix on Limine edits the KERNEL_CMDLINE[default] line (an appended += line ended up as literal text on the kernel command line, found in a VM); the modules are only loaded early when every installed kernel has them, and a Limine boot entry without the parameters is an error**
|
||||
- **test: tests/nvidia-hardware-test.sh for a real NVIDIA PC: check (read-only state of the detection, the live nvidia_drm modeset/fbdev, versions), apply, and visual (was the gaming mode picture clean), with a report file to paste**
|
||||
- **fix: the NVIDIA modules are loaded early only while every installed kernel has them, decided again at every kernel or driver change by a pacman hook (steamify-nvidia-initramfs): a later kernel without the modules (another kernel, a failed DKMS build, a downgrade) no longer makes its initramfs and Limine boot entry fail**
|
||||
- **feat: the NVIDIA fix is only for RTX 20 series or newer, decided like the VRAM booster does (vram_nvidia_legacy_id: chwd's legacy card lists); older cards are left alone**
|
||||
|
||||
## 2.9.6 - 2026-09-30
|
||||
|
||||
- **fix(ci): a dev ISO from a release branch is built with that branch's own Steamify (input steamify_ref of the ISO workflow), not the newest published release: release/2.9.6 kept producing 2.9.5 ISOs**
|
||||
- **docs: changelog hashes for 2.9.6**
|
||||
- `9a2965d` **fix(ci): the ISO workflow always runs from master; main asks for a release ISO, a release branch for a dev ISO (input `kind` of iso-1-github-tag.yml; feat/steamify is no longer needed)**
|
||||
- `c42d545` **fix(ci): a version published from main starts a real ISO release, a release branch a dev ISO (it always started the dev one)**
|
||||
- `b3bed43` **chore: Version 2.9.6**
|
||||
|
||||
## 2.9.5 - 2026-09-30
|
||||
|
||||
- `70ecb56` **ci: trigger a mirror sync**
|
||||
- `a7276cf` **ci: sync the git.upriser.nl mirror on every branch and tag**
|
||||
- `b3549d4` **ci: sync the mirror on release branch pushes too**
|
||||
- `a232a55` **feat(ci): sync the git.upriser.nl mirror on every push to main and every tag (git-upriser-sync.yml calls the mirror-sync API: the Gitea mirror builds at once instead of at its interval; secrets GIT_UPRISER_URL and GIT_UPRISER_TOKEN, retried, skipped on Gitea itself)**
|
||||
- `3676c64` **docs: link the renamed steamify-cachyos-live-iso repo (the release dispatches the ISO workflow iso-1-github-tag.yml there)**
|
||||
- `971e792` **chore: Version 2.9.5**
|
||||
|
||||
## 2.9.4 - 2026-09-29
|
||||
|
||||
- `619ef1f` **docs: AGENTS.md and TECHNICAL.md: the CEC driver cache, the one workflow for GitHub and a Gitea mirror, and that a new release starts the Steamify ISO's release**
|
||||
- `b624053` **chore: Version 2.9.4**
|
||||
|
||||
## 2.9.3 - 2026-09-29
|
||||
|
||||
- `7f5d29c` **feat(ci): a new Steamify release starts the Steamify ISO's release (a test build from the ISO repo's feat/steamify; secret ISO_DISPATCH_TOKEN)**
|
||||
- `cfe3ce7` **chore: Version 2.9.3**
|
||||
|
||||
## 2.9.2 - 2026-09-29
|
||||
|
||||
- **feat(ci): a Gitea mirror publishes its own release per version (akkuman/gitea-release-action; never overwrites one, notes from the changelog, links to the mirror)**
|
||||
- **fix(ci): the build also runs on a Gitea mirror (act_runner): shellcheck through ludeeus/action-shellcheck, which brings its own binary; the artifact goes up there with christopherhx/gitea-upload-artifact (GitHub refuses a workflow that mentions the deprecated upload-artifact@v3); releases are only published on GitHub**
|
||||
- `fe4f3f4` **chore: Version 2.9.2**
|
||||
|
||||
## 2.9.1 - 2026-09-29
|
||||
|
||||
- `c87e6c7` **docs: changelog for the CEC driver cache**
|
||||
- `fc05725` **fix: HDMI-CEC: an older cached CEC driver is removed when a new pin is downloaded**
|
||||
- `90bc5e4` **fix: HDMI-CEC: Valve's CEC driver is downloaded once and kept in /var/cache/steamify (GitHub rate-limits repeated downloads with HTTP 429, which left CEC off); turning CEC on again needs no network**
|
||||
- `d99ff65` **chore: Version 2.9.1**
|
||||
|
||||
## 2.9.0 - 2026-09-28
|
||||
|
||||
- `d30d505` **chore: Version 2.9.0**
|
||||
- `66ea63c` **docs: KDE Plasma only: other desktops and display managers "are not supported" (README, was "don't work yet")**
|
||||
- `9b86cd1` **docs: KDE Plasma only: other desktops don't work yet (README)**
|
||||
- `d73e71d` **docs: README, TECHNICAL and TROUBLESHOOTING for 2.9.0: Steam's System settings, serial number and Wi-Fi backend, --defaults --list, the Steamify ISO**
|
||||
- `a72d848` **feat: Steam's OS Version is the SteamOS release Steamify follows (steamos-3.9), its OS Codename steam-machine; About this System keeps "CachyOS Linux" (UseOSReleaseVersion)**
|
||||
- `27a4070` **fix: Steam's OS Variant shows Steamify's version (VARIANT_ID=steamify-2.9.0; Steam shows VARIANT_ID, not VARIANT)**
|
||||
- `44bfe07` **fix: No VERSION_ID in os-release: About this System said "CachyOS Linux 2.9.0"; the version is in VARIANT ("Steamify 2.9.0")**
|
||||
- `435f69c` **feat: Steam's System settings: the OS name stays CachyOS (no renaming, also not in About this System), Steamify <version> as the variant, the SteamOS release it follows as the codename (steamos-3.9)**
|
||||
- `ce71b34` **feat: Steam's System settings and About this System like on SteamOS: OS name "CachyOS with Steamify" (lsb-release, kept through CachyOS updates by a pacman hook), Steamify as OS variant and version (os-release VARIANT/VERSION_ID; NAME/PRETTY_NAME stay CachyOS's for limine, TARGET_OS_NAME pinned), "CachyOS Linux with Steamify" in About this System; on a Steam Machine the serial number and Steam's Wi-Fi backend setting (existing installs get it as an update)**
|
||||
- `07a94cd` **fix(ui): The progress screen's ✓ and ! stand upright: only a dot on the circle spins while a step runs (they kept the spinner's last angle)**
|
||||
|
||||
## 2.8.0 - 2026-09-28
|
||||
|
||||
- **chore: Version 2.8.0**
|
||||
- **feat: steamify.sh --defaults --list: what --defaults can set up here, as JSON, for an installer page**
|
||||
|
||||
## 2.7.0 - 2026-09-28
|
||||
|
||||
- `4f6e6fd` **feat: --defaults takes --skip <ids> and --boot gamescope|desktop, for the Steam Machine ISO's installer pages**
|
||||
- `5bf9da4` **fix: HDMI-CEC enables cec-audio-control.socket (the TV remote's volume keys); existing installs get it as an update**
|
||||
- `14aa7c0` **fix: the app's progress screen says "Boot into desktop", not "Boot into Boot into"**
|
||||
- `c4ec755` **feat: --defaults --options <ids> (exactly these on) replaces --skip; steamify.sh --boot gamescope|desktop on its own switches where an installed conversion starts**
|
||||
- `eadbdda` **docs: release branches (release/X.Y.Z, feature/ and bugfix/ branches into it, the release into main); CI builds release/** pushes**
|
||||
- `bee18b7` **docs: the agent merges feature/bugfix branches into the release branch; the release into main stays the user's**
|
||||
- `501c0ba` **docs: gh or git for merging into the release branch**
|
||||
- `b1adacb` **docs: gh is required for the release-branch pull requests; ask the user to install it**
|
||||
- `ced4a45` **chore: the v2 app preview is gone (it is the released app): no preview pre-release step in CI, no mention in steamify-app.sh**
|
||||
- **fix: turning the theme off no longer brings back single user's launcher restriction when single user was turned off in between**
|
||||
|
||||
## 2.6.0 - 2026-09-27
|
||||
|
||||
- `b948c20` **feat: --defaults applies the default setup without the menu, also from an installer (no session): the base for a Steam Machine ISO**
|
||||
|
||||
## 2.5.2 - 2026-09-27
|
||||
|
||||
- `0c96bed` **docs: README screenshot at 2.5.2: everything on, nothing to update**
|
||||
|
||||
## 2.5.1 - 2026-09-27
|
||||
|
||||
- **fix: Add as non-Steam game asks Steam to close again every 15 s (a Steam that was still starting ignored it)**
|
||||
|
||||
@@ -19,6 +19,10 @@ Steam Machine.
|
||||
on the desktop too.
|
||||
- **Boot into: gamescope / desktop** - where the PC starts. Gaming mode is
|
||||
the default.
|
||||
- Steam's **System** settings show the SteamOS release Steamify follows
|
||||
as OS Version (e.g. `steamos-3.9`), `steam-machine` as OS Codename and
|
||||
Steamify's version as OS Variant. The OS name stays CachyOS
|
||||
([details](TECHNICAL.md#what-steams-system-settings-show)).
|
||||
2. **SteamOS theme** - the Vapor look of SteamOS for the desktop, with
|
||||
**Add to Steam** in right-click menus
|
||||
([details](TECHNICAL.md#steamos-desktop-look)).
|
||||
@@ -62,7 +66,8 @@ What Steamify can do on a Valve Steam Machine:
|
||||
([details](TECHNICAL.md#hdmi-cec)).
|
||||
- **Steam Machine support** - the front **LED bar** works, Steam's
|
||||
**hardware settings** (fan, performance) work, and the power button puts
|
||||
it to sleep like a console.
|
||||
it to sleep like a console. Steam's System settings show the serial
|
||||
number, and Steam's **Wi-Fi backend** setting works.
|
||||
- **Power-off fix** - on by default: shutting down really turns the Steam
|
||||
Machine off, also with the newest CachyOS kernel
|
||||
([details](TECHNICAL.md#power-off-fix-steam-machine)).
|
||||
@@ -73,6 +78,11 @@ What Steamify can do on a Valve Steam Machine:
|
||||
## Requirements
|
||||
|
||||
- CachyOS with the KDE Plasma desktop (the default CachyOS Desktop edition)
|
||||
|
||||
> **KDE Plasma only.** Steamify works with KDE Plasma and its login managers
|
||||
> (plasma-login-manager or SDDM). Other desktops (GNOME, Hyprland, Cosmic,
|
||||
> ...) and other display managers are not supported: the switching between gaming mode
|
||||
> and the desktop, the theme and the shortcuts are all built for Plasma.
|
||||
- Your normal user account, with permission to use `sudo`
|
||||
|
||||
## Installation
|
||||
@@ -83,6 +93,11 @@ Open **Konsole** on your Plasma desktop and run:
|
||||
curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify.sh | bash
|
||||
```
|
||||
|
||||
Installing CachyOS on a Steam Machine? The
|
||||
[Steamify CachyOS ISO](https://github.com/theupriser/steamify-cachyos-live-iso)
|
||||
has Steamify built into the installer: pick the options there, and the
|
||||
first boot is already set up.
|
||||
|
||||
Prefer to look at the script first? Clone the repository and run
|
||||
[`./steamify.sh`](steamify.sh) (keep the whole folder: it needs
|
||||
[`lib/`](lib/)).
|
||||
@@ -125,6 +140,14 @@ steamos-session-select persistent # start where you left off last time
|
||||
steamos-session-select oneshot # always start in gaming mode (default)
|
||||
```
|
||||
|
||||
Where the PC starts after a restart can also be set from a script, once the
|
||||
SteamOS conversion is on (only that changes; `sudo` may ask for your password):
|
||||
|
||||
```bash
|
||||
steamify.sh --boot desktop # start in the desktop from the next boot on
|
||||
steamify.sh --boot gamescope # start in gaming mode again (default)
|
||||
```
|
||||
|
||||
## Something wrong?
|
||||
|
||||
Stuck on a black screen in gaming mode: press **Ctrl+Alt+F3**, log in, and run
|
||||
|
||||
+97
-3
@@ -111,6 +111,9 @@ Turning it off restores `/etc/plasmalogin.conf` from its backup, removes the
|
||||
SDDM autologin, sync bridge, shortcut, sudoers rule and Steam autostart, and
|
||||
switches back to plasma-login-manager.
|
||||
|
||||
The conversion also sets what Steam's System settings show, see
|
||||
[below](#what-steams-system-settings-show).
|
||||
|
||||
**Steam Deck/Machine icons:** `STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"`
|
||||
in `~/.config/environment.d/` (and gamescope-session's own environment
|
||||
file), which makes Steam show Steam Deck button glyphs in gaming mode.
|
||||
@@ -139,6 +142,33 @@ taken from the newest `steamdeck-kde-presets` on Valve's SteamOS mirror
|
||||
Turning it off restores your previous look and panel layout, and removes `cachyos-vapor` again
|
||||
if the wizard installed it (and nothing else, like `cachyos-handheld`, needs it).
|
||||
|
||||
## What Steam's System settings show
|
||||
|
||||
With the SteamOS conversion on, `/etc/os-release` gets:
|
||||
|
||||
| Key | Value | Shown in Steam as |
|
||||
|---|---|---|
|
||||
| `VERSION_ID` | `steamos-3.9`: the newest SteamOS release in Valve's repo (offline: the previous value) | OS Version |
|
||||
| `VERSION_CODENAME` | `steam-machine` | OS Codename |
|
||||
| `VARIANT` / `VARIANT_ID` | `Steamify 2.9.0` / `steamify-2.9.0` | OS Variant (`VARIANT_ID`) |
|
||||
|
||||
The OS name stays CachyOS everywhere: Steam's OS Name comes from
|
||||
`lsb_release -d`, which isn't touched, and `NAME`/`PRETTY_NAME` stay
|
||||
CachyOS's. limine-snapper-sync finds the boot entries by that name, so
|
||||
changing it would break snapshot boot entries; `/etc/default/limine` gets
|
||||
`TARGET_OS_NAME="CachyOS"` as a guard when it has none.
|
||||
|
||||
KDE's About this System would show `VERSION_ID` after the name
|
||||
("CachyOS Linux steamos-3.9"); `UseOSReleaseVersion=true` in
|
||||
`~/.config/kcm-about-distrorc` makes it show `VERSION`, which CachyOS doesn't
|
||||
have, so it keeps saying "CachyOS Linux".
|
||||
|
||||
CachyOS's own hooks (`cachyos-hooks`) reset os-release on updates of
|
||||
`filesystem`; the pacman hook `zz-steamify-os-release` runs after them and
|
||||
sets the keys again (`/usr/local/libexec/steamify-os-release`). The values are
|
||||
refreshed after every Steamify run that changes something. Turning the
|
||||
conversion off removes the hook and runs CachyOS's `cachyos-branding` again.
|
||||
|
||||
## Front LED bar (Steam Machine)
|
||||
|
||||
The **Steam Machine support** component, only shown on Fremont hardware
|
||||
@@ -156,7 +186,14 @@ The **Steam Machine support** component, only shown on Fremont hardware
|
||||
- installs and enables `steamos-manager`, the service Steam in gaming mode
|
||||
uses for hardware settings (fan, performance, and the HDMI-CEC settings
|
||||
when [HDMI-CEC](#hdmi-cec) is on); it recognises the Steam Machine from its
|
||||
DMI data.
|
||||
DMI data;
|
||||
- makes the serial number readable for Steam, which shows it in its System
|
||||
settings (`/etc/tmpfiles.d/steamify-serial.conf`: `product_serial` is
|
||||
root-only by default);
|
||||
- makes Steam's Wi-Fi backend setting work: steamos-manager switches it in
|
||||
`/etc/NetworkManager/conf.d/99-valve-wifi-backend.conf`, which is created
|
||||
with `wifi.backend=wpa_supplicant` (NetworkManager's default) when no
|
||||
backend is set anywhere yet.
|
||||
|
||||
Turning it off removes all of that again (the AUR helper is kept).
|
||||
|
||||
@@ -169,6 +206,34 @@ or upgraded. A newly added kernel doesn't come with its headers, so
|
||||
`ensure-kernel-headers.service` checks at every boot and installs any
|
||||
missing `-headers` package, which makes DKMS build the driver for it.
|
||||
|
||||
## NVIDIA fix for gaming mode
|
||||
|
||||
gamescope drives the display itself through DRM/KMS, which with NVIDIA needs
|
||||
kernel modesetting and the framebuffer driver, and the driver loaded early;
|
||||
without them gaming mode can show a corrupted image. With a supported NVIDIA GPU (RTX 20 series or newer, decided like the VRAM
|
||||
booster does: a card on chwd's legacy lists `/var/lib/chwd/ids/nvidia-*.ids`
|
||||
is older and left alone, `vram_nvidia_legacy_id`; without those lists every
|
||||
card counts) and its driver installed (`lib/nvidia.sh`), the SteamOS conversion adds
|
||||
`nvidia-drm.modeset=1 nvidia-drm.fbdev=1` to the kernel command line (Limine,
|
||||
systemd-boot or GRUB; the file is backed up first) and
|
||||
`/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf` (`MODULES+=(nvidia
|
||||
nvidia_modeset nvidia_uvm nvidia_drm)`), then rebuilds the initramfs and boot
|
||||
entries. The early-load drop-in is only there while every installed kernel has the
|
||||
NVIDIA modules (mkinitcpio fails on a missing module, and `limine-mkinitcpio`
|
||||
then skips that kernel's boot entry, parameters included). That is decided again
|
||||
at every kernel or driver change by a pacman hook
|
||||
(`/etc/pacman.d/hooks/85-steamify-nvidia-initramfs.hook`, after DKMS builds,
|
||||
before the initramfs is built) running `/usr/local/libexec/steamify-nvidia-initramfs`:
|
||||
another kernel without the modules, a failed DKMS build or a downgrade removes
|
||||
the drop-in, and it comes back once every kernel has them again.
|
||||
On Limine the parameters go into the existing `KERNEL_CMDLINE[default]="..."`
|
||||
line: an extra appended `+=` line is pasted into the command line as text.
|
||||
Only what's missing is changed; it applies after a reboot. Turning
|
||||
the conversion off removes both, the hook and its script. `tests/nvidia-test.sh` tests it against a fake GPU
|
||||
and fake boot loader files; `tests/nvidia-hardware-test.sh check|apply|visual` is for a
|
||||
real NVIDIA PC (read-only check, the real apply, and a prompt for whether the picture
|
||||
was clean), and writes `~/steamify-nvidia-report.txt`.
|
||||
|
||||
## HDMI-CEC
|
||||
|
||||
The **HDMI-CEC** item (on every PC; ticked by default only on a Steam
|
||||
@@ -180,7 +245,9 @@ SHA-256 in Valve's package index:
|
||||
- `cecd`, Valve's CEC daemon (a user service started with the desktop and
|
||||
gaming mode): TV remote keys become normal key presses (arrows, Enter,
|
||||
Back), and it turns the TV on and off with the PC;
|
||||
- `cec-audio-control`: volume of the TV or receiver;
|
||||
- `cec-audio-control`: volume of the TV or receiver (the TV remote's volume
|
||||
keys); its user socket is enabled by Steamify, since SteamOS enables it
|
||||
through a preset that pacman doesn't apply;
|
||||
- `inputattach-cec-units` (with `linuxconsole` from CachyOS for
|
||||
`inputattach`): attaches USB CEC adapters (Pulse-Eight, RainShadow).
|
||||
|
||||
@@ -418,6 +485,31 @@ steamos-session-select persistent # remember the last-used session across reboo
|
||||
steamos-session-select oneshot # always start in gamescope (default, like a Deck)
|
||||
```
|
||||
|
||||
`steamify.sh --boot gamescope|desktop` sets where the PC starts after a
|
||||
restart (the menu's Boot into row) from a script: it needs the SteamOS
|
||||
conversion and changes nothing else, not even the updates a normal run would
|
||||
apply. Exit code 1 without the conversion or with another value.
|
||||
|
||||
## Install-time mode (`--defaults`)
|
||||
|
||||
For an installer (the Steam Machine ISO), without a session or prompts
|
||||
(passwordless sudo required):
|
||||
|
||||
```bash
|
||||
steamify.sh --defaults # what the menu would preselect
|
||||
steamify.sh --defaults --options gaming,theme,cec,machine --boot desktop
|
||||
steamify.sh --defaults --list # what --defaults can set up here, as JSON
|
||||
```
|
||||
|
||||
`--options` turns on exactly the listed items (the menu's ids: `gaming`,
|
||||
`theme`, `glyphs`, `single`, `launcher`, `notify`, `vram`, `cec`, `machine`,
|
||||
`poweroff`), everything else off; an item that's on brings its parent
|
||||
(single user the conversion, the power-off fix Steam Machine support). An
|
||||
item this PC can't use (e.g. `vram` without a VRAM region) is left off with
|
||||
a warning. `--boot desktop` needs `gaming`. Unknown options, ids, `boot` or
|
||||
`bios` in the list: exit code 1 before anything changes. What needs a
|
||||
Plasma session waits for the first login (`lib/first-login.sh`).
|
||||
|
||||
With `Relogin=true`, a gamescope session that fails to start is restarted
|
||||
immediately, which can turn into a loop - see
|
||||
[TROUBLESHOOTING.md](TROUBLESHOOTING.md) for the way out.
|
||||
@@ -445,11 +537,13 @@ immediately, which can turn into a loop - see
|
||||
| `lib/fremont-poweroff.sh` | Steam Machine support: the power-off fix (DKMS module from `patches/`) |
|
||||
| `lib/steam-game.sh` | Add as non-Steam game: Steamify in the Steam library (`patches/steam-shortcuts.py`) |
|
||||
| `lib/update-notifier.sh` | Update notifications: the notifier from `patches/` and its user timer |
|
||||
| `lib/first-login.sh` | `--defaults` without a session (the Steam Machine ISO's installer): the one-time first-login step that sets up single user's launcher on Plasma's new layout and opens the app |
|
||||
| `lib/nvidia.sh` | NVIDIA fix for gaming mode: kernel parameters and early modules (part of the SteamOS conversion) |
|
||||
| `lib/vram-booster.sh` | VRAM booster (`dmemcg-booster`, `plasma-foreground-booster`) |
|
||||
| `services/` | The systemd units the scripts install (`service_file`, `@KEY@` placeholders); see its README |
|
||||
| `patches/` | Module sources and patches the scripts build or apply (`patch_file`); see its README |
|
||||
| `.github/tools/bundle.sh` | Builds the single-file version (`dist/steamify.sh`), with `patches/` and `services/` embedded |
|
||||
| `.github/workflows/bundle.yml` | Builds and checks it on every push; publishes it on `main` |
|
||||
| `.github/workflows/bundle.yml` | Builds and checks it on every push (GitHub and a Gitea mirror); publishes it on `main`, and starts the Steamify ISO's release |
|
||||
|
||||
The single-file version is generated: on every push to `main`, GitHub
|
||||
Actions runs `.github/tools/bundle.sh`, checks the result with `bash -n` and
|
||||
|
||||
@@ -18,6 +18,14 @@ restarted right away (`Relogin=true`), which is why it can loop.
|
||||
Run the wizard again and press `a` in the menu to re-apply everything that's
|
||||
on (also useful after a CachyOS update). To undo a part, untick it.
|
||||
|
||||
## "Target OS name ... not found in /boot/limine.conf"
|
||||
|
||||
limine-snapper-sync finds the boot entries by the OS name. Steamify never
|
||||
changes that name (it only adds version keys to `/etc/os-release`), and pins
|
||||
`TARGET_OS_NAME="CachyOS"` in `/etc/default/limine`. If you see this message,
|
||||
check that `PRETTY_NAME` in `/etc/os-release` still says `CachyOS`, or set
|
||||
`TARGET_OS_NAME` in `/etc/default/limine` to the name your boot entries use.
|
||||
|
||||
## The LED bar on the Steam Machine stays dark
|
||||
|
||||
Restart once more; a freshly installed driver often needs a reboot. The menu
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 517 KiB After Width: | Height: | Size: 519 KiB |
@@ -177,6 +177,7 @@ backend_apply() {
|
||||
if backend_run_component "$c" enable; then is_action "$c" || feature_record "$c" enable; else failed+=("$c"); fi
|
||||
done
|
||||
feature_record_unticked
|
||||
os_version_refresh
|
||||
[[ " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " =~ \ (gaming|single|boot|kpin)\ ]] && RESTART_FOR_LOGIN=true
|
||||
backend_event finished "\"failed\":$(json_list "${failed[@]}"),\"restart\":$(restart_needed && echo true || echo false)"
|
||||
}
|
||||
|
||||
+30
-16
@@ -26,6 +26,10 @@ CEC_DKMS_VER=1
|
||||
CEC_DKMS_SRC="/usr/src/$CEC_DKMS_NAME-$CEC_DKMS_VER"
|
||||
CEC_DRIVER_URL="https://raw.githubusercontent.com/evlaV/linux-integration/10c8c8800ccd3ae359203b4eefb6479f613b3b8e/drivers/media/cec/platform/cros-ec/cros-ec-cec.c"
|
||||
CEC_DRIVER_SHA256=e89fd4e87fceb32d713ffc59b64794779b3c2b3c012b0e2f2e9f0c40b42f4373
|
||||
# Downloaded once, then kept: raw.githubusercontent.com rate-limits (HTTP 429) repeated downloads
|
||||
# from one address, and turning CEC off and on again needs no network then. Named after its
|
||||
# checksum, so a new pin (a new commit and checksum above) downloads its file once by itself.
|
||||
CEC_DRIVER_CACHE="/var/cache/steamify/cros-ec-cec-${CEC_DRIVER_SHA256:0:12}.c"
|
||||
|
||||
cec_link_steamos_manager() {
|
||||
# On a Steam Machine: steamos-manager writes cecd's config from Steam's
|
||||
@@ -34,11 +38,11 @@ cec_link_steamos_manager() {
|
||||
# called by Steam Machine support, which installs steamos-manager after
|
||||
# this item ran.
|
||||
pacman -Q steamos-manager >/dev/null 2>&1 || return 0
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable steamos-manager-configure-cecd.service 2>/dev/null
|
||||
systemctl --user start steamos-manager-configure-cecd.service 2>/dev/null
|
||||
systemctl --user restart cecd.service 2>/dev/null
|
||||
systemctl --user restart steamos-manager.service 2>/dev/null
|
||||
user_systemctl daemon-reload
|
||||
user_systemctl enable steamos-manager-configure-cecd.service 2>/dev/null
|
||||
user_systemctl start steamos-manager-configure-cecd.service 2>/dev/null
|
||||
user_systemctl restart cecd.service 2>/dev/null
|
||||
user_systemctl restart steamos-manager.service 2>/dev/null
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -51,10 +55,10 @@ cec_status() { cec_installed && [[ -f "$CEC_STEAM_DROPIN" ]] && cec_driver_ok; }
|
||||
|
||||
cec_reload_driver() {
|
||||
# cecd keeps /dev/cec0 open, so the old module can't be unloaded under it.
|
||||
systemctl --user stop cecd.service 2>/dev/null
|
||||
user_systemctl stop cecd.service 2>/dev/null
|
||||
sudo modprobe -r cros_ec_cec 2>/dev/null
|
||||
sudo modprobe cros_ec_cec 2>/dev/null
|
||||
systemctl --user start cecd.service 2>/dev/null
|
||||
user_systemctl start cecd.service 2>/dev/null
|
||||
}
|
||||
|
||||
cec_driver_enable() {
|
||||
@@ -65,13 +69,20 @@ cec_driver_enable() {
|
||||
fi
|
||||
install_kernel_headers || return 1
|
||||
tmp="$(mktemp -d)"
|
||||
if [[ -f "$CEC_DRIVER_CACHE" ]] && echo "$CEC_DRIVER_SHA256 $CEC_DRIVER_CACHE" | sha256sum -c --quiet - 2>/dev/null; then
|
||||
cp "$CEC_DRIVER_CACHE" "$tmp/cros-ec-cec.c"
|
||||
else
|
||||
info "Downloading Valve's Steam Machine CEC driver..."
|
||||
if ! curl -fsL "$CEC_DRIVER_URL" -o "$tmp/cros-ec-cec.c" ||
|
||||
if ! curl -fsL --retry 2 "$CEC_DRIVER_URL" -o "$tmp/cros-ec-cec.c" ||
|
||||
! echo "$CEC_DRIVER_SHA256 $tmp/cros-ec-cec.c" | sha256sum -c --quiet -; then
|
||||
rm -rf "$tmp"
|
||||
err "Downloading Valve's CEC driver failed (or its checksum didn't match)."
|
||||
return 1
|
||||
fi
|
||||
# The name carries the checksum: a newer pin gets its own file, the old one goes.
|
||||
sudo find "${CEC_DRIVER_CACHE%/*}" -maxdepth 1 -name 'cros-ec-cec-*.c' ! -name "${CEC_DRIVER_CACHE##*/}" -delete 2>/dev/null
|
||||
sudo install -Dm644 "$tmp/cros-ec-cec.c" "$CEC_DRIVER_CACHE"
|
||||
fi
|
||||
# So it finds amdgpu's HDMI port (see the patch for why).
|
||||
patch_file cros-ec-cec-single-port.patch | patch -s -d "$tmp" -p1 ||
|
||||
{ rm -rf "$tmp"; err "Patching Valve's CEC driver failed."; return 1; }
|
||||
@@ -154,10 +165,13 @@ cec_enable() {
|
||||
sudo tee "$CEC_STEAM_ENV" >/dev/null
|
||||
printf '%s\n' "# Written by Steamify: overrides STEAM_ENABLE_CEC=0 from the gaming mode script." \
|
||||
'[Service]' "EnvironmentFile=-$CEC_STEAM_ENV" | sudo tee "$CEC_STEAM_DROPIN" >/dev/null
|
||||
systemctl --user daemon-reload
|
||||
user_systemctl daemon-reload
|
||||
# The TV remote's volume keys: SteamOS enables this socket through its
|
||||
# preset, which pacman doesn't apply, so nothing else does on CachyOS.
|
||||
user_systemctl enable --now cec-audio-control.socket 2>/dev/null
|
||||
cec_link_steamos_manager
|
||||
if compgen -G "/dev/cec*" >/dev/null; then
|
||||
systemctl --user restart cecd.service 2>/dev/null
|
||||
user_systemctl restart cecd.service 2>/dev/null
|
||||
ok "HDMI-CEC on ($(cd /dev && echo cec*)); Steam shows its settings from the next gaming mode start."
|
||||
info "Turn on CEC on your TV too (e.g. Sony: BRAVIA Sync, Samsung: Anynet+, LG: SimpLink)."
|
||||
else
|
||||
@@ -168,20 +182,20 @@ cec_enable() {
|
||||
|
||||
cec_disable() {
|
||||
info "Removing HDMI-CEC..."
|
||||
systemctl --user disable --now cecd.service cec-audio-control.socket cec-audio-control.service 2>/dev/null
|
||||
systemctl --user disable steamos-manager-configure-cecd.service 2>/dev/null
|
||||
user_systemctl disable --now cecd.service cec-audio-control.socket cec-audio-control.service 2>/dev/null
|
||||
user_systemctl disable steamos-manager-configure-cecd.service 2>/dev/null
|
||||
sudo pacman -Rns --noconfirm "${CEC_PKGS[@]}" 2>/dev/null
|
||||
cec_driver_disable
|
||||
sudo rm -f "$CEC_ORDER_DROPIN" "$CEC_STEAM_DROPIN" "$CEC_STEAM_ENV"
|
||||
sudo rmdir "$(dirname "$CEC_ORDER_DROPIN")" "$(dirname "$CEC_STEAM_DROPIN")" "$(dirname "$CEC_STEAM_ENV")" 2>/dev/null
|
||||
systemctl --user daemon-reload
|
||||
user_systemctl daemon-reload
|
||||
if [[ -n "$(state_get cec installed_linuxconsole)" ]]; then
|
||||
sudo pacman -Rns --noconfirm linuxconsole 2>/dev/null
|
||||
state_clear cec
|
||||
fi
|
||||
sudo udevadm control --reload
|
||||
systemctl --user is-active -q steamos-manager.service 2>/dev/null &&
|
||||
systemctl --user restart steamos-manager.service
|
||||
user_systemctl is-active -q steamos-manager.service 2>/dev/null &&
|
||||
user_systemctl restart steamos-manager.service
|
||||
ok "HDMI-CEC removed."
|
||||
}
|
||||
|
||||
@@ -189,5 +203,5 @@ cec_overview() {
|
||||
# For the menu's kernel overview.
|
||||
local dev="none"
|
||||
compgen -G "/dev/cec*" >/dev/null && dev="$(cd /dev && echo cec*)"
|
||||
echo "CEC devices: $dev cecd: $(systemctl --user is-active cecd 2>/dev/null)"
|
||||
echo "CEC devices: $dev cecd: $(user_systemctl is-active cecd 2>/dev/null)"
|
||||
}
|
||||
@@ -44,6 +44,30 @@ require_root_helper() {
|
||||
fi
|
||||
}
|
||||
|
||||
user_session() {
|
||||
# A running user systemd and session bus. Not in the installer's chroot,
|
||||
# where the ISO applies Steamify for a user who has never logged in.
|
||||
[[ -S "${XDG_RUNTIME_DIR:-/nonexistent}/bus" ]]
|
||||
}
|
||||
|
||||
user_systemctl() {
|
||||
# systemctl --user, also without a session: then only the unit files
|
||||
# change (enable/disable through --root); starting and stopping is left
|
||||
# to the first login, which starts what's enabled anyway.
|
||||
if user_session; then systemctl --user "$@"; return; fi
|
||||
local a verb="" args=()
|
||||
for a in "$@"; do
|
||||
[[ "$a" == --now ]] && continue
|
||||
[[ -z "$verb" && "$a" != -* ]] && verb="$a"
|
||||
args+=("$a")
|
||||
done
|
||||
case "$verb" in
|
||||
enable|disable|is-enabled|mask|unmask) systemctl --user --root=/ "${args[@]}" ;;
|
||||
is-active) return 1 ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
plasma_applets() {
|
||||
# Print "containment:applet" for every applet of plugin $1 in the
|
||||
# user's Plasma layout, for kwriteconfig6 --group paths.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
# The ISO applies Steamify in the installer, before the user ever logged
|
||||
# in (steamify.sh --defaults without a session). What needs Plasma's first
|
||||
# layout is finished at the first desktop login, by a one-time autostart
|
||||
# that then opens the app, next to CachyOS Hello.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
FIRST_LOGIN_ENTRY="${XDG_CONFIG_HOME:-$HOME/.config}/autostart/steamify-first-login.desktop"
|
||||
FIRST_LOGIN_SCRIPT="$STEAMIFY_BIN/first-login"
|
||||
|
||||
first_login_schedule() {
|
||||
install_executable "$FIRST_LOGIN_SCRIPT" 755 << EOF2
|
||||
#!/bin/bash
|
||||
# Installed by Steamify CachyOS: runs once, at the first desktop login.
|
||||
set -o pipefail
|
||||
curl -fsSL --max-time 30 "$WIZARD_URL" | bash -s -- --first-login
|
||||
rm -f "$FIRST_LOGIN_ENTRY" "\$0"
|
||||
[[ -x "$WIZARD_APP_LAUNCHER" ]] && exec "$WIZARD_APP_LAUNCHER"
|
||||
EOF2
|
||||
printf '%s\n' '[Desktop Entry]' 'Type=Application' 'Name=Steamify first login' \
|
||||
"Exec=$FIRST_LOGIN_SCRIPT" 'OnlyShowIn=KDE;' 'X-KDE-autostart-phase=2' 'NoDisplay=true' |
|
||||
install_executable "$FIRST_LOGIN_ENTRY" 644
|
||||
}
|
||||
|
||||
first_login_run() {
|
||||
# plasmashell has just laid out the desktop from the look-and-feel
|
||||
# package; wait for its config, then put single user's launcher
|
||||
# settings on the new launcher.
|
||||
local _
|
||||
for _ in $(seq 30); do
|
||||
[[ -n "$(plasma_applets org.kde.plasma.kickoff)" ]] && break
|
||||
sleep 2
|
||||
done
|
||||
if single_status; then
|
||||
stop_plasmashell_for_edit
|
||||
single_launcher
|
||||
restart_plasmashell_if_stopped
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
@@ -18,6 +18,78 @@ gaming_status() {
|
||||
esac
|
||||
}
|
||||
|
||||
# What Steam shows in its System settings besides the OS name (which stays
|
||||
# CachyOS's, for legal clarity and because limine-snapper-sync finds the boot
|
||||
# entries by it): the SteamOS release as the OS version, steam-machine as the
|
||||
# codename, Steamify with its version as the variant (os-release VERSION_ID,
|
||||
# VERSION_CODENAME, VARIANT_ID; see patches/steamify-os-release.sh).
|
||||
OS_NAME_SCRIPT=/usr/local/libexec/steamify-os-release
|
||||
OS_NAME_HOOK=/etc/pacman.d/hooks/zz-steamify-os-release.hook
|
||||
# limine's tools take the OS name from TARGET_OS_NAME, else os-release's
|
||||
# PRETTY_NAME: pinned to CachyOS, the boot entries never depend on os-release.
|
||||
LIMINE_DEFAULTS=/etc/default/limine
|
||||
|
||||
steamos_release() {
|
||||
# The SteamOS release Steamify follows: Valve's newest jupiter-X.Y repo
|
||||
# (where the SteamOS extras come from), as an os-release ID (no spaces or
|
||||
# capitals: steamos-3.9). Offline (e.g. in the installer): the one set
|
||||
# before, if any.
|
||||
local v
|
||||
v="$(curl -fsL --max-time 15 "$VALVE_MIRROR/" 2>/dev/null | grep -oE 'jupiter-[0-9]+\.[0-9]+/' | tr -d / | sort -V | tail -n 1)"
|
||||
if [[ -n "$v" ]]; then echo "steamos-${v#jupiter-}"
|
||||
else sed -n 's/^VERSION_ID=\(steamos-.*\)$/\1/p' /etc/os-release 2>/dev/null; fi
|
||||
}
|
||||
|
||||
os_name_enable() {
|
||||
# 2.9.0 pre-releases renamed the OS itself; the name stays CachyOS's.
|
||||
if grep -q '^DISTRIB_DESCRIPTION=.*with Steamify' /etc/lsb-release 2>/dev/null &&
|
||||
[[ -x /usr/share/libalpm/scripts/cachyos-branding ]]; then
|
||||
sudo /usr/share/libalpm/scripts/cachyos-branding lsb-release
|
||||
fi
|
||||
[[ -n "$(kreadconfig6 --file kcm-about-distrorc --group General --key Name 2>/dev/null)" ]] &&
|
||||
kset gaming kcm-about-distrorc General Name --delete
|
||||
# About this System: os-release's VERSION (CachyOS has none) instead of
|
||||
# VERSION_ID, which is the SteamOS release now.
|
||||
kset gaming kcm-about-distrorc General UseOSReleaseVersion true
|
||||
patch_file steamify-os-release.sh | fill VERSION="$VERSION" STEAMOS="$(steamos_release)" |
|
||||
sudo install -Dm755 /dev/stdin "$OS_NAME_SCRIPT" &&
|
||||
patch_file steamify-os-release.hook | fill SCRIPT="$OS_NAME_SCRIPT" |
|
||||
sudo install -Dm644 /dev/stdin "$OS_NAME_HOOK" &&
|
||||
sudo "$OS_NAME_SCRIPT" || { err "Setting Steamify's version for Steam failed."; return 1; }
|
||||
if [[ -f "$LIMINE_DEFAULTS" ]] && ! grep -q '^TARGET_OS_NAME=' "$LIMINE_DEFAULTS"; then
|
||||
backup_file "$LIMINE_DEFAULTS"
|
||||
printf '%s\n' 'TARGET_OS_NAME="CachyOS"' | sudo tee -a "$LIMINE_DEFAULTS" > /dev/null
|
||||
state_set gaming limine_target 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
os_name_disable() {
|
||||
sudo rm -f "$OS_NAME_HOOK" "$OS_NAME_SCRIPT"
|
||||
[[ -f /etc/os-release ]] && sudo sed -i -e '/^VARIANT=/d' -e '/^VARIANT_ID=/d' -e '/^VERSION_ID=/d' -e '/^VERSION_CODENAME=/d' /etc/os-release
|
||||
# CachyOS's own values back, the way its hooks write them.
|
||||
if [[ -x /usr/share/libalpm/scripts/cachyos-branding ]]; then
|
||||
sudo /usr/share/libalpm/scripts/cachyos-branding os-release
|
||||
# Undoes 2.9.0 pre-releases, which changed lsb-release's name too.
|
||||
sudo /usr/share/libalpm/scripts/cachyos-branding lsb-release
|
||||
fi
|
||||
if [[ -n "$(state_get gaming limine_target)" ]]; then
|
||||
sudo sed -i '/^TARGET_OS_NAME="CachyOS"$/d' "$LIMINE_DEFAULTS"
|
||||
state_set gaming limine_target ""
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
os_version_refresh() {
|
||||
# After every run that changed something (sudo is at hand then): Steam's
|
||||
# OS version follows Steamify's, not just the one that set it up. Silent:
|
||||
# the app reads the backend's stdout as JSON.
|
||||
gaming_status 2>/dev/null || return 0
|
||||
grep -qx "VARIANT_ID=steamify-$VERSION" /etc/os-release 2>/dev/null && return 0
|
||||
os_name_enable > /dev/null 2>&1
|
||||
return 0
|
||||
}
|
||||
|
||||
gaming_enable() {
|
||||
# LOGIN_MANAGER (sddm with single user, else plasmalogin) is set by the
|
||||
# menu. Re-running with the other value switches over cleanly.
|
||||
@@ -37,6 +109,8 @@ gaming_enable() {
|
||||
esac
|
||||
create_desktop_shortcut
|
||||
steam_enable
|
||||
nvidia_enable || return 1
|
||||
os_name_enable || return 1
|
||||
}
|
||||
|
||||
gaming_disable() {
|
||||
@@ -49,6 +123,9 @@ gaming_disable() {
|
||||
switch_to_plasmalogin
|
||||
remove_desktop_shortcut
|
||||
steam_disable
|
||||
krevert gaming
|
||||
os_name_disable
|
||||
nvidia_disable
|
||||
ok "The PC boots to the normal login screen again (from the next boot)."
|
||||
}
|
||||
|
||||
|
||||
+85
-2
@@ -25,8 +25,8 @@ NO_PRESELECT=(boot cec kpin hdmi)
|
||||
# FEATURE_BASELINE.
|
||||
FEATURE_BASELINE=2.1.0
|
||||
declare -A FEATURE_VERSION=(
|
||||
[gaming]=2.1.0 [boot]=2.1.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0
|
||||
[launcher]=2.1.0 [cec]=2.1.0 [machine]=2.2.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1
|
||||
[gaming]=2.9.7 [boot]=2.1.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0
|
||||
[launcher]=2.1.0 [cec]=2.7.0 [machine]=2.9.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1
|
||||
[kpin]=2.1.0 [hdmi]=2.1.0
|
||||
)
|
||||
|
||||
@@ -179,6 +179,88 @@ detect_components() {
|
||||
fi
|
||||
}
|
||||
|
||||
defaults_options() {
|
||||
# defaults_options [--options <id>[,<id>...]] [--boot gamescope|desktop]:
|
||||
# what --defaults sets up, from the Steam Machine ISO's installer page.
|
||||
# --options: exactly these items on, every other off (without it, the
|
||||
# menu's preselection). An item that's on brings its parent (single user
|
||||
# the conversion, like ticking it in the menu); one this PC can't use is
|
||||
# left off with a warning. --boot desktop needs the conversion. Returns 1
|
||||
# on an unknown option, item or value.
|
||||
local c ids list=false boot=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
# Both take a value: without one, shift 2 fails and never shifts, so
|
||||
# the loop would spin forever.
|
||||
[[ "$1" == --options || "$1" == --boot ]] && [[ $# -lt 2 ]] && { err "$1 needs a value"; return 1; }
|
||||
case "$1" in
|
||||
--options)
|
||||
list=true
|
||||
IFS=, read -ra ids <<< "$2"
|
||||
shift 2 ;;
|
||||
--boot)
|
||||
case "$2" in
|
||||
gamescope|desktop) boot="$2" ;;
|
||||
*) err "--boot takes gamescope or desktop"; return 1 ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
*) err "Unknown option: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
if [[ "$list" == true ]]; then
|
||||
for c in "${ids[@]}"; do
|
||||
[[ -n "$c" ]] || continue
|
||||
[[ -n "${LABEL[$c]:-}" ]] || { err "Unknown item: $c"; return 1; }
|
||||
[[ "$c" == boot ]] && { err "Where to start is --boot, not an item."; return 1; }
|
||||
is_action "$c" && { err "$c can't be part of the install."; return 1; }
|
||||
done
|
||||
for c in "${COMPONENTS[@]}"; do WANTED[$c]=0; done
|
||||
for c in "${ids[@]}"; do
|
||||
[[ -n "$c" ]] || continue
|
||||
if component_available "$c" && component_selectable "$c"; then
|
||||
WANTED[$c]=1
|
||||
else
|
||||
warn "Leaving out ${LABEL[$c]%%:*}: not available on this PC."
|
||||
fi
|
||||
done
|
||||
[[ "${WANTED[single]}" == 1 ]] && WANTED[gaming]=1
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
[[ "${WANTED[$c]}" == 1 && -n "${PARENT[$c]:-}" ]] && WANTED[${PARENT[$c]}]=1
|
||||
done
|
||||
fi
|
||||
case "$boot" in
|
||||
desktop)
|
||||
[[ "${WANTED[gaming]}" == 1 ]] || { err "--boot desktop needs the SteamOS conversion (gaming)."; return 1; }
|
||||
WANTED[boot]=1 ;;
|
||||
gamescope) WANTED[boot]=0 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
defaults_list() {
|
||||
# --defaults --list: what --defaults can set up on this PC, as one JSON
|
||||
# array, for an installer page (the Steam Machine ISO builds its Steamify
|
||||
# page from it, so new items show up without a new ISO). Per item: id,
|
||||
# label, hint, kind (toggle, or choice for boot: on = desktop), parent,
|
||||
# on (preselected like a first run) and selectable. Actions, retired
|
||||
# items and items this PC can't use (e.g. no Steam account yet) are
|
||||
# left out. Read-only: no sudo, no state.
|
||||
local c kind on sel items=""
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
component_available "$c" || continue
|
||||
is_action "$c" && continue
|
||||
[[ "$c" == kpin || "$c" == hdmi ]] && continue
|
||||
kind=toggle; [[ "$c" == boot ]] && kind=choice
|
||||
sel=false; component_selectable "$c" && sel=true
|
||||
on=false
|
||||
[[ "$sel" == true && " ${NO_PRESELECT[*]} " != *" $c "* ]] && on=true
|
||||
[[ "$c" == cec ]] && machine_available && on=true
|
||||
items+="${items:+,}{\"id\":$(json_str "$c"),\"label\":$(json_str "${LABEL[$c]%%:*}")"
|
||||
items+=",\"hint\":$(json_str "$( [[ "${LABEL[$c]}" == *:* ]] && echo "${LABEL[$c]#*: }")")"
|
||||
items+=",\"kind\":\"$kind\",\"parent\":$(json_str "${PARENT[$c]:-}"),\"on\":$on,\"selectable\":$sel}"
|
||||
done
|
||||
printf '[%s]\n' "$items"
|
||||
}
|
||||
|
||||
toggle_component() {
|
||||
local c="$1"
|
||||
component_selectable "$c" || return 1
|
||||
@@ -383,5 +465,6 @@ apply_changes() {
|
||||
if "${c}_enable"; then is_action "$c" || feature_record "$c" enable; else failed+=("$c"); fi
|
||||
done
|
||||
feature_record_unticked
|
||||
os_version_refresh
|
||||
FAILED=("${failed[@]}")
|
||||
}
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
#!/bin/bash
|
||||
# NVIDIA fix for gaming mode, part of the SteamOS conversion
|
||||
# (gaming_enable/gaming_disable). gamescope drives the display itself
|
||||
# through DRM/KMS; with NVIDIA that needs kernel modesetting and the
|
||||
# framebuffer driver (nvidia-drm.modeset=1 nvidia-drm.fbdev=1) and the
|
||||
# driver in the initramfs, or the screen shows a corrupted image.
|
||||
# Does nothing without a supported NVIDIA GPU (RTX 20 series or newer) that has
|
||||
# its driver installed.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
NVIDIA_PARAMS="nvidia-drm.modeset=1 nvidia-drm.fbdev=1"
|
||||
NVIDIA_INITRAMFS_CONF=/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf
|
||||
# The script and pacman hook that keep the initramfs file right at every kernel change.
|
||||
NVIDIA_SCRIPT=${NVIDIA_SCRIPT:-/usr/local/libexec/steamify-nvidia-initramfs}
|
||||
NVIDIA_HOOK=${NVIDIA_HOOK:-/etc/pacman.d/hooks/85-steamify-nvidia-initramfs.hook}
|
||||
# The DRM devices in sysfs; the tests point this at a fake tree.
|
||||
NVIDIA_DRM_DIR=${NVIDIA_DRM_DIR:-/sys/class/drm}
|
||||
|
||||
nvidia_present() {
|
||||
# A supported NVIDIA GPU: PCI vendor 0x10de, display class, its kernel
|
||||
# driver installed, and not older than the RTX 20 series, decided like the
|
||||
# VRAM booster does (vram_nvidia_legacy_id: chwd's legacy card lists, every
|
||||
# other card runs NVIDIA's open modules). Older cards are left alone.
|
||||
local d
|
||||
for d in "$NVIDIA_DRM_DIR"/card[0-9]*/device; do
|
||||
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de ]] || continue
|
||||
[[ "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
|
||||
vram_nvidia_legacy_id "$(cat "$d/device" 2>/dev/null)" && continue
|
||||
modinfo nvidia_drm >/dev/null 2>&1 && return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
nvidia_legacy_gpu() {
|
||||
# 0 when the only NVIDIA GPU(s) are older than RTX 20 (reported, not fixed).
|
||||
local d found=0
|
||||
for d in "$NVIDIA_DRM_DIR"/card[0-9]*/device; do
|
||||
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de && "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
|
||||
vram_nvidia_legacy_id "$(cat "$d/device" 2>/dev/null)" || return 1
|
||||
found=1
|
||||
done
|
||||
[[ $found == 1 ]]
|
||||
}
|
||||
|
||||
nvidia_boot_file() {
|
||||
# Same boot loaders as the kernel command line elsewhere (lib/hdmi-refresh.sh).
|
||||
hdmi_boot_file
|
||||
}
|
||||
|
||||
nvidia_param_set() {
|
||||
# 0 when $1 (e.g. nvidia-drm.modeset=1) is on the kernel command line or
|
||||
# already in the boot loader's file (not booted yet).
|
||||
local f; f="$(nvidia_boot_file)"
|
||||
grep -qw -- "$1" /proc/cmdline 2>/dev/null ||
|
||||
{ [[ -n "$f" ]] && grep -qw -- "$1" "$f" 2>/dev/null; }
|
||||
}
|
||||
|
||||
nvidia_params_missing() {
|
||||
local p
|
||||
for p in $NVIDIA_PARAMS; do nvidia_param_set "$p" || return 0; done
|
||||
return 1
|
||||
}
|
||||
|
||||
nvidia_initramfs_ok() {
|
||||
[[ -f "$NVIDIA_INITRAMFS_CONF" ]] || grep -qE '^MODULES=.*nvidia_drm' /etc/mkinitcpio.conf 2>/dev/null
|
||||
}
|
||||
|
||||
nvidia_modules_everywhere() {
|
||||
# 0 when every installed kernel has the nvidia_drm module (the script's own check).
|
||||
patch_file steamify-nvidia-initramfs.sh | NVIDIA_MODULES_DIR="${NVIDIA_MODULES_DIR:-/usr/lib/modules}" bash -s check
|
||||
}
|
||||
|
||||
nvidia_hook_install() {
|
||||
# Never installs an empty script or hook (a piped patch_file that failed
|
||||
# still lets install succeed with no input).
|
||||
local script hook
|
||||
script="$(patch_file steamify-nvidia-initramfs.sh)" && [[ -n "$script" ]] &&
|
||||
hook="$(patch_file steamify-nvidia-initramfs.hook | fill SCRIPT="$NVIDIA_SCRIPT")" && [[ -n "$hook" ]] || return 1
|
||||
printf '%s\n' "$script" | sudo install -Dm755 /dev/stdin "$NVIDIA_SCRIPT" &&
|
||||
printf '%s\n' "$hook" | sudo install -Dm644 /dev/stdin "$NVIDIA_HOOK"
|
||||
}
|
||||
|
||||
nvidia_rebuild_boot() {
|
||||
local f; f="$(nvidia_boot_file)"
|
||||
info "Rebuilding the initramfs and boot entries..."
|
||||
case "$f" in
|
||||
/etc/default/limine) sudo limine-mkinitcpio ;;
|
||||
/etc/sdboot-manage.conf) sudo /usr/bin/mkinitcpio -P && sudo sdboot-manage gen ;;
|
||||
/etc/default/grub) sudo /usr/bin/mkinitcpio -P && sudo grub-mkconfig -o /boot/grub/grub.cfg ;;
|
||||
*) sudo /usr/bin/mkinitcpio -P ;;
|
||||
esac
|
||||
}
|
||||
|
||||
nvidia_boot_has_params() {
|
||||
# 0 when the generated boot entries carry the parameters (or can't be
|
||||
# checked): limine.conf, systemd-boot's entries, grub.cfg.
|
||||
local target
|
||||
case "$1" in
|
||||
*/limine) target="${NVIDIA_LIMINE_CONF:-/boot/limine.conf}" ;;
|
||||
*/sdboot-manage.conf) target="${NVIDIA_SDBOOT_DIR:-/boot/loader/entries}" ;;
|
||||
*/grub) target="${NVIDIA_GRUB_CFG:-/boot/grub/grub.cfg}" ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
sudo test -e "$target" || return 0
|
||||
sudo grep -rqs 'nvidia-drm.modeset=1' "$target"
|
||||
}
|
||||
|
||||
nvidia_enable() {
|
||||
nvidia_present || return 0
|
||||
local f changed=0 p; f="$(nvidia_boot_file)"
|
||||
if nvidia_params_missing; then
|
||||
if [[ -z "$f" ]]; then
|
||||
warn "NVIDIA GPU found, but no supported boot loader: add '$NVIDIA_PARAMS' to the kernel command line yourself."
|
||||
else
|
||||
info "NVIDIA GPU found: adding $NVIDIA_PARAMS to the kernel command line (fixes a corrupted screen in gaming mode)..."
|
||||
backup_file "$f"
|
||||
case "$f" in
|
||||
*/limine)
|
||||
sudo sed -i -E "s/^(KERNEL_CMDLINE\[default\]=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
|
||||
*/sdboot-manage.conf)
|
||||
sudo sed -i -E "s/^(LINUX_OPTIONS=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
|
||||
*/grub)
|
||||
sudo sed -i -E "s/^(GRUB_CMDLINE_LINUX_DEFAULT=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
|
||||
esac
|
||||
if ! grep -q "nvidia-drm.fbdev=1" "$f"; then
|
||||
err "Couldn't add the NVIDIA parameters to $f (no kernel command line setting in it): add '$NVIDIA_PARAMS' yourself."
|
||||
return 1
|
||||
fi
|
||||
changed=1
|
||||
fi
|
||||
fi
|
||||
nvidia_hook_install || { err "Installing the NVIDIA initramfs hook failed."; return 1; }
|
||||
local had=0; [[ -f "$NVIDIA_INITRAMFS_CONF" ]] && had=1
|
||||
sudo env NVIDIA_INITRAMFS_CONF="$NVIDIA_INITRAMFS_CONF" NVIDIA_MODULES_DIR="${NVIDIA_MODULES_DIR:-/usr/lib/modules}" "$NVIDIA_SCRIPT" sync
|
||||
if [[ -f "$NVIDIA_INITRAMFS_CONF" && $had == 0 ]]; then
|
||||
info "Loading the NVIDIA modules early (initramfs)..."
|
||||
changed=1
|
||||
elif [[ ! -f "$NVIDIA_INITRAMFS_CONF" && $had == 1 ]]; then
|
||||
warn "A kernel without the NVIDIA modules is installed: not loading them early any more (rebuilding the initramfs without them)."
|
||||
changed=1
|
||||
elif [[ ! -f "$NVIDIA_INITRAMFS_CONF" ]] && ! nvidia_initramfs_ok; then
|
||||
warn "Not every installed kernel has the NVIDIA modules: not loading them early for now (the kernel parameters still apply; this is checked again at every kernel update)."
|
||||
fi
|
||||
if [[ $changed == 1 ]]; then
|
||||
nvidia_rebuild_boot || { err "Rebuilding the boot entries failed."; return 1; }
|
||||
if ! nvidia_boot_has_params "$f"; then
|
||||
err "The boot entries don't have the NVIDIA parameters: the initramfs or boot entry build failed (see above)."
|
||||
return 1
|
||||
fi
|
||||
ok "NVIDIA gaming mode fix applied; it takes effect after a reboot."
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
nvidia_disable() {
|
||||
local f changed=0; f="$(nvidia_boot_file)"
|
||||
if [[ -n "$f" ]] && grep -q "$NVIDIA_PARAMS" "$f" 2>/dev/null; then
|
||||
sudo sed -i "s/ \?$NVIDIA_PARAMS//" "$f"
|
||||
changed=1
|
||||
fi
|
||||
[[ -f "$NVIDIA_INITRAMFS_CONF" ]] && { sudo rm -f "$NVIDIA_INITRAMFS_CONF"; changed=1; }
|
||||
sudo rm -f "$NVIDIA_HOOK" "$NVIDIA_SCRIPT"
|
||||
[[ $changed == 1 ]] && nvidia_rebuild_boot
|
||||
return 0
|
||||
}
|
||||
@@ -101,6 +101,24 @@ single_launcher() {
|
||||
done
|
||||
}
|
||||
|
||||
single_launcher_drop() {
|
||||
# The theme's layout backup is taken when it's turned on: with single
|
||||
# user on then, it holds single's launcher keys, and restoring it after
|
||||
# single was turned off brings them back. Drop exactly single's values
|
||||
# (a launcher set up differently by the user is left alone).
|
||||
local applet
|
||||
local -a kick_args
|
||||
for applet in $(plasma_applets org.kde.plasma.kickoff); do
|
||||
kick_args=(--file plasma-org.kde.plasma.desktop-appletsrc --group Containments --group "${applet%%:*}"
|
||||
--group Applets --group "${applet#*:}" --group Configuration --group General)
|
||||
[[ "$(kreadconfig6 "${kick_args[@]}" --key primaryActions)" == 3 ]] &&
|
||||
kwriteconfig6 "${kick_args[@]}" --key primaryActions --delete
|
||||
[[ "$(kreadconfig6 "${kick_args[@]}" --key systemFavorites)" == 'suspend,reboot,shutdown' ]] &&
|
||||
kwriteconfig6 "${kick_args[@]}" --key systemFavorites --delete
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
single_enable() {
|
||||
info "Turning off the lock screen, user switching and logging out..."
|
||||
stop_plasmashell_for_edit
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ migrate_layout() {
|
||||
"$(wizard_desktop_dir)/$WIZARD_DESKTOP_NAME"; do
|
||||
[[ -f "$f" ]] && sed -i "s|$old_bin/|$STEAMIFY_BIN/|g" "$f"
|
||||
done
|
||||
systemctl --user daemon-reload 2>/dev/null
|
||||
user_systemctl daemon-reload 2>/dev/null
|
||||
fi
|
||||
if [[ -f "$old_icon" ]]; then
|
||||
if [[ -e "$WIZARD_ICON" ]]; then rm -f "$old_icon"; else mv "$old_icon" "$WIZARD_ICON"; fi
|
||||
|
||||
@@ -22,18 +22,18 @@ steam_enable() {
|
||||
rm -f "$HOME/.config/autostart/steam.desktop"
|
||||
|
||||
# Reload user systemd context and activate the background loop
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable --now steam-desktop-autostart.service
|
||||
user_systemctl daemon-reload
|
||||
user_systemctl enable --now steam-desktop-autostart.service
|
||||
|
||||
ok "Steam UI parameters and keyboard autostart deployed successfully."
|
||||
}
|
||||
|
||||
steam_disable() {
|
||||
info "Removing Steam desktop autostart..."
|
||||
systemctl --user disable --now steam-desktop-autostart.service 2>/dev/null
|
||||
user_systemctl disable --now steam-desktop-autostart.service 2>/dev/null
|
||||
rm -f "$HOME/.config/systemd/user/steam-desktop-autostart.service" \
|
||||
"$HOME/.config/environment.d/99-kde-virtual-keyboard.conf"
|
||||
systemctl --user daemon-reload
|
||||
user_systemctl daemon-reload
|
||||
ok "Steam desktop settings removed (takes full effect at next login)."
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -72,8 +72,8 @@ steamgame_edit() {
|
||||
fi
|
||||
"$1"; local rc=$?
|
||||
if [[ "$was_running" == true ]]; then
|
||||
if systemctl --user is-enabled -q steam-desktop-autostart.service 2>/dev/null; then
|
||||
systemctl --user start steam-desktop-autostart.service
|
||||
if user_systemctl is-enabled -q steam-desktop-autostart.service 2>/dev/null; then
|
||||
user_systemctl start steam-desktop-autostart.service
|
||||
else
|
||||
systemd-run --user --collect -q steam -silent >/dev/null 2>&1
|
||||
fi
|
||||
|
||||
+46
-2
@@ -378,6 +378,46 @@ machine_status() {
|
||||
pacman -Qi leds-valve-dkms-git >/dev/null 2>&1 && pacman -Qi steamos-manager >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Steam (steamwebhelper) reads the serial number for its System settings
|
||||
# straight from DMI, which the kernel makes root-only; SteamOS makes it
|
||||
# readable. A tmpfiles rule does that at every boot.
|
||||
SERIAL_TMPFILES=/etc/tmpfiles.d/steamify-serial.conf
|
||||
|
||||
# Steam's Wi-Fi backend switch goes through steamos-manager, which reads and
|
||||
# writes the backend in this file (SteamOS ships it); without it, it fails
|
||||
# with "Wi-Fi backend not found in config". wpa_supplicant is what
|
||||
# NetworkManager uses on CachyOS anyway. Not written when someone set a
|
||||
# backend themselves.
|
||||
WIFI_BACKEND_CONF=/etc/NetworkManager/conf.d/99-valve-wifi-backend.conf
|
||||
|
||||
wifi_backend_enable() {
|
||||
[[ -f "$WIFI_BACKEND_CONF" ]] && return 0
|
||||
grep -rqs '^wifi.backend=' /etc/NetworkManager/NetworkManager.conf /etc/NetworkManager/conf.d && return 0
|
||||
printf '%s\n' "# Written by Steamify: Steam's Wi-Fi backend setting (steamos-manager)." \
|
||||
'[device]' 'wifi.backend=wpa_supplicant' | sudo install -Dm644 /dev/stdin "$WIFI_BACKEND_CONF" ||
|
||||
{ err "Writing the Wi-Fi backend setting failed."; return 1; }
|
||||
state_set machine wifi_backend 1
|
||||
}
|
||||
|
||||
wifi_backend_disable() {
|
||||
[[ -n "$(state_get machine wifi_backend)" ]] || return 0
|
||||
sudo rm -f "$WIFI_BACKEND_CONF"
|
||||
state_clear machine
|
||||
}
|
||||
|
||||
serial_enable() {
|
||||
printf '%s\n' "# Written by Steamify: Steam shows the serial number, like on SteamOS." \
|
||||
'z /sys/class/dmi/id/product_serial 0444 - - -' | sudo tee "$SERIAL_TMPFILES" > /dev/null &&
|
||||
sudo systemd-tmpfiles --create "$SERIAL_TMPFILES" ||
|
||||
{ err "Making the serial number readable for Steam failed."; return 1; }
|
||||
}
|
||||
|
||||
serial_disable() {
|
||||
sudo rm -f "$SERIAL_TMPFILES"
|
||||
sudo chmod 0400 /sys/class/dmi/id/product_serial 2>/dev/null
|
||||
return 0
|
||||
}
|
||||
|
||||
machine_enable() {
|
||||
# The pinned kernel first when it's wanted too, so DKMS builds the LED
|
||||
# driver for it once, instead of for the current kernel and then again.
|
||||
@@ -403,9 +443,11 @@ EOF
|
||||
# for hardware and controller settings; it knows the Steam Machine from its DMI data.
|
||||
info "Installing hardware manager packages (steamos-manager & inputplumber)..."
|
||||
sudo pacman -S --needed --noconfirm steamos-manager inputplumber || { err "Installing hardware manager packages failed."; return 1; }
|
||||
serial_enable || return 1
|
||||
wifi_backend_enable || return 1
|
||||
sudo systemctl enable --now inputplumber.service
|
||||
sudo systemctl enable --now steamos-manager.service
|
||||
systemctl --user enable steamos-manager.service 2>/dev/null
|
||||
user_systemctl enable steamos-manager.service 2>/dev/null
|
||||
# HDMI-CEC ran before this and couldn't link cecd to steamos-manager yet.
|
||||
cec_status && cec_link_steamos_manager
|
||||
|
||||
@@ -422,10 +464,12 @@ EOF
|
||||
|
||||
machine_disable() {
|
||||
info "Removing Steam Machine support..."
|
||||
systemctl --user disable --now steamos-manager.service 2>/dev/null
|
||||
user_systemctl disable --now steamos-manager.service 2>/dev/null
|
||||
sudo systemctl disable --now steamos-manager.service 2>/dev/null
|
||||
sudo systemctl disable --now inputplumber.service 2>/dev/null
|
||||
sudo pacman -Rns --noconfirm steamos-manager inputplumber 2>/dev/null
|
||||
serial_disable
|
||||
wifi_backend_disable
|
||||
sudo rm -f "$LED_UDEV_RULE" /etc/modules-load.d/leds-valve.conf
|
||||
sudo udevadm control --reload
|
||||
sudo modprobe -r leds-valve 2>/dev/null
|
||||
|
||||
@@ -12,8 +12,8 @@ NOTIFY_NAME=steamify-update-check
|
||||
|
||||
notify_status() {
|
||||
[[ -f "$NOTIFY_SCRIPT" ]] &&
|
||||
systemctl --user is-enabled -q "$NOTIFY_NAME.timer" 2>/dev/null &&
|
||||
systemctl --user is-enabled -q "$NOTIFY_NAME.service" 2>/dev/null
|
||||
user_systemctl is-enabled -q "$NOTIFY_NAME.timer" 2>/dev/null &&
|
||||
user_systemctl is-enabled -q "$NOTIFY_NAME.service" 2>/dev/null
|
||||
}
|
||||
|
||||
notify_seen() {
|
||||
@@ -40,19 +40,19 @@ notify_enable() {
|
||||
mkdir -p "$NOTIFY_UNITS"
|
||||
service_file "$NOTIFY_NAME.service" NOTIFY_SCRIPT="$NOTIFY_SCRIPT" > "$NOTIFY_UNITS/$NOTIFY_NAME.service"
|
||||
service_file "$NOTIFY_NAME.timer" > "$NOTIFY_UNITS/$NOTIFY_NAME.timer"
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable "$NOTIFY_NAME.service" >/dev/null 2>&1 &&
|
||||
systemctl --user enable --now "$NOTIFY_NAME.timer" >/dev/null 2>&1 ||
|
||||
user_systemctl daemon-reload
|
||||
user_systemctl enable "$NOTIFY_NAME.service" >/dev/null 2>&1 &&
|
||||
user_systemctl enable --now "$NOTIFY_NAME.timer" >/dev/null 2>&1 ||
|
||||
{ err "Enabling the update check failed."; return 1; }
|
||||
state_set notify seen "$VERSION"
|
||||
ok "Update notifications on: you'll get a notification when there's a new Steamify."
|
||||
}
|
||||
|
||||
notify_disable() {
|
||||
systemctl --user disable --now "$NOTIFY_NAME.timer" "$NOTIFY_NAME.service" >/dev/null 2>&1
|
||||
user_systemctl disable --now "$NOTIFY_NAME.timer" "$NOTIFY_NAME.service" >/dev/null 2>&1
|
||||
rm -f "$NOTIFY_UNITS/$NOTIFY_NAME.service" "$NOTIFY_UNITS/$NOTIFY_NAME.timer" "$NOTIFY_SCRIPT"
|
||||
rmdir "$STEAMIFY_BIN" 2>/dev/null || true
|
||||
systemctl --user daemon-reload
|
||||
user_systemctl daemon-reload
|
||||
state_clear notify
|
||||
ok "Update notifications off."
|
||||
}
|
||||
+19
-1
@@ -54,10 +54,18 @@ theme_enable() {
|
||||
# Only remove it again on disable if we were the ones installing it.
|
||||
state_set theme installed_pkg 1
|
||||
fi
|
||||
# Without a session (the ISO's installer), for a user who has never
|
||||
# logged in: the layout still CachyOS's default from /etc/skel is
|
||||
# removed (after the backup below), and Plasma builds its first layout
|
||||
# from the look-and-feel package, as --resetLayout does below.
|
||||
local offline=false layout=~/.config/plasma-org.kde.plasma.desktop-appletsrc
|
||||
if [[ -z "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]]; then
|
||||
if [[ -e "$layout" ]] && ! cmp -s "$layout" "/etc/skel/.config/${layout##*/}"; then
|
||||
err "Run this from the Plasma desktop: applying the Vapor layout needs a running Plasma session."
|
||||
return 1
|
||||
fi
|
||||
offline=true
|
||||
fi
|
||||
|
||||
# Only the first time, so a re-apply doesn't overwrite the originals.
|
||||
local backup="$STATE_DIR/theme-layout" f
|
||||
@@ -87,6 +95,12 @@ theme_enable() {
|
||||
kset theme kdeglobals General ColorScheme --delete
|
||||
plasma-apply-colorscheme Vapor >/dev/null 2>&1 || true
|
||||
|
||||
if [[ "$offline" == true ]]; then
|
||||
rm -f ~/.config/plasma-org.kde.plasma.desktop-appletsrc ~/.config/plasmashellrc
|
||||
extras_enable || warn "SteamOS desktop extras not installed (see above); the theme itself is on."
|
||||
ok "Vapor theme set; Plasma lays out the Vapor desktop at the first login."
|
||||
return 0
|
||||
fi
|
||||
info "Applying the Vapor theme with its desktop and window layout..."
|
||||
# --resetLayout is "Desktop and window layout" in System Settings: the
|
||||
# SteamOS panel, launcher icon and wallpaper. It needs plasmashell up.
|
||||
@@ -120,7 +134,11 @@ theme_disable() {
|
||||
fi
|
||||
# After the tools above, so keys that weren't set before are removed again.
|
||||
krevert theme
|
||||
single_status && single_launcher
|
||||
if single_status; then
|
||||
single_launcher
|
||||
else
|
||||
single_launcher_drop
|
||||
fi
|
||||
restart_plasmashell_if_stopped
|
||||
qdbus6 org.kde.KWin /KWin org.kde.KWin.reconfigure >/dev/null 2>&1 || true
|
||||
|
||||
|
||||
+12
-6
@@ -44,6 +44,13 @@ vram_nvidia() {
|
||||
# 470xx, 390xx); every other NVIDIA card runs the open kernel modules.
|
||||
VRAM_CHWD_IDS=/var/lib/chwd/ids
|
||||
|
||||
vram_nvidia_legacy_id() {
|
||||
# vram_nvidia_legacy_id <pci device id, with or without 0x>: 0 when chwd
|
||||
# lists the card for a closed legacy branch, i.e. it is older than the
|
||||
# RTX 20 series. Also what lib/nvidia.sh uses to decide if a card is supported.
|
||||
grep -qwi "${1#0x}" "$VRAM_CHWD_IDS"/nvidia-*.ids 2>/dev/null
|
||||
}
|
||||
|
||||
vram_nvidia_case() {
|
||||
# Why an NVIDIA card's VRAM isn't registered, so the menu can say what to
|
||||
# do: "update" (open modules older than 615), "switch <chwd profile>"
|
||||
@@ -62,8 +69,7 @@ vram_nvidia_case() {
|
||||
esac
|
||||
for d in /sys/bus/pci/devices/*; do
|
||||
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de && "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
|
||||
id="$(cat "$d/device")"; id="${id#0x}"
|
||||
grep -qwi "$id" "$VRAM_CHWD_IDS"/nvidia-*.ids 2>/dev/null && { echo legacy; return; }
|
||||
vram_nvidia_legacy_id "$(cat "$d/device")" && { echo legacy; return; }
|
||||
done
|
||||
for p in 580xx 470xx 390xx; do
|
||||
pacman -Q "nvidia-$p-dkms" >/dev/null 2>&1 && { echo "switch nvidia-dkms-$p"; return; }
|
||||
@@ -101,7 +107,7 @@ vram_selectable() { vram_supported || vram_status; }
|
||||
vram_status() {
|
||||
pacman -Q "${VRAM_PKGS[@]}" >/dev/null 2>&1 &&
|
||||
systemctl is-enabled -q dmemcg-booster-system.service 2>/dev/null &&
|
||||
systemctl --user is-enabled -q dmemcg-booster-user.service 2>/dev/null
|
||||
user_systemctl is-enabled -q dmemcg-booster-user.service 2>/dev/null
|
||||
}
|
||||
|
||||
vram_enable() {
|
||||
@@ -115,18 +121,18 @@ vram_enable() {
|
||||
fi
|
||||
sudo systemctl enable --now dmemcg-booster-system.service >/dev/null 2>&1 ||
|
||||
{ err "Starting dmemcg-booster failed."; return 1; }
|
||||
systemctl --user enable --now dmemcg-booster-user.service >/dev/null 2>&1 ||
|
||||
user_systemctl enable --now dmemcg-booster-user.service >/dev/null 2>&1 ||
|
||||
{ err "Starting dmemcg-booster for $USER failed."; return 1; }
|
||||
kset vram kcgroupsrc "Foreground Booster" autostart true
|
||||
# Started by the Plasma session from now on; start it in this one too.
|
||||
[[ "${XDG_CURRENT_DESKTOP:-}" == KDE ]] &&
|
||||
systemctl --user start plasma-foreground-booster.service >/dev/null 2>&1
|
||||
user_systemctl start plasma-foreground-booster.service >/dev/null 2>&1
|
||||
ok "VRAM booster on: the game in front keeps its VRAM."
|
||||
}
|
||||
|
||||
vram_disable() {
|
||||
local pkgs
|
||||
systemctl --user disable --now plasma-foreground-booster.service dmemcg-booster-user.service >/dev/null 2>&1
|
||||
user_systemctl disable --now plasma-foreground-booster.service dmemcg-booster-user.service >/dev/null 2>&1
|
||||
sudo systemctl disable --now dmemcg-booster-system.service >/dev/null 2>&1
|
||||
krevert vram
|
||||
pkgs="$(state_get vram installed_pkgs)"
|
||||
|
||||
@@ -13,4 +13,6 @@ read and reviewed on their own. `lib/*.sh` reads them with `patch_file
|
||||
| `steamify-fremont-poweroff.dkms.conf`, `steamify-cros-ec-cec.dkms.conf` | `lib/fremont-poweroff.sh`, `lib/cec.sh` | The DKMS modules' `dkms.conf` (`fill NAME=... VERSION=...`) |
|
||||
| `steam-shortcuts.py` | `lib/steam-game.sh` (Add as non-Steam game) | Reads and writes Steam's binary `shortcuts.vdf` (find, add or update, remove) |
|
||||
| `steamify-notifier.py` | `lib/update-notifier.sh` (Update notifications) | The daily check: notification and tray icon when there's a new release |
|
||||
| `steamify-os-release.sh`, `steamify-os-release.hook` | `lib/login-manager.sh` (SteamOS conversion) | What Steam's System settings show besides the OS name (which stays CachyOS's): `VERSION_ID=steamos-X.Y`, `VERSION_CODENAME=steam-machine`, `VARIANT`/`VARIANT_ID` Steamify with its version, in `/etc/os-release`; the pacman hook runs it again after cachyos-hooks (`fill SCRIPT=... VERSION=... STEAMOS=...`) |
|
||||
| `steamify-nvidia-initramfs.sh`, `steamify-nvidia-initramfs.hook` | `lib/nvidia.sh` (SteamOS conversion, NVIDIA fix) | The pacman hook (before the initramfs is built, after DKMS) and its script: the NVIDIA modules go into the initramfs only while every installed kernel has them, decided again at every kernel or driver change (`fill SCRIPT=...`) |
|
||||
| `cros-ec-cec-single-port.patch` | `lib/cec.sh` (HDMI-CEC) | Makes Valve's Steam Machine CEC driver find amdgpu's HDMI port |
|
||||
@@ -0,0 +1,17 @@
|
||||
# Installed by Steamify CachyOS (SteamOS conversion, NVIDIA fix): decides
|
||||
# again whether the NVIDIA modules go into the initramfs, after DKMS has built
|
||||
# its modules (71-dkms-install) and before the initramfs is built
|
||||
# (90-mkinitcpio-install); hooks run in file name order.
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Operation = Remove
|
||||
Type = Path
|
||||
Target = usr/lib/modules/*/vmlinuz
|
||||
Target = usr/lib/modules/*/extramodules/nvidia*
|
||||
Target = usr/lib/modules/*/updates/*
|
||||
|
||||
[Action]
|
||||
Description = Steamify: NVIDIA modules in the initramfs only if every kernel has them
|
||||
When = PostTransaction
|
||||
Exec = @SCRIPT@ sync
|
||||
@@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
# Installed by Steamify CachyOS (SteamOS conversion, NVIDIA fix), run by the
|
||||
# pacman hook steamify-nvidia-initramfs.hook before the initramfs is built.
|
||||
# The NVIDIA modules go into the initramfs (early KMS) only while EVERY
|
||||
# installed kernel has them: mkinitcpio fails on a module a kernel lacks, and
|
||||
# limine-mkinitcpio then skips that kernel's boot entry, kernel parameters
|
||||
# included. Decided again at every kernel or driver change, so a new kernel
|
||||
# without the modules (another kernel, a failed DKMS build, a downgrade) gets
|
||||
# a working initramfs and the file comes back once it has them.
|
||||
# steamify-nvidia-initramfs [sync|check]
|
||||
# sync (default) write or remove the drop-in to match
|
||||
# check exit status 0 when every installed kernel has nvidia_drm
|
||||
conf="${NVIDIA_INITRAMFS_CONF:-/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf}"
|
||||
mods="${NVIDIA_MODULES_DIR:-/usr/lib/modules}"
|
||||
|
||||
everywhere() {
|
||||
local k found=0
|
||||
for k in "$mods"/*/; do
|
||||
[[ -f "$k/vmlinuz" || -f "$k/pkgbase" ]] || continue # an installed kernel, not a leftover folder
|
||||
find "$k" -name 'nvidia-drm.ko*' -print -quit 2>/dev/null | grep -q . || return 1
|
||||
found=1
|
||||
done
|
||||
[[ $found == 1 ]]
|
||||
}
|
||||
|
||||
case "${1:-sync}" in
|
||||
check) everywhere ;;
|
||||
sync)
|
||||
if everywhere; then
|
||||
[[ -f "$conf" ]] || { mkdir -p "$(dirname "$conf")" &&
|
||||
echo 'MODULES+=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)' > "$conf"; }
|
||||
else
|
||||
rm -f "$conf"
|
||||
fi ;;
|
||||
*) echo "usage: $0 [sync|check]" >&2; exit 2 ;;
|
||||
esac
|
||||
@@ -0,0 +1,14 @@
|
||||
# Installed by Steamify CachyOS (SteamOS conversion): runs after
|
||||
# cachyos-hooks' os-release/cachyos-branding hooks (hooks run in file name
|
||||
# order).
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Type = Package
|
||||
Target = filesystem
|
||||
Target = cachyos-hooks
|
||||
|
||||
[Action]
|
||||
Description = Steamify: the OS variant and version Steam shows
|
||||
When = PostTransaction
|
||||
Exec = @SCRIPT@
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
# Installed by Steamify CachyOS (SteamOS conversion): what Steam shows in its
|
||||
# System settings besides the OS name, which stays CachyOS's: the SteamOS
|
||||
# release Steamify follows as the OS version (VERSION_ID, e.g. steamos-3.9),
|
||||
# steam-machine as the codename, and Steamify with its version as the variant
|
||||
# (VARIANT_ID, which Steam shows). KDE's About this System would show
|
||||
# VERSION_ID after the name: the conversion sets its UseOSReleaseVersion, so it
|
||||
# shows os-release's VERSION instead, which CachyOS doesn't have. NAME and
|
||||
# PRETTY_NAME are never touched: limine-snapper-sync finds the boot entries by
|
||||
# the OS name. The zz-steamify-os-release hook runs this after cachyos-hooks.
|
||||
sed -i -e '/^VARIANT=/d' -e '/^VARIANT_ID=/d' -e '/^VERSION_ID=/d' -e '/^VERSION_CODENAME=/d' /etc/os-release
|
||||
printf '%s\n' 'VARIANT="Steamify @VERSION@"' 'VARIANT_ID=steamify-@VERSION@' 'VERSION_CODENAME=steam-machine' >> /etc/os-release
|
||||
[ -n "@STEAMOS@" ] && echo 'VERSION_ID=@STEAMOS@' >> /etc/os-release
|
||||
exit 0
|
||||
+65
-3
@@ -15,11 +15,11 @@
|
||||
set -uo pipefail
|
||||
|
||||
# Release version, see CHANGELOG.md.
|
||||
VERSION=2.5.1
|
||||
VERSION=2.9.7
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
|
||||
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier menu backend; do
|
||||
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh nvidia cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier first-login menu backend; do
|
||||
# shellcheck source=/dev/null
|
||||
source "$SCRIPT_DIR/lib/$lib.sh"
|
||||
done
|
||||
@@ -28,8 +28,21 @@ require_root_helper
|
||||
|
||||
BACKEND=false
|
||||
[[ "${1:-}" == --backend ]] && BACKEND=true
|
||||
# --defaults [--options <id>,...] [--boot gamescope|desktop]: apply what the
|
||||
# menu would preselect (or exactly the listed items), without the menu or any
|
||||
# prompt (the Steam Machine ISO's first login runs this; sudo must not ask).
|
||||
DEFAULTS=false
|
||||
[[ "${1:-}" == --defaults ]] && DEFAULTS=true
|
||||
# --defaults --list: what --defaults can set up here, as JSON (an installer
|
||||
# page is built from it); nothing else on stdout.
|
||||
LIST=false
|
||||
[[ "$DEFAULTS" == true && "${2:-}" == --list ]] && LIST=true
|
||||
# --boot gamescope|desktop: only change where an installed conversion
|
||||
# starts, everything else stays as it is (for scripts; no menu).
|
||||
BOOT_ONLY=false
|
||||
[[ "${1:-}" == --boot ]] && BOOT_ONLY=true
|
||||
|
||||
if [[ "$BACKEND" == false ]]; then
|
||||
if [[ "$BACKEND" == false && "$LIST" == false ]]; then
|
||||
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."
|
||||
@@ -114,6 +127,55 @@ if [[ "$BACKEND" == true ]]; then
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == --first-login ]]; then
|
||||
first_login_run
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$LIST" == true ]]; then
|
||||
defaults_list
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$DEFAULTS" == true ]]; then
|
||||
RESTART_FOR_LOGIN=false
|
||||
REAPPLY=false
|
||||
sudo -n true 2>/dev/null || { err "--defaults needs sudo without a password."; exit 1; }
|
||||
detect_components
|
||||
defaults_options "${@:2}" || exit 1
|
||||
plan_changes
|
||||
apply_changes
|
||||
# Run by the installer: the rest waits for the first desktop login.
|
||||
user_session || first_login_schedule
|
||||
[[ ${#FAILED[@]} -eq 0 ]] || { warn "These had problems (see above): ${FAILED[*]}"; exit 1; }
|
||||
ok "Done; the changes take effect after a restart."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$BOOT_ONLY" == true ]]; then
|
||||
RESTART_FOR_LOGIN=false
|
||||
REAPPLY=false
|
||||
case "${2:-}" in
|
||||
gamescope|desktop) ;;
|
||||
*) err "--boot takes gamescope or desktop"; exit 1 ;;
|
||||
esac
|
||||
detect_components
|
||||
[[ "${CURRENT[gaming]}" == 1 ]] || { err "--boot needs the SteamOS conversion; turn it on first."; exit 1; }
|
||||
# What is on stays on, and nothing else changes: not the updates or
|
||||
# removals a normal run would pick.
|
||||
for c in "${COMPONENTS[@]}"; do WANTED[$c]=${CURRENT[$c]:-0}; done
|
||||
WANTED[boot]=0; [[ "$2" == desktop ]] && WANTED[boot]=1
|
||||
plan_changes
|
||||
if [[ ${#TO_DISABLE[@]} -eq 0 && ${#TO_ENABLE[@]} -eq 0 ]]; then
|
||||
ok "Already starting in $2."
|
||||
exit 0
|
||||
fi
|
||||
apply_changes
|
||||
[[ ${#FAILED[@]} -eq 0 ]] || { warn "These had problems (see above): ${FAILED[*]}"; exit 1; }
|
||||
ok "Starts in $2 from the next boot on."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
# Test of the NVIDIA fix on a real PC with an NVIDIA GPU (the unit test fakes
|
||||
# one: tests/nvidia-test.sh). Run from the Steamify checkout:
|
||||
# bash tests/nvidia-hardware-test.sh check read-only: what is detected, what the live kernel uses, what apply would change
|
||||
# bash tests/nvidia-hardware-test.sh apply really applies the fix (sudo), then reboot and run check again
|
||||
# bash tests/nvidia-hardware-test.sh visual after trying gaming mode: was the picture clean? (asks you)
|
||||
# Every run appends to ~/steamify-nvidia-report.txt: paste that file when asking for help.
|
||||
cd "$(dirname "$0")/.." || exit 1
|
||||
REPORT="${NVIDIA_REPORT:-$HOME/steamify-nvidia-report.txt}"
|
||||
source lib/common.sh; source lib/hdmi-refresh.sh; source lib/vram-booster.sh; source lib/nvidia.sh
|
||||
mode="${1:-check}"
|
||||
fail=0
|
||||
say() { echo "$*" | tee -a "$REPORT"; }
|
||||
pass() { say "PASS $*"; }
|
||||
bad() { say "FAIL $*"; fail=1; }
|
||||
note() { say " $*"; }
|
||||
root_cat() { cat "$1" 2>/dev/null || sudo cat "$1" 2>/dev/null || echo "(unreadable)"; }
|
||||
|
||||
say ""; say "===== $(date '+%F %T') mode=$mode kernel=$(uname -r)"
|
||||
|
||||
report_system() {
|
||||
say "-- GPU and software"
|
||||
lspci -nn 2>/dev/null | grep -iE 'vga|3d|display' | while read -r l; do note "$l"; done
|
||||
command -v nvidia-smi >/dev/null && note "driver: $(nvidia-smi --query-gpu=name,driver_version --format=csv,noheader 2>&1 | head -n 1)"
|
||||
for p in nvidia-open nvidia-utils nvidia-dkms gamescope gamescope-session-cachyos linux-cachyos-nvidia-open; do
|
||||
v="$(pacman -Q "$p" 2>/dev/null)" && note "$v"
|
||||
done
|
||||
note "boot loader file: $(nvidia_boot_file || true)"
|
||||
note "cmdline: $(cat /proc/cmdline)"
|
||||
}
|
||||
|
||||
check_state() {
|
||||
say "-- Steamify's view"
|
||||
if nvidia_present; then pass "a supported NVIDIA GPU (RTX 20 series or newer) with its driver is detected"
|
||||
elif nvidia_legacy_gpu; then bad "the NVIDIA GPU is older than RTX 20 (on chwd's legacy lists in $VRAM_CHWD_IDS): the fix is not applied"
|
||||
else bad "no NVIDIA GPU with its driver detected: the fix does nothing here"; fi
|
||||
for c in /sys/class/drm/card[0-9]*/device; do
|
||||
[[ "$(cat "$c/vendor" 2>/dev/null)" == 0x10de ]] && note "NVIDIA PCI device id $(cat "$c/device") $(vram_nvidia_legacy_id "$(cat "$c/device")" && echo '(on a chwd legacy list)' || echo '(not on a legacy list: RTX 20 or newer)')"
|
||||
done
|
||||
ls "$VRAM_CHWD_IDS"/nvidia-*.ids >/dev/null 2>&1 || note "no chwd legacy lists found: every NVIDIA card counts as supported"
|
||||
local p
|
||||
for p in $NVIDIA_PARAMS; do
|
||||
if grep -qw -- "$p" /proc/cmdline; then pass "$p is on the running kernel's command line"
|
||||
elif nvidia_param_set "$p"; then bad "$p is in the boot loader's file but not booted yet: reboot"
|
||||
else bad "$p is missing (run: bash tests/nvidia-hardware-test.sh apply)"; fi
|
||||
done
|
||||
say "-- the live NVIDIA driver"
|
||||
local m
|
||||
for m in modeset fbdev; do
|
||||
v="$(root_cat /sys/module/nvidia_drm/parameters/$m)"
|
||||
if [[ "$v" == Y ]]; then pass "nvidia_drm $m = Y"; else bad "nvidia_drm $m = $v (want Y)"; fi
|
||||
done
|
||||
lsmod | grep -q '^nvidia_drm' && pass "nvidia_drm is loaded" || bad "nvidia_drm is not loaded"
|
||||
local c found=0
|
||||
for c in /sys/class/drm/card[0-9]*/device; do
|
||||
[[ "$(cat "$c/vendor" 2>/dev/null)" == 0x10de ]] || continue
|
||||
found=1; note "NVIDIA card: ${c%/device} driver=$(basename "$(readlink -f "$c/driver" 2>/dev/null)")"
|
||||
for s in "${c%/device}"/card*-*/status; do [[ -f "$s" ]] && note " $(basename "$(dirname "$s")"): $(cat "$s")"; done
|
||||
done
|
||||
[[ $found == 1 ]] || bad "no NVIDIA card in /sys/class/drm"
|
||||
say "-- initramfs"
|
||||
if nvidia_modules_everywhere; then note "every installed kernel has nvidia_drm: the early-load drop-in is used"
|
||||
else note "not every installed kernel has nvidia_drm: the early-load drop-in is skipped (parameters still apply)"; fi
|
||||
nvidia_initramfs_ok && note "NVIDIA modules are in the initramfs config" || note "NVIDIA modules are not in the initramfs config"
|
||||
say "-- what apply would change"
|
||||
if nvidia_params_missing; then note "adds $NVIDIA_PARAMS to $(nvidia_boot_file)"; else note "kernel parameters: nothing to change"; fi
|
||||
if ! nvidia_initramfs_ok && nvidia_modules_everywhere; then note "writes $NVIDIA_INITRAMFS_CONF"; fi
|
||||
}
|
||||
|
||||
case "$mode" in
|
||||
check)
|
||||
report_system; check_state ;;
|
||||
apply)
|
||||
report_system
|
||||
say "-- applying"
|
||||
if nvidia_enable 2>&1 | tee -a "$REPORT"; [[ ${PIPESTATUS[0]} == 0 ]]; then pass "nvidia_enable finished"
|
||||
else bad "nvidia_enable failed (output above)"; fi
|
||||
say "Now reboot, then run: bash tests/nvidia-hardware-test.sh check" ;;
|
||||
visual)
|
||||
report_system
|
||||
say "-- try gaming mode now (log in to it or reboot into it), look at the screen, then answer"
|
||||
read -rp "Is the gaming mode picture clean (no corruption, no flicker)? [y/n/partly] " a
|
||||
read -rp "What did you see (one line, e.g. 'garbled colours at start, fine after login')? " what
|
||||
say "visual result: $a: $what"
|
||||
[[ "$a" == y ]] && pass "picture clean" || bad "picture not clean ($a)"
|
||||
say "-- gamescope and NVIDIA lines from this boot's log"
|
||||
{ journalctl -b --no-pager 2>/dev/null || sudo journalctl -b --no-pager 2>/dev/null; } |
|
||||
grep -iE 'gamescope|nvidia|drm|nvrm|wlserver|vulkan' | tail -n 80 | tee -a "$REPORT" | tail -n 5
|
||||
note "(more in $REPORT)" ;;
|
||||
*) echo "usage: $0 check|apply|visual"; exit 2 ;;
|
||||
esac
|
||||
say ""; say "Report: $REPORT"
|
||||
exit $fail
|
||||
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
# Tests lib/nvidia.sh against a fake RTX 5080 (PCI 10de:2c02) beside an
|
||||
# Intel iGPU, a stub modinfo, and temp copies of the boot loader files. No
|
||||
# root, VM or NVIDIA hardware needed: bash tests/nvidia-test.sh
|
||||
cd "$(dirname "$0")/.." || exit 1
|
||||
T="$(mktemp -d)"; trap 'rm -rf "$T"' EXIT
|
||||
fail=0
|
||||
check() { if eval "$2"; then echo "ok $1"; else echo "FAIL $1"; fail=1; fi; }
|
||||
|
||||
SCRIPT_DIR="$PWD"; source lib/common.sh; source lib/hdmi-refresh.sh; source lib/vram-booster.sh; source lib/nvidia.sh
|
||||
sudo() { "$@"; }
|
||||
info() { :; }; ok() { :; }; warn() { :; }; err() { echo "ERR $*"; }
|
||||
backup_file() { [[ -f "$1.bak" ]] || cp "$1" "$1.bak"; }
|
||||
modinfo() { [[ "$FAKE_DRIVER" == 1 ]]; }
|
||||
REBUILDS=0; nvidia_rebuild_boot() { REBUILDS=$((REBUILDS + 1)); }
|
||||
NVIDIA_INITRAMFS_CONF="$T/90-steamify-nvidia.conf"
|
||||
mkdir -p "$T/drm/card0/device" "$T/drm/card1/device"
|
||||
echo 0x8086 > "$T/drm/card0/device/vendor"; echo 0x030000 > "$T/drm/card0/device/class"
|
||||
echo 0x10de > "$T/drm/card1/device/vendor"; echo 0x030000 > "$T/drm/card1/device/class"
|
||||
echo 0x2c02 > "$T/drm/card1/device/device"
|
||||
NVIDIA_DRM_DIR="$T/drm"
|
||||
mkdir -p "$T/mods/6.1.0-cachyos/kernel"; : > "$T/mods/6.1.0-cachyos/kernel/nvidia-drm.ko.zst"; : > "$T/mods/6.1.0-cachyos/pkgbase"
|
||||
NVIDIA_SCRIPT="$T/libexec/steamify-nvidia-initramfs"; NVIDIA_HOOK="$T/hooks/85-steamify-nvidia-initramfs.hook"
|
||||
NVIDIA_MODULES_DIR="$T/mods"
|
||||
NVIDIA_LIMINE_CONF="$T/none/limine.conf"; NVIDIA_SDBOOT_DIR="$T/none/entries"; NVIDIA_GRUB_CFG="$T/none/grub.cfg" # not generated here: not checked
|
||||
|
||||
mkdir -p "$T/chwd"; VRAM_CHWD_IDS="$T/chwd"
|
||||
FAKE_DRIVER=1; check "finds the NVIDIA card as card1 beside an iGPU (no legacy lists)" nvidia_present
|
||||
printf '1c03\n1b80\n' > "$T/chwd/nvidia-580.ids" # a GTX 1060 and a GTX 1080: chwd's 580xx legacy list
|
||||
check "RTX 5080 (2c02) is not on a legacy list: supported" nvidia_present
|
||||
echo 0x1c03 > "$T/drm/card1/device/device"
|
||||
check "GTX 1060 (on chwd's legacy list, older than RTX 20): not supported" '! nvidia_present'
|
||||
check "...and reported as a legacy GPU" nvidia_legacy_gpu
|
||||
echo 0x2c02 > "$T/drm/card1/device/device"; check "RTX 5080 is not a legacy GPU" '! nvidia_legacy_gpu'
|
||||
printf '2c02\n' > "$T/chwd/nvidia-580.ids"; check "a card id that is on a legacy list is skipped, whatever it is" '! nvidia_present'
|
||||
printf '1c03\n' > "$T/chwd/nvidia-580.ids"
|
||||
FAKE_DRIVER=0; check "skips when the driver isn't installed" '! nvidia_present'
|
||||
FAKE_DRIVER=1; NVIDIA_DRM_DIR="$T/none"; check "skips without an NVIDIA GPU" '! nvidia_present'
|
||||
NVIDIA_DRM_DIR="$T/drm"
|
||||
|
||||
for loader in limine sdboot grub; do
|
||||
case $loader in
|
||||
limine) F="$T/limine"; printf 'KERNEL_CMDLINE[default]="quiet splash"\n' > "$F" ;;
|
||||
sdboot) F="$T/sdboot-manage.conf"; printf 'LINUX_OPTIONS="quiet splash"\n' > "$F" ;;
|
||||
grub) F="$T/grub"; printf 'GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"\n' > "$F" ;;
|
||||
esac
|
||||
nvidia_boot_file() { echo "$F"; }
|
||||
rm -f "$NVIDIA_INITRAMFS_CONF"; REBUILDS=0; ORIG="$(cat "$F")"
|
||||
nvidia_enable
|
||||
check "$loader: parameters added" 'grep -q "nvidia-drm.modeset=1" "$F" && grep -q "nvidia-drm.fbdev=1" "$F"'
|
||||
check "$loader: initramfs drop-in written" 'grep -q nvidia_drm "$NVIDIA_INITRAMFS_CONF"'
|
||||
check "$loader: script and pacman hook installed" '[[ -x "$NVIDIA_SCRIPT" ]] && grep -q "^Exec = $NVIDIA_SCRIPT sync" "$NVIDIA_HOOK"'
|
||||
check "$loader: backup made, rebuilt once" '[[ -f "$F.bak" && $REBUILDS == 1 ]]'
|
||||
SUM="$(cat "$F")"; nvidia_enable
|
||||
check "$loader: second run changes nothing" '[[ "$(cat "$F")" == "$SUM" && $REBUILDS == 1 ]]'
|
||||
nvidia_disable
|
||||
check "$loader: disable restores the file, drops the drop-in, script and hook" '[[ "$(cat "$F")" == "$ORIG" && ! -f "$NVIDIA_INITRAMFS_CONF" && ! -e "$NVIDIA_SCRIPT" && ! -e "$NVIDIA_HOOK" ]]'
|
||||
done
|
||||
|
||||
# A missing patches/ file must be an error, never an empty script or hook.
|
||||
( SCRIPT_DIR="$T/no-patches"; NVIDIA_SCRIPT="$T/empty/script"; NVIDIA_HOOK="$T/empty/hook"; ! nvidia_hook_install 2>/dev/null && [[ ! -s "$T/empty/script" ]] ) && echo "ok a missing patch file is an error, nothing empty installed" || { echo "FAIL a missing patch file is an error, nothing empty installed"; fail=1; }
|
||||
# The pacman hook's script decides again at every kernel change.
|
||||
syncit() { NVIDIA_INITRAMFS_CONF="$NVIDIA_INITRAMFS_CONF" NVIDIA_MODULES_DIR="$NVIDIA_MODULES_DIR" bash "$NVIDIA_SCRIPT" sync; }
|
||||
nvidia_hook_install; rm -f "$NVIDIA_INITRAMFS_CONF"
|
||||
syncit; check "hook script: every kernel has the modules -> drop-in written" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
|
||||
mkdir -p "$T/mods/6.6.0-lts/kernel"; : > "$T/mods/6.6.0-lts/pkgbase"
|
||||
syncit; check "hook script: a new kernel without modules -> drop-in removed" '[[ ! -f "$NVIDIA_INITRAMFS_CONF" ]]'
|
||||
: > "$T/mods/6.6.0-lts/kernel/nvidia-drm.ko.zst"
|
||||
syncit; check "hook script: the modules arrive (DKMS built) -> drop-in back" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
|
||||
rm -rf "$T/mods/6.6.0-lts"; mkdir -p "$T/mods/5.0.0-leftover"; : > "$T/mods/5.0.0-leftover/modules.dep"
|
||||
syncit; check "hook script: a leftover folder of a removed kernel is ignored" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
|
||||
rm -rf "$T/mods/5.0.0-leftover"; nvidia_disable
|
||||
# A second kernel without the NVIDIA modules: no early-load drop-in, parameters still set.
|
||||
mkdir -p "$T/mods/6.6.0-lts/kernel"; : > "$T/mods/6.6.0-lts/pkgbase"; F="$T/sdboot-manage.conf"; printf 'LINUX_OPTIONS="quiet"\n' > "$F"
|
||||
nvidia_boot_file() { echo "$F"; }; rm -f "$NVIDIA_INITRAMFS_CONF"; REBUILDS=0; nvidia_enable
|
||||
check "kernel without nvidia modules: no drop-in, parameters set" '[[ ! -f "$NVIDIA_INITRAMFS_CONF" ]] && grep -q "nvidia-drm.fbdev=1" "$F"'
|
||||
rm -rf "$T/mods/6.6.0-lts"
|
||||
# Generated boot entries without the parameters (the initramfs build failed): an error.
|
||||
printf 'linux /vmlinuz root=/dev/sda1\n' > "$T/grub.cfg"; NVIDIA_GRUB_CFG="$T/grub.cfg"
|
||||
F="$T/grub"; printf 'GRUB_CMDLINE_LINUX_DEFAULT="quiet"\n' > "$F"; nvidia_boot_file() { echo "$F"; }; rm -f "$NVIDIA_INITRAMFS_CONF"
|
||||
check "boot entries without the parameters: error" '! nvidia_enable >/dev/null'
|
||||
NVIDIA_GRUB_CFG="$T/none/grub.cfg"
|
||||
# A config file without the setting to edit: an error, not "applied".
|
||||
F="$T/sdboot-manage.conf"; printf '#LINUX_OPTIONS=""\n' > "$F"; nvidia_boot_file() { echo "$F"; }; REBUILDS=0
|
||||
check "no setting to edit: error, nothing rebuilt" '! nvidia_enable >/dev/null && [[ $REBUILDS == 0 ]]'
|
||||
FAKE_DRIVER=0; printf 'LINUX_OPTIONS="quiet"\n' > "$T/sdboot"; F="$T/sdboot"; REBUILDS=0; nvidia_enable
|
||||
check "no NVIDIA driver: nothing touched" '[[ "$(cat "$F")" == "LINUX_OPTIONS=\"quiet\"" && $REBUILDS == 0 ]]'
|
||||
exit $fail
|
||||
@@ -35,9 +35,15 @@ Item {
|
||||
border.width: step.st === "wait" || step.st === "run" ? 2 : 0; border.color: step.st === "run" ? Theme.accent : "#343f50"
|
||||
Text { anchors.centerIn: parent; text: step.st === "ok" ? "✓" : (step.st === "fail" ? "!" : ""); color: step.st === "ok" ? Theme.good : Theme.bad
|
||||
font.pixelSize: 13; font.weight: Font.Bold }
|
||||
RotationAnimator on rotation { running: step.st === "run"; from: 0; to: 360; duration: 1000; loops: Animation.Infinite } }
|
||||
// Only this dot turns while the step runs: ✓ and ! never rotate
|
||||
// (an animator leaves its item at whatever angle it stopped).
|
||||
Item { anchors.fill: parent; visible: step.st === "run"
|
||||
Rectangle { width: 6; height: 6; radius: 3; color: Theme.accent; x: parent.width / 2 - 3; y: -3 }
|
||||
RotationAnimator on rotation { running: step.st === "run"; from: 0; to: 360; duration: 1000; loops: Animation.Infinite } } }
|
||||
Row { width: 380; anchors.verticalCenter: parent.verticalCenter; spacing: 10
|
||||
Text { text: (Texts.actions[step.modelData.action] || [])[3] + Texts.label(step.modelData.id)
|
||||
// Boot into's label is its prefix already: "Boot into desktop", not "Boot into Boot into".
|
||||
Text { text: step.modelData.id === "boot" ? (Texts.actions[step.modelData.action] || [])[3] + Texts.actions[step.modelData.action][0].toLowerCase()
|
||||
: (Texts.actions[step.modelData.action] || [])[3] + Texts.label(step.modelData.id)
|
||||
color: step.st === "wait" ? Theme.faint : Theme.textHi; font.family: Theme.body; font.pixelSize: 16; font.weight: Font.DemiBold
|
||||
anchors.verticalCenter: parent.verticalCenter; elide: Text.ElideRight
|
||||
width: Math.min(implicitWidth, parent.width - (badge.visible ? badge.width + parent.spacing : 0)) }
|
||||
|
||||
+4
-4
@@ -1,12 +1,12 @@
|
||||
#!/bin/bash
|
||||
# Steamify CachyOS - get and start the app (v2), for `curl | bash`:
|
||||
# Steamify CachyOS - get and start the app, for `curl | bash`:
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify-app.sh | bash
|
||||
# Downloads the newest release's app package (steamify-app.tar.gz: the app,
|
||||
# steamify.sh, lib/, patches/ and services/) to ~/.local/share/steamify/app, installs PySide6 if
|
||||
# it's missing, adds a launcher entry, and starts the app.
|
||||
# STEAMIFY_RELEASE=<tag> takes that release instead of the newest (the
|
||||
# v2-ui-preview build's copy of this script sets it). STEAMIFY_BRANCH=<branch>
|
||||
# takes that branch's source instead (for testing before a build).
|
||||
# STEAMIFY_RELEASE=<tag> takes that release instead of the newest.
|
||||
# STEAMIFY_BRANCH=<branch> takes that branch's source instead (for testing
|
||||
# before a build).
|
||||
set -euo pipefail
|
||||
|
||||
REPO="theupriser/steamify-cachyos"
|
||||
|
||||
Reference in new issue
Block a user