├── LICENSE.md ├── README.md ├── arm32-cross-fixes.nix ├── base.nix ├── ca.cnf ├── ca ├── codesign.crt ├── codesign.key └── root.pem ├── configuration.nix ├── default.nix ├── flake.lock ├── flake.nix ├── gen_ca ├── gen_keys ├── ipxe.nix ├── linux-build-slave.nix ├── linux-rpi.nix ├── nix.nix ├── notes.txt ├── qemu.nix ├── release.nix ├── rpi-base.nix ├── rpi_image.nix ├── runit.nix ├── ssh ├── ssh_host_ed25519_key ├── ssh_host_ed25519_key.pub ├── ssh_host_rsa_key └── ssh_host_rsa_key.pub ├── stage-1.nix ├── stage-2-init.sh ├── stage-2.nix ├── system-path.nix ├── systemd-compat.nix ├── tests ├── boot.nix └── test-instrumentation.nix └── zynq_image.nix /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright © `2016-2020` `Michael Bishop` 5 | 6 | Permission is hereby granted, free of charge, to any person 7 | obtaining a copy of this software and associated documentation 8 | files (the “Software”), to deal in the Software without 9 | restriction, including without limitation the rights to use, 10 | copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the 12 | Software is furnished to do so, subject to the following 13 | conditions: 14 | 15 | The above copyright notice and this permission notice shall be 16 | included in all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, 19 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 20 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 21 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 22 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 | OTHER DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | not-os is a small experimental OS I wrote for embeded situations, it is based heavily on NixOS, but compiles down to a kernel, initrd, and a 48mb squashfs 2 | 3 | there are also example iPXE config files, that will check the cryptographic signature over all images, to ensure only authorized files can run on the given hardware 4 | 5 | and I have [Hydra](https://hydra.angeldsis.com/jobset/not-os/notos-unstable#tabs-jobs) setup and doing automatic builds of not-os against nixos-unstable, including testing that it can boot under qemu 6 | -------------------------------------------------------------------------------- /arm32-cross-fixes.nix: -------------------------------------------------------------------------------- 1 | { 2 | nixpkgs.overlays = [ 3 | (self: super: { 4 | libuv = super.libuv.overrideAttrs (old: { 5 | doCheck = false; 6 | }); 7 | elfutils = super.elfutils.overrideAttrs (old: { 8 | doCheck = false; 9 | doInstallCheck = false; 10 | }); 11 | systemd = super.systemd.override { withEfi = false; }; 12 | util-linux = super.util-linux.override { systemdSupport = false; }; 13 | procps = super.procps.override { withSystemd = false; }; 14 | nix = super.nix.override { enableDocumentation = false; }; 15 | }) 16 | ]; 17 | } 18 | -------------------------------------------------------------------------------- /base.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, lib, ... }: 2 | 3 | with lib; 4 | 5 | { 6 | options = { 7 | boot.isContainer = mkOption { 8 | type = types.bool; 9 | default = false; 10 | }; 11 | hardware.firmware = mkOption { 12 | type = types.listOf types.package; 13 | default = []; 14 | apply = list: pkgs.buildEnv { 15 | name = "firmware"; 16 | paths = list; 17 | pathsToLink = [ "/lib/firmware" ]; 18 | ignoreCollisions = true; 19 | }; 20 | }; 21 | not-os.nix = mkOption { 22 | type = types.bool; 23 | description = "enable nix-daemon and a writeable store"; 24 | }; 25 | nix.enable = mkOption { 26 | type = types.bool; 27 | default = config.not-os.nix; 28 | }; 29 | not-os.rngd = mkOption { 30 | type = types.bool; 31 | description = "enable rngd"; 32 | default = false; 33 | }; 34 | not-os.simpleStaticIp = mkOption { 35 | type = types.bool; 36 | default = false; 37 | description = "set a static ip of 10.0.2.15"; 38 | }; 39 | networking.timeServers = mkOption { 40 | default = [ 41 | "0.nixos.pool.ntp.org" 42 | "1.nixos.pool.ntp.org" 43 | "2.nixos.pool.ntp.org" 44 | "3.nixos.pool.ntp.org" 45 | ]; 46 | type = types.listOf types.str; 47 | description = '' 48 | The set of NTP servers from which to synchronise. 49 | ''; 50 | }; 51 | system.systemBuilderArgs = mkOption { 52 | type = types.attrsOf types.unspecified; 53 | internal = true; 54 | default = {}; 55 | description = lib.mdDoc '' 56 | `lib.mkDerivation` attributes that will be passed to the top level system builder. 57 | ''; 58 | }; 59 | system.systemBuilderCommands = mkOption { 60 | type = types.lines; 61 | internal = true; 62 | default = ""; 63 | description = '' 64 | This code will be added to the builder creating the system store path. 65 | ''; 66 | }; 67 | }; 68 | config = { 69 | environment.systemPackages = lib.optional config.not-os.nix pkgs.nix; 70 | nixpkgs.config = { 71 | packageOverrides = self: { 72 | utillinux = self.utillinux.override { systemd = null; systemdSupport = false; }; 73 | dhcpcd = self.dhcpcd.override { udev = null; }; 74 | linux_rpixxx = self.linux_rpi.override { 75 | extraConfig = '' 76 | DEBUG_LL y 77 | EARLY_PRINTK y 78 | DEBUG_BCM2708_UART0 y 79 | ARM_APPENDED_DTB n 80 | ARM_ATAG_DTB_COMPAT n 81 | ARCH_BCM2709 y 82 | BCM2708_GPIO y 83 | BCM2708_NOL2CACHE y 84 | BCM2708_SPIDEV y 85 | ''; 86 | }; 87 | }; 88 | }; 89 | environment.etc = { 90 | "nix/nix.conf".source = pkgs.runCommand "nix.conf" {} '' 91 | extraPaths=$(for i in $(cat ${pkgs.writeReferencesToFile pkgs.runtimeShell}); do if test -d $i; then echo $i; fi; done) 92 | cat > $out << EOF 93 | build-use-sandbox = true 94 | build-users-group = nixbld 95 | build-sandbox-paths = /bin/sh=${pkgs.runtimeShell} $(echo $extraPaths) 96 | build-max-jobs = 1 97 | build-cores = 4 98 | EOF 99 | ''; 100 | bashrc.text = "export PATH=/run/current-system/sw/bin"; 101 | profile.text = "export PATH=/run/current-system/sw/bin"; 102 | "resolv.conf".text = "nameserver 10.0.2.3"; 103 | passwd.text = '' 104 | root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash 105 | sshd:x:498:65534:SSH privilege separation user:/var/empty:/run/current-system/sw/bin/nologin 106 | toxvpn:x:1010:65534::/var/lib/toxvpn:/run/current-system/sw/bin/nologin 107 | nixbld1:x:30001:30000:Nix build user 1:/var/empty:/run/current-system/sw/bin/nologin 108 | nixbld2:x:30002:30000:Nix build user 2:/var/empty:/run/current-system/sw/bin/nologin 109 | nixbld3:x:30003:30000:Nix build user 3:/var/empty:/run/current-system/sw/bin/nologin 110 | nixbld4:x:30004:30000:Nix build user 4:/var/empty:/run/current-system/sw/bin/nologin 111 | nixbld5:x:30005:30000:Nix build user 5:/var/empty:/run/current-system/sw/bin/nologin 112 | nixbld6:x:30006:30000:Nix build user 6:/var/empty:/run/current-system/sw/bin/nologin 113 | nixbld7:x:30007:30000:Nix build user 7:/var/empty:/run/current-system/sw/bin/nologin 114 | nixbld8:x:30008:30000:Nix build user 8:/var/empty:/run/current-system/sw/bin/nologin 115 | nixbld9:x:30009:30000:Nix build user 9:/var/empty:/run/current-system/sw/bin/nologin 116 | nixbld10:x:30010:30000:Nix build user 10:/var/empty:/run/current-system/sw/bin/nologin 117 | ''; 118 | "nsswitch.conf".text = '' 119 | hosts: files dns myhostname mymachines 120 | networks: files dns 121 | ''; 122 | "services".source = pkgs.iana-etc + "/etc/services"; 123 | group.text = '' 124 | root:x:0: 125 | nixbld:x:30000:nixbld1,nixbld10,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9 126 | ''; 127 | "ssh/ssh_host_rsa_key.pub".source = ./ssh/ssh_host_rsa_key.pub; 128 | "ssh/ssh_host_rsa_key" = { mode = "0600"; source = ./ssh/ssh_host_rsa_key; }; 129 | "ssh/ssh_host_ed25519_key.pub".source = ./ssh/ssh_host_ed25519_key.pub; 130 | "ssh/ssh_host_ed25519_key" = { mode = "0600"; source = ./ssh/ssh_host_ed25519_key; }; 131 | }; 132 | boot.kernelParams = [ "systemConfig=${config.system.build.toplevel}" ]; 133 | boot.kernelPackages = lib.mkDefault (if pkgs.system == "armv7l-linux" then pkgs.linuxPackages_rpi1 else pkgs.linuxPackages); 134 | system.build.earlyMountScript = pkgs.writeScript "dummy" '' 135 | ''; 136 | system.build.runvm = pkgs.writeScript "runner" '' 137 | #!${pkgs.stdenv.shell} 138 | exec ${pkgs.qemu_kvm}/bin/qemu-kvm -name not-os -m 512 \ 139 | -drive index=0,id=drive1,file=${config.system.build.squashfs},readonly,media=cdrom,format=raw,if=virtio \ 140 | -kernel ${config.system.build.kernel}/bzImage -initrd ${config.system.build.initialRamdisk}/initrd -nographic \ 141 | -append "console=ttyS0 ${toString config.boot.kernelParams} quiet panic=-1" -no-reboot \ 142 | -net nic,model=virtio \ 143 | -net user,net=10.0.2.0/24,host=10.0.2.2,dns=10.0.2.3,hostfwd=tcp::2222-:22 \ 144 | -device virtio-rng-pci 145 | ''; 146 | 147 | system.build.dist = pkgs.runCommand "not-os-dist" {} '' 148 | mkdir $out 149 | cp ${config.system.build.squashfs} $out/root.squashfs 150 | cp ${config.system.build.kernel}/*Image $out/kernel 151 | cp ${config.system.build.initialRamdisk}/initrd $out/initrd 152 | echo "${builtins.unsafeDiscardStringContext (toString config.boot.kernelParams)}" > $out/command-line 153 | ''; 154 | 155 | system.activationScripts.users = '' 156 | # dummy to make setup-etc happy 157 | ''; 158 | system.activationScripts.groups = '' 159 | # dummy to make setup-etc happy 160 | ''; 161 | system.activationScripts.etc = stringAfter [ "users" "groups" ] config.system.build.etcActivationCommands; 162 | 163 | # nix-build -A system.build.toplevel && du -h $(nix-store -qR result) --max=0 -BM|sort -n 164 | system.build.toplevel = pkgs.runCommand "not-os" { 165 | activationScript = config.system.activationScripts.script; 166 | } '' 167 | mkdir $out 168 | cp ${config.system.build.bootStage2} $out/init 169 | substituteInPlace $out/init --subst-var-by systemConfig $out 170 | ln -s ${config.system.path} $out/sw 171 | echo "$activationScript" > $out/activate 172 | substituteInPlace $out/activate --subst-var out 173 | chmod u+x $out/activate 174 | unset activationScript 175 | ''; 176 | # nix-build -A squashfs && ls -lLh result 177 | system.build.squashfs = pkgs.callPackage (pkgs.path + "/nixos/lib/make-squashfs.nix") { 178 | storeContents = [ config.system.build.toplevel ]; 179 | }; 180 | }; 181 | } 182 | -------------------------------------------------------------------------------- /ca.cnf: -------------------------------------------------------------------------------- 1 | [ ca ] 2 | default_ca = ca_default 3 | 4 | [ ca_default ] 5 | certificate = ca/root.pem 6 | private_key = ca/root.key 7 | serial = ca/ca.srl 8 | database = ca/ca.idx 9 | new_certs_dir = ca/signed 10 | default_md = default 11 | policy = policy_anything 12 | preserve = yes 13 | default_days = 90 14 | unique_subject = no 15 | 16 | [ policy_anything ] 17 | countryName = optional 18 | stateOrProvinceName = optional 19 | localityName = optional 20 | organizationName = optional 21 | organizationalUnitName = optional 22 | commonName = optional 23 | emailAddress = optional 24 | 25 | [ cross ] 26 | basicConstraints = critical,CA:true 27 | keyUsage = critical,cRLSign,keyCertSign 28 | 29 | [ codesigning ] 30 | keyUsage = digitalSignature 31 | extendedKeyUsage = codeSigning 32 | 33 | -------------------------------------------------------------------------------- /ca/codesign.crt: -------------------------------------------------------------------------------- 1 | Certificate: 2 | Data: 3 | Version: 3 (0x2) 4 | Serial Number: 1 (0x1) 5 | Signature Algorithm: sha256WithRSAEncryption 6 | Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd 7 | Validity 8 | Not Before: Jul 8 07:17:47 2019 GMT 9 | Not After : Apr 27 07:17:47 2022 GMT 10 | Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd 11 | Subject Public Key Info: 12 | Public Key Algorithm: rsaEncryption 13 | Public-Key: (2048 bit) 14 | Modulus: 15 | 00:b4:7d:90:34:5c:57:ee:ab:c1:e7:9e:cd:5c:8e: 16 | 01:97:14:a4:50:02:ad:ec:66:df:40:0b:74:e2:4d: 17 | b4:a1:b5:6a:15:6e:b1:f9:a5:ee:e4:87:71:60:6c: 18 | af:d5:3e:21:d7:70:22:4f:05:cc:fe:31:e6:a4:d7: 19 | cd:df:c4:ae:66:f2:43:80:fd:f8:5d:87:e7:01:85: 20 | cc:1a:59:1a:cb:54:8f:8d:58:8c:e0:aa:14:1f:63: 21 | c5:88:db:61:e7:58:96:8b:16:c6:38:2a:0e:e5:90: 22 | 60:e6:81:46:54:1d:8b:30:23:35:2d:76:75:12:96: 23 | 07:de:88:d6:08:8f:ce:09:e5:c4:01:95:88:05:9c: 24 | a3:3d:66:8a:d2:2b:58:72:ec:94:df:57:0b:f3:fa: 25 | a7:e3:99:ff:f3:61:d7:8a:70:cc:3e:1b:a4:0d:d6: 26 | 1a:e4:f5:c6:59:c9:14:ac:9a:d2:e0:34:f9:71:73: 27 | 1b:db:53:c8:fb:02:89:0f:df:68:c5:fe:0f:e4:8c: 28 | 8c:6d:5c:87:80:41:59:67:51:99:00:24:43:13:7e: 29 | b0:f8:41:a2:7e:97:87:ae:2f:74:38:f0:eb:dc:59: 30 | 39:20:eb:ea:a8:19:97:2c:fe:f5:cd:4a:6e:f7:55: 31 | 82:b6:70:48:1b:f4:4f:6f:67:8f:07:44:22:8c:c4: 32 | ac:1d 33 | Exponent: 65537 (0x10001) 34 | X509v3 extensions: 35 | X509v3 Key Usage: 36 | Digital Signature 37 | X509v3 Extended Key Usage: 38 | Code Signing 39 | Signature Algorithm: sha256WithRSAEncryption 40 | 62:c2:e7:90:d5:2b:08:c6:4c:88:59:0d:93:43:d9:30:62:f1: 41 | 16:25:71:62:1e:ac:8f:43:c9:eb:7f:db:c8:f5:b4:65:b4:de: 42 | 53:71:6c:23:22:65:d5:ed:6f:4c:cc:95:db:3f:e2:f3:fd:44: 43 | 0b:42:eb:d6:b7:84:51:2f:96:92:8e:cc:ec:8a:6c:b4:45:46: 44 | 10:ef:67:04:dd:b9:d4:a0:01:86:14:31:c7:4d:eb:3b:ac:85: 45 | 80:aa:38:8b:b9:65:95:08:f0:48:e4:29:8b:e4:19:80:6b:3b: 46 | 56:69:18:8b:cc:51:77:a2:82:93:15:c5:34:f0:84:9b:72:9a: 47 | 1d:85:35:a5:de:26:50:6a:bd:d2:8a:9a:be:e5:dc:4d:e1:4f: 48 | da:40:b5:d6:0f:6a:28:20:12:4c:00:c3:d5:aa:e5:53:20:71: 49 | ca:3d:d5:36:82:f2:84:10:24:3f:61:fe:57:99:f2:d2:14:1a: 50 | 4d:32:4a:c7:f0:fa:af:4d:57:2e:ea:e2:66:5c:e2:bb:62:a8: 51 | c0:fb:5e:55:a3:46:ba:9f:01:11:c2:c6:8d:05:d4:02:22:53: 52 | 65:b1:87:6d:37:22:4c:64:b9:bf:e0:a6:3f:33:e8:52:40:0e: 53 | 66:8c:13:c8:a8:5e:1c:d1:e7:f3:5b:00:87:ad:2c:b2:1f:c8: 54 | d8:1b:51:df 55 | -----BEGIN CERTIFICATE----- 56 | MIIDKTCCAhGgAwIBAgIBATANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJBVTET 57 | MBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJuZXQgV2lkZ2l0cyBQ 58 | dHkgTHRkMB4XDTE5MDcwODA3MTc0N1oXDTIyMDQyNzA3MTc0N1owRTELMAkGA1UE 59 | BhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdp 60 | ZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALR9 61 | kDRcV+6rweeezVyOAZcUpFACrexm30ALdOJNtKG1ahVusfml7uSHcWBsr9U+Iddw 62 | Ik8FzP4x5qTXzd/ErmbyQ4D9+F2H5wGFzBpZGstUj41YjOCqFB9jxYjbYedYlosW 63 | xjgqDuWQYOaBRlQdizAjNS12dRKWB96I1giPzgnlxAGViAWcoz1mitIrWHLslN9X 64 | C/P6p+OZ//Nh14pwzD4bpA3WGuT1xlnJFKya0uA0+XFzG9tTyPsCiQ/faMX+D+SM 65 | jG1ch4BBWWdRmQAkQxN+sPhBon6Xh64vdDjw69xZOSDr6qgZlyz+9c1KbvdVgrZw 66 | SBv0T29njwdEIozErB0CAwEAAaMkMCIwCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoG 67 | CCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQBiwueQ1SsIxkyIWQ2TQ9kwYvEW 68 | JXFiHqyPQ8nrf9vI9bRltN5TcWwjImXV7W9MzJXbP+Lz/UQLQuvWt4RRL5aSjszs 69 | imy0RUYQ72cE3bnUoAGGFDHHTes7rIWAqjiLuWWVCPBI5CmL5BmAaztWaRiLzFF3 70 | ooKTFcU08ISbcpodhTWl3iZQar3Sipq+5dxN4U/aQLXWD2ooIBJMAMPVquVTIHHK 71 | PdU2gvKEECQ/Yf5XmfLSFBpNMkrH8PqvTVcu6uJmXOK7YqjA+15Vo0a6nwERwsaN 72 | BdQCIlNlsYdtNyJMZLm/4KY/M+hSQA5mjBPIqF4c0efzWwCHrSyyH8jYG1Hf 73 | -----END CERTIFICATE----- 74 | -------------------------------------------------------------------------------- /ca/codesign.key: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY----- 2 | MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC0fZA0XFfuq8Hn 3 | ns1cjgGXFKRQAq3sZt9AC3TiTbShtWoVbrH5pe7kh3FgbK/VPiHXcCJPBcz+Meak 4 | 183fxK5m8kOA/fhdh+cBhcwaWRrLVI+NWIzgqhQfY8WI22HnWJaLFsY4Kg7lkGDm 5 | gUZUHYswIzUtdnUSlgfeiNYIj84J5cQBlYgFnKM9ZorSK1hy7JTfVwvz+qfjmf/z 6 | YdeKcMw+G6QN1hrk9cZZyRSsmtLgNPlxcxvbU8j7AokP32jF/g/kjIxtXIeAQVln 7 | UZkAJEMTfrD4QaJ+l4euL3Q48OvcWTkg6+qoGZcs/vXNSm73VYK2cEgb9E9vZ48H 8 | RCKMxKwdAgMBAAECggEBAJcdAZ01K1Hib+hSprG1G1O4rpFmjON+hbADZ4sJcBBr 9 | 6TOkiFHyQX8Ifz4yAU1SRdcwRSlQO/8fHHIrVGzjKPl8IFRhTo5QeHJn6SiuLabL 10 | V50J5Hk9LLfTOtGIjAG7w98T5EWlwO8m4FpdJdrLGXvmHmG/6ejzwAbrHffxHppd 11 | YWCfVJa34CAVfG46F9QrHmc2d1AreKataSyFxGybuswSSfZqJomvjd2vUHYgiphK 12 | dXTijuNGHyZB31AAKWVi00SDMsMFY31Q1zDoxmd0l/kanMv53mv5MdR8dHZINKxB 13 | +qxyGjAsCmFQxCh/POefi4lYtAgUh5bMt5r+pENB/wECgYEA6mj49wIPaTFj0Yvw 14 | hHajCtQsvGEvBUswZpgdOfso90OB0EY8rL/Z307vYpbdYBjAgrVLqHN0F8qA2F3u 15 | zROWhxdHrRMKMmM9MngGKZA1dKoKa5tVR0KOJEUkpMWNn5qdSicTDFMsEq1CAryh 16 | SRGied0oYevCmuQ7cBBjBfz0HmECgYEAxR1AIsQikVvP+oJ85tLolgEtSPbIy22B 17 | 8dgWHSuyqF4czJA8s8Pxfpo3yk1GOvJt5VcR2aqkjKM6cIjiogjr+kWLmx9ZGsDJ 18 | HvLNp5dL2Y4CyTf6aECQZs7v4FFo+eEWoL3c5+ne2LAFe6E9hn+ke12h+cLnuFqX 19 | zO0gjFSpzz0CgYBkwd5R/ja1lp87URV/Oqd2XiEkj/lwIxOY5cWaSJUhQ4knBynJ 20 | b2WtEPbgv8xEJB+Lj3YH4CiEmWyslCOzTrojMySCBm8ZnYKOkPzFHNF9ZiG4gzoy 21 | uS7z9Cx+DtSDSChX2Vfcslt9Y6++EWqaR9Q44ZEcFgS+I2BRGRoXVtVvwQKBgCfg 22 | +hfOjJvR8mrhOXnNk8a9aDcJzqfxeMfACwFN1PBhUfxE9jL8YoBVnRHtvlaws3Eh 23 | w3fBIVdesrUPzKIxoeRZa5wvpGxYMphzUQ4l+u+B3qhtDdlHrq9OEJPWhKGBW32b 24 | y/STiUVXn1Ra08LBUjqvP9TzDMRsd6e7FcmuW0iVAoGBAJt68lSRQV+uqzd7UjIa 25 | aIpEr25LNcZjwcGJ56P9SnXXNhs6nStW3V9tYgPTnjmsQGg8eqZt9AaRMuBn+naT 26 | jMN2g/RFzzHSkD/T+0iurrYm1bC7CPoCsQD9Ddo9UCZG/csh5akffZWAlybWULU0 27 | OV/V/mC5VPBjOw5xYeGeoFwK 28 | -----END PRIVATE KEY----- 29 | -------------------------------------------------------------------------------- /ca/root.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDXTCCAkWgAwIBAgIJAM+QrfXmgGKtMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV 3 | BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX 4 | aWRnaXRzIFB0eSBMdGQwHhcNMTkwNzA4MDcxNzQzWhcNMjIwNDI3MDcxNzQzWjBF 5 | MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50 6 | ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB 7 | CgKCAQEApe3gEfslJuptMwFdu5U1tdPvG0j6cWX8FnsInbeR1qHRHNapwp2S21Up 8 | 5yfMsqhLHz68GjYL7nYBmPIKhV0BkVQcW4zkP2b09aED3dR+FJkzyKB6pC8GA0sg 9 | ulOfW2Igd9MybS4WIgjXMxW9taIu7NQlrtdcbVnv5K8+EifFNX65kXwMoFsnmKeE 10 | RuuzVxEl3ZAUF4ENrIxa79FHdEaKAT2EuytxgBUuZNBzQsRKlqXejMPCjsIFdEDT 11 | oNzG8xya9NuQQC/tpr4DODsmCO8yKh0jvDmERro2fcPBSIY00AUtIdoyCdV1UEXF 12 | NWzPadqexUkg7FxRnf01gp/MD+7BFQIDAQABo1AwTjAdBgNVHQ4EFgQUvNHBftjg 13 | qUIOaCg/OkcI21MFN4IwHwYDVR0jBBgwFoAUvNHBftjgqUIOaCg/OkcI21MFN4Iw 14 | DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAC+NIv4JwP9fKvdTsveUY 15 | AQ+ggbSaBWfDbKQmQgaCDYy8YCh5fBnGR2tRjTS87f5GgE1hNp/9OMNL+pp5zNmr 16 | JBulkuqYop7MXCfrkf6AWsYXjPwnmQgN0NYdZNjlPmeiq/TLlsoVOTUhhvMnL/Qx 17 | amxX8sNUnGkEHQl/eNK2bpGNifbqPYmLy1BNhlB1KutJUul+AkK4cKM5wxcClh3T 18 | 1ZG7IoJTACaQWenG4Rn5UuZQf41hINv6NwXLw5tjEAjD2dBMgHRuLz7hyw4EqXRA 19 | TWlgBUOJm06XFgDbjOLJuzs3t5/ze3cmLBfqAL/IuEHG8FAs8my8GCGPolUmKxjS 20 | UA== 21 | -----END CERTIFICATE----- 22 | -------------------------------------------------------------------------------- /configuration.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | 3 | { 4 | imports = [ ./qemu.nix ]; 5 | not-os.nix = true; 6 | environment.systemPackages = [ pkgs.utillinux ]; 7 | environment.etc = { 8 | "ssh/authorized_keys.d/root" = { 9 | text = '' 10 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC34wZQFEOGkA5b0Z6maE3aKy/ix1MiK1D0Qmg4E9skAA57yKtWYzjA23r5OCF4Nhlj1CuYd6P1sEI/fMnxf+KkqqgW3ZoZ0+pQu4Bd8Ymi3OkkQX9kiq2coD3AFI6JytC6uBi6FaZQT5fG59DbXhxO5YpZlym8ps1obyCBX0hyKntD18RgHNaNM+jkQOhQ5OoxKsBEobxQOEdjIowl2QeEHb99n45sFr53NFqk3UCz0Y7ZMf1hSFQPuuEC/wExzBBJ1Wl7E1LlNA4p9O3qJUSadGZS4e5nSLqMnbQWv2icQS/7J8IwY0M8r1MsL8mdnlXHUofPlG1r4mtovQ2myzOx clever@nixos 11 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKITUnIETct0d1Ky7iEofM8BV/U9ViuAd72abm26ibhkVKYuLlIvNBtf7+fsyaHR3cc4kmiUz26co4LV2q10HLO7nua7Ry0QhtPvPnpudandB4LbV4ieW1cqcWcPpsM1GssUZhZthbkwLf7h2exojqVj8vqPm5RaBl1eULXaPTldCiSe5ZxNuVbm3qT8Lfc2E3ifKT6A7WqZN00f1+YSnaA9uy0VgVDReDqyujAZaKGUwSa2G8eqzN3guN7VcBZek2p1v1n0EwpFdBxzT3Ncqh5wIYPNn084q5lU13TAjw+tTO7Q059e4HFLaR24w8NT60BrO1dbGYLbjWNri1G3pz root@router 12 | ''; 13 | mode = "0444"; 14 | }; 15 | }; 16 | } 17 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { configuration ? import ./configuration.nix 2 | , nixpkgs ? 3 | , extraModules ? [] 4 | , system ? builtins.currentSystem 5 | , platform ? null 6 | , crossSystem ? null }: 7 | 8 | let 9 | pkgs = import nixpkgs { inherit system; platform = platform; config = {}; }; 10 | pkgsModule = {config, ... }: { 11 | _file = ./default.nix; 12 | key = ./default.nix; 13 | config = { 14 | nixpkgs.pkgs = (import nixpkgs { 15 | inherit system crossSystem; 16 | #crossSystem = (import ).systems.examples.aarch64-multiplatform; 17 | config = config.nixpkgs.config; 18 | overlays = config.nixpkgs.overlays; 19 | }); 20 | nixpkgs.localSystem = { 21 | inherit system; 22 | } // pkgs.lib.optionalAttrs (crossSystem != null) { 23 | inherit crossSystem; 24 | }; 25 | }; 26 | }; 27 | baseModules = [ 28 | ./base.nix 29 | ./system-path.nix 30 | ./stage-1.nix 31 | ./stage-2.nix 32 | ./runit.nix 33 | (nixpkgs + "/nixos/modules/system/etc/etc.nix") 34 | (nixpkgs + "/nixos/modules/system/activation/activation-script.nix") 35 | (nixpkgs + "/nixos/modules/misc/nixpkgs.nix") 36 | (nixpkgs + "/nixos/modules/system/boot/kernel.nix") 37 | (nixpkgs + "/nixos/modules/misc/assertions.nix") 38 | (nixpkgs + "/nixos/modules/misc/lib.nix") 39 | (nixpkgs + "/nixos/modules/config/sysctl.nix") 40 | ./ipxe.nix 41 | ./systemd-compat.nix 42 | pkgsModule 43 | ]; 44 | other = { 45 | _module.check = true; 46 | _module.args = {}; 47 | }; 48 | evalConfig = modules: pkgs.lib.evalModules { 49 | prefix = []; 50 | modules = modules ++ baseModules ++ [ pkgsModule other ] ++ extraModules; 51 | }; 52 | in 53 | rec { 54 | test1 = evalConfig [ 55 | configuration 56 | ]; 57 | runner = test1.config.system.build.runvm; 58 | config = test1.config; 59 | } 60 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "firmware": { 4 | "flake": false, 5 | "locked": { 6 | "lastModified": 1697732010, 7 | "narHash": "sha256-kGXbqkqHCPU2Xz6az3LtdAccVzGtlq+vnTLiR3Xl9+8=", 8 | "owner": "raspberrypi", 9 | "repo": "firmware", 10 | "rev": "ce3a0b4197eaf311ba0734efdb9f5bdedefe5e27", 11 | "type": "github" 12 | }, 13 | "original": { 14 | "owner": "raspberrypi", 15 | "repo": "firmware", 16 | "type": "github" 17 | } 18 | }, 19 | "nixpkgs": { 20 | "locked": { 21 | "lastModified": 1697730408, 22 | "narHash": "sha256-Ww//zzukdTrwTrCUkaJA/NsaLEfUfQpWZXBdXBYfhak=", 23 | "owner": "NixOS", 24 | "repo": "nixpkgs", 25 | "rev": "ff0a5a776b56e0ca32d47a4a47695452ec7f7d80", 26 | "type": "github" 27 | }, 28 | "original": { 29 | "id": "nixpkgs", 30 | "type": "indirect" 31 | } 32 | }, 33 | "root": { 34 | "inputs": { 35 | "firmware": "firmware", 36 | "nixpkgs": "nixpkgs" 37 | } 38 | } 39 | }, 40 | "root": "root", 41 | "version": 7 42 | } 43 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | inputs = { 3 | firmware = { 4 | url = "github:raspberrypi/firmware"; 5 | flake = false; 6 | }; 7 | }; 8 | outputs = { self, nixpkgs, firmware }: { 9 | packages.armv7l-linux = let 10 | platforms = (import nixpkgs { config = {}; }).platforms; 11 | eval = (import ./default.nix { 12 | extraModules = [ 13 | ./rpi_image.nix 14 | { system.build.rpi_firmware = firmware; } 15 | ]; 16 | platform = system: platforms.raspberrypi2; 17 | system = "x86_64-linux"; 18 | crossSystem.system = "armv7l-linux"; 19 | inherit nixpkgs; 20 | }); 21 | zynq_eval = (import ./. { 22 | extraModules = [ 23 | ./zynq_image.nix 24 | ]; 25 | platform = system: platforms.raspberrypi2; 26 | system = "x86_64-linux"; 27 | crossSystem.system = "armv7l-linux"; 28 | inherit nixpkgs; 29 | }); 30 | in { 31 | rpi_image = eval.config.system.build.rpi_image; 32 | rpi_image_tar = eval.config.system.build.rpi_image_tar; 33 | toplevel = eval.config.system.build.toplevel; 34 | zynq_image = zynq_eval.config.system.build.zynq_image; 35 | }; 36 | hydraJobs = { 37 | armv7l-linux = { 38 | rpi_image_tar = self.packages.armv7l-linux.rpi_image_tar; 39 | zynq_image = self.packages.armv7l-linux.zynq_image; 40 | }; 41 | }; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /gen_ca: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | mkdir -p ca/signed 4 | echo 01 > ca/ca.srl 5 | touch ca/ca.idx 6 | mkdir ca/signed 7 | 8 | openssl genrsa -out ca/root.key 2048 9 | openssl req -x509 -new -nodes -key ca/root.key -sha256 -days 1024 -out ca/root.pem 10 | 11 | openssl req -newkey rsa -nodes -keyout ca/codesign.key -out ca/codesign.req 12 | openssl ca -config ca.cnf -extensions codesigning -in ca/codesign.req -days 1024 -out ca/codesign.crt 13 | -------------------------------------------------------------------------------- /gen_keys: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | mkdir ssh 3 | ssh-keygen -t rsa -b 4096 -f ssh/ssh_host_rsa_key -N "" 4 | ssh-keygen -t ed25519 -f ssh/ssh_host_ed25519_key -N "" 5 | -------------------------------------------------------------------------------- /ipxe.nix: -------------------------------------------------------------------------------- 1 | { pkgs, config, ... }: 2 | 3 | let 4 | ipxe_script = pkgs.writeText "script.ipxe" '' 5 | #!ipxe 6 | :restart 7 | menu iPXE boot menu 8 | item normal Boot normally 9 | item loop Start iPXE shell 10 | item off Shutdown 11 | item reset Reboot 12 | choose --default normal --timeout 5000 res || goto restart 13 | goto ''${res} 14 | 15 | :off 16 | poweroff 17 | goto off 18 | :reset 19 | reboot 20 | goto reset 21 | 22 | :normal 23 | imgfree 24 | imgfetch tftp://10.0.2.2/kernel root=/root.squashfs console=tty0 console=ttyS0 panic=-1 ${toString config.boot.kernelParams} || goto normal 25 | imgfetch tftp://10.0.2.2/initrd || goto normal 26 | imgfetch tftp://10.0.2.2/root.squashfs root.squashfs || goto normal 27 | imgverify kernel tftp://10.0.2.2/kernel.sig 28 | imgverify initrd tftp://10.0.2.2/initrd.sig 29 | imgverify root.squashfs tftp://10.0.2.2/root.squashfs.sig 30 | imgselect kernel 31 | boot 32 | 33 | :loop 34 | login || goto cancelled 35 | 36 | iseq ''${password} hunter2 && goto is_correct || 37 | echo password wrong 38 | sleep 5 39 | goto loop 40 | 41 | :cancelled 42 | echo you gave up, goodbye 43 | sleep 5 44 | poweroff 45 | goto cancelled 46 | 47 | :is_correct 48 | shell 49 | ''; 50 | ftpdir = pkgs.runCommand "ftpdir" { buildInputs = [ pkgs.openssl ]; } '' 51 | mkdir $out 52 | ln -sv ${config.system.build.dist}/kernel $out/ 53 | ln -sv ${config.system.build.dist}/initrd $out/ 54 | ln -sv ${config.system.build.dist}/root.squashfs $out/ 55 | ln -sv ${ipxe_script} $out/script.ipxe 56 | function signit { 57 | openssl cms -sign -binary -noattr -in $1 -signer ${./ca/codesign.crt} -inkey ${./ca/codesign.key} -certfile ${./ca/root.pem} -outform DER -out ''${1}.sig 58 | } 59 | signit $out/kernel 60 | signit $out/initrd 61 | signit $out/script.ipxe 62 | signit $out/root.squashfs 63 | ''; 64 | ipxe = pkgs.lib.overrideDerivation pkgs.ipxe (x: { 65 | script = pkgs.writeText "embed.ipxe" '' 66 | #!ipxe 67 | imgtrust --permanent 68 | dhcp 69 | imgfetch tftp://10.0.2.2/script.ipxe 70 | imgverify script.ipxe tftp://10.0.2.2/script.ipxe.sig 71 | chain script.ipxe 72 | echo temporary debug shell 73 | shell 74 | ''; 75 | ca_cert = ./ca/root.pem; 76 | nativeBuildInputs = x.nativeBuildInputs ++ [ pkgs.openssl ]; 77 | makeFlags = x.makeFlags ++ [ 78 | ''EMBED=''${script}'' 79 | ''TRUST=''${ca_cert}'' 80 | "CERT=${./ca/codesign.crt},${./ca/root.pem}" 81 | #"bin-i386-efi/ipxe.efi" "bin-i386-efi/ipxe.efidrv" 82 | ]; 83 | 84 | enabledOptions = x.enabledOptions ++ [ "CONSOLE_SERIAL" "POWEROFF_CMD" "IMAGE_TRUST_CMD" ]; 85 | }); 86 | testipxe = pkgs.writeScript "runner" '' 87 | #!${pkgs.stdenv.shell} 88 | exec ${pkgs.qemu_kvm}/bin/qemu-kvm -name not-os -m 512 \ 89 | -kernel ${ipxe}/ipxe.lkrn \ 90 | -net nic,vlan=0,model=virtio \ 91 | -net user,vlan=0,net=10.0.2.0/24,host=10.0.2.2,dns=10.0.2.3,hostfwd=tcp::2222-:22,tftp=${ftpdir} \ 92 | -net dump,vlan=0 \ 93 | -device virtio-rng-pci -serial stdio 94 | ''; 95 | in 96 | { 97 | options = { 98 | }; 99 | config = { 100 | system.build = { 101 | inherit ipxe_script ftpdir ipxe testipxe; 102 | }; 103 | }; 104 | } 105 | -------------------------------------------------------------------------------- /linux-build-slave.nix: -------------------------------------------------------------------------------- 1 | { sshKeyFile ? null, memory ? 512, rootsize ? "10g" }: 2 | # usage: nix-build linux-build-slave.nix -I nixpkgs=https://github.com/nixos/nixpkgs/archive/c29d2fde74d.tar.gz --arg sshKeyFile ~/.ssh/id_rsa.pub 3 | let 4 | pkgs = import {}; 5 | eval = import ./. { 6 | inherit configuration; 7 | system = "x86_64-linux"; 8 | }; 9 | configuration = { pkgs, ... }: { 10 | imports = [ ./qemu.nix ]; 11 | not-os = { 12 | nix = true; 13 | simpleStaticIp = true; 14 | preMount = '' 15 | ${pkgs.e2fsprogs}/bin/mkfs.ext4 $realroot || true 16 | ''; 17 | }; 18 | boot.kernelParams = [ "realroot=/dev/vdb" ]; 19 | boot.initrd.kernelModules = [ "ext4" "crc32c_generic" ]; 20 | environment.systemPackages = with pkgs; [ ]; 21 | environment.etc = { 22 | "ssh/authorized_keys.d/root" = { 23 | text = "${if (sshKeyFile != null) then builtins.readFile sshKeyFile else ""}"; 24 | mode = "0444"; 25 | }; 26 | }; 27 | }; 28 | runvm = pkgs.writeScript "runner" '' 29 | #!${pkgs.stdenv.shell} 30 | set -e 31 | 32 | export PATH=${pkgs.coreutils}/bin/:$PATH 33 | 34 | rm -f rootdisk.img 35 | truncate -s ${rootsize} rootdisk.img 36 | 37 | exec ${pkgs.qemu_kvm}/bin/qemu-kvm -name buildSlave -m ${toString memory} \ 38 | -drive index=0,id=drive0,file=${eval.config.system.build.squashfs},readonly=on,media=cdrom,format=raw,if=virtio \ 39 | -drive index=1,id=drive1,file=rootdisk.img,format=raw,if=virtio \ 40 | -kernel ${eval.config.system.build.kernel}/bzImage -initrd ${eval.config.system.build.initialRamdisk}/initrd -nographic \ 41 | -append "console=ttyS0 ${toString eval.config.boot.kernelParams} quiet panic=-1" -no-reboot \ 42 | -net nic,model=virtio \ 43 | -net user,net=10.0.2.0/24,host=10.0.2.2,dns=10.0.2.3,hostfwd=tcp::2222-:22 \ 44 | -device virtio-rng-pci 45 | ''; 46 | in { 47 | inherit runvm; 48 | } 49 | -------------------------------------------------------------------------------- /linux-rpi.nix: -------------------------------------------------------------------------------- 1 | { stdenv, fetchFromGitHub, perl, buildLinux, ... } @ args: 2 | 3 | let 4 | modDirVersion = "4.4.36"; 5 | tag = "1.20161020-1"; 6 | in 7 | stdenv.lib.overrideDerivation (import (args // rec { 8 | version = "${modDirVersion}-${tag}"; 9 | inherit modDirVersion; 10 | 11 | src = fetchFromGitHub { 12 | owner = "raspberrypi"; 13 | repo = "linux"; 14 | rev = "c6d86f7aa554854b04614ebb4d394766081fb41f"; 15 | sha256 = "13rjmks4whh7kn0wrswanwq3b0ia9bxsq8a6xiqiivh6k3vxqhys"; 16 | }; 17 | 18 | features.iwlwifi = true; 19 | features.needsCifsUtils = true; 20 | features.canDisableNetfilterConntrackHelpers = true; 21 | features.netfilterRPFilter = true; 22 | 23 | extraMeta.hydraPlatforms = []; 24 | })) (oldAttrs: { 25 | postConfigure = '' 26 | # The v7 defconfig has this set to '-v7' which screws up our modDirVersion. 27 | sed -i $buildRoot/.config -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/' 28 | ''; 29 | 30 | postFixup = '' 31 | # Make copies of the DTBs so that U-Boot finds them, as it is looking for the upstream names. 32 | # This is ugly as heck. 33 | copyDTB() { 34 | if [ -f "$out/dtbs/$1" ]; then 35 | cp -v "$out/dtbs/$1" "$out/dtbs/$2" 36 | fi 37 | } 38 | 39 | # I am not sure if all of these are correct... 40 | copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-a.dtb 41 | copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b.dtb 42 | copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b-rev2.dtb 43 | copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-a-plus.dtb 44 | copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-b-plus.dtb 45 | copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-zero.dtb 46 | copyDTB bcm2708-rpi-cm.dtb bcm2835-rpi-cm.dtb 47 | copyDTB bcm2709-rpi-2-b.dtb bcm2836-rpi-2-b.dtb 48 | copyDTB bcm2710-rpi-3-b.dtb bcm2837-rpi-3-b.dtb 49 | ''; 50 | }) 51 | -------------------------------------------------------------------------------- /nix.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | 3 | { 4 | } 5 | -------------------------------------------------------------------------------- /notes.txt: -------------------------------------------------------------------------------- 1 | http://wiki.qemu.org/Features-Done/VirtIORNG to improve entropy for toxvpn 2 | -------------------------------------------------------------------------------- /qemu.nix: -------------------------------------------------------------------------------- 1 | { ... }: 2 | 3 | { 4 | boot.initrd.kernelModules = [ "virtio" "virtio_pci" "virtio_net" "virtio_rng" "virtio_blk" "virtio_console" ]; 5 | } 6 | -------------------------------------------------------------------------------- /release.nix: -------------------------------------------------------------------------------- 1 | { supportedSystems ? [ "x86_64-linux" "i686-linux" ], supportedSystems2 ? [ "x86_64-linux" "i686-linux" "armv6l-linux" ] }: 2 | 3 | with import ; 4 | 5 | let 6 | pkgs = import { config = {}; }; 7 | forAllSystems = genAttrs supportedSystems; 8 | forAllSystems2 = genAttrs supportedSystems2; 9 | importTest = fn: args: system: import fn ({ 10 | inherit system; 11 | } // args); 12 | callTest = fn: args: forAllSystems (system: hydraJob (importTest fn args system)); 13 | callSubTests = fn: args: let 14 | discover = attrs: let 15 | subTests = filterAttrs (const (hasAttr "test")) attrs; 16 | in mapAttrs (const (t: hydraJob t.test)) subTests; 17 | 18 | discoverForSystem = system: mapAttrs (_: test: { 19 | ${system} = test; 20 | }) (discover (importTest fn args system)); 21 | # If the test is only for a particular system, use only the specified 22 | # system instead of generating attributes for all available systems. 23 | in if args ? system then discover (import fn args) 24 | else foldAttrs mergeAttrs {} (map discoverForSystem supportedSystems); 25 | platforms = (import { config = {}; }).platforms; 26 | platformForSystem = system: if system == "armv7l-linux" then platforms.raspberrypi2 else null; 27 | fetchClosure = f: forAllSystems (system: f (import ./default.nix { inherit system; }).config ); 28 | fetchClosure2 = f: forAllSystems2 (system: f (import ./default.nix { inherit system; platform = platformForSystem system; }).config ); 29 | in 30 | { 31 | tests.boot = callSubTests tests/boot.nix {}; 32 | closureSizes = { 33 | toplevel = fetchClosure2 (cfg: cfg.system.build.toplevel); 34 | initialRamdisk = fetchClosure2 (cfg: cfg.system.build.initialRamdisk); 35 | squashed = fetchClosure2 (cfg: cfg.system.build.squashfs); 36 | }; 37 | libraspberrypi = (import { config = {}; system = "armv7l-linux"; }).libraspberrypi; 38 | dist_test = fetchClosure2 (cfg: pkgs.runCommand "dist" { inherit (cfg.system.build) dist kernel; config = cfg.system.build.kernel.configfile; }'' 39 | #!/bin/sh 40 | mkdir -p $out/nix-support 41 | echo file kernel ''${dist}/kernel > $out/nix-support/hydra-build-products 42 | echo file rootfs ''${dist}/root.squashfs >> $out/nix-support/hydra-build-products 43 | echo file initrd ''${dist}/initrd >> $out/nix-support/hydra-build-products 44 | echo file command-line ''${dist}/command-line >> $out/nix-support/hydra-build-products 45 | cd $out 46 | ln -sv ''${dist}/initrd 47 | ln -sv ''${dist}/kernel 48 | ln -sv ''${dist}/root.squashfs 49 | ln -sv ''${config} config 50 | for x in $kernel/dtbs/*;do ln -sv $x $out/;done 51 | ''); 52 | #rpi_image = (import ./default.nix { extraModules = [ ./rpi_image.nix ]; platform = system: platforms.raspberrypi2; }).config.system.build.rpi_image; 53 | } 54 | -------------------------------------------------------------------------------- /rpi-base.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | let 4 | in { 5 | options = { 6 | rpi.rpi1 = lib.mkEnableOption "support pi1"; 7 | rpi.rpi2 = lib.mkEnableOption "support pi2"; 8 | rpi.rpi3 = lib.mkEnableOption "support pi3"; 9 | rpi.rpi4 = lib.mkEnableOption "support pi4"; 10 | rpi.rpi5 = lib.mkEnableOption "support pi5"; 11 | rpi.copyKernels = lib.mkOption { 12 | type = lib.types.separatedString "\n"; 13 | }; 14 | }; 15 | config = lib.mkMerge [ 16 | (lib.mkIf config.rpi.rpi1 { 17 | rpi.copyKernels = '' 18 | cp ${pkgs.linuxPackages_rpi1}/zImage kernel.img 19 | ''; 20 | }) 21 | (lib.mkIf config.rpi.rpi2 { 22 | rpi.copyKernels = '' 23 | cp ${pkgs.linuxPackages_rpi2}/zImage kernel7.img 24 | ''; 25 | }) 26 | ]; 27 | } 28 | -------------------------------------------------------------------------------- /rpi_image.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | { 4 | boot.kernelPackages = pkgs.linuxPackages_rpi2; 5 | imports = [ 6 | ./arm32-cross-fixes.nix 7 | ./rpi-base.nix 8 | ]; 9 | nixpkgs.system = "armv7l-linux"; 10 | rpi.rpi1 = true; 11 | rpi.rpi2 = true; 12 | system.build.rpi_image = let 13 | config_txt = pkgs.writeText "config.txt" '' 14 | initramfs initrd followkernel 15 | dtoverlay=pi3-disable-bt 16 | enable_uart=1 17 | auto_initramfs=1 18 | ramfsfile=initrd 19 | ''; 20 | cmdline = pkgs.writeText "cmdline.txt" '' 21 | console=ttyS0,115200 pi3-disable-bt kgdboc=ttyS0,115200 systemConfig=${builtins.unsafeDiscardStringContext config.system.build.toplevel} netroot=192.168.2.1=9080d9b6/root.squashfs quiet splash plymouth.ignore-serial-consoles plymouth.ignore-udev 22 | ''; 23 | firm = config.system.build.rpi_firmware; 24 | in pkgs.runCommand "rpi_image" {} '' 25 | mkdir $out 26 | cd $out 27 | cp ${config_txt} config.txt 28 | cp ${cmdline} cmdline.txt 29 | cp ${config.system.build.kernel}/*zImage kernel7.img 30 | cp ${config.system.build.squashfs} root.squashfs 31 | cp ${firm}/boot/{bcm2710-rpi-3-b.dtb,bcm2709-rpi-2-b.dtb} . 32 | cp -r ${firm}/boot/overlays overlays 33 | cp ${firm}/boot/start.elf start.elf 34 | cp ${firm}/boot/fixup.dat fixup.dat 35 | cp ${config.system.build.initialRamdisk}/initrd initrd 36 | ls -ltrhL 37 | ''; 38 | system.build.rpi_image_tar = pkgs.runCommand "dist.tar" {} '' 39 | mkdir -p $out/nix-support 40 | tar -cvf $out/dist.tar ${config.system.build.rpi_image} 41 | echo "file binary-dist $out/dist.tar" >> $out/nix-support/hydra-build-products 42 | ''; 43 | environment.systemPackages = [ pkgs.strace ]; 44 | nixpkgs.config.packageOverrides = pkgs: { 45 | linux_rpi = pkgs.callPackage ./linux-rpi.nix {}; 46 | }; 47 | nixpkgs.overlays = [ 48 | (self: super: { 49 | openssh = super.openssh.override { withFIDO = false; withKerberos = false; }; 50 | util-linux = super.util-linux.override { pamSupport=false; capabilitiesSupport=false; ncursesSupport=false; systemdSupport=false; nlsSupport=false; translateManpages=false; }; 51 | utillinuxCurses = self.util-linux; 52 | utillinuxMinimal = self.util-linux; 53 | }) 54 | ]; 55 | } 56 | -------------------------------------------------------------------------------- /runit.nix: -------------------------------------------------------------------------------- 1 | { pkgs, lib, config, ... }: 2 | 3 | let 4 | sshd_config = pkgs.writeText "sshd_config" '' 5 | HostKey /etc/ssh/ssh_host_rsa_key 6 | HostKey /etc/ssh/ssh_host_ed25519_key 7 | Port 22 8 | PidFile /run/sshd.pid 9 | Protocol 2 10 | PermitRootLogin yes 11 | PasswordAuthentication yes 12 | AuthorizedKeysFile /etc/ssh/authorized_keys.d/%u 13 | ''; 14 | compat = pkgs.runCommand "runit-compat" {} '' 15 | mkdir -p $out/bin/ 16 | cat << EOF > $out/bin/poweroff 17 | #!/bin/sh 18 | exec runit-init 0 19 | EOF 20 | cat << EOF > $out/bin/reboot 21 | #!/bin/sh 22 | exec runit-init 6 23 | EOF 24 | chmod +x $out/bin/{poweroff,reboot} 25 | ''; 26 | in 27 | { 28 | environment.systemPackages = [ compat ]; 29 | environment.etc = lib.mkMerge [ 30 | { 31 | "runit/1".source = pkgs.writeScript "1" '' 32 | #!${pkgs.runtimeShell} 33 | ${lib.optionalString config.not-os.simpleStaticIp '' 34 | ip addr add 10.0.2.15 dev eth0 35 | ip link set eth0 up 36 | ip route add 10.0.2.0/24 dev eth0 37 | ip route add default via 10.0.2.2 dev eth0 38 | ''} 39 | mkdir /bin/ 40 | ln -s ${pkgs.runtimeShell} /bin/sh 41 | 42 | ${lib.optionalString (config.networking.timeServers != []) '' 43 | ${pkgs.ntp}/bin/ntpdate ${toString config.networking.timeServers} 44 | ''} 45 | 46 | # disable DPMS on tty's 47 | echo -ne "\033[9;0]" > /dev/tty0 48 | 49 | touch /etc/runit/stopit 50 | chmod 0 /etc/runit/stopit 51 | ${if true then "" else "${pkgs.dhcpcd}/sbin/dhcpcd"} 52 | ''; 53 | "runit/2".source = pkgs.writeScript "2" '' 54 | #!${pkgs.runtimeShell} 55 | cat /proc/uptime 56 | exec runsvdir -P /etc/service 57 | ''; 58 | "runit/3".source = pkgs.writeScript "3" '' 59 | #!${pkgs.runtimeShell} 60 | echo and down we go 61 | ''; 62 | "service/sshd/run".source = pkgs.writeScript "sshd_run" '' 63 | #!${pkgs.runtimeShell} 64 | ${pkgs.openssh}/bin/sshd -f ${sshd_config} 65 | ''; 66 | "service/nix/run".source = pkgs.writeScript "nix" '' 67 | #!${pkgs.runtimeShell} 68 | nix-store --load-db < /nix/store/nix-path-registration 69 | nix-daemon 70 | ''; 71 | } 72 | (lib.mkIf config.not-os.rngd { 73 | "service/rngd/run".source = pkgs.writeScript "rngd" '' 74 | #!${pkgs.runtimeShell} 75 | export PATH=$PATH:${pkgs.rng-tools}/bin 76 | exec rngd -r /dev/hwrng 77 | ''; 78 | }) 79 | ]; 80 | } 81 | -------------------------------------------------------------------------------- /ssh/ssh_host_ed25519_key: -------------------------------------------------------------------------------- 1 | -----BEGIN OPENSSH PRIVATE KEY----- 2 | b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW 3 | QyNTUxOQAAACCyu5b2+49W47G9KYQj+7xz1YuY3w3Iz1kb/eIgNWPF7wAAAJhmBZVCZgWV 4 | QgAAAAtzc2gtZWQyNTUxOQAAACCyu5b2+49W47G9KYQj+7xz1YuY3w3Iz1kb/eIgNWPF7w 5 | AAAEBALOVU4aPZln0n7z7AR5jOoVnT7OhWAJiROqTw9ecEILK7lvb7j1bjsb0phCP7vHPV 6 | i5jfDcjPWRv94iA1Y8XvAAAAEGNsZXZlckBhbWQtbml4b3MBAgMEBQ== 7 | -----END OPENSSH PRIVATE KEY----- 8 | -------------------------------------------------------------------------------- /ssh/ssh_host_ed25519_key.pub: -------------------------------------------------------------------------------- 1 | ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILK7lvb7j1bjsb0phCP7vHPVi5jfDcjPWRv94iA1Y8Xv clever@amd-nixos 2 | -------------------------------------------------------------------------------- /ssh/ssh_host_rsa_key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | 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 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /ssh/ssh_host_rsa_key.pub: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDFMHZqYRB1GfEoqhOmbzUTJ13SBKCKi13RSN6D54SQCsvCVa/qCOh40TNw0fy1nSDeyOTVJWF5k3F0dYJeomcv8QimgafxU1bumBE/VmBbjzA+Mnt03x697/bx3ZAINgSRk0NOMfMMQc/9PGeCMDqWWLQpfpJ8lspSapH+R2fwDk2myMwGaND9SQxMAf8obceFIdGiWMcWzJ8rD3Xtre471qEuIScWKHfr9X1qeOWNugRkC7Fco0VQkVaSf5A8Yuc9C2s/zllS1IQWLCM4JyMJy2mz6aJEnBmw0cTZ6up6Ulslvu8Kr6lqh9/FzbtTt2G8ujPZ/1dqVbhKPyYvjmTLKys3hYFIPGLXOc+PEPo+42xpsJ5MGKwePYzT1m/uFkihHncm/pyPBmgwvkw3pUDbJz84Chi8MAkRP9lE+SXy3PO8xehj5t/JSK1gDcUmMEicWb6aZWQdOqL9XtLAUpYZdGEA7YlTRxRdSsPIjs4qc1LhW56Hk7tQcaG0G+gUsOmSv0YnA0k1le010rvt5Bc8OS/STapBwtlAsZFHiEFMgv0YCATeeUIazps3D46BqJYypwvCh7wgF6rRYOuNEMS7Kgg5EQBBhnS3BiuG9PmsteHP0gmdTKfs/u5fj+La0NbLeI8ckc20VIPaUsD7G5cDrGhbVER8veUKkgdm2mik/w== clever@amd-nixos 2 | -------------------------------------------------------------------------------- /stage-1.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, config, ... }: 2 | 3 | with lib; 4 | let 5 | modules = pkgs.makeModulesClosure { 6 | rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules; 7 | allowMissing = true; 8 | kernel = config.system.build.kernel; 9 | firmware = config.hardware.firmware; 10 | }; 11 | plymouth = (pkgs.plymouth.override { 12 | udev = null; 13 | gtk3 = null; 14 | systemd = null; 15 | }).overrideDerivation (old: { 16 | #src = /tmp/plymouth; 17 | src = pkgs.fetchgit { 18 | url = "https://anongit.freedesktop.org/git/plymouth"; 19 | rev = "266d954b7a0ff5b046df6ed54c22e3322b2c80d0"; 20 | sha256 = "10k7vfbfp3q1ysw3w5nd6wnixizbng3lqbb21bgd18v997k74xb3"; 21 | }; 22 | #patches2 = [ ./fix2.patch ./udev3.patch ]; 23 | }); 24 | dhcpcd = pkgs.dhcpcd.override { udev = null; }; 25 | extraUtils = pkgs.runCommandCC "extra-utils" 26 | { 27 | nativeBuildInputs = [ pkgs.nukeReferences ]; 28 | allowedReferences = [ "out" ]; 29 | } '' 30 | set +o pipefail 31 | mkdir -p $out/bin $out/lib 32 | ln -s $out/bin $out/sbin 33 | 34 | copy_bin_and_libs() { 35 | [ -f "$out/bin/$(basename $1)" ] && rm "$out/bin/$(basename $1)" 36 | cp -pd $1 $out/bin 37 | } 38 | 39 | # Copy Busybox 40 | for BIN in ${pkgs.busybox}/{s,}bin/*; do 41 | copy_bin_and_libs $BIN 42 | done 43 | 44 | copy_bin_and_libs ${pkgs.dhcpcd}/bin/dhcpcd 45 | 46 | # Copy ld manually since it isn't detected correctly 47 | cp -pv ${pkgs.glibc.out}/lib/ld*.so.? $out/lib 48 | 49 | # Copy all of the needed libraries 50 | find $out/bin $out/lib -type f | while read BIN; do 51 | echo "Copying libs for executable $BIN" 52 | LDD="$(ldd $BIN)" || continue 53 | LIBS="$(echo "$LDD" | awk '{print $3}' | sed '/^$/d')" 54 | for LIB in $LIBS; do 55 | TGT="$out/lib/$(basename $LIB)" 56 | if [ ! -f "$TGT" ]; then 57 | SRC="$(readlink -e $LIB)" 58 | cp -pdv "$SRC" "$TGT" 59 | fi 60 | done 61 | done 62 | 63 | # Strip binaries further than normal. 64 | chmod -R u+w $out 65 | stripDirs "lib bin" "-s" 66 | 67 | # Run patchelf to make the programs refer to the copied libraries. 68 | find $out/bin $out/lib -type f | while read i; do 69 | if ! test -L $i; then 70 | nuke-refs -e $out $i 71 | fi 72 | done 73 | 74 | find $out/bin -type f | while read i; do 75 | if ! test -L $i; then 76 | echo "patching $i..." 77 | patchelf --set-interpreter $out/lib/ld*.so.? --set-rpath $out/lib $i || true 78 | fi 79 | done 80 | 81 | # Make sure that the patchelf'ed binaries still work. 82 | echo "testing patched programs..." 83 | $out/bin/ash -c 'echo hello world' | grep "hello world" 84 | export LD_LIBRARY_PATH=$out/lib 85 | $out/bin/mount --help 2>&1 | grep -q "BusyBox" 86 | ''; 87 | shell = "${extraUtils}/bin/ash"; 88 | enablePlymouth = false; 89 | dhcpHook = pkgs.writeScript "dhcpHook" '' 90 | #!${shell} 91 | ''; 92 | bootStage1 = pkgs.writeScript "stage1" '' 93 | #!${shell} 94 | echo 95 | echo "<<< NotOS Stage 1 >>>" 96 | echo 97 | 98 | export PATH=${extraUtils}/bin/${lib.optionalString enablePlymouth ":${plymouth}/bin/"} 99 | mkdir -p /proc /sys /dev /etc/udev /tmp /run/ /lib/ /mnt/ /var/log /etc/plymouth /bin 100 | mount -t devtmpfs devtmpfs /dev/ 101 | mount -t proc proc /proc 102 | mount -t sysfs sysfs /sys 103 | 104 | ${lib.optionalString enablePlymouth '' 105 | ln -sv ${plymouth}/lib/plymouth /etc/plymouth/plugins 106 | ln -sv ${plymouth}/etc/plymouth/plymouthd.conf /etc/plymouth/plymouthd.conf 107 | ln -sv ${plymouth}/share/plymouth/plymouthd.defaults /etc/plymouth//plymouthd.defaults 108 | ln -sv ${plymouth}/share/plymouth/themes /etc/plymouth/themes 109 | ln -sv /dev/fb0 /dev/fb 110 | ''} 111 | ln -sv ${shell} /bin/sh 112 | ln -s ${modules}/lib/modules /lib/modules 113 | 114 | ${lib.optionalString enablePlymouth '' 115 | # gdb --args plymouthd --debug --mode=boot --no-daemon 116 | sleep 1 117 | plymouth --show-splash 118 | ''} 119 | 120 | 121 | for x in ${lib.concatStringsSep " " config.boot.initrd.kernelModules}; do 122 | modprobe $x 123 | done 124 | 125 | root=/dev/vda 126 | realroot=tmpfs 127 | for o in $(cat /proc/cmdline); do 128 | case $o in 129 | systemConfig=*) 130 | set -- $(IFS==; echo $o) 131 | sysconfig=$2 132 | ;; 133 | root=*) 134 | set -- $(IFS==; echo $o) 135 | root=$2 136 | ;; 137 | netroot=*) 138 | set -- $(IFS==; echo $o) 139 | mkdir -pv /var/run /var/db 140 | ${lib.optionalString enablePlymouth ''plymouth display-message --text="waiting for eth"''} 141 | sleep 5 142 | ${lib.optionalString enablePlymouth ''plymouth display-message --text="dhcp query"''} 143 | dhcpcd eth0 -c ${dhcpHook} 144 | ${lib.optionalString enablePlymouth ''plymouth display-message --text="downloading rootfs"''} 145 | tftp -g -r "$3" "$2" 146 | root=/root.squashfs 147 | ;; 148 | realroot=*) 149 | set -- $(IFS==; echo $o) 150 | realroot=$2 151 | ;; 152 | esac 153 | done 154 | 155 | ${lib.optionalString enablePlymouth ''plymouth display-message --text="mounting things"''} 156 | 157 | ${config.not-os.preMount} 158 | if [ $realroot = tmpfs ]; then 159 | mount -t tmpfs root /mnt/ -o size=1G || exec ${shell} 160 | else 161 | mount $realroot /mnt || exec ${shell} 162 | fi 163 | chmod 755 /mnt/ 164 | mkdir -p /mnt/nix/store/ 165 | 166 | 167 | ${if config.not-os.nix then '' 168 | # make the store writeable 169 | mkdir -p /mnt/nix/.ro-store /mnt/nix/.overlay-store /mnt/nix/store 170 | mount $root /mnt/nix/.ro-store -t squashfs 171 | if [ $realroot = $1 ]; then 172 | mount tmpfs -t tmpfs /mnt/nix/.overlay-store -o size=1G 173 | fi 174 | mkdir -pv /mnt/nix/.overlay-store/work /mnt/nix/.overlay-store/rw 175 | modprobe overlay 176 | mount -t overlay overlay -o lowerdir=/mnt/nix/.ro-store,upperdir=/mnt/nix/.overlay-store/rw,workdir=/mnt/nix/.overlay-store/work /mnt/nix/store 177 | '' else '' 178 | # readonly store 179 | mount $root /mnt/nix/store/ -t squashfs 180 | ''} 181 | 182 | ${lib.optionalString enablePlymouth '' 183 | plymouth --newroot=/mnt 184 | plymouth update-root-fs --new-root-dir=/mnt --read-write 185 | ''} 186 | 187 | exec env -i $(type -P switch_root) /mnt/ $sysconfig/init 188 | exec ${shell} 189 | ''; 190 | initialRamdisk = pkgs.makeInitrd { 191 | contents = [ { object = bootStage1; symlink = "/init"; } ]; 192 | }; 193 | in 194 | { 195 | options = { 196 | not-os.preMount = mkOption { 197 | type = types.lines; 198 | default = ""; 199 | }; 200 | boot.initrd.enable = mkOption { 201 | type = types.bool; 202 | default = true; 203 | }; 204 | }; 205 | config = { 206 | system.build.bootStage1 = bootStage1; 207 | system.build.initialRamdisk = initialRamdisk; 208 | system.build.extraUtils = extraUtils; 209 | boot.initrd.availableKernelModules = [ ]; 210 | boot.initrd.kernelModules = [ "tun" "loop" "squashfs" ] ++ (lib.optional config.not-os.nix "overlay"); 211 | }; 212 | } 213 | -------------------------------------------------------------------------------- /stage-2-init.sh: -------------------------------------------------------------------------------- 1 | #!@runtimeShell@ 2 | 3 | systemConfig=@systemConfig@ 4 | export PATH=@path@/bin/ 5 | 6 | # Print a greeting. 7 | echo 8 | echo -e "\e[1;32m<<< NotOS Stage 2 >>>\e[0m" 9 | echo 10 | 11 | mkdir -p /proc /sys /dev /tmp /var/log /etc /root /run /nix/var/nix/gcroots 12 | mount -t proc proc /proc 13 | mount -t sysfs sys /sys 14 | mount -t devtmpfs devtmpfs /dev 15 | mkdir /dev/pts /dev/shm 16 | mount -t devpts devpts /dev/pts 17 | mount -t tmpfs tmpfs /run 18 | mount -t tmpfs tmpfs /dev/shm 19 | 20 | $systemConfig/activate 21 | 22 | exec runit 23 | -------------------------------------------------------------------------------- /stage-2.nix: -------------------------------------------------------------------------------- 1 | { lib, pkgs, config, ... }: 2 | 3 | with lib; 4 | 5 | { 6 | options = { 7 | boot = { 8 | devSize = mkOption { 9 | default = "5%"; 10 | example = "32m"; 11 | type = types.str; 12 | }; 13 | devShmSize = mkOption { 14 | default = "50%"; 15 | example = "256m"; 16 | type = types.str; 17 | }; 18 | runSize = mkOption { 19 | default = "25%"; 20 | example = "256m"; 21 | type = types.str; 22 | }; 23 | }; 24 | }; 25 | config = { 26 | system.build.bootStage2 = pkgs.substituteAll { 27 | src = ./stage-2-init.sh; 28 | isExecutable = true; 29 | path = config.system.path; 30 | inherit (pkgs) runtimeShell; 31 | }; 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /system-path.nix: -------------------------------------------------------------------------------- 1 | { config, lib, pkgs, ... }: 2 | 3 | # based heavily on https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/config/system-path.nix 4 | # crosser = if pkgs.stdenv ? cross then (x: if x ? crossDrv then x.crossDrv else x) else (x: x); 5 | 6 | with lib; 7 | 8 | let 9 | requiredPackages = with pkgs; [ utillinux coreutils iproute iputils procps bashInteractive runit ]; 10 | in 11 | { 12 | options = { 13 | environment = { 14 | systemPackages = mkOption { 15 | type = types.listOf types.package; 16 | default = []; 17 | example = literalExample "[ pkgs.firefox pkgs.thunderbird ]"; 18 | }; 19 | pathsToLink = mkOption { 20 | type = types.listOf types.str; 21 | default = []; 22 | example = ["/"]; 23 | description = "List of directories to be symlinked in /run/current-system/sw."; 24 | }; 25 | extraOutputsToInstall = mkOption { 26 | type = types.listOf types.str; 27 | default = [ ]; 28 | example = [ "doc" "info" "docdev" ]; 29 | description = "List of additional package outputs to be symlinked into /run/current-system/sw."; 30 | }; 31 | }; 32 | system.path = mkOption { 33 | internal = true; 34 | }; 35 | }; 36 | config = { 37 | environment.systemPackages = requiredPackages; 38 | environment.pathsToLink = [ "/bin" ]; 39 | system.path = pkgs.buildEnv { 40 | name = "system-path"; 41 | paths = config.environment.systemPackages; 42 | inherit (config.environment) pathsToLink extraOutputsToInstall; 43 | postBuild = '' 44 | # TODO, any system level caches that need to regenerate 45 | ''; 46 | }; 47 | }; 48 | } 49 | -------------------------------------------------------------------------------- /systemd-compat.nix: -------------------------------------------------------------------------------- 1 | { lib, ... }: 2 | 3 | with lib; 4 | 5 | { 6 | options = { 7 | # TODO, it just silently ignores all systemd services 8 | systemd.services = mkOption { 9 | }; 10 | systemd.user = mkOption { 11 | }; 12 | systemd.tmpfiles = mkOption { 13 | }; 14 | }; 15 | config = { 16 | }; 17 | } 18 | -------------------------------------------------------------------------------- /tests/boot.nix: -------------------------------------------------------------------------------- 1 | { system }: 2 | 3 | with import { inherit system; }; 4 | 5 | let 6 | config = (import ./.. { inherit system; extraModules = [ ./test-instrumentation.nix ../qemu.nix ]; }).config; 7 | in 8 | { 9 | ipxeCrypto = makeTest { 10 | name = "ipxe-crypto"; 11 | nodes = {}; 12 | testScript = '' 13 | import time 14 | 15 | machine = create_machine( 16 | { 17 | "qemuFlags": "-device virtio-rng-pci -kernel ${config.system.build.ipxe}/ipxe.lkrn -m 768 -net nic,model=e1000 -net user,tftp=${config.system.build.ftpdir}/", 18 | } 19 | ) 20 | machine.start() 21 | time.sleep(6) 22 | machine.screenshot("test1") 23 | machine.sleep(1) 24 | machine.screenshot("test2") 25 | machine.shutdown() 26 | ''; 27 | }; 28 | normalBoot = makeTest { 29 | name = "normal-boot"; 30 | nodes = {}; 31 | testScript = '' 32 | machine = create_machine( 33 | { 34 | "qemuFlags": '-device virtio-rng-pci -kernel ${config.system.build.kernel}/bzImage -initrd ${config.system.build.initialRamdisk}/initrd -append "console=tty0 console=ttyS0 ${toString config.boot.kernelParams}" -drive index=0,id=drive1,file=${config.system.build.squashfs},readonly,media=cdrom,format=raw,if=virtio', 35 | } 36 | ) 37 | machine.start() 38 | machine.sleep(1) 39 | machine.screenshot("test") 40 | machine.shutdown() 41 | ''; 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /tests/test-instrumentation.nix: -------------------------------------------------------------------------------- 1 | { pkgs, ... }: 2 | 3 | { 4 | environment.etc = { 5 | "service/backdoor/run".source = pkgs.writeScript "backdoor_run" '' 6 | #!/bin/sh 7 | export USER=root 8 | export HOME=/root 9 | export DISPLAY=:0.0 10 | 11 | source /etc/profile 12 | 13 | # Don't use a pager when executing backdoor 14 | # actions. Because we use a tty, commands like systemctl 15 | # or nix-store get confused into thinking they're running 16 | # interactively. 17 | export PAGER= 18 | 19 | cd /tmp 20 | exec < /dev/hvc0 > /dev/hvc0 21 | while ! exec 2> /dev/ttyS0; do sleep 0.1; done 22 | echo "connecting to host..." >&2 23 | stty -F /dev/hvc0 raw -echo # prevent nl -> cr/nl conversion 24 | echo 25 | PS1= exec /bin/sh 26 | ''; 27 | }; 28 | boot.initrd.availableKernelModules = [ "virtio_console" ]; 29 | boot.kernelParams = [ "panic=-1" ]; 30 | } 31 | -------------------------------------------------------------------------------- /zynq_image.nix: -------------------------------------------------------------------------------- 1 | { config, pkgs, ... }: 2 | 3 | let 4 | # dont use overlays for the qemu, it causes a lot of wasted time on recompiles 5 | x86pkgs = import pkgs.path { system = "x86_64-linux"; }; 6 | customKernel = pkgs.linux.override { 7 | extraConfig = '' 8 | OVERLAY_FS y 9 | ''; 10 | }; 11 | customKernelPackages = pkgs.linuxPackagesFor customKernel; 12 | in { 13 | imports = [ ./arm32-cross-fixes.nix ]; 14 | boot.kernelPackages = customKernelPackages; 15 | nixpkgs.system = "armv7l-linux"; 16 | system.build.zynq_image = let 17 | cmdline = "root=/dev/mmcblk0 console=ttyPS0,115200n8 systemConfig=${builtins.unsafeDiscardStringContext config.system.build.toplevel}"; 18 | qemuScript = '' 19 | #!/bin/bash -v 20 | export PATH=${x86pkgs.qemu}/bin:$PATH 21 | set -x 22 | base=$(dirname $0) 23 | 24 | cp $base/root.squashfs /tmp/ 25 | chmod +w /tmp/root.squashfs 26 | truncate -s 64m /tmp/root.squashfs 27 | 28 | qemu-system-arm \ 29 | -M xilinx-zynq-a9 \ 30 | -serial /dev/null \ 31 | -serial stdio \ 32 | -display none \ 33 | -dtb $base/zynq-zc702.dtb \ 34 | -kernel $base/zImage \ 35 | -initrd $base/initrd \ 36 | -drive file=/tmp/root.squashfs,if=sd,format=raw \ 37 | -append "${cmdline}" 38 | ''; 39 | in pkgs.runCommand "zynq_image" { 40 | inherit qemuScript; 41 | passAsFile = [ "qemuScript" ]; 42 | preferLocalBuild = true; 43 | } '' 44 | mkdir $out 45 | cd $out 46 | cp -s ${config.system.build.squashfs} root.squashfs 47 | cp -s ${config.system.build.kernel}/*zImage . 48 | cp -s ${config.system.build.initialRamdisk}/initrd initrd 49 | cp -s ${config.system.build.kernel}/dtbs/zynq-zc702.dtb . 50 | ln -sv ${config.system.build.toplevel} toplevel 51 | cp $qemuScriptPath qemu-script 52 | chmod +x qemu-script 53 | patchShebangs qemu-script 54 | ls -ltrh 55 | ''; 56 | system.build.rpi_image_tar = pkgs.runCommand "dist.tar" {} '' 57 | mkdir -p $out/nix-support 58 | tar -cvf $out/dist.tar ${config.system.build.rpi_image} 59 | echo "file binary-dist $out/dist.tar" >> $out/nix-support/hydra-build-products 60 | ''; 61 | environment.systemPackages = [ pkgs.strace ]; 62 | environment.etc."service/getty/run".source = pkgs.writeShellScript "getty" '' 63 | agetty ttyPS0 115200 64 | ''; 65 | environment.etc."pam.d/other".text = ""; 66 | } 67 | --------------------------------------------------------------------------------