diff --git a/nixos-modules/hardware.nix b/nixos-modules/hardware.nix index f800145..23a45c5 100644 --- a/nixos-modules/hardware.nix +++ b/nixos-modules/hardware.nix @@ -3,188 +3,265 @@ with lib; { - options.networking.interfaces = lib.mkOption { - type = with types; - attrsOf (submodule ({ ... }: { - options.genode = { + options = { - driver = mkOption { type = types.enum [ "ipxe" "virtio" ]; }; + networking.interfaces = lib.mkOption { + type = with types; + attrsOf (submodule ({ ... }: { + options.genode = { + + driver = mkOption { type = types.enum [ "ipxe" "virtio" ]; }; + + stack = mkOption { + type = with types; nullOr (enum [ "lwip" "lxip" ]); + default = "lwip"; + }; - stack = mkOption { - type = types.enum [ "lwip" "lxip" ]; - default = "lwip"; }; + })); + }; - }; - })); - }; - - config.genode.init.children = let - inherit (builtins) toFile; - - nics = mapAttrs' (name: interface: - let name' = "nic." + name; - in { - name = name'; - value = { - inputs = with pkgs.genodePackages; - { - ipxe = [ ipxe_nic_drv ]; - virtio = [ virtio_nic_drv ]; - }.${interface.genode.driver}; - configFile = toFile "${name'}.dhall" '' - let Genode = env:DHALL_GENODE - - let Init = Genode.Init - - in Init.Child.flat - Init.Child.Attributes::{ - , binary = "virtio_pci_nic" - , provides = [ "Nic" ] - , resources = Init.Resources::{ - , caps = 128 - , ram = Genode.units.MiB 4 - } - , routes = [ Init.ServiceRoute.parent "IO_MEM" ] - , config = Init.Config::{ - , policies = - [ Init.Config.Policy::{ - , service = "Nic" - , label = - Init.LabelSelector.prefix "sockets.${name}" - } - ] - } - } - ''; - }; - }) config.networking.interfaces; - - sockets = mapAttrs' (name: interface: - let name' = "sockets." + name; - in { - name = name'; - value = { - inputs = with pkgs.genodePackages; - { - lwip = [ vfs_lwip ]; - lxip = [ vfs_lixp ]; - }.${interface.genode.stack}; - configFile = let ipv4 = builtins.head interface.ipv4.addresses; - in toFile "${name'}.dhall" '' - let Genode = env:DHALL_GENODE - - let Init = Genode.Init - - in Init.Child.flat - Init.Child.Attributes::{ - , binary = "vfs" - , provides = [ "File_system" ] - , resources = Init.Resources::{ caps = 128, ram = Genode.units.MiB 16 } - , config = Init.Config::{ - , policies = - [ Init.Config.Policy::{ - , service = "File_system" - , label = Init.LabelSelector.suffix "sockets" - , attributes = toMap { root = "/" } - } - ] - , content = - let XML = Genode.Prelude.XML - - in [ XML.element - { name = "vfs" - , attributes = XML.emptyAttributes - , content = - [ XML.leaf - { name = "lwip" - , attributes = toMap - { ip_addr = "${ipv4.address}", netmask = "${ - if ipv4.prefixLength == 24 then - "255.255.255.0" - else - throw - "missing prefix to netmask conversion" - }" } - } - ] - } - ] - } - } - ''; - }; - }) config.networking.interfaces; - - in nics // sockets // { - - platform_drv = { - inputs = [ pkgs.genodePackages.platform_drv ]; - configFile = let - policies = concatMapStrings (name: '' - Init.Config.Policy::{ - , service = "Platform" - , label = Init.LabelSelector.prefix "nic.${name}" - , content = - [ Genode.Prelude.XML.leaf - { name = "pci", attributes = toMap { class = "ETHERNET" } } - ] - } - '') (builtins.attrNames config.networking.interfaces); - in toFile "platform_drv.dhall" '' - let Genode = env:DHALL_GENODE - - let Init = Genode.Init - - let label = \(_ : Text) -> { local = _, route = _ } - - in Init.Child.flat - Init.Child.Attributes::{ - , binary = "platform_drv" - , resources = Init.Resources::{ - , caps = 800 - , ram = Genode.units.MiB 4 - , constrainPhys = True - } - , reportRoms = [ label "acpi" ] - , provides = [ "Platform" ] - , routes = - [ Init.ServiceRoute.parent "IRQ" - , Init.ServiceRoute.parent "IO_MEM" - , Init.ServiceRoute.parent "IO_PORT" - ] - , config = Init.Config::{ - , policies = [ ${policies} ] - } - } + hardware.genode.platform.policies = lib.mkOption { + type = with types; listOf path; + default = [ ]; + description = '' + List of policies to append to the Genode platform driver. + Type is Init.Config.Policy.Type. ''; }; - acpi_drv = { - inputs = [ pkgs.genodePackages.acpi_drv ]; - configFile = toFile "acpi_drv.dhall" '' + }; + + config = { + + 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."; + }; + in lib.mapAttrsToList addrCheck config.networking.interfaces + ++ lib.mapAttrsToList routeCheck config.networking.interfaces; + + hardware.genode.platform.policies = lib.lists.imap0 (i: name: + builtins.toFile (name + ".platform-policy.dhall") '' let Genode = env:DHALL_GENODE - let Init = Genode.Init + 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); - let label = \(_ : Text) -> { local = _, route = _ } + genode.core.basePackages = with pkgs.genodePackages; [ + acpi_drv + platform_drv + ]; - in Init.Child.flat - Init.Child.Attributes::{ - , binary = "acpi_drv" - , resources = Init.Resources::{ - , caps = 400 - , ram = Genode.units.MiB 4 - , constrainPhys = True - } - , romReports = [ label "acpi" ] - , routes = - [ Init.ServiceRoute.parent "IRQ" - , Init.ServiceRoute.parent "IO_MEM" - , Init.ServiceRoute.parent "IO_PORT" + genode.init.children = let + + nics = mapAttrs' (name: interface: + let name' = name + ".driver"; + in { + name = name'; + value = let + binary = with pkgs.genodePackages; + { + ipxe = ipxe_nic_drv; + virtio = virtio_nic_drv; + }.${interface.genode.driver}; + in { + inputs = [ binary ]; + configFile = let + policies = if interface.genode.stack == null then + "[] : List Init.Config.Policy.Type" + else '' + [ Init.Config.Policy::{ + , service = "Nic" + , label = Init.LabelSelector.prefix "${name}.sockets" + } ] - } - ''; + ''; + in pkgs.writeText "${name'}.dhall" '' + let Genode = env:DHALL_GENODE + + let Init = Genode.Init + + in Init.Child.flat + Init.Child.Attributes::{ + , binary = "${binary.pname}" + , provides = [ "Nic" ] + , resources = Init.Resources::{ + , caps = 128 + , ram = Genode.units.MiB 4 + } + , routes = [ Init.ServiceRoute.parent "IO_MEM" ] + , config = Init.Config::{ + , attributes = toMap { verbose = "true" } + , policies = ${policies} + } + } + ''; + }; + }) config.networking.interfaces; + + sockets = mapAttrs' (name: interface: + let name' = name + ".sockets"; + in { + name = name'; + value = if interface.genode.stack == null then + null + else { + inputs = with pkgs.genodePackages; + { + lwip = [ vfs_lwip ]; + lxip = [ vfs_lixp ]; + }.${interface.genode.stack}; + configFile = let + binary = "${pkgs.genodePackages.vfs}/bin/vfs"; + settings = with builtins; + 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 = map ({ name, value }: + ''{ mapKey = "${name}", mapValue = "${value}" }'') settings; + in pkgs.writeText "${name'}.dhall" '' + let Genode = env:DHALL_GENODE + + let Init = Genode.Init + + in Init.Child.flat + Init.Child.Attributes::{ + , binary = "${binary}" + , provides = [ "File_system" ] + , resources = Init.Resources::{ caps = 128, ram = Genode.units.MiB 16 } + , config = Init.Config::{ + , policies = + [ Init.Config.Policy::{ + , service = "File_system" + , label = Init.LabelSelector.suffix "sockets" + , attributes = toMap { root = "/" } + } + ] + , content = + let XML = Genode.Prelude.XML + + in [ XML.element + { name = "vfs" + , attributes = XML.emptyAttributes + , content = + [ XML.leaf + { name = "lwip" + , attributes = [ + ${ + builtins.concatStringsSep ", " + settingsMap + } + ] : Genode.Prelude.Map.Type Text Text + } + ] + } + ] + } + } + ''; + }; + }) config.networking.interfaces; + + in nics // (lib.filterAttrs (n: v: v != null) sockets) // { + + acpi_drv = { + coreROMs = [ "acpi_drv" ]; + configFile = pkgs.writeText "acpi_drv.dhall" '' + let Genode = env:DHALL_GENODE + + let Init = Genode.Init + + let label = λ(_ : Text) → { local = _, route = _ } + + in Init.Child.flat + Init.Child.Attributes::{ + , binary = "acpi_drv" + , resources = Init.Resources::{ + , caps = 400 + , ram = Genode.units.MiB 4 + , constrainPhys = True + } + , romReports = [ label "acpi", label "smbios_table" ] + , routes = + [ Init.ServiceRoute.parent "IRQ" + , Init.ServiceRoute.parent "IO_MEM" + , Init.ServiceRoute.parent "IO_PORT" + ] + } + ''; + }; + + platform_drv = { + coreROMs = [ "platform_drv" ]; + configFile = let + policies = map (policy: ", ${policy}") + config.hardware.genode.platform.policies; + in pkgs.writeText "platform_drv.dhall" '' + let Genode = env:DHALL_GENODE + + let Init = Genode.Init + + in Init.Child.flat + Init.Child.Attributes::{ + , binary = "platform_drv" + , resources = Init.Resources::{ + , caps = 800 + , ram = Genode.units.MiB 4 + , constrainPhys = True + } + , reportRoms = let label = "acpi" in [ { local = label, route = label } ] + , provides = [ "Platform" ] + , routes = + [ Init.ServiceRoute.parent "IRQ" + , Init.ServiceRoute.parent "IO_MEM" + , Init.ServiceRoute.parent "IO_PORT" + ] + , config = Init.Config::{ + , policies = [ ${toString policies} ] + } + } + ''; + }; + }; }; diff --git a/tests/lib/build-vms.nix b/tests/lib/build-vms.nix index 3119872..8224a73 100644 --- a/tests/lib/build-vms.nix +++ b/tests/lib/build-vms.nix @@ -79,7 +79,9 @@ rec { config = { networking.hostName = mkDefault m.fst; - networking.interfaces = listToAttrs interfaces; + networking.interfaces = { + eth0.genode.driver = "virtio"; + } // listToAttrs interfaces; networking.primaryIPAddress = optionalString (interfaces != [ ]) (head (head interfaces).value.ipv4.addresses).address;