{ config, pkgs, lib, modulesPath, ... }: with lib; let localPackages = pkgs.buildPackages; in { options.genode = { core = { prefix = mkOption { type = types.str; example = "hw-pc-"; }; supportedSystems = mkOption { type = types.listOf types.str; example = [ "i686-genode" "x86_64-genode" ]; }; basePackages = mkOption { type = types.listOf types.package; }; }; boot = { kernel = mkOption { type = types.path; default = "${pkgs.genodePackages.bender}/bender"; }; initrd = mkOption { type = types.str; default = "${pkgs.genodePackages.bender}/bender"; description = "Path to an image or a command-line arguments"; }; configFile = mkOption { type = types.path; description = '' Dhall boot configuration. See https://git.sr.ht/~ehmry/dhall-genode/tree/master/Boot/package.dhall ''; }; image = mkOption { type = types.path; description = "Boot image containing the base component binaries and configuration."; }; romModules = mkOption { type = types.attrsOf types.path; description = "Attr set of initial ROM modules"; }; }; }; config = let initInputs = unique config.genode.init.inputs; addManifest = drv: drv // { manifest = localPackages.runCommand "${drv.name}.dhall" { inherit drv; } '' set -eu echo -n '[' >> $out find $drv/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out ${if builtins.elem "lib" drv.outputs then '' find ${drv.lib}/ -type f -printf ',{mapKey= "%f",mapValue="%p"}' >> $out'' else ""} echo -n ']' >> $out ''; }; mergeManifests = inputs: localPackages.writeTextFile { name = "manifest.dhall"; text = with builtins; let f = head: input: if hasAttr "manifest" input then '' ${head}, { mapKey = "${ lib.getName input }", mapValue = ${input.manifest} }'' else abort "${input.pname} does not have a manifest"; in (foldl' f "[" inputs) + "]"; }; in { assertions = [{ assertion = builtins.any (s: s == config.nixpkgs.system) config.genode.core.supportedSystems; message = "invalid Genode core for this system"; }]; genode.boot.configFile = let tarball = "${config.system.build.tarball}/tarball/${config.system.build.tarball.fileName}.tar"; manifest = mergeManifests (map addManifest (config.genode.core.basePackages ++ [ config.system.build.tarball ] ++ (with pkgs.genodePackages; [ init cached_fs_rom vfs ]))); in localPackages.runCommand "boot.dhall" { } '' cat > $out << EOF ${./store-wrapper.dhall} (${config.genode.init.configFile}) "${config.system.build.tarball.fileName}.tar" $(stat --format '%s' ${tarball}) ${config.system.build.storeManifest} ${manifest} EOF ''; system.build.storeManifest = mergeManifests (map addManifest initInputs); # Create the tarball of the store to live in core ROM system.build.tarball = pkgs.callPackage "${modulesPath}/../lib/make-system-tarball.nix" { contents = [ ]; storeContents = [ { # assume that the init config will depend # on every store path needed to boot object = config.genode.init.configFile; symlink = "/config.dhall"; } { object = pkgs.buildPackages.symlinkJoin { name = config.system.name + ".rom"; paths = config.genode.init.inputs; }; symlink = "/rom"; } ]; compressCommand = "cat"; compressionExtension = ""; }; system.build.initXml = pkgs.buildPackages.runCommand "init.xml" { nativeBuildInputs = with pkgs.buildPackages; [ dhall xorg.lndir ]; DHALL_GENODE = "${pkgs.genodePackages.dhallGenode}/binary.dhall"; BOOT_CONFIG = config.genode.boot.configFile; } '' export XDG_CACHE_HOME=$NIX_BUILD_TOP lndir -silent \ ${pkgs.genodePackages.dhallGenode}/.cache \ $XDG_CACHE_HOME dhall text <<< "(env:DHALL_GENODE).Init.render (env:BOOT_CONFIG).config" > $out ''; }; }