diff --git a/nixos-modules/nixos-host.nix b/nixos-modules/nixos-host.nix
index 5bca725..6ab5649 100644
--- a/nixos-modules/nixos-host.nix
+++ b/nixos-modules/nixos-host.nix
@@ -6,22 +6,29 @@
{
options.genodeGuests = with lib;
+ with lib.types;
let
genodeOpts = { ... }: {
options = {
name = mkOption {
example = "webserver";
- type = types.str;
+ type = str;
description = "Name of the Genode subsystem.";
};
config = mkOption {
- type = types.str;
- default = "";
+ type = oneOf [ str path ];
+ example = ''
+ let Genode = env:DHALL_GENODE
+
+ in Genode.Init::{=}
+ '';
description = ''
- Configuration of the Genode subsystem.
- Must be rendered in the Genode XML format.
+ Configuration of the Genode subsystem in Dhall.
+ The type of the expression must be Genode.Init.Type,
+ where the Genode is library available at
+ env:DHALL_GENODE.
'';
};
@@ -39,15 +46,24 @@
'';
};
+ nics = mkOption {
+ type = with types; listOf str;
+ default = [ ];
+ example = [ "tap0" "tap1" ];
+ description = ''
+ TAP interfaces to pass from NixOS into the Genode guest.
+ '';
+ };
+
};
};
in mkOption {
- type = with lib.types; loaOf (submodule genodeOpts);
+ type = loaOf (submodule genodeOpts);
default = { };
example = {
foobar = {
- config = "";
+ config = "…";
rom = pkgs: { };
};
};
@@ -64,25 +80,38 @@
inherit (crossPkgs.genodePackages) base-linux;
toService = name: cfg: {
description = "Genode subsystem";
+ after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
preStart = let
+ config' =
+ self.lib.${crossSystem}.runDhallCommand "${name}.config" { } ''
+ set -e
+ exec ${self.apps.${crossSystem}.render-init.program} > $out << EOF
+ ${./root-config.dhall}
+ { guest = ${cfg.config}
+ , nics = [ "${builtins.concatStringsSep ''", "'' cfg.nics}" ]
+ }
+ EOF
+ '';
rom' = with crossPkgs.genodePackages;
{
- core = "${base-linux}/bin/core-linux";
- init = "${init}/bin/init";
- "ld.lib.so" = "${base-linux}/bin/ld.lib.so";
- timer = "${base-linux}/bin/linux_timer_drv";
- config = builtins.toFile "${name}.config.xml" cfg.config;
+ init = "${init}/init";
+ "ld.lib.so" = "${base-linux}/lib/ld.lib.so";
+ timer_drv = "${base-linux}/timer_drv";
+ config = config';
+ linux_nic_drv = "${
+ crossPkgs.genodeSources.depot "linux_nic_drv"
+ }/linux_nic_drv";
} // (cfg.rom crossPkgs);
in builtins.concatStringsSep "\n"
- (lib.mapAttrsToList (name: value: "ln -s ${value} ${name}") rom');
+ (lib.mapAttrsToList (name: value: "ln -sv ${value} ${name}") rom');
serviceConfig = {
DynamicUser = true;
RuntimeDirectory = "genode/" + name;
WorkingDirectory = "/run/genode/" + name;
- ExecStart = "${base-linux}/bin/core-linux";
+ ExecStart = "${base-linux}/core-linux";
};
};
in lib.mapAttrs toService config.genodeGuests;
diff --git a/nixos-modules/root-config.dhall b/nixos-modules/root-config.dhall
new file mode 100644
index 0000000..8a95116
--- /dev/null
+++ b/nixos-modules/root-config.dhall
@@ -0,0 +1,70 @@
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let Init = Genode.Init
+
+let Child = Init.Child
+
+let nicChild
+ : Text → Init.Children.Entry
+ = λ(tapDevice : Text)
+ → { mapKey = tapDevice
+ , mapValue =
+ Child.flat
+ Child.Attributes::{
+ , binary = "linux_nic_drv"
+ , config = Init.Config::{ attributes = toMap { tap = tapDevice } }
+ , ld = False
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 4
+ }
+ , provides = [ "Nic" ]
+ }
+ }
+
+let nicChildren = Prelude.List.map Text Init.Children.Entry nicChild
+
+let init =
+ λ(params : { guest : Init.Type, nics : List Text })
+ → Init::{
+ , routes = [ Init.ServiceRoute.child "Timer" "timer_drv" ]
+ , children =
+ nicChildren params.nics
+ # toMap
+ { timer_drv =
+ Child.flat
+ Child.Attributes::{
+ , binary = "timer_drv"
+ , provides = [ "Timer" ]
+ }
+ , init =
+ Init.toChild
+ params.guest
+ Init.Attributes::{
+ , exitPropagate = True
+ , routes =
+ Prelude.List.map
+ Text
+ Init.ServiceRoute.Type
+ ( λ(tapDevice : Text)
+ → { service =
+ { name = "Nic"
+ , label = Init.LabelSelector.last tapDevice
+ }
+ , route =
+ Init.Route.Type.Child
+ { name = tapDevice
+ , label = None Text
+ , diag = None Bool
+ }
+ }
+ )
+ params.nics
+ }
+ }
+ , verbose = True
+ }
+
+in init
diff --git a/tests/nixos-host.nix b/tests/nixos-host.nix
index 6cb744c..7214f02 100644
--- a/tests/nixos-host.nix
+++ b/tests/nixos-host.nix
@@ -6,45 +6,80 @@ import "${self.inputs.nixpkgs}/nixos/tests/make-test-python.nix"
# meta.maintainers = [ pkgs.lib.maintainers.ehmry ];
machine = {
+
imports = [
self.nixosModules.genodeGuests
"${self.inputs.nixpkgs}/nixos/modules/profiles/minimal.nix"
];
- genodeGuests.signal-test = {
+
+ networking.bridges.br0.interfaces = [ "eth0" "tap0" ];
+
+ networking.interfaces.eth0.useDHCP = false;
+
+ networking.interfaces.tap0 = {
+ useDHCP = false;
+ virtual = true;
+ virtualType = "tap";
+ };
+
+ genodeGuests.tap-test = {
config = ''
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ let Genode = env:DHALL_GENODE
+
+ let Prelude = Genode.Prelude
+
+ let XML = Prelude.XML
+
+ let Init = Genode.Init
+
+ in Init::{
+ , children = toMap
+ { lwip_fs =
+ Init.Child.flat
+ Init.Child.Attributes::{
+ , binary = "vfs"
+ , config = Init.Config::{
+ , content =
+ [ XML.element
+ { name = "vfs"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.leaf
+ { name = "lwip"
+ , attributes = toMap { dhcp = "yes" }
+ }
+ ]
+ }
+ ]
+ }
+ , provides = [ "File_system" ]
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 8
+ }
+ , routes =
+ [ Init.ServiceRoute.parentLabel "Nic" (None Text) (Some "tap0")
+ , Init.ServiceRoute.parent "Timer"
+ ]
+ }
+ }
+ , verbose = True
+ }
'';
+ nics = [ "tap0" ];
rom = pkgs: {
- "test-signal" =
- "${pkgs.genodeSources.depot "test-signal"}/bin/test-signal";
+ "vfs" = "${pkgs.genodeSources.depot "vfs"}/vfs";
+ "libvfs.so" = "${(pkgs.genodeSources.depot "vfs").lib}/lib/libvfs.so";
+ "libvfs_lwip.so" =
+ "${pkgs.genodeSources.depot "vfs_lwip"}/lib/libvfs_lwip.so";
};
};
+
};
testScript = ''
start_all()
- machine.wait_for_unit("genode")
+ machine.wait_for_unit("tap-test")
machine.wait_for_open_port("1965")
'';
-}) {
- system = localSystem;
-}
+}) { system = localSystem; }