mia 9fa102e098 Add SteamOS distro
Adds `--distro steamos` as a first-class build target. Pattern is the
same as bazzite-deck/batocera: distros/steamos/build-rootfs.sh fetches
the upstream rootfs (Valve's Steam Deck recovery .img.bz2 from
steamdeck-images.steamos.cloud), extracts the rootfs-A + var-A btrfs
slots into $CHROOT, swaps in our linux-ps5 kernel pkg.tar.zst, and
rebuilds the initramfs with the modules amdgpu needs for the PS5
Oberon GPU.

PS5-specific fixes applied to the SteamOS rootfs:

- Replace /usr/bin/steamos-session-select with a shim that writes
  /etc/sddm.conf.d/zzz-session-override.conf directly + restarts sddm.
  The vendored helper goes through steamosctl / steamos-manager whose
  Deck-hardware code paths silently no-op on PS5, leaving the UI stuck
  at "Switching to Desktop..." with no actual session swap.

- Install a small Python dbus monitor (steam-session-switch-listener)
  that catches org.freedesktop.DisplayManager.Seat.SwitchToUser from
  Big Picture's "Switch to Desktop" button and writes the same
  override file. No -steamos3 / -steampal needed (those trigger Steam's
  A/B update reboot loop on a non-Deck box).

- Drop a Return-to-Gaming-Mode.desktop into /home/deck/Desktop pointing
  at steamos-session-select gamescope.

- chown /home/deck to deck:deck (the recovery image leaves it root:root,
  which breaks ~/.config writability on first Plasma launch).

- Enable sshd + set deck:deck so the box is reachable for further
  iteration without dragging a USB keyboard around.

- Patch /etc/fstab: comment out the by-partsets atomic mount entries
  (those paths don't exist on a flat-rootfs flash), append a LABEL-based
  /efi mount so the FAT boot partition comes up cleanly. Required for
  ps5-iw620-firmware.service to find the WLAN blob.

- Append amdgpu.dpm=0 + amdgpu.gpu_recovery=0 to the kernel cmdline.
  modprobe.d alone isn't enough — amdgpu loads before the rootfs conf
  is read, so the cmdline is the only reliable path. Without these
  Switch-to-Desktop produces a black screen on the PS5 HDMI output.

- Polkit-deny the deck user reboot/poweroff to break Steam's update
  reboot loop on first boot.

- Patch steam-jupiter to skip its OOBE rm -rf path. The OOBE assumes
  Deck factory layout and wipes /home/deck/.local if it runs.

Verified end-to-end on real PS5 (HW-rev EA-1102): autologin lands in
gamescope, Switch-to-Desktop and Return-to-Gaming both work, sshd is
reachable, ps5-iw620 brings up internal WiFi after firmware staging.

Files:
- distros/steamos/build-rootfs.sh  (646 lines)
- distros/steamos/README.md
- distros/steamos/return-to-gaming-mode.desktop
- distros/steamos/steam-session-switch-listener.{py,service}
- build_image.sh: steamos → FORMAT=arch (uses linux-ps5 pkg.tar.zst)
- .github/workflows/build-image.yml: steamos in matrix options + distros list
2026-06-27 17:10:07 -04:00
2026-06-27 17:10:07 -04:00
2026-05-19 09:11:54 +02:00
2026-06-27 17:10:07 -04:00
2026-05-19 09:11:54 +02:00
2026-06-27 17:10:07 -04:00
2026-06-20 17:40:50 +02:00

PS5 Linux Image Builder

Builds bootable Linux USB images for PlayStation 5 using Docker containers. Supports Ubuntu 26.04, Arch, CachyOS (Gamescope + Steam), Fedora (GNOME), individually or as a multi-distro image with kexec switching.

Prerequisites

  • Docker (with permission to run --privileged containers) — install as per your distro's instructions
  • ~30GB free disk space for Ubuntu, Arch, or CachyOS

Once Docker is installed, add your user to the docker group and apply it without logging out:

sudo usermod -aG docker $USER
newgrp docker

Quick Start

# Build a single Ubuntu 26.04 image
./build_image.sh --distro ubuntu2604

OR

# Build CachyOS (Arch-based, Gamescope + Steam Big Picture)
./build_image.sh --distro cachyos

OR

OR

# Build Fedora (GNOME desktop)
./build_image.sh --distro fedora

OR

# Build a multi-distro image (ubuntu2604 + arch + cachyos)
./build_image.sh --distro all

The script auto-clones the kernel source, applies PS5 patches, compiles, and builds the image. Subsequent runs reuse cached artifacts automatically. Press Ctrl+C at any time to abort cleanly.

Flash to USB

sudo dd if=output/ps5-ubuntu2604.img of=/dev/sdX bs=4M status=progress

Options

Flag Description Default
--distro ubuntu2604, arch, cachyos, fedora, or all ubuntu2604
--kernel Path to kernel source directory auto-clone version selected by PS5 patch set
--img-size Disk image size in MB 12000 (32000 for all)
--clean Remove all cached build artifacts and start fresh off
--kernel-only Build and package the kernel only, then exit off
--patches-ref Branch, tag, or commit SHA for patches v1.2

Caching

The build automatically skips stages that have already completed:

  • Kernel source — reused if work/linux/ exists
  • Kernel packages — reused if .deb/.pkg.tar.zst files exist in linux-bin/
  • Root filesystem — reused if chroot directories are populated

Use --clean to wipe everything and rebuild from scratch. The build will also suggest --clean if a stage fails.

Build Output

PS5 Linux Image Builder
=======================
  Distro:       all
                (ubuntu2604 arch cachyos)
  Image size:   32000MB
  Kernel src:   /path/to/work/linux

Stages:
  1. Kernel            cached
  2. Root filesystem   build
  3. Disk image        build

Logs: /path/to/build.log

  ✓ Kernel packages (cached)
  ✓ Build image builder image
  ⠹ Building arch rootfs

All verbose output goes to build.log. The terminal shows a spinner with live progress.

Distributions

Distro Desktop Kernel format Init
Ubuntu 26.04 (Resolute) GNOME .deb systemd
Arch Sway .pkg.tar.zst systemd
CachyOS Gamescope + Steam Big Picture (Arch + [cachyos] repo, no v3 migration in image build) .pkg.tar.zst systemd

Multi-distro Image

--distro all builds a 32GB image with 4 partitions (one EFI boot partition plus three root filesystems):

Partition Type Label Content
p1 FAT32 boot Shared kernel, per-distro initrds, kexec scripts
p2 ext4 ubuntu2604 Ubuntu 26.04 rootfs
p3 ext4 arch Arch rootfs
p4 ext4 cachyos CachyOS rootfs

The boot partition contains kexec scripts to switch between distros at runtime. Ubuntu 26.04 is the default boot target.

Building the Kernel Standalone

Use --kernel-only to compile the PS5 kernel and produce installable packages without building a full disk image.

./build_image.sh --kernel-only                                # .deb (default)
./build_image.sh --kernel-only --distro all                   # .deb + .pkg.tar.zst
./build_image.sh --kernel-only --patches-ref main             # fetch from specific branch/tag
./build_image.sh --kernel-only --clean                        # wipe and rebuild from scratch

Output packages are written to linux-bin/. Install on a running PS5 Linux system:

sudo dpkg -i linux-bin/linux-ps5_*.deb

Directory Layout

build_image.sh                  # Image builder (also supports --kernel-only)
docker/
  kernel-builder/               # Kernel compilation container
  kernel-builder-arch/          # Repackages .deb kernel as .pkg.tar.zst
  image-builder/
    Dockerfile                  # Image building container (distrobuilder)
    entrypoint.sh               # Single-distro build logic
    entrypoint-multi.sh         # Multi-distro build logic
distros/
  ubuntu2604/                   # Ubuntu 26.04 (Resolute)
  arch/                         # Arch Linux
  cachyos/                      # CachyOS repos + Gamescope/Steam
  shared/                       # Kernel postinst hooks (single + multi)
boot/
  cmdline.txt                   # Kernel cmdline template (__DISTRO__ placeholder)
  vram.txt                      # VRAM allocation
  kexec-{ubuntu2604,arch,cachyos}.sh
work/                           # Build artifacts (auto-created)
linux-bin/                      # Compiled kernel packages
output/                         # Final .img files
Description
No description provided
Readme 357 KiB
Languages
Shell 94.1%
Dockerfile 2.7%
Python 2.6%
Lua 0.6%