diff --git a/repos/gems/recipes/pkg/sculpt/archives b/repos/gems/recipes/pkg/sculpt/archives index 51f69b996..482040abb 100644 --- a/repos/gems/recipes/pkg/sculpt/archives +++ b/repos/gems/recipes/pkg/sculpt/archives @@ -45,3 +45,4 @@ _/src/zlib _/src/menu_view _/src/gpt_write _/src/sculpt_manager +_/src/fs_query diff --git a/repos/gems/run/sculpt.run b/repos/gems/run/sculpt.run index 404903b14..e3e4fb6d3 100644 --- a/repos/gems/run/sculpt.run +++ b/repos/gems/run/sculpt.run @@ -110,6 +110,7 @@ install_config { + } [config_system_content] { @@ -514,7 +515,7 @@ close $fd # -# Manual configuration of deploy runtime +# Configuration of deploy runtime # # This configuration is not provided as a file at run/sculpt/ because some # parts need to be filled in at run-script execution time, in particular the @@ -532,200 +533,24 @@ append manual_deploy_config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + } @@ -734,6 +559,51 @@ puts $fd $manual_deploy_config close $fd +# +# Install launcher snippets +# +# The launcher snippets are wrapped into a tar archive to be loaded as boot +# module. This procedure involves the following steps: +# +# The launcher snippets are copied from run/sculpt/launcher/ to +# [run_dir]/genode/launcher. Each launcher is inspected regarding its 'pkg' +# attribute. If its 'pkg' attribute contains a single identifier (rather than +# a valid pkg path), the attribute value is replaced by a valid pkg path +# referring to the current version of the pkg and the [depot_user]. The +# filtered launchers are archived into 'launcher.tar' and removed from the +# [run_dir]. +# + +set launchers [glob -tails -directory [genode_dir]/repos/gems/run/sculpt/launcher/ *] + +foreach file $launchers { + + # skip backup files + if {[regexp {~$} $file dummy]} { continue } + + set fd [open [genode_dir]/repos/gems/run/sculpt/launcher/$file r] + set content [read $fd] + close $fd + + # filter 'pkg' attribute + set pattern {(\]+?pkg=")([^/]+)(")} + if {[regexp $pattern $content dummy head pkg tail]} { + set pkg_path [depot_user]/pkg/[current_pkg $pkg] + regsub $pattern $content "$head$pkg_path$tail" content + } + + # write filtered launcher snippet + file mkdir [run_dir]/genode/launcher + set fd [open [run_dir]/genode/launcher/$file w] + puts $fd $content + close $fd +} + +# wrap launcher snippets into tar archive and remove individual snippets +exec tar cf [run_dir]/genode/launcher.tar -C [run_dir]/genode launcher +exec rm -r [run_dir]/genode/launcher + + # # Create boot image # diff --git a/repos/gems/run/sculpt/launcher/2048 b/repos/gems/run/sculpt/launcher/2048 new file mode 100644 index 000000000..4bae8f555 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/2048 @@ -0,0 +1,5 @@ + + + + + diff --git a/repos/gems/run/sculpt/launcher/acpica b/repos/gems/run/sculpt/launcher/acpica new file mode 100644 index 000000000..0fb7ed3c5 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/acpica @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/backdrop b/repos/gems/run/sculpt/launcher/backdrop new file mode 100644 index 000000000..ae0ad5ac8 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/backdrop @@ -0,0 +1,5 @@ + + + + + diff --git a/repos/gems/run/sculpt/launcher/config_editor b/repos/gems/run/sculpt/launcher/config_editor new file mode 100644 index 000000000..0b88be586 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/config_editor @@ -0,0 +1,7 @@ + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/download_debian b/repos/gems/run/sculpt/launcher/download_debian new file mode 100644 index 000000000..35533fe6e --- /dev/null +++ b/repos/gems/run/sculpt/launcher/download_debian @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/fonts_fs b/repos/gems/run/sculpt/launcher/fonts_fs new file mode 100644 index 000000000..e9aa7bdca --- /dev/null +++ b/repos/gems/run/sculpt/launcher/fonts_fs @@ -0,0 +1,5 @@ + + + + + diff --git a/repos/gems/run/sculpt/launcher/gambatte b/repos/gems/run/sculpt/launcher/gambatte new file mode 100644 index 000000000..8508c9d33 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/gambatte @@ -0,0 +1,5 @@ + + + + + diff --git a/repos/gems/run/sculpt/launcher/nano3d b/repos/gems/run/sculpt/launcher/nano3d new file mode 100644 index 000000000..38d39fed9 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/nano3d @@ -0,0 +1,5 @@ + + + + + diff --git a/repos/gems/run/sculpt/launcher/noux-system b/repos/gems/run/sculpt/launcher/noux-system new file mode 100644 index 000000000..342a8f153 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/noux-system @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/report_dump b/repos/gems/run/sculpt/launcher/report_dump new file mode 100644 index 000000000..6849520d7 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/report_dump @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/seoul-vmm-browser b/repos/gems/run/sculpt/launcher/seoul-vmm-browser new file mode 100644 index 000000000..7a552e0e8 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/seoul-vmm-browser @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/shared_fs b/repos/gems/run/sculpt/launcher/shared_fs new file mode 100644 index 000000000..5f32c4264 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/shared_fs @@ -0,0 +1,6 @@ + + + + + + diff --git a/repos/gems/run/sculpt/launcher/top_view b/repos/gems/run/sculpt/launcher/top_view new file mode 100644 index 000000000..a60d7e3d3 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/top_view @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/usb_devices_rom b/repos/gems/run/sculpt/launcher/usb_devices_rom new file mode 100644 index 000000000..b432c3c03 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/usb_devices_rom @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/vbox5-tc-browser b/repos/gems/run/sculpt/launcher/vbox5-tc-browser new file mode 100644 index 000000000..9bf6974ea --- /dev/null +++ b/repos/gems/run/sculpt/launcher/vbox5-tc-browser @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/vm b/repos/gems/run/sculpt/launcher/vm new file mode 100644 index 000000000..5cd90f615 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/vm @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/repos/gems/run/sculpt/launcher/vm_fs b/repos/gems/run/sculpt/launcher/vm_fs new file mode 100644 index 000000000..4f77086ef --- /dev/null +++ b/repos/gems/run/sculpt/launcher/vm_fs @@ -0,0 +1,6 @@ + + + + + + diff --git a/repos/gems/run/sculpt/launcher/wm b/repos/gems/run/sculpt/launcher/wm new file mode 100644 index 000000000..a48fdf651 --- /dev/null +++ b/repos/gems/run/sculpt/launcher/wm @@ -0,0 +1,6 @@ + + + + + + diff --git a/repos/gems/src/app/depot_deploy/child.h b/repos/gems/src/app/depot_deploy/child.h index f03583e3d..c6b5e9a55 100644 --- a/repos/gems/src/app/depot_deploy/child.h +++ b/repos/gems/src/app/depot_deploy/child.h @@ -35,13 +35,15 @@ class Depot_deploy::Child : public List_model::Element typedef String<80> Binary_name; typedef String<80> Config_name; typedef String<32> Depot_rom_server; + typedef String<100> Launcher_name; private: Allocator &_alloc; - Reconstructible _start_xml; /* from config */ - Constructible _pkg_xml { }; /* from blueprint */ + Reconstructible _start_xml; /* from config */ + Constructible _launcher_xml { }; + Constructible _pkg_xml { }; /* from blueprint */ /* * State of the condition check for generating the start node of @@ -55,11 +57,34 @@ class Depot_deploy::Child : public List_model::Element Name const _name; + bool _defined_by_launcher() const + { + /* + * If the node lacks a 'pkg' attribute, we expect the + * policy to be defined by a launcher XML snippet. + */ + return _start_xml.constructed() && !_start_xml->xml().has_attribute("pkg"); + } + Archive::Path _config_pkg_path() const { + if (_defined_by_launcher() && _launcher_xml.constructed()) + return _launcher_xml->xml().attribute_value("pkg", Archive::Path()); + return _start_xml->xml().attribute_value("pkg", Archive::Path()); } + Launcher_name _launcher_name() const + { + if (!_defined_by_launcher()) + return Launcher_name(); + + if (_start_xml->xml().has_attribute("launcher")) + return _start_xml->xml().attribute_value("launcher", Launcher_name()); + + return _start_xml->xml().attribute_value("name", Launcher_name()); + } + /* * The pkg-archive path of the current blueprint query, which may * deviate from pkg path given in the config, once the config is @@ -67,8 +92,12 @@ class Depot_deploy::Child : public List_model::Element */ Archive::Path _blueprint_pkg_path = _config_pkg_path(); - Ram_quota _ram_quota { 0 }; - Cap_quota _cap_quota { 0 }; + /* + * Quota definitions obtained from the blueprint + */ + Number_of_bytes _pkg_ram_quota { 0 }; + unsigned long _pkg_cap_quota { 0 }; + Binary_name _binary_name { }; Config_name _config_name { }; @@ -131,20 +160,21 @@ class Depot_deploy::Child : public List_model::Element if (!start_node_changed) return; - Archive::Path const pkg = - start_node.attribute_value("pkg", Archive::Path()); - - /* invalidate blueprint if 'pkg' attribute of start node changed */ - if (pkg != _config_pkg_path()) - _pkg_xml.destruct(); - - _blueprint_pkg_path = pkg; + Archive::Path const old_pkg_path = _config_pkg_path(); /* import new start node */ _start_xml.construct(_alloc, start_node); - /* reset error state, attempt to obtain the blueprint again */ - _pkg_incomplete = false; + Archive::Path const new_pkg_path = _config_pkg_path(); + + /* invalidate blueprint if 'pkg' path changed */ + if (old_pkg_path != new_pkg_path) { + _blueprint_pkg_path = new_pkg_path; + _pkg_xml.destruct(); + + /* reset error state, attempt to obtain the blueprint again */ + _pkg_incomplete = false; + } } void apply_blueprint(Xml_node pkg) @@ -157,11 +187,8 @@ class Depot_deploy::Child : public List_model::Element Xml_node const runtime = pkg.sub_node("runtime"); - Number_of_bytes const ram { runtime.attribute_value("ram", Number_of_bytes()) }; - _ram_quota = Ram_quota { _start_xml->xml().attribute_value("ram", ram) }; - - unsigned long const caps = runtime.attribute_value("caps", 0UL); - _cap_quota = Cap_quota { _start_xml->xml().attribute_value("caps", caps) }; + _pkg_ram_quota = runtime.attribute_value("ram", Number_of_bytes()); + _pkg_cap_quota = runtime.attribute_value("caps", 0UL); _binary_name = runtime.attribute_value("binary", Binary_name()); _config_name = runtime.attribute_value("config", Config_name()); @@ -170,22 +197,57 @@ class Depot_deploy::Child : public List_model::Element _pkg_xml.construct(_alloc, pkg); } - template - void apply_condition(COND_FN const &fn) + void apply_launcher(Launcher_name const &name, Xml_node launcher) { - /* don't check the condition twice */ - if (_condition == SATISFIED) + if (!_defined_by_launcher()) return; + if (_launcher_name() != name) + return; + + if (_launcher_xml.constructed()) { + bool const launcher_changed = + (launcher.size() != _launcher_xml->xml().size()) || + (strcmp(launcher.addr(), _launcher_xml->xml().addr(), + launcher.size()) != 0); + + if (!launcher_changed) + return; + } + + _launcher_xml.construct(_alloc, launcher); + + _blueprint_pkg_path = _config_pkg_path(); + } + + /* + * \return true if condition changed + */ + template + bool apply_condition(COND_FN const &fn) + { + Condition const orig_condition = _condition; + + Xml_node launcher_xml = _launcher_xml.constructed() + ? _launcher_xml->xml() + : Xml_node(""); + if (_start_xml.constructed()) - _condition = fn(_start_xml->xml()) ? SATISFIED : UNSATISFIED; + _condition = fn(_start_xml->xml(), launcher_xml) + ? SATISFIED : UNSATISFIED; + + return _condition != orig_condition; } template void apply_if_unsatisfied(FN const &fn) const { + Xml_node launcher_xml = _launcher_xml.constructed() + ? _launcher_xml->xml() + : Xml_node(""); + if (_condition == UNSATISFIED && _start_xml.constructed()) - fn(_start_xml->xml()); + fn(_start_xml->xml(), launcher_xml); } void mark_as_incomplete(Xml_node missing) @@ -219,6 +281,9 @@ class Depot_deploy::Child : public List_model::Element if (_configured() || _pkg_incomplete) return; + if (_defined_by_launcher() && !_launcher_xml.constructed()) + return; + xml.node("blueprint", [&] () { xml.attribute("pkg", _blueprint_pkg_path); }); } @@ -264,6 +329,9 @@ void Depot_deploy::Child::gen_start_node(Xml_generator &xml, Xml_node common, if (!_configured() || _condition == UNSATISFIED) return; + if (_defined_by_launcher() && !_launcher_xml.constructed()) + return; + if (!_pkg_xml->xml().has_sub_node("runtime")) { warning("blueprint for '", _name, "' lacks runtime information"); return; @@ -272,7 +340,13 @@ void Depot_deploy::Child::gen_start_node(Xml_generator &xml, Xml_node common, xml.node("start", [&] () { xml.attribute("name", _name); - xml.attribute("caps", _cap_quota.value); + + unsigned long caps = _pkg_cap_quota; + if (_defined_by_launcher()) + caps = _launcher_xml->xml().attribute_value("caps", caps); + caps = _start_xml->xml().attribute_value("caps", caps); + + xml.attribute("caps", caps); typedef String<64> Version; Version const version = _start_xml->xml().attribute_value("version", Version()); @@ -281,22 +355,32 @@ void Depot_deploy::Child::gen_start_node(Xml_generator &xml, Xml_node common, xml.node("binary", [&] () { xml.attribute("name", _binary_name); }); + Number_of_bytes ram = _pkg_ram_quota; + if (_defined_by_launcher()) + ram = _launcher_xml->xml().attribute_value("ram", ram); + ram = _start_xml->xml().attribute_value("ram", ram); + xml.node("resource", [&] () { xml.attribute("name", "RAM"); - xml.attribute("quantum", String<32>(Number_of_bytes(_ram_quota.value))); + xml.attribute("quantum", String<32>(ram)); }); Xml_node const runtime = _pkg_xml->xml().sub_node("runtime"); /* - * Insert inline '' node if provided by the start node or the + * Insert inline '' node if provided by the start node, + * the launcher definition (if a launcher is user), or the * blueprint. The former is preferred over the latter. */ if (_start_xml->xml().has_sub_node("config")) { _gen_copy_of_sub_node(xml, _start_xml->xml(), "config"); } else { - if (runtime.has_sub_node("config")) - _gen_copy_of_sub_node(xml, runtime, "config"); + if (_defined_by_launcher() && _launcher_xml->xml().has_sub_node("config")) { + _gen_copy_of_sub_node(xml, _launcher_xml->xml(), "config"); + } else { + if (runtime.has_sub_node("config")) + _gen_copy_of_sub_node(xml, runtime, "config"); + } } /* @@ -344,6 +428,14 @@ void Depot_deploy::Child::_gen_routes(Xml_generator &xml, Xml_node common, xml.append(route.content_base(), route.content_size()); } + /* + * Add routes given in the launcher definition. + */ + if (_launcher_xml.constructed() && _launcher_xml->xml().has_sub_node("route")) { + Xml_node const route = _launcher_xml->xml().sub_node("route"); + xml.append(route.content_base(), route.content_size()); + } + /** * Return name of depot-ROM server used for obtaining the 'path' * diff --git a/repos/gems/src/app/depot_deploy/children.h b/repos/gems/src/app/depot_deploy/children.h index 9ebe065b1..7b76c4ec0 100644 --- a/repos/gems/src/app/depot_deploy/children.h +++ b/repos/gems/src/app/depot_deploy/children.h @@ -67,6 +67,12 @@ class Depot_deploy::Children _children.update_from_xml(_model_update_policy, config); } + void apply_launcher(Child::Launcher_name const &name, Xml_node launcher) + { + _children.for_each([&] (Child &child) { + child.apply_launcher(name, launcher); }); + } + void apply_blueprint(Xml_node blueprint) { blueprint.for_each_sub_node("pkg", [&] (Xml_node pkg) { @@ -78,11 +84,16 @@ class Depot_deploy::Children child.mark_as_incomplete(missing); }); }); } + /* + * \return true if the condition of any child changed + */ template - void apply_condition(COND_FN const &fn) + bool apply_condition(COND_FN const &fn) { + bool any_condition_changed = false; _children.for_each([&] (Child &child) { - child.apply_condition(fn); }); + any_condition_changed |= child.apply_condition(fn); }); + return any_condition_changed; } /** diff --git a/repos/gems/src/app/sculpt_manager/deploy.cc b/repos/gems/src/app/sculpt_manager/deploy.cc index e960da45e..28dbc231f 100644 --- a/repos/gems/src/app/sculpt_manager/deploy.cc +++ b/repos/gems/src/app/sculpt_manager/deploy.cc @@ -17,33 +17,30 @@ bool Sculpt::Deploy::update_child_conditions() { - /* track whether any condition changed for the better */ - bool result = false; + /* return true if any condition changed */ + return _children.apply_condition([&] (Xml_node start, Xml_node launcher) { - _children.apply_condition([&] (Xml_node start) { - - /* the child cannot be started as long as any dependency is missing */ + /* the child cannot run as long as any dependency is missing */ bool condition = true; _for_each_missing_server(start, [&] (Start_name const &) { condition = false; }); + _for_each_missing_server(launcher, [&] (Start_name const &) { + condition = false; }); - result |= condition; return condition; }); - return result; } -void Sculpt::Deploy::_gen_missing_dependencies(Xml_generator &xml, +void Sculpt::Deploy::_gen_missing_dependencies(Xml_generator &xml, Start_name const &name, Xml_node start, int &count) const { - Start_name const child = start.attribute_value("name", Start_name()); _for_each_missing_server(start, [&] (Start_name const &server) { gen_named_node(xml, "hbox", String<20>(count++), [&] () { gen_named_node(xml, "float", "left", [&] () { xml.attribute("west", "yes"); xml.node("label", [&] () { - xml.attribute("text", String<64>(child, " requires ", server)); + xml.attribute("text", String<64>(name, " requires ", server)); xml.attribute("font", "annotation/regular"); }); }); @@ -55,7 +52,7 @@ void Sculpt::Deploy::_gen_missing_dependencies(Xml_generator &xml, void Sculpt::Deploy::gen_child_diagnostics(Xml_generator &xml) const { bool all_children_ok = true; - _children.for_each_unsatisfied_child([&] (Xml_node) { + _children.for_each_unsatisfied_child([&] (Xml_node, Xml_node) { all_children_ok = false; }); if (all_children_ok) @@ -70,8 +67,13 @@ void Sculpt::Deploy::gen_child_diagnostics(Xml_generator &xml) const xml.node("float", [&] () { xml.node("vbox", [&] () { - _children.for_each_unsatisfied_child([&] (Xml_node start) { - _gen_missing_dependencies(xml, start, count); }); }); }); + _children.for_each_unsatisfied_child([&] (Xml_node start, Xml_node launcher) { + Start_name const name = start.attribute_value("name", Start_name()); + _gen_missing_dependencies(xml, name, start, count); + _gen_missing_dependencies(xml, name, launcher, count); + }); + }); + }); }); }); } @@ -90,6 +92,31 @@ void Sculpt::Deploy::handle_deploy() catch (...) { error("spurious exception during deploy update (apply_config)"); } + /* + * Apply launchers + */ + Xml_node const launcher_listing = _launcher_listing_rom.xml(); + launcher_listing.for_each_sub_node("dir", [&] (Xml_node dir) { + + typedef String<20> Path; + Path const path = dir.attribute_value("path", Path()); + + if (path != "/launcher") + return; + + dir.for_each_sub_node("file", [&] (Xml_node file) { + + if (file.attribute_value("xml", false) == false) + return; + + typedef Depot_deploy::Child::Launcher_name Name; + Name const name = file.attribute_value("name", Name()); + + file.for_each_sub_node("launcher", [&] (Xml_node launcher) { + _children.apply_launcher(name, launcher); }); + }); + }); + /* update query for blueprints of all unconfigured start nodes */ if (_arch.valid()) { _depot_query_reporter.generate([&] (Xml_generator &xml) { diff --git a/repos/gems/src/app/sculpt_manager/deploy.h b/repos/gems/src/app/sculpt_manager/deploy.h index 728ca8191..ede29a0e7 100644 --- a/repos/gems/src/app/sculpt_manager/deploy.h +++ b/repos/gems/src/app/sculpt_manager/deploy.h @@ -54,6 +54,8 @@ struct Sculpt::Deploy Attached_rom_dataspace _manual_deploy_rom { _env, "config -> deploy" }; + Attached_rom_dataspace _launcher_listing_rom { _env, "report -> /runtime/launcher_query/listing" }; + Attached_rom_dataspace _blueprint_rom { _env, "report -> runtime/depot_query/blueprint" }; Expanding_reporter _depot_query_reporter { _env, "query", "depot_query"}; @@ -81,6 +83,7 @@ struct Sculpt::Deploy void _handle_manual_deploy() { _manual_deploy_rom.update(); + _launcher_listing_rom.update(); _query_version.value++; handle_deploy(); } @@ -125,7 +128,7 @@ struct Sculpt::Deploy */ bool update_child_conditions(); - void _gen_missing_dependencies(Xml_generator &, Xml_node, int &) const; + void _gen_missing_dependencies(Xml_generator &, Start_name const &, Xml_node, int &) const; void gen_child_diagnostics(Xml_generator &xml) const; @@ -134,6 +137,9 @@ struct Sculpt::Deploy Signal_handler _manual_deploy_handler { _env.ep(), *this, &Deploy::_handle_manual_deploy }; + Signal_handler _launcher_listing_handler { + _env.ep(), *this, &Deploy::_handle_manual_deploy }; + Signal_handler _blueprint_handler { _env.ep(), *this, &Deploy::_handle_blueprint }; @@ -160,6 +166,7 @@ struct Sculpt::Deploy _runtime_config_generator(runtime_config_generator) { _manual_deploy_rom.sigh(_manual_deploy_handler); + _launcher_listing_rom.sigh(_launcher_listing_handler); _blueprint_rom.sigh(_blueprint_handler); } }; diff --git a/repos/gems/src/app/sculpt_manager/main.cc b/repos/gems/src/app/sculpt_manager/main.cc index 7405086a3..ceae0f711 100644 --- a/repos/gems/src/app/sculpt_manager/main.cc +++ b/repos/gems/src/app/sculpt_manager/main.cc @@ -22,11 +22,11 @@ #include /* local includes */ +#include #include #include #include #include -#include #include #include #include @@ -38,7 +38,6 @@ namespace Sculpt { struct Main; } struct Sculpt::Main : Input_event_handler, Dialog::Generator, Runtime_config_generator, - Runtime_info, Storage::Target_user { Env &_env; @@ -155,7 +154,7 @@ struct Sculpt::Main : Input_event_handler, } - Network _network { _env, _heap, *this, *this, *this, _pci_info }; + Network _network { _env, _heap, *this, *this, _runtime_state, _pci_info }; /************ @@ -175,7 +174,7 @@ struct Sculpt::Main : Input_event_handler, && _network.ready() && _deploy.update_needed(); }; - Deploy _deploy { _env, _heap, *this, *this, *this }; + Deploy _deploy { _env, _heap, _runtime_state, *this, *this }; @@ -242,19 +241,9 @@ struct Sculpt::Main : Input_event_handler, }); } - Attached_rom_dataspace _runtime_state { _env, "report -> runtime/state" }; + Attached_rom_dataspace _runtime_state_rom { _env, "report -> runtime/state" }; - /** - * Runtime_info interface - */ - bool present_in_runtime(Start_name const &name) const override - { - bool present = false; - _runtime_state.xml().for_each_sub_node("child", [&] (Xml_node child) { - if (child.attribute_value("name", Start_name()) == name) - present = true; }); - return present; - } + Runtime_state _runtime_state { _heap }; Managed_config
_runtime_config { _env, "config", "runtime", *this, &Main::_handle_runtime }; @@ -372,7 +361,7 @@ struct Sculpt::Main : Input_event_handler, Main(Env &env) : _env(env) { - _runtime_state.sigh(_runtime_state_handler); + _runtime_state_rom.sigh(_runtime_state_handler); _nitpicker_displays.sigh(_nitpicker_displays_handler); /* @@ -631,9 +620,11 @@ void Sculpt::Main::_handle_update_state() void Sculpt::Main::_handle_runtime_state() { - _runtime_state.update(); + _runtime_state_rom.update(); - Xml_node state = _runtime_state.xml(); + Xml_node state = _runtime_state_rom.xml(); + + _runtime_state.update_from_state_report(state); bool reconfigure_runtime = false; @@ -861,8 +852,12 @@ void Sculpt::Main::_generate_runtime_config(Xml_generator &xml) const xml.node("start", [&] () { gen_update_start_content(xml); }); - if (_storage._sculpt_partition.valid() && !_prepare_in_progress()) + if (_storage._sculpt_partition.valid() && !_prepare_in_progress()) { + xml.node("start", [&] () { + gen_launcher_query_start_content(xml); }); + _deploy.gen_runtime_start_nodes(xml); + } } diff --git a/repos/gems/src/app/sculpt_manager/model/runtime_state.h b/repos/gems/src/app/sculpt_manager/model/runtime_state.h new file mode 100644 index 000000000..34ee5c3c6 --- /dev/null +++ b/repos/gems/src/app/sculpt_manager/model/runtime_state.h @@ -0,0 +1,87 @@ +/* + * \brief State of the components hosted in the runtime subsystem + * \author Norman Feske + * \date 2018-08-22 + */ + +/* + * 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. + */ + +#ifndef _MODEL__RUNTIME_STATE_H_ +#define _MODEL__RUNTIME_STATE_H_ + +/* Genode includes */ +#include +#include + +/* local includes */ +#include +#include + +namespace Sculpt { class Runtime_state; } + +class Sculpt::Runtime_state : public Runtime_info +{ + private: + + Allocator &_alloc; + + struct Child : List_model::Element + { + Start_name const name; + + Child(Start_name const &name) : name(name) { } + }; + + List_model _children { }; + + struct Update_policy : List_model::Update_policy + { + Allocator &_alloc; + + Update_policy(Allocator &alloc) : _alloc(alloc) { } + + void destroy_element(Child &elem) { destroy(_alloc, &elem); } + + Child &create_element(Xml_node node) + { + return *new (_alloc) + Child(node.attribute_value("name", Start_name())); + } + + void update_element(Child &, Xml_node) { } + + static bool element_matches_xml_node(Child const &elem, Xml_node node) + { + return node.attribute_value("name", Start_name()) == elem.name; + } + }; + + public: + + Runtime_state(Allocator &alloc) : _alloc(alloc) { } + + void update_from_state_report(Xml_node state) + { + Update_policy policy(_alloc); + _children.update_from_xml(policy, state); + } + + /** + * Runtime_info interface + */ + bool present_in_runtime(Start_name const &name) const override + { + bool result = false; + _children.for_each([&] (Child const &child) { + if (!result && child.name == name) + result = true; }); + return result; + } +}; + +#endif /* _MODEL__RUNTIME_STATE_H_ */ diff --git a/repos/gems/src/app/sculpt_manager/runtime.cc b/repos/gems/src/app/sculpt_manager/runtime.cc index 229d178c3..af0fcab8c 100644 --- a/repos/gems/src/app/sculpt_manager/runtime.cc +++ b/repos/gems/src/app/sculpt_manager/runtime.cc @@ -16,6 +16,7 @@ #include #include +#include #include #include #include diff --git a/repos/gems/src/app/sculpt_manager/runtime.h b/repos/gems/src/app/sculpt_manager/runtime.h index a82d238c8..d4fa17484 100644 --- a/repos/gems/src/app/sculpt_manager/runtime.h +++ b/repos/gems/src/app/sculpt_manager/runtime.h @@ -39,6 +39,7 @@ namespace Sculpt { Path const &, Writeable); void gen_depot_query_start_content(Xml_generator &); + void gen_launcher_query_start_content(Xml_generator &); struct File_browser_version { unsigned value; }; void gen_file_browser(Xml_generator &, Storage_devices const &, diff --git a/repos/gems/src/app/sculpt_manager/runtime/launcher_query.cc b/repos/gems/src/app/sculpt_manager/runtime/launcher_query.cc new file mode 100644 index 000000000..fbd66edd4 --- /dev/null +++ b/repos/gems/src/app/sculpt_manager/runtime/launcher_query.cc @@ -0,0 +1,48 @@ +/* + * \brief XML configuration for the fs-query tool for obtaining the launchers + * \author Norman Feske + * \date 2018-08-21 + */ + +/* + * 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 + +void Sculpt::gen_launcher_query_start_content(Xml_generator &xml) +{ + gen_common_start_content(xml, "launcher_query", + Cap_quota{200}, Ram_quota{2*1024*1024}); + + gen_named_node(xml, "binary", "fs_query"); + + xml.node("config", [&] () { + xml.attribute("query", "rom"); + xml.node("vfs", [&] () { + xml.node("fs", [&] () {}); }); + + xml.node("query", [&] () { + xml.attribute("path", "/launcher"); + xml.attribute("content", "yes"); + }); + }); + + xml.node("route", [&] () { + gen_parent_rom_route(xml, "fs_query"); + gen_parent_rom_route(xml, "ld.lib.so"); + gen_parent_rom_route(xml, "vfs.lib.so"); + + gen_parent_route (xml); + gen_parent_route (xml); + gen_parent_route (xml); + gen_parent_route (xml); + + gen_service_node<::File_system::Session>(xml, [&] () { + xml.node("parent", [&] () { + xml.attribute("label", "config"); }); }); + }); +}