mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 01:00:18 +02:00
Test against Valve's own Steam Frame OS from its recovery image
tests/frame-container/frame-image.sh extracts rootfs-A from Valve's Frame recovery image (steamdeck-images.steamos.cloud/recovery), mounts it read-only with a throwaway writable layer and starts the image's own sshd, so the iPhone app can pair with and run its server on the real SteamOS for Frame userland. Verified: password pairing then key login in the image's sshd log, the power password check through the image's sudo, status reading SteamOS 0.3.0. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
b1fa3afd40
commit
d65f7130d5
3 files changed
+62
-5
No files matched your search
+4
-3
@@ -78,9 +78,10 @@ screenshots, a file upload (checked on the Frame), a background install job, and
|
||||
the power password check (a wrong password is refused). The server on the Frame
|
||||
exits within seconds of the app closing.
|
||||
|
||||
Against a stand-in built on Valve's Holo Core aarch64 base
|
||||
([tests/frame-container](../tests/frame-container)), since Valve publishes no
|
||||
Frame OS image: pairing with the password (key added with the right
|
||||
Against Valve's own Steam Frame OS (SteamOS 0.3.0 build 20260922.5152327, the
|
||||
`rootfs-A` partition of the Frame recovery image, run with its own sshd; see
|
||||
[tests/frame-container](../tests/frame-container)), and a Holo Core stand-in:
|
||||
pairing with the password (key added with the right
|
||||
permissions, host key pinned, password stored nowhere), the power password
|
||||
check (a wrong or missing password refused; the right one reaches `systemctl`),
|
||||
a changed host key refused with "Pair with the Frame again", and a wrong
|
||||
|
||||
@@ -1,6 +1,27 @@
|
||||
# A Frame stand-in for testing without the headset
|
||||
# Testing without the headset
|
||||
|
||||
Valve publishes no Steam Frame OS image. This builds the closest thing: Valve and
|
||||
## Valve's own Frame OS, from its recovery image
|
||||
|
||||
Valve publishes a Steam Frame recovery image at
|
||||
https://steamdeck-images.steamos.cloud/recovery/ (`steamframe-oobe-repair-*.img.bz2`,
|
||||
~4 GB). `frame-image.sh` extracts its `rootfs-A` partition (btrfs), mounts it
|
||||
read-only with a throwaway writable layer, and starts the image's own sshd on
|
||||
port 2223, so the iPhone app can pair with, and run its server on, the real
|
||||
SteamOS for Frame userland (Python, sudo, sshd, PAM). It needs Linux with btrfs,
|
||||
e.g. Colima's VM on a Mac:
|
||||
|
||||
```sh
|
||||
colima start --arch aarch64 --vm-type vz
|
||||
colima ssh -- sudo sh tests/frame-container/frame-image.sh ~/Downloads/steamframe-oobe-repair-<build>.img.bz2
|
||||
# pair with 127.0.0.1:2223, user steamos, password frame-test-pw
|
||||
```
|
||||
|
||||
The image's kernel is built for the Frame's Qualcomm chip, so this runs its
|
||||
userland, not the whole OS: no SteamVR, Steam client, battery or Lepton.
|
||||
|
||||
## Holo Core stand-in
|
||||
|
||||
A lighter option: Valve and
|
||||
Collabora's [Holo Core aarch64 preview](https://www.collabora.com/news-and-blog/news-and-events/building-an-arch-linux-aarch64-port-for-holo-core.html)
|
||||
(the Arch Linux ARM64 base the Frame's SteamOS is built on) with the Frame's SSH
|
||||
surface: a `steamos` user with a password and sudo, OpenSSH taking keys and
|
||||
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
#!/bin/sh
|
||||
# Run Valve's own Steam Frame OS, from its recovery image, as an SSH target for
|
||||
# testing (see README.md). Run on a Linux host or VM with btrfs, as root:
|
||||
# frame-image.sh steamframe-oobe-repair-<build>.img.bz2
|
||||
# It extracts the rootfs-A partition, mounts it read-only, adds a throwaway
|
||||
# writable layer, and starts the image's own sshd on port 2223 (user steamos,
|
||||
# password frame-test-pw). systemctl only records what it's asked.
|
||||
set -e
|
||||
command -v bzcat >/dev/null && command -v python3 >/dev/null || {
|
||||
command -v apt-get >/dev/null && apt-get install -y -qq bzip2 python3 >/dev/null; }
|
||||
IMG=${1:?recovery .img.bz2}; RAW=${RAW:-$(dirname "$IMG")/frame-rootfs-A.img}
|
||||
if [ ! -f "$RAW" ]; then
|
||||
# Partition 3 (rootfs-A) from the image's GPT: start and size in 512-byte sectors.
|
||||
set -- $(bzcat "$IMG" | head -c 1048576 | python3 -c '
|
||||
import struct,sys; d=sys.stdin.buffer.read(); e=d[1024+2*128:1024+3*128]
|
||||
a,b=struct.unpack("<QQ",e[32:48]); print(a, b-a+1)')
|
||||
bzcat "$IMG" | tail -c +$(( $1 * 512 + 1 )) | head -c $(( $2 * 512 )) > "$RAW"
|
||||
fi
|
||||
R=/mnt/frame; O=/var/lib/frame-ovl; M=/srv/frame
|
||||
mkdir -p $R $O/upper $O/work $M
|
||||
mountpoint -q $R || mount -o ro -t btrfs "$(losetup -f --show -r "$RAW")" $R
|
||||
mountpoint -q $M || mount -t overlay overlay -o lowerdir=$R,upperdir=$O/upper,workdir=$O/work $M
|
||||
for d in proc sys dev dev/pts; do mountpoint -q $M/$d || mount --rbind /$d $M/$d; done
|
||||
mountpoint -q $M/run || mount -t tmpfs tmpfs $M/run
|
||||
mountpoint -q $M/tmp || mount -t tmpfs tmpfs $M/tmp
|
||||
mkdir -p $M/run/sshd $M/home/steamos $M/usr/local/bin
|
||||
chroot $M chown 1000:1000 /home/steamos
|
||||
echo 'steamos:frame-test-pw' | chroot $M chpasswd
|
||||
chroot $M ssh-keygen -A >/dev/null
|
||||
# No systemd here: systemctl records power requests instead of acting.
|
||||
printf '#!/bin/sh\necho "systemctl $*" >> /tmp/power-requests.log\n' > $M/usr/local/bin/systemctl
|
||||
chmod +x $M/usr/local/bin/systemctl
|
||||
pkill -f "[s]shd -p 2223" 2>/dev/null || true
|
||||
chroot $M /usr/bin/sshd -p 2223 -E /tmp/sshd.log
|
||||
echo up
|
||||
Reference in new issue
Block a user