Infecting the Steam Link with NixOS

Lobsters Hottest Tools

Summary

The article describes how to install NixOS on a Steam Link device by using a custom kernel module and kexec to bypass bootloader restrictions, repurposing the Arm hardware for general use.

<p><a href="https://lobste.rs/s/wpv5ed/infecting_steam_link_with_nixos">Comments</a></p>
Original Article
View Cached Full Text

Cached at: 09/26/26, 03:26 PM

# Infecting the Steam Link with NixOS Source: [https://feyor.sh/blog/infecting-the-steam-link-with-nixos/](https://feyor.sh/blog/infecting-the-steam-link-with-nixos/) While rummaging through my closet the other day I discovered a[Steam Link](https://en.wikipedia.org/wiki/Steam_Link#Hardware_device)I had bought on flash sale way back in 2018 still dutifully humming away all these years later\. It occured to me that having an always\-on low power Arm device with Ethernet, WiFi, Bluetooth, and several USB ports would be handy, so thus began my journey to get NixOS running on the Steam Link\. As it turns out, a fellow named[fijam](https://heap.ovh/getting-linux-on-valve-steam-link.html)already figured out the hard parts involved in running a custom Linux distro on the Steam Link\. The most notable obstacle is that the bootloader will only boot kernels signed by Valve; to get around this, we can boot into the Valve\-blessed kernel and thenkexecour new kernel\. However, the kernel shipped with the Steam Link was not built with`CONFIG\_KEXEC`enabled\. This is where things get*really*clever: we can cobble the pertinent kexec source files into a minimal kernel module that adds thekexecsyscall to the running system\! Several people have successfully used this technique to get other distros[1](https://feyor.sh/blog/infecting-the-steam-link-with-nixos/#fn:1)booting, but they all seem to have just copied thekexecbinary and kernel module from fijam’s website\. fijam seems like a lovely person and all, but I’m wary of downloading kernel modules from the interwebs so I decided to compile it myself\. ## Booting the thing Compiling a NixOS userspace and kernel/initrd is pretty simple; you just pass the correctsystem\(and because I’m using\_\_splicedPackages/crossSystem, alsopkgs\) tolib\.nixosSystemand add your modules\. Choosing the target architecture was slightly less straightforward: Valve’s steamlink toolchain uses`armv7a`, but importing nixpkgs withcrossSystem\.config = “armv7a\-unknown\-linux\-gnueabihf”interacts[poorly with the Go build plumbing](https://github.com/NixOS/nixpkgs/blob/fbe840e7184ed15fd5b1ca8f1a8746462a38d59c/lib/systems/default.nix#L596-L599), so I used the \(seemingly\) equivalent`armv7l`instead\. Nix``` { inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; outputs = { self, nixpkgs }: let inherit (nixpkgs) lib; system = "armv7l-linux"; # hostSystem should be linux but does not have to be arm (x86 should work) hostSystem = "aarch64-linux"; pkgs = (import nixpkgs { system = hostSystem; crossSystem = { config = "armv7l-unknown-linux-gnueabihf"; }; }).__splicedPackages; in { nixosConfigurations.steamlink = lib.nixosSystem { inherit system pkgs; modules = [ # ... ]; }; }; } ``` The real challenge is compiling a kernel module for a vendored fork of a 13 year old kernel; the[NixOS wiki](https://wiki.nixos.org/wiki/Linux_kernel#Packaging_out-of-tree_kernel_modules)is actually pretty helpful here and points out some footguns related to the default hardening flags in stdenv\. Nix``` kexecMod = let inherit (pkgs) stdenv; inherit (self.nixosConfigurations.steamlink.config.system.build) kernel oldKernel; in stdenv.mkDerivation { pname = "kexec_mod"; version = "0.0.1"; src = ./kexec_mod; postPatch = '' for f in machine_kexec.c kexec.c relocate_kernel.S; do substituteInPlace "$f" --subst-var-by KERNEL ${oldKernel} done ''; nativeBuildInputs = kernel.moduleBuildDependencies; makeFlags = [ "ARCH=${stdenv.hostPlatform.linuxArch}" "CROSS_COMPILE=${stdenv.cc.targetPrefix}" "KDIR=${oldKernel}" "INSTALL_MOD_PATH=$(out)" ]; env.NIX_CFLAGS_COMPILE = toString [ "-std=gnu89" "-fno-pie" ]; inherit (kernel) hardeningDisable; meta = { description = "kexec functionality as a kernel module for old kernels"; homepage = "https://github.com/lukas2511/steamlink-sdk"; license = lib.licenses.gpl2; platforms = [ system ]; }; }; ``` \(See[Files](https://feyor.sh/blog/infecting-the-steam-link-with-nixos/#files)for the kexec\_mod source code\.\) In order to get this to build we need to point Kbuild to a Linux kernel checkout that has been built withmake modules[2](https://feyor.sh/blog/infecting-the-steam-link-with-nixos/#fn:2)\. \(Note that I’m using themoduleBuildDependenciesattribute of the comparatively modernkernelfrom my NixOS configuration\.\) Nix``` oldKernel = let inherit (pkgs) stdenv fetchFromGitHub buildPackages fetchpatch writeText; inherit (self.nixosConfigurations.steamlink.config.system.build) kernel; in stdenv.mkDerivation { pname = "linux-steamlink"; version = "3.8.13"; src = fetchFromGitHub { owner = "ValveSoftware"; repo = "steamlink-sdk"; rootDir = "kernel"; rev = "62b4d098d1472c3534dd098ca2a0e0e10712f1c6"; hash = "sha256-3Q8JjNmkRFCkdt8E+ol+E/c2sy+X5I7UYhsHAfYBdWs="; }; sourceRoot = "source"; patches = [ (fetchpatch { url = "https://gitlab.com/postmarketOS/pmaports/-/raw/aa289aa350071e6afc54f6b6704ba28971b50466/device/.shared-patches/linux/linux3.4-ARM-8933-1-replace-Sun-Solaris-style-flag-on-section.patch"; hash = "sha256-KRNI4070H0AFMCZl7pYnIbin6lbp68/xuf6yOPvmYdI="; }) (fetchpatch { url = "https://gitlab.com/postmarketOS/pmaports/-/raw/aa289aa350071e6afc54f6b6704ba28971b50466/device/.shared-patches/linux/gcc10-extern_YYLOC_global_declaration.patch"; hash = "sha256-9hq5xGeJRL/ESHofOh4MAOAGV2IlDRYvvpxyxk3MXlw="; }) (writeText "0001-gcc-bug85745.diff" '' diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 74b17d0..dc64fa2 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -164,7 +164,7 @@ #define __put_user_check(x,p)''\t''\t''\t''\t''\t''\t''\t${"\\"} ''\t({''\t''\t''\t''\t''\t''\t''\t''\t${"\\"} ''\t''\tunsigned long __limit = current_thread_info()->addr_limit - 1; ${"\\"} -''\t''\tregister const typeof(*(p)) __r2 asm("r2") = (x);''\t${"\\"} +''\t''\tregister typeof(*(p)) __r2 asm("r2") = (x);''\t${"\\"} ''\t''\tregister const typeof(*(p)) __user *__p asm("r0") = (p);${"\\"} ''\t''\tregister unsigned long __l asm("r1") = __limit;''\t''\t${"\\"} ''\t''\tregister int __e asm("r0");''\t''\t''\t''\t${"\\"} '') ]; postPatch = '' substituteInPlace arch/arm/boot/compressed/piggy.xzkern.S --replace-fail '#alloc' ' "a"' substituteInPlace arch/arm/mach-berlin/Makefile.boot --replace-fail '/bin/bash' '${stdenv.shell}' substituteInPlace arch/arm/boot/compressed/Makefile --replace-fail '${"\t"}@$(check_for_multiple_zreladdr)' '${"\t"}echo LDFLAGS_vmlinux = ''${LDFLAGS_vmlinux}${"\n\t"}@$(check_for_multiple_zreladdr)' cp include/linux/compiler-gcc4.h include/linux/compiler-gcc${lib.versions.major buildPackages.stdenv.cc.version}.h ''; inherit (kernel) nativeBuildInputs; depsBuildBuild = [ buildPackages.stdenv.cc ]; makeFlags = [ "ARCH=${stdenv.hostPlatform.linuxArch}" "LOCALVERSION=-mrvl" "CROSS_COMPILE=${stdenv.cc.targetPrefix}" ]; env.NIX_CFLAGS_COMPILE = toString [ "-std=gnu89" "-Wno-error=address" "-Wno-error=dangling-pointer" "-Wno-error=missing-attributes" ]; inherit (kernel) hardeningDisable; configurePhase = '' make bg2cd_penguin_mlc_defconfig $makeFlags echo "CONFIG_KEXEC=y" >> .config echo "CONFIG_KERNEL_XZ=y" >> .config make olddefconfig $makeFlags ''; postBuild = '' make modules $makeFlags -j$NIX_BUILD_CORES ''; installPhase = '' mkdir $out cp -r * $out/ ''; dontFixup = true; }; ``` It took several hacks to get things building on a modern version of GCC, but eventually I was able to get the 3\.8\.13\-mrvl kernel and the kexec\_mod kernel module building\. Now that we have`kexec\_mod\.ko`, we need our new initrd and kernel \(which all come from our NixOS config\), the device tree blob for the Steam Link \(which has been[upstreamed](https://github.com/torvalds/linux/blob/6812ce4e4379ffc99c52401ec28f0d7ffbc36206/arch/arm/boot/dts/synaptics/berlin2cd-valve-steamlink.dts)to Linux so we can get it fromhardware\.deviceTree\.package\), a copy of thekexecuserland binary \(compiled withpkgsStaticso we can run it on non\-NixOS\), and a small script to tie everything together: Bash``` fts-set steamlink.crashcounter 0 # required to prevent factory reset after a few reboots mkdir -p /mnt/disk/proc /mnt/disk/sys /mnt/disk/dev mount -t proc proc /mnt/disk/proc mount -o rbind /sys /mnt/disk/sys mount -o rbind /dev /mnt/disk/dev insmod /mnt/disk/kexec_load.ko chroot /mnt/disk/ /kexec --load /zImage \ --initrd /initrd \ --dtb /berlin2cd-valve-steamlink.dtb \ --command-line "init=/init root=/dev/sda2 rootwait rw usbcore.autosuspend=-1" chroot /mnt/disk/ /kexec -e ``` You could juggle these files manually and upload them to a USB drive yourself, but it’s much easier to use the[sd\-image](https://github.com/NixOS/nixpkgs/blob/5f5458dc42bf4391dc5f85e7682decb8c78e8756/nixos/modules/installer/sd-card/sd-image.nix)NixOS module to create a disk image instead: Nix``` usb-image = { modulesPath, config, ... }: { imports = [ (modulesPath + "/installer/sd-card/sd-image.nix") ]; image.extension = lib.mkForce "img"; sdImage = let dtb = "berlin2cd-valve-steamlink.dtb"; kexecScript = ./kexec-nixos; inherit (config.system.build) kernel initialRamdisk; in { compressImage = false; firmwarePartitionName = "STEAMLINK"; rootVolumeLabel = "NIXOS"; populateFirmwareCommands = '' pushd firmware files=( ${kernel}/${config.system.boot.loader.kernelFile} ${initialRamdisk}/${config.system.boot.loader.initrdFile} ${config.hardware.deviceTree.package}/${dtb} ${self.packages.${system}.kexecMod}/lib/modules/3.8.13-mrvl/extra/kexec_load.ko ${pkgs.pkgsStatic.kexec-tools}/bin/kexec ) for f in ''${files[@]}; do cp $f ./ done # factory_test/run.sh will run before this has a chance to # enable ssh; uncomment if not booting straight into NixOS # mkdir -p steamlink/config/system # touch steamlink/config/system/enable_ssh.txt mkdir -p steamlink/factory_test cp ${kexecScript} steamlink/factory_test/run.sh popd ''; populateRootCommands = ""; }; }; ``` Testing that thekexechandoff works was really tricky because the HDMI output doesn’t work with the kernel I’m using, and since I decided not to open up the device to get at the UART I was flying completely blind\. I decided to test with a minimal \(slop\) Busybox\-based initramfs that rebooted after a variable amount of time to indicate success\. Nix``` initramfs = pkgs.buildPackages.runCommand "build-initramfs" {} '' mkdir initramfs; cd initramfs mkdir -pv {etc,proc,sys,usr/{bin,sbin}} cp -a ${pkgs.pkgsStatic.busybox}/{bin,sbin} . chmod 755 ./{bin,sbin} cat <<EOF > init #!/bin/sh mount -t proc none /proc mount -t sysfs none /sys mount -t devtmpfs devtmpfs /dev mkdir -p /mnt try_mount() { dev="$1" fs="$2" if [ "$fs" = auto ]; then mount -o rw "$dev" /mnt 2>/dev/null || return 1 else mount -t "$fs" -o rw "$dev" /mnt 2>/dev/null || return 1 fi marker=kexec-mounted-ok if [ -f /mnt/zImage ]; then marker=kexec-steamlink-ok fi { echo "device=$dev" echo "fs=$fs" cat /proc/partitions } > "/mnt/$marker" 2>/dev/null && sync umount /mnt sleep 10 reboot -f } for dev in /dev/mmcblk*p* /dev/sd[a-z][0-9]* /dev/vd[a-z][0-9]*; do [ -b "$dev" ] || continue try_mount "$dev" vfat try_mount "$dev" ext4 try_mount "$dev" auto done sleep 45 reboot -f EOF chmod +x init find . -print0 | ${lib.getExe pkgs.buildPackages.cpio} --null -ov --format=newc > $out ''; ``` Once I knew that worked, I switched to the NixOS initrd withboot\.initrd\.network\.enable = trueand used a Netcat based reverse shell to my laptop’s IP for further debugging\. Nix``` debugModule = { lib, ... }: { boot.initrd.systemd.enable = lib.mkForce false; boot.initrd.kernelModules = [ "pxa168_eth" ]; boot.initrd.availableKernelModules = [ "reset_berlin" ]; boot.initrd.network.enable = true; boot.initrd.network.udhcpc.enable = false; boot.kernelParams = [ "ip=192.168.2.2::192.168.2.1:255.255.255.0:stm-link:eth0:off" ]; boot.initrd.network.postCommands = '' mac_peer=192.168.2.1 stm_link_ip=192.168.2.2 echo "initrd net debug: interfaces: $(ls /sys/class/net)" > /dev/kmsg for iface_path in /sys/class/net/*; do iface="''${iface_path##*/}" [ "$iface" != lo ] || continue echo "initrd net debug: configuring $iface" > /dev/kmsg ip link set dev "$iface" up || true ip address flush dev "$iface" || true ip address add "$stm_link_ip/24" dev "$iface" || true done ( while true; do ping -c 1 -W 1 "$mac_peer" sleep 2 done ) & ( while true; do rm -f /tmp/revsh mkfifo /tmp/revsh /bin/ash -i < /tmp/revsh 2>&1 | nc "$mac_peer" 4444 > /tmp/revsh rm -f /tmp/revsh sleep 2 done ) & ''; }; ``` The main things I needed to figure out at this stage were adding`reset\_berlin`toboot\.initrd\.availableKernelModulesto allow reading from the USB drive and using the old NixOS initrd system in lieu of the new systemd\-based version \(boot\.initrd\.systemd\.enable = lib\.mkForce false\)\. Finally I was able to boot into userspace and connect over SSH\! 🥳 That having been said, the USB image I was booting from was weighing in at a hefty 2\.3GB… surely we can do better\. ## Trimming the fat I was surprised that there wasn’t a definitive guide for reducing NixOS closure sizes; I found some NixOS Discourse questions and a few blog posts, but the most useful writeups were[NixOS is a good server OS, except when it isn’t](https://sidhion.com/blog/nixos_server_issues)and[I can haz smoller NixOS ISOs?](https://natkr.com/2026-06-19-nixos-but-smol/)\. Those are good resources, but because we’re targeting actual hardware instead of a VM we must necessarily be more conservative in what we cut\. Nix``` minimal = { modulesPath, pkgs, ... }: { imports = [ (modulesPath + "/profiles/minimal.nix") (modulesPath + "/profiles/headless.nix") # (modulesPath + "/profiles/perlless.nix") ]; disabledModules = [ (modulesPath + "/profiles/base.nix") ]; boot.loader = { grub.enable = false; systemd-boot.enable = false; supportsInitrdSecrets = false; }; boot.initrd.systemd.enable = lib.mkForce false; boot.initrd.availableKernelModules = lib.mkForce [ "reset_berlin" "uas" ]; boot.kernelModules = [ "pxa168_eth" "mwifiex_sdio" "btmrvl_sdio" ]; hardware.firmware = lib.mkForce (with pkgs; [ (runCommand "marvell-firmware" {} '' mkdir -p $out/lib/firmware/mrvl cp ${linux-firmware}/lib/firmware/mrvl/sd8897_uapsta.bin $out/lib/firmware/mrvl/ '') wireless-regdb ]); documentation.enable = false; programs.command-not-found.enable = lib.mkDefault false; networking.networkmanager.enable = false; networking.firewall.enable = false; xdg.icons.enable = false; xdg.mime.enable = false; xdg.sounds.enable = false; fonts.fontconfig.enable = false; programs.nano.enable = false; system.disableInstallerTools = true; system.switch.enable = false; system.nixos-init.enable = false; nix.enable = false; systemd.services.register-nix-paths = lib.mkForce {}; }; ``` Here are the main things that came up during the slim\-ening: - We only need one firmware blob from the massivelinux\-firmwarepackage \(1\.8GB compressed\!\), so we can save a huge amount of space by only adding that blob tohardware\.firmware- On a similar note it should be possible to use a kconfig tailored for the Steam Link hardware to build a smaller kernel, but this seemed like more trouble than it was worth - OpenSSH does not seem to like it wheni18n\.glibcLocalesor thesecurity\.wrappersmodule are removed - Thekexecboot flow renders most of the NixOS system administration utilities irrelevant; as a matter of fact, Nix itself is not very useful on such a system, so we can save space by getting rid of that too - I feel like it should be possible to disableboot\.initrdandboot\.kernelbecause we provide the kernel/initrd/DTB from the FAT32 partition when wekexec, but I was never able to disable these without breaking the boot process - If I could switch to the systemd\-based initrd I could enable the “perlless” NixOS module to remove Perl from the system closure for additional savings After reaching a point of diminshing returns and most new changes breaking my system, I declared the 1\.2GB disk image I had to be “good enough”\. ## Files The Nix flake I used and the source for thekexec\_modkernel module can be downloaded[here](https://feyor.sh/infecting-the-steam-link-with-nixos/steamlink-nixos.tar.gz)\. The same`flake\.nix`is reproduced below for your convenience\. Nixflake\.nix ``` { inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; outputs = { self, nixpkgs }: let inherit (nixpkgs) lib; system = "armv7l-linux"; # hostSystem should be linux but does not have to be arm (x86 should work) hostSystem = "aarch64-linux"; pkgs = (import nixpkgs { system = hostSystem; crossSystem = { config = "armv7l-unknown-linux-gnueabihf"; }; overlays = [ # https://github.com/NixOS/nixpkgs/issues/388309 (self: super: { efivar = self.emptyDirectory; efibootmgr = self.emptyDirectory; }) ]; }).__splicedPackages; in { nixosModules = { # https://sidhion.com/blog/nixos_server_issues # https://discourse.nixos.org/t/how-to-have-a-minimal-nixos/22652/4 minimal = { modulesPath, pkgs, ... }: { imports = [ (modulesPath + "/profiles/minimal.nix") (modulesPath + "/profiles/headless.nix") ]; disabledModules = [ (modulesPath + "/profiles/base.nix") ]; boot.loader = { grub.enable = false; systemd-boot.enable = false; supportsInitrdSecrets = false; }; # systemd initrd did not work for me; you could add the perlless profile if you got it working boot.initrd.systemd.enable = lib.mkForce false; boot.initrd.availableKernelModules = lib.mkForce [ "reset_berlin" "uas" ]; boot.kernelModules = [ "pxa168_eth" "mwifiex_sdio" "btmrvl_sdio" ]; hardware.firmware = lib.mkForce (with pkgs; [ (runCommand "marvell-firmware" {} '' mkdir -p $out/lib/firmware/mrvl cp ${linux-firmware}/lib/firmware/mrvl/sd8897_uapsta.bin $out/lib/firmware/mrvl/ '') wireless-regdb ]); documentation.enable = false; programs.command-not-found.enable = lib.mkDefault false; networking.networkmanager.enable = false; networking.firewall.enable = false; xdg.icons.enable = false; xdg.mime.enable = false; xdg.sounds.enable = false; fonts.fontconfig.enable = false; programs.nano.enable = false; system.disableInstallerTools = true; system.switch.enable = false; system.nixos-init.enable = false; nix.enable = false; systemd.services.register-nix-paths = lib.mkForce {}; }; usb-image = { modulesPath, config, ... }: { imports = [ (modulesPath + "/installer/sd-card/sd-image.nix") ]; # in theory it should be possible to disable the kernel # and initrd for the nixos rootfs for some significant # space savings (because we're passing a copy of the # kernel and initrd from the STEAMLINK partition to kexec # directly, but in practice I never got that working) boot.kernelParams = [ "root=/dev/disk/by-label/${config.sdImage.rootVolumeLabel}" "rootwait" "rw" "usbcore.autosuspend=-1" ]; image.extension = lib.mkForce "img"; sdImage = let dtb = "berlin2cd-valve-steamlink.dtb"; kexecScript = pkgs.buildPackages.writeScript "kexec-nixos" '' #!/bin/sh fts-set steamlink.crashcounter 0 mkdir -p /mnt/disk/proc /mnt/disk/sys /mnt/disk/dev mount -t proc proc /mnt/disk/proc mount -o rbind /sys /mnt/disk/sys mount -o rbind /dev /mnt/disk/dev insmod /mnt/disk/kexec_load.ko chroot /mnt/disk/ /kexec --load /zImage \ --initrd /initrd \ --dtb /berlin2cd-valve-steamlink.dtb \ --command-line "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}" chroot /mnt/disk/ /kexec -e ''; inherit (self.packages.${system}) kernel initialRamdisk; in { compressImage = false; firmwarePartitionName = "STEAMLINK"; rootVolumeLabel = "NIXOS"; populateFirmwareCommands = '' pushd firmware files=( ${kernel}/${config.system.boot.loader.kernelFile} ${initialRamdisk}/${config.system.boot.loader.initrdFile} ${config.hardware.deviceTree.package}/${dtb} ${self.packages.${system}.kexecMod}/lib/modules/3.8.13-mrvl/extra/kexec_load.ko ${pkgs.pkgsStatic.kexec-tools}/bin/kexec ) for f in ''${files[@]}; do cp $f ./ done # factory_test/run.sh will run before this has a chance to # enable ssh; uncomment if not booting straight into NixOS # mkdir -p steamlink/config/system # touch steamlink/config/system/enable_ssh.txt mkdir -p steamlink/factory_test cp ${kexecScript} steamlink/factory_test/run.sh popd ''; populateRootCommands = ""; }; }; }; nixosConfigurations.steamlink = lib.nixosSystem { inherit system pkgs; modules = [ self.nixosModules.minimal self.nixosModules.usb-image ({ ... }: { # your NixOS config here! services.tailscale.enable = true; services.openssh = { # might be able to remove security wrappers if using static openssh # see https://sidhion.com/blog/nixos_server_issues#:~:text=While%20looking%20through%20the%20lvm%20stuff # package = pkgs.pkgsStatic.openssh; enable = true; settings = { PermitRootLogin = "yes"; }; }; users.users.root.openssh.authorizedKeys.keys = [ "..." ]; hardware.bluetooth.enable = true; networking = { hostName = "steamlink"; useDHCP = true; interfaces.eth0 = { useDHCP = true; # prefer DHCP but use a static IP for debugging over a direct ethernet serial line to your host machine ipv4.addresses = [{ address = "169.254.31.216"; prefixLength = 16; }]; }; wireless = { enable = true; networks = { "WiFi" = { psk = "hunter2"; }; }; }; }; }) ]; }; packages.${system} = { inherit (self.nixosConfigurations.steamlink.config.system.build) kernel initialRamdisk sdImage; default = self.packages.${system}.sdImage; oldKernel = let inherit (pkgs) stdenv fetchFromGitHub buildPackages fetchpatch writeText; inherit (self.packages.${system}) kernel; in stdenv.mkDerivation { pname = "linux-steamlink"; version = "3.8.13"; src = fetchFromGitHub { owner = "ValveSoftware"; repo = "steamlink-sdk"; rootDir = "kernel"; rev = "62b4d098d1472c3534dd098ca2a0e0e10712f1c6"; hash = "sha256-3Q8JjNmkRFCkdt8E+ol+E/c2sy+X5I7UYhsHAfYBdWs="; }; sourceRoot = "source"; patches = [ (fetchpatch { url = "https://gitlab.com/postmarketOS/pmaports/-/raw/aa289aa350071e6afc54f6b6704ba28971b50466/device/.shared-patches/linux/linux3.4-ARM-8933-1-replace-Sun-Solaris-style-flag-on-section.patch"; hash = "sha256-KRNI4070H0AFMCZl7pYnIbin6lbp68/xuf6yOPvmYdI="; }) (fetchpatch { url = "https://gitlab.com/postmarketOS/pmaports/-/raw/aa289aa350071e6afc54f6b6704ba28971b50466/device/.shared-patches/linux/gcc10-extern_YYLOC_global_declaration.patch"; hash = "sha256-9hq5xGeJRL/ESHofOh4MAOAGV2IlDRYvvpxyxk3MXlw="; }) (writeText "0001-gcc-bug85745.diff" '' diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 74b17d0..dc64fa2 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -164,7 +164,7 @@ #define __put_user_check(x,p)''\t''\t''\t''\t''\t''\t''\t${"\\"} ''\t({''\t''\t''\t''\t''\t''\t''\t''\t${"\\"} ''\t''\tunsigned long __limit = current_thread_info()->addr_limit - 1; ${"\\"} -''\t''\tregister const typeof(*(p)) __r2 asm("r2") = (x);''\t${"\\"} +''\t''\tregister typeof(*(p)) __r2 asm("r2") = (x);''\t${"\\"} ''\t''\tregister const typeof(*(p)) __user *__p asm("r0") = (p);${"\\"} ''\t''\tregister unsigned long __l asm("r1") = __limit;''\t''\t${"\\"} ''\t''\tregister int __e asm("r0");''\t''\t''\t''\t${"\\"} '') ]; postPatch = '' substituteInPlace arch/arm/boot/compressed/piggy.xzkern.S --replace-fail '#alloc' ' "a"' substituteInPlace arch/arm/mach-berlin/Makefile.boot --replace-fail '/bin/bash' '${stdenv.shell}' substituteInPlace arch/arm/boot/compressed/Makefile --replace-fail '${"\t"}@$(check_for_multiple_zreladdr)' '${"\t"}echo LDFLAGS_vmlinux = ''${LDFLAGS_vmlinux}${"\n\t"}@$(check_for_multiple_zreladdr)' cp include/linux/compiler-gcc4.h include/linux/compiler-gcc${lib.versions.major buildPackages.stdenv.cc.version}.h ''; inherit (kernel) nativeBuildInputs; depsBuildBuild = [ buildPackages.stdenv.cc ]; makeFlags = [ "ARCH=${stdenv.hostPlatform.linuxArch}" "LOCALVERSION=-mrvl" "CROSS_COMPILE=${stdenv.cc.targetPrefix}" ]; env.NIX_CFLAGS_COMPILE = toString [ "-std=gnu89" "-Wno-error=address" "-Wno-error=dangling-pointer" "-Wno-error=missing-attributes" ]; inherit (kernel) hardeningDisable; configurePhase = '' make bg2cd_penguin_mlc_defconfig $makeFlags echo "CONFIG_KEXEC=y" >> .config echo "CONFIG_KERNEL_XZ=y" >> .config make olddefconfig $makeFlags ''; postBuild = '' make modules $makeFlags -j$NIX_BUILD_CORES ''; installPhase = '' mkdir $out cp -r * $out/ ''; dontFixup = true; }; kexecMod = let inherit (pkgs) stdenv; inherit (self.packages.${system}) kernel oldKernel; in stdenv.mkDerivation { pname = "kexec_mod"; version = "0.0.1"; src = ./kexec_mod; postPatch = '' for f in machine_kexec.c kexec.c relocate_kernel.S; do substituteInPlace "$f" --subst-var-by KERNEL ${oldKernel} done ''; nativeBuildInputs = kernel.moduleBuildDependencies; makeFlags = [ "ARCH=${stdenv.hostPlatform.linuxArch}" "CROSS_COMPILE=${stdenv.cc.targetPrefix}" "KDIR=${oldKernel}" "INSTALL_MOD_PATH=$(out)" ]; env.NIX_CFLAGS_COMPILE = toString [ "-std=gnu89" "-fno-pie" ]; inherit (kernel) hardeningDisable; meta = { description = "kexec functionality as a kernel module for old kernels"; homepage = "https://github.com/lukas2511/steamlink-sdk"; license = lib.licenses.gpl2; platforms = [ system ]; }; }; }; }; } ```

Similar Articles

Lanzaboote – NixOS Secure Boot

Hacker News Top

This article introduces Lanzaboote, a UEFI UKI stub written in Rust that enables Secure Boot support for NixOS. It solves NixOS-specific boot challenges by deferring signature checking to UEFI while keeping kernels and initrds separate from the UKI binary.

Migrating my NAS from CoreOS/Flatcar Linux to NixOS

Michael Stapelberg

Michael Stapelberg details his migration of a NAS from CoreOS/Flatcar Linux to NixOS, covering the step-by-step transition from Docker containers to native NixOS modules with practical examples.

Taming the Steam arm64 client (on pmOS)

Lobsters Hottest

A blog post detailing the quirks and challenges of running the unofficial Steam arm64 client on postmarketOS, including the client's obliviousness to being arm64, missing Proton/runtime downloads, and references to FEX and graphics-provider manifests for Valve's upcoming Steam Frame.