mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
sculpt: host AHCI driver in runtime
This patch moves the AHCI driver from the 'drivers -> dynamic' subsystem to the runtime, managed by the sculpt_manager. One implication of this change is the new need to supplement a device port number to the 'Storage_target', in addition to the existing label and partition. Previously, each block device was addressed by merely a label specified for a parent session. The meanings of the 'Storage_target' elements are now as follows. - The label corresponds to the driver component providing the storage. - The port is used as block-session label when opening the session at the driver. - The partition(s) denote the partition information contained in the block session. Components operating as clients of the AHCI driver (e.g., a file system) refer to their storage target as <label>-<port>.<partition> when a port is defined (for AHCI). For drivers w/o ports, like USB storage where each USB-block driver correponds to only one device, the storage target is denoted as <label>.<partition>. When no partition table is present, the '.<partition>' part is omitted. Issue #5150
This commit is contained in:
parent
e3803fb861
commit
206bf856bb
@ -42,7 +42,6 @@
|
||||
<policy label="dynamic -> config" report="driver_manager -> init.config"/>
|
||||
<policy label="driver_manager -> devices" report="platform_drv -> devices"/>
|
||||
<policy label="driver_manager -> dynamic_state" report="dynamic -> state"/>
|
||||
<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 -> devices" report="platform_drv -> devices"/>
|
||||
@ -127,7 +126,7 @@
|
||||
<report devices="yes" iommu="yes"/>
|
||||
<policy label_prefix="runtime -> ps2"> <device name="ps2"/> </policy>
|
||||
<policy label_prefix="runtime -> vesa_fb" info="yes"> <pci class="VGA"/> </policy>
|
||||
<policy label_prefix="dynamic -> ahci_drv"> <pci class="AHCI"/> </policy>
|
||||
<policy label_prefix="runtime -> ahci"> <pci class="AHCI"/> </policy>
|
||||
<policy label_prefix="dynamic -> nvme_drv" info="yes"> <pci class="NVME"/> </policy>
|
||||
<policy label_prefix="runtime -> usb" info="yes"> <pci class="USB"/> </policy>
|
||||
<policy label_prefix="runtime -> intel_gpu" info="yes">
|
||||
@ -147,7 +146,6 @@
|
||||
<service name="Report" label="init.config"> <child name="report_rom"/> </service>
|
||||
<service name="Report" label="block_devices"> <parent label="block_devices"/> </service>
|
||||
<service name="ROM" label="devices"> <child name="report_rom"/> </service>
|
||||
<service name="ROM" label="ahci_ports"> <child name="report_rom"/> </service>
|
||||
<service name="ROM" label="nvme_ns"> <child name="report_rom"/> </service>
|
||||
<service name="ROM" label="dynamic_state"> <child name="report_rom"/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
@ -167,7 +165,6 @@
|
||||
</provides>
|
||||
<route>
|
||||
<service name="Platform"> <child name="platform_drv"/> </service>
|
||||
<service name="Report" label="ahci_ports"> <child name="report_rom"/> </service>
|
||||
<service name="Report" label="nvme_ns"> <child name="report_rom"/> </service>
|
||||
<service name="Report" label="state"> <child name="report_rom"/> </service>
|
||||
<service name="Report"> <parent/> </service>
|
||||
|
@ -30,7 +30,6 @@ namespace Driver_manager {
|
||||
using namespace Genode;
|
||||
struct Main;
|
||||
struct Device_driver;
|
||||
struct Ahci_driver;
|
||||
struct Nvme_driver;
|
||||
|
||||
struct Priority { int value; };
|
||||
@ -114,62 +113,6 @@ class Driver_manager::Device_driver : Noncopyable
|
||||
};
|
||||
|
||||
|
||||
struct Driver_manager::Ahci_driver : Device_driver
|
||||
{
|
||||
void generate_start_node(Xml_generator &xml) const override
|
||||
{
|
||||
xml.node("start", [&] () {
|
||||
_gen_common_start_node_content(xml, "ahci_drv", "ahci_drv",
|
||||
Ram_quota{10*1024*1024}, Cap_quota{100},
|
||||
Priority{-1}, Version{0});
|
||||
_gen_provides_node<Block::Session>(xml);
|
||||
xml.node("config", [&] () {
|
||||
xml.node("report", [&] () { xml.attribute("ports", "yes"); });
|
||||
for (unsigned i = 0; i < 6; i++) {
|
||||
xml.node("policy", [&] () {
|
||||
xml.attribute("label_suffix", String<64>("ahci-", i));
|
||||
xml.attribute("device", i);
|
||||
xml.attribute("writeable", "yes");
|
||||
});
|
||||
}
|
||||
});
|
||||
xml.node("heartbeat", [&] () { });
|
||||
xml.node("route", [&] () {
|
||||
xml.node("service", [&] () {
|
||||
xml.attribute("name", "Report");
|
||||
xml.node("parent", [&] () { xml.attribute("label", "ahci_ports"); });
|
||||
});
|
||||
_gen_default_parent_route(xml);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
typedef String<32> Default_label;
|
||||
|
||||
void gen_service_forwarding_policy(Xml_generator &xml,
|
||||
Default_label const &default_label) const
|
||||
{
|
||||
for (unsigned i = 0; i < 6; i++) {
|
||||
xml.node("policy", [&] () {
|
||||
xml.attribute("label_suffix", String<64>("ahci-", i));
|
||||
xml.node("child", [&] () {
|
||||
xml.attribute("name", "ahci_drv"); });
|
||||
});
|
||||
}
|
||||
|
||||
if (default_label.valid()) {
|
||||
xml.node("policy", [&] () {
|
||||
xml.attribute("label_suffix", " default");
|
||||
xml.node("child", [&] () {
|
||||
xml.attribute("name", "ahci_drv");
|
||||
xml.attribute("label", default_label);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Driver_manager::Nvme_driver : Device_driver
|
||||
{
|
||||
void generate_start_node(Xml_generator &xml) const override
|
||||
@ -227,13 +170,11 @@ struct Driver_manager::Main
|
||||
|
||||
Attached_rom_dataspace _platform { _env, "platform_info" };
|
||||
Attached_rom_dataspace _devices { _env, "devices" };
|
||||
Attached_rom_dataspace _ahci_ports { _env, "ahci_ports" };
|
||||
Attached_rom_dataspace _nvme_ns { _env, "nvme_ns" };
|
||||
|
||||
Reporter _init_config { _env, "config", "init.config" };
|
||||
Reporter _block_devices { _env, "block_devices" };
|
||||
|
||||
Constructible<Ahci_driver> _ahci_driver { };
|
||||
Constructible<Nvme_driver> _nvme_driver { };
|
||||
|
||||
bool _devices_rom_parsed { false };
|
||||
@ -243,11 +184,6 @@ struct Driver_manager::Main
|
||||
Signal_handler<Main> _devices_update_handler {
|
||||
_env.ep(), *this, &Main::_handle_devices_update };
|
||||
|
||||
void _handle_ahci_ports_update();
|
||||
|
||||
Signal_handler<Main> _ahci_ports_update_handler {
|
||||
_env.ep(), *this, &Main::_handle_ahci_ports_update };
|
||||
|
||||
void _handle_nvme_ns_update();
|
||||
|
||||
Signal_handler<Main> _nvme_ns_update_handler {
|
||||
@ -261,8 +197,6 @@ struct Driver_manager::Main
|
||||
void _generate_init_config (Reporter &) const;
|
||||
void _generate_block_devices(Reporter &) const;
|
||||
|
||||
Ahci_driver::Default_label _default_block_device() const;
|
||||
|
||||
void _generate_block_devices()
|
||||
{
|
||||
/* devices must be detected before the checks below can be conducted */
|
||||
@ -270,8 +204,6 @@ struct Driver_manager::Main
|
||||
return;
|
||||
|
||||
/* check that all drivers completed initialization before reporting */
|
||||
if (_ahci_driver.constructed() && !_ahci_ports.xml().has_type("ports"))
|
||||
return;
|
||||
if (_nvme_driver.constructed() && !_nvme_ns.xml().has_type("controller"))
|
||||
return;
|
||||
|
||||
@ -284,13 +216,11 @@ struct Driver_manager::Main
|
||||
_block_devices.enabled(true);
|
||||
|
||||
_devices .sigh(_devices_update_handler);
|
||||
_ahci_ports.sigh(_ahci_ports_update_handler);
|
||||
_nvme_ns .sigh(_nvme_ns_update_handler);
|
||||
|
||||
_generate_init_config(_init_config);
|
||||
|
||||
_handle_devices_update();
|
||||
_handle_ahci_ports_update();
|
||||
_handle_nvme_ns_update();
|
||||
}
|
||||
};
|
||||
@ -326,11 +256,6 @@ void Driver_manager::Main::_handle_devices_update()
|
||||
});
|
||||
});
|
||||
|
||||
if (!_ahci_driver.constructed() && has_ahci) {
|
||||
_ahci_driver.construct();
|
||||
_generate_init_config(_init_config);
|
||||
}
|
||||
|
||||
if (!_nvme_driver.constructed() && has_nvme) {
|
||||
_nvme_driver.construct();
|
||||
_generate_init_config(_init_config);
|
||||
@ -340,16 +265,6 @@ void Driver_manager::Main::_handle_devices_update()
|
||||
}
|
||||
|
||||
|
||||
void Driver_manager::Main::_handle_ahci_ports_update()
|
||||
{
|
||||
_ahci_ports.update();
|
||||
_generate_block_devices();
|
||||
|
||||
/* update service forwarding rules */
|
||||
_generate_init_config(_init_config);
|
||||
}
|
||||
|
||||
|
||||
void Driver_manager::Main::_handle_nvme_ns_update()
|
||||
{
|
||||
_nvme_ns.update();
|
||||
@ -388,81 +303,27 @@ void Driver_manager::Main::_generate_init_config(Reporter &init_config) const
|
||||
_gen_parent_service_xml(xml, Capture::Session::service_name());
|
||||
});
|
||||
|
||||
if (_ahci_driver.constructed())
|
||||
_ahci_driver->generate_start_node(xml);
|
||||
|
||||
if (_nvme_driver.constructed())
|
||||
_nvme_driver->generate_start_node(xml);
|
||||
|
||||
/* block-service forwarding rules */
|
||||
bool const ahci = _ahci_driver.constructed() && _ahci_ports.xml().has_sub_node("port");
|
||||
bool const nvme = _nvme_driver.constructed() && _nvme_ns.xml().has_sub_node("namespace");
|
||||
|
||||
if (!ahci && !nvme) return;
|
||||
if (!nvme) return;
|
||||
|
||||
bool const ahci_and_nvme = ahci && nvme;
|
||||
xml.node("service", [&] () {
|
||||
xml.attribute("name", Block::Session::service_name());
|
||||
if (ahci)
|
||||
_ahci_driver->gen_service_forwarding_policy(xml,
|
||||
ahci_and_nvme ? Ahci_driver::Default_label() : _default_block_device());
|
||||
if (nvme)
|
||||
_nvme_driver->gen_service_forwarding_policy(xml,
|
||||
ahci_and_nvme ? Nvme_driver::Default_label() : "nvme-0");
|
||||
_nvme_driver->gen_service_forwarding_policy(xml, "nvme-0");
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Driver_manager::Ahci_driver::Default_label
|
||||
Driver_manager::Main::_default_block_device() const
|
||||
{
|
||||
unsigned num_devices = 0;
|
||||
|
||||
Ahci_driver::Default_label result;
|
||||
|
||||
_ahci_ports.xml().for_each_sub_node([&] (Xml_node ahci_port) {
|
||||
|
||||
/* count devices */
|
||||
num_devices++;
|
||||
|
||||
unsigned long const num = ahci_port.attribute_value("num", 0UL);
|
||||
result = Ahci_driver::Default_label("ahci-", num);
|
||||
});
|
||||
|
||||
/* if there is more than one device, we don't return a default device */
|
||||
return (num_devices == 1) ? result : Ahci_driver::Default_label();
|
||||
}
|
||||
|
||||
|
||||
void Driver_manager::Main::_generate_block_devices(Reporter &block_devices) const
|
||||
{
|
||||
Reporter::Xml_generator xml(block_devices, [&] () {
|
||||
|
||||
/* mention default block device in 'default' attribute */
|
||||
Ahci_driver::Default_label const default_label = _default_block_device();
|
||||
if (default_label.valid())
|
||||
xml.attribute("default", default_label);
|
||||
|
||||
_ahci_ports.xml().for_each_sub_node([&] (Xml_node ahci_port) {
|
||||
|
||||
xml.node("device", [&] () {
|
||||
|
||||
unsigned long const
|
||||
num = ahci_port.attribute_value("num", 0UL),
|
||||
block_count = ahci_port.attribute_value("block_count", 0UL),
|
||||
block_size = ahci_port.attribute_value("block_size", 0UL);
|
||||
|
||||
typedef String<80> Model;
|
||||
Model const model = ahci_port.attribute_value("model", Model());
|
||||
|
||||
xml.attribute("label", String<64>("ahci-", num));
|
||||
xml.attribute("block_count", block_count);
|
||||
xml.attribute("block_size", block_size);
|
||||
xml.attribute("model", model);
|
||||
});
|
||||
});
|
||||
|
||||
/* for now just report the first name space */
|
||||
if (_nvme_ns.xml().has_sub_node("namespace")) {
|
||||
|
||||
|
@ -328,6 +328,7 @@ struct Sculpt::Main : Input_event_handler,
|
||||
_block_devices_rom.update();
|
||||
_usb_driver.with_devices([&] (Xml_node const &usb_devices) {
|
||||
_storage.update(usb_devices,
|
||||
Xml_node { "<empty/> " }, /* ahci */
|
||||
_block_devices_rom.xml(),
|
||||
_block_devices_handler);
|
||||
});
|
||||
@ -2237,7 +2238,7 @@ void Sculpt::Main::_handle_runtime_state()
|
||||
|
||||
device.for_each_partition([&] (Partition &partition) {
|
||||
|
||||
Storage_target const target { device.label, partition.number };
|
||||
Storage_target const target { device.label, device.port, partition.number };
|
||||
|
||||
if (partition.check_in_progress) {
|
||||
String<64> name(target.label(), ".e2fsck");
|
||||
|
97
repos/gems/src/app/sculpt_manager/ahci_driver.h
Normal file
97
repos/gems/src/app/sculpt_manager/ahci_driver.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* \brief Sculpt AHCI-driver management
|
||||
* \author Norman Feske
|
||||
* \date 2024-03-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _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>
|
||||
|
||||
namespace Sculpt { struct Ahci_driver; }
|
||||
|
||||
|
||||
struct Sculpt::Ahci_driver : private Noncopyable
|
||||
{
|
||||
struct Action : Interface
|
||||
{
|
||||
virtual void handle_ahci_discovered() = 0;
|
||||
};
|
||||
|
||||
Env &_env;
|
||||
Action &_action;
|
||||
|
||||
Constructible<Child_state> _ahci { };
|
||||
|
||||
Attached_rom_dataspace _ports { _env, "report -> runtime/ahci/ports" };
|
||||
|
||||
Signal_handler<Ahci_driver> _ports_handler {
|
||||
_env.ep(), *this, &Ahci_driver::_handle_ports };
|
||||
|
||||
void _handle_ports()
|
||||
{
|
||||
_ports.update();
|
||||
_action.handle_ahci_discovered();
|
||||
}
|
||||
|
||||
Ahci_driver(Env &env, Action &action) : _env(env), _action(action)
|
||||
{
|
||||
_ports.sigh(_ports_handler);
|
||||
_ports_handler.local_submit();
|
||||
}
|
||||
|
||||
void gen_start_node(Xml_generator &xml) const
|
||||
{
|
||||
if (!_ahci.constructed())
|
||||
return;
|
||||
|
||||
xml.node("start", [&] {
|
||||
_ahci->gen_start_node_content(xml);
|
||||
gen_named_node(xml, "binary", "ahci_drv");
|
||||
gen_provides<Block::Session>(xml);
|
||||
xml.node("config", [&] {
|
||||
xml.node("report", [&] { xml.attribute("ports", "yes"); });
|
||||
for (unsigned i = 0; i < 6; i++)
|
||||
xml.node("policy", [&] {
|
||||
xml.attribute("label", i);
|
||||
xml.attribute("device", i);
|
||||
xml.attribute("writeable", "yes"); });
|
||||
});
|
||||
xml.node("route", [&] {
|
||||
gen_parent_route<Platform::Session>(xml);
|
||||
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);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
void update(Registry<Child_state> ®istry, Board_info const &board_info)
|
||||
{
|
||||
_ahci.conditional(board_info.ahci_present,
|
||||
registry, "ahci", Priority::DEFAULT,
|
||||
Ram_quota { 10*1024*1024 }, Cap_quota { 100 });
|
||||
}
|
||||
|
||||
void with_ahci_ports(auto const &fn) const { fn(_ports.xml()); }
|
||||
};
|
||||
|
||||
#endif /* _AHCI_DRIVER_H_ */
|
@ -116,6 +116,10 @@ void Graph::_view_selected_node_content(Scope<Depgraph, Frame, Vbox> &s,
|
||||
if ((name == "usb") && _storage_devices.usb_present)
|
||||
s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
|
||||
s.widget(_usb_devices_widget); });
|
||||
|
||||
if (name == "ahci")
|
||||
s.sub_scope<Frame>([&] (Scope<Depgraph, Frame, Vbox, Frame> &s) {
|
||||
s.widget(_ahci_devices_widget); });
|
||||
}
|
||||
|
||||
|
||||
@ -286,6 +290,7 @@ void Graph::click(Clicked_at const &at, Action &action)
|
||||
|
||||
_ram_fs_widget .propagate(at, _sculpt_partition, action);
|
||||
_block_devices_widget.propagate(at, action);
|
||||
_ahci_devices_widget .propagate(at, action);
|
||||
_usb_devices_widget .propagate(at, action);
|
||||
|
||||
_remove .propagate(at);
|
||||
@ -297,6 +302,7 @@ void Graph::clack(Clacked_at const &at, Action &action, Ram_fs_widget::Action &r
|
||||
{
|
||||
_ram_fs_widget .propagate(at, ram_fs_action);
|
||||
_block_devices_widget.propagate(at, action);
|
||||
_ahci_devices_widget .propagate(at, action);
|
||||
_usb_devices_widget .propagate(at, action);
|
||||
|
||||
_remove.propagate(at, [&] {
|
||||
|
@ -58,6 +58,10 @@ struct Sculpt::Graph : Widget<Depgraph>
|
||||
_block_devices_widget { Id { "block_devices" },
|
||||
_storage_devices, _sculpt_partition };
|
||||
|
||||
Hosted<Depgraph, Frame, Vbox, Frame, Ahci_devices_widget>
|
||||
_ahci_devices_widget { Id { "ahci_devices" },
|
||||
_storage_devices, _sculpt_partition };
|
||||
|
||||
Hosted<Depgraph, Frame, Vbox, Frame, Usb_devices_widget>
|
||||
_usb_devices_widget { Id { "usb_devices" },
|
||||
_storage_devices, _sculpt_partition };
|
||||
@ -99,6 +103,7 @@ struct Sculpt::Graph : Widget<Depgraph>
|
||||
void reset_storage_operation()
|
||||
{
|
||||
_block_devices_widget.reset_operation();
|
||||
_ahci_devices_widget.reset_operation();
|
||||
_usb_devices_widget.reset_operation();
|
||||
}
|
||||
};
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include <fb_driver.h>
|
||||
#include <ps2_driver.h>
|
||||
#include <usb_driver.h>
|
||||
#include <ahci_driver.h>
|
||||
#include <gui.h>
|
||||
#include <keyboard_focus.h>
|
||||
#include <network.h>
|
||||
@ -76,7 +77,8 @@ struct Sculpt::Main : Input_event_handler,
|
||||
Panel_dialog::State,
|
||||
Popup_dialog::Refresh,
|
||||
Screensaver::Action,
|
||||
Usb_driver::Action
|
||||
Usb_driver::Action,
|
||||
Ahci_driver::Action
|
||||
{
|
||||
Env &_env;
|
||||
|
||||
@ -223,17 +225,19 @@ struct Sculpt::Main : Input_event_handler,
|
||||
|
||||
_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);
|
||||
_fb_driver .update(_child_states, _board_info, _platform.xml());
|
||||
_ps2_driver .update(_child_states, _board_info);
|
||||
_ahci_driver.update(_child_states, _board_info);
|
||||
_update_usb_drivers();
|
||||
|
||||
update_network_dialog();
|
||||
generate_runtime_config();
|
||||
}
|
||||
|
||||
Ps2_driver _ps2_driver { };
|
||||
Fb_driver _fb_driver { };
|
||||
Usb_driver _usb_driver { _env, *this };
|
||||
Ps2_driver _ps2_driver { };
|
||||
Fb_driver _fb_driver { };
|
||||
Usb_driver _usb_driver { _env, *this };
|
||||
Ahci_driver _ahci_driver { _env, *this };
|
||||
|
||||
void _update_usb_drivers()
|
||||
{
|
||||
@ -270,9 +274,11 @@ struct Sculpt::Main : Input_event_handler,
|
||||
{
|
||||
_block_devices_rom.update();
|
||||
_usb_driver.with_devices([&] (Xml_node const &usb_devices) {
|
||||
_storage.update(usb_devices,
|
||||
_block_devices_rom.xml(),
|
||||
_block_devices_handler);
|
||||
_ahci_driver.with_ahci_ports([&] (Xml_node const &ahci_ports) {
|
||||
_storage.update(usb_devices, ahci_ports,
|
||||
_block_devices_rom.xml(),
|
||||
_block_devices_handler);
|
||||
});
|
||||
});
|
||||
|
||||
/* update USB policies for storage devices */
|
||||
@ -294,6 +300,11 @@ struct Sculpt::Main : Input_event_handler,
|
||||
_storage.gen_usb_storage_policies(xml);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ahci_driver::Action
|
||||
*/
|
||||
void handle_ahci_discovered() override { _handle_block_devices(); }
|
||||
|
||||
/**
|
||||
* Storage::Action interface
|
||||
*/
|
||||
@ -1883,7 +1894,7 @@ void Sculpt::Main::_handle_runtime_state()
|
||||
|
||||
device.for_each_partition([&] (Partition &partition) {
|
||||
|
||||
Storage_target const target { device.label, partition.number };
|
||||
Storage_target const target { device.label, device.port, partition.number };
|
||||
|
||||
if (partition.check_in_progress) {
|
||||
String<64> name(target.label(), ".e2fsck");
|
||||
@ -2116,9 +2127,10 @@ 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);
|
||||
_ps2_driver .gen_start_node (xml);
|
||||
_fb_driver .gen_start_nodes(xml);
|
||||
_usb_driver .gen_start_nodes(xml);
|
||||
_ahci_driver.gen_start_node (xml);
|
||||
|
||||
_dialog_runtime.gen_start_nodes(xml);
|
||||
|
||||
|
57
repos/gems/src/app/sculpt_manager/model/ahci_device.h
Normal file
57
repos/gems/src/app/sculpt_manager/model/ahci_device.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* \brief Representation of AHCI devices
|
||||
* \author Norman Feske
|
||||
* \date 2024-04-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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 _MODEL__AHCI_DEVICE_H_
|
||||
#define _MODEL__AHCI_DEVICE_H_
|
||||
|
||||
#include <model/storage_device.h>
|
||||
|
||||
namespace Sculpt {
|
||||
|
||||
struct Ahci_device;
|
||||
|
||||
using Ahci_devices = List_model<Ahci_device>;
|
||||
};
|
||||
|
||||
|
||||
struct Sculpt::Ahci_device : List_model<Ahci_device>::Element, Storage_device
|
||||
{
|
||||
using Model = String<16>;
|
||||
|
||||
Model const model;
|
||||
|
||||
static Port _port(Xml_node const &node)
|
||||
{
|
||||
return node.attribute_value("num", Port());
|
||||
}
|
||||
|
||||
static Capacity _capacity(Xml_node const &node)
|
||||
{
|
||||
return { node.attribute_value("block_size", 0ULL)
|
||||
* node.attribute_value("block_count", 0ULL) };
|
||||
}
|
||||
|
||||
Ahci_device(Env &env, Allocator &alloc, Signal_context_capability sigh,
|
||||
Xml_node const &node)
|
||||
:
|
||||
Storage_device(env, alloc, Storage_device::Provider::RUNTIME,
|
||||
"ahci", _port(node), _capacity(node), sigh),
|
||||
model(node.attribute_value("model", Model()))
|
||||
{ }
|
||||
|
||||
bool matches(Xml_node const &node) const { return _port(node) == port; }
|
||||
|
||||
static bool type_matches(Xml_node const &) { return true; }
|
||||
};
|
||||
|
||||
#endif /* _MODEL__AHCI_DEVICE_H_ */
|
@ -35,7 +35,8 @@ struct Sculpt::Block_device : List_model<Block_device>::Element,
|
||||
Block_device(Env &env, Allocator &alloc, Signal_context_capability sigh,
|
||||
Label const &label, Model const &model, Capacity capacity)
|
||||
:
|
||||
Storage_device(env, alloc, label, capacity, sigh), model(model)
|
||||
Storage_device(env, alloc, Storage_device::Provider::PARENT,
|
||||
label, Port { }, capacity, sigh), model(model)
|
||||
{ }
|
||||
|
||||
bool matches(Xml_node const &node) const
|
||||
|
@ -51,7 +51,7 @@ struct Sculpt::Board_info
|
||||
WIFI = 0x28000,
|
||||
LAN = 0x20000,
|
||||
VGA = 0x30000,
|
||||
AHCI = 0x10600,
|
||||
AHCI = 0x10601,
|
||||
NVME = 0x10800,
|
||||
UHCI = 0xc0300, OHCI = 0xc0310, EHCI = 0xc0320, XHCI = 0xc0330,
|
||||
};
|
||||
|
@ -67,7 +67,7 @@ struct Sculpt::Discovery_state
|
||||
if (!partition.whole_device()
|
||||
&& partition.label == "GENODE*"
|
||||
&& partition.file_system.accessible())
|
||||
target = Storage_target { device.label, partition.number }; });
|
||||
target = Storage_target { device.label, device.port, partition.number }; });
|
||||
};
|
||||
|
||||
if (!target.valid())
|
||||
@ -82,7 +82,7 @@ struct Sculpt::Discovery_state
|
||||
devices.block_devices.for_each([&] (Storage_device const &device) {
|
||||
if (device.whole_device
|
||||
&& device.whole_device_partition->file_system.accessible())
|
||||
target = Storage_target { device.label, Partition::Number() }; });
|
||||
target = Storage_target { device.label, device.port, Partition::Number() }; });
|
||||
|
||||
if (target.valid())
|
||||
_done = true;
|
||||
|
@ -14,10 +14,9 @@
|
||||
#ifndef _MODEL__STORAGE_DEVICE_H_
|
||||
#define _MODEL__STORAGE_DEVICE_H_
|
||||
|
||||
#include "types.h"
|
||||
#include "partition.h"
|
||||
#include "capacity.h"
|
||||
#include "xml.h"
|
||||
#include <model/partition.h>
|
||||
#include <model/capacity.h>
|
||||
#include <xml.h>
|
||||
|
||||
namespace Sculpt { struct Storage_device; };
|
||||
|
||||
@ -33,9 +32,24 @@ struct Sculpt::Storage_device
|
||||
|
||||
Allocator &_alloc;
|
||||
|
||||
typedef String<32> Label;
|
||||
enum class Provider { PARENT, RUNTIME };
|
||||
|
||||
Label const label;
|
||||
using Label = String<32>;
|
||||
using Port = String<8>;
|
||||
|
||||
Provider const provider;
|
||||
Label const label; /* driver name, or label of parent session */
|
||||
Port const port;
|
||||
|
||||
Label name() const
|
||||
{
|
||||
return port.valid() ? Start_name { label, "-", port }
|
||||
: Start_name { label };
|
||||
}
|
||||
|
||||
Start_name part_block_start_name() const { return { name(), ".part_block" }; }
|
||||
Start_name relabel_start_name() const { return { name(), ".relabel" }; }
|
||||
Start_name expand_start_name() const { return { name(), ".expand" }; }
|
||||
|
||||
Capacity capacity; /* non-const because USB storage devices need to update it */
|
||||
|
||||
@ -114,14 +128,15 @@ struct Sculpt::Storage_device
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* \param label label of block device
|
||||
* \param label label of block device at parent, or driver name
|
||||
* \param sigh signal handler to be notified on partition-info updates
|
||||
*/
|
||||
Storage_device(Env &env, Allocator &alloc, Label const &label,
|
||||
Storage_device(Env &env, Allocator &alloc, Provider provider,
|
||||
Label const &label, Port const &port,
|
||||
Capacity capacity, Signal_context_capability sigh)
|
||||
:
|
||||
_alloc(alloc), label(label), capacity(capacity),
|
||||
_partitions_rom(env, String<80>("report -> runtime/", label, ".part_block/partitions").string())
|
||||
_alloc(alloc), provider(provider), label(label), port(port), capacity(capacity),
|
||||
_partitions_rom(env, String<80>("report -> runtime/", part_block_start_name(), "/partitions").string())
|
||||
{
|
||||
_partitions_rom.sigh(sigh);
|
||||
process_part_block_report();
|
||||
@ -156,13 +171,7 @@ struct Sculpt::Storage_device
|
||||
return needed_for_access;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate content of start node for part_block
|
||||
*
|
||||
* \param service_name name of server that provides the block device, or
|
||||
* if invalid, request block device from parent.
|
||||
*/
|
||||
inline void gen_part_block_start_content(Xml_generator &xml, Label const &server_name) const;
|
||||
inline void gen_part_block_start_content(Xml_generator &) const;
|
||||
|
||||
template <typename FN>
|
||||
void for_each_partition(FN const &fn) const
|
||||
@ -216,19 +225,14 @@ struct Sculpt::Storage_device
|
||||
}
|
||||
|
||||
bool discovery_in_progress() const { return state == UNKNOWN; }
|
||||
|
||||
Start_name part_block_start_name() const { return Start_name(label, ".part_block"); }
|
||||
Start_name relabel_start_name() const { return Start_name(label, ".relabel"); }
|
||||
Start_name expand_start_name() const { return Start_name(label, ".expand"); }
|
||||
};
|
||||
|
||||
|
||||
void Sculpt::Storage_device::gen_part_block_start_content(Xml_generator &xml,
|
||||
Label const &server_name) const
|
||||
void Sculpt::Storage_device::gen_part_block_start_content(Xml_generator &xml) const
|
||||
{
|
||||
xml.attribute("version", _part_block_version);
|
||||
|
||||
gen_common_start_content(xml, Label(label, ".part_block"),
|
||||
gen_common_start_content(xml, part_block_start_name(),
|
||||
Cap_quota{100}, Ram_quota{8*1024*1024},
|
||||
Priority::STORAGE);
|
||||
|
||||
@ -253,11 +257,13 @@ void Sculpt::Storage_device::gen_part_block_start_content(Xml_generator &xml,
|
||||
xml.node("route", [&] () {
|
||||
|
||||
gen_service_node<Block::Session>(xml, [&] () {
|
||||
if (server_name.valid())
|
||||
gen_named_node(xml, "child", server_name);
|
||||
if (provider == Provider::PARENT)
|
||||
xml.node("parent", [&] {
|
||||
xml.attribute("label", label); });
|
||||
else
|
||||
xml.node("parent", [&] () {
|
||||
xml.attribute("label", label); }); });
|
||||
gen_named_node(xml, "child", label, [&] {
|
||||
xml.attribute("label", port); });
|
||||
});
|
||||
|
||||
gen_parent_rom_route(xml, "part_block");
|
||||
gen_parent_rom_route(xml, "ld.lib.so");
|
||||
|
@ -14,9 +14,10 @@
|
||||
#ifndef _MODEL__STORAGE_DEVICES_
|
||||
#define _MODEL__STORAGE_DEVICES_
|
||||
|
||||
#include "types.h"
|
||||
#include "block_device.h"
|
||||
#include "usb_storage_device.h"
|
||||
#include <types.h>
|
||||
#include <model/block_device.h>
|
||||
#include <model/ahci_device.h>
|
||||
#include <model/usb_storage_device.h>
|
||||
|
||||
namespace Sculpt { struct Storage_devices; }
|
||||
|
||||
@ -24,6 +25,7 @@ namespace Sculpt { struct Storage_devices; }
|
||||
struct Sculpt::Storage_devices
|
||||
{
|
||||
Block_devices block_devices { };
|
||||
Ahci_devices ahci_devices { };
|
||||
Usb_storage_devices usb_storage_devices { };
|
||||
|
||||
bool _block_devices_report_valid = false;
|
||||
@ -60,8 +62,32 @@ struct Sculpt::Storage_devices
|
||||
_block_devices_report_valid = true;
|
||||
}
|
||||
|
||||
bool update_ahci_devices_from_xml(Env &env, Allocator &alloc, Xml_node node,
|
||||
Signal_context_capability sigh)
|
||||
{
|
||||
bool progress = false;
|
||||
ahci_devices.update_from_xml(node,
|
||||
|
||||
/* create */
|
||||
[&] (Xml_node const &node) -> Ahci_device & {
|
||||
progress = true;
|
||||
return *new (alloc) Ahci_device(env, alloc, sigh, node);
|
||||
},
|
||||
|
||||
/* destroy */
|
||||
[&] (Ahci_device &a) {
|
||||
destroy(alloc, &a);
|
||||
progress = true;
|
||||
},
|
||||
|
||||
/* update */
|
||||
[&] (Ahci_device &, Xml_node const &) { }
|
||||
);
|
||||
return progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update 'usb_storage_devices' from 'usb_active_config' report
|
||||
* Update 'usb_storage_devices' from USB devices report
|
||||
*
|
||||
* \return true if USB storage device was added or vanished
|
||||
*/
|
||||
@ -125,6 +151,9 @@ struct Sculpt::Storage_devices
|
||||
block_devices.for_each([&] (Block_device const &dev) {
|
||||
fn(dev); });
|
||||
|
||||
ahci_devices.for_each([&] (Ahci_device const &dev) {
|
||||
fn(dev); });
|
||||
|
||||
usb_storage_devices.for_each([&] (Usb_storage_device const &dev) {
|
||||
fn(dev); });
|
||||
}
|
||||
@ -135,6 +164,9 @@ struct Sculpt::Storage_devices
|
||||
block_devices.for_each([&] (Block_device &dev) {
|
||||
fn(dev); });
|
||||
|
||||
ahci_devices.for_each([&] (Ahci_device &dev) {
|
||||
fn(dev); });
|
||||
|
||||
usb_storage_devices.for_each([&] (Usb_storage_device &dev) {
|
||||
fn(dev); });
|
||||
}
|
||||
|
@ -22,26 +22,35 @@ namespace Sculpt { struct Storage_target; }
|
||||
|
||||
struct Sculpt::Storage_target
|
||||
{
|
||||
typedef String<Storage_device::Label::capacity() + 4> Label;
|
||||
using Label = String<Storage_device::Label::capacity() + 5>;
|
||||
|
||||
Storage_device::Label device;
|
||||
Storage_device::Port port;
|
||||
Partition::Number partition;
|
||||
|
||||
bool operator == (Storage_target const &other) const
|
||||
{
|
||||
return (device == other.device) && (partition == other.partition);
|
||||
return (device == other.device)
|
||||
&& (port == other.port)
|
||||
&& (partition == other.partition);
|
||||
}
|
||||
|
||||
bool operator != (Storage_target const &other) const { return !(*this == other); }
|
||||
|
||||
bool valid() const { return device.valid(); }
|
||||
|
||||
Label device_and_port() const
|
||||
{
|
||||
return port.valid() ? Label { device, "-", port } : Label { device };
|
||||
}
|
||||
|
||||
/**
|
||||
* Return string to be used as session label referring to the target
|
||||
*/
|
||||
Label label() const
|
||||
{
|
||||
return partition.valid() ? Label(device, ".", partition) : Label(device);
|
||||
return partition.valid() ? Label(device_and_port(), ".", partition)
|
||||
: Label(device_and_port());
|
||||
}
|
||||
|
||||
bool ram_fs() const { return device == "ram_fs"; }
|
||||
@ -50,7 +59,9 @@ struct Sculpt::Storage_target
|
||||
|
||||
void gen_block_session_route(Xml_generator &xml) const
|
||||
{
|
||||
bool const usb = (Label(Cstring(device.string(), 3)) == "usb");
|
||||
bool const usb = (Label(Cstring(device.string(), 3)) == "usb");
|
||||
bool const ahci = (Label(Cstring(device.string(), 4)) == "ahci");
|
||||
|
||||
bool const whole_device = !partition.valid();
|
||||
|
||||
xml.node("service", [&] () {
|
||||
@ -58,10 +69,11 @@ struct Sculpt::Storage_target
|
||||
|
||||
if (whole_device) {
|
||||
|
||||
if (usb)
|
||||
if (usb || ahci)
|
||||
xml.node("child", [&] () {
|
||||
xml.attribute("name", Label(device, ".drv"));
|
||||
xml.attribute("label", partition);
|
||||
xml.attribute("name", device);
|
||||
if (port.valid())
|
||||
xml.attribute("label", port);
|
||||
});
|
||||
else
|
||||
xml.node("parent", [&] () { xml.attribute("label", device); });
|
||||
@ -70,7 +82,7 @@ struct Sculpt::Storage_target
|
||||
/* access partition */
|
||||
else {
|
||||
xml.node("child", [&] () {
|
||||
xml.attribute("name", Label(device, ".part_block"));
|
||||
xml.attribute("name", Label(device_and_port(), ".part_block"));
|
||||
xml.attribute("label", partition);
|
||||
});
|
||||
}
|
||||
|
@ -107,7 +107,8 @@ struct Sculpt::Usb_storage_device : List_model<Usb_storage_device>::Element,
|
||||
Usb_storage_device(Env &env, Allocator &alloc, Signal_context_capability sigh,
|
||||
Label const &label)
|
||||
:
|
||||
Storage_device(env, alloc, label, Capacity{0}, sigh),
|
||||
Storage_device(env, alloc, Storage_device::Provider::RUNTIME, label,
|
||||
Port { }, Capacity{0}, sigh),
|
||||
_driver_report_rom(env, String<80>("report -> runtime/", usb_block_drv_name(),
|
||||
"/devices").string())
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ void Sculpt::_gen_gpt_write_start_content(Xml_generator &xml,
|
||||
|
||||
xml.node("route", [&] () {
|
||||
|
||||
Storage_target const target { device.label, Partition::Number { } };
|
||||
Storage_target const target { device.label, device.port, Partition::Number { } };
|
||||
target.gen_block_session_route(xml);
|
||||
|
||||
gen_parent_rom_route(xml, "gpt_write");
|
||||
|
@ -22,7 +22,7 @@ static void for_each_inspected_storage_target(Storage_devices const &devices, FN
|
||||
devices.for_each([&] (Storage_device const &device) {
|
||||
device.for_each_partition([&] (Partition const &partition) {
|
||||
if (partition.file_system.inspected)
|
||||
fn(Storage_target { device.label, partition.number }); }); });
|
||||
fn(Storage_target { device.label, device.port, partition.number }); }); });
|
||||
}
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
|
||||
void Sculpt::Storage::update(Xml_node const &usb_devices,
|
||||
Xml_node const &ahci_ports,
|
||||
Xml_node const &block_devices,
|
||||
Signal_context_capability sigh)
|
||||
{
|
||||
@ -32,6 +33,15 @@ void Sculpt::Storage::update(Xml_node const &usb_devices,
|
||||
reconfigure_runtime = true;
|
||||
};
|
||||
|
||||
{
|
||||
reconfigure_runtime |=
|
||||
_storage_devices.update_ahci_devices_from_xml(_env, _alloc, ahci_ports,
|
||||
sigh);
|
||||
|
||||
_storage_devices.ahci_devices.for_each([&] (Ahci_device &dev) {
|
||||
process_part_block_report(dev); });
|
||||
}
|
||||
|
||||
{
|
||||
_storage_devices.update_block_devices_from_xml(_env, _alloc, block_devices,
|
||||
sigh);
|
||||
@ -100,41 +110,42 @@ void Sculpt::Storage::gen_runtime_start_nodes(Xml_generator &xml) const
|
||||
xml.node("start", [&] () {
|
||||
gen_ram_fs_start_content(xml, _ram_fs_state); });
|
||||
|
||||
auto part_block_needed_for_use = [&] (Storage_device const &dev) {
|
||||
return (_sculpt_partition.device == dev.label)
|
||||
&& _sculpt_partition.partition.valid(); };
|
||||
auto contains_used_fs = [&] (Storage_device const &device)
|
||||
{
|
||||
if (!_sculpt_partition.valid())
|
||||
return false;
|
||||
|
||||
_storage_devices.block_devices.for_each([&] (Block_device const &dev) {
|
||||
|
||||
if (dev.part_block_needed_for_discovery()
|
||||
|| dev.part_block_needed_for_access()
|
||||
|| part_block_needed_for_use(dev))
|
||||
if (device.provider == Storage_device::Provider::PARENT)
|
||||
return (device.label == _sculpt_partition.device);
|
||||
|
||||
return (device.port == _sculpt_partition.port)
|
||||
&& (device.label == _sculpt_partition.device);
|
||||
};
|
||||
|
||||
_storage_devices.usb_storage_devices.for_each([&] (Usb_storage_device const &device) {
|
||||
|
||||
if (device.usb_block_drv_needed() || contains_used_fs(device))
|
||||
xml.node("start", [&] () {
|
||||
Storage_device::Label const parent { };
|
||||
dev.gen_part_block_start_content(xml, parent); }); });
|
||||
|
||||
_storage_devices.usb_storage_devices.for_each([&] (Usb_storage_device const &dev) {
|
||||
|
||||
if (dev.usb_block_drv_needed() || _sculpt_partition.device == dev.label)
|
||||
xml.node("start", [&] () {
|
||||
dev.gen_usb_block_drv_start_content(xml); });
|
||||
|
||||
if (dev.part_block_needed_for_discovery()
|
||||
|| dev.part_block_needed_for_access()
|
||||
|| part_block_needed_for_use(dev))
|
||||
|
||||
xml.node("start", [&] () {
|
||||
Storage_device::Label const driver = dev.usb_block_drv_name();
|
||||
dev.gen_part_block_start_content(xml, driver);
|
||||
});
|
||||
device.gen_usb_block_drv_start_content(xml); });
|
||||
});
|
||||
|
||||
_storage_devices.for_each([&] (Storage_device const &device) {
|
||||
|
||||
bool const device_contains_used_fs_in_partition =
|
||||
contains_used_fs(device) && !device.whole_device;
|
||||
|
||||
bool const part_block_needed = device.part_block_needed_for_discovery()
|
||||
|| device.part_block_needed_for_access()
|
||||
|| device_contains_used_fs_in_partition;
|
||||
if (part_block_needed)
|
||||
xml.node("start", [&] {
|
||||
device.gen_part_block_start_content(xml); });
|
||||
|
||||
device.for_each_partition([&] (Partition const &partition) {
|
||||
|
||||
Storage_target const target { device.label, partition.number };
|
||||
Storage_target const target { .device = device.label,
|
||||
.port = device.port,
|
||||
.partition = partition.number };
|
||||
|
||||
if (partition.check_in_progress) {
|
||||
xml.node("start", [&] () {
|
||||
|
@ -53,7 +53,8 @@ struct Sculpt::Storage : Storage_device_widget::Action, Ram_fs_widget::Action
|
||||
|
||||
Inspect_view_version _inspect_view_version { 0 };
|
||||
|
||||
void update(Xml_node const &usb_devices, Xml_node const &block_devices,
|
||||
void update(Xml_node const &usb_devices, Xml_node const &ahci_ports,
|
||||
Xml_node const &block_devices,
|
||||
Signal_context_capability sigh);
|
||||
|
||||
/*
|
||||
|
@ -29,7 +29,7 @@ void Partition_operations::view(Scope<Vbox> &s,
|
||||
|
||||
bool const whole_device = !partition.number.valid();
|
||||
|
||||
Storage_target const target { device.label, partition.number };
|
||||
Storage_target const target { device.label, device.port, partition.number };
|
||||
|
||||
bool const device_in_use = (used_target.device == device.label);
|
||||
|
||||
|
@ -22,7 +22,7 @@ namespace Sculpt { struct Ram_fs_widget; }
|
||||
|
||||
struct Sculpt::Ram_fs_widget : Widget<Vbox>
|
||||
{
|
||||
Storage_target const _target { "ram_fs", Partition::Number() };
|
||||
Storage_target const _target { "ram_fs", { }, Partition::Number() };
|
||||
|
||||
struct Action : Interface, Noncopyable
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ struct Dialog::Partition_button : Widget<Hbox>
|
||||
if (partition.label.length() > 1)
|
||||
s.sub_scope<Label>(String<80>(" (", partition.label, ") "));
|
||||
|
||||
Storage_target const target { device.label, partition.number };
|
||||
Storage_target const target { device.label, device.port, partition.number };
|
||||
if (used_target == target)
|
||||
s.sub_scope<Label>("* ");
|
||||
});
|
||||
|
@ -35,12 +35,11 @@ struct Sculpt::Storage_device_widget : Widget<Vbox>
|
||||
_partition_operations.reset_operation();
|
||||
}
|
||||
|
||||
void click(Clicked_at const &at, Storage_target const &used_target, Action &action)
|
||||
void click(Clicked_at const &at, Storage_device const &device, Storage_target const &used_target, Action &action)
|
||||
{
|
||||
Id const device_id = at.matching_id<Vbox>();
|
||||
Id const partition_id = at.matching_id<Vbox, Hbox>();
|
||||
|
||||
Storage_target const selected_target { device_id.value, _selected_partition };
|
||||
Storage_target const selected_target { device.label, device.port, _selected_partition };
|
||||
|
||||
if (partition_id.valid()) {
|
||||
_selected_partition = (partition_id.value == _selected_partition)
|
||||
@ -53,11 +52,9 @@ struct Sculpt::Storage_device_widget : Widget<Vbox>
|
||||
_partition_operations.click(at, selected_target, used_target, action);
|
||||
}
|
||||
|
||||
void clack(Clacked_at const &at, Action &action)
|
||||
void clack(Clacked_at const &at, Storage_device const &device, Action &action)
|
||||
{
|
||||
Id const device_id = at.matching_id<Vbox>();
|
||||
|
||||
Storage_target const selected_target { device_id.value, _selected_partition };
|
||||
Storage_target const selected_target { device.label, device.port, _selected_partition };
|
||||
|
||||
_partition_operations.clack(at, selected_target, action);
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ struct Sculpt::Storage_devices_widget_base : Widget<Vbox>
|
||||
template <typename DEVICE, typename BUTTON>
|
||||
void _view_device(Scope<Vbox> &s, DEVICE const &dev, BUTTON const &button) const
|
||||
{
|
||||
bool const selected = ( _selected_device == dev.label );
|
||||
bool const selected = ( _selected_device == dev.name() );
|
||||
|
||||
s.widget(button, dev, selected, _used_target);
|
||||
|
||||
@ -51,6 +51,14 @@ struct Sculpt::Storage_devices_widget_base : Widget<Vbox>
|
||||
}
|
||||
}
|
||||
|
||||
void _with_selected_device(auto const &fn) const
|
||||
{
|
||||
if (_selected_device.valid() && _storage_device_widget.constructed())
|
||||
_storage_devices.for_each([&] (Storage_device const &dev) {
|
||||
if (_selected_device == dev.name())
|
||||
fn(dev); });
|
||||
}
|
||||
|
||||
template <typename BUTTON>
|
||||
void _click_device(Clicked_at const &at, Storage_device_widget::Action &action)
|
||||
{
|
||||
@ -66,14 +74,14 @@ struct Sculpt::Storage_devices_widget_base : Widget<Vbox>
|
||||
}
|
||||
}
|
||||
|
||||
if (_selected_device.valid() && _storage_device_widget.constructed())
|
||||
_storage_device_widget->propagate(at, _used_target, action);
|
||||
_with_selected_device([&] (Storage_device const &dev) {
|
||||
_storage_device_widget->propagate(at, dev, _used_target, action); });
|
||||
}
|
||||
|
||||
void _clack_device(Clacked_at const &at, Storage_device_widget::Action &action)
|
||||
{
|
||||
if (_selected_device.valid() && _storage_device_widget.constructed())
|
||||
_storage_device_widget->propagate(at, action);
|
||||
_with_selected_device([&] (Storage_device const &dev) {
|
||||
_storage_device_widget->propagate(at, dev, action); });
|
||||
}
|
||||
|
||||
void reset_operation()
|
||||
@ -90,11 +98,16 @@ struct Sculpt::Storage_devices_widget_base : Widget<Vbox>
|
||||
};
|
||||
|
||||
|
||||
namespace Sculpt { struct Block_device_button; }
|
||||
namespace Sculpt { struct Storage_device_button; }
|
||||
|
||||
struct Sculpt::Block_device_button : Widget<Button>
|
||||
struct Sculpt::Storage_device_button : Widget<Button>
|
||||
{
|
||||
void view(Scope<Button> &s, Block_device const &dev, bool const selected,
|
||||
using Model = String<64>;
|
||||
Model const model;
|
||||
|
||||
Storage_device_button(Model const &model) : model(model) { }
|
||||
|
||||
void view(Scope<Button> &s, Storage_device const &dev, bool const selected,
|
||||
Storage_target const &used_target) const
|
||||
{
|
||||
if (s.hovered()) s.attribute("hovered", "yes");
|
||||
@ -103,9 +116,9 @@ struct Sculpt::Block_device_button : Widget<Button>
|
||||
s.sub_scope<Hbox>([&] (Scope<Button, Hbox> &s) {
|
||||
s.sub_scope<Left_floating_hbox>(
|
||||
[&] (Scope<Button, Hbox, Left_floating_hbox> &s) {
|
||||
s.sub_scope<Label>(dev.label);
|
||||
s.sub_scope<Label>(String<80>(" (", dev.model, ") "));
|
||||
if (used_target.device == dev.label)
|
||||
s.sub_scope<Label>(dev.name());
|
||||
s.sub_scope<Label>(String<80>(" (", model, ") "));
|
||||
if (used_target.device_and_port() == dev.name())
|
||||
s.sub_scope<Label>("* ");
|
||||
});
|
||||
|
||||
@ -127,14 +140,41 @@ struct Sculpt::Block_devices_widget : Storage_devices_widget_base
|
||||
{
|
||||
s.sub_scope<Min_ex>(35);
|
||||
_storage_devices.block_devices.for_each([&] (Block_device const &dev) {
|
||||
Hosted<Vbox, Block_device_button> button { Id { dev.label } };
|
||||
Hosted<Vbox, Storage_device_button> button { Id { dev.name() }, dev.model };
|
||||
_view_device(s, dev, button);
|
||||
});
|
||||
}
|
||||
|
||||
void click(Clicked_at const &at, Storage_device_widget::Action &action)
|
||||
{
|
||||
_click_device<Block_device_button>(at, action);
|
||||
_click_device<Storage_device_button>(at, action);
|
||||
}
|
||||
|
||||
void clack(Clacked_at const &at, Storage_device_widget::Action &action)
|
||||
{
|
||||
_clack_device(at, action);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
namespace Sculpt { struct Ahci_devices_widget; }
|
||||
|
||||
struct Sculpt::Ahci_devices_widget : Storage_devices_widget_base
|
||||
{
|
||||
using Storage_devices_widget_base::Storage_devices_widget_base;
|
||||
|
||||
void view(Scope<Vbox> &s) const
|
||||
{
|
||||
s.sub_scope<Min_ex>(35);
|
||||
_storage_devices.ahci_devices.for_each([&] (Ahci_device const &dev) {
|
||||
Hosted<Vbox, Storage_device_button> button { Id { dev.name() }, dev.model };
|
||||
_view_device(s, dev, button);
|
||||
});
|
||||
}
|
||||
|
||||
void click(Clicked_at const &at, Storage_device_widget::Action &action)
|
||||
{
|
||||
_click_device<Storage_device_button>(at, action);
|
||||
}
|
||||
|
||||
void clack(Clacked_at const &at, Storage_device_widget::Action &action)
|
||||
@ -159,12 +199,12 @@ struct Sculpt::Usb_storage_device_button : Widget<Button>
|
||||
s.sub_scope<Hbox>([&] (Scope<Button, Hbox> &s) {
|
||||
s.sub_scope<Left_floating_hbox>(
|
||||
[&] (Scope<Button, Hbox, Left_floating_hbox> &s) {
|
||||
s.sub_scope<Label>(dev.label);
|
||||
s.sub_scope<Label>(dev.name());
|
||||
if (dev.driver_info.constructed()) {
|
||||
String<16> const vendor { dev.driver_info->vendor };
|
||||
s.sub_scope<Label>(String<64>(" (", vendor, ") "));
|
||||
}
|
||||
if (used_target.device == dev.label)
|
||||
if (used_target.device_and_port() == dev.name())
|
||||
s.sub_scope<Label>("* ");
|
||||
});
|
||||
|
||||
@ -190,7 +230,7 @@ struct Sculpt::Usb_devices_widget : Storage_devices_widget_base
|
||||
{
|
||||
s.sub_scope<Min_ex>(35);
|
||||
_storage_devices.usb_storage_devices.for_each([&] (Usb_storage_device const &dev) {
|
||||
Hosted<Vbox, Usb_storage_device_button> button { Id { dev.label } };
|
||||
Hosted<Vbox, Usb_storage_device_button> button { Id { dev.name() } };
|
||||
_view_device(s, dev, button);
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user