let Genode =
        env:DHALL_GENODE
      ? https://git.sr.ht/~ehmry/dhall-genode/blob/master/package.dhall sha256:62d5c59808ca94a903497469be41f17d0022a44b3049f156ae2ea30b3a0499c3

let drivers =
      Genode.Init::{
      , services =
          [ Genode.ServiceRoute.child "Framebuffer" "dynamic"
          , Genode.ServiceRoute.child "Block" "dynamic"
          , Genode.ServiceRoute.child "Usb" "usb_drv"
          , Genode.ServiceRoute.child "Platform" "platform_drv"
          , Genode.ServiceRoute.child "Input" "input_filter"
          ]
      , children =
          toMap
            { report_rom =
                Genode.Init.Start::{
                , binary = "report_rom"
                , resources = { caps = 96, ram = Genode.units.MiB 2 }
                , provides = [ "ROM", "Report" ]
                , config =
                    Some
                      ( Genode.Prelude.XML.text
                          ''
                          <config verbose="no">
                          	<policy label="platform_drv -> acpi"          report="acpi_drv -> acpi"/>
                          	<policy label="driver_manager -> pci_devices" report="platform_drv -> pci"/>
                          	<policy label="usb_drv -> config"             report="driver_manager -> usb_drv.config"/>
                          	<policy label="driver_manager -> usb_devices" report="usb_drv -> devices"/>
                          	<policy label="dynamic -> config"             report="driver_manager -> init.config"/>
                          	<policy label="driver_manager -> ahci_ports"  report="dynamic -> ahci_ports"/>
                          	<policy label="driver_manager -> nvme_ns"     report="dynamic -> nvme_ns"/>
                          	<policy label="rom_reporter -> acpi"          report="acpi_drv -> acpi"/>
                          	<policy label="rom_reporter -> pci_devices"   report="platform_drv -> pci"/>
                          	<policy label="rom_reporter -> usb_devices"   report="usb_drv -> devices"/>
                          </config>
                          ''
                      )
                }
            , rom_reporter =
                Genode.Init.Start::{
                , binary = "rom_reporter"
                , resources = { caps = 96, ram = Genode.units.MiB 1 }
                , config =
                    Some
                      ( Genode.Prelude.XML.text
                          ''
                          <config>
                          	<rom label="acpi"/>
                          	<rom label="pci_devices"/>
                          	<rom label="usb_devices"/>
                          </config>
                          ''
                      )
                , routes =
                    let routeRomToReportRom =
                          Genode.ServiceRoute.childLabel "ROM" "report_rom"

                    let routeReportToParent =
                            λ(label : Text)
                          → Genode.ServiceRoute.parentLabel
                              "Report"
                              (Some label)
                              (Some label)

                    in  [ routeRomToReportRom (Some "acpi") (None Text)
                        , routeRomToReportRom (Some "pci_devices") (None Text)
                        , routeRomToReportRom (Some "usb_devices") (None Text)
                        , routeReportToParent "acpi"
                        , routeReportToParent "pci_devices"
                        , routeReportToParent "usb_devices"
                        ]
                }
            , acpi_drv =
                Genode.Init.Start::{
                , binary = "acpi_drv"
                , resources = { caps = 350, ram = Genode.units.MiB 4 }
                , routes =
                    [ Genode.ServiceRoute.parent "IO_MEM"
                    , Genode.ServiceRoute.childLabel "Report" "report_rom" (Some "acpi") (None Text)
                    , Genode.ServiceRoute.parentLabel
                        "Report"
                        (Some "smbios_table")
                        (Some "smbios_table")

                    ]
                }
            , platform_drv =
                Genode.Init.Start::{
                , binary = "platform_drv"
                , resources = { caps = 400, ram = Genode.units.MiB 4 }
                , constrainPhys = True
                , provides = [ "Acpi", "Platform" ]
                , routes =
                    [ Genode.ServiceRoute.parent "IRQ"
                    , Genode.ServiceRoute.parent "IO_MEM"
                    , Genode.ServiceRoute.parent "IO_PORT"
                    , Genode.ServiceRoute.parent "Timer"
                    , Genode.ServiceRoute.parentLabel
                        "ROM"
                        (Some "system")
                        (Some "system")
                    , Genode.ServiceRoute.childLabel
                        "ROM"
                        "report_rom"
                        (Some "acpi")
                        (None Text)
                    , Genode.ServiceRoute.childLabel
                        "Report"
                        "report_rom"
                        (Some "pci")
                        (None Text)
                    ]
                , config =
                    Some
                      ( Genode.Prelude.XML.text
                          ''
                          <config system="yes">
                            <report pci="yes"/>
                            <policy label_prefix="ps2_drv">
                              <device name="PS2"/>
                            </policy>
                            <policy label_prefix="dynamic -> vesa_fb_drv">
                              <pci class="VGA"/>
                            </policy>
                            <policy label_prefix="dynamic -> ahci_drv">
                              <pci class="AHCI"/>
                            </policy>
                            <policy label_prefix="dynamic -> nvme_drv">
                              <pci class="NVME"/>
                            </policy>
                            <policy label_prefix="usb_drv">
                              <pci class="USB"/>
                            </policy>
                            <policy label_prefix="dynamic -> intel_fb_drv">
                              <pci class="VGA"/>
                              <pci bus="0" device="0" function="0"/>
                              <pci class="ISABRIDGE"/>
                            </policy>
                            <policy label="acpica"> </policy>
                          </config>
                          ''
                      )
                }
            , usb_drv =
                Genode.Init.Start::{
                , binary = "usb_drv"
                , resources = { caps = 200, ram = Genode.units.MiB 16 }
                , provides = [ "Input", "Usb" ]
                , routes =
                    [ Genode.ServiceRoute.child "Platform" "platform_drv"
                    , Genode.ServiceRoute.childLabel
                        "ROM"
                        "report_rom"
                        (Some "config")
                        (None Text)
                    , Genode.ServiceRoute.childLabel
                        "Report"
                        "report_rom"
                        (Some "devices")
                        (None Text)
                    , Genode.ServiceRoute.parentLabel
                        "Report"
                        (Some "config")
                        (Some "usb_active_config")
                    , Genode.ServiceRoute.parent "Timer"
                    ]
                }
            , ps2_drv =
                Genode.Init.Start::{
                , binary = "ps2_drv"
                , provides = [ "Input" ]
                , routes =
                    [ Genode.ServiceRoute.child "Platform" "platform_drv"
                    , Genode.ServiceRoute.parent "Timer"
                    ]
                }
            , input_filter =
                Genode.Init.Start::{
                , binary = "input_filter"
                , resources = { caps = 90, ram = Genode.units.MiB 2 }
                , provides = [ "Input" ]
                , routes =
                    [ Genode.ServiceRoute.parent "Timer"
                    , Genode.ServiceRoute.parentLabel
                        "ROM"
                        (Some "config")
                        (Some "input_filter.config")
                    , Genode.ServiceRoute.childLabel
                        "Input"
                        "ps2_drv"
                        (Some "ps2")
                        (None Text)
                    , Genode.ServiceRoute.childLabel
                        "Input"
                        "usb_drv"
                        (Some "usb")
                        (None Text)
                    ]
                }
            , driver_manager =
                Genode.Init.Start::{
                , binary = "driver_manager"
                , routes =
                    [ Genode.ServiceRoute.childLabel
                        "Report"
                        "report_rom"
                        (Some "init.config")
                        (None Text)
                    , Genode.ServiceRoute.childLabel
                        "Report"
                        "report_rom"
                        (Some "usb_drv.config")
                        (None Text)
                    , Genode.ServiceRoute.parentLabel
                        "Report"
                        (Some "block_devices")
                        (Some "block_devices")
                    , Genode.ServiceRoute.childLabel
                        "ROM"
                        "report_rom"
                        (Some "usb_devices")
                        (None Text)
                    , Genode.ServiceRoute.childLabel
                        "ROM"
                        "report_rom"
                        (Some "pci_devices")
                        (None Text)
                    , Genode.ServiceRoute.childLabel
                        "ROM"
                        "report_rom"
                        (Some "ahci_ports")
                        (None Text)
                    , Genode.ServiceRoute.childLabel
                        "ROM"
                        "report_rom"
                        (Some "nvme_ns")
                        (None Text)
                    , Genode.ServiceRoute.parentLabel
                        "ROM"
                        (Some "usb_policy")
                        (Some "usb_policy")
                    ]
                }
            , dynamic =
                Genode.Init.Start::{
                , binary = "init"
                , resources = { caps = 1400, ram = Genode.units.MiB 64 }
                , provides = [ "Framebuffer", "Block" ]
                , routes =
                    [ Genode.ServiceRoute.child "Platform" "platform_drv"
                    , Genode.ServiceRoute.childLabel
                        "Report"
                        "report_rom"
                        (Some "ahci_ports")
                        (None Text)
                    , Genode.ServiceRoute.childLabel
                        "Report"
                        "report_rom"
                        (Some "nvme_ns")
                        (None Text)
                    , Genode.ServiceRoute.child "Usb" "usb_drv"
                    , Genode.ServiceRoute.childLabel
                        "ROM"
                        "report_rom"
                        (Some "config")
                        (None Text)
                    , Genode.ServiceRoute.parent "Report"
                    , Genode.ServiceRoute.parent "IO_MEM"
                    , Genode.ServiceRoute.parent "IO_PORT"
                    , Genode.ServiceRoute.parent "Timer"
                    ]
                }
            }
      }

