diff --git a/nixos-modules/genode-core.nix b/nixos-modules/genode-core.nix index 11e6306..8f608f8 100644 --- a/nixos-modules/genode-core.nix +++ b/nixos-modules/genode-core.nix @@ -4,7 +4,8 @@ with lib; let localPackages = pkgs.buildPackages; - children' = config.lib.children.freeze config.genode.core.children; + children' = config.lib.children.freeze + (config.genode.core.children // config.genode.core.supportChildren); coreErisCaps = with builtins; let pkgNames = [ "rtc_drv" ]; @@ -26,9 +27,12 @@ let net = [ ]; }.${config.genode.boot.storeBackend}; - coreInputs = with builtins; + coreInputs = + # TODO: get rid of this? + with builtins; concatMap (getAttr "extraInputs") - (attrValues config.genode.core.children); + ((attrValues config.genode.core.children) + ++ (attrValues config.genode.core.supportChildren)); mergeManifests = inputs: with builtins; @@ -150,6 +154,14 @@ in { ''; }; + supportChildren = config.lib.types.children { extraOptions = { }; } // { + internal = true; + description = '' + Children added to support other children, such as drivers. + Do not manually add children here. + ''; + }; + }; boot = { diff --git a/nixos-modules/hardware/default.nix b/nixos-modules/hardware/default.nix index 460e4f3..a6efb52 100644 --- a/nixos-modules/hardware/default.nix +++ b/nixos-modules/hardware/default.nix @@ -70,7 +70,7 @@ with lib; , Init.ServiceRoute.parent "IO_PORT" ] , config = Init.Config::{ - , policies = [ ${toString policies} ] + , policies = [ ${toString policies} ] : List Init.Config.Policy.Type } } ''; diff --git a/nixos-modules/hardware/nic.nix b/nixos-modules/hardware/nic.nix index 63db860..fb0097f 100644 --- a/nixos-modules/hardware/nic.nix +++ b/nixos-modules/hardware/nic.nix @@ -23,193 +23,97 @@ with lib; }; - config = { + config = + # TODO: create drivers in both the first and second level inits + { - assertions = with builtins; - let - addrCheck = name: interface: { - assertion = lessThan (length interface.ipv4.addresses) 2; - message = "Genode interfaces do not support multihoming."; - }; - routeCheck = name: interface: { - assertion = lessThan (length interface.ipv4.routes) 2; - message = "Genode interfaces do not support multiple routes."; - }; - policyCheck = name: interface: - let - clientList = filter (x: x != null) (lib.mapAttrsToList - (childName: value: - if any (nic: nic == name) value.routeToNics then - childName - else - null) config.genode.init.children); - in { - assertion = clientList == [ ] || length clientList == 1; - message = "Multiple routes to Nic ${name}, ${clientList}"; + assertions = with builtins; + let + addrCheck = name: interface: { + assertion = lessThan (length interface.ipv4.addresses) 2; + message = "Genode interfaces do not support multihoming."; }; - in lib.lists.concatMap - (f: lib.mapAttrsToList f config.networking.interfaces) [ - addrCheck - routeCheck - policyCheck - ]; + routeCheck = name: interface: { + assertion = lessThan (length interface.ipv4.routes) 2; + message = "Genode interfaces do not support multiple routes."; + }; + policyCheck = name: interface: + let + clientList = filter (x: x != null) (lib.mapAttrsToList + (childName: value: + if any (nic: nic == name) value.routeToNics then + childName + else + null) config.genode.core.children); + in { + assertion = clientList == [ ] || length clientList == 1; + message = "Multiple routes to Nic ${name}, ${clientList}"; + }; + in lib.lists.concatMap + (f: lib.mapAttrsToList f config.networking.interfaces) [ + addrCheck + routeCheck + policyCheck + ]; - hardware.genode.platform.policies = lib.lists.imap0 (i: name: - builtins.toFile (name + ".platform-policy.dhall") '' - let Genode = env:DHALL_GENODE + hardware.genode.platform.policies = let + mkPolicy = { name, platformPolicy }: + pkgs.writeText "${name}.policy.dhall" ''${platformPolicy} "${name}"''; - in Genode.Init.Config.Policy::{ - , service = "Platform" - , label = Genode.Init.LabelSelector.prefix "${name}.driver" - , content = - [ Genode.Prelude.XML.leaf - { name = "pci" - , attributes = toMap { - , class = "ETHERNET" - , index = "${toString i}" - } - } - ] - } - '') (builtins.attrNames config.networking.interfaces); + childPolicies = builtins.concatLists (lib.attrsets.mapAttrsToList + (child: childAttrs: + lib.attrsets.mapAttrsToList (uplink: uplinkAttrs: + mkPolicy { + name = "${child}-${uplink}.driver"; + inherit (uplinkAttrs) platformPolicy; + }) childAttrs.uplinks) config.genode.core.children); - genode.core.children = mapAttrs' (name: interface: - let name' = name + ".driver"; - in { - name = name'; - value = { + in childPolicies; + + genode.core.supportChildren = let + + mkUplinkDriver = { policyPrefix, driver, verbose }: { package = with pkgs.genodePackages; { ipxe = ipxe_nic_drv; virtio = virtio_nic_drv; - }.${interface.genode.driver}; - configFile = let - policy = lib.mapAttrsToList (childName: value: - if any (nic: nic == name) value.routeToNics then '' - Init.Config.Policy::{ - , service = "Nic" - , label = Init.LabelSelector.prefix "nixos -> ${childName}" - } - '' else - "") config.genode.init.children; - - in pkgs.writeText "${name'}.dhall" '' + }.${driver}; + configFile = pkgs.writeText "driver.dhall" '' let Genode = env:DHALL_GENODE let Init = Genode.Init - in λ(binary : Text) -> Init.Child.flat - Init.Child.Attributes::{ - , binary - , resources = Init.Resources::{ caps = 128, ram = Genode.units.MiB 4 } - , routes = [ Init.ServiceRoute.parent "IO_MEM" ] - , config = Init.Config::{ - , attributes = toMap { verbose = "true" } - , policies = [ ${ - toString policy - } ] : List Init.Config.Policy.Type - } - } - ''; - }; - }) config.networking.interfaces; - - genode.init.children = let - sockets = mapAttrs' (name: interface: - let - name' = name + ".sockets"; - vfsPlugin = lib.getEris "lib" (with pkgs.genodePackages; - { - lwip = vfs_lwip; - lxip = vfs_lxip; - }.${interface.genode.stack}); - in { - name = name'; - value = if interface.genode.stack == null then - null - else { - package = pkgs.genodePackages.vfs; - extraErisInputs = [ vfsPlugin ]; - routeToNics = [ name ]; - configFile = let - ram = { - lwip = 16; - lxip = 32; - }.${interface.genode.stack}; - settings = with builtins; - [ - { - name = "label"; - value = name; - } - { - name = "load"; - value = vfsPlugin.cap; - } - ] ++ lib.optionals (interface.ipv4.addresses != [ ]) - (let addr = head interface.ipv4.addresses; - in [ - { - name = "ip_addr"; - value = addr.address; - } - { - name = "netmask"; - value = if addr.prefixLength == 24 then - "255.255.255.0" - else - throw "missing prefix to netmask conversion"; - } - ]) ++ lib.optional (interface.ipv4.routes != [ ]) - (let route = head interface.ipv4.routes; - in { - name = "gateway"; - value = route.address; - }) ++ lib.optional (interface.useDHCP != null) { - name = "dhcp"; - value = if interface.useDHCP then "true" else "false"; - }; - settingsMap = builtins.concatStringsSep ", " (map - ({ name, value }: - ''{ mapKey = "${name}", mapValue = "${value}" }'') settings); - in pkgs.writeText "${name'}.dhall" '' - let Genode = env:DHALL_GENODE - - let Init = Genode.Init - - in λ(binary : Text) -> Init.Child.flat + in λ(binary : Text) → + Init.Child.flat Init.Child.Attributes::{ , binary - , provides = [ "File_system" ] - , resources = Init.Resources::{ - , caps = 128 - , ram = Genode.units.MiB ${toString ram} - } + , resources = Init.Resources::{ caps = 128, ram = Genode.units.MiB 4 } + , routes = [ Init.ServiceRoute.parent "IO_MEM" ] , config = Init.Config::{ + , attributes = toMap { verbose = "${ + if verbose then "yes" else "no" + }" } , policies = [ Init.Config.Policy::{ - , service = "File_system" - , label = Init.LabelSelector.suffix "${name'}" - , attributes = toMap { root = "/", writeable="yes" } + , service = "Nic" + , label = Init.LabelSelector.prefix "${policyPrefix}" } ] - , content = - let VFS = Genode.VFS - - in [ VFS.vfs - [ VFS.leafAttrs - "plugin" - ([ ${settingsMap} ] : Genode.Prelude.Map.Type Text Text) - ] - ] } } - ''; - }; - }) config.networking.interfaces; + ''; + }; - in lib.filterAttrs (n: v: v != null) sockets; - - }; + otherDrivers = builtins.concatLists (lib.attrsets.mapAttrsToList + (child: childAttrs: + lib.attrsets.mapAttrsToList (uplink: uplinkAttrs: { + name = "${child}-${uplink}.driver"; + value = mkUplinkDriver { + policyPrefix = "${child} -> ${uplink}"; + inherit (uplinkAttrs) driver verbose; + }; + }) childAttrs.uplinks) config.genode.core.children); + in builtins.listToAttrs otherDrivers; + }; } diff --git a/nixos-modules/lib/children.nix b/nixos-modules/lib/children.nix index dc9832d..10f1c13 100644 --- a/nixos-modules/lib/children.nix +++ b/nixos-modules/lib/children.nix @@ -61,6 +61,8 @@ example = literalExample "pkg.genodePackages.init"; }; + uplinks = import ./uplinks-option.nix { inherit lib; }; + } // extraOptions; }); }; diff --git a/nixos-modules/lib/uplinks-option.nix b/nixos-modules/lib/uplinks-option.nix new file mode 100644 index 0000000..fc26f6d --- /dev/null +++ b/nixos-modules/lib/uplinks-option.nix @@ -0,0 +1,29 @@ +{ lib }: +with lib; + +mkOption { + default = { }; + type = with types; + attrsOf (submodule { + options = { + driver = mkOption { type = types.enum [ "ipxe" "virtio" ]; }; + platformPolicy = mkOption { + type = types.path; + default = builtins.toFile "driver.policy.dhall" '' + let Genode = env:DHALL_GENODE + + in λ(driverName : Text) → + Genode.Init.Config.Policy::{ + , service = "Platform" + , label = Genode.Init.LabelSelector.prefix driverName + , content = + [ Genode.Prelude.XML.leaf + { name = "pci", attributes = toMap { class = "ETHERNET" } } + ] + } + ''; + }; + verbose = lib.mkEnableOption "verbose driver logging"; + }; + }); +}