sculpt: group driver management in 'Drivers' class

This patch harmonizes the driver management between the sculpt manager
and the phone manager by hosting the individual drivers in a new
'Drivers' class with a narrow interface towards 'Sculpt::Main'. The
patch also introduces a clean separation of the 'Board_info' between
features detected at runtime (on PC hardware), statically
known/managed features (phone hardware), and options that can be
toggled at runtime.

With common patterns for managing drivers in place now, this commit
also moves the former runtime/wifi_drv.cc and runtime/nic_drv.cc
code to driver/wifi.h and driver/nic.h. The _drv suffix of the wifi
and nic driver components have been dropped.

Issue #5150
This commit is contained in:
Norman Feske 2024-03-25 15:54:26 +01:00 committed by Christian Helmuth
parent b7bbf8f7e4
commit 6cabc85ac8
27 changed files with 819 additions and 625 deletions

View File

@ -116,7 +116,7 @@
</route>
</start>
<start name="manager" caps="300">
<start name="manager" caps="400">
<binary name="phone_manager"/>
<resource name="RAM" quantum="3M"/>
<provides> <service name="Gui"/> </provides>

View File

@ -37,10 +37,7 @@
#include <model/presets.h>
#include <model/screensaver.h>
#include <managed_config.h>
#include <fb_driver.h>
#include <touch_driver.h>
#include <usb_driver.h>
#include <mmc_driver.h>
#include <drivers.h>
#include <gui.h>
#include <storage.h>
#include <network.h>
@ -89,8 +86,8 @@ struct Sculpt::Main : Input_event_handler,
Software_update_widget::Action,
Software_add_widget::Action,
Screensaver::Action,
Usb_driver::Action,
Mmc_driver::Action
Drivers::Info,
Drivers::Action
{
Env &_env;
@ -101,6 +98,8 @@ struct Sculpt::Main : Input_event_handler,
Build_info const _build_info =
Build_info::from_xml(Attached_rom_dataspace(_env, "build_info").xml());
bool const _phone_hardware = (_build_info.board == "pinephone");
Registry<Child_state> _child_states { };
Input::Seq_number _global_input_seq_number { };
@ -130,7 +129,7 @@ struct Sculpt::Main : Input_event_handler,
struct System
{
bool storage;
bool storage_stage;
using State = String<32>;
@ -145,7 +144,7 @@ struct Sculpt::Main : Input_event_handler,
static System from_xml(Xml_node const &node)
{
return System {
.storage = node.attribute_value("storage", false),
.storage_stage = node.attribute_value("storage", false),
.state = node.attribute_value("state", State()),
.power_profile = node.attribute_value("power_profile", Power_profile()),
.brightness = node.attribute_value("brightness", 0u),
@ -169,7 +168,7 @@ struct Sculpt::Main : Input_event_handler,
bool operator != (System const &other) const
{
return (other.storage != storage)
return (other.storage_stage != storage_stage)
|| (other.state != state)
|| (other.power_profile != power_profile)
|| (other.brightness != brightness);
@ -188,36 +187,40 @@ struct Sculpt::Main : Input_event_handler,
_update_managed_system_config();
}
Attached_rom_dataspace const _platform { _env, "platform_info" };
Attached_rom_dataspace _devices { _env, "report -> drivers/devices" };
/**********************
** Device discovery **
**********************/
Signal_handler<Main> _devices_handler {
_env.ep(), *this, &Main::_handle_devices };
Board_info::Soc _soc {
.fb = _phone_hardware, /* immediately activated */
.touch = _phone_hardware,
.wifi = false, /* activated at second driver stage */
.usb = false,
.mmc = false,
.modem = false, /* depends on presence of battery */
};
Board_info _board_info { };
Drivers _drivers { _env, _child_states, *this, *this };
void _handle_devices()
Board_info::Options _driver_options { };
/**
* Drivers::Action
*/
void handle_device_plug_unplug() override
{
_devices.update();
_handle_block_devices();
network_config_changed();
generate_runtime_config();
}
_board_info = Board_info::from_xml(_devices.xml(), _platform.xml());
/* enable non-PCI wifi (PinePhone) */
if (_devices.xml().num_sub_nodes() == 0)
_board_info.wifi_present = true;
_board_info.usb_present = true;
_board_info.mmc_present = true;
_board_info.soc_fb_present = true;
_board_info.soc_touch_present = true;
_fb_driver .update(_child_states, _board_info, _platform.xml());
_touch_driver.update(_child_states, _board_info);
_mmc_driver .update(_child_states, _board_info);
_update_usb_drivers();
update_network_dialog();
/**
* Drivers::Info
*/
void gen_usb_storage_policies(Xml_generator &xml) const override
{
_storage.gen_usb_storage_policies(xml);
}
void _enter_second_driver_stage()
@ -228,28 +231,16 @@ struct Sculpt::Main : Input_event_handler,
* is up, we can kick off the start of the remaining drivers.
*/
if (_system.storage)
if (_system.storage_stage)
return;
System const orig_system = _system;
_system.storage_stage = true;
_system.storage = true;
if (_system != orig_system)
_update_managed_system_config();
}
Fb_driver _fb_driver { };
Touch_driver _touch_driver { };
Usb_driver _usb_driver { _env, *this };
Mmc_driver _mmc_driver { _env, *this };
void _update_usb_drivers()
{
_usb_driver.update(_child_states, _board_info, {
.hid = false,
.net = (_network._nic_target.type() == Nic_target::MODEM)
});
if (_phone_hardware) {
_soc.mmc = true;
_drivers.update_soc(_soc);
_update_soc_feature_selection();
}
}
Signal_handler<Main> _gui_mode_handler {
@ -280,7 +271,8 @@ struct Sculpt::Main : Input_event_handler,
*/
void screensaver_changed() override
{
_update_managed_system_config();
_driver_options.display = _screensaver.display_enabled();
_drivers.update_options(_driver_options);
generate_runtime_config();
}
@ -327,41 +319,22 @@ struct Sculpt::Main : Input_event_handler,
void _handle_block_devices()
{
_block_devices_rom.update();
_usb_driver.with_devices([&] (Xml_node const &usb_devices) {
_mmc_driver.with_devices([&] (Xml_node const &mmc_devices) {
_storage.update(usb_devices,
Xml_node { "<empty/> " }, /* ahci */
Xml_node { "<empty/> " }, /* nvme */
mmc_devices,
_block_devices_rom.xml(),
_block_devices_handler);
});
_drivers.with_storage_devices([&] (Xml_node const &usb_devices,
Xml_node const &ahci_ports,
Xml_node const &nvme_namespaces,
Xml_node const &mmc_devices) {
_storage.update(usb_devices, ahci_ports, nvme_namespaces, mmc_devices,
_block_devices_rom.xml(),
_block_devices_handler);
});
/* update USB policies for storage devices */
_update_usb_drivers();
_drivers.update_usb();
}
Storage _storage { _env, _heap, _child_states, *this, *this };
/**
* Usb_driver::Action
*/
void handle_usb_plug_unplug() override { _handle_block_devices(); }
/**
* Usb_driver::Action
*/
void gen_usb_storage_policies(Xml_generator &xml) const override
{
_storage.gen_usb_storage_policies(xml);
}
/**
* Mmc_driver::Action
*/
void handle_mmc_discovered() override { _handle_block_devices(); }
/**
* Storage::Action interface
*/
@ -387,12 +360,12 @@ struct Sculpt::Main : Input_event_handler,
** Network **
*************/
Network _network { _env, _heap, *this, *this, _child_states, *this, _runtime_state };
Network _network { _env, _heap, *this, *this, _child_states, *this };
/**
* Network::Action interface
*/
void update_network_dialog() override
void network_config_changed() override
{
_generate_dialog();
}
@ -414,9 +387,11 @@ struct Sculpt::Main : Input_event_handler,
void nic_target(Nic_target::Type const type) override
{
_network.nic_target(type);
/* start/stop USB net driver */
_update_usb_drivers();
_driver_options.usb_net = (type == Nic_target::MODEM);
_driver_options.wifi = (type == Nic_target::WIFI);
_driver_options.nic = (type == Nic_target::WIRED);
_drivers.update_options(_driver_options);
_update_soc_feature_selection();
generate_runtime_config();
}
@ -959,7 +934,8 @@ struct Sculpt::Main : Input_event_handler,
_network_title_bar.view_status(s, network_status_message());
});
s.widget(_network_widget, _network_title_bar.selected(), _board_info);
_drivers.with_board_info([&] (Board_info const &board_info) {
s.widget(_network_widget, _network_title_bar.selected(), board_info); });
s.widget(_software_title_bar, [&] (auto &s) {
_software_title_bar.view_status(s, _software_status_message()); });
@ -1700,6 +1676,25 @@ struct Sculpt::Main : Input_event_handler,
Signal_handler<Main> _power_handler {
_env.ep(), *this, &Main::_handle_power };
bool _update_soc_feature_selection()
{
Board_info::Soc const orig_soc = _soc;
/* wifi and mobile data depends on the presence of a battery */
_soc.modem = _power_state.modem_present() && _modem_state.ready();
_soc.wifi = _power_state.wifi_present();
/* start USB host driver only when needed for USB net */
if (_phone_hardware)
_soc.usb = (_network._nic_target.type() == Nic_target::MODEM);
bool const changed = (orig_soc != _soc);
if (changed)
_drivers.update_soc(_soc);
return changed;
}
void _handle_power()
{
_power_rom.update();
@ -1709,15 +1704,8 @@ struct Sculpt::Main : Input_event_handler,
bool regenerate_dialog = false;
/* mobile data connectivity depends on the presence of a battery */
if (_power_state.modem_present() != _board_info.modem_present) {
/* update condition for the "Mobile data" network option */
_board_info.modem_present = _power_state.modem_present()
&& _modem_state.ready();
if (_system.storage_stage && _update_soc_feature_selection())
regenerate_dialog = true;
}
if (orig_power_state.summary() != _power_state.summary())
regenerate_dialog = true;
@ -1846,13 +1834,8 @@ struct Sculpt::Main : Input_event_handler,
_modem_state = Modem_state::from_xml(_modem_state_rom.xml());
/* update condition of "Mobile data" network option */
{
bool const orig_mobile_data_ready = _board_info.modem_present;
_board_info.modem_present = _power_state.modem_present()
&& _modem_state.ready();
if (orig_mobile_data_ready != _board_info.modem_present)
regenerate_dialog = true;
}
if (orig_modem_state.ready() != _modem_state.ready())
regenerate_dialog = true;
_current_call.update(_modem_state);
@ -2029,6 +2012,10 @@ struct Sculpt::Main : Input_event_handler,
Main(Env &env) : _env(env)
{
_driver_options.display = true;
_drivers.update_options(_driver_options);
_drivers.update_soc(_soc);
_config.sigh(_config_handler);
_leitzentrale_rom.sigh(_leitzentrale_handler);
_manual_deploy_rom.sigh(_manual_deploy_handler);
@ -2041,7 +2028,6 @@ struct Sculpt::Main : Input_event_handler,
* Subscribe to reports
*/
_update_state_rom .sigh(_update_state_handler);
_devices .sigh(_devices_handler);
_window_list .sigh(_window_list_handler);
_decorator_margins .sigh(_decorator_margins_handler);
_scan_rom .sigh(_scan_handler);
@ -2058,8 +2044,6 @@ struct Sculpt::Main : Input_event_handler,
_handle_config();
_handle_leitzentrale();
_handle_gui_mode();
_handle_devices();
_handle_block_devices();
_handle_runtime_config();
_handle_modem_state();
@ -2071,10 +2055,10 @@ struct Sculpt::Main : Input_event_handler,
/*
* Read static platform information
*/
_platform.xml().with_optional_sub_node("affinity-space", [&] (Xml_node const &node) {
_affinity_space = Affinity::Space(node.attribute_value("width", 1U),
node.attribute_value("height", 1U));
});
_drivers.with_platform_info([&] (Xml_node const &platform) {
platform.with_optional_sub_node("affinity-space", [&] (Xml_node const &node) {
_affinity_space = Affinity::Space(node.attribute_value("width", 1U),
node.attribute_value("height", 1U)); }); });
/*
* Generate initial config/managed/deploy configuration
@ -2128,7 +2112,7 @@ void Sculpt::Main::_handle_window_layout()
*
* Once after the basic GUI is up, spawn storage drivers and touch keyboard.
*/
if (!_system.storage) {
if (!_system.storage_stage) {
_with_window(window_list, main_view_label, [&] (Xml_node) {
_enter_second_driver_stage();
_touch_keyboard.started = true;
@ -2468,22 +2452,10 @@ void Sculpt::Main::_generate_runtime_config(Xml_generator &xml) const
xml.attribute("height", _affinity_space.height());
});
if (_screensaver.display_enabled()) {
_fb_driver .gen_start_nodes(xml);
_touch_driver.gen_start_node (xml);
}
if (_system.storage)
_mmc_driver.gen_start_node(xml);
if (_network._nic_target.type() == Nic_target::Type::MODEM)
_usb_driver.gen_start_nodes(xml);
_drivers.gen_start_nodes(xml);
_dialog_runtime.gen_start_nodes(xml);
_touch_keyboard.gen_start_node(xml);
_storage.gen_runtime_start_nodes(xml);
_touch_keyboard.gen_start_node(xml);
/*
* Load configuration and update depot config on the sculpt partition

View File

@ -97,6 +97,8 @@ struct Sculpt::Power_state
return battery_present;
}
bool wifi_present() const { return modem_present(); }
};
#endif /* _MODEL__POWER_STATE_H_ */

View File

@ -7,7 +7,7 @@ SRC_CC += $(notdir $(wildcard $(PRG_DIR)/*.cc))
SRC_CC += $(addprefix view/, $(notdir $(wildcard $(SCULPT_MANAGER_DIR)/view/*.cc)))
SRC_CC += $(addprefix runtime/, $(notdir $(wildcard $(SCULPT_MANAGER_DIR)/runtime/*.cc)))
SRC_CC += $(addprefix dialog/, $(notdir $(wildcard $(SCULPT_MANAGER_DIR)/dialog/*.cc)))
SRC_CC += gui.cc graph.cc deploy.cc storage.cc network.cc
SRC_CC += gui.cc graph.cc deploy.cc storage.cc network.cc drivers.cc
LIBS += base
INC_DIR += $(PRG_DIR) $(SCULPT_MANAGER_DIR) $(DEPOT_DEPLOY_DIR)

View File

@ -11,16 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _AHCI_DRIVER_H_
#define _AHCI_DRIVER_H_
/* Genode includes */
#include <block_session/block_session.h>
/* local includes */
#include <model/child_exit_state.h>
#include <model/board_info.h>
#include <runtime.h>
#ifndef _DRIVER__AHCI_H_
#define _DRIVER__AHCI_H_
namespace Sculpt { struct Ahci_driver; }
@ -73,25 +65,21 @@ struct Sculpt::Ahci_driver : private Noncopyable
});
xml.node("route", [&] {
gen_parent_route<Platform::Session>(xml);
gen_parent_rom_route(xml, "ahci_drv");
gen_parent_rom_route(xml, "system", "config -> managed/system");
gen_parent_route<Rom_session> (xml);
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Report::Session> (xml);
gen_common_routes(xml);
});
});
};
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_ahci.conditional(board_info.ahci_present,
_ahci.conditional(board_info.detected.ahci,
registry, "ahci", Priority::DEFAULT,
Ram_quota { 10*1024*1024 }, Cap_quota { 100 });
}
void with_ahci_ports(auto const &fn) const { fn(_ports.xml()); }
void with_ports(auto const &fn) const { fn(_ports.xml()); }
};
#endif /* _AHCI_DRIVER_H_ */
#endif /* _DRIVER__AHCI_H_ */

View File

@ -11,13 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _FB_DRIVER_H_
#define _FB_DRIVER_H_
/* local includes */
#include <model/child_exit_state.h>
#include <model/board_info.h>
#include <runtime.h>
#ifndef _DRIVER__FB_H_
#define _DRIVER__FB_H_
namespace Sculpt { struct Fb_driver; }
@ -32,16 +27,6 @@ struct Sculpt::Fb_driver : private Noncopyable
void gen_start_nodes(Xml_generator &xml) const
{
auto gen_common_routes = [&] (Xml_generator &xml)
{
gen_parent_route<Rom_session> (xml);
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Report::Session> (xml);
};
auto gen_capture_route = [&] (Xml_generator &xml)
{
gen_service_node<Capture::Session>(xml, [&] {
@ -65,6 +50,7 @@ struct Sculpt::Fb_driver : private Noncopyable
});
xml.node("route", [&] {
gen_parent_route<Platform::Session>(xml);
gen_parent_rom_route(xml, "intel_gpu_drv");
gen_parent_rom_route(xml, "config", "config -> gpu_drv");
gen_parent_route<Rm_session>(xml);
gen_common_routes(xml);
@ -76,6 +62,7 @@ struct Sculpt::Fb_driver : private Noncopyable
gen_service_node<Platform::Session>(xml, [&] {
gen_named_node(xml, "child", "intel_gpu"); });
gen_capture_route(xml);
gen_parent_rom_route(xml, "pc_intel_fb_drv");
gen_parent_rom_route(xml, "config", "config -> fb_drv");
gen_parent_rom_route(xml, "intel_opregion", "report -> drivers/intel_opregion");
gen_parent_route<Rm_session>(xml);
@ -87,6 +74,7 @@ struct Sculpt::Fb_driver : private Noncopyable
xml.node("route", [&] () {
gen_parent_route<Platform::Session>(xml);
gen_capture_route(xml);
gen_parent_rom_route(xml, "vesa_fb_drv");
gen_parent_rom_route(xml, "config", "config -> fb_drv");
gen_parent_route<Io_mem_session>(xml);
gen_parent_route<Io_port_session>(xml);
@ -97,6 +85,7 @@ struct Sculpt::Fb_driver : private Noncopyable
start_node(_boot_fb, "boot_fb_drv", [&] {
xml.node("route", [&] () {
gen_parent_rom_route(xml, "config", "config -> fb_drv");
gen_parent_rom_route(xml, "boot_fb_drv");
gen_parent_route<Io_mem_session>(xml);
gen_capture_route(xml);
gen_common_routes(xml);
@ -108,6 +97,7 @@ struct Sculpt::Fb_driver : private Noncopyable
gen_parent_route<Platform::Session> (xml);
gen_parent_route<Pin_control::Session>(xml);
gen_capture_route(xml);
gen_parent_rom_route(xml, "fb_drv");
gen_parent_rom_route(xml, "config", "config -> fb_drv");
gen_parent_rom_route(xml, "dtb", "fb_drv.dtb");
gen_parent_route<Rm_session>(xml);
@ -119,27 +109,27 @@ struct Sculpt::Fb_driver : private Noncopyable
void update(Registry<Child_state> &registry, Board_info const &board_info,
Xml_node const &platform)
{
_intel_gpu.conditional(board_info.intel_gfx_present,
_intel_gpu.conditional(board_info.detected.intel_gfx,
registry, "intel_gpu", Priority::MULTIMEDIA,
Ram_quota { 32*1024*1024 }, Cap_quota { 1400 });
_intel_fb.conditional(board_info.intel_gfx_present,
_intel_fb.conditional(board_info.detected.intel_gfx,
registry, "intel_fb", Priority::MULTIMEDIA,
Ram_quota { 16*1024*1024 }, Cap_quota { 800 });
_vesa_fb.conditional(board_info.vesa_fb_present,
_vesa_fb.conditional(board_info.detected.vesa,
registry, "vesa_fb", Priority::MULTIMEDIA,
Ram_quota { 8*1024*1024 }, Cap_quota { 110 });
_soc_fb.conditional(board_info.soc_fb_present,
_soc_fb.conditional(board_info.soc.fb && board_info.options.display,
registry, "fb", Priority::MULTIMEDIA,
Ram_quota { 16*1024*1024 }, Cap_quota { 250 });
if (board_info.boot_fb_present && !_boot_fb.constructed())
if (board_info.detected.boot_fb && !_boot_fb.constructed())
Boot_fb::with_mode(platform, [&] (Boot_fb::Mode mode) {
_boot_fb.construct(registry, "boot_fb", Priority::MULTIMEDIA,
mode.ram_quota(), Cap_quota { 100 }); });
}
};
#endif /* _FB_DRIVER_H_ */
#endif /* _DRIVER__FB_H_ */

View File

@ -11,16 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _MMC_DRIVER_H_
#define _MMC_DRIVER_H_
/* Genode includes */
#include <block_session/block_session.h>
/* local includes */
#include <model/child_exit_state.h>
#include <model/board_info.h>
#include <runtime.h>
#ifndef _DRIVER__MMC_H_
#define _DRIVER__MMC_H_
namespace Sculpt { struct Mmc_driver; }
@ -72,20 +64,15 @@ struct Sculpt::Mmc_driver : private Noncopyable
xml.node("route", [&] {
gen_parent_route<Platform::Session>(xml);
gen_parent_rom_route(xml, "dtb", "mmc_drv.dtb");
gen_parent_rom_route(xml, "ld.lib.so");
gen_parent_rom_route(xml, "mmc_drv");
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Report::Session> (xml);
gen_common_routes(xml);
});
});
};
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_mmc.conditional(board_info.mmc_present,
_mmc.conditional(board_info.soc.mmc,
registry, "mmc", Priority::DEFAULT,
Ram_quota { 16*1024*1024 }, Cap_quota { 500 });
}
@ -93,4 +80,4 @@ struct Sculpt::Mmc_driver : private Noncopyable
void with_devices(auto const &fn) const { fn(_devices.xml()); }
};
#endif /* _MMC_DRIVER_H_ */
#endif /* _DRIVER__MMC_H_ */

View File

@ -0,0 +1,56 @@
/*
* \brief Sculpt NIC-driver management
* \author Norman Feske
* \date 2024-03-26
*/
/*
* Copyright (C) 2024 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DRIVER__NIC_H_
#define _DRIVER__NIC_H_
namespace Sculpt { struct Nic_driver; }
struct Sculpt::Nic_driver : private Noncopyable
{
Constructible<Child_state> _nic { };
void gen_start_node(Xml_generator &xml) const
{
if (!_nic.constructed())
return;
xml.node("start", [&] {
_nic->gen_start_node_content(xml);
gen_named_node(xml, "binary", "nic_drv");
xml.node("config", [&] { });
xml.node("route", [&] {
gen_service_node<Uplink::Session>(xml, [&] {
xml.node("child", [&] {
xml.attribute("name", "nic_router"); }); });
gen_service_node<Platform::Session>(xml, [&] {
xml.node("parent", [&] {
xml.attribute("label", "nic"); }); });
gen_common_routes(xml);
gen_parent_rom_route(xml, "nic_drv");
gen_parent_rom_route(xml, "nic_drv.dtb");
gen_parent_route<Rm_session>(xml);
});
});
};
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_nic.conditional(board_info.detected.nic && board_info.options.nic,
registry, "nic", Priority::DEFAULT,
Ram_quota { 20*1024*1024 }, Cap_quota { 300 });
}
};
#endif /* _DRIVER__NIC_H_ */

View File

@ -11,16 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _NVME_DRIVER_H_
#define _NVME_DRIVER_H_
/* Genode includes */
#include <block_session/block_session.h>
/* local includes */
#include <model/child_exit_state.h>
#include <model/board_info.h>
#include <runtime.h>
#ifndef _DRIVER_NVME_H_
#define _DRIVER_NVME_H_
namespace Sculpt { struct Nvme_driver; }
@ -72,25 +64,21 @@ struct Sculpt::Nvme_driver : private Noncopyable
});
xml.node("route", [&] {
gen_parent_route<Platform::Session>(xml);
gen_parent_rom_route(xml, "nvme_drv");
gen_parent_rom_route(xml, "system", "config -> managed/system");
gen_parent_route<Rom_session> (xml);
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Report::Session> (xml);
gen_common_routes(xml);
});
});
};
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_nvme.conditional(board_info.nvme_present,
_nvme.conditional(board_info.detected.nvme,
registry, "nvme", Priority::DEFAULT,
Ram_quota { 8*1024*1024 }, Cap_quota { 100 });
}
void with_nvme_namespaces(auto const &fn) const { fn(_namespaces.xml()); }
void with_namespaces(auto const &fn) const { fn(_namespaces.xml()); }
};
#endif /* _NVME_DRIVER_H_ */
#endif /* _DRIVER_NVME_H_ */

View File

@ -11,13 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _PS2_DRIVER_H_
#define _PS2_DRIVER_H_
/* local includes */
#include <model/child_exit_state.h>
#include <model/board_info.h>
#include <runtime.h>
#ifndef _DRIVER__PS2_H_
#define _DRIVER__PS2_H_
namespace Sculpt { struct Ps2_driver; }
@ -44,14 +39,11 @@ struct Sculpt::Ps2_driver : private Noncopyable
xml.node("route", [&] {
gen_parent_route<Platform::Session>(xml);
gen_common_routes(xml);
gen_parent_rom_route(xml, "capslock", "capslock");
gen_parent_rom_route(xml, "numlock", "numlock");
gen_parent_rom_route(xml, "system", "config -> managed/system");
gen_parent_route<Rom_session> (xml);
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session>(xml);
gen_service_node<Event::Session>(xml, [&] {
xml.node("parent", [&] {
xml.attribute("label", "ps2"); }); });
@ -61,10 +53,10 @@ struct Sculpt::Ps2_driver : private Noncopyable
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_ps2.conditional(board_info.ps2_present,
_ps2.conditional(board_info.detected.ps2,
registry, "ps2", Priority::MULTIMEDIA,
Ram_quota { 1*1024*1024 }, Cap_quota { 100 });
}
};
#endif /* _PS2_DRIVER_H_ */
#endif /* _DRIVER__PS2_H_ */

View File

@ -11,13 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TOUCH_DRIVER_H_
#define _TOUCH_DRIVER_H_
/* local includes */
#include <model/child_exit_state.h>
#include <model/board_info.h>
#include <runtime.h>
#ifndef _DRIVER__TOUCH_H_
#define _DRIVER__TOUCH_H_
namespace Sculpt { struct Touch_driver; }
@ -38,14 +33,10 @@ struct Sculpt::Touch_driver : private Noncopyable
xml.node("route", [&] {
gen_parent_route<Platform::Session> (xml);
gen_parent_rom_route(xml, "dtb", "touch_drv.dtb");
gen_parent_rom_route(xml, "ld.lib.so");
gen_parent_rom_route(xml, "touch_drv");
gen_common_routes(xml);
gen_parent_route<Pin_control::Session>(xml);
gen_parent_route<Irq_session> (xml);
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_service_node<Event::Session>(xml, [&] {
xml.node("parent", [&] {
xml.attribute("label", "touch"); }); });
@ -55,10 +46,10 @@ struct Sculpt::Touch_driver : private Noncopyable
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_soc.conditional(board_info.soc_touch_present,
_soc.conditional(board_info.soc.touch && board_info.options.display,
registry, "touch", Priority::MULTIMEDIA,
Ram_quota { 10*1024*1024 }, Cap_quota { 250 });
}
};
#endif /* _TOUCH_DRIVER_H_ */
#endif /* _DRIVER__TOUCH_H_ */

View File

@ -11,17 +11,10 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _USB_DRIVER_H_
#define _USB_DRIVER_H_
#ifndef _DRIVER__USB_H_
#define _DRIVER__USB_H_
/* Genode includes */
#include <uplink_session/uplink_session.h>
/* local includes */
#include <model/child_exit_state.h>
#include <model/board_info.h>
#include <managed_config.h>
#include <runtime.h>
namespace Sculpt { struct Usb_driver; }
@ -31,15 +24,38 @@ struct Sculpt::Usb_driver : private Noncopyable
struct Action : Interface
{
virtual void handle_usb_plug_unplug() = 0;
};
struct Info : Interface
{
virtual void gen_usb_storage_policies(Xml_generator &) const = 0;
};
Env &_env;
Action &_action;
Env &_env;
Info const &_info;
Action &_action;
Constructible<Child_state> _hcd { },
_hid { },
_net { };
Constructible<Child_state> _hcd { }, _hid { }, _net { };
static constexpr unsigned CLASS_HID = 3, CLASS_NET = 2;
struct Detected
{
bool hid, net;
static Detected from_xml(Xml_node const &devices)
{
Detected result { };
devices.for_each_sub_node("device", [&] (Xml_node const &device) {
device.for_each_sub_node("config", [&] (Xml_node const &config) {
config.for_each_sub_node("interface", [&] (Xml_node const &interface) {
unsigned const class_id = interface.attribute_value("class", 0u);
result.hid |= (class_id == CLASS_HID);
result.net |= (class_id == CLASS_NET); }); }); });
return result;
}
} _detected { };
Attached_rom_dataspace _devices { _env, "report -> runtime/usb/devices" };
@ -49,6 +65,7 @@ struct Sculpt::Usb_driver : private Noncopyable
void _handle_devices()
{
_devices.update();
_detected = Detected::from_xml(_devices.xml());
_action.handle_usb_plug_unplug();
}
@ -66,17 +83,19 @@ struct Sculpt::Usb_driver : private Noncopyable
xml.node("policy", [&] {
xml.attribute("label_prefix", "usb_hid");
xml.node("device", [&] {
xml.attribute("class", "0x3"); }); });
xml.attribute("class", CLASS_HID); }); });
/* copy user-provided rules */
config.for_each_sub_node("policy", [&] (Xml_node const &policy) {
copy_node(xml, policy); });
_action.gen_usb_storage_policies(xml);
_info.gen_usb_storage_policies(xml);
});
}
Usb_driver(Env &env, Action &action) : _env(env), _action(action)
Usb_driver(Env &env, Info const &info, Action &action)
:
_env(env), _info(info), _action(action)
{
_devices.sigh(_devices_handler);
_usb_config.trigger_update();
@ -85,16 +104,6 @@ struct Sculpt::Usb_driver : private Noncopyable
void gen_start_nodes(Xml_generator &xml) const
{
auto gen_common_routes = [&] (Xml_generator &xml)
{
gen_parent_route<Rom_session> (xml);
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Report::Session> (xml);
};
auto start_node = [&] (auto const &driver, auto const &binary, auto const &fn)
{
if (driver.constructed())
@ -108,6 +117,7 @@ struct Sculpt::Usb_driver : private Noncopyable
gen_provides<Usb::Session>(xml);
xml.node("route", [&] {
gen_parent_route<Platform::Session>(xml);
gen_parent_rom_route(xml, "usb_drv");
gen_parent_rom_route(xml, "config", "config -> managed/usb");
gen_parent_rom_route(xml, "dtb", "usb_drv.dtb");
gen_common_routes(xml);
@ -122,6 +132,7 @@ struct Sculpt::Usb_driver : private Noncopyable
xml.node("route", [&] {
gen_service_node<Usb::Session>(xml, [&] {
gen_named_node(xml, "child", "usb"); });
gen_parent_rom_route(xml, "usb_hid_drv");
gen_parent_rom_route(xml, "capslock", "capslock");
gen_parent_rom_route(xml, "numlock", "numlock");
gen_common_routes(xml);
@ -138,6 +149,7 @@ struct Sculpt::Usb_driver : private Noncopyable
xml.node("route", [&] {
gen_service_node<Usb::Session>(xml, [&] {
gen_named_node(xml, "child", "usb"); });
gen_parent_rom_route(xml, "usb_net_drv");
gen_common_routes(xml);
gen_service_node<Uplink::Session>(xml, [&] {
xml.node("child", [&] () {
@ -149,20 +161,17 @@ struct Sculpt::Usb_driver : private Noncopyable
});
};
struct Features { bool hid, net; };
void update(Registry<Child_state> &registry,
Board_info const &board_info, Features features)
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_hcd.conditional(board_info.usb_present,
_hcd.conditional(board_info.usb_avail(),
registry, "usb", Priority::MULTIMEDIA,
Ram_quota { 16*1024*1024 }, Cap_quota { 200 });
_hid.conditional(board_info.usb_present && features.hid,
_hid.conditional(board_info.usb_avail() && _detected.hid,
registry, "usb_hid", Priority::MULTIMEDIA,
Ram_quota { 11*1024*1024 }, Cap_quota { 180 });
_net.conditional(board_info.usb_present && features.net,
_net.conditional(board_info.usb_avail() && _detected.net && board_info.options.usb_net,
registry, "usb_net", Priority::DEFAULT,
Ram_quota { 20*1024*1024 }, Cap_quota { 200 });
@ -172,4 +181,4 @@ struct Sculpt::Usb_driver : private Noncopyable
void with_devices(auto const &fn) const { fn(_devices.xml()); }
};
#endif /* _USB_DRIVER_H_ */
#endif /* _DRIVER__USB_H_ */

View File

@ -0,0 +1,107 @@
/*
* \brief Sculpt Wifi-driver management
* \author Norman Feske
* \date 2024-03-26
*/
/*
* Copyright (C) 2024 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DRIVER__WIFI_H_
#define _DRIVER__WIFI_H_
namespace Sculpt { struct Wifi_driver; }
struct Sculpt::Wifi_driver : private Noncopyable
{
Constructible<Child_state> _wifi { };
void gen_start_node(Xml_generator &xml) const
{
if (!_wifi.constructed())
return;
xml.node("start", [&] {
_wifi->gen_start_node_content(xml);
gen_named_node(xml, "binary", "wifi_drv");
xml.node("config", [&] {
xml.attribute("dtb", "wifi_drv.dtb");
xml.node("vfs", [&] {
gen_named_node(xml, "dir", "dev", [&] {
xml.node("null", [&] {});
xml.node("zero", [&] {});
xml.node("log", [&] {});
xml.node("null", [&] {});
gen_named_node(xml, "jitterentropy", "random");
gen_named_node(xml, "jitterentropy", "urandom"); });
gen_named_node(xml, "inline", "rtc", [&] {
xml.append("2018-01-01 00:01");
});
gen_named_node(xml, "dir", "firmware", [&] {
xml.node("tar", [&] {
xml.attribute("name", "wifi_firmware.tar");
});
});
});
xml.node("libc", [&] {
xml.attribute("stdout", "/dev/null");
xml.attribute("stderr", "/dev/null");
xml.attribute("rtc", "/dev/rtc");
});
});
xml.node("route", [&] {
xml.node("service", [&] {
xml.attribute("name", "Uplink");
xml.node("child", [&] {
xml.attribute("name", "nic_router");
xml.attribute("label", "wifi -> ");
});
});
gen_service_node<Platform::Session>(xml, [&] {
xml.node("parent", [&] {
xml.attribute("label", "wifi"); }); });
gen_common_routes(xml);
gen_parent_rom_route(xml, "wifi_drv");
gen_parent_rom_route(xml, "wifi_drv.dtb");
gen_parent_rom_route(xml, "libcrypto.lib.so");
gen_parent_rom_route(xml, "vfs.lib.so");
gen_parent_rom_route(xml, "libc.lib.so");
gen_parent_rom_route(xml, "libm.lib.so");
gen_parent_rom_route(xml, "vfs_jitterentropy.lib.so");
gen_parent_rom_route(xml, "libssl.lib.so");
gen_parent_rom_route(xml, "wifi.lib.so");
gen_parent_rom_route(xml, "wifi_firmware.tar");
gen_parent_rom_route(xml, "wpa_driver_nl80211.lib.so");
gen_parent_rom_route(xml, "wpa_supplicant.lib.so");
gen_parent_route<Rm_session> (xml);
gen_parent_route<Rtc::Session> (xml);
gen_service_node<Rom_session>(xml, [&] {
xml.attribute("label", "wifi_config");
xml.node("parent", [&] {
xml.attribute("label", "config -> managed/wifi"); }); });
});
});
};
void update(Registry<Child_state> &registry, Board_info const &board_info)
{
_wifi.conditional(board_info.wifi_avail() && board_info.options.wifi,
registry, "wifi", Priority::DEFAULT,
Ram_quota { 16*1024*1024 }, Cap_quota { 250 });
}
};
#endif /* _DRIVER__WIFI_H_ */

View File

@ -0,0 +1,187 @@
/*
* \brief Sculpt dynamic drivers management
* \author Norman Feske
* \date 2024-03-25
*/
/*
* Copyright (C) 2025 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <block_session/block_session.h>
#include <capture_session/capture_session.h>
#include <event_session/event_session.h>
#include <gpu_session/gpu_session.h>
#include <io_port_session/io_port_session.h>
#include <pin_control_session/pin_control_session.h>
#include <pin_state_session/pin_state_session.h>
#include <timer_session/connection.h>
#include <uplink_session/uplink_session.h>
#include <vm_session/vm_session.h>
/* local includes */
#include <drivers.h>
#include <driver/ahci.h>
#include <driver/fb.h>
#include <driver/mmc.h>
#include <driver/nvme.h>
#include <driver/ps2.h>
#include <driver/touch.h>
#include <driver/usb.h>
#include <driver/wifi.h>
#include <driver/nic.h>
class Sculpt::Drivers::Instance : Noncopyable,
Nvme_driver::Action,
Mmc_driver::Action,
Ahci_driver::Action,
Usb_driver::Action, Usb_driver::Info
{
private:
using Action = Drivers::Action;
using Info = Drivers::Info;
Env &_env;
Children &_children;
Info const &_info;
Action &_action;
Board_info _board_info { };
Attached_rom_dataspace const _platform { _env, "platform_info" };
Attached_rom_dataspace _devices { _env, "report -> drivers/devices" };
Signal_handler<Instance> _devices_handler {
_env.ep(), *this, &Instance::_handle_devices };
void _handle_devices()
{
_devices.update();
_board_info.detected = Board_info::Detected::from_xml(_devices.xml(),
_platform.xml());
_fb_driver .update(_children, _board_info, _platform.xml());
_ps2_driver .update(_children, _board_info);
_touch_driver.update(_children, _board_info);
_ahci_driver .update(_children, _board_info);
_nvme_driver .update(_children, _board_info);
_mmc_driver .update(_children, _board_info);
_wifi_driver .update(_children, _board_info);
_nic_driver .update(_children, _board_info);
_action.handle_device_plug_unplug();
}
Ps2_driver _ps2_driver { };
Touch_driver _touch_driver { };
Fb_driver _fb_driver { };
Usb_driver _usb_driver { _env, *this, *this };
Ahci_driver _ahci_driver { _env, *this };
Nvme_driver _nvme_driver { _env, *this };
Mmc_driver _mmc_driver { _env, *this };
Wifi_driver _wifi_driver { };
Nic_driver _nic_driver { };
void gen_usb_storage_policies(Xml_generator &xml) const override
{
_info.gen_usb_storage_policies(xml);
}
void handle_usb_plug_unplug() override { _action.handle_device_plug_unplug(); }
void handle_ahci_discovered() override { _action.handle_device_plug_unplug(); }
void handle_mmc_discovered() override { _action.handle_device_plug_unplug(); }
void handle_nvme_discovered() override { _action.handle_device_plug_unplug(); }
public:
Instance(Env &env, Children &children, Info const &info, Action &action)
:
_env(env), _children(children), _info(info), _action(action)
{
_devices.sigh(_devices_handler);
_devices_handler.local_submit();
}
void update_usb() { _usb_driver.update(_children, _board_info); }
void update_soc(Board_info::Soc soc)
{
_board_info.soc = soc;
_handle_devices();
}
void update_options(Board_info::Options const options)
{
if (options != _board_info.options) {
_board_info.options = options;
_handle_devices();
_usb_driver.update(_children, _board_info);
}
}
void gen_start_nodes(Xml_generator &xml) const
{
_ps2_driver .gen_start_node (xml);
_touch_driver.gen_start_node (xml);
_fb_driver .gen_start_nodes(xml);
_usb_driver .gen_start_nodes(xml);
_ahci_driver .gen_start_node (xml);
_nvme_driver .gen_start_node (xml);
_mmc_driver .gen_start_node (xml);
_wifi_driver .gen_start_node (xml);
_nic_driver .gen_start_node (xml);
}
void with(With_storage_devices::Callback const &fn) const
{
_usb_driver.with_devices([&] (Xml_node const &usb_devices) {
_ahci_driver.with_ports([&] (Xml_node const &ahci_ports) {
_nvme_driver.with_namespaces([&] (Xml_node const &nvme_namespaces) {
_mmc_driver.with_devices([&] (Xml_node const &mmc_devices) {
fn( { .usb = usb_devices,
.ahci = ahci_ports,
.nvme = nvme_namespaces,
.mmc = mmc_devices }); }); }); }); });
}
void with(With_board_info::Callback const &fn) const { fn(_board_info); }
void with(With_platform_info::Callback const &fn) const { fn(_platform.xml()); }
};
using namespace Sculpt;
Drivers::Instance &Drivers::_construct_instance(auto &&... args)
{
static bool called_once;
if (called_once)
error("unexpected attempt to construct multiple 'Drivers' instances");
called_once = true;
static Drivers::Instance instance { args... };
return instance;
}
Sculpt::Drivers::Drivers(Env &env, Children &children, Info const &info, Action &action)
:
_instance(_construct_instance(env, children, info, action))
{ }
void Drivers::_with(With_storage_devices::Callback const &fn) const { _instance.with(fn); }
void Drivers::_with(With_board_info::Callback const &fn) const { _instance.with(fn); }
void Drivers::_with(With_platform_info::Callback const &fn) const { _instance.with(fn); }
void Drivers::update_usb () { _instance.update_usb(); }
void Drivers::update_soc (Board_info::Soc soc) { _instance.update_soc(soc); }
void Drivers::update_options(Board_info::Options opt) { _instance.update_options(opt); }
void Drivers::gen_start_nodes(Xml_generator &xml) const { _instance.gen_start_nodes(xml); }

View File

@ -0,0 +1,77 @@
/*
* \brief Sculpt dynamic drivers management
* \author Norman Feske
* \date 2024-03-25
*/
/*
* Copyright (C) 2025 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DRIVERS_H_
#define _DRIVERS_H_
/* local includes */
#include <xml.h>
#include <model/child_state.h>
#include <model/board_info.h>
namespace Sculpt { struct Drivers; }
class Sculpt::Drivers : Noncopyable
{
public:
struct Action : Interface
{
virtual void handle_device_plug_unplug() = 0;
};
struct Info : Interface
{
virtual void gen_usb_storage_policies(Xml_generator &) const = 0;
};
using Children = Registry<Child_state>;
/**
* Argument type for 'with_storage_devices'
*/
struct Storage_devices { Xml_node const &usb, &ahci, &nvme, &mmc; };
private:
struct Instance;
Instance &_instance;
static Instance &_construct_instance(auto &&...);
using With_storage_devices = With<Storage_devices const &>;
using With_board_info = With<Board_info const &>;
using With_platform_info = With<Xml_node const &>;
void _with(With_storage_devices::Callback const &) const;
void _with(With_board_info::Callback const &) const;
void _with(With_platform_info::Callback const &) const;
public:
Drivers(Env &, Children &, Info const &, Action &);
void update_usb();
void update_soc(Board_info::Soc);
void update_options(Board_info::Options);
void gen_start_nodes(Xml_generator &) const;
void with_storage_devices(auto const &fn) const { _with(With_storage_devices::Fn { fn }); }
void with_board_info (auto const &fn) const { _with(With_board_info::Fn { fn }); }
void with_platform_info (auto const &fn) const { _with(With_platform_info::Fn { fn }); }
};
#endif /* _DRIVERS_H_ */

View File

@ -92,8 +92,8 @@ void Graph::_view_selected_node_content(Scope<Depgraph, Frame, Vbox> &s,
s.widget(_remove);
s.widget(_restart); }); });
} else if (name == "nic_drv" ||
name == "wifi_drv") {
} else if (name == "nic" ||
name == "wifi") {
s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
s.sub_scope<Hbox>([&] (Scope<Depgraph, Frame, Vbox, Frame, Hbox> &s) {

View File

@ -44,11 +44,7 @@
#include <view/settings_widget.h>
#include <view/system_dialog.h>
#include <view/file_browser_dialog.h>
#include <fb_driver.h>
#include <ps2_driver.h>
#include <usb_driver.h>
#include <ahci_driver.h>
#include <nvme_driver.h>
#include <drivers.h>
#include <gui.h>
#include <keyboard_focus.h>
#include <network.h>
@ -78,9 +74,8 @@ struct Sculpt::Main : Input_event_handler,
Panel_dialog::State,
Popup_dialog::Refresh,
Screensaver::Action,
Usb_driver::Action,
Ahci_driver::Action,
Nvme_driver::Action
Drivers::Info,
Drivers::Action
{
Env &_env;
@ -212,43 +207,26 @@ struct Sculpt::Main : Input_event_handler,
** Device discovery **
**********************/
Attached_rom_dataspace const _platform { _env, "platform_info" };
Drivers _drivers { _env, _child_states, *this, *this };
Attached_rom_dataspace _devices { _env, "report -> drivers/devices" };
Board_info::Options _driver_options { };
Signal_handler<Main> _devices_handler {
_env.ep(), *this, &Main::_handle_devices };
Board_info _board_info { };
void _handle_devices()
/**
* Drivers::Action
*/
void handle_device_plug_unplug() override
{
_devices.update();
_board_info = Board_info::from_xml(_devices.xml(), _platform.xml());
_fb_driver .update(_child_states, _board_info, _platform.xml());
_ps2_driver .update(_child_states, _board_info);
_ahci_driver.update(_child_states, _board_info);
_nvme_driver.update(_child_states, _board_info);
_update_usb_drivers();
update_network_dialog();
_handle_block_devices();
network_config_changed();
generate_runtime_config();
}
Ps2_driver _ps2_driver { };
Fb_driver _fb_driver { };
Usb_driver _usb_driver { _env, *this };
Ahci_driver _ahci_driver { _env, *this };
Nvme_driver _nvme_driver { _env, *this };
void _update_usb_drivers()
/**
* Drivers::Info
*/
void gen_usb_storage_policies(Xml_generator &xml) const override
{
_usb_driver.update(_child_states, _board_info, {
.hid = true,
.net = (_network._nic_target.type() == Nic_target::MODEM)
});
_storage.gen_usb_storage_policies(xml);
}
@ -277,45 +255,18 @@ struct Sculpt::Main : Input_event_handler,
void _handle_block_devices()
{
_block_devices_rom.update();
_usb_driver.with_devices([&] (Xml_node const &usb_devices) {
_ahci_driver.with_ahci_ports([&] (Xml_node const &ahci_ports) {
_nvme_driver.with_nvme_namespaces([&] (Xml_node const &nvme_namespaces) {
_storage.update(usb_devices, ahci_ports, nvme_namespaces,
Xml_node { "<empty/> " }, /* mmc */
_block_devices_rom.xml(),
_block_devices_handler);
});
});
});
_drivers.with_storage_devices([&] (Drivers::Storage_devices const &devices) {
_storage.update(devices.usb, devices.ahci, devices.nvme, devices.mmc,
_block_devices_rom.xml(),
_block_devices_handler); });
/* update USB policies for storage devices */
_update_usb_drivers();
_drivers.update_usb();
}
Storage _storage { _env, _heap, _child_states, *this, *this };
/**
* Usb_driver::Action
*/
void handle_usb_plug_unplug() override { _handle_block_devices(); }
/**
* Usb_driver::Action
*/
void gen_usb_storage_policies(Xml_generator &xml) const override
{
_storage.gen_usb_storage_policies(xml);
}
/**
* Ahci_driver::Action
*/
void handle_ahci_discovered() override { _handle_block_devices(); }
/**
* Nvme_driver::Action
*/
void handle_nvme_discovered() override { _handle_block_devices(); }
/**
* Storage::Action interface
@ -344,7 +295,7 @@ struct Sculpt::Main : Input_event_handler,
** Network **
*************/
Network _network { _env, _heap, *this, *this, _child_states, *this, _runtime_state };
Network _network { _env, _heap, *this, *this, _child_states, *this };
/**
* Network::Info interface
@ -364,8 +315,10 @@ struct Sculpt::Main : Input_event_handler,
void view(Scope<> &s) const override
{
s.sub_scope<Frame>([&] (Scope<Frame> &s) {
_main._network.dialog.view(s, _main._board_info); });
_main._drivers.with_board_info([&] (Board_info const &board_info) {
s.sub_scope<Frame>([&] (Scope<Frame> &s) {
_main._network.dialog.view(s, board_info); });
});
}
void click(Clicked_at const &at) override
@ -385,9 +338,6 @@ struct Sculpt::Main : Input_event_handler,
void nic_target(Nic_target::Type const type) override
{
_network.nic_target(type);
/* start/stop USB net driver */
_update_usb_drivers();
generate_runtime_config();
}
@ -407,8 +357,14 @@ struct Sculpt::Main : Input_event_handler,
/**
* Network::Action interface
*/
void update_network_dialog() override
void network_config_changed() override
{
Nic_target::Type const type = _network._nic_target.type();
_driver_options.usb_net = (type == Nic_target::MODEM);
_driver_options.wifi = (type == Nic_target::WIFI);
_driver_options.nic = (type == Nic_target::WIRED);
_drivers.update_options(_driver_options);
_network_dialog.refresh();
_system_dialog.refresh();
}
@ -939,12 +895,12 @@ struct Sculpt::Main : Input_event_handler,
*/
void restart_deployed_component(Start_name const &name) override
{
if (name == "nic_drv") {
if (name == "nic") {
_network.restart_nic_drv_on_next_runtime_cfg();
generate_runtime_config();
} else if (name == "wifi_drv") {
} else if (name == "wifi") {
_network.restart_wifi_drv_on_next_runtime_cfg();
generate_runtime_config();
@ -1493,7 +1449,6 @@ struct Sculpt::Main : Input_event_handler,
* Subscribe to reports
*/
_update_state_rom .sigh(_update_state_handler);
_devices .sigh(_devices_handler);
_window_list .sigh(_window_list_handler);
_decorator_margins .sigh(_decorator_margins_handler);
_scan_rom .sigh(_scan_handler);
@ -1513,17 +1468,16 @@ struct Sculpt::Main : Input_event_handler,
* Import initial report content
*/
_handle_gui_mode();
_handle_devices();
_handle_block_devices();
_handle_runtime_config();
/*
* Read static platform information
*/
_platform.xml().with_optional_sub_node("affinity-space", [&] (Xml_node const &node) {
_affinity_space = Affinity::Space(node.attribute_value("width", 1U),
node.attribute_value("height", 1U));
});
_drivers.with_platform_info([&] (Xml_node const &platform) {
platform.with_optional_sub_node("affinity-space", [&] (Xml_node const &node) {
_affinity_space = Affinity::Space(node.attribute_value("width", 1U),
node.attribute_value("height", 1U)); }); });
/*
* Generate initial config/managed/deploy configuration
@ -2139,14 +2093,8 @@ void Sculpt::Main::_generate_runtime_config(Xml_generator &xml) const
xml.attribute("height", _affinity_space.height());
});
_ps2_driver .gen_start_node (xml);
_fb_driver .gen_start_nodes(xml);
_usb_driver .gen_start_nodes(xml);
_ahci_driver.gen_start_node (xml);
_nvme_driver.gen_start_node (xml);
_drivers.gen_start_nodes(xml);
_dialog_runtime.gen_start_nodes(xml);
_storage.gen_runtime_start_nodes(xml);
_file_browser_state.gen_start_nodes(xml);

View File

@ -20,97 +20,124 @@ namespace Sculpt { struct Board_info; }
struct Sculpt::Board_info
{
bool wifi_present,
lan_present,
modem_present,
intel_gfx_present,
boot_fb_present,
vesa_fb_present,
soc_fb_present,
nvme_present,
ahci_present,
mmc_present,
usb_present,
ps2_present,
soc_touch_present;
static Board_info from_xml(Xml_node const &devices, Xml_node const &platform)
/**
* Runtime-detected features
*/
struct Detected
{
Board_info result { };
bool wifi, nic, intel_gfx, boot_fb, vesa, nvme, ahci, usb, ps2;
Boot_fb::with_mode(platform, [&] (Boot_fb::Mode mode) {
result.boot_fb_present = mode.valid(); });
void print(Output &out) const
{
Genode::print(out, "wifi=", wifi, " nic=", nic,
" intel_gfx=", intel_gfx, " boot_fb=", boot_fb,
" vesa=", vesa, " nvme=", nvme,
" ahci=", ahci, " usb=", usb);
}
bool vga = false;
static inline Detected from_xml(Xml_node const &devices, Xml_node const &platform);
devices.for_each_sub_node("device", [&] (Xml_node const &device) {
} detected;
if (device.attribute_value("name", String<16>()) == "ps2")
result.ps2_present = true;
device.with_optional_sub_node("pci-config", [&] (Xml_node const &pci) {
enum class Pci_class : unsigned {
WIFI = 0x28000,
LAN = 0x20000,
VGA = 0x30000,
AHCI = 0x10601,
NVME = 0x10802,
UHCI = 0xc0300, OHCI = 0xc0310, EHCI = 0xc0320, XHCI = 0xc0330,
};
enum class Pci_vendor : unsigned { INTEL = 0x8086U, };
auto matches_class = [&] (Pci_class value)
{
return pci.attribute_value("class", 0U) == unsigned(value);
};
auto matches_vendor = [&] (Pci_vendor value)
{
return pci.attribute_value("vendor_id", 0U) == unsigned(value);
};
if (matches_class(Pci_class::WIFI)) result.wifi_present = true;
if (matches_class(Pci_class::LAN)) result.lan_present = true;
if (matches_class(Pci_class::NVME)) result.nvme_present = true;
if (matches_class(Pci_class::UHCI) || matches_class(Pci_class::OHCI)
|| matches_class(Pci_class::EHCI) || matches_class(Pci_class::XHCI))
result.usb_present = true;
if (matches_class(Pci_class::AHCI) && matches_vendor(Pci_vendor::INTEL))
result.ahci_present = true;
if (matches_class(Pci_class::VGA)) {
vga = true;
if (matches_vendor(Pci_vendor::INTEL))
result.intel_gfx_present = true;
}
});
});
if (result.intel_gfx_present)
result.boot_fb_present = false;
if (vga && !result.intel_gfx_present && !result.boot_fb_present)
result.vesa_fb_present = true;
return result;
}
void print(Output &out) const
/**
* Statically-known or configured features
*/
struct Soc
{
Genode::print(out, "wifi=", wifi_present,
" lan=", lan_present,
" modem=", modem_present,
" intel_gfx=", intel_gfx_present,
" boot_fb=", boot_fb_present,
" vesa_fb=", vesa_fb_present,
" nvme=", nvme_present,
" ahci=", ahci_present,
" usb=", usb_present);
}
bool fb, touch, wifi, usb, mmc, modem;
bool operator != (Soc const &other) const
{
return (fb != other.fb) || (touch != other.touch)
|| (wifi != other.wifi) || (usb != other.usb)
|| (mmc != other.mmc) || (modem != other.modem);
}
} soc;
/**
* Features that can be toggled at runtime
*/
struct Options
{
bool display, usb_net, nic, wifi;
bool operator != (Options const &other) const
{
return display != other.display || usb_net != other.usb_net
|| nic != other.nic || wifi != other.wifi;
}
} options;
bool usb_avail() const { return detected.usb || soc.usb; }
bool wifi_avail() const { return detected.wifi || soc.wifi; }
};
Sculpt::Board_info::Detected
Sculpt::Board_info::Detected::from_xml(Xml_node const &devices, Xml_node const &platform)
{
Detected detected { };
Boot_fb::with_mode(platform, [&] (Boot_fb::Mode mode) {
detected.boot_fb = mode.valid(); });
bool vga = false;
devices.for_each_sub_node("device", [&] (Xml_node const &device) {
if (device.attribute_value("name", String<16>()) == "ps2")
detected.ps2 = true;
device.with_optional_sub_node("pci-config", [&] (Xml_node const &pci) {
enum class Pci_class : unsigned {
WIFI = 0x28000,
NIC = 0x20000,
VGA = 0x30000,
AHCI = 0x10601,
NVME = 0x10802,
UHCI = 0xc0300, OHCI = 0xc0310, EHCI = 0xc0320, XHCI = 0xc0330,
};
enum class Pci_vendor : unsigned { INTEL = 0x8086U, };
auto matches_class = [&] (Pci_class value)
{
return pci.attribute_value("class", 0U) == unsigned(value);
};
auto matches_vendor = [&] (Pci_vendor value)
{
return pci.attribute_value("vendor_id", 0U) == unsigned(value);
};
if (matches_class(Pci_class::WIFI)) detected.wifi = true;
if (matches_class(Pci_class::NIC)) detected.nic = true;
if (matches_class(Pci_class::NVME)) detected.nvme = true;
if (matches_class(Pci_class::UHCI) || matches_class(Pci_class::OHCI)
|| matches_class(Pci_class::EHCI) || matches_class(Pci_class::XHCI))
detected.usb = true;
if (matches_class(Pci_class::AHCI) && matches_vendor(Pci_vendor::INTEL))
detected.ahci = true;
if (matches_class(Pci_class::VGA)) {
vga = true;
if (matches_vendor(Pci_vendor::INTEL))
detected.intel_gfx = true;
}
});
});
if (detected.intel_gfx)
detected.boot_fb = false;
if (vga && !detected.intel_gfx && !detected.boot_fb)
detected.vesa = true;
return detected;
}
#endif /* _MODEL__BOARD_INFO_H_ */

View File

@ -63,7 +63,7 @@ void Sculpt::Network::handle_key_press(Codepoint code)
if (_wifi_connection.state == Wifi_connection::CONNECTING)
wifi_connect(_wifi_connection.bssid);
_action.update_network_dialog();
_action.network_config_changed();
}
@ -93,9 +93,9 @@ void Sculpt::Network::_generate_nic_router_config()
bool uplink_exists = true;
switch (_nic_target.type()) {
case Nic_target::WIRED: _generate_nic_router_uplink(xml, "nic_drv -> "); break;
case Nic_target::WIFI: _generate_nic_router_uplink(xml, "wifi_drv -> "); break;
case Nic_target::MODEM: _generate_nic_router_uplink(xml, "usb_net -> "); break;
case Nic_target::WIRED: _generate_nic_router_uplink(xml, "nic -> "); break;
case Nic_target::WIFI: _generate_nic_router_uplink(xml, "wifi -> "); break;
case Nic_target::MODEM: _generate_nic_router_uplink(xml, "usb_net -> "); break;
default: uplink_exists = false;
}
gen_named_node(xml, "domain", "default", [&] () {
@ -189,7 +189,7 @@ void Sculpt::Network::_handle_wlan_accesspoints()
}
);
_action.update_network_dialog();
_action.network_config_changed();
}
@ -197,7 +197,7 @@ void Sculpt::Network::_handle_wlan_state()
{
_wlan_state_rom.update();
_wifi_connection = Wifi_connection::from_xml(_wlan_state_rom.xml());
_action.update_network_dialog();
_action.network_config_changed();
}
@ -209,7 +209,7 @@ void Sculpt::Network::_handle_nic_router_state()
_nic_state = Nic_state::from_xml(_nic_router_state_rom.xml());
if (_nic_state.ipv4 != old_nic_state.ipv4)
_action.update_network_dialog();
_action.network_config_changed();
/* if the nic state becomes ready, consider spawning the update subsystem */
if (old_nic_state.ready() != _nic_state.ready())
@ -236,10 +236,10 @@ void Sculpt::Network::_update_nic_target_from_config(Xml_node const &config)
if (uplink.attribute_value("domain", String<16>()) != "uplink")
return;
if (uplink.attribute_value("label_prefix", String<16>()) == "nic_drv -> ")
if (uplink.attribute_value("label_prefix", String<16>()) == "nic -> ")
result = Nic_target::WIRED;
if (uplink.attribute_value("label_prefix", String<16>()) == "wifi_drv -> ")
if (uplink.attribute_value("label_prefix", String<16>()) == "wifi -> ")
result = Nic_target::WIFI;
if (uplink.attribute_value("label_prefix", String<16>()) == "usb_net -> ")
@ -259,22 +259,12 @@ void Sculpt::Network::_handle_nic_router_config(Xml_node config)
_update_nic_target_from_config(config);
_generate_nic_router_config();
_runtime_config_generator.generate_runtime_config();
_action.update_network_dialog();
_action.network_config_changed();
}
void Sculpt::Network::gen_runtime_start_nodes(Xml_generator &xml) const
{
if (_nic_target.type() == Nic_target::WIRED)
xml.node("start", [&] () {
xml.attribute("version", _nic_drv_version);
gen_nic_drv_start_content(xml); });
if (_nic_target.type() == Nic_target::WIFI)
xml.node("start", [&] () {
xml.attribute("version", _wifi_drv_version);
gen_wifi_drv_start_content(xml); });
bool const nic_router_needed = _nic_target.type() != Nic_target::OFF
&& _nic_target.type() != Nic_target::UNDEFINED;

View File

@ -37,7 +37,7 @@ struct Sculpt::Network : Noncopyable
struct Action : Interface
{
virtual void update_network_dialog() = 0;
virtual void network_config_changed() = 0;
};
struct Info : Interface
@ -52,8 +52,6 @@ struct Sculpt::Network : Noncopyable
Runtime_config_generator &_runtime_config_generator;
Runtime_info const &_runtime_info;
using Wlan_config_policy = Network_widget::Wlan_config_policy;
Nic_target _nic_target { };
@ -67,18 +65,17 @@ struct Sculpt::Network : Noncopyable
unsigned _wifi_drv_version = 0;
Attached_rom_dataspace _wlan_accesspoints_rom {
_env, "report -> runtime/wifi_drv/accesspoints" };
_env, "report -> runtime/wifi/accesspoints" };
Attached_rom_dataspace _wlan_state_rom {
_env, "report -> runtime/wifi_drv/state" };
_env, "report -> runtime/wifi/state" };
Attached_rom_dataspace _nic_router_state_rom {
_env, "report -> runtime/nic_router/state" };
void _generate_nic_router_config();
void _generate_nic_router_uplink(Xml_generator &xml,
char const *label);
void _generate_nic_router_uplink(Xml_generator &xml, char const *label);
Access_points _access_points { };
@ -120,7 +117,7 @@ struct Sculpt::Network : Noncopyable
{
if (_wlan_config.try_generate_manually_managed()) {
_wlan_config_policy = Wlan_config_policy::MANUAL;
_action.update_network_dialog();
_action.network_config_changed();
return;
}
@ -140,7 +137,7 @@ struct Sculpt::Network : Noncopyable
_nic_target.managed_type = type;
_generate_nic_router_config();
_runtime_config_generator.generate_runtime_config();
_action.update_network_dialog();
_action.network_config_changed();
}
}
@ -210,13 +207,11 @@ struct Sculpt::Network : Noncopyable
Network(Env &env, Allocator &alloc, Action &action, Info const &info,
Registry<Child_state> &child_states,
Runtime_config_generator &runtime_config_generator,
Runtime_info const &runtime_info)
Runtime_config_generator &runtime_config_generator)
:
_env(env), _alloc(alloc), _action(action), _info(info),
_child_states(child_states),
_runtime_config_generator(runtime_config_generator),
_runtime_info(runtime_info)
_runtime_config_generator(runtime_config_generator)
{
/*
* Subscribe to reports

View File

@ -22,11 +22,9 @@
#include <runtime/file_system.cc>
#include <runtime/fs_rom.cc>
#include <runtime/gpt_write.cc>
#include <runtime/nic_drv.cc>
#include <runtime/nic_router.cc>
#include <runtime/prepare.cc>
#include <runtime/ram_fs.cc>
#include <runtime/runtime_view.cc>
#include <runtime/update.cc>
#include <runtime/wifi_drv.cc>
#include <runtime/fs_tool.cc>

View File

@ -69,9 +69,6 @@ namespace Sculpt {
void gen_gpt_relabel_start_content(Xml_generator &, Storage_device const &);
void gen_gpt_expand_start_content (Xml_generator &, Storage_device const &);
void gen_nic_drv_start_content(Xml_generator &);
void gen_wifi_drv_start_content(Xml_generator &);
void gen_nic_router_start_content(Xml_generator &);
void gen_nic_router_uplink(Xml_generator &, char const *);

View File

@ -1,46 +0,0 @@
/*
* \brief XML configuration for wired NIC driver
* \author Norman Feske
* \date 2018-05-02
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <runtime.h>
#include <uplink_session/uplink_session.h>
void Sculpt::gen_nic_drv_start_content(Xml_generator &xml)
{
gen_common_start_content(xml, "nic_drv",
Cap_quota{300}, Ram_quota{20*1024*1024},
Priority::NETWORK);
gen_named_node(xml, "resource", "CPU", [&] () { xml.attribute("quantum", "10"); });
xml.node("config", [&] () { });
xml.node("route", [&] () {
gen_service_node<Uplink::Session>(xml, [&] () {
xml.node("child", [&] () {
xml.attribute("name", "nic_router"); }); });
gen_service_node<Platform::Session>(xml, [&] () {
xml.node("parent", [&] () {
xml.attribute("label", "nic"); }); });
gen_parent_rom_route(xml, "nic_drv");
gen_parent_rom_route(xml, "nic_drv.dtb");
gen_parent_rom_route(xml, "ld.lib.so");
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Rm_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
});
}

View File

@ -1,91 +0,0 @@
/*
* \brief XML configuration for wireless driver
* \author Norman Feske
* \date 2018-05-02
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#include <runtime.h>
void Sculpt::gen_wifi_drv_start_content(Xml_generator &xml)
{
gen_common_start_content(xml, "wifi_drv",
Cap_quota{250}, Ram_quota{32*1024*1024},
Priority::NETWORK);
xml.node("config", [&] () {
xml.attribute("dtb", "wifi_drv.dtb");
xml.node("vfs", [&] () {
gen_named_node(xml, "dir", "dev", [&] () {
xml.node("null", [&] () {});
xml.node("zero", [&] () {});
xml.node("log", [&] () {});
xml.node("null", [&] () {});
gen_named_node(xml, "jitterentropy", "random");
gen_named_node(xml, "jitterentropy", "urandom"); });
gen_named_node(xml, "inline", "rtc", [&] () {
xml.append("2018-01-01 00:01");
});
gen_named_node(xml, "dir", "firmware", [&] () {
xml.node("tar", [&] () {
xml.attribute("name", "wifi_firmware.tar");
});
});
});
xml.node("libc", [&] () {
xml.attribute("stdout", "/dev/null");
xml.attribute("stderr", "/dev/null");
xml.attribute("rtc", "/dev/rtc");
});
});
xml.node("route", [&] () {
xml.node("service", [&] () {
xml.attribute("name", "Uplink");
xml.node("child", [&] () {
xml.attribute("name", "nic_router");
xml.attribute("label", "wifi_drv -> ");
});
});
gen_service_node<Platform::Session>(xml, [&] () {
xml.node("parent", [&] () {
xml.attribute("label", "wifi"); }); });
gen_parent_rom_route(xml, "wifi_drv");
gen_parent_rom_route(xml, "wifi_drv.dtb");
gen_parent_rom_route(xml, "ld.lib.so");
gen_parent_rom_route(xml, "libcrypto.lib.so");
gen_parent_rom_route(xml, "vfs.lib.so");
gen_parent_rom_route(xml, "libc.lib.so");
gen_parent_rom_route(xml, "libm.lib.so");
gen_parent_rom_route(xml, "vfs_jitterentropy.lib.so");
gen_parent_rom_route(xml, "libssl.lib.so");
gen_parent_rom_route(xml, "wifi.lib.so");
gen_parent_rom_route(xml, "wifi_firmware.tar");
gen_parent_rom_route(xml, "wpa_driver_nl80211.lib.so");
gen_parent_rom_route(xml, "wpa_supplicant.lib.so");
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Rm_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Rtc::Session> (xml);
gen_parent_route<Report::Session> (xml);
gen_service_node<Rom_session>(xml, [&] () {
xml.attribute("label", "wifi_config");
xml.node("parent", [&] () {
xml.attribute("label", "config -> managed/wifi"); }); });
});
}

View File

@ -66,6 +66,26 @@ namespace Sculpt {
* Argument type for controlling the verification of downloads
*/
struct Verify { bool value; };
/**
* Utility for passing lambda arguments to non-template functions
*/
template <typename... ARGS>
struct With
{
struct Callback : Interface
{
virtual void operator () (ARGS &&...) const = 0;
};
template <typename FN>
struct Fn : Callback
{
FN const &_fn;
Fn(FN const &fn) : _fn(fn) { };
void operator () (ARGS &&... args) const override { _fn(args...); }
};
};
}
#endif /* _TYPES_H_ */

View File

@ -60,15 +60,15 @@ struct Sculpt::Network_widget : Widget<Frame>
s.widget(_local, selected);
if (target.managed() || target.manual_type == Nic_target::WIRED)
if (board_info.lan_present)
if (board_info.detected.nic)
s.widget(_wired, selected);
if (target.managed() || target.manual_type == Nic_target::WIFI)
if (board_info.wifi_present)
if (board_info.wifi_avail())
s.widget(_wifi, selected);
if (target.managed() || target.manual_type == Nic_target::MODEM)
if (board_info.modem_present)
if (board_info.soc.modem)
s.widget(_modem, selected);
}

View File

@ -94,6 +94,16 @@ namespace Sculpt {
gen_named_node(xml, "service", SESSION::service_name()); });
}
static inline void gen_common_routes(Xml_generator &xml)
{
gen_parent_rom_route(xml, "ld.lib.so");
gen_parent_route<Cpu_session> (xml);
gen_parent_route<Pd_session> (xml);
gen_parent_route<Log_session> (xml);
gen_parent_route<Timer::Session> (xml);
gen_parent_route<Report::Session>(xml);
}
static inline void gen_common_start_content(Xml_generator &xml,
Rom_name const &name,
Cap_quota const caps,