in  { arch =
        let Arch = < x86_32 | x86_64 > in Arch.x86_64
    , config =
        Genode.Init::{
        , children =
            toMap
              { timer =
                  Genode.Init.Start::{
                  , binary = "nova_timer_drv"
                  , resources = { caps = 96, ram = Genode.units.MiB 1 }
                  , provides = [ "Timer" ]
                  }
              , report_rom =
                  Genode.Init.Start::{
                  , binary = "report_rom"
                  , resources = { caps = 96, ram = Genode.units.MiB 1 }
                  , provides = [ "ROM", "Report" ]
                  , config =
                      Some (Genode.Prelude.XML.text "<config verbose=\"yes\"/>")
                  }
              , drivers =
                  let subinit = Genode.Init.toStart drivers

                  in    subinit
                      ⫽ { provides =
                            [ "Input"
                            , "Framebuffer"
                            , "Block"
                            , "Usb"
                            , "Platform"
                            ]
                        , routes =
                            [ Genode.ServiceRoute.parent "IO_MEM"
                            , Genode.ServiceRoute.parent "IO_PORT"
                            , Genode.ServiceRoute.parent "IRQ"
                            , Genode.ServiceRoute.parentLabel
                                "ROM"
                                (Some "config")
                                (Some "drivers.config")
                            , Genode.ServiceRoute.child "Timer" "timer"
                            , Genode.ServiceRoute.child "Report" "report_rom"
                            ]
                        }
              , nitpicker =
                  Genode.Init.Start::{
                  , binary = "nitpicker"
                  , resources = { caps = 1000, ram = Genode.units.MiB 6 }
                  , provides = [ "Nitpicker" ]
                  , routes =
                      [ Genode.ServiceRoute.childLabel
                          "ROM"
                          "nit_focus"
                          (Some "focus")
                          (Some "focus")
                      , Genode.ServiceRoute.child "Report" "report_rom"
                      , Genode.ServiceRoute.child "Framebuffer" "drivers"
                      , Genode.ServiceRoute.child "Input" "drivers"
                      , Genode.ServiceRoute.child "Timer" "timer"
                      ]
                  , config =
                      Some
                        ( Genode.Prelude.XML.text
                            ''
                            <config focus="rom">
                            	<background color="#ffffff"/>
                            	<domain name="default" layer="0" content="client" label="no" hover="always" focus="click" />
                            	<default-policy domain="default"/>
                            </config>
                            ''
                        )
                  }
              , nit_focus =
                  Genode.Init.Start::{
                  , binary = "rom_filter"
                  , provides = [ "ROM" ]
                  , config =
                      Some
                        ( Genode.Prelude.XML.text
                            ''
                                                      <config>
                                                      	<output node="focus">
                            				<attribute name="label" value="oberon"/>
                                                      	</output>
                                                      </config>
                                                      ''
                        )
                  }
              , oberon =
                  Genode.Init.Start::{
                  , binary = "retro_frontend"
                  , resources = { caps = 256, ram = Genode.units.MiB 32 }
                  , routes =
                      [ Genode.ServiceRoute.child "Nitpicker" "nitpicker"
                      , Genode.ServiceRoute.child "Timer" "timer"
                      , Genode.ServiceRoute.parentLabel
                          "ROM"
                          (Some "")
                          (Some "retro_frontend")
                      ]
                  , config =
                      Some
                        ( Genode.Prelude.XML.text
                            ''
                            <config ld_verbose="yes">
                              <libc stdout="/dev/log" stderr="/dev/log"/>
                              <defaultController port="0" device="3"/>
                              <game path="/Oberon.dsk"/>
                              <vfs>
                                <rom name="Oberon.dsk"/>
                                <dir name="dev">
                                  <log label="core"/>
                                </dir>
                              </vfs>
                            </config>
                            ''
                        )
                  }
              }
        }
    , rom =
        let manifest = env:MANIFEST

        let emptyXML = λ(name : Text) → { mapKey = name, mapValue = "<empty/>" }

        in    Genode.Boot.toRomPaths
                [ manifest.base-nova.lib.ld-nova ⫽ { mapKey = "ld.lib.so" }
                , manifest.base-nova.bin.nova_timer_drv
                , manifest.os.bin.acpi_drv
                , manifest.os.bin.ahci_drv
                , manifest.os.bin.init
                , manifest.os.bin.input_filter
                , manifest.os.bin.log_core
                , manifest.os.bin.nitpicker
                , manifest.os.bin.platform_drv
                , manifest.os.bin.ps2_drv
                , manifest.os.bin.report_rom
                , manifest.os.bin.rom_filter
                , manifest.os.bin.rom_reporter
                , manifest.os.bin.vfs
                , manifest.os.lib.vfs
                , manifest.driver_manager.bin.driver_manager
                , manifest.usb_drv.bin.usb_drv
                , manifest.boot_fb_drv.bin.fb_boot_drv
                , manifest.intel_fb_drv.bin.intel_fb_drv
                , manifest.vesa_drv.bin.vesa_fb_drv
               ]
            # Genode.Boot.toRomTexts
                [ emptyXML "capslock"
                , emptyXML "numlock"
                , emptyXML "usb.config"
                , emptyXML "usb_policy"
                , { mapKey = "fb_drv.config"
                  , mapValue =
''
<config width="1024" height="768" buffered="yes">
	<report connectors="yes"/>
	<connector name="eDP-36" width="1920" height="1080" enabled="true"/>
	<!-- <connector name="HDMI-A-56" width="1024" height="768" hz="75" enabled="true"/> -->
</config>
''}
                , { mapKey = "input_filter.config"
                  , mapValue =
                      ''
                      <config>
                      	<input label="ps2"/>
                      	<input label="usb"/>
                      	<output>
                      		<chargen>
                      			<merge>
                      				<input name="ps2"/>
                      				<input name="usb"/>
                      			</merge>
                      			<repeat delay_ms="230" rate_ms="90"/>
                      		</chargen>
                      	</output>
                      </config>
                      ''
                  }
                ]
    }
