Steam Link Development

💰 Intro - Inexpensive device

The Steam Link was recently put on sale for $15, and I purchased several of them at that price, because the hardware seems worthwhile to me at that cost.

Shortly after that, during black friday of 2017, the price fell even cheaper to $5. Shipping from Steam directly costs $7, so the overall cost shipped was $12 directly from Steam in the USA.

At such a low price, the Steam Link becomes a device worthy of tinkering with and pulling out its potential. It is only a single core 1ghz device, but it does have a Vivante GC1000 GPU that is capable of basic graphics acceleration. As such it can handle emulating a wide variety of console games.

I looked into making the Steam Link become a lower powered equivalent of a Raspberry Pie device running RetroPie. I found people have already compiled RetroArch and some emulation cores to run directly on the device, thanks to the provision of a SDK for native app development by Valve that was provided 2 years ago ( in 2015 ).

🕹 Lets emulate! EmulationStation

With a bit of hacking I was able to compile EmulationStation to run on the Steam Link as well. It was painful and required monkeying with the build process a bunch, but I was able to get it working. The result of that work is a tarball of the app from my Steamlink: emustation.tar.bz2 Download that and extract it into /home/apps to get it working.

You will note that the provided file is not a tgz file. It cannot be dropped on a usb stick and be picked up by the Steam Link automatically. I will clean up the file and make a version like that soon enough. For now you will need to enable ssh on your device and do the following steps to get it installed:

  1. Enable ssh on your Steam Link.
  2. Download the file emustation.tar.bz2
  3. Copy the file to your device through sftp to /home/apps
  4. Extract it using 'tar -xf emustation.tar.bz2'
  5. Delete the .tar.bz2 file as it is no longer needed
  6. Create a roms folder in /home/steam/roms, with 'nes' and 'snes' folders under it
  7. Copy your legally acquired roms into the roms folders you created.
  8. Reboot your steam link to have the icon for EmulationStation show up
  9. Run it, and run the scraper to pull down the images/metadata for your ROMs
  10. Download RetroArch + cores from google drive ( provided by IncognitoMan )
    See steam forum discussion for more information.
  11. Alter the core configuration to contain/use the core you desire.
    Edit /home/apps/emustation/.home/.emulationstation/es_systems.cfg
    Note that the current file above does not have a correctly configured snes emulator setup. To get snes working you will need to alter the cfg file to point it to a working core on your device.

Share apps others can install

Suppose you want to create a small shellscript others can use easily on the steamlink. How do you do this? This is how:

How they install it: How does that app actually get run by the steam link?
( note the following is a cleaned up version and not exactly what happens )

🐧 Debian Linux

One of the nice things you can do with the Steam Link is easily enable ssd on it and ssh into it. A lot of basic tooling is enabled there, but many things are also lacking. It does not come with what could be considered the typical GNU toolset.

From a broad perspective, you can consider a Steam Link as just a Arm power device with some custom device connected to the CPU. The specific variant of Arm on it is Arm 7 Hard Float. More specifically Neon with SFP version 3 extensions are supported. Many Linux distributions have binary packages available for Arm7, both with and without hard float. Soft float means that floats are emulated. Hard float means that there is support for hardware floats despite not being 64-bit. So, code compiled for either variant of Arm7 will work on the Steam Link.

What this means is that you can take binary packages from existing Linux distributions, and run them on the Steam Link after extracting them, as long as you also extract all of their dependent binaries as well. Now, optimally, you want to avoid packages compiled against kernel features newer than the Linux kernel running on the Steam Link. Interestingly though, most basic utilities do not care that much about which kernel they are running on.

The process of getting a basic set of packages running on a new device is called bootstrapping. It is well known for many variants of Linux. I found a site online where someone made a bootstrap package set for the Steam Link from arch. You can download that, chroot into it, and run basic Arch. Not only that, you can easily download and run additional Arch packages of your choice with the Arch package manager, pacman.

I decided to take this one step further and bootstrap another OS to the Steam Link. I used Debian, running deboostrap, and was easily able to produce a arm7hf bootstrap package set for the Steam Link. With a bit of tinkering I was able to make package fetch and installation with apt-get work as well.

Will post the full process and steps to doing this soon. Stay tuned.

📜 Boot Process

The Steam Link does an interesting thing when it boots. It checks for a plugged in USB stick and it will install tarballs off that device. Additionally, it will automatically run some code on the USB device as well. This is intended to make it possible to easily add native apps to the Steam Link, enable ssh on it, and run testing of the device ( I assume they do this as a final step before shipping the things out )

What is amazing is that they allow this at all. Many similar device, such as Chromecast, allow no such extensions of the device. Certainly most device prevent you from gaining ssh access easily and monkeying with the internal binaries on the device. The Steam Link does not have those protections.

The bootloader is of course locked. Only a signed kernel from Valve can be run. This means we are stuck on an old kernel for the device, and also forced to use binary drivers for graphics that have no freely available source. Despite that, the rest of the system could theoretically be replaced. You can easily turn the Steam Link into a basic Linux machine, removing the Steam Link software itself and repurposing it to do something entirely different.

I doubt Valve intended for people to do this, but they made it possible. I for one am having fun hacking the thing, and will happily share my research and progress with making the Steam Link a much more useful device.

⛏ Replacing the Kernel

Root access is available automatically after enabling ssh on the Steam Link. As a result, it should be possible to dynamically reload a replacement Linux kernel instead of the one provided by Valve.

There are two primary ways that a kernel is updated dynamically on Linux. The first is using ksplice. Ksplice is a proprietary method that dynamically patches portions of the Linux kernel as it is running. It is not open source and using it on the Steam Link would be difficult if not impossible.

The second method is to use kexec. Kexec is a Linux kernel feature that allows to to specify a new kernel and dynamically load into it. Unfortunately kexec is not built into the kernel provided by Valve.

Despite kexec not being built in, we are still able to install kernel mods via insmod. Since we can, I believe it should be possible to take the kexec code and compile it as a kernel mod. In all likelyhood a manual kexec can then be done directly from the init routine of that kernel mod. What that would cause is for the kernel to be swapped immediately when the kernel mod is loaded.

It is not clear if a standard kernel compiled for armhf would work properly. Even supposing we can dynamically swap the kernel, it would be good to know what modifications Valve has done to the kernel they provided, and why. Those changes are likely important and would have to also be done on a more up to date kernel for everything to work properly.

⛏ How to kexec

As suspected, kexec can be built as a kernel mod. It was done over 2 years ago for the Kindle Fire. Github code for that can be seen here

Lukas2511 on github modified that code some already and built a working kexec.so kernel mod. Prebuilt binary working on Steam Link can be grabbed from github here

For whatever reason, kexec initiated in a chroot over ssh does not work and results in the Steam Link shutting down. kexec trigger in init.d startup scripts does work and successfully will boot to a new kernel.

Basic arch Linux arm7 initramfs works fine in order to initiate kexec. Additionally, mkinitcpio from arch also works fine when combined with lib/modules from a Kernel build of your choice.

Working versions of these things that I have built/put together:

Working kexec line:

kexec -l zImage --initrd=initramfs.img --dtb=steamlink.dtb

A full tgz that can be deployed to an ext4 formatted usb drive to use in combination with the above is here. I am hosting it here at the moment, but will likely switch to torrent seeding if/when people swamp my server downloading it.

This arch installation is setup for dhcp through ethernet. There is no graphics output; all you will get is a black screen after kexec. Initial kexec/bootup can take almost 2 minutes if you have a slow usb drive. Be patient, and watch your router to see what IP is picked up by the Steam Link.

If you don't have a Linux machine to easily deploy the tgz to a USB stick, and want to get started easily, I have created a minimal Debian VirtualBox VM for development. You can fetch that here. Instructions on how to set that up coming soon. Basically just make a new VM and set the extracted disk image from that 7z archive as the main drive. The root pw for this image is 'steamroot'. The network driver should be configured to gigabit server.

Build a Kernel and modules

The basic steps to follow to build a kernel for the Steamlink are as follows: