{ config, pkgs, lib, ... }: { options.genode = with lib; let genodeOpts = { ... }: { options = { name = mkOption { example = "webserver"; type = types.str; description = "Name of the Genode subsystem."; }; depot = mkOption { type = with types; attrsOf package; description = '' Attribute set of Genode depot binaries. ''; }; pkgs = mkOption { type = with types; attrsOf package; description = '' Attribute set of Genode packages. ''; }; config = mkOption { type = types.str; default = ""; description = '' Configuration of the Genode subsystem. Must be rendering in the Genode XML format. ''; }; rom = mkOption { type = with types; attrs; example = literalExample { nic_drv = "${depot.ipxe_nic_drv}/bin/ipxe_nic_drv"; }; }; }; }; in mkOption { type = with lib.types; loaOf (submodule genodeOpts); default = { }; example = { foobar = { config = ""; rom = { }; }; }; description = '' Configurations of Genode subsystems ''; }; config = { systemd.services = let toService = name: cfg: { description = "Genode subsystem"; wantedBy = [ "multi-user.target" ]; preStart = let rom' = with cfg.pkgs; { core = "${base-linux}/bin/core-linux"; init = "${os}/bin/init"; "ld.lib.so" = "${cfg.depot.base-linux}/lib/ld.lib.so"; timer = "${base-linux}/bin/linux_timer_drv"; config = builtins.toFile "${name}.config.xml" cfg.config; } // cfg.rom; in builtins.concatStringsSep "\n" (lib.mapAttrsToList (name: value: "ln -s ${value} ${name}") rom'); serviceConfig = { DynamicUser = true; RuntimeDirectory = "genode/" + name; WorkingDirectory = "/run/genode/" + name; ExecStart = "${cfg.pkgs.base-linux}/bin/core-linux"; }; }; in lib.mapAttrs toService config.genode; }; }