2
0
Atdalīts 0
genodepkgs/nixos-modules/hardware.nix

515 rindas
17 KiB
Nix

{ config, pkgs, lib, ... }:
with lib;
{
options = {
networking.interfaces = lib.mkOption {
type = with types;
attrsOf (submodule ({ ... }: {
options.genode = {
driver = mkOption {
type = types.enum [ "ipxe" "virtio" ];
description = "Nic driver to use for this interface.";
};
stack = mkOption {
type = with types; nullOr (enum [ "lwip" "lxip" ]);
default = "lwip";
description = "IP stack to use for this interface.";
};
};
}));
};
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.
'';
};
hardware.genode = {
ahci.enable = lib.mkEnableOption "AHCI (SATA) block driver";
framebuffer = {
enable = lib.mkEnableOption "framebuffer driver";
driver = mkOption {
type = types.enum [ "boot" "vesa" ];
default = "vesa";
};
};
usb = {
enable = lib.mkEnableOption "USB driver";
storage.enable = lib.mkEnableOption "USB mass storage driver";
ehciSupport = lib.mkEnableOption "EHCI support" // { default = true; };
ohciSupport = lib.mkEnableOption "OHCI support" // { default = true; };
uhciSupport = lib.mkEnableOption "UHCI support" // { default = false; };
xhciSupport = lib.mkEnableOption "XHCI support" // { default = true; };
};
};
};
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.";
};
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 =
trace clientList (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.ahci.enable = config.genode.boot.storeBackend == "ahci";
hardware.genode.usb.storage.enable = config.genode.boot.storeBackend
== "usb";
hardware.genode.usb.enable = config.hardware.genode.usb.storage.enable;
hardware.genode.platform.policies = lib.lists.imap0 (i: name:
builtins.toFile (name + ".platform-policy.dhall") ''
let Genode = env:DHALL_GENODE
in Genode.Init.Config.Policy::{
, service = "Platform"
, label = Genode.Init.LabelSelector.prefix "nixos -> ${name}.driver"
, content =
[ Genode.Prelude.XML.leaf
{ name = "pci"
, attributes = toMap {
, class = "ETHERNET"
, index = "${toString i}"
}
}
]
}
'') (builtins.attrNames config.networking.interfaces)
++ (lib.optional config.hardware.genode.ahci.enable
(builtins.toFile ("ahci.platform-policy.dhall") ''
let Genode = env:DHALL_GENODE
in Genode.Init.Config.Policy::{
, service = "Platform"
, label = Genode.Init.LabelSelector.prefix "ahci_drv"
, content =
[ Genode.Prelude.XML.leaf
{ name = "pci", attributes = toMap { class = "AHCI" } }
]
}
'')) ++ (lib.optional config.hardware.genode.framebuffer.enable
(builtins.toFile ("framebuffer.platform-policy.dhall") ''
let Genode = env:DHALL_GENODE
in Genode.Init.Config.Policy::{
, service = "Platform"
, label = Genode.Init.LabelSelector.prefix "fb_drv"
, content =
[ Genode.Prelude.XML.leaf
{ name = "pci", attributes = toMap { class = "VGA" } }
]
}
'')) ++ (lib.optional config.hardware.genode.usb.enable
(builtins.toFile ("usb.platform-policy.dhall") ''
let Genode = env:DHALL_GENODE
in Genode.Init.Config.Policy::{
, service = "Platform"
, label = Genode.Init.LabelSelector.prefix "usb_drv"
, content =
[ Genode.Prelude.XML.leaf
{ name = "pci", attributes = toMap { class = "USB" } }
]
}
''));
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
policy = lib.mapAttrsToList (childName: value:
if any (nic: nic == name) value.routeToNics then ''
Init.Config.Policy::{
, service = "Nic"
, label = Init.LabelSelector.prefix "${childName}"
}
'' else
"") config.genode.init.children;
in pkgs.writeText "${name'}.dhall" ''
let Genode = env:DHALL_GENODE
let Init = Genode.Init
in Init.Child.flat
Init.Child.Attributes::{
, binary = "${binary}/bin/${binary.pname}"
, resources = Init.Resources::{
, caps = 128
, ram = Genode.units.MiB 4
}
, routes = [
, Init.ServiceRoute.parent "IO_MEM"
, Init.ServiceRoute.parent "Platform"
]
, config = Init.Config::{
, attributes = toMap { verbose = "true" }
, policies =
[ ${toString policy} ]
: List Init.Config.Policy.Type
}
}
'';
};
}) 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_lxip ];
}.${interface.genode.stack};
routeToNics = [ name ];
configFile = let
binary = "${pkgs.genodePackages.vfs}/bin/vfs";
ram = {
lwip = 16;
lxip = 32;
}.${interface.genode.stack};
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 = 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 Init.Child.flat
Init.Child.Attributes::{
, binary = "${binary}"
, provides = [ "File_system" ]
, resources = Init.Resources::{
, caps = 128
, ram = Genode.units.MiB ${toString ram}
}
, config = Init.Config::{
, policies =
[ Init.Config.Policy::{
, service = "File_system"
, label = Init.LabelSelector.suffix "${name'}"
, attributes = toMap { root = "/", writeable="yes" }
}
]
, content =
let VFS = Genode.VFS
in [ VFS.vfs
[ VFS.leafAttrs
"${interface.genode.stack}"
([ ${settingsMap} ] : Genode.Prelude.Map.Type Text Text)
]
]
}
}
'';
};
}) config.networking.interfaces;
in lib.filterAttrs (n: v: v != null) (nics // sockets);
genode.core.children.ahci_drv = {
inputs = [ pkgs.genodePackages.ahci_drv ];
configFile = pkgs.writeText "ahci_drv.dhall" ''
let Genode = env:DHALL_GENODE
let Init = Genode.Init
in Init.Child.flat
Init.Child.Attributes::{
, binary = "ahci_drv"
, resources = Init.Resources::{
, caps = 400
, ram = Genode.units.MiB 10
, constrainPhys = True
}
, romReports = [ { local = "ports", route = "ahci_ports" } ]
, routes =
[ Init.ServiceRoute.parent "IRQ"
, Init.ServiceRoute.parent "IO_MEM"
, Init.ServiceRoute.parent "IO_PORT"
]
, config = Init.Config::{
, policies =
[ Init.Config.Policy::{
, service = "Block"
, label = Init.LabelSelector.prefix "part_block"
, attributes = toMap { device = "0", writeable = "yes" }
}
]
}
}
'';
};
genode.core.children.acpi_drv = {
inputs = [ pkgs.genodePackages.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"
]
}
'';
};
genode.core.children.platform_drv = {
inputs = [ pkgs.genodePackages.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 } ]
, routes =
[ Init.ServiceRoute.parent "IRQ"
, Init.ServiceRoute.parent "IO_MEM"
, Init.ServiceRoute.parent "IO_PORT"
]
, config = Init.Config::{
, policies = [ ${
toString policies
} ] : List Init.Config.Policy.Type
}
}
'';
};
genode.core.children.usb_drv = let
cfg = config.hardware.genode.usb;
toYesNo = b: if b then "yes" else "no";
in mkIf cfg.enable {
inputs = [ pkgs.genodePackages.usb_drv ];
configFile = builtins.toFile "usb_drv.dhall" ''
let Genode = env:DHALL_GENODE
let XML = Genode.Prelude.XML
let Init = Genode.Init
in Init.Child.flat
Init.Child.Attributes::{
, binary = "usb_drv"
, resources = Init.Resources::{ caps = 256, ram = Genode.units.MiB 12 }
, romReports = let local = "devices" in [ { local, route = local } ]
, routes = [ Init.ServiceRoute.parent "IO_MEM" ]
, config =
let storagePolicy =
Init.Config.Policy::{
, service = "Usb"
, label = Init.LabelSelector.prefix "usb_block_drv"
, attributes = toMap { class = "8" }
, diag = Some True
}
in Init.Config::{
, attributes = toMap
{ ehci = "${toYesNo cfg.ehciSupport}"
, ohci = "${toYesNo cfg.ohciSupport}"
, uhci = "${toYesNo cfg.uhciSupport}"
, xhci = "${toYesNo cfg.xhciSupport}"
}
, content =
[ XML.element
{ name = "raw"
, attributes = XML.emptyAttributes
, content =
[ XML.leaf
{ name = "report"
, attributes = toMap { devices = "yes" }
}
, Init.Config.Policy.toXML storagePolicy
]
}
]
, policies = [ storagePolicy ] : List Init.Config.Policy.Type
}
}
'';
};
genode.core.children.usb_block_drv =
mkIf config.hardware.genode.usb.storage.enable {
inputs = [ pkgs.genodePackages.usb_block_drv ];
configFile = builtins.toFile "usb_block_drv.dhall" ''
let Genode = env:DHALL_GENODE
let XML = Genode.Prelude.XML
let Init = Genode.Init
in Init.Child.flat
Init.Child.Attributes::{
, binary = "usb_block_drv"
, resources = Init.Resources::{ caps = 256, ram = Genode.units.MiB 4 }
, config = Init.Config::{
, attributes = toMap { writeable = "yes" }
, policies =
[ Init.Config.Policy::{
, service = "Block"
, label = Init.LabelSelector.prefix "part_block"
}
]
}
}
'';
};
genode.core.children.fb_drv =
mkIf config.hardware.genode.framebuffer.enable {
inputs = with pkgs.genodePackages;
{
"boot" = [ boot_fb_drv ];
"vesa" = [ vesa_drv ];
}.${config.hardware.genode.framebuffer.driver};
configFile = let
binary = with pkgs.genodePackages;
{
"boot" = "boot_fb_drv";
"vesa" = "vesa_fb_drv";
}.${config.hardware.genode.framebuffer.driver};
in builtins.toFile "fb_drv.dhall" ''
let Genode = env:DHALL_GENODE
let XML = Genode.Prelude.XML
let Init = Genode.Init
in Init.Child.flat
Init.Child.Attributes::{
, binary = "${binary}"
, resources = Init.Resources::{ caps = 256, ram = Genode.units.MiB 32 }
, routes =
[ Init.ServiceRoute.parent "IO_MEM"
, Init.ServiceRoute.parent "IO_PORT"
]
}
'';
};
virtualisation.useBootLoader = config.genode.boot.storeBackend != "tarball";
virtualisation.qemu.options = lib.optional config.hardware.genode.usb.enable
(lib.optional (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) "-usb"
++ lib.optional (pkgs.stdenv.isAarch32 || pkgs.stdenv.isAarch64)
"-device usb-ehci,id=usb0");
};
}