diff --git a/flake.nix b/flake.nix
index 1e72f0e..bc32f67 100644
--- a/flake.nix
+++ b/flake.nix
@@ -5,7 +5,7 @@
description = "Genode packages";
- inputs.nixpkgs.url = "github:ehmry/nixpkgs?ref=genode";
+ inputs.nixpkgs.url = "github:ehmry/nixpkgs/genode";
outputs = { self, nixpkgs }:
let
@@ -111,17 +111,52 @@
apps = let
apps' = forAllCrossSystems ({ system, localSystem, crossSystem }:
import ./apps {
- system = crossSystem;
+ inherit system;
self = self.apps.${system};
nixpkgs = nixpkgsFor.${system};
nixpkgsLocal = nixpkgsFor.${localSystem};
packages = self.packages.${system};
+ } // {
+ nixosModule = {
+ type = "app";
+ program =
+ "${self.checks.${localSystem}.nixosModule}/bin/run-nixos-vm";
+ };
});
in apps' // { x86_64-linux = apps'.x86_64-linux-x86_64-genode; };
+ nixosModules = import ./nixos-modules { inherit self; };
+
checks = let
+
checks' = forAllCrossSystems ({ system, localSystem, crossSystem }:
- import ./tests {
+ let
+ nixos = nixpkgs.lib.nixosSystem {
+ system = localSystem;
+ modules = [
+ self.nixosModules.genodeHost
+ ({ modulesPath, ... }: {
+ imports = [ "${modulesPath}/virtualisation/qemu-vm.nix" ];
+ boot.loader.grub.extraEntriesBeforeNixOS = true;
+ genode.inputFilter.extraChargen =
+ "${./nixos-modules/dhall/workman.chargen.dhall}";
+ virtualisation = {
+ cores = 2;
+ memorySize = 1024;
+ useBootLoader = true;
+ qemu = {
+ options =
+ [ "-machine q35" "-cpu phenom" "-serial mon:stdio" ];
+ networkingOptions = [
+ "-net nic,netdev=user.0,model=e1000"
+ "-netdev user,id=user.0\${QEMU_NET_OPTS:+,$QEMU_NET_OPTS}"
+ ];
+ };
+ };
+ })
+ ];
+ };
+ in import ./tests {
inherit self;
apps = self.apps.${system};
localPackages = nixpkgsFor.${localSystem};
@@ -129,10 +164,56 @@
lib = self.lib.${system};
nixpkgs = nixpkgsFor.${system};
legacyPackages = self.legacyPackages.${system};
+ } // {
+
+ ports = nixpkgsFor.${localSystem}.symlinkJoin {
+ name = "ports";
+ paths = (builtins.attrValues
+ self.packages.${system}.genodeSources.ports);
+ };
+
+ nixosModule = nixos.config.system.build.vm;
+ nixosXML = nixos.config.system.build.genode.xml;
+
+ nixosGuest = let
+ nixos = nixpkgs.lib.nixosSystem {
+ system = localSystem;
+ modules = [
+ self.nixosModules.genodeHost
+ ({ modulesPath, ... }: {
+ imports = [ "${modulesPath}/virtualisation/qemu-vm.nix" ];
+ boot.loader.grub.extraEntriesBeforeNixOS = true;
+ virtualisation = {
+ cores = 2;
+ memorySize = 1024;
+ useBootLoader = true;
+ qemu = {
+ options =
+ [ "-machine q35" "-cpu phenom" "-serial mon:stdio" ];
+ networkingOptions = [
+ "-net nic,netdev=user.0,model=e1000"
+ "-netdev user,id=user.0\${QEMU_NET_OPTS:+,$QEMU_NET_OPTS}"
+ ];
+ };
+ };
+ genode.guests.flakeCheck = {
+ config = { config, lib, pkgs, ... }: {
+ networking.firewall.allowedTCPPorts = [ 80 ];
+ services.mingetty.autologinUser = lib.mkDefault "root";
+ services.nginx.enable = true;
+ services.openssh.permitRootLogin = lib.mkDefault "yes";
+ services.sshd.enable = true;
+ users.users.root.password = "nixos";
+ virtualbox.memorySize = 128;
+ };
+ };
+ })
+ ];
+ };
+ in nixos.config.system.build.vm;
+
});
- in checks' // {
- x86_64-linux = with builtins;
- foldl' (x: y: x // y) { } (attrValues checks');
- };
+ in { x86_64-linux = checks'.x86_64-linux-x86_64-genode; };
+
};
}
diff --git a/nixos-modules/buildBootDescription.nix b/nixos-modules/buildBootDescription.nix
new file mode 100644
index 0000000..511102e
--- /dev/null
+++ b/nixos-modules/buildBootDescription.nix
@@ -0,0 +1,67 @@
+# SPDX-License-Identifier: CC0-1.0
+
+# Generate a total boot description by matching the binaries referred to by an init
+# configuration with a list of input packages.
+
+{ lib, writeText, dhall-json }:
+
+{ initConfig, imageInputs, extraBinaries ? [ ], extraRoms ? { } }:
+
+with builtins;
+let
+ extractDrv = lib.runDhallCommand "binaries.json" {
+ nativeBuildInputs = [ dhall-json ];
+ } ''
+ dhall-to-json << TRUE_DEATH > $out
+ let Genode = env:DHALL_GENODE
+ let init = ${initConfig}
+ in Genode.Init.Child.binaries (Genode.Init.toChild init Genode.Init.Attributes::{=})
+ TRUE_DEATH
+ '';
+ binariesJSON = readFile (toString extractDrv);
+ binaries = lib.unique (fromJSON binariesJSON ++ extraBinaries);
+
+ matches = let
+ f = binary: {
+ name = binary;
+ value = let
+ f = drv:
+ if lib.hasPrefix "lib" binary && lib.hasSuffix ".so" binary
+ && pathExists "${drv.lib or drv}/lib" then
+ toPath "${drv.lib or drv}/lib/${binary}"
+ else
+ toPath (if pathExists "${drv}/bin" then
+ "${drv}/bin/${binary}"
+ else
+ "${drv}/${binary}");
+ in filter pathExists (map f imageInputs);
+ };
+ in map f binaries;
+
+ binaryPaths = let
+ f = { name, value }:
+ let l = length value;
+ in if l == 1 then {
+ inherit name;
+ value = elemAt value 0;
+ } else if l == 0 then
+ throw "${name} not found in imageInputs"
+ else
+ throw "${name} found in multiple imageInputs, ${toString value}";
+ in map f matches;
+
+ extraList =
+ lib.mapAttrsToList (name: value: { inherit name value; }) extraRoms;
+
+in writeText "boot.dhall" ''
+ let Genode = env:DHALL_GENODE
+ in { config = ${initConfig}
+ , rom = Genode.BootModules.toRomPaths ([
+ ${
+ toString (map ({ name, value }: ''
+ , { mapKey = "${name}", mapValue = "${value}" }
+ '') (binaryPaths ++ extraList))
+ }
+ ])
+ }
+''
diff --git a/nixos-modules/default.nix b/nixos-modules/default.nix
new file mode 100644
index 0000000..9f6af90
--- /dev/null
+++ b/nixos-modules/default.nix
@@ -0,0 +1,235 @@
+{ self }: {
+ genodeHost = { config, lib, pkgs, ... }:
+ let
+ apps' = self.apps.x86_64-linux-x86_64-genode;
+ config' = config;
+ lib' = self.lib.x86_64-linux-x86_64-genode;
+ pkgs' = self.packages.x86_64-linux-x86_64-genode;
+ legacyPackages' = self.legacyPackages.x86_64-linux-x86_64-genode;
+
+ modulesPath = "${self.inputs.nixpkgs}/nixos/modules";
+
+ cfg = config.genode;
+
+ toVdi = config:
+ import "${modulesPath}/../lib/make-disk-image.nix" {
+ inherit config lib pkgs;
+ diskSize = config.virtualbox.baseImageSize;
+ partitionTableType = "legacy";
+ fsType = "ext4";
+ name = "nixos-${pkgs.stdenv.hostPlatform.system}.vdi";
+ format = "vdi";
+ };
+
+ console = lib'.runDhallCommand "vbox.dhall" { } ''
+ dhall > $out <<< '${
+ ./dhall/console.dhall
+ } { bash = "${legacyPackages'.bash}", coreutils = "${legacyPackages'.coreutils}", path = "${
+ lib.makeSearchPathOutput "bin" "bin"
+ (with legacyPackages'; [ bash coreutils ])
+ }" }'
+ '';
+
+ guestChildren = lib'.runDhallCommand "vbox.dhall" { } (''
+ dhall > $out << END
+ let Genode = env:DHALL_GENODE
+ in [
+ '' + builtins.concatStringsSep "," (lib.mapAttrsToList (vmName: cfg:
+ let
+ inherit (cfg) config;
+ vdiRoot = toVdi config;
+ in lib'.runDhallCommand "vbox.dhall" { } ''
+ vdiUuid=$(${pkgs.virtualbox}/bin/VBoxManage showmediuminfo "${vdiRoot}/nixos.vdi" | awk '/^UUID:/ {print $2}')
+ dhall > $out << END
+ { mapKey = "vbox-${vmName}"
+ , mapValue =
+ ${./dhall/vbox-guest.dhall}
+ { vdiFilename = "nixos.vdi"
+ , vdiPkg = "${baseNameOf vdiRoot}"
+ , vdiUuid = "$vdiUuid"
+ , memorySize = ${toString config.virtualbox.memorySize}
+ , vmName = "${vmName}"
+ }
+ }
+ END
+ '') config.genode.guests) + ''
+ ] : Genode.Init.Children.Type
+ END
+ '');
+
+ initConfig = let
+ fbDriverConfig = if cfg.fbDriver == "intel" then
+ ./dhall/intel_fb_drv.dhall
+ else if cfg.fbDriver == "vesa" then
+ ./dhall/vesa_fb_drv.dhall
+ else
+ throw ''No driver configuration found for "${cfg.fbDriver}"'';
+ in ''
+ ${
+ ./dhall/root.dhall
+ } { fbDriver = ${fbDriverConfig}, guests = toMap { console = ${console} } # ${guestChildren}, inputFilterChargens = ${cfg.inputFilter.extraChargen}, partitionType = ${
+ ./dhall/partition-type
+ }, wm = ${./dhall/wm.dhall}
+ }'';
+
+ buildBootDescription = self.legacyPackages.x86_64-linux.callPackage
+ ./buildBootDescription.nix { lib = lib'; };
+
+ bootDescription = buildBootDescription {
+ inherit initConfig;
+ imageInputs = [ legacyPackages'.bash pkgs'.show_input ]
+ ++ map pkgs'.genodeSources.depot ([
+ "acpi_drv"
+ "ahci_drv"
+ "cached_fs_rom"
+ "chroot"
+ "decorator"
+ "init"
+ "input_filter"
+ "ipxe_nic_drv"
+ "libc"
+ "libiconv"
+ "log_core"
+ "nit_fb"
+ "nitpicker"
+ "part_block"
+ "platform_drv"
+ "posix"
+ "ps2_drv"
+ "report_rom"
+ "rom_logger"
+ "rtc_drv"
+ "rump"
+ "stdcxx"
+ "terminal"
+ "terminal_log"
+ "usb_drv"
+ "vfs"
+ "vfs_audit"
+ "vfs_import"
+ "vfs_pipe"
+ "vfs_ttf"
+ "window_layouter"
+ "wm"
+ ] ++ lib.optional (cfg.guests != { }) "vbox5"
+ ++ lib.optional (cfg.fbDriver == "vesa") "vesa_drv"
+ ++ lib.optional (cfg.fbDriver == "intel") "intel_fb_drv")
+ ++ (with pkgs'; [ base-nova block_router ]);
+ extraBinaries = [
+ "ld.lib.so"
+ "libc.so"
+ "libm.so"
+ "libposix.so"
+ "librump.so"
+ "librump_fs.so"
+ "libstdcxx.so"
+ "libvfs.so"
+ "libvfs_audit.so"
+ "libvfs_import.so"
+ "libvfs_pipe.so"
+ "libvfs_rump.so"
+ "libvfs_ttf.so"
+ ] ++ lib.optionals (cfg.guests != { }) [
+ "libc_pipe.so"
+ "libiconv.so"
+ "libqemu-usb.so"
+ ];
+ extraRoms = {
+ "Inconsolata.ttf" =
+ "${pkgs.inconsolata}/share/fonts/truetype/inconsolata/Inconsolata-Regular.ttf";
+ "focus" = builtins.toFile "nitpicker-is-too-complicated.xml" ''
+
+ '';
+ };
+ };
+
+ firmware = lib'.novaImage "stage0" { gzip = true; } bootDescription;
+
+ in {
+
+ options.genode = with lib; {
+
+ fbDriver = mkOption {
+ default = "vesa";
+ type = types.enum [ "intel" "vesa" ];
+ description = ''
+ Set framebuffer driver.
+ '';
+ };
+
+ guests = mkOption {
+ type = types.attrsOf (types.submodule
+ ({ config, options, name, ... }: {
+ options = {
+
+ config = mkOption {
+ description = ''
+ A specification of the desired configuration of this
+ guest VM, as a NixOS module.
+ '';
+ type = mkOptionType {
+ name = "Toplevel NixOS config";
+ merge = loc: defs:
+ (import "${modulesPath}/../lib/eval-config.nix" {
+ inherit (config'.nixpkgs) system;
+ modules = [
+ "${modulesPath}/virtualisation/virtualbox-image.nix"
+ ] ++ (map (x: x.value) defs);
+ prefix = [ "guests" name ];
+ }).config;
+ };
+ };
+
+ };
+ }));
+ default = { };
+ };
+
+ inputFilter = {
+ extraChargen = mkOption {
+ description =
+ "Dhall expression of the type List Prelude.XML.Type
";
+ type = types.str;
+ default = "${./dhall/qwerty.chargen.dhall}";
+ };
+ };
+
+ };
+
+ config = {
+
+ system.build.genode = {
+ inherit firmware console;
+ config = lib'.runDhallCommand "config.dhall" { }
+ ''dhall > $out <<< "${initConfig}"'';
+
+ xml = lib'.runDhallCommand "config.xml" { }
+ ''${apps'.render-init.program} <<< "${initConfig}" > $out'';
+ };
+
+ boot.loader.grub = {
+ extraEntries = ''
+ menuentry Genode on NOVA {
+ insmod multiboot2
+ insmod gzio
+ multiboot2 /bender
+ module2 /hypervisor hypervisor iommu novpid serial logmem
+ module2 /image.elf.gz image.elf
+ }
+ '';
+
+ extraFiles = {
+ "bender" = "${pkgs'.genodeSources}/tool/boot/bender";
+ "hypervisor" = "${pkgs'.NOVA}/hypervisor-x86_64";
+ "image.elf.gz" = "${firmware}/image.elf.gz";
+ };
+ };
+
+ };
+
+ };
+
+ workman-layout.genode.inputFilter.extraChargen =
+ "${./dhall/workman.chargen.dhall}";
+
+}
diff --git a/nixos-modules/dhall/console.dhall b/nixos-modules/dhall/console.dhall
new file mode 100644
index 0000000..a504af1
--- /dev/null
+++ b/nixos-modules/dhall/console.dhall
@@ -0,0 +1,189 @@
+-- SPDX-License-Identifier: CC0-1.0
+-- TODO: Move routes passed to toChild into the Init
+
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let XML = Prelude.XML
+
+let Init = Genode.Init
+
+let Child = Init.Child
+
+let Resources = Init.Resources
+
+let ServiceRoute = Init.ServiceRoute
+
+in λ(params : { bash : Text, coreutils : Text, path : Text })
+ → let init =
+ Init::{
+ , verbose = True
+ , routes =
+ Prelude.List.map
+ Text
+ Init.ServiceRoute.Type
+ Init.ServiceRoute.parent
+ [ "Nitpicker", "Rtc", "Timer" ]
+ , children = toMap
+ { nit_fb =
+ Child.flat
+ Child.Attributes::{
+ , binary = "nit_fb"
+ , config = Init.Config::{
+ , attributes = toMap
+ { xpos = "10"
+ , ypos = "10"
+ , initial_width = "800"
+ , initial_height = "600"
+ }
+ }
+ , provides = [ "Framebuffer", "Input" ]
+ , resources = Resources::{ ram = Genode.units.MiB 8 }
+ }
+ , terminal =
+ Child.flat
+ Child.Attributes::{
+ , binary = "terminal"
+ , config = Init.Config::{
+ , content =
+ [ XML.element
+ { name = "vfs"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.element
+ { name = "dir"
+ , attributes = toMap { name = "fonts" }
+ , content =
+ [ XML.leaf
+ { name = "fs"
+ , attributes = toMap
+ { label = "fonts" }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ , provides = [ "Terminal" ]
+ , resources = Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 4
+ }
+ , routes =
+ [ ServiceRoute.child "Framebuffer" "nit_fb"
+ , ServiceRoute.child "Input" "nit_fb"
+ , ServiceRoute.parent "File_system"
+ ]
+ }
+ , vfs =
+ Child.flat
+ Child.Attributes::{
+ , binary = "vfs"
+ , config = Init.Config::{
+ , content =
+ [ Prelude.XML.text
+ ''
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ''
+ ]
+ }
+ , provides = [ "File_system" ]
+ , resources = Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 8
+ }
+ , routes =
+ [ Init.ServiceRoute.parent "File_system"
+ , Init.ServiceRoute.child "Terminal" "terminal"
+ ]
+ }
+ , store_rom =
+ Child.flat
+ Child.Attributes::{
+ , binary = "cached_fs_rom"
+ , provides = [ "ROM" ]
+ , resources = Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 4
+ }
+ , routes = [ Init.ServiceRoute.child "File_system" "vfs" ]
+ }
+ , shell =
+ Child.flat
+ Child.Attributes::{
+ , binary = "bash"
+ , config = Genode.Init.Config::{
+ , content =
+ [ Prelude.XML.text
+ ''
+
+
+
+
+
+ ''
+ ]
+ # Prelude.List.map
+ Text
+ XML.Type
+ ( λ(x : Text)
+ → XML.leaf
+ { name = "arg"
+ , attributes = toMap { value = x }
+ }
+ )
+ [ "bash" ]
+ }
+ , exitPropagate = True
+ , resources = Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 8
+ }
+ , routes =
+ [ Init.ServiceRoute.child "File_system" "vfs"
+ , { service =
+ { name = "ROM"
+ , label =
+ Init.LabelSelector.Type.Partial
+ { prefix = Some "/nix/store/"
+ , suffix = None Text
+ }
+ }
+ , route =
+ Init.Route.Type.Child
+ { name = "store_rom"
+ , label = None Text
+ , diag = None Bool
+ }
+ }
+ ]
+ }
+ }
+ }
+
+ in Init.toChild
+ init
+ Init.Attributes::{
+ , routes =
+ [ ServiceRoute.parent "File_system"
+ , ServiceRoute.parent "Nitpicker"
+ , ServiceRoute.parent "Rtc"
+ , ServiceRoute.parent "Timer"
+ ]
+ }
diff --git a/nixos-modules/dhall/intel_fb_drv.dhall b/nixos-modules/dhall/intel_fb_drv.dhall
new file mode 100644
index 0000000..2ecb1b9
--- /dev/null
+++ b/nixos-modules/dhall/intel_fb_drv.dhall
@@ -0,0 +1,23 @@
+let Genode = env:DHALL_GENODE
+
+let Init = Genode.Init
+
+let Child = Init.Child
+
+let ServiceRoute = Init.ServiceRoute
+
+in Child.flat
+ Child.Attributes::{
+ , binary = "intel_fb_drv"
+ , provides = [ "Framebuffer" ]
+ , resources = Init.Resources::{ caps = 256, ram = Genode.units.MiB 48 }
+ , routes =
+ [ ServiceRoute.parent "IO_MEM"
+ , ServiceRoute.parent "IO_PORT"
+ , ServiceRoute.childLabel
+ "Platform"
+ "platform_drv"
+ (None Text)
+ (Some "intel_fb_drv")
+ ]
+ }
diff --git a/nixos-modules/dhall/partition-type b/nixos-modules/dhall/partition-type
new file mode 100644
index 0000000..2cca25d
--- /dev/null
+++ b/nixos-modules/dhall/partition-type
@@ -0,0 +1 @@
+"24b69406-18a1-428d-908e-d21a1437122c"
diff --git a/nixos-modules/dhall/qwerty.chargen.dhall b/nixos-modules/dhall/qwerty.chargen.dhall
new file mode 100644
index 0000000..ad11e92
--- /dev/null
+++ b/nixos-modules/dhall/qwerty.chargen.dhall
@@ -0,0 +1,297 @@
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let XML = Prelude.XML
+
+let Key = < Ascii : Natural | Char : Text | Code : Natural > : Type
+
+let Map =
+ { Type =
+ { keys : Prelude.Map.Type Text Key
+ , mod1 : Bool
+ , mod2 : Bool
+ , mod3 : Bool
+ , mod4 : Bool
+ }
+ , default = { mod1 = False, mod2 = False, mod3 = False, mod4 = False }
+ }
+
+let boolToAttr = λ(_ : Bool) → if _ then "yes" else "no"
+
+let keyToXML =
+ λ(x : Prelude.Map.Entry Text Key)
+ → XML.leaf
+ { name = "key"
+ , attributes =
+ [ merge
+ { Ascii =
+ λ(_ : Natural)
+ → { mapKey = "ascii", mapValue = Prelude.Natural.show _ }
+ , Char = λ(_ : Text) → { mapKey = "char", mapValue = _ }
+ , Code =
+ λ(_ : Natural)
+ → { mapKey = "code", mapValue = Prelude.Natural.show _ }
+ }
+ x.mapValue
+ , { mapKey = "name", mapValue = x.mapKey }
+ ]
+ }
+
+let mapToXML =
+ λ(map : Map.Type)
+ → XML.element
+ { name = "map"
+ , attributes = toMap
+ { mod1 = boolToAttr map.mod1
+ , mod2 = boolToAttr map.mod2
+ , mod3 = boolToAttr map.mod3
+ , mod4 = boolToAttr map.mod4
+ }
+ , content =
+ Prelude.List.map
+ (Prelude.Map.Entry Text Key)
+ XML.Type
+ keyToXML
+ map.keys
+ }
+
+let qwerty =
+ [ Map::{
+ , mod1 = False
+ , mod2 = False
+ , mod3 = False
+ , mod4 = False
+ , keys = toMap
+ { KEY_1 = Key.Code 49
+ , KEY_2 = Key.Code 50
+ , KEY_3 = Key.Code 51
+ , KEY_4 = Key.Code 52
+ , KEY_5 = Key.Code 53
+ , KEY_6 = Key.Code 54
+ , KEY_7 = Key.Code 55
+ , KEY_8 = Key.Code 56
+ , KEY_9 = Key.Code 57
+ , KEY_0 = Key.Code 48
+ , KEY_MINUS = Key.Code 45
+ , KEY_EQUAL = Key.Code 61
+ , KEY_Q = Key.Code 113
+ , KEY_W = Key.Code 119
+ , KEY_E = Key.Code 101
+ , KEY_R = Key.Code 114
+ , KEY_T = Key.Code 116
+ , KEY_Y = Key.Code 121
+ , KEY_U = Key.Code 117
+ , KEY_I = Key.Code 105
+ , KEY_O = Key.Code 111
+ , KEY_P = Key.Code 112
+ , KEY_LEFTBRACE = Key.Code 91
+ , KEY_RIGHTBRACE = Key.Code 93
+ , KEY_A = Key.Code 97
+ , KEY_S = Key.Code 115
+ , KEY_D = Key.Code 100
+ , KEY_F = Key.Code 102
+ , KEY_G = Key.Code 103
+ , KEY_H = Key.Code 104
+ , KEY_J = Key.Code 106
+ , KEY_K = Key.Code 107
+ , KEY_L = Key.Code 108
+ , KEY_SEMICOLON = Key.Code 59
+ , KEY_APOSTROPHE = Key.Code 39
+ , KEY_GRAVE = Key.Code 96
+ , KEY_BACKSLASH = Key.Code 92
+ , KEY_Z = Key.Code 122
+ , KEY_X = Key.Code 120
+ , KEY_C = Key.Code 99
+ , KEY_V = Key.Code 118
+ , KEY_B = Key.Code 98
+ , KEY_N = Key.Code 110
+ , KEY_M = Key.Code 109
+ , KEY_COMMA = Key.Code 44
+ , KEY_DOT = Key.Code 46
+ , KEY_SLASH = Key.Code 47
+ , KEY_KPASTERISK = Key.Code 42
+ , KEY_SPACE = Key.Code 32
+ , KEY_KP7 = Key.Code 55
+ , KEY_KP8 = Key.Code 56
+ , KEY_KP9 = Key.Code 57
+ , KEY_KPMINUS = Key.Code 45
+ , KEY_KP4 = Key.Code 52
+ , KEY_KP5 = Key.Code 53
+ , KEY_KP6 = Key.Code 54
+ , KEY_KPPLUS = Key.Code 43
+ , KEY_KP1 = Key.Code 49
+ , KEY_KP2 = Key.Code 50
+ , KEY_KP3 = Key.Code 51
+ , KEY_KP0 = Key.Code 48
+ , KEY_KPDOT = Key.Code 46
+ , KEY_102ND = Key.Code 60
+ , KEY_KPSLASH = Key.Code 47
+ , KEY_ESC = Key.Ascii 27
+ , KEY_BACKSPACE = Key.Ascii 8
+ , KEY_TAB = Key.Ascii 9
+ , KEY_ENTER = Key.Ascii 10
+ , KEY_KPENTER = Key.Ascii 10
+ , KEY_DELETE = Key.Ascii 127
+ }
+ }
+ , Map::{
+ , mod1 = True
+ , mod2 = False
+ , mod3 = False
+ , mod4 = False
+ , keys = toMap
+ { KEY_1 = Key.Code 33
+ , KEY_2 = Key.Code 64
+ , KEY_3 = Key.Code 35
+ , KEY_4 = Key.Code 36
+ , KEY_5 = Key.Code 37
+ , KEY_6 = Key.Code 94
+ , KEY_7 = Key.Code 38
+ , KEY_8 = Key.Code 42
+ , KEY_9 = Key.Code 40
+ , KEY_0 = Key.Code 41
+ , KEY_MINUS = Key.Code 95
+ , KEY_EQUAL = Key.Code 43
+ , KEY_Q = Key.Code 81
+ , KEY_W = Key.Code 87
+ , KEY_E = Key.Code 69
+ , KEY_R = Key.Code 82
+ , KEY_T = Key.Code 84
+ , KEY_Y = Key.Code 89
+ , KEY_U = Key.Code 85
+ , KEY_I = Key.Code 73
+ , KEY_O = Key.Code 79
+ , KEY_P = Key.Code 80
+ , KEY_LEFTBRACE = Key.Code 123
+ , KEY_RIGHTBRACE = Key.Code 125
+ , KEY_A = Key.Code 65
+ , KEY_S = Key.Code 83
+ , KEY_D = Key.Code 68
+ , KEY_F = Key.Code 70
+ , KEY_G = Key.Code 71
+ , KEY_H = Key.Code 72
+ , KEY_J = Key.Code 74
+ , KEY_K = Key.Code 75
+ , KEY_L = Key.Code 76
+ , KEY_SEMICOLON = Key.Code 58
+ , KEY_APOSTROPHE = Key.Code 34
+ , KEY_GRAVE = Key.Code 126
+ , KEY_BACKSLASH = Key.Code 124
+ , KEY_Z = Key.Code 90
+ , KEY_X = Key.Code 88
+ , KEY_C = Key.Code 67
+ , KEY_V = Key.Code 86
+ , KEY_B = Key.Code 66
+ , KEY_N = Key.Code 78
+ , KEY_M = Key.Code 77
+ , KEY_COMMA = Key.Code 60
+ , KEY_DOT = Key.Code 62
+ , KEY_SLASH = Key.Code 63
+ , KEY_KPASTERISK = Key.Code 42
+ , KEY_KPMINUS = Key.Code 45
+ , KEY_KPPLUS = Key.Code 43
+ , KEY_102ND = Key.Code 62
+ , KEY_KPSLASH = Key.Code 47
+ }
+ }
+ , Map::{
+ , mod1 = False
+ , mod2 = False
+ , mod3 = True
+ , mod4 = False
+ , keys = toMap { KEY_5 = Key.Code 8364, KEY_102ND = Key.Code 124 }
+ }
+ , Map::{
+ , mod1 = False
+ , mod2 = False
+ , mod3 = False
+ , mod4 = True
+ , keys = toMap
+ { KEY_Q = Key.Code 81
+ , KEY_W = Key.Code 87
+ , KEY_E = Key.Code 69
+ , KEY_R = Key.Code 82
+ , KEY_T = Key.Code 84
+ , KEY_Y = Key.Code 89
+ , KEY_U = Key.Code 85
+ , KEY_I = Key.Code 73
+ , KEY_O = Key.Code 79
+ , KEY_P = Key.Code 80
+ , KEY_A = Key.Code 65
+ , KEY_S = Key.Code 83
+ , KEY_D = Key.Code 68
+ , KEY_F = Key.Code 70
+ , KEY_G = Key.Code 71
+ , KEY_H = Key.Code 72
+ , KEY_J = Key.Code 74
+ , KEY_K = Key.Code 75
+ , KEY_L = Key.Code 76
+ , KEY_Z = Key.Code 90
+ , KEY_X = Key.Code 88
+ , KEY_C = Key.Code 67
+ , KEY_V = Key.Code 86
+ , KEY_B = Key.Code 66
+ , KEY_N = Key.Code 78
+ , KEY_M = Key.Code 77
+ }
+ }
+ , Map::{
+ , mod1 = True
+ , mod2 = False
+ , mod3 = False
+ , mod4 = True
+ , keys = toMap
+ { KEY_1 = Key.Code 33
+ , KEY_2 = Key.Code 64
+ , KEY_3 = Key.Code 35
+ , KEY_4 = Key.Code 36
+ , KEY_5 = Key.Code 37
+ , KEY_6 = Key.Code 94
+ , KEY_7 = Key.Code 38
+ , KEY_8 = Key.Code 42
+ , KEY_9 = Key.Code 40
+ , KEY_0 = Key.Code 41
+ , KEY_MINUS = Key.Code 95
+ , KEY_EQUAL = Key.Code 43
+ , KEY_Q = Key.Code 113
+ , KEY_W = Key.Code 119
+ , KEY_E = Key.Code 101
+ , KEY_R = Key.Code 114
+ , KEY_T = Key.Code 116
+ , KEY_Y = Key.Code 121
+ , KEY_U = Key.Code 117
+ , KEY_I = Key.Code 105
+ , KEY_O = Key.Code 111
+ , KEY_P = Key.Code 112
+ , KEY_LEFTBRACE = Key.Code 123
+ , KEY_RIGHTBRACE = Key.Code 125
+ , KEY_A = Key.Code 97
+ , KEY_S = Key.Code 115
+ , KEY_D = Key.Code 100
+ , KEY_F = Key.Code 102
+ , KEY_G = Key.Code 103
+ , KEY_H = Key.Code 104
+ , KEY_J = Key.Code 106
+ , KEY_K = Key.Code 107
+ , KEY_L = Key.Code 108
+ , KEY_SEMICOLON = Key.Code 58
+ , KEY_APOSTROPHE = Key.Code 34
+ , KEY_GRAVE = Key.Code 126
+ , KEY_BACKSLASH = Key.Code 124
+ , KEY_Z = Key.Code 122
+ , KEY_X = Key.Code 120
+ , KEY_C = Key.Code 99
+ , KEY_V = Key.Code 118
+ , KEY_B = Key.Code 98
+ , KEY_N = Key.Code 110
+ , KEY_M = Key.Code 109
+ , KEY_COMMA = Key.Code 60
+ , KEY_DOT = Key.Code 62
+ , KEY_SLASH = Key.Code 63
+ , KEY_102ND = Key.Code 62
+ }
+ }
+ ]
+
+in Prelude.List.map Map.Type XML.Type mapToXML qwerty
diff --git a/nixos-modules/dhall/root.dhall b/nixos-modules/dhall/root.dhall
new file mode 100644
index 0000000..c2e5c5b
--- /dev/null
+++ b/nixos-modules/dhall/root.dhall
@@ -0,0 +1,718 @@
+-- SPDX-License-Identifier: CC0-1.0
+
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let XML = Prelude.XML
+
+let Init = Genode.Init
+
+let Child = Init.Child
+
+let Resources = Init.Resources
+
+let ServiceRoute = Init.ServiceRoute
+
+let Policy = Init.Config.Policy
+
+let DefaultPolicy = Init.Config.DefaultPolicy
+
+let LabelSelector = Init.LabelSelector
+
+let label =
+ λ(label : Text)
+ → { local = label, route = label } : Child.Attributes.Label
+
+let routeLogRom =
+ λ(label : Text) → ServiceRoute.parentLabel "ROM" (Some "log") (Some label)
+
+let rootInit =
+ λ ( params
+ : { fbDriver : Init.Child.Type
+ , guests : Init.Children.Type
+ , inputFilterChargens : List XML.Type
+ , partitionType : Text
+ , wm : Init.Type
+ }
+ )
+ → Init::{
+ , children = toMap
+ { timer =
+ Child.flat
+ Child.Attributes::{
+ , binary = "timer_drv"
+ , provides = [ "Timer" ]
+ }
+ , rtc =
+ Child.flat
+ Child.Attributes::{
+ , binary = "rtc_drv"
+ , provides = [ "Rtc" ]
+ , routes =
+ [ ServiceRoute.parent "IO_PORT"
+ , ServiceRoute.parent "IO_MEM"
+ ]
+ }
+ , acpi_drv =
+ Child.flat
+ Child.Attributes::{
+ , binary = "acpi_drv"
+ , priority = 1
+ , resources = Resources::{
+ , caps = 350
+ , ram = Genode.units.MiB 4
+ }
+ , romReports = [ label "acpi", label "smbios_table" ]
+ , routes = [ ServiceRoute.parent "IO_MEM" ]
+ }
+ , platform_drv =
+ Child.flat
+ Child.Attributes::{
+ , binary = "platform_drv"
+ , resources = Resources::{
+ , caps = 400
+ , ram = Genode.units.MiB 4
+ , constrainPhys = True
+ }
+ , reportRoms = [ label "acpi" ]
+ , romReports = [ label "pci" ]
+ , provides = [ "Acpi", "Platform" ]
+ , routes =
+ [ ServiceRoute.parent "IRQ"
+ , ServiceRoute.parent "IO_MEM"
+ , ServiceRoute.parent "IO_PORT"
+ , ServiceRoute.parentLabel
+ "ROM"
+ (Some "system")
+ (Some "system")
+ ]
+ , config = Init.Config::{
+ , attributes = toMap { system = "yes" }
+ , content =
+ let PciPolicy/Type =
+ { labelSuffix : Text, pciClass : Text }
+
+ in [ XML.text
+ ''
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ''
+ ]
+ # Prelude.List.map
+ PciPolicy/Type
+ XML.Type
+ ( λ(policy : PciPolicy/Type)
+ → XML.element
+ { name = "policy"
+ , attributes = toMap
+ { label_suffix = policy.labelSuffix }
+ , content =
+ [ XML.leaf
+ { name = "pci"
+ , attributes = toMap
+ { class = policy.pciClass }
+ }
+ ]
+ }
+ )
+ [ { labelSuffix = "ahci_drv"
+ , pciClass = "AHCI"
+ }
+ , { labelSuffix = "nic_drv"
+ , pciClass = "ETHERNET"
+ }
+ , { labelSuffix = "usb_drv", pciClass = "USB" }
+ , { labelSuffix = "vesa_fb_drv"
+ , pciClass = "VGA"
+ }
+ ]
+ }
+ }
+ , framebuffer = params.fbDriver
+ , input_filter =
+ Child.flat
+ Child.Attributes::{
+ , binary = "input_filter"
+ , config =
+ let key =
+ λ(name : Text)
+ → XML.leaf
+ { name = "key"
+ , attributes = toMap { name = name }
+ }
+
+ let remap =
+ λ(name : Text)
+ → λ(to : Text)
+ → XML.leaf
+ { name = "key"
+ , attributes = toMap { name = name, to = to }
+ }
+
+ in Init.Config::{
+ , content =
+ [ XML.leaf
+ { name = "input"
+ , attributes = toMap { label = "ps2" }
+ }
+ , XML.leaf
+ { name = "input"
+ , attributes = toMap { label = "usb" }
+ }
+ , XML.element
+ { name = "output"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.element
+ { name = "chargen"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.element
+ { name = "remap"
+ , attributes =
+ XML.emptyAttributes
+ , content =
+ [ remap
+ "KEY_LEFTMETA"
+ "KEY_SCREEN"
+ , XML.element
+ { name = "merge"
+ , attributes =
+ XML.emptyAttributes
+ , content =
+ [ XML.leaf
+ { name = "input"
+ , attributes = toMap
+ { name = "ps2" }
+ }
+ , XML.leaf
+ { name = "input"
+ , attributes = toMap
+ { name = "usb" }
+ }
+ ]
+ }
+ ]
+ }
+ , XML.element
+ { name = "mod1"
+ , attributes =
+ XML.emptyAttributes
+ , content =
+ [ key "KEY_LEFTSHIFT"
+ , key "KEY_RIGHTSHIFT"
+ ]
+ }
+ , XML.element
+ { name = "mod2"
+ , attributes =
+ XML.emptyAttributes
+ , content =
+ [ key "KEY_LEFTCTRL"
+ , key "KEY_RIGHTCTRL"
+ ]
+ }
+ , XML.element
+ { name = "mod3"
+ , attributes =
+ XML.emptyAttributes
+ , content =
+ [ key "KEY_RIGHTALT" ]
+ }
+ ]
+ # params.inputFilterChargens
+ }
+ ]
+ }
+ ]
+ }
+ , provides = [ "Input" ]
+ , routes =
+ [ ServiceRoute.parentLabel
+ "ROM"
+ (Some "config")
+ (Some "config -> input_filter.config")
+ , ServiceRoute.childLabel
+ "Input"
+ "ps2_drv"
+ (Some "ps2")
+ (None Text)
+ , ServiceRoute.childLabel
+ "Input"
+ "usb_drv"
+ (Some "usb")
+ (None Text)
+ ]
+ }
+ , ps2_drv =
+ Child.flat
+ Child.Attributes::{
+ , binary = "ps2_drv"
+ , provides = [ "Input" ]
+ , routes =
+ [ ServiceRoute.childLabel
+ "Platform"
+ "platform_drv"
+ (None Text)
+ (Some "ps2_drv")
+ ]
+ }
+ , usb_drv =
+ Child.flat
+ Child.Attributes::{
+ , binary = "usb_drv"
+ , config = Init.Config::{
+ , attributes = toMap
+ { uhci = "yes"
+ , ohci = "yes"
+ , ehci = "yes"
+ , xhci = "yes"
+ , bios_handoff = "yes"
+ }
+ , content =
+ [ XML.leaf
+ { name = "hid", attributes = XML.emptyAttributes }
+ ]
+ }
+ , provides = [ "Input" ]
+ , resources = Init.Resources::{
+ , caps = 128
+ , ram = Genode.units.MiB 12
+ }
+ , routes =
+ [ ServiceRoute.childLabel
+ "Platform"
+ "platform_drv"
+ (None Text)
+ (Some "usb_drv")
+ ]
+ }
+ , wm =
+ Init.toChild
+ params.wm
+ Init.Attributes::{
+ , provides = [ "Nitpicker", "Report", "ROM" ]
+ , romReports = [ label "clipboard", label "shape" ]
+ , routes =
+ [ ServiceRoute.child "Framebuffer" "framebuffer"
+ , ServiceRoute.child "Input" "input_filter"
+ ]
+ }
+ , fonts_fs =
+ Child.flat
+ Child.Attributes::{
+ , binary = "vfs"
+ , config = Init.Config::{
+ , content =
+ [ XML.element
+ { name = "vfs"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.leaf
+ { name = "rom"
+ , attributes = toMap
+ { name = "Inconsolata.ttf" }
+ }
+ , XML.element
+ { name = "dir"
+ , attributes = toMap { name = "fonts" }
+ , content =
+ [ XML.element
+ { name = "dir"
+ , attributes = toMap { name = "title" }
+ , content =
+ [ XML.leaf
+ { name = "ttf"
+ , attributes = toMap
+ { name = "regular"
+ , path = "/Inconsolata.ttf"
+ , size_px = "12"
+ }
+ }
+ ]
+ }
+ , XML.element
+ { name = "dir"
+ , attributes = toMap { name = "text" }
+ , content =
+ [ XML.leaf
+ { name = "ttf"
+ , attributes = toMap
+ { name = "regular"
+ , path = "/Inconsolata.ttf"
+ , size_px = "12"
+ }
+ }
+ ]
+ }
+ , XML.element
+ { name = "dir"
+ , attributes = toMap
+ { name = "annotation" }
+ , content =
+ [ XML.leaf
+ { name = "ttf"
+ , attributes = toMap
+ { name = "regular"
+ , path = "/Inconsolata.ttf"
+ , size_px = "12"
+ }
+ }
+ ]
+ }
+ , XML.element
+ { name = "dir"
+ , attributes = toMap
+ { name = "monospace" }
+ , content =
+ [ XML.leaf
+ { name = "ttf"
+ , attributes = toMap
+ { name = "regular"
+ , path = "/Inconsolata.ttf"
+ , size_px = "12"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ , defaultPolicy = Some DefaultPolicy::{
+ , attributes = toMap { root = "/fonts" }
+ }
+ }
+ , provides = [ "File_system" ]
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 12
+ }
+ , routes = [ ServiceRoute.child "Block" "block_router" ]
+ }
+ , nit_fb =
+ Child.flat
+ Child.Attributes::{
+ , binary = "nit_fb"
+ , config = Init.Config::{
+ , attributes = toMap
+ { xpos = "600", width = "600", height = "768" }
+ }
+ , provides = [ "Framebuffer", "Input" ]
+ , resources = Resources::{ ram = Genode.units.MiB 8 }
+ , routes =
+ [ ServiceRoute.childLabel
+ "Nitpicker"
+ "wm"
+ (None Text)
+ (Some "log")
+ ]
+ }
+ , terminal =
+ Child.flat
+ Child.Attributes::{
+ , binary = "terminal"
+ , config = Init.Config::{
+ , content =
+ [ XML.element
+ { name = "vfs"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.element
+ { name = "dir"
+ , attributes = toMap { name = "fonts" }
+ , content =
+ [ XML.leaf
+ { name = "fs"
+ , attributes = toMap { label = "fonts" }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ , provides = [ "Terminal" ]
+ , resources = Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 4
+ }
+ , routes =
+ [ ServiceRoute.child "Framebuffer" "nit_fb"
+ , ServiceRoute.child "Input" "nit_fb"
+ , ServiceRoute.child "File_system" "fonts_fs"
+ ]
+ }
+ , terminal_log =
+ Child.flat
+ Child.Attributes::{
+ , binary = "terminal_log"
+ , provides = [ "LOG" ]
+ , routes = [ ServiceRoute.child "Terminal" "terminal" ]
+ }
+ , log_core =
+ Child.flat
+ Child.Attributes::{
+ , binary = "log_core"
+ , routes =
+ [ routeLogRom "core_log"
+ , ServiceRoute.childLabel
+ "LOG"
+ "terminal_log"
+ (Some "log")
+ (Some "core")
+ ]
+ }
+ , log_kernel =
+ Child.flat
+ Child.Attributes::{
+ , binary = "log_core"
+ , routes =
+ [ routeLogRom "kernel_log"
+ , ServiceRoute.childLabel
+ "LOG"
+ "terminal_log"
+ (Some "log")
+ (Some "kernel")
+ ]
+ }
+ , block =
+ Child.flat
+ Child.Attributes::{
+ , binary = "ahci_drv"
+ , config = Init.Config::{
+ , defaultPolicy = Some DefaultPolicy::{
+ , attributes = toMap { device = "0", writeable = "yes" }
+ }
+ }
+ , provides = [ "Block" ]
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 10
+ }
+ , routes =
+ [ ServiceRoute.childLabel
+ "Platform"
+ "platform_drv"
+ (None Text)
+ (Some "ahci_drv")
+ ]
+ }
+ , block_partitions =
+ Child.flat
+ Child.Attributes::{
+ , binary = "part_block"
+ , config = Init.Config::{
+ , content =
+ Prelude.List.map
+ Natural
+ XML.Type
+ ( λ(i : Natural)
+ → XML.leaf
+ { name = "policy"
+ , attributes =
+ let partition =
+ Prelude.Natural.show (i + 1)
+
+ in toMap
+ { label_suffix = " ${partition}"
+ , partition = partition
+ , writeable = "yes"
+ }
+ }
+ )
+ (Prelude.Natural.enumerate 128)
+ # [ XML.leaf
+ { name = "report"
+ , attributes = toMap { partitions = "yes" }
+ }
+ ]
+ }
+ , resources = Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 8
+ }
+ , provides = [ "Block" ]
+ , routes =
+ [ ServiceRoute.child "Block" "block"
+ , ServiceRoute.child "Report" "block_router"
+ ]
+ }
+ , block_router =
+ Child.flat
+ Child.Attributes::{
+ , binary = "block_router"
+ , config = Init.Config::{
+ , attributes = toMap { verbose = "yes" }
+ , content =
+ [ XML.element
+ { name = "default-policy"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.leaf
+ { name = "partition"
+ , attributes = toMap
+ { type = params.partitionType
+ , writeable = "yes"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ , resources = Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 8
+ }
+ , provides = [ "Block", "Report" ]
+ , routes = [ ServiceRoute.child "Block" "block_partitions" ]
+ }
+ , file_system =
+ Child.flat
+ Child.Attributes::{
+ , binary = "vfs"
+ , config = Init.Config::{
+ , content =
+ [ XML.element
+ { name = "vfs"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.element
+ { name = "dir"
+ , attributes = toMap { name = "ext2" }
+ , content =
+ [ XML.leaf
+ { name = "rump"
+ , attributes = toMap
+ { fs = "ext2fs"
+ , writeable = "yes"
+ , ram = "8M"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ , policies =
+ [ Policy::{
+ , label = LabelSelector.suffix "nix/store"
+ , attributes = toMap
+ { root = "/ext2/nix/store", writeable = "no" }
+ }
+ , Policy::{
+ , label = LabelSelector.prefix "chroot"
+ , attributes = toMap
+ { root = "/ext2", writeable = "yes" }
+ }
+ , Policy::{
+ , label = LabelSelector.prefix "init -> console"
+ , attributes = toMap { root = "/", writeable = "yes" }
+ }
+ ]
+ }
+ , provides = [ "File_system" ]
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 12
+ }
+ , routes = [ ServiceRoute.child "Block" "block_router" ]
+ }
+ , chroot =
+ Child.flat
+ Child.Attributes::{
+ , binary = "chroot"
+ , config = Init.Config::{
+ , defaultPolicy = Some DefaultPolicy::{
+ , attributes = toMap { writeable = "yes" }
+ }
+ }
+ , provides = [ "File_system" ]
+ , routes = [ ServiceRoute.child "File_system" "file_system" ]
+ }
+ , nic_drv =
+ Child.flat
+ Child.Attributes::{
+ , binary = "ipxe_nic_drv"
+ , provides = [ "Nic" ]
+ , resources = Init.Resources::{
+ , caps = 128
+ , ram = Genode.units.MiB 4
+ }
+ , routes =
+ [ ServiceRoute.childLabel
+ "Platform"
+ "platform_drv"
+ (None Text)
+ (Some "nic_drv")
+ ]
+ }
+ , init =
+ Init.toChild
+ Init::{ children = params.guests }
+ Init.Attributes::{
+ , routes =
+ [ ServiceRoute.parent "VM"
+ , ServiceRoute.child "Nitpicker" "wm"
+ , { service =
+ { name = "File_system"
+ , label = LabelSelector.last "fonts"
+ }
+ , route =
+ Init.Route.Type.Child
+ { name = "fonts_fs"
+ , label = None Text
+ , diag = None Bool
+ }
+ }
+ , { service =
+ { name = "File_system"
+ , label = LabelSelector.suffix "nix/store"
+ }
+ , route =
+ Init.Route.Type.Child
+ { name = "file_system"
+ , label = Some "nix/store"
+ , diag = None Bool
+ }
+ }
+ , { service =
+ { name = "File_system"
+ , label = LabelSelector.prefix "console"
+ }
+ , route =
+ Init.Route.Type.Child
+ { name = "file_system"
+ , label = None Text
+ , diag = None Bool
+ }
+ }
+ , ServiceRoute.child "File_system" "chroot"
+ , ServiceRoute.child "Nic" "nic_drv"
+ , ServiceRoute.child "Rtc" "rtc"
+ , ServiceRoute.parentLabel
+ "ROM"
+ (Some "platform_info")
+ (Some "platform_info")
+ , ServiceRoute.child "Report" "_report_rom"
+ ]
+ }
+ }
+ , routes = [ ServiceRoute.child "Timer" "timer" ]
+ }
+
+in rootInit
diff --git a/nixos-modules/dhall/show_input.dhall b/nixos-modules/dhall/show_input.dhall
new file mode 100644
index 0000000..3ad9699
--- /dev/null
+++ b/nixos-modules/dhall/show_input.dhall
@@ -0,0 +1,43 @@
+-- SPDX-License-Identifier: CC0-1.0
+
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let XML = Prelude.XML
+
+let Init = Genode.Init
+
+let Child = Init.Child
+
+let Resources = Init.Resources
+
+let ServiceRoute = Init.ServiceRoute
+
+in Child.flat
+ Child.Attributes::{
+ , binary = "show_input"
+ , config = Init.Config::{
+ , content =
+ [ XML.element
+ { name = "vfs"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.element
+ { name = "dir"
+ , attributes = toMap { name = "fonts" }
+ , content =
+ [ XML.leaf
+ { name = "fs"
+ , attributes = toMap { label = "fonts" }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ , resources = Resources::{ ram = Genode.units.MiB 32 }
+ , routes =
+ [ ServiceRoute.parent "File_system", ServiceRoute.parent "Nitpicker" ]
+ }
diff --git a/nixos-modules/dhall/vbox-guest.dhall b/nixos-modules/dhall/vbox-guest.dhall
new file mode 100644
index 0000000..bd6bb31
--- /dev/null
+++ b/nixos-modules/dhall/vbox-guest.dhall
@@ -0,0 +1,163 @@
+-- SPDX-License-Identifier: CC0-1.0
+
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let XML = Prelude.XML
+
+let Init = Genode.Init
+
+let Child = Init.Child
+
+let Resources = Init.Resources
+
+let ServiceRoute = Init.ServiceRoute
+
+let Vfs/inline =
+ λ(name : Text)
+ → λ(body : Text)
+ → XML.element
+ { name = "inline"
+ , attributes = toMap { name = name }
+ , content = [ XML.text body ]
+ }
+
+let toVbox =
+ λ ( params
+ : { vdiFilename : Text
+ , vdiPkg : Text
+ , vdiUuid : Text
+ , memorySize : Natural
+ , vmName : Text
+ }
+ )
+ → let vboxConfig =
+ ''
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ''
+
+ in Child.flat
+ Child.Attributes::{
+ , binary = "virtualbox5"
+ , config = Init.Config::{
+ , attributes = toMap
+ { vbox_file = "machine.vbox", vm_name = params.vmName }
+ , content =
+ [ XML.leaf
+ { name = "libc"
+ , attributes = toMap
+ { stdout = "/dev/log"
+ , stderr = "/dev/log"
+ , rtc = "/dev/rtc"
+ }
+ }
+ , XML.element
+ { name = "vfs"
+ , attributes = XML.emptyAttributes
+ , content =
+ let tag =
+ λ(name : Text)
+ → XML.leaf
+ { name = name
+ , attributes = XML.emptyAttributes
+ }
+
+ in [ Vfs/inline "machine.vbox" vboxConfig
+ , XML.element
+ { name = "dir"
+ , attributes = toMap { name = "dev" }
+ , content = [ tag "log", tag "rtc" ]
+ }
+ , XML.leaf
+ { name = "fs"
+ , attributes = toMap { writeable = "yes" }
+ }
+ , XML.element
+ { name = "import"
+ , attributes = toMap { overwrite = "no" }
+ , content =
+ [ XML.leaf
+ { name = "fs"
+ , attributes = toMap
+ { label = "nix/store"
+ , root = "${params.vdiPkg}"
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ , resources = Resources::{
+ , caps = 1024
+ , ram =
+ Genode.units.MiB 128 + Genode.units.MiB params.memorySize
+ }
+ , routes =
+ [ ServiceRoute.parent "File_system"
+ , ServiceRoute.parent "Nic"
+ , ServiceRoute.parent "Nitpicker"
+ , ServiceRoute.parent "Rtc"
+ , ServiceRoute.parent "Timer"
+ , ServiceRoute.parent "VM"
+ , ServiceRoute.parent "Report"
+ , ServiceRoute.parentLabel
+ "ROM"
+ (Some "platform_info")
+ (Some "platform_info")
+ ]
+ }
+
+in toVbox
diff --git a/nixos-modules/dhall/vesa_fb_drv.dhall b/nixos-modules/dhall/vesa_fb_drv.dhall
new file mode 100644
index 0000000..50c7daa
--- /dev/null
+++ b/nixos-modules/dhall/vesa_fb_drv.dhall
@@ -0,0 +1,27 @@
+let Genode = env:DHALL_GENODE
+
+let ServiceRoute = Genode.Init.ServiceRoute
+
+let Child = Genode.Init.Child
+
+in Child.flat
+ Child.Attributes::{
+ , binary = "vesa_fb_drv"
+ , config = Genode.Init.Config::{
+ , attributes = toMap { width = "1024", height = "768" }
+ }
+ , provides = [ "Framebuffer" ]
+ , resources = Genode.Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 16
+ }
+ , routes =
+ [ ServiceRoute.parent "IO_MEM"
+ , ServiceRoute.parent "IO_PORT"
+ , ServiceRoute.childLabel
+ "Platform"
+ "platform_drv"
+ (None Text)
+ (Some "vesa_fb_drv")
+ ]
+ }
diff --git a/nixos-modules/dhall/wm.dhall b/nixos-modules/dhall/wm.dhall
new file mode 100644
index 0000000..02aee6e
--- /dev/null
+++ b/nixos-modules/dhall/wm.dhall
@@ -0,0 +1,237 @@
+-- SPDX-License-Identifier: CC0-1.0
+
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let XML = Prelude.XML
+
+let Init = Genode.Init
+
+let Child = Init.Child
+
+let Resources = Init.Resources
+
+let ServiceRoute = Init.ServiceRoute
+
+let Policy = Init.Config.Policy
+
+let DefaultPolicy = Init.Config.DefaultPolicy
+
+let LabelSelector = Init.LabelSelector
+
+let label =
+ λ(label : Text)
+ → { local = label, route = label } : Child.Attributes.Label
+
+in Init::{
+ , children = toMap
+ { nitpicker =
+ Child.flat
+ Child.Attributes::{
+ , binary = "nitpicker"
+ , config = Init.Config::{
+ , attributes = toMap { focus = "rom" }
+ , content =
+ [ XML.text
+ ''
+
+
+
+
+
+
+ ''
+ ]
+ , policies =
+ [ Policy::{
+ , label = LabelSelector.prefix "pointer"
+ , attributes = toMap { domain = "pointer" }
+ }
+ , Policy::{
+ , label = LabelSelector.suffix "-> decorator"
+ , attributes = toMap { domain = "decorator" }
+ }
+ , Policy::{
+ , label = LabelSelector.prefix "wm"
+ , attributes = toMap { domain = "desktop" }
+ }
+ , Policy::{
+ , label = LabelSelector.label "backdrop"
+ , attributes = toMap { domain = "backdrop" }
+ }
+ ]
+ , defaultPolicy = Some DefaultPolicy::{
+ , attributes = toMap { domain = "default" }
+ }
+ }
+ , provides = [ "Nitpicker" ]
+ , resources = Resources::{ caps = 256, ram = Genode.units.MiB 64 }
+ , routes =
+ [ ServiceRoute.parent "Framebuffer"
+ , ServiceRoute.parent "Input"
+ ]
+ }
+ , pointer =
+ Child.flat
+ Child.Attributes::{
+ , binary = "pointer"
+ , routes = [ ServiceRoute.child "Nitpicker" "nitpicker" ]
+ }
+ , wm =
+ Child.flat
+ Child.Attributes::{
+ , binary = "wm"
+ , config = Init.Config::{
+ , policies =
+ [ Policy::{
+ , attributes = toMap { role = "decorator" }
+ , label = LabelSelector.prefix "decorator"
+ }
+ , Policy::{
+ , attributes = toMap { role = "layouter" }
+ , label = LabelSelector.prefix "layouter"
+ }
+ ]
+ , defaultPolicy = Some DefaultPolicy::{=}
+ }
+ , provides = [ "Nitpicker", "Report", "ROM" ]
+ , reportRoms = [ label "focus", label "resize_request" ]
+ , romReports =
+ [ label "focus_request"
+ , label "pointer"
+ , label "shape"
+ , label "window_list"
+ ]
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 8
+ }
+ , routes =
+ [ ServiceRoute.childLabel
+ "Nitpicker"
+ "nitpicker"
+ (Some "")
+ (Some "focus")
+ , ServiceRoute.child "Nitpicker" "nitpicker"
+ , ServiceRoute.parentLabel
+ "Report"
+ (Some "clipboard")
+ (Some "clipboard")
+ , ServiceRoute.parentLabel
+ "Report"
+ (Some "shape")
+ (Some "shape")
+ ]
+ }
+ , layouter =
+ Child.flat
+ Child.Attributes::{
+ , binary = "window_layouter"
+ , config = Init.Config::{
+ , attributes = toMap { rules = "rom" }
+ , content =
+ [ XML.text
+ ''
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ''
+ ]
+ }
+ , provides = [ "Nitpicker", "Report", "ROM" ]
+ , romReports =
+ [ label "focus"
+ , label "resize_request"
+ , label "rules"
+ , label "window_layout"
+ ]
+ , reportRoms =
+ [ label "decorator_margins"
+ , label "focus_request"
+ , label "hover"
+ , label "rules"
+ , label "shape"
+ , label "window_list"
+ ]
+ , resources = Init.Resources::{
+ , caps = 256
+ , ram = Genode.units.MiB 8
+ }
+ , routes = [ ServiceRoute.child "Nitpicker" "wm" ]
+ }
+ , decorator =
+ Child.flat
+ Child.Attributes::{
+ , binary = "decorator"
+ , config = Init.Config::{
+ , content =
+ [ XML.element
+ { name = "controls"
+ , attributes = XML.emptyAttributes
+ , content =
+ [ XML.leaf
+ { name = "maximizer"
+ , attributes = XML.emptyAttributes
+ }
+ , XML.leaf
+ { name = "title", attributes = XML.emptyAttributes }
+ ]
+ }
+ ]
+ , defaultPolicy = Some DefaultPolicy::{=}
+ }
+ , provides = [ "Nitpicker", "Report", "ROM" ]
+ , reportRoms = [ label "window_layout", label "pointer" ]
+ , romReports = [ label "decorator_margins", label "hover" ]
+ , resources = Init.Resources::{
+ , caps = 128
+ , ram = Genode.units.MiB 12
+ }
+ , routes = [ ServiceRoute.child "Nitpicker" "wm" ]
+ }
+ }
+ , routes = [ ServiceRoute.parent "Timer" ]
+ , services =
+ [ ServiceRoute.child "Nitpicker" "wm"
+ , ServiceRoute.child "Report" "wm"
+ , ServiceRoute.child "ROM" "wm"
+ ]
+ }
diff --git a/nixos-modules/dhall/workman.chargen.dhall b/nixos-modules/dhall/workman.chargen.dhall
new file mode 100644
index 0000000..fa83045
--- /dev/null
+++ b/nixos-modules/dhall/workman.chargen.dhall
@@ -0,0 +1,245 @@
+let Genode = env:DHALL_GENODE
+
+let Prelude = Genode.Prelude
+
+let XML = Prelude.XML
+
+let Key = < Ascii : Natural | Char : Text | Code : Natural > : Type
+
+let Map =
+ { Type =
+ { keys : Prelude.Map.Type Text Key
+ , mod1 : Bool
+ , mod2 : Bool
+ , mod3 : Bool
+ , mod4 : Bool
+ }
+ , default = { mod1 = False, mod2 = False, mod3 = False, mod4 = False }
+ }
+
+let boolToAttr = λ(_ : Bool) → if _ then "yes" else "no"
+
+let keyToXML =
+ λ(x : Prelude.Map.Entry Text Key)
+ → XML.leaf
+ { name = "key"
+ , attributes =
+ [ merge
+ { Ascii =
+ λ(_ : Natural)
+ → { mapKey = "ascii", mapValue = Prelude.Natural.show _ }
+ , Char = λ(_ : Text) → { mapKey = "char", mapValue = _ }
+ , Code =
+ λ(_ : Natural)
+ → { mapKey = "code", mapValue = Prelude.Natural.show _ }
+ }
+ x.mapValue
+ , { mapKey = "name", mapValue = x.mapKey }
+ ]
+ }
+
+let mapToXML =
+ λ(map : Map.Type)
+ → XML.element
+ { name = "map"
+ , attributes = toMap
+ { mod1 = boolToAttr map.mod1
+ , mod2 = boolToAttr map.mod2
+ , mod3 = boolToAttr map.mod3
+ , mod4 = boolToAttr map.mod4
+ }
+ , content =
+ Prelude.List.map
+ (Prelude.Map.Entry Text Key)
+ XML.Type
+ keyToXML
+ map.keys
+ }
+
+let workman =
+ [ Map::{
+ , keys = toMap
+ { KEY_ESC = Key.Ascii 27
+ , KEY_1 = Key.Char "1"
+ , KEY_2 = Key.Char "2"
+ , KEY_3 = Key.Char "3"
+ , KEY_4 = Key.Char "4"
+ , KEY_5 = Key.Char "5"
+ , KEY_6 = Key.Char "6"
+ , KEY_7 = Key.Char "7"
+ , KEY_8 = Key.Char "8"
+ , KEY_9 = Key.Char "9"
+ , KEY_0 = Key.Char "0"
+ , KEY_MINUS = Key.Char "-"
+ , KEY_EQUAL = Key.Char "="
+ , KEY_BACKSPACE = Key.Ascii 8
+ , KEY_TAB = Key.Ascii 9
+ , KEY_Q = Key.Char "q"
+ , KEY_W = Key.Char "d"
+ , KEY_E = Key.Char "r"
+ , KEY_R = Key.Char "w"
+ , KEY_T = Key.Char "b"
+ , KEY_Y = Key.Char "j"
+ , KEY_U = Key.Char "f"
+ , KEY_I = Key.Char "u"
+ , KEY_O = Key.Char "p"
+ , KEY_P = Key.Char ";"
+ , KEY_LEFTBRACE = Key.Char "["
+ , KEY_RIGHTBRACE = Key.Char "]"
+ , KEY_ENTER = Key.Ascii 10
+ , KEY_A = Key.Char "a"
+ , KEY_S = Key.Char "s"
+ , KEY_D = Key.Char "h"
+ , KEY_F = Key.Char "t"
+ , KEY_G = Key.Char "g"
+ , KEY_H = Key.Char "y"
+ , KEY_J = Key.Char "n"
+ , KEY_K = Key.Char "e"
+ , KEY_L = Key.Char "o"
+ , KEY_SEMICOLON = Key.Char "i"
+ , KEY_APOSTROPHE = Key.Char "'"
+ , KEY_GRAVE = Key.Char "`"
+ , KEY_BACKSLASH = Key.Ascii 92
+ , KEY_Z = Key.Char "z"
+ , KEY_X = Key.Char "x"
+ , KEY_C = Key.Char "m"
+ , KEY_V = Key.Char "c"
+ , KEY_B = Key.Char "v"
+ , KEY_N = Key.Char "k"
+ , KEY_M = Key.Char "l"
+ , KEY_COMMA = Key.Char ","
+ , KEY_DOT = Key.Char "."
+ , KEY_SLASH = Key.Char "/"
+ , KEY_SPACE = Key.Char " "
+ , KEY_KP7 = Key.Char "7"
+ , KEY_KP8 = Key.Char "8"
+ , KEY_KP9 = Key.Char "9"
+ , KEY_KPMINUS = Key.Char "-"
+ , KEY_KP4 = Key.Char "4"
+ , KEY_KP5 = Key.Char "5"
+ , KEY_KP6 = Key.Char "6"
+ , KEY_KPPLUS = Key.Char "+"
+ , KEY_KP1 = Key.Char "1"
+ , KEY_KP2 = Key.Char "2"
+ , KEY_KP3 = Key.Char "3"
+ , KEY_KP0 = Key.Char "0"
+ , KEY_KPDOT = Key.Char "."
+ , KEY_KPENTER = Key.Ascii 10
+ , KEY_KPSLASH = Key.Char "/"
+ }
+ }
+ , Map::{
+ , mod1 = True
+ , keys = toMap
+ { KEY_1 = Key.Char "!"
+ , KEY_2 = Key.Char "@"
+ , KEY_3 = Key.Char "#"
+ , KEY_4 = Key.Char "\$"
+ , KEY_5 = Key.Char "%"
+ , KEY_6 = Key.Char "^"
+ , KEY_7 = Key.Ascii 38
+ , KEY_8 = Key.Char "*"
+ , KEY_9 = Key.Char "("
+ , KEY_0 = Key.Char ")"
+ , KEY_MINUS = Key.Char "_"
+ , KEY_EQUAL = Key.Char "+"
+ , KEY_Q = Key.Char "Q"
+ , KEY_W = Key.Char "D"
+ , KEY_E = Key.Char "R"
+ , KEY_R = Key.Char "W"
+ , KEY_T = Key.Char "B"
+ , KEY_Y = Key.Char "J"
+ , KEY_U = Key.Char "F"
+ , KEY_I = Key.Char "U"
+ , KEY_O = Key.Char "P"
+ , KEY_P = Key.Char ":"
+ , KEY_LEFTBRACE = Key.Char "{"
+ , KEY_RIGHTBRACE = Key.Char "}"
+ , KEY_A = Key.Char "A"
+ , KEY_S = Key.Char "S"
+ , KEY_D = Key.Char "H"
+ , KEY_F = Key.Char "T"
+ , KEY_G = Key.Char "G"
+ , KEY_H = Key.Char "Y"
+ , KEY_J = Key.Char "N"
+ , KEY_K = Key.Char "E"
+ , KEY_L = Key.Char "O"
+ , KEY_SEMICOLON = Key.Char "I"
+ , KEY_APOSTROPHE = Key.Ascii 34
+ , KEY_GRAVE = Key.Char "~"
+ , KEY_BACKSLASH = Key.Char "|"
+ , KEY_Z = Key.Char "Z"
+ , KEY_X = Key.Char "X"
+ , KEY_C = Key.Char "M"
+ , KEY_V = Key.Char "C"
+ , KEY_B = Key.Char "V"
+ , KEY_N = Key.Char "K"
+ , KEY_M = Key.Char "L"
+ , KEY_COMMA = Key.Ascii 60
+ , KEY_DOT = Key.Ascii 62
+ , KEY_SLASH = Key.Char "?"
+ }
+ }
+ , Map::{
+ , mod2 = True
+ , keys = toMap
+ { KEY_A = Key.Ascii 1
+ , KEY_B = Key.Ascii 22
+ , KEY_C = Key.Ascii 13
+ , KEY_D = Key.Ascii 8
+ , KEY_E = Key.Ascii 18
+ , KEY_F = Key.Ascii 20
+ , KEY_G = Key.Ascii 7
+ , KEY_H = Key.Ascii 25
+ , KEY_I = Key.Ascii 21
+ , KEY_J = Key.Ascii 14
+ , KEY_K = Key.Ascii 5
+ , KEY_L = Key.Ascii 15
+ , KEY_M = Key.Ascii 12
+ , KEY_N = Key.Ascii 11
+ , KEY_O = Key.Ascii 16
+ , KEY_P = Key.Ascii 9
+ , KEY_Q = Key.Ascii 17
+ , KEY_R = Key.Ascii 23
+ , KEY_S = Key.Ascii 19
+ , KEY_T = Key.Ascii 2
+ , KEY_U = Key.Ascii 6
+ , KEY_V = Key.Ascii 3
+ , KEY_W = Key.Ascii 4
+ , KEY_X = Key.Ascii 24
+ , KEY_Y = Key.Ascii 10
+ , KEY_Z = Key.Ascii 26
+ }
+ }
+ , Map::{
+ , mod3 = True
+ , keys = toMap
+ { KEY_4 = Key.Code 8364
+ , KEY_A = Key.Code 228
+ , KEY_S = Key.Code 223
+ , KEY_I = Key.Code 252
+ , KEY_DOT = Key.Code 8230
+ , KEY_K = Key.Code 235
+ , KEY_C = Key.Code 181
+ , KEY_L = Key.Code 246
+ }
+ }
+ , Map::{
+ , mod1 = True
+ , mod3 = True
+ , keys = toMap
+ { KEY_0 = Key.Code 8320
+ , KEY_1 = Key.Code 8321
+ , KEY_2 = Key.Code 8322
+ , KEY_3 = Key.Code 8323
+ , KEY_4 = Key.Code 8324
+ , KEY_5 = Key.Code 8325
+ , KEY_6 = Key.Code 8326
+ , KEY_7 = Key.Code 8327
+ , KEY_8 = Key.Code 8328
+ , KEY_9 = Key.Code 8329
+ }
+ }
+ ]
+
+in Prelude.List.map Map.Type XML.Type mapToXML workman