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:
Norman Feske 2024-03-21 15:23:06 +01:00 committed by Christian Helmuth
parent e3803fb861
commit 206bf856bb
24 changed files with 396 additions and 259 deletions

View File

@ -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>

View File

@ -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")) {

View File

@ -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");

View 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> &registry, 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_ */

View File

@ -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, [&] {

View File

@ -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();
}
};

View File

@ -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);

View 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_ */

View File

@ -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

View File

@ -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,
};

View File

@ -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;

View File

@ -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");

View File

@ -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); });
}

View File

@ -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);
});
}

View File

@ -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())
{

View File

@ -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");

View File

@ -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 }); }); });
}

View File

@ -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", [&] () {

View File

@ -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);
/*

View File

@ -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);

View File

@ -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
{

View File

@ -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>("* ");
});

View File

@ -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);
}

View File

@ -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);
});
}