<feed xmlns="http://www.w3.org/2005/Atom">
  <title>feyor.sh (Nix)</title>
  <link href="https://feyor.sh/tags/nix/atom.xml" rel="self"/>
  <link href="https://feyor.sh/tags/nix/"/>
  
  <updated>2026-09-26T00:00:00+00:00</updated>
  
  <id>https://feyor.sh/tags/nix/</id>
  
  <author>
    <name>George Huebner</name>
    
    <email>george@feyor.sh</email>
    
  </author>
  
  
  <entry>
    <title type="html"><![CDATA[Infecting the Steam Link with NixOS]]></title>
    <link href="https://feyor.sh/blog/infecting-the-steam-link-with-nixos/"/>
    <id>tag:feyor.sh:0eadbf0a-bf2d-4bbf-bc43-899f5f7e989f</id>
    
    <author>
      <name>George Huebner</name>
    </author>
    
    <published>2026-09-26T00:00:00+00:00</published>
    <updated>2026-09-26T02:09:17-05:00</updated>
    
    
    <content type="html" xml:base="https://feyor.sh/blog/infecting-the-steam-link-with-nixos/"><![CDATA[<p>While rummaging through my closet the other day I discovered a <a href="https://en.wikipedia.org/wiki/Steam_Link#Hardware_device">Steam Link</a> 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.</p>
<p>As it turns out, a fellow named <a href="https://heap.ovh/getting-linux-on-valve-steam-link.html">fijam</a> 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 then <kbd>kexec</kbd> our new kernel.
However, the kernel shipped with the Steam Link was not built with <code>CONFIG_KEXEC</code> enabled.
This is where things get <em>really</em> clever: we can cobble the pertinent kexec source files into a minimal kernel module that adds the <kbd>kexec</kbd> syscall to the running system!</p>
<p>Several people have successfully used this technique to get other distros<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> booting, but they all seem to have just copied the <kbd>kexec</kbd> binary and kernel module from fijam&rsquo;s website.
fijam seems like a lovely person and all, but I&rsquo;m wary of downloading kernel modules from the interwebs so I decided to compile it myself.</p>
<h2 id="booting-the-thing">Booting the thing</h2>
<p>Compiling a NixOS userspace and kernel/initrd is pretty simple; you just pass the correct <kbd>system</kbd> (and because I&rsquo;m using <kbd>__splicedPackages</kbd>/<kbd>crossSystem</kbd>, also <kbd>pkgs</kbd>) to <kbd>lib.nixosSystem</kbd> and add your modules.
Choosing the target architecture was slightly less straightforward: Valve&rsquo;s steamlink toolchain uses <code>armv7a</code>, but importing nixpkgs with <kbd>crossSystem.config = &ldquo;armv7a-unknown-linux-gnueabihf&rdquo;</kbd> interacts <a href="https://github.com/NixOS/nixpkgs/blob/fbe840e7184ed15fd5b1ca8f1a8746462a38d59c/lib/systems/default.nix#L596-L599">poorly with the Go build plumbing</a>, so I used the (seemingly) equivalent <code>armv7l</code> instead.</p>





  
  
    

  
  
    









<details open>
  
  <summary>Nix</summary>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  inputs<span style="color:#00d3d0">.</span>nixpkgs<span style="color:#00d3d0">.</span>url <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;github:NixOS/nixpkgs/nixos-unstable&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  outputs <span style="color:#00d3d0">=</span> { self<span style="color:#00d3d0">,</span> nixpkgs }:
</span></span><span style="display:flex;"><span>    <span style="color:#b6a0ff">let</span>
</span></span><span style="display:flex;"><span>      <span style="color:#b6a0ff">inherit</span> (nixpkgs) lib;
</span></span><span style="display:flex;"><span>      system <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;armv7l-linux&#34;</span>;
</span></span><span style="display:flex;"><span>      <span style="color:#a8a8a8"># hostSystem should be linux but does not have to be arm (x86 should work)</span>
</span></span><span style="display:flex;"><span>      hostSystem <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;aarch64-linux&#34;</span>;
</span></span><span style="display:flex;"><span>      pkgs <span style="color:#00d3d0">=</span> (<span style="color:#b6a0ff">import</span> nixpkgs {
</span></span><span style="display:flex;"><span>        system <span style="color:#00d3d0">=</span> hostSystem;
</span></span><span style="display:flex;"><span>        crossSystem <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>          config <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;armv7l-unknown-linux-gnueabihf&#34;</span>;
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>      })<span style="color:#00d3d0">.</span>__splicedPackages;
</span></span><span style="display:flex;"><span>    <span style="color:#b6a0ff">in</span> {
</span></span><span style="display:flex;"><span>      nixosConfigurations<span style="color:#00d3d0">.</span>steamlink <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>nixosSystem {
</span></span><span style="display:flex;"><span>        <span style="color:#b6a0ff">inherit</span> system pkgs;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        modules <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>          <span style="color:#a8a8a8"># ...</span>
</span></span><span style="display:flex;"><span>        ];
</span></span><span style="display:flex;"><span>      };
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
</details>

<p>The real challenge is compiling a kernel module for a vendored fork of a 13 year old kernel; the <a href="https://wiki.nixos.org/wiki/Linux_kernel#Packaging_out-of-tree_kernel_modules">NixOS wiki</a> is actually pretty helpful here and points out some footguns related to the default hardening flags in stdenv.</p>





  
  
    

  
  
    









<details open>
  
  <summary>Nix</summary>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>kexecMod <span style="color:#00d3d0">=</span> <span style="color:#b6a0ff">let</span>
</span></span><span style="display:flex;"><span>  <span style="color:#b6a0ff">inherit</span> (pkgs) stdenv;
</span></span><span style="display:flex;"><span>  <span style="color:#b6a0ff">inherit</span> (self<span style="color:#00d3d0">.</span>nixosConfigurations<span style="color:#00d3d0">.</span>steamlink<span style="color:#00d3d0">.</span>config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>build) kernel oldKernel;
</span></span><span style="display:flex;"><span><span style="color:#b6a0ff">in</span> stdenv<span style="color:#00d3d0">.</span>mkDerivation {
</span></span><span style="display:flex;"><span>  pname <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;kexec_mod&#34;</span>;
</span></span><span style="display:flex;"><span>  version <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;0.0.1&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  src <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">./kexec_mod</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  postPatch <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    for f in machine_kexec.c kexec.c relocate_kernel.S; do
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      substituteInPlace &#34;$f&#34; --subst-var-by KERNEL </span><span style="color:#79a8ff">${</span>oldKernel<span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    done
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">  &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  nativeBuildInputs <span style="color:#00d3d0">=</span> kernel<span style="color:#00d3d0">.</span>moduleBuildDependencies;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  makeFlags <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;ARCH=</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>hostPlatform<span style="color:#00d3d0">.</span>linuxArch<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;CROSS_COMPILE=</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>cc<span style="color:#00d3d0">.</span>targetPrefix<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;KDIR=</span><span style="color:#79a8ff">${</span>oldKernel<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;INSTALL_MOD_PATH=$(out)&#34;</span>
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  env<span style="color:#00d3d0">.</span>NIX_CFLAGS_COMPILE <span style="color:#00d3d0">=</span> <span style="color:#f78fe7">toString</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;-std=gnu89&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;-fno-pie&#34;</span>
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>  <span style="color:#b6a0ff">inherit</span> (kernel) hardeningDisable;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  meta <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>    description <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;kexec functionality as a kernel module for old kernels&#34;</span>;
</span></span><span style="display:flex;"><span>    homepage <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;https://github.com/lukas2511/steamlink-sdk&#34;</span>;
</span></span><span style="display:flex;"><span>    license <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>licenses<span style="color:#00d3d0">.</span>gpl2;
</span></span><span style="display:flex;"><span>    platforms <span style="color:#00d3d0">=</span> [ system ];
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>};</span></span></code></pre></div>
</details>

<p>(See <a href="/blog/infecting-the-steam-link-with-nixos/#files">Files</a> for the kexec_mod source code.)</p>
<p>In order to get this to build we need to point Kbuild to a Linux kernel checkout that has been built with <kbd>make modules</kbd><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.
(Note that I&rsquo;m using the <kbd>moduleBuildDependencies</kbd> attribute of the comparatively modern <kbd>kernel</kbd> from my NixOS configuration.)</p>





  
  
    

  
  
    









<details open>
  
  <summary>Nix</summary>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>oldKernel <span style="color:#00d3d0">=</span> <span style="color:#b6a0ff">let</span>
</span></span><span style="display:flex;"><span>  <span style="color:#b6a0ff">inherit</span> (pkgs) stdenv fetchFromGitHub buildPackages fetchpatch writeText;
</span></span><span style="display:flex;"><span>  <span style="color:#b6a0ff">inherit</span> (self<span style="color:#00d3d0">.</span>nixosConfigurations<span style="color:#00d3d0">.</span>steamlink<span style="color:#00d3d0">.</span>config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>build) kernel;
</span></span><span style="display:flex;"><span><span style="color:#b6a0ff">in</span> stdenv<span style="color:#00d3d0">.</span>mkDerivation {
</span></span><span style="display:flex;"><span>  pname <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;linux-steamlink&#34;</span>;
</span></span><span style="display:flex;"><span>  version <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;3.8.13&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  src <span style="color:#00d3d0">=</span> fetchFromGitHub {
</span></span><span style="display:flex;"><span>    owner <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;ValveSoftware&#34;</span>;
</span></span><span style="display:flex;"><span>    repo <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;steamlink-sdk&#34;</span>;
</span></span><span style="display:flex;"><span>    rootDir <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;kernel&#34;</span>;
</span></span><span style="display:flex;"><span>    rev <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;62b4d098d1472c3534dd098ca2a0e0e10712f1c6&#34;</span>;
</span></span><span style="display:flex;"><span>    hash <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;sha256-3Q8JjNmkRFCkdt8E+ol+E/c2sy+X5I7UYhsHAfYBdWs=&#34;</span>;
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>  sourceRoot <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;source&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  patches <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    (fetchpatch {
</span></span><span style="display:flex;"><span>      url <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;https://gitlab.com/postmarketOS/pmaports/-/raw/aa289aa350071e6afc54f6b6704ba28971b50466/device/.shared-patches/linux/linux3.4-ARM-8933-1-replace-Sun-Solaris-style-flag-on-section.patch&#34;</span>;
</span></span><span style="display:flex;"><span>      hash <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;sha256-KRNI4070H0AFMCZl7pYnIbin6lbp68/xuf6yOPvmYdI=&#34;</span>;
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>    (fetchpatch {
</span></span><span style="display:flex;"><span>      url <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;https://gitlab.com/postmarketOS/pmaports/-/raw/aa289aa350071e6afc54f6b6704ba28971b50466/device/.shared-patches/linux/gcc10-extern_YYLOC_global_declaration.patch&#34;</span>;
</span></span><span style="display:flex;"><span>      hash <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;sha256-9hq5xGeJRL/ESHofOh4MAOAGV2IlDRYvvpxyxk3MXlw=&#34;</span>;
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>    (writeText <span style="color:#79a8ff">&#34;0001-gcc-bug85745.diff&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        index 74b17d0..dc64fa2 100644
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        --- a/arch/arm/include/asm/uaccess.h
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        +++ b/arch/arm/include/asm/uaccess.h
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        @@ -164,7 +164,7 @@
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">         #define __put_user_check(x,p)</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">         </span><span style="color:#79a8ff">&#39;&#39;\t</span><span style="color:#79a8ff">({</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">         </span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">unsigned long __limit = current_thread_info()-&gt;addr_limit - 1; </span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        -</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register const typeof(*(p)) __r2 asm(&#34;r2&#34;) = (x);</span><span style="color:#79a8ff">&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        +</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register typeof(*(p)) __r2 asm(&#34;r2&#34;) = (x);</span><span style="color:#79a8ff">&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">         </span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register const typeof(*(p)) __user *__p asm(&#34;r0&#34;) = (p);</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">         </span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register unsigned long __l asm(&#34;r1&#34;) = __limit;</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">         </span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register int __e asm(&#34;r0&#34;);</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      &#39;&#39;</span>)
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  postPatch <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    substituteInPlace arch/arm/boot/compressed/piggy.xzkern.S --replace-fail &#39;#alloc&#39; &#39; &#34;a&#34;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    substituteInPlace arch/arm/mach-berlin/Makefile.boot --replace-fail &#39;/bin/bash&#39; &#39;</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>shell<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    substituteInPlace arch/arm/boot/compressed/Makefile --replace-fail &#39;</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\t</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">@$(check_for_multiple_zreladdr)&#39; &#39;</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\t</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">echo LDFLAGS_vmlinux = </span><span style="color:#79a8ff">&#39;&#39;$</span><span style="color:#79a8ff">{LDFLAGS_vmlinux}</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\n\t</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">@$(check_for_multiple_zreladdr)&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    cp include/linux/compiler-gcc4.h include/linux/compiler-gcc</span><span style="color:#79a8ff">${</span>lib<span style="color:#00d3d0">.</span>versions<span style="color:#00d3d0">.</span>major buildPackages<span style="color:#00d3d0">.</span>stdenv<span style="color:#00d3d0">.</span>cc<span style="color:#00d3d0">.</span>version<span style="color:#79a8ff">}</span><span style="color:#79a8ff">.h
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">  &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#b6a0ff">inherit</span> (kernel) nativeBuildInputs;
</span></span><span style="display:flex;"><span>  depsBuildBuild <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    buildPackages<span style="color:#00d3d0">.</span>stdenv<span style="color:#00d3d0">.</span>cc
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  makeFlags <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;ARCH=</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>hostPlatform<span style="color:#00d3d0">.</span>linuxArch<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;LOCALVERSION=-mrvl&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;CROSS_COMPILE=</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>cc<span style="color:#00d3d0">.</span>targetPrefix<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>  env<span style="color:#00d3d0">.</span>NIX_CFLAGS_COMPILE <span style="color:#00d3d0">=</span> <span style="color:#f78fe7">toString</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;-std=gnu89&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;-Wno-error=address&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;-Wno-error=dangling-pointer&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;-Wno-error=missing-attributes&#34;</span>
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>  <span style="color:#b6a0ff">inherit</span> (kernel) hardeningDisable;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  configurePhase <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    make bg2cd_penguin_mlc_defconfig $makeFlags
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    echo &#34;CONFIG_KEXEC=y&#34; &gt;&gt; .config
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    echo &#34;CONFIG_KERNEL_XZ=y&#34; &gt;&gt; .config
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    make olddefconfig $makeFlags
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">  &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  postBuild <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    make modules $makeFlags -j$NIX_BUILD_CORES
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">  &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  installPhase <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    mkdir $out
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    cp -r * $out/
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">  &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  dontFixup <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>};</span></span></code></pre></div>
</details>

<p>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.</p>
<p>Now that we have <code>kexec_mod.ko</code>, 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 <a href="https://github.com/torvalds/linux/blob/6812ce4e4379ffc99c52401ec28f0d7ffbc36206/arch/arm/boot/dts/synaptics/berlin2cd-valve-steamlink.dts">upstreamed</a> to Linux so we can get it from <kbd>hardware.deviceTree.package</kbd>), a copy of the <kbd>kexec</kbd> userland binary (compiled with <kbd>pkgsStatic</kbd> so we can run it on non-NixOS), and a small script to tie everything together:</p>





  
  
    

  
  
    









<details open>
  
  <summary>Bash</summary>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>fts-set steamlink.crashcounter <span style="color:#00bcff">0</span> <span style="color:#a8a8a8"># required to prevent factory reset after a few reboots</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>mkdir -p /mnt/disk/proc /mnt/disk/sys /mnt/disk/dev
</span></span><span style="display:flex;"><span>mount -t proc proc /mnt/disk/proc
</span></span><span style="display:flex;"><span>mount -o rbind /sys /mnt/disk/sys
</span></span><span style="display:flex;"><span>mount -o rbind /dev /mnt/disk/dev
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>insmod /mnt/disk/kexec_load.ko
</span></span><span style="display:flex;"><span>chroot /mnt/disk/ /kexec --load /zImage <span style="color:#79a8ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff"></span>                         --initrd /initrd <span style="color:#79a8ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff"></span>                         --dtb /berlin2cd-valve-steamlink.dtb <span style="color:#79a8ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff"></span>                         --command-line <span style="color:#79a8ff">&#34;init=/init root=/dev/sda2 rootwait rw usbcore.autosuspend=-1&#34;</span>
</span></span><span style="display:flex;"><span>chroot /mnt/disk/ /kexec -e</span></span></code></pre></div>
</details>

<p>You could juggle these files manually and upload them to a USB drive yourself, but it&rsquo;s much easier to use the <a href="https://github.com/NixOS/nixpkgs/blob/5f5458dc42bf4391dc5f85e7682decb8c78e8756/nixos/modules/installer/sd-card/sd-image.nix">sd-image</a> NixOS module to create a disk image instead:</p>





  
  
    

  
  
    









<details open>
  
  <summary>Nix</summary>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>usb-image <span style="color:#00d3d0">=</span> { modulesPath<span style="color:#00d3d0">,</span> config<span style="color:#00d3d0">,</span> <span style="color:#00d3d0">...</span> }: {
</span></span><span style="display:flex;"><span>  imports <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    (modulesPath <span style="color:#00d3d0">+</span> <span style="color:#79a8ff">&#34;/installer/sd-card/sd-image.nix&#34;</span>)
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  image<span style="color:#00d3d0">.</span>extension <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce <span style="color:#79a8ff">&#34;img&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  sdImage <span style="color:#00d3d0">=</span> <span style="color:#b6a0ff">let</span>
</span></span><span style="display:flex;"><span>    dtb <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;berlin2cd-valve-steamlink.dtb&#34;</span>;
</span></span><span style="display:flex;"><span>    kexecScript <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">./kexec-nixos</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#b6a0ff">inherit</span> (config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>build) kernel initialRamdisk;
</span></span><span style="display:flex;"><span>  <span style="color:#b6a0ff">in</span> {
</span></span><span style="display:flex;"><span>    compressImage <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>    firmwarePartitionName <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;STEAMLINK&#34;</span>;
</span></span><span style="display:flex;"><span>    rootVolumeLabel <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;NIXOS&#34;</span>;
</span></span><span style="display:flex;"><span>    populateFirmwareCommands <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      pushd firmware
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      files=(
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        </span><span style="color:#79a8ff">${</span>kernel<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/</span><span style="color:#79a8ff">${</span>config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>boot<span style="color:#00d3d0">.</span>loader<span style="color:#00d3d0">.</span>kernelFile<span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        </span><span style="color:#79a8ff">${</span>initialRamdisk<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/</span><span style="color:#79a8ff">${</span>config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>boot<span style="color:#00d3d0">.</span>loader<span style="color:#00d3d0">.</span>initrdFile<span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        </span><span style="color:#79a8ff">${</span>config<span style="color:#00d3d0">.</span>hardware<span style="color:#00d3d0">.</span>deviceTree<span style="color:#00d3d0">.</span>package<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/</span><span style="color:#79a8ff">${</span>dtb<span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        </span><span style="color:#79a8ff">${</span>self<span style="color:#00d3d0">.</span>packages<span style="color:#00d3d0">.</span><span style="color:#79a8ff">${</span>system<span style="color:#79a8ff">}</span><span style="color:#00d3d0">.</span>kexecMod<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/lib/modules/3.8.13-mrvl/extra/kexec_load.ko
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        </span><span style="color:#79a8ff">${</span>pkgs<span style="color:#00d3d0">.</span>pkgsStatic<span style="color:#00d3d0">.</span>kexec-tools<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/bin/kexec
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      )
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      for f in </span><span style="color:#79a8ff">&#39;&#39;$</span><span style="color:#79a8ff">{files[@]}; do
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        cp $f ./
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      done
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      # factory_test/run.sh will run before this has a chance to
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      # enable ssh; uncomment if not booting straight into NixOS
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      # mkdir -p steamlink/config/system
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      # touch steamlink/config/system/enable_ssh.txt
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      mkdir -p steamlink/factory_test
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      cp </span><span style="color:#79a8ff">${</span>kexecScript<span style="color:#79a8ff">}</span><span style="color:#79a8ff"> steamlink/factory_test/run.sh
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      popd
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>    populateRootCommands <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>};</span></span></code></pre></div>
</details>

<p>Testing that the <kbd>kexec</kbd> handoff works was really tricky because the HDMI output doesn&rsquo;t work with the kernel I&rsquo;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.</p>





  
  
    

  
  
    









<details open>
  
  <summary>Nix</summary>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>initramfs <span style="color:#00d3d0">=</span> pkgs<span style="color:#00d3d0">.</span>buildPackages<span style="color:#00d3d0">.</span>runCommand <span style="color:#79a8ff">&#34;build-initramfs&#34;</span> {}
</span></span><span style="display:flex;"><span>  <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    mkdir initramfs; cd initramfs
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    mkdir -pv {etc,proc,sys,usr/{bin,sbin}}
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    cp -a </span><span style="color:#79a8ff">${</span>pkgs<span style="color:#00d3d0">.</span>pkgsStatic<span style="color:#00d3d0">.</span>busybox<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/{bin,sbin} .
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    chmod 755 ./{bin,sbin}
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    cat &lt;&lt;EOF &gt; init
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    #!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    mount -t proc none /proc
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    mount -t sysfs none /sys
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    mount -t devtmpfs devtmpfs /dev
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    mkdir -p /mnt
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    try_mount() {
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      dev=&#34;$1&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      fs=&#34;$2&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      if [ &#34;$fs&#34; = auto ]; then
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        mount -o rw &#34;$dev&#34; /mnt 2&gt;/dev/null || return 1
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      else
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        mount -t &#34;$fs&#34; -o rw &#34;$dev&#34; /mnt 2&gt;/dev/null || return 1
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      fi
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      marker=kexec-mounted-ok
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      if [ -f /mnt/zImage ]; then
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        marker=kexec-steamlink-ok
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      fi
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      {
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        echo &#34;device=$dev&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        echo &#34;fs=$fs&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        cat /proc/partitions
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      } &gt; &#34;/mnt/$marker&#34; 2&gt;/dev/null &amp;&amp; sync
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      umount /mnt
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      sleep 10
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      reboot -f
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    }
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    for dev in /dev/mmcblk*p* /dev/sd[a-z][0-9]* /dev/vd[a-z][0-9]*; do
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      [ -b &#34;$dev&#34; ] || continue
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      try_mount &#34;$dev&#34; vfat
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      try_mount &#34;$dev&#34; ext4
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      try_mount &#34;$dev&#34; auto
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    done
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    sleep 45
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    reboot -f
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    EOF
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    chmod +x init
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    find . -print0 | </span><span style="color:#79a8ff">${</span>lib<span style="color:#00d3d0">.</span>getExe pkgs<span style="color:#00d3d0">.</span>buildPackages<span style="color:#00d3d0">.</span>cpio<span style="color:#79a8ff">}</span><span style="color:#79a8ff"> --null -ov --format=newc &gt; $out
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">  &#39;&#39;</span>;</span></span></code></pre></div>
</details>

<p>Once I knew that worked, I switched to the NixOS initrd with <kbd>boot.initrd.network.enable = true</kbd> and used a Netcat based reverse shell to my laptop&rsquo;s IP for further debugging.</p>





  
  
    

  
  
    









<details open>
  
  <summary>Nix</summary>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>debugModule <span style="color:#00d3d0">=</span> { lib<span style="color:#00d3d0">,</span> <span style="color:#00d3d0">...</span> }: {
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>systemd<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce false;
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>kernelModules <span style="color:#00d3d0">=</span> [ <span style="color:#79a8ff">&#34;pxa168_eth&#34;</span> ];
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>availableKernelModules <span style="color:#00d3d0">=</span> [ <span style="color:#79a8ff">&#34;reset_berlin&#34;</span> ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>network<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>network<span style="color:#00d3d0">.</span>udhcpc<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>kernelParams <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;ip=192.168.2.2::192.168.2.1:255.255.255.0:stm-link:eth0:off&#34;</span>
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>network<span style="color:#00d3d0">.</span>postCommands <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    mac_peer=192.168.2.1
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    stm_link_ip=192.168.2.2
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    echo &#34;initrd net debug: interfaces: $(ls /sys/class/net)&#34; &gt; /dev/kmsg
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    for iface_path in /sys/class/net/*; do
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      iface=&#34;</span><span style="color:#79a8ff">&#39;&#39;$</span><span style="color:#79a8ff">{iface_path##*/}&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      [ &#34;$iface&#34; != lo ] || continue
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      echo &#34;initrd net debug: configuring $iface&#34; &gt; /dev/kmsg
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      ip link set dev &#34;$iface&#34; up || true
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      ip address flush dev &#34;$iface&#34; || true
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      ip address add &#34;$stm_link_ip/24&#34; dev &#34;$iface&#34; || true
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    done
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    (
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      while true; do
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        ping -c 1 -W 1 &#34;$mac_peer&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        sleep 2
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      done
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    ) &amp;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    (
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      while true; do
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        rm -f /tmp/revsh
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        mkfifo /tmp/revsh
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        /bin/ash -i &lt; /tmp/revsh 2&gt;&amp;1 | nc &#34;$mac_peer&#34; 4444 &gt; /tmp/revsh
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        rm -f /tmp/revsh
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">        sleep 2
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      done
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    ) &amp;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">  &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>};</span></span></code></pre></div>
</details>

<p>The main things I needed to figure out at this stage were adding <code>reset_berlin</code> to <kbd>boot.initrd.availableKernelModules</kbd> to allow reading from the USB drive and using the old NixOS initrd system in lieu of the new systemd-based version (<kbd>boot.initrd.systemd.enable = lib.mkForce false</kbd>).</p>
<p>Finally I was able to boot into userspace and connect over SSH! 🥳</p>
<p>That having been said, the USB image I was booting from was weighing in at a hefty 2.3GB&hellip; surely we can do better.</p>
<h2 id="trimming-the-fat">Trimming the fat</h2>
<p>I was surprised that there wasn&rsquo;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 <a href="https://sidhion.com/blog/nixos_server_issues">NixOS is a good server OS, except when it isn&rsquo;t</a> and <a href="https://natkr.com/2026-06-19-nixos-but-smol/">I can haz smoller NixOS ISOs?</a>.
Those are good resources, but because we&rsquo;re targeting actual hardware instead of a VM we must necessarily be more conservative in what we cut.</p>





  
  
    

  
  
    









<details open>
  
  <summary>Nix</summary>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>minimal <span style="color:#00d3d0">=</span> { modulesPath<span style="color:#00d3d0">,</span> pkgs<span style="color:#00d3d0">,</span> <span style="color:#00d3d0">...</span> }: {
</span></span><span style="display:flex;"><span>  imports <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    (modulesPath <span style="color:#00d3d0">+</span> <span style="color:#79a8ff">&#34;/profiles/minimal.nix&#34;</span>)
</span></span><span style="display:flex;"><span>    (modulesPath <span style="color:#00d3d0">+</span> <span style="color:#79a8ff">&#34;/profiles/headless.nix&#34;</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#a8a8a8"># (modulesPath + &#34;/profiles/perlless.nix&#34;)</span>
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  disabledModules <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    (modulesPath <span style="color:#00d3d0">+</span> <span style="color:#79a8ff">&#34;/profiles/base.nix&#34;</span>)
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>loader <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>    grub<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>    systemd-boot<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>    supportsInitrdSecrets <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>  };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>systemd<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce false;
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>availableKernelModules <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce [
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;reset_berlin&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;uas&#34;</span>
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>  boot<span style="color:#00d3d0">.</span>kernelModules <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;pxa168_eth&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;mwifiex_sdio&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#79a8ff">&#34;btmrvl_sdio&#34;</span>
</span></span><span style="display:flex;"><span>  ];
</span></span><span style="display:flex;"><span>  hardware<span style="color:#00d3d0">.</span>firmware <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce (<span style="color:#b6a0ff">with</span> pkgs; [
</span></span><span style="display:flex;"><span>    (runCommand <span style="color:#79a8ff">&#34;marvell-firmware&#34;</span> {} <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      mkdir -p $out/lib/firmware/mrvl
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">      cp </span><span style="color:#79a8ff">${</span>linux-firmware<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/lib/firmware/mrvl/sd8897_uapsta.bin $out/lib/firmware/mrvl/
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">    &#39;&#39;</span>)
</span></span><span style="display:flex;"><span>    wireless-regdb
</span></span><span style="display:flex;"><span>  ]);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  documentation<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>  programs<span style="color:#00d3d0">.</span>command-not-found<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkDefault false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  networking<span style="color:#00d3d0">.</span>networkmanager<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>  networking<span style="color:#00d3d0">.</span>firewall<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  xdg<span style="color:#00d3d0">.</span>icons<span style="color:#00d3d0">.</span>enable  <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>  xdg<span style="color:#00d3d0">.</span>mime<span style="color:#00d3d0">.</span>enable   <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>  xdg<span style="color:#00d3d0">.</span>sounds<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>  fonts<span style="color:#00d3d0">.</span>fontconfig<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  programs<span style="color:#00d3d0">.</span>nano<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  system<span style="color:#00d3d0">.</span>disableInstallerTools <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>  system<span style="color:#00d3d0">.</span>switch<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>  system<span style="color:#00d3d0">.</span>nixos-init<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  nix<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>  systemd<span style="color:#00d3d0">.</span>services<span style="color:#00d3d0">.</span>register-nix-paths <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce {};
</span></span><span style="display:flex;"><span>};</span></span></code></pre></div>
</details>

<p>Here are the main things that came up during the slim-ening:</p>
<ul>
<li>We only need one firmware blob from the massive <kbd>linux-firmware</kbd> package (1.8GB compressed!), so we can save a huge amount of space by only adding that blob to <kbd>hardware.firmware</kbd>
<ul>
<li>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</li>
</ul>
</li>
<li>OpenSSH does not seem to like it when <kbd>i18n.glibcLocales</kbd> or the <kbd>security.wrappers</kbd> module are removed</li>
<li>The <kbd>kexec</kbd> boot 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</li>
<li>I feel like it should be possible to disable <kbd>boot.initrd</kbd> and <kbd>boot.kernel</kbd> because we provide the kernel/initrd/DTB from the FAT32 partition when we <kbd>kexec</kbd>, but I was never able to disable these without breaking the boot process</li>
<li>If I could switch to the systemd-based initrd I could enable the &ldquo;perlless&rdquo; NixOS module to remove Perl from the system closure for additional savings</li>
</ul>
<p>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 &ldquo;good enough&rdquo;.</p>
<h2 id="files">Files</h2>
<p>The Nix flake I used and the source for the <kbd>kexec_mod</kbd> kernel module can be downloaded <a href="/infecting-the-steam-link-with-nixos/steamlink-nixos.tar.gz">here</a>.
The same <code>flake.nix</code> is reproduced below for your convenience.</p>





  
  
    

  
  
    









<details >
  
  <summary><div class="named-src">
      <span>Nix</span>
      <span>flake.nix</span>
    </div>
  
  </summary>
  <div class="highlight"><pre tabindex="0" style="color:#fff;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-nix" data-lang="nix"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  inputs<span style="color:#00d3d0">.</span>nixpkgs<span style="color:#00d3d0">.</span>url <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;github:NixOS/nixpkgs/nixos-unstable&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  outputs <span style="color:#00d3d0">=</span> { self<span style="color:#00d3d0">,</span> nixpkgs }:
</span></span><span style="display:flex;"><span>    <span style="color:#b6a0ff">let</span>
</span></span><span style="display:flex;"><span>      <span style="color:#b6a0ff">inherit</span> (nixpkgs) lib;
</span></span><span style="display:flex;"><span>      system <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;armv7l-linux&#34;</span>;
</span></span><span style="display:flex;"><span>      <span style="color:#a8a8a8"># hostSystem should be linux but does not have to be arm (x86 should work)</span>
</span></span><span style="display:flex;"><span>      hostSystem <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;aarch64-linux&#34;</span>;
</span></span><span style="display:flex;"><span>      pkgs <span style="color:#00d3d0">=</span> (<span style="color:#b6a0ff">import</span> nixpkgs {
</span></span><span style="display:flex;"><span>        system <span style="color:#00d3d0">=</span> hostSystem;
</span></span><span style="display:flex;"><span>        crossSystem <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>          config <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;armv7l-unknown-linux-gnueabihf&#34;</span>;
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>        overlays <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>          <span style="color:#a8a8a8"># https://github.com/NixOS/nixpkgs/issues/388309</span>
</span></span><span style="display:flex;"><span>          (self: super: {
</span></span><span style="display:flex;"><span>            efivar <span style="color:#00d3d0">=</span> self<span style="color:#00d3d0">.</span>emptyDirectory;
</span></span><span style="display:flex;"><span>            efibootmgr <span style="color:#00d3d0">=</span> self<span style="color:#00d3d0">.</span>emptyDirectory;
</span></span><span style="display:flex;"><span>          })
</span></span><span style="display:flex;"><span>        ];
</span></span><span style="display:flex;"><span>      })<span style="color:#00d3d0">.</span>__splicedPackages;
</span></span><span style="display:flex;"><span>    <span style="color:#b6a0ff">in</span> {
</span></span><span style="display:flex;"><span>      nixosModules <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#a8a8a8"># https://sidhion.com/blog/nixos_server_issues</span>
</span></span><span style="display:flex;"><span>        <span style="color:#a8a8a8"># https://discourse.nixos.org/t/how-to-have-a-minimal-nixos/22652/4</span>
</span></span><span style="display:flex;"><span>        minimal <span style="color:#00d3d0">=</span> { modulesPath<span style="color:#00d3d0">,</span> pkgs<span style="color:#00d3d0">,</span> <span style="color:#00d3d0">...</span> }: {
</span></span><span style="display:flex;"><span>          imports <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            (modulesPath <span style="color:#00d3d0">+</span> <span style="color:#79a8ff">&#34;/profiles/minimal.nix&#34;</span>)
</span></span><span style="display:flex;"><span>            (modulesPath <span style="color:#00d3d0">+</span> <span style="color:#79a8ff">&#34;/profiles/headless.nix&#34;</span>)
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          disabledModules <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            (modulesPath <span style="color:#00d3d0">+</span> <span style="color:#79a8ff">&#34;/profiles/base.nix&#34;</span>)
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          boot<span style="color:#00d3d0">.</span>loader <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>            grub<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>            systemd-boot<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>            supportsInitrdSecrets <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>          };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          <span style="color:#a8a8a8"># systemd initrd did not work for me; you could add the perlless profile if you got it working</span>
</span></span><span style="display:flex;"><span>          boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>systemd<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce false;
</span></span><span style="display:flex;"><span>          boot<span style="color:#00d3d0">.</span>initrd<span style="color:#00d3d0">.</span>availableKernelModules <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce [
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;reset_berlin&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;uas&#34;</span>
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>          boot<span style="color:#00d3d0">.</span>kernelModules <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;pxa168_eth&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;mwifiex_sdio&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;btmrvl_sdio&#34;</span>
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>          hardware<span style="color:#00d3d0">.</span>firmware <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce (<span style="color:#b6a0ff">with</span> pkgs; [
</span></span><span style="display:flex;"><span>            (runCommand <span style="color:#79a8ff">&#34;marvell-firmware&#34;</span> {} <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              mkdir -p $out/lib/firmware/mrvl
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              cp </span><span style="color:#79a8ff">${</span>linux-firmware<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/lib/firmware/mrvl/sd8897_uapsta.bin $out/lib/firmware/mrvl/
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            &#39;&#39;</span>)
</span></span><span style="display:flex;"><span>            wireless-regdb
</span></span><span style="display:flex;"><span>          ]);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          documentation<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>          programs<span style="color:#00d3d0">.</span>command-not-found<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkDefault false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          networking<span style="color:#00d3d0">.</span>networkmanager<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>          networking<span style="color:#00d3d0">.</span>firewall<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          xdg<span style="color:#00d3d0">.</span>icons<span style="color:#00d3d0">.</span>enable  <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>          xdg<span style="color:#00d3d0">.</span>mime<span style="color:#00d3d0">.</span>enable   <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>          xdg<span style="color:#00d3d0">.</span>sounds<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>          fonts<span style="color:#00d3d0">.</span>fontconfig<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          programs<span style="color:#00d3d0">.</span>nano<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          system<span style="color:#00d3d0">.</span>disableInstallerTools <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>          system<span style="color:#00d3d0">.</span>switch<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>          system<span style="color:#00d3d0">.</span>nixos-init<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          nix<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>          systemd<span style="color:#00d3d0">.</span>services<span style="color:#00d3d0">.</span>register-nix-paths <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce {};
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        usb-image <span style="color:#00d3d0">=</span> { modulesPath<span style="color:#00d3d0">,</span> config<span style="color:#00d3d0">,</span> <span style="color:#00d3d0">...</span> }: {
</span></span><span style="display:flex;"><span>          imports <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            (modulesPath <span style="color:#00d3d0">+</span> <span style="color:#79a8ff">&#34;/installer/sd-card/sd-image.nix&#34;</span>)
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          <span style="color:#a8a8a8"># in theory it should be possible to disable the kernel</span>
</span></span><span style="display:flex;"><span>          <span style="color:#a8a8a8"># and initrd for the nixos rootfs for some significant</span>
</span></span><span style="display:flex;"><span>          <span style="color:#a8a8a8"># space savings (because we&#39;re passing a copy of the</span>
</span></span><span style="display:flex;"><span>          <span style="color:#a8a8a8"># kernel and initrd from the STEAMLINK partition to kexec</span>
</span></span><span style="display:flex;"><span>          <span style="color:#a8a8a8"># directly, but in practice I never got that working)</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          boot<span style="color:#00d3d0">.</span>kernelParams <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;root=/dev/disk/by-label/</span><span style="color:#79a8ff">${</span>config<span style="color:#00d3d0">.</span>sdImage<span style="color:#00d3d0">.</span>rootVolumeLabel<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span> <span style="color:#79a8ff">&#34;rootwait&#34;</span> <span style="color:#79a8ff">&#34;rw&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;usbcore.autosuspend=-1&#34;</span>
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          image<span style="color:#00d3d0">.</span>extension <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>mkForce <span style="color:#79a8ff">&#34;img&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          sdImage <span style="color:#00d3d0">=</span> <span style="color:#b6a0ff">let</span>
</span></span><span style="display:flex;"><span>            dtb <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;berlin2cd-valve-steamlink.dtb&#34;</span>;
</span></span><span style="display:flex;"><span>            kexecScript <span style="color:#00d3d0">=</span> pkgs<span style="color:#00d3d0">.</span>buildPackages<span style="color:#00d3d0">.</span>writeScript <span style="color:#79a8ff">&#34;kexec-nixos&#34;</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              #!/bin/sh
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              fts-set steamlink.crashcounter 0
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              mkdir -p /mnt/disk/proc /mnt/disk/sys /mnt/disk/dev
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              mount -t proc proc /mnt/disk/proc
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              mount -o rbind /sys /mnt/disk/sys
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              mount -o rbind /dev /mnt/disk/dev
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              insmod /mnt/disk/kexec_load.ko
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              chroot /mnt/disk/ /kexec --load /zImage \
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                                       --initrd /initrd \
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                                       --dtb /berlin2cd-valve-steamlink.dtb \
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                                       --command-line &#34;init=</span><span style="color:#79a8ff">${</span>config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>build<span style="color:#00d3d0">.</span>toplevel<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/init </span><span style="color:#79a8ff">${</span><span style="color:#f78fe7">toString</span> config<span style="color:#00d3d0">.</span>boot<span style="color:#00d3d0">.</span>kernelParams<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              chroot /mnt/disk/ /kexec -e
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>            <span style="color:#b6a0ff">inherit</span> (self<span style="color:#00d3d0">.</span>packages<span style="color:#00d3d0">.</span><span style="color:#79a8ff">${</span>system<span style="color:#79a8ff">}</span>) kernel initialRamdisk;
</span></span><span style="display:flex;"><span>          <span style="color:#b6a0ff">in</span> {
</span></span><span style="display:flex;"><span>            compressImage <span style="color:#00d3d0">=</span> false;
</span></span><span style="display:flex;"><span>            firmwarePartitionName <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;STEAMLINK&#34;</span>;
</span></span><span style="display:flex;"><span>            rootVolumeLabel <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;NIXOS&#34;</span>;
</span></span><span style="display:flex;"><span>            populateFirmwareCommands <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              pushd firmware
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              files=(
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                </span><span style="color:#79a8ff">${</span>kernel<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/</span><span style="color:#79a8ff">${</span>config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>boot<span style="color:#00d3d0">.</span>loader<span style="color:#00d3d0">.</span>kernelFile<span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                </span><span style="color:#79a8ff">${</span>initialRamdisk<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/</span><span style="color:#79a8ff">${</span>config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>boot<span style="color:#00d3d0">.</span>loader<span style="color:#00d3d0">.</span>initrdFile<span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                </span><span style="color:#79a8ff">${</span>config<span style="color:#00d3d0">.</span>hardware<span style="color:#00d3d0">.</span>deviceTree<span style="color:#00d3d0">.</span>package<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/</span><span style="color:#79a8ff">${</span>dtb<span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                </span><span style="color:#79a8ff">${</span>self<span style="color:#00d3d0">.</span>packages<span style="color:#00d3d0">.</span><span style="color:#79a8ff">${</span>system<span style="color:#79a8ff">}</span><span style="color:#00d3d0">.</span>kexecMod<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/lib/modules/3.8.13-mrvl/extra/kexec_load.ko
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                </span><span style="color:#79a8ff">${</span>pkgs<span style="color:#00d3d0">.</span>pkgsStatic<span style="color:#00d3d0">.</span>kexec-tools<span style="color:#79a8ff">}</span><span style="color:#79a8ff">/bin/kexec
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              )
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              for f in </span><span style="color:#79a8ff">&#39;&#39;$</span><span style="color:#79a8ff">{files[@]}; do
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                cp $f ./
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              done
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              # factory_test/run.sh will run before this has a chance to
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              # enable ssh; uncomment if not booting straight into NixOS
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              # mkdir -p steamlink/config/system
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              # touch steamlink/config/system/enable_ssh.txt
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              mkdir -p steamlink/factory_test
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              cp </span><span style="color:#79a8ff">${</span>kexecScript<span style="color:#79a8ff">}</span><span style="color:#79a8ff"> steamlink/factory_test/run.sh
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              popd
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>            populateRootCommands <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;&#34;</span>;
</span></span><span style="display:flex;"><span>          };
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>      };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      nixosConfigurations<span style="color:#00d3d0">.</span>steamlink <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>nixosSystem {
</span></span><span style="display:flex;"><span>        <span style="color:#b6a0ff">inherit</span> system pkgs;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        modules <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>          self<span style="color:#00d3d0">.</span>nixosModules<span style="color:#00d3d0">.</span>minimal
</span></span><span style="display:flex;"><span>          self<span style="color:#00d3d0">.</span>nixosModules<span style="color:#00d3d0">.</span>usb-image
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          ({ <span style="color:#00d3d0">...</span> }: {
</span></span><span style="display:flex;"><span>            <span style="color:#a8a8a8"># your NixOS config here!</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            services<span style="color:#00d3d0">.</span>tailscale<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            services<span style="color:#00d3d0">.</span>openssh <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>              <span style="color:#a8a8a8"># might be able to remove security wrappers if using static openssh</span>
</span></span><span style="display:flex;"><span>              <span style="color:#a8a8a8"># see https://sidhion.com/blog/nixos_server_issues#:~:text=While%20looking%20through%20the%20lvm%20stuff</span>
</span></span><span style="display:flex;"><span>              <span style="color:#a8a8a8"># package = pkgs.pkgsStatic.openssh;</span>
</span></span><span style="display:flex;"><span>              enable <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>              settings <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>                PermitRootLogin <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;yes&#34;</span>;
</span></span><span style="display:flex;"><span>              };
</span></span><span style="display:flex;"><span>            };
</span></span><span style="display:flex;"><span>            users<span style="color:#00d3d0">.</span>users<span style="color:#00d3d0">.</span>root<span style="color:#00d3d0">.</span>openssh<span style="color:#00d3d0">.</span>authorizedKeys<span style="color:#00d3d0">.</span>keys <span style="color:#00d3d0">=</span> [ <span style="color:#79a8ff">&#34;...&#34;</span> ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            hardware<span style="color:#00d3d0">.</span>bluetooth<span style="color:#00d3d0">.</span>enable <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            networking <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>              hostName <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;steamlink&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>              useDHCP <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>              interfaces<span style="color:#00d3d0">.</span>eth0 <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>                useDHCP <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>                <span style="color:#a8a8a8"># prefer DHCP but use a static IP for debugging over a direct ethernet serial line to your host machine</span>
</span></span><span style="display:flex;"><span>                ipv4<span style="color:#00d3d0">.</span>addresses <span style="color:#00d3d0">=</span> [{
</span></span><span style="display:flex;"><span>                  address <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;169.254.31.216&#34;</span>;
</span></span><span style="display:flex;"><span>                  prefixLength <span style="color:#00d3d0">=</span> <span style="color:#00bcff">16</span>;
</span></span><span style="display:flex;"><span>                }];
</span></span><span style="display:flex;"><span>              };
</span></span><span style="display:flex;"><span>              wireless <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>                enable <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>                networks  <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>                  <span style="color:#79a8ff">&#34;WiFi&#34;</span> <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>                    psk <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;hunter2&#34;</span>;
</span></span><span style="display:flex;"><span>                  };
</span></span><span style="display:flex;"><span>                };
</span></span><span style="display:flex;"><span>              };
</span></span><span style="display:flex;"><span>            };
</span></span><span style="display:flex;"><span>          })
</span></span><span style="display:flex;"><span>        ];
</span></span><span style="display:flex;"><span>      };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>      packages<span style="color:#00d3d0">.</span><span style="color:#79a8ff">${</span>system<span style="color:#79a8ff">}</span> <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>        <span style="color:#b6a0ff">inherit</span> (self<span style="color:#00d3d0">.</span>nixosConfigurations<span style="color:#00d3d0">.</span>steamlink<span style="color:#00d3d0">.</span>config<span style="color:#00d3d0">.</span>system<span style="color:#00d3d0">.</span>build) kernel initialRamdisk sdImage;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        default <span style="color:#00d3d0">=</span> self<span style="color:#00d3d0">.</span>packages<span style="color:#00d3d0">.</span><span style="color:#79a8ff">${</span>system<span style="color:#79a8ff">}</span><span style="color:#00d3d0">.</span>sdImage;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        oldKernel <span style="color:#00d3d0">=</span> <span style="color:#b6a0ff">let</span>
</span></span><span style="display:flex;"><span>          <span style="color:#b6a0ff">inherit</span> (pkgs) stdenv fetchFromGitHub buildPackages fetchpatch writeText;
</span></span><span style="display:flex;"><span>          <span style="color:#b6a0ff">inherit</span> (self<span style="color:#00d3d0">.</span>packages<span style="color:#00d3d0">.</span><span style="color:#79a8ff">${</span>system<span style="color:#79a8ff">}</span>) kernel;
</span></span><span style="display:flex;"><span>        <span style="color:#b6a0ff">in</span> stdenv<span style="color:#00d3d0">.</span>mkDerivation {
</span></span><span style="display:flex;"><span>          pname <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;linux-steamlink&#34;</span>;
</span></span><span style="display:flex;"><span>          version <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;3.8.13&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          src <span style="color:#00d3d0">=</span> fetchFromGitHub {
</span></span><span style="display:flex;"><span>            owner <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;ValveSoftware&#34;</span>;
</span></span><span style="display:flex;"><span>            repo <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;steamlink-sdk&#34;</span>;
</span></span><span style="display:flex;"><span>            rootDir <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;kernel&#34;</span>;
</span></span><span style="display:flex;"><span>            rev <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;62b4d098d1472c3534dd098ca2a0e0e10712f1c6&#34;</span>;
</span></span><span style="display:flex;"><span>            hash <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;sha256-3Q8JjNmkRFCkdt8E+ol+E/c2sy+X5I7UYhsHAfYBdWs=&#34;</span>;
</span></span><span style="display:flex;"><span>          };
</span></span><span style="display:flex;"><span>          sourceRoot <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;source&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          patches <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            (fetchpatch {
</span></span><span style="display:flex;"><span>              url <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;https://gitlab.com/postmarketOS/pmaports/-/raw/aa289aa350071e6afc54f6b6704ba28971b50466/device/.shared-patches/linux/linux3.4-ARM-8933-1-replace-Sun-Solaris-style-flag-on-section.patch&#34;</span>;
</span></span><span style="display:flex;"><span>              hash <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;sha256-KRNI4070H0AFMCZl7pYnIbin6lbp68/xuf6yOPvmYdI=&#34;</span>;
</span></span><span style="display:flex;"><span>            })
</span></span><span style="display:flex;"><span>            (fetchpatch {
</span></span><span style="display:flex;"><span>              url <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;https://gitlab.com/postmarketOS/pmaports/-/raw/aa289aa350071e6afc54f6b6704ba28971b50466/device/.shared-patches/linux/gcc10-extern_YYLOC_global_declaration.patch&#34;</span>;
</span></span><span style="display:flex;"><span>              hash <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;sha256-9hq5xGeJRL/ESHofOh4MAOAGV2IlDRYvvpxyxk3MXlw=&#34;</span>;
</span></span><span style="display:flex;"><span>            })
</span></span><span style="display:flex;"><span>            (writeText <span style="color:#79a8ff">&#34;0001-gcc-bug85745.diff&#34;</span>
</span></span><span style="display:flex;"><span>              <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                index 74b17d0..dc64fa2 100644
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                --- a/arch/arm/include/asm/uaccess.h
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                +++ b/arch/arm/include/asm/uaccess.h
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                @@ -164,7 +164,7 @@
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                 #define __put_user_check(x,p)</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                 </span><span style="color:#79a8ff">&#39;&#39;\t</span><span style="color:#79a8ff">({</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                 </span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">unsigned long __limit = current_thread_info()-&gt;addr_limit - 1; </span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                -</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register const typeof(*(p)) __r2 asm(&#34;r2&#34;) = (x);</span><span style="color:#79a8ff">&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                +</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register typeof(*(p)) __r2 asm(&#34;r2&#34;) = (x);</span><span style="color:#79a8ff">&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                 </span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register const typeof(*(p)) __user *__p asm(&#34;r0&#34;) = (p);</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                 </span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register unsigned long __l asm(&#34;r1&#34;) = __limit;</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">                 </span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">register int __e asm(&#34;r0&#34;);</span><span style="color:#79a8ff">&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t&#39;&#39;\t</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\\</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              &#39;&#39;</span>)
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          postPatch <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            substituteInPlace arch/arm/boot/compressed/piggy.xzkern.S --replace-fail &#39;#alloc&#39; &#39; &#34;a&#34;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            substituteInPlace arch/arm/mach-berlin/Makefile.boot --replace-fail &#39;/bin/bash&#39; &#39;</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>shell<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            substituteInPlace arch/arm/boot/compressed/Makefile --replace-fail &#39;</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\t</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">@$(check_for_multiple_zreladdr)&#39; &#39;</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\t</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">echo LDFLAGS_vmlinux = </span><span style="color:#79a8ff">&#39;&#39;$</span><span style="color:#79a8ff">{LDFLAGS_vmlinux}</span><span style="color:#79a8ff">${</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">\n\t</span><span style="color:#79a8ff">&#34;</span><span style="color:#79a8ff">}</span><span style="color:#79a8ff">@$(check_for_multiple_zreladdr)&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            cp include/linux/compiler-gcc4.h include/linux/compiler-gcc</span><span style="color:#79a8ff">${</span>lib<span style="color:#00d3d0">.</span>versions<span style="color:#00d3d0">.</span>major buildPackages<span style="color:#00d3d0">.</span>stdenv<span style="color:#00d3d0">.</span>cc<span style="color:#00d3d0">.</span>version<span style="color:#79a8ff">}</span><span style="color:#79a8ff">.h
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">          &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          <span style="color:#b6a0ff">inherit</span> (kernel) nativeBuildInputs;
</span></span><span style="display:flex;"><span>          depsBuildBuild <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            buildPackages<span style="color:#00d3d0">.</span>stdenv<span style="color:#00d3d0">.</span>cc
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          makeFlags <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;ARCH=</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>hostPlatform<span style="color:#00d3d0">.</span>linuxArch<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;LOCALVERSION=-mrvl&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;CROSS_COMPILE=</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>cc<span style="color:#00d3d0">.</span>targetPrefix<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>          env<span style="color:#00d3d0">.</span>NIX_CFLAGS_COMPILE <span style="color:#00d3d0">=</span> <span style="color:#f78fe7">toString</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;-std=gnu89&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;-Wno-error=address&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;-Wno-error=dangling-pointer&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;-Wno-error=missing-attributes&#34;</span>
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>          <span style="color:#b6a0ff">inherit</span> (kernel) hardeningDisable;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          configurePhase <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            make bg2cd_penguin_mlc_defconfig $makeFlags
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            echo &#34;CONFIG_KEXEC=y&#34; &gt;&gt; .config
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            echo &#34;CONFIG_KERNEL_XZ=y&#34; &gt;&gt; .config
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            make olddefconfig $makeFlags
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">          &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          postBuild <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            make modules $makeFlags -j$NIX_BUILD_CORES
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">          &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          installPhase <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            mkdir $out
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            cp -r * $out/
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">          &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          dontFixup <span style="color:#00d3d0">=</span> true;
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        kexecMod <span style="color:#00d3d0">=</span> <span style="color:#b6a0ff">let</span>
</span></span><span style="display:flex;"><span>          <span style="color:#b6a0ff">inherit</span> (pkgs) stdenv;
</span></span><span style="display:flex;"><span>          <span style="color:#b6a0ff">inherit</span> (self<span style="color:#00d3d0">.</span>packages<span style="color:#00d3d0">.</span><span style="color:#79a8ff">${</span>system<span style="color:#79a8ff">}</span>) kernel oldKernel;
</span></span><span style="display:flex;"><span>        <span style="color:#b6a0ff">in</span> stdenv<span style="color:#00d3d0">.</span>mkDerivation {
</span></span><span style="display:flex;"><span>          pname <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;kexec_mod&#34;</span>;
</span></span><span style="display:flex;"><span>          version <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;0.0.1&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          src <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">./kexec_mod</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          postPatch <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            for f in machine_kexec.c kexec.c relocate_kernel.S; do
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">              substituteInPlace &#34;$f&#34; --subst-var-by KERNEL </span><span style="color:#79a8ff">${</span>oldKernel<span style="color:#79a8ff">}</span><span style="color:#79a8ff">
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">            done
</span></span></span><span style="display:flex;"><span><span style="color:#79a8ff">          &#39;&#39;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          nativeBuildInputs <span style="color:#00d3d0">=</span> kernel<span style="color:#00d3d0">.</span>moduleBuildDependencies;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          makeFlags <span style="color:#00d3d0">=</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;ARCH=</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>hostPlatform<span style="color:#00d3d0">.</span>linuxArch<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;CROSS_COMPILE=</span><span style="color:#79a8ff">${</span>stdenv<span style="color:#00d3d0">.</span>cc<span style="color:#00d3d0">.</span>targetPrefix<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;KDIR=</span><span style="color:#79a8ff">${</span>oldKernel<span style="color:#79a8ff">}</span><span style="color:#79a8ff">&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;INSTALL_MOD_PATH=$(out)&#34;</span>
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          env<span style="color:#00d3d0">.</span>NIX_CFLAGS_COMPILE <span style="color:#00d3d0">=</span> <span style="color:#f78fe7">toString</span> [
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;-std=gnu89&#34;</span>
</span></span><span style="display:flex;"><span>            <span style="color:#79a8ff">&#34;-fno-pie&#34;</span>
</span></span><span style="display:flex;"><span>          ];
</span></span><span style="display:flex;"><span>          <span style="color:#b6a0ff">inherit</span> (kernel) hardeningDisable;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>          meta <span style="color:#00d3d0">=</span> {
</span></span><span style="display:flex;"><span>            description <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;kexec functionality as a kernel module for old kernels&#34;</span>;
</span></span><span style="display:flex;"><span>            homepage <span style="color:#00d3d0">=</span> <span style="color:#79a8ff">&#34;https://github.com/lukas2511/steamlink-sdk&#34;</span>;
</span></span><span style="display:flex;"><span>            license <span style="color:#00d3d0">=</span> lib<span style="color:#00d3d0">.</span>licenses<span style="color:#00d3d0">.</span>gpl2;
</span></span><span style="display:flex;"><span>            platforms <span style="color:#00d3d0">=</span> [ system ];
</span></span><span style="display:flex;"><span>          };
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>      };
</span></span><span style="display:flex;"><span>    };
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div>
</details>

<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>Right before I published this I discovered <a href="https://github.com/Ondra-Zik/steamlink-nixos">someone else</a> had vibed their way to a bootable NixOS install, although their config is more _slop_py, doesn&rsquo;t handle reboots correctly, and uses a bunch of unnecessary binary blobs instead of building from source.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>Although using <kbd>make modules_prepare</kbd> lets us build successfully, the resulting kernel module will not have the right vermagic and symbol addresses and will not be accepted by <kbd>insmod</kbd>:</p>
<blockquote>
<p>NOTE: &ldquo;modules_prepare&rdquo; will not build Module.symvers even if <code>CONFIG_MODVERSIONS</code> is set; therefore, a full kernel build needs to be executed to make module versioning work.</p></blockquote>
<p>(<a href="https://www.kernel.org/doc/html/latest/kbuild/modules.html%20">source</a>)&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>]]></content>
    
  </entry>
  
</feed>
