diff --git a/base.nix b/base.nix index 6f5d5f5..8ef3890 100644 --- a/base.nix +++ b/base.nix @@ -23,21 +23,69 @@ with lib; ignoreCollisions = true; }; }; + not-os.nix = mkOption { + type = types.bool; + description = "enable nix-daemon and a writeable store"; + }; }; config = { + environment.systemPackages = lib.optional config.not-os.nix pkgs.nix; nixpkgs.config = { packageOverrides = self: { utillinux = self.utillinux.override { systemd = null; }; toxvpn = self.toxvpn.override { systemd = null; }; + linux_rpixxx = self.linux_rpi.override { + extraConfig = '' + DEBUG_LL y + EARLY_PRINTK y + DEBUG_BCM2708_UART0 y + ARM_APPENDED_DTB n + ARM_ATAG_DTB_COMPAT n + ARCH_BCM2709 y + BCM2708_GPIO y + BCM2708_NOL2CACHE y + BCM2708_SPIDEV y + ''; + }; }; }; environment.etc = { + "nix/nix.conf".source = pkgs.runCommand "nix.conf" {} '' + extraPaths=$(for i in $(cat ${pkgs.writeReferencesToFile pkgs.stdenv.shell}); do if test -d $i; then echo $i; fi; done) + cat > $out << EOF + build-use-sandbox = true + build-users-group = nixbld + build-sandbox-paths = /bin/sh=${pkgs.stdenv.shell} $(echo $extraPaths) + build-max-jobs = 1 + build-cores = 4 + EOF + ''; + bashrc.text = "export PATH=/run/current-system/sw/bin"; profile.text = "export PATH=/run/current-system/sw/bin"; "resolv.conf".text = "nameserver 10.0.2.3"; passwd.text = '' root:x:0:0:System administrator:/root:/run/current-system/sw/bin/bash sshd:x:498:65534:SSH privilege separation user:/var/empty:/run/current-system/sw/bin/nologin toxvpn:x:1010:65534::/var/lib/toxvpn:/run/current-system/sw/bin/nologin + nixbld1:x:30001:30000:Nix build user 1:/var/empty:/run/current-system/sw/bin/nologin + nixbld2:x:30002:30000:Nix build user 2:/var/empty:/run/current-system/sw/bin/nologin + nixbld3:x:30003:30000:Nix build user 3:/var/empty:/run/current-system/sw/bin/nologin + nixbld4:x:30004:30000:Nix build user 4:/var/empty:/run/current-system/sw/bin/nologin + nixbld5:x:30005:30000:Nix build user 5:/var/empty:/run/current-system/sw/bin/nologin + nixbld6:x:30006:30000:Nix build user 6:/var/empty:/run/current-system/sw/bin/nologin + nixbld7:x:30007:30000:Nix build user 7:/var/empty:/run/current-system/sw/bin/nologin + nixbld8:x:30008:30000:Nix build user 8:/var/empty:/run/current-system/sw/bin/nologin + nixbld9:x:30009:30000:Nix build user 9:/var/empty:/run/current-system/sw/bin/nologin + nixbld10:x:30010:30000:Nix build user 10:/var/empty:/run/current-system/sw/bin/nologin + ''; + "nsswitch.conf".text = '' + hosts: files dns myhostname mymachines + networks: files dns + ''; + "services".source = pkgs.iana_etc + "/etc/services"; + group.text = '' + root:x:0: + nixbld:x:30000:nixbld1,nixbld10,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9 ''; "ssh/ssh_host_rsa_key.pub".source = ./ssh/ssh_host_rsa_key.pub; "ssh/ssh_host_rsa_key" = { mode = "0600"; source = ./ssh/ssh_host_rsa_key; }; @@ -45,7 +93,7 @@ with lib; "ssh/ssh_host_ed25519_key" = { mode = "0600"; source = ./ssh/ssh_host_ed25519_key; }; }; boot.kernelParams = [ "systemConfig=${config.system.build.toplevel}" ]; - boot.kernelPackages = if pkgs.system == "armv6l-linux" then pkgs.linuxPackages_rpi else pkgs.linuxPackages; + boot.kernelPackages = if pkgs.system == "armv7l-linux" then pkgs.linuxPackages_rpi else pkgs.linuxPackages; system.build.earlyMountScript = pkgs.writeScript "dummy" '' ''; system.build.runvm = pkgs.writeScript "runner" '' diff --git a/configuration.nix b/configuration.nix index 0a5a628..4205c50 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,6 +1,8 @@ { pkgs, ... }: { + not-os.nix = true; + environment.systemPackages = [ pkgs.utillinux ]; environment.etc = { "service/toxvpn/run".source = pkgs.writeScript "toxvpn_run" '' #!/bin/sh @@ -12,6 +14,7 @@ "ssh/authorized_keys.d/root" = { text = '' ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC34wZQFEOGkA5b0Z6maE3aKy/ix1MiK1D0Qmg4E9skAA57yKtWYzjA23r5OCF4Nhlj1CuYd6P1sEI/fMnxf+KkqqgW3ZoZ0+pQu4Bd8Ymi3OkkQX9kiq2coD3AFI6JytC6uBi6FaZQT5fG59DbXhxO5YpZlym8ps1obyCBX0hyKntD18RgHNaNM+jkQOhQ5OoxKsBEobxQOEdjIowl2QeEHb99n45sFr53NFqk3UCz0Y7ZMf1hSFQPuuEC/wExzBBJ1Wl7E1LlNA4p9O3qJUSadGZS4e5nSLqMnbQWv2icQS/7J8IwY0M8r1MsL8mdnlXHUofPlG1r4mtovQ2myzOx clever@nixos + ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKITUnIETct0d1Ky7iEofM8BV/U9ViuAd72abm26ibhkVKYuLlIvNBtf7+fsyaHR3cc4kmiUz26co4LV2q10HLO7nua7Ry0QhtPvPnpudandB4LbV4ieW1cqcWcPpsM1GssUZhZthbkwLf7h2exojqVj8vqPm5RaBl1eULXaPTldCiSe5ZxNuVbm3qT8Lfc2E3ifKT6A7WqZN00f1+YSnaA9uy0VgVDReDqyujAZaKGUwSa2G8eqzN3guN7VcBZek2p1v1n0EwpFdBxzT3Ncqh5wIYPNn084q5lU13TAjw+tTO7Q059e4HFLaR24w8NT60BrO1dbGYLbjWNri1G3pz root@router ''; mode = "0444"; }; diff --git a/default.nix b/default.nix index 163675f..32c6fe1 100644 --- a/default.nix +++ b/default.nix @@ -1,12 +1,13 @@ -{ configuration ? import ./configuration.nix, nixpkgs ? , extraModules ? [], system ? builtins.currentSystem }: +{ configuration ? import ./configuration.nix, nixpkgs ? , extraModules ? [], system ? builtins.currentSystem, platform ? null }: let - pkgs = import nixpkgs { inherit system; config = {}; }; + pkgs = import nixpkgs { inherit system; platform = platform; config = {}; }; pkgsModule = rec { _file = ./default.nix; key = _file; config = { nixpkgs.system = pkgs.lib.mkDefault system; + nixpkgs.config.platform = platform; }; }; baseModules = [ @@ -22,7 +23,6 @@ let - ./ipxe.nix ./systemd-compat.nix pkgsModule diff --git a/linux-rpi.nix b/linux-rpi.nix new file mode 100644 index 0000000..0165a60 --- /dev/null +++ b/linux-rpi.nix @@ -0,0 +1,50 @@ +{ stdenv, fetchFromGitHub, perl, buildLinux, ... } @ args: + +let + modDirVersion = "4.4.36"; + tag = "1.20161020-1"; +in +stdenv.lib.overrideDerivation (import (args // rec { + version = "${modDirVersion}-${tag}"; + inherit modDirVersion; + + src = fetchFromGitHub { + owner = "raspberrypi"; + repo = "linux"; + rev = "c6d86f7aa554854b04614ebb4d394766081fb41f"; + sha256 = "13rjmks4whh7kn0wrswanwq3b0ia9bxsq8a6xiqiivh6k3vxqhys"; + }; + + features.iwlwifi = true; + features.needsCifsUtils = true; + features.canDisableNetfilterConntrackHelpers = true; + features.netfilterRPFilter = true; + + extraMeta.hydraPlatforms = []; +})) (oldAttrs: { + postConfigure = '' + # The v7 defconfig has this set to '-v7' which screws up our modDirVersion. + sed -i $buildRoot/.config -e 's/^CONFIG_LOCALVERSION=.*/CONFIG_LOCALVERSION=""/' + ''; + + postFixup = '' + # Make copies of the DTBs so that U-Boot finds them, as it is looking for the upstream names. + # This is ugly as heck. + copyDTB() { + if [ -f "$out/dtbs/$1" ]; then + cp -v "$out/dtbs/$1" "$out/dtbs/$2" + fi + } + + # I am not sure if all of these are correct... + copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-a.dtb + copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b.dtb + copyDTB bcm2708-rpi-b.dtb bcm2835-rpi-b-rev2.dtb + copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-a-plus.dtb + copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-b-plus.dtb + copyDTB bcm2708-rpi-b-plus.dtb bcm2835-rpi-zero.dtb + copyDTB bcm2708-rpi-cm.dtb bcm2835-rpi-cm.dtb + copyDTB bcm2709-rpi-2-b.dtb bcm2836-rpi-2-b.dtb + copyDTB bcm2710-rpi-3-b.dtb bcm2837-rpi-3-b.dtb + ''; +}) diff --git a/nix.nix b/nix.nix new file mode 100644 index 0000000..04618ac --- /dev/null +++ b/nix.nix @@ -0,0 +1,4 @@ +{ ... }: + +{ +} diff --git a/qemu.nix b/qemu.nix new file mode 100644 index 0000000..9f38ff5 --- /dev/null +++ b/qemu.nix @@ -0,0 +1,5 @@ +{ ... }: + +{ + boot.initrd.kernelModules = [ "virtio" "virtio_pci" "virtio_net" "virtio_rng" "virtio_blk" "virtio_console" ]; +} diff --git a/release.nix b/release.nix index 6443525..21fd5fb 100644 --- a/release.nix +++ b/release.nix @@ -22,8 +22,10 @@ let # system instead of generating attributes for all available systems. in if args ? system then discover (import fn args) else foldAttrs mergeAttrs {} (map discoverForSystem supportedSystems); + platforms = import ; + platformForSystem = system: if system == "armv7l-linux" then platforms.raspberrypi2 else null; fetchClosure = f: forAllSystems (system: f (import ./default.nix { inherit system; }).config ); - fetchClosure2 = f: forAllSystems2 (system: f (import ./default.nix { inherit system; }).config ); + fetchClosure2 = f: forAllSystems2 (system: f (import ./default.nix { inherit system; platform = platformForSystem system; }).config ); in { tests.boot = callSubTests tests/boot.nix {}; @@ -32,12 +34,19 @@ in initialRamdisk = fetchClosure2 (cfg: cfg.system.build.initialRamdisk); squashed = fetchClosure2 (cfg: cfg.system.build.squashfs); }; - dist_test = fetchClosure2 (cfg: pkgs.runCommand "dist" { inherit (cfg.system.build) dist; }'' + dist_test = fetchClosure2 (cfg: pkgs.runCommand "dist" { inherit (cfg.system.build) dist kernel; config = cfg.system.build.kernel.configfile; }'' #!/bin/sh mkdir -p $out/nix-support echo file kernel ''${dist}/kernel > $out/nix-support/hydra-build-products echo file rootfs ''${dist}/root.squashfs >> $out/nix-support/hydra-build-products echo file initrd ''${dist}/initrd >> $out/nix-support/hydra-build-products echo file command-line ''${dist}/command-line >> $out/nix-support/hydra-build-products + cd $out + ln -sv ''${dist}/initrd + ln -sv ''${dist}/kernel + ln -sv ''${dist}/root.squashfs + ln -sv ''${config} config + for x in $kernel/dtbs/*;do ln -sv $x $out/;done ''); + rpi_image = (import ./default.nix { extraModules = [ ./rpi_image.nix ]; platform = system: platforms.raspberrypi2; }).config.system.build.rpi_image; } diff --git a/rpi_image.nix b/rpi_image.nix new file mode 100644 index 0000000..de8873a --- /dev/null +++ b/rpi_image.nix @@ -0,0 +1,32 @@ +{ config, pkgs, ... }: + +{ + nixpkgs.system = "armv7l-linux"; + system.build.rpi_image = let + config_txt = pkgs.writeText "config.txt" '' + initramfs initrd followkernel + dtoverlay=pi3-disable-bt + enable_uart=1 + ''; + cmdline = pkgs.writeText "cmdline.txt" '' + 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 + ''; + in pkgs.runCommand "rpi_image" {} '' + mkdir $out + cd $out + cp ${config_txt} config.txt + cp ${cmdline} cmdline.txt + cp -s ${config.system.build.kernel}/*zImage kernel7.img + cp -s ${config.system.build.squashfs} root.squashfs + cp ${./../bcm2710-rpi-3-b.dtb} bcm2710-rpi-3-b.dtb + cp -r ${./../../overlays} overlays + cp -s ${../../start.elf} start.elf + cp ${../../fixup.dat} fixup.dat + cp -s ${config.system.build.initialRamdisk}/initrd initrd + ls -ltrhL + ''; + environment.systemPackages = [ pkgs.strace ]; + nixpkgs.config.packageOverrides = pkgs: { + linux_rpi = pkgs.callPackage ./linux-rpi.nix {}; + }; +} diff --git a/runit.nix b/runit.nix index e8c6a5e..d4319f4 100644 --- a/runit.nix +++ b/runit.nix @@ -29,14 +29,20 @@ in environment.etc = { "runit/1".source = pkgs.writeScript "1" '' #!${pkgs.stdenv.shell} - ip addr add 10.0.2.15 dev eth0 - ip link set eth0 up - ip route add 10.0.2.0/24 dev eth0 - ip route add default via 10.0.2.2 dev eth0 + # ip addr add 10.0.2.15 dev eth0 + # ip link set eth0 up + # ip route add 10.0.2.0/24 dev eth0 + # ip route add default via 10.0.2.2 dev eth0 mkdir /bin/ ln -s ${pkgs.stdenv.shell} /bin/sh + ${pkgs.ntp}/bin/ntpdate 192.168.2.1 + + # disable DPMS on tty's + echo -ne "\033[9;0]" > /dev/tty0 + touch /etc/runit/stopit chmod 0 /etc/runit/stopit + # ${pkgs.dhcpcd.override { udev = null; }}/sbin/dhcpcd ''; "runit/2".source = pkgs.writeScript "2" '' #!/bin/sh @@ -56,5 +62,10 @@ in export PATH=$PATH:${pkgs.rng_tools}/bin exec rngd -r /dev/hwrng ''; + "service/nix/run".source = pkgs.writeScript "nix" '' + #!/bin/sh + nix-store --load-db < /nix/store/nix-path-registration + nix-daemon + ''; }; } diff --git a/stage-1.nix b/stage-1.nix index d62ecca..42ce10d 100644 --- a/stage-1.nix +++ b/stage-1.nix @@ -1,34 +1,124 @@ -{ pkgs, config, ... }: +{ lib, pkgs, config, ... }: let modules = pkgs.makeModulesClosure { rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules; allowMissing = true; kernel = config.system.build.kernel; }; + plymouth = (pkgs.plymouth.override { + udev = null; + gtk3 = null; + systemd = null; + }).overrideDerivation (old: { + #src = /tmp/plymouth; + src = pkgs.fetchgit { + url = "https://anongit.freedesktop.org/git/plymouth"; + rev = "266d954b7a0ff5b046df6ed54c22e3322b2c80d0"; + sha256 = "10k7vfbfp3q1ysw3w5nd6wnixizbng3lqbb21bgd18v997k74xb3"; + }; + #patches2 = [ ./fix2.patch ./udev3.patch ]; + }); + dhcpcd = pkgs.dhcpcd.override { udev = null; }; + extraUtils = pkgs.runCommandCC "extra-utils" + { + buildInputs = [ pkgs.nukeReferences ]; + allowedReferences = [ "out" ]; + } '' + set +o pipefail + mkdir -p $out/bin $out/lib + ln -s $out/bin $out/sbin + + copy_bin_and_libs() { + [ -f "$out/bin/$(basename $1)" ] && rm "$out/bin/$(basename $1)" + cp -pd $1 $out/bin + } + + # Copy Busybox + for BIN in ${pkgs.busybox}/{s,}bin/*; do + copy_bin_and_libs $BIN + done + + copy_bin_and_libs ${pkgs.dhcpcd}/bin/dhcpcd + + # Copy ld manually since it isn't detected correctly + cp -pv ${pkgs.glibc.out}/lib/ld*.so.? $out/lib + + # Copy all of the needed libraries + find $out/bin $out/lib -type f | while read BIN; do + echo "Copying libs for executable $BIN" + LDD="$(ldd $BIN)" || continue + LIBS="$(echo "$LDD" | awk '{print $3}' | sed '/^$/d')" + for LIB in $LIBS; do + TGT="$out/lib/$(basename $LIB)" + if [ ! -f "$TGT" ]; then + SRC="$(readlink -e $LIB)" + cp -pdv "$SRC" "$TGT" + fi + done + done + + # Strip binaries further than normal. + chmod -R u+w $out + stripDirs "lib bin" "-s" + + # Run patchelf to make the programs refer to the copied libraries. + find $out/bin $out/lib -type f | while read i; do + if ! test -L $i; then + nuke-refs -e $out $i + fi + done + + find $out/bin -type f | while read i; do + if ! test -L $i; then + echo "patching $i..." + patchelf --set-interpreter $out/lib/ld*.so.? --set-rpath $out/lib $i || true + fi + done + + # Make sure that the patchelf'ed binaries still work. + echo "testing patched programs..." + $out/bin/ash -c 'echo hello world' | grep "hello world" + export LD_LIBRARY_PATH=$out/lib + $out/bin/mount --help 2>&1 | grep -q "BusyBox" + ''; + shell = "${extraUtils}/bin/ash"; + enablePlymouth = false; + dhcpHook = pkgs.writeScript "dhcpHook" '' + #!${shell} + ''; bootStage1 = pkgs.writeScript "stage1" '' - #!${pkgs.stdenv.shell} + #!${shell} echo echo "<<< NotOS Stage 1 >>>" echo - export PATH=${pkgs.busybox}/bin/ - mkdir -p /proc /sys /dev /etc/udev /tmp /run/ /lib/ /mnt/ + export PATH=${extraUtils}/bin/${lib.optionalString enablePlymouth ":${plymouth}/bin/"} + mkdir -p /proc /sys /dev /etc/udev /tmp /run/ /lib/ /mnt/ /var/log /etc/plymouth /bin mount -t devtmpfs devtmpfs /dev/ mount -t proc proc /proc + mount -t sysfs sysfs /sys + ${lib.optionalString enablePlymouth '' + ln -sv ${plymouth}/lib/plymouth /etc/plymouth/plugins + ln -sv ${plymouth}/etc/plymouth/plymouthd.conf /etc/plymouth/plymouthd.conf + ln -sv ${plymouth}/share/plymouth/plymouthd.defaults /etc/plymouth//plymouthd.defaults + ln -sv ${plymouth}/share/plymouth/themes /etc/plymouth/themes + ln -sv /dev/fb0 /dev/fb + ''} + ln -sv ${shell} /bin/sh ln -s ${modules}/lib/modules /lib/modules - modprobe virtio - modprobe virtio_pci - modprobe virtio_net - modprobe virtio_rng + ${lib.optionalString enablePlymouth '' + # gdb --args plymouthd --debug --mode=boot --no-daemon + sleep 1 + plymouth --show-splash + ''} + + + for x in ${lib.concatStringsSep " " config.boot.initrd.kernelModules}; do + modprobe $x + done - modprobe virtio_blk - modprobe virtio_console - modprobe squashfs - modprobe tun - modprobe loop - root=/dev/vda for o in $(cat /proc/cmdline); do case $o in @@ -40,16 +130,47 @@ let set -- $(IFS==; echo $o) root=$2 ;; + netroot=*) + set -- $(IFS==; echo $o) + mkdir -pv /var/run /var/db + ${lib.optionalString enablePlymouth ''plymouth display-message --text="waiting for eth"''} + sleep 5 + ${lib.optionalString enablePlymouth ''plymouth display-message --text="dhcp query"''} + dhcpcd eth0 -c ${dhcpHook} + ${lib.optionalString enablePlymouth ''plymouth display-message --text="downloading rootfs"''} + tftp -g -r "$3" "$2" + root=/root.squashfs + ;; esac done - mount -t tmpfs root /mnt/ + + ${lib.optionalString enablePlymouth ''plymouth display-message --text="mounting things"''} + + mount -t tmpfs root /mnt/ -o size=1G || exec ${shell} chmod 755 /mnt/ mkdir -p /mnt/nix/store/ + + ${if config.not-os.nix then '' + # make the store writeable + mkdir -p /mnt/nix/.ro-store /mnt/nix/.overlay-store /mnt/nix/store + mount $root /mnt/nix/.ro-store -t squashfs + mount tmpfs -t tmpfs /mnt/nix/.overlay-store -o size=1G + mkdir -pv /mnt/nix/.overlay-store/work /mnt/nix/.overlay-store/rw + modprobe overlay + 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 + '' else '' + # readonly store mount $root /mnt/nix/store/ -t squashfs + ''} + + ${lib.optionalString enablePlymouth '' + plymouth --newroot=/mnt + plymouth update-root-fs --new-root-dir=/mnt --read-write + ''} exec env -i $(type -P switch_root) /mnt/ $sysconfig/init - exec ${pkgs.stdenv.shell} + exec ${shell} ''; initialRamdisk = pkgs.makeInitrd { contents = [ { object = bootStage1; symlink = "/init"; } ]; @@ -59,6 +180,8 @@ in config = { system.build.bootStage1 = bootStage1; system.build.initialRamdisk = initialRamdisk; - boot.initrd.availableKernelModules = [ "squashfs" "virtio" "virtio_pci" "virtio_blk" "virtio_net" "tun" "virtio-rng" "loop" ]; + system.build.extraUtils = extraUtils; + boot.initrd.availableKernelModules = [ ]; + boot.initrd.kernelModules = [ "tun" "loop" "squashfs" ] ++ (lib.optional config.not-os.nix "overlay"); }; }