From 0dfda7560fe6c86cf1108f1751af5f1d337caf09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Sj=C3=B6strom?= Date: Thu, 20 Feb 2025 10:40:53 +0100 Subject: [PATCH] chore: add dbus-broker --- dbus-broker/default.nix | 165 ++++++++++++++++++++++++++++++++++++++ flake.nix | 153 +++--------------------------------- glibc/default.nix | 16 ++-- utils/mkinitrd.nix | 170 ++++++++++++++++++++++++++++++++++++++++ utils/qemu-uefi-tpm.nix | 50 ++++++++++++ 5 files changed, 401 insertions(+), 153 deletions(-) create mode 100644 dbus-broker/default.nix create mode 100644 utils/mkinitrd.nix create mode 100644 utils/qemu-uefi-tpm.nix diff --git a/dbus-broker/default.nix b/dbus-broker/default.nix new file mode 100644 index 0000000..cad66af --- /dev/null +++ b/dbus-broker/default.nix @@ -0,0 +1,165 @@ +{ + lib, + stdenv, + fetchFromGitHub, + pkgs, + ... +}: + +let + meta = { + maintainers = with lib.maintainers; [ peterhoeg ]; + platforms = lib.platforms.linux; + }; + + dep = + { + pname, + version, + hash, + rev ? "v${version}", + buildInputs ? [ ], + }: + stdenv.mkDerivation { + inherit pname version; + src = fetchFromGitHub { + owner = "c-util"; + repo = pname; + inherit hash rev; + }; + nativeBuildInputs = with pkgs; [ + meson + ninja + pkg-config + ]; + inherit buildInputs; + meta = meta // { + description = "The C-Util Project is a collection of utility libraries for the C11 language."; + homepage = "https://c-util.github.io/"; + license = [ + lib.licenses.asl20 + lib.licenses.lgpl21Plus + ]; + }; + }; + + # These libraries are not used outside of dbus-broker. + # + # If that changes, we can always break them out, but they are essentially + # part of the dbus-broker project, just in separate repositories. + c-dvar = dep { + pname = "c-dvar"; + version = "1.1.0"; + hash = "sha256-p/C+BktclVseCtZJ1Q/YK03vP2ClnYRLB1Vmj2OQJD4="; + buildInputs = [ + c-stdaux + c-utf8 + ]; + }; + c-ini = dep { + pname = "c-ini"; + version = "1.1.0"; + hash = "sha256-wa7aNl20hkb/83c4AkQ/0YFDdmBs4XGW+WLUtBWIC98="; + buildInputs = [ + c-list + c-rbtree + c-stdaux + c-utf8 + ]; + }; + c-list = dep { + pname = "c-list"; + version = "3.1.0"; + hash = "sha256-fp3EAqcbFCLaT2EstLSzwP2X13pi2EFpFAullhoCtpw="; + }; + c-rbtree = dep { + pname = "c-rbtree"; + version = "3.2.0"; + hash = "sha256-dTMeawhPLRtHvMXfXCrT5iCdoh7qS3v+raC6c+t+X38="; + buildInputs = [ c-stdaux ]; + }; + c-shquote = dep { + pname = "c-shquote"; + version = "1.1.0"; + hash = "sha256-z6hpQ/kpCYAngMNfxLkfsxaGtvP4yBMigX1lGpIIzMQ="; + buildInputs = [ c-stdaux ]; + }; + c-stdaux = dep { + pname = "c-stdaux"; + version = "1.5.0"; + hash = "sha256-MsnuEyVCmOIr/q6I1qyPsNXp48jxIEcXoYLHbOAZtW0="; + }; + c-utf8 = dep { + pname = "c-utf8"; + version = "1.1.0"; + hash = "sha256-9vBYylbt1ypJwIAQJd/oiAueh+4VYcn/KzofQuhUea0="; + buildInputs = [ c-stdaux ]; + }; + +in + +stdenv.mkDerivation (finalAttrs: { + pname = "dbus-broker"; + version = "36"; + + src = fetchFromGitHub { + owner = "bus1"; + repo = "dbus-broker"; + rev = "v${finalAttrs.version}"; + hash = "sha256-5dAMKjybqrHG57vArbtWEPR/svSj2ION75JrjvnnpVM="; + }; + + nativeBuildInputs = with pkgs; [ + docutils + meson + ninja + pkg-config + ]; + + buildInputs = [ + c-dvar + c-ini + c-list + c-rbtree + c-shquote + c-stdaux + c-utf8 + pkgs.dbus + pkgs.linuxHeaders + pkgs.systemd + ]; + + mesonFlags = [ + # while we technically support 4.9 and 4.14, the NixOS module will throw an + # error when using a kernel that's too old + "--prefix=/" + "--bindir=/usr/bin" + "-D=linux-4-17=true" + "-D=system-console-users=gdm,sddm,lightdm" + ]; + + PKG_CONFIG_SYSTEMD_SYSTEMDSYSTEMUNITDIR = "/usr/lib/systemd/system"; + PKG_CONFIG_SYSTEMD_SYSTEMDUSERUNITDIR = "/usr/lib/systemd/user"; + PKG_CONFIG_SYSTEMD_CATALOGDIR = "/usr/lib/systemd/catalog"; + + preInstall = '' + export DESTDIR=${placeholder "out"} + ''; + + postInstall = '' + mkdir -p $out/usr/share + cp -Pr ${pkgs.dbus.out}/share/* $out/usr/share/ + cp ${pkgs.dbus.out}/etc/systemd/system/dbus.socket $out/usr/lib/systemd/system/ + find $out/usr/share/ -type d -exec chmod 755 {} \; + sed -i 's#/nix/store.*/share#/usr/share#' $out/usr/share/xml/dbus-1/catalog.xml + sed -i 's#/nix/store.*/libexec#/usr/bin#' $out/usr/share/dbus-1/system.conf + ''; + + doCheck = false; + + meta = meta // { + description = "Linux D-Bus Message Broker"; + homepage = "https://github.com/bus1/dbus-broker/wiki"; + license = lib.licenses.asl20; + }; +}) diff --git a/flake.nix b/flake.nix index 866ed43..221d203 100644 --- a/flake.nix +++ b/flake.nix @@ -16,165 +16,30 @@ system: let pkgs = import nixpkgs { inherit system; }; + patosPkgs = self.packages.${system}; in { packages = { default = self.packages.${system}.image; image = pkgs.writeShellScriptBin "image" '' + set -ex echo "make UKI..." - echo ${self.packages.${system}.kernel.kernel}/bzImage + + mkdir -p patos/efi/boot ${self.packages.${system}.systemd.out}/usr/bin/ukify build \ --linux ${self.packages.${system}.kernel.kernel}/bzImage \ --initrd ./initrd.gz \ --cmdline "console=ttyS0" \ - -o patos.efi + -o patos/efi/boot/bootx64.efi ''; kernel = pkgs.callPackage ./kernel { }; glibc = pkgs.callPackage ./glibc { }; systemd = pkgs.callPackage ./systemd { }; + dbus-broker = pkgs.callPackage ./dbus-broker { }; - mkinitrd = pkgs.writeShellScriptBin "mkinitrd" '' - echo "make initrd..." - mkdir -p out - - # copy systemd - cp -Pr ${self.packages.${system}.systemd.out}/* out/ - pushd out - - find . -type d -exec chmod 755 {} \; - - # Copy kernel modules - cp -Pr ${self.packages.${system}.kernel.kernel}/lib/modules ./usr/lib/ - find usr/lib/modules -type d -exec chmod 755 {} \; - - mkdir -p dev proc sys tmp root - ln -sf usr/bin bin - ln -sf usr/bin sbin - ln -sf usr/lib lib - ln -sf usr/lib lib64 - - ln -sf ../proc/self/mounts etc/mtab - ln -sf ../usr/lib/systemd/systemd init - - echo patos > ./etc/hostname - cat < ./etc/os-release - NAME="PatOS" - PRETTY_NAME="PatOS Platform" - ID=patos - EOF - - cat < ./etc/passwd - root::0:0:root:/root:/bin/sh - bin:x:1:1:bin:/bin:/usr/bin/nologin - daemon:x:2:2:daemon:/:/usr/bin/nologin - mail:x:8:12:mail:/var/spool/mail:/usr/bin/nologin - ftp:x:14:11:ftp:/srv/ftp:/usr/bin/nologin - http:x:33:33:http:/srv/http:/usr/bin/nologin - uuidd:x:68:68:uuidd:/:/usr/bin/nologin - dbus:x:81:81:dbus:/:/usr/bin/nologin - nobody:x:99:99:nobody:/:/usr/bin/nologin - EOF - chmod 644 ./etc/passwd - - cat < ./etc/group - root:x:0:root - bin:x:1:root,bin,daemon - daemon:x:2:root,bin,daemon - sys:x:3:root,bin - adm:x:4:root,daemon - tty:x:5: - disk:x:6:root - lp:x:7:daemon - mem:x:8: - kmem:x:9: - wheel:x:10:root - ftp:x:11: - mail:x:12: - uucp:x:14: - log:x:19:root - utmp:x:20: - locate:x:21: - rfkill:x:24: - smmsp:x:25: - proc:x:26: - http:x:33: - games:x:50: - lock:x:54: - uuidd:x:68: - dbus:x:81: - network:x:90: - video:x:91: - audio:x:92: - optical:x:93: - floppy:x:94: - storage:x:95: - scanner:x:96: - input:x:97: - power:x:98: - nobody:x:99: - EOF - chmod 644 ./etc/group - - # FIXME: remove this - cat < usr/lib/systemd/system/demo.service - [Unit] - Description=Debug Shell (/bin/sulogin) - Conflicts=shutdown.target - Before=shutdown.target - - [Service] - Environment=HOME=/root - WorkingDirectory=/root - ExecStart=/bin/sulogin - Type=idle - StandardInput=tty-force - StandardOutput=inherit - StandardError=inherit - KillMode=process - IgnoreSIGPIPE=no - SendSIGHUP=yes - Restart=always - - [Install] - WantedBy=basic.target - EOF - mkdir usr/lib/systemd/system/basic.target.wants - ln -sf ../demo.service usr/lib/systemd/system/basic.target.wants/demo.service - - # set default target - ln -sf basic.target usr/lib/systemd/system/default.target - # remove first boot - rm -f usr/lib/systemd/system/sysinit.target.wants/systemd-firstboot.service - # remove vconsole setup - rm -f usr/lib/udev/rules.d/90-vconsole.rules - - # install busybox - cp ${pkgs.busybox.out}/bin/busybox usr/bin/ - usr/bin/busybox --list | xargs -I {} ln -sf busybox usr/bin/{} - - # install lib kmod - cp -P ${pkgs.kmod.lib}/lib/* ./usr/lib - cp -P ${pkgs.kmod.out}/bin/* ./usr/bin - cp -P ${pkgs.libbpf.out}/lib/libbpf* ./usr/lib - - # get shared libs - find . -type f -executable | xargs ldd 2> /dev/null | awk '{print $3}' | grep -v systemd | sort -u | xargs cp -t usr/lib - find . -type f -executable | xargs chmod 755 - - # FIXME: hacky(?) ELF patching. Is there a better way???????? - find . -type f -executable -print | xargs -I {} ${pkgs.lib.getExe pkgs.patchelf} --set-rpath /lib:/usr/lib:/usr/lib/systemd {} 2> /dev/null - find . -type f -executable -print | xargs -I {} ${pkgs.lib.getExe pkgs.patchelf} --set-interpreter /lib/ld-linux-x86-64.so.2 {} 2> /dev/null - cp ${ - self.packages.${system}.glibc.out - }/lib/ld-linux-x86-64.so.2 lib/ && ${pkgs.lib.getExe pkgs.patchelf} --remove-rpath lib/ld-linux-x86-64.so.2 - - # strip binaries - find . -type f -executable | xargs strip 2> /dev/null - - # gen initrd - find . -print0 | ${pkgs.lib.getExe pkgs.cpio} --null --owner=root:root -o --format=newc | ${pkgs.lib.getExe pkgs.gzip} -9 > ../initrd.gz - ''; + mkinitrd = pkgs.callPackage ./utils/mkinitrd.nix { inherit patosPkgs; }; + qemu-uefi-tpm = pkgs.callPackage ./utils/qemu-uefi-tpm.nix { }; }; checks = { @@ -193,6 +58,8 @@ nixd nixfmt-rfc-style squashfs-tools-ng + self.packages.${system}.qemu-uefi-tpm + self.packages.${system}.mkinitrd ]; }; diff --git a/glibc/default.nix b/glibc/default.nix index 65bebc3..b5028c0 100644 --- a/glibc/default.nix +++ b/glibc/default.nix @@ -1,25 +1,21 @@ { - fetchurl, pkgs, stdenv, ... }: let - version = "2.40"; - pname = "glibcStandalone"; + version = pkgs.glibc.version; + src = pkgs.glibc.src; + pname = "glibcPatos"; in stdenv.mkDerivation (finalAttrs: { inherit version; - - pname = pname; - - src = fetchurl { - url = "mirror://gnu/glibc/glibc-${version}.tar.xz"; - sha256 = "sha256-GaiQF16SY9dI9ieZPeb0sa+c0h4D8IDkv7Oh+sECBaI="; - }; + inherit src; + inherit pname; enableParallelBuilding = true; + dontPatchShebangs = true; configureFlags = [ "--prefix=/" diff --git a/utils/mkinitrd.nix b/utils/mkinitrd.nix new file mode 100644 index 0000000..0bd234c --- /dev/null +++ b/utils/mkinitrd.nix @@ -0,0 +1,170 @@ +{ + pkgs, + patosPkgs, + ... +}: +pkgs.writeShellApplication { + name = "mkinitrd"; + + runtimeInputs = with pkgs; [ + patchelf + cpio + gzip + ]; + + text = '' + echo "Building initram disk" + mkdir -p root + pushd root + + ### create directories + mkdir -p etc dev proc sys tmp root + ln -sf usr/bin bin + ln -sf usr/bin sbin + ln -sf usr/lib lib + ln -sf usr/lib lib64 + ln -sf ../proc/self/mounts etc/mtab + ln -sf ../usr/lib/systemd/systemd init + + ### install systemd + cp -Pr ${patosPkgs.systemd.out}/* ./ + find . -type d -exec chmod 755 {} \; + rm -rf ./usr/include + rm -rf ./usr/sbin + # set default target to basic + mkdir usr/lib/systemd/system/basic.target.wants + ln -sf basic.target usr/lib/systemd/system/default.target + # remove first boot + rm -f usr/lib/systemd/system/sysinit.target.wants/systemd-firstboot.service + # remove vconsole setup + rm -f usr/lib/udev/rules.d/90-vconsole.rules + + ### install PatOS glibc + cp -Pr ${patosPkgs.glibc.out}/lib/*.so* ./usr/lib/ + + ### install kernel modules + cp -Pr ${patosPkgs.kernel.kernel}/lib/modules ./usr/lib/ + find usr/lib/modules -type d -exec chmod 755 {} \; + + ### install busybox + cp ${pkgs.busybox.out}/bin/busybox ./usr/bin/ + usr/bin/busybox --list | xargs -I {} ln -sf busybox usr/bin/{} + + ### install dbus broker + cp -r ${patosPkgs.dbus-broker.out}/* ./ + ln -sf ../dbus-broker.service usr/lib/systemd/system/basic.target.wants/dbus.service + ln -sf ../dbus.socket usr/lib/systemd/system/sockets.target.wants/dbus.socket + + ### install lib kmod + cp -P ${pkgs.kmod.lib}/lib/* ./usr/lib + cp -P ${pkgs.kmod.out}/bin/* ./usr/bin + + ### install libbpf + cp -P ${pkgs.libbpf.out}/lib/libbpf* ./usr/lib + + ### Find and install all shared libs + find . -type f -executable -exec ldd {} \; 2> /dev/null | awk '{print $3}' | grep -v systemd | grep -v glibc | sort -u | xargs cp -t usr/lib + find . -type f -executable -exec chmod 755 {} \; + + + ### Create needed files + echo patos > ./etc/hostname + cat < ./etc/os-release + NAME="PatOS" + PRETTY_NAME="PatOS Platform" + ID=patos + EOF + + cat < ./etc/passwd + root::0:0:root:/root:/bin/sh + bin:x:1:1:bin:/bin:/usr/bin/nologin + daemon:x:2:2:daemon:/:/usr/bin/nologin + mail:x:8:12:mail:/var/spool/mail:/usr/bin/nologin + ftp:x:14:11:ftp:/srv/ftp:/usr/bin/nologin + http:x:33:33:http:/srv/http:/usr/bin/nologin + uuidd:x:68:68:uuidd:/:/usr/bin/nologin + messagebus:x:81:81:messagebus:/:/usr/bin/nologin + nobody:x:99:99:nobody:/:/usr/bin/nologin + EOF + chmod 644 ./etc/passwd + + cat < ./etc/group + root:x:0:root + bin:x:1:root,bin,daemon + daemon:x:2:root,bin,daemon + sys:x:3:root,bin + adm:x:4:root,daemon + tty:x:5: + disk:x:6:root + lp:x:7:daemon + mem:x:8: + kmem:x:9: + wheel:x:10:root + ftp:x:11: + mail:x:12: + uucp:x:14: + log:x:19:root + utmp:x:20: + locate:x:21: + rfkill:x:24: + smmsp:x:25: + proc:x:26: + http:x:33: + games:x:50: + lock:x:54: + uuidd:x:68: + messagebus:x:81: + network:x:90: + video:x:91: + audio:x:92: + optical:x:93: + floppy:x:94: + storage:x:95: + scanner:x:96: + input:x:97: + power:x:98: + nobody:x:99: + EOF + chmod 644 ./etc/group + + # FIXME: remove this later (just to get a shell in the initramfs) + cat < usr/lib/systemd/system/demo.service + [Unit] + Description=Debug Shell (/bin/sulogin) + Conflicts=shutdown.target + Before=shutdown.target + + [Service] + Environment=HOME=/root + WorkingDirectory=/root + ExecStart=/bin/sulogin + Type=idle + StandardInput=tty-force + StandardOutput=inherit + StandardError=inherit + KillMode=process + IgnoreSIGPIPE=no + SendSIGHUP=yes + Restart=always + + [Install] + WantedBy=basic.target + EOF + ln -sf ../demo.service usr/lib/systemd/system/basic.target.wants/demo.service + + # FIXME: ELF patching. Is there a better way? + find . -type f -executable -exec patchelf --set-rpath /lib:/usr/lib:/usr/lib/systemd {} \; 2> /dev/null + find . -type f -executable -exec patchelf --set-interpreter /lib/ld-linux-x86-64.so.2 {} \; 2> /dev/null + patchelf --remove-rpath ./usr/lib/ld-linux-x86-64.so.2 + + # strip binaries + find . -type f -executable -exec strip {} \; 2> /dev/null + find . -type d -exec chmod 755 {} \; + + # gen initrd + find . -print0 | cpio --null --owner=root:root -o --format=newc | gzip -9 > ../initrd.gz + + popd + rm -rf root + ''; +} diff --git a/utils/qemu-uefi-tpm.nix b/utils/qemu-uefi-tpm.nix new file mode 100644 index 0000000..e6a27f9 --- /dev/null +++ b/utils/qemu-uefi-tpm.nix @@ -0,0 +1,50 @@ +{ + pkgs, + ... +}: +pkgs.writeShellApplication { + name = "qemu-uefi-tpm"; + + runtimeInputs = with pkgs; [ + qemu + swtpm + ]; + + text = + let + tpmOVMF = pkgs.OVMF.override { tpmSupport = true; }; + in + '' + set -ex + state="/tmp/patos-qemu-$USER" + rm -rf "$state" + mkdir -m 700 "$state" + truncate -s 1G "$state/disk.raw" + + swtpm socket -d --tpmstate dir="$state" \ + --ctrl type=unixio,path="$state/swtpm-sock" \ + --tpm2 \ + --log level=20 + + qemu-system-x86_64 \ + -enable-kvm \ + -machine q35,accel=kvm \ + -cpu host \ + -smp 8 \ + -m 4G \ + -display none \ + -nographic \ + -chardev "stdio,id=char0,mux=on,logfile=$state/console.log,signal=off" \ + -serial chardev:char0 \ + -mon chardev=char0 \ + -drive "if=pflash,format=raw,unit=0,readonly=on,file=${tpmOVMF.firmware}" \ + -drive "if=pflash,format=raw,unit=1,readonly=on,file=${tpmOVMF.variables}" \ + -chardev socket,id=chrtpm,path="$state/swtpm-sock" \ + -tpmdev emulator,id=tpm0,chardev=chrtpm \ + -device tpm-tis,tpmdev=tpm0 \ + -netdev id=net00,type=user,hostfwd=tcp::2222-:22 \ + -device virtio-net-pci,netdev=net00 \ + -drive "file=fat:rw:patos/,format=raw" \ + -drive "format=raw,file=$state/disk.raw" + ''; +}