diff --git a/os/include/loader_session/client.h b/os/include/loader_session/client.h index 7442ba8456..131321680f 100644 --- a/os/include/loader_session/client.h +++ b/os/include/loader_session/client.h @@ -21,35 +21,34 @@ namespace Loader { - struct Session_client : Genode::Rpc_client + struct Session_client : Rpc_client { - Session_client(Loader::Session_capability session) - : Genode::Rpc_client(session) { } + explicit Session_client(Loader::Session_capability session) + : Rpc_client(session) { } + Dataspace_capability alloc_rom_module(Name const &name, size_t size) { + return call(name, size); } - /****************************** - ** Loader-session interface ** - ******************************/ + void commit_rom_module(Name const &name) { + call(name); } - Genode::Dataspace_capability dataspace() { - return call(); } + void ram_quota(size_t quantum) { + call(quantum); } - void start(Start_args const &args, - int max_width, int max_height, - Genode::Alarm::Time timeout, - Name const &name = "") - { - call(args, max_width, max_height, timeout, name); - } + void constrain_geometry(int width, int height) { + call(width, height); } - Nitpicker::View_capability view(int *w, int *h, int *buf_x, int *buf_y) - { - int dummy = 0; - return call(w ? w : &dummy, - h ? h : &dummy, - buf_x ? buf_x : &dummy, - buf_y ? buf_y : &dummy); - } + void view_ready_sigh(Signal_context_capability sigh) { + call(sigh); } + + void start(Name const &binary, Name const &label = "") { + call(binary, label); } + + Nitpicker::View_capability view() { + return call(); } + + View_geometry view_geometry() { + return call(); } }; } diff --git a/os/include/loader_session/connection.h b/os/include/loader_session/connection.h index f05f80f9b2..1f3522a484 100644 --- a/os/include/loader_session/connection.h +++ b/os/include/loader_session/connection.h @@ -1,6 +1,7 @@ /* * \brief Connection to Loader service * \author Christian Prochaska + * \author Norman Feske * \date 2009-10-05 */ @@ -21,15 +22,9 @@ namespace Loader { struct Connection : Genode::Connection, Session_client { - /** - * Constructor - * - * \param args argument string stating the RAM quota to be - * transfered to the service - */ - Connection(const char *args) + Connection(size_t ram_quota) : - Genode::Connection(session(args)), + Genode::Connection(session("ram_quota=%zd", ram_quota)), Session_client(cap()) { } }; diff --git a/os/include/loader_session/loader_session.h b/os/include/loader_session/loader_session.h index 8b07292e0e..418ea6f0d9 100644 --- a/os/include/loader_session/loader_session.h +++ b/os/include/loader_session/loader_session.h @@ -1,6 +1,7 @@ /* * \brief Loader session interface * \author Christian Prochaska + * \author Norman Feske * \date 2009-10-05 */ @@ -18,56 +19,131 @@ #include #include #include -#include -#include +#include #include namespace Loader { + using namespace Genode; + struct Session : Genode::Session { - /** - * Exception type + /* + * Exception types */ - class Start_failed { }; - class Rom_access_failed : public Start_failed { }; - class Plugin_start_timed_out : public Start_failed { }; - class Invalid_args : public Start_failed { }; + struct Exception : Genode::Exception { }; + struct View_does_not_exist : Exception { }; + struct Rom_module_does_not_exist : Exception { }; + + /** + * Return argument of 'view_geometry()' + */ + struct View_geometry + { + int width, height; + int buf_x, buf_y; + }; typedef Genode::Rpc_in_buffer<64> Name; - typedef Genode::Rpc_in_buffer<160> Start_args; static const char *service_name() { return "Loader"; } virtual ~Session() { } - virtual Genode::Dataspace_capability dataspace() = 0; + /** + * Allocate dataspace to be used as ROM module by the loaded subsystem + * + * \param name designated name of the ROM module + * \param size size of ROM module + * + * \return Dataspace_capability dataspace that contains the backing + * store of the ROM module + * + * The content of the dataspace is made visible to the loaded subsystem + * not before 'commit_rom_module' has been called. This two-step + * procedure enables the client to update the content of the ROM module + * during the lifetime of the session by subsequently calling dataspace + * with the same name as argument. Each time, a new dataspace is + * allocated but not yet presented to the loaded subsystem. When + * calling 'commit_rom_module', the most recently allocated dataspace + * becomes visible. The server frees intermediate dataspaces that are + * no longer used. + */ + virtual Dataspace_capability alloc_rom_module(Name const &name, size_t size) = 0; /** - * Start program or subsystem contained in dataspace + * Expose ROM module to loaded subsystem * - * \throw Rom_access_failed - * \throw Plugin_start_timed_out + * \throw Rom_module_does_not_exist if the ROM module name wasn't + * allocated beforehand */ - virtual void start(Start_args const &args, - int max_width, int max_height, - Genode::Alarm::Time timeout, - Name const &name) = 0; + virtual void commit_rom_module(Name const &name) = 0; - virtual Nitpicker::View_capability view(int *w, int *h, int *buf_x, int *buf_y) = 0; + /** + * Define RAM quota assigned to the subsystem + * + * The quantum specified must be in the bounds of the quota attached + * the session. Note that RAM resources used for ROM modules are + * accounted, too. If ROM modules are modified at runtime by subsequent + * calls of 'alloc_rom_module', the resources needed for the respective + * ROM modules are doubled. + * + * If 'ram_quota' is not called prior calling 'start', all available + * session resources will be assigned to the subsystem. + */ + virtual void ram_quota(size_t quantum) = 0; + + /** + * Constrain size of the nitpicker buffer used by the subsystem + * + * Calling this function prior 'start()' enables the virtualization + * of the nitpicker session interface. + */ + virtual void constrain_geometry(int width, int height) = 0; + + /** + * Register signal handler notified at creation time of the first view + */ + virtual void view_ready_sigh(Signal_context_capability sigh) = 0; + + /** + * Start subsystem + */ + virtual void start(Name const &binary, Name const &label = "") = 0; + + /** + * Return first nitpicker view created by the loaded subsystem + * + * \throw View_does_not_exist + */ + virtual Nitpicker::View_capability view() = 0; + + /** + * Return view geometry as initialized by the loaded subsystem + * + * \throw View_does_not_exist + */ + virtual View_geometry view_geometry() = 0; /******************* ** RPC interface ** *******************/ - GENODE_RPC(Rpc_dataspace, Genode::Dataspace_capability, dataspace); - GENODE_RPC_THROW(Rpc_start, void, start, - GENODE_TYPE_LIST(Start_failed, Rom_access_failed, Plugin_start_timed_out, Invalid_args), - Start_args const &, int, int, Genode::Alarm::Time, Name const &); - GENODE_RPC(Rpc_view, Nitpicker::View_capability, view, int *, int *, int *, int *); + GENODE_RPC(Rpc_alloc_rom_module, Dataspace_capability, alloc_rom_module, + Name const &, size_t); + GENODE_RPC(Rpc_commit_rom_module, void, commit_rom_module, Name const &); + GENODE_RPC(Rpc_ram_quota, void, ram_quota, size_t); + GENODE_RPC(Rpc_constrain_geometry, void, constrain_geometry, int, int); + GENODE_RPC(Rpc_view_ready_sigh, void, view_ready_sigh, Signal_context_capability); + GENODE_RPC(Rpc_start, void, start, Name const &, Name const &); + GENODE_RPC(Rpc_view, Nitpicker::View_capability, view); + GENODE_RPC(Rpc_view_geometry, View_geometry, view_geometry); - GENODE_RPC_INTERFACE(Rpc_dataspace, Rpc_start, Rpc_view); + GENODE_RPC_INTERFACE(Rpc_alloc_rom_module, Rpc_commit_rom_module, + Rpc_ram_quota, Rpc_constrain_geometry, + Rpc_view_ready_sigh, Rpc_start, Rpc_view, + Rpc_view_geometry); }; } diff --git a/os/run/dynamic_config_loader.run b/os/run/dynamic_config_loader.run new file mode 100644 index 0000000000..b78ac1e067 --- /dev/null +++ b/os/run/dynamic_config_loader.run @@ -0,0 +1,42 @@ +build "core init drivers/timer server/loader test/dynamic_config" + +create_boot_directory + +install_config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +build_boot_image "core init timer loader test-dynamic_config test-dynamic_config_loader" + +append qemu_args "-nographic -m 64" + +run_genode_until {obtained counter value 11 from config.*} 100 + +puts "Test succeeded" diff --git a/os/run/loader.run b/os/run/loader.run new file mode 100644 index 0000000000..8b4037e9ce --- /dev/null +++ b/os/run/loader.run @@ -0,0 +1,111 @@ +# +# Build +# + +set build_components { + core init + drivers/timer + server/nitpicker server/loader + test/nitpicker test/loader + drivers/framebuffer drivers/pci drivers/input +} + +build $build_components + +create_boot_directory + +# +# Generate config +# + +append config { + + + + + + + + + + + + + + + + + } + +append_if [have_spec sdl] config { + + + + + + + } + +append_if [have_spec pci] config { + + + + } + +append_if [have_spec vesa] config { + + + + } + +append_if [have_spec pl11x] config { + + + + } + +append_if [have_spec ps2] config { + + + + } + +append config { + + + + + + + + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +# generic modules +set boot_modules { core init timer nitpicker testnit loader test-loader } + +# platform-specific modules +lappend_if [have_spec linux] boot_modules fb_sdl +lappend_if [have_spec pci] boot_modules pci_drv +lappend_if [have_spec vesa] boot_modules vesa_drv +lappend_if [have_spec ps2] boot_modules ps2_drv +lappend_if [have_spec pl11x] boot_modules pl11x_drv + +build_boot_image $boot_modules + +append qemu_args " -m 256 " + +run_genode_until forever diff --git a/os/src/server/loader/README b/os/src/server/loader/README index 8a956035ba..3547c32844 100644 --- a/os/src/server/loader/README +++ b/os/src/server/loader/README @@ -1,9 +1,5 @@ -This directory contains an experimental loader service, which allows -for the instantiation of subsystems via a service. The resources for -the new subsystem are provided by the client when opening the session. -Except for the lifetime of the subsystem, however, the client has no -control over the functioning of the subsystem. - -Note that this is an experimental implementation crafted for the -browser plugin mechanism presented at the 2010-10 Live CD. But the -service will eventually evolve to become a generally useful tool. +This directory contains a loader service, which allows for the instantiation of +subsystems via a session interface. The resources for the new subsystem are +provided by the client when opening the session. The client has no control over +the functioning of the subsystem except for the controlling the lifetime of the +subsystem. diff --git a/os/src/server/loader/child.h b/os/src/server/loader/child.h new file mode 100644 index 0000000000..13c0192c41 --- /dev/null +++ b/os/src/server/loader/child.h @@ -0,0 +1,176 @@ +/* + * \brief Loader child interface + * \author Christian Prochaska + * \author Norman Feske + * \date 2009-10-05 + */ + +/* + * Copyright (C) 2009-2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _CHILD_H_ +#define _CHILD_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include + + +namespace Loader { + + using namespace Genode; + + class Child : public Child_policy + { + private: + + struct Label { + char string[Session::Name::MAX_SIZE]; + Label(char const *l) { strncpy(string, l, sizeof(string)); } + } _label; + + Rpc_entrypoint &_ep; + + struct Resources + { + Ram_connection ram; + Cpu_connection cpu; + Rm_connection rm; + + Resources(char const *label, size_t ram_quota) + : ram(label), cpu(label) + { + /* deduce session costs from usable ram quota */ + size_t session_donations = Rm_connection::RAM_QUOTA + + Cpu_connection::RAM_QUOTA + + Ram_connection::RAM_QUOTA; + + if (ram_quota > session_donations) + ram_quota -= session_donations; + else ram_quota = 0; + + ram.ref_account(env()->ram_session_cap()); + env()->ram_session()->transfer_quota(ram.cap(), ram_quota); + } + } _resources; + + + Service_registry &_parent_services; + Service &_local_nitpicker_service; + Service &_local_rom_service; + + Rom_session_client _binary_rom_session; + + Init::Child_policy_provide_rom_file _binary_policy; + Init::Child_policy_enforce_labeling _labeling_policy; + + int _max_width, _max_height; + + Genode::Child _child; + + Rom_session_capability _rom_session(char const *name) + { + char args[Session::Name::MAX_SIZE]; + snprintf(args, sizeof(args), "ram_quota=4K, filename=\"%s\"", name); + return static_cap_cast(_local_rom_service.session(args)); + } + + public: + + Child(const char *binary_name, + const char *label, + Rpc_entrypoint &ep, + size_t ram_quota, + Service_registry &parent_services, + Service &local_rom_service, + Service &local_nitpicker_service, + int max_width, int max_height) + : + _label(label), + _ep(ep), + _resources(_label.string, ram_quota), + _parent_services(parent_services), + _local_nitpicker_service(local_nitpicker_service), + _local_rom_service(local_rom_service), + _binary_rom_session(_rom_session(binary_name)), + _binary_policy("binary", _binary_rom_session.dataspace(), &_ep), + _labeling_policy(_label.string), + _max_width(max_width), _max_height(max_height), + _child(_binary_rom_session.dataspace(), + _resources.ram.cap(), _resources.cpu.cap(), + _resources.rm.cap(), &_ep, this) + { } + + ~Child() + { + _local_rom_service.close(_binary_rom_session); + } + + + /**************************** + ** Child-policy interface ** + ****************************/ + + const char *name() const { return _label.string; } + + void filter_session_args(char const *service, char *args, size_t args_len) + { + _labeling_policy.filter_session_args(0, args, args_len); + + if (!strcmp(service, "Nitpicker")) { + + /* + * Restrict the child's framebuffer size to the maximum + * size given by the client. + */ + + if (_max_width > -1) { + int fb_width = Arg_string::find_arg(args, "fb_width" ).long_value(_max_width); + if (!Arg_string::set_arg(args, args_len, "fb_width", + min(fb_width, _max_width))) { + PERR("could not set fb_width argument"); + } + } + if (_max_height > -1) { + int fb_height = Arg_string::find_arg(args, "fb_height" ).long_value(_max_height); + if (!Arg_string::set_arg(args, args_len, "fb_height", + min(fb_height, _max_height))) { + PERR("could not set fb_height argument"); + } + } + } + } + + Service *resolve_session_request(const char *name, + const char *args) + { + Service *service = 0; + + if ((service = _binary_policy.resolve_session_request(name, args))) + return service; + + if (!strcmp(name, "Nitpicker")) + return &_local_nitpicker_service; + + if (!strcmp(name, "ROM")) + return &_local_rom_service; + + /* populate session-local parent service registry on demand */ + service = _parent_services.find(name); + if (!service) { + service = new (env()->heap()) Parent_service(name); + _parent_services.insert(service); + } + return service; + } + }; +} + +#endif /* _CHILD_H_ */ diff --git a/os/src/server/loader/input.h b/os/src/server/loader/input.h new file mode 100644 index 0000000000..ba79cfebfa --- /dev/null +++ b/os/src/server/loader/input.h @@ -0,0 +1,103 @@ +/* + * \brief Virtualized input session + * \author Christian Prochaska + * \author Norman Feske + * \date 2010-09-02 + * + * This input service implementation is used by the virtualized nitpicker + * service to translate the input coordinate system from the coordinates + * seen by the user of the virtualized session and the physical coordinates + * dictated by the loader-session client. + */ + +/* + * Copyright (C) 2010-2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INPUT_H_ +#define _INPUT_H_ + +#include +#include +#include +#include + +namespace Input { + + using namespace Genode; + + struct Transformer + { + struct Delta { int const x, y; }; + + virtual Delta delta() = 0; + }; + + class Session_component : public Rpc_object + { + private: + + Session_client _real_input; + Transformer &_transformer; + Event * const _ev_buf; + + public: + + /** + * Constructor + */ + Session_component(Session_capability real_input, + Transformer &transformer) + : + _real_input(real_input), _transformer(transformer), + _ev_buf(env()->rm_session()->attach(_real_input.dataspace())) + { } + + /** + * Destructor + */ + ~Session_component() { env()->rm_session()->detach(_ev_buf); } + + + /***************************** + ** Input session interface ** + *****************************/ + + Dataspace_capability dataspace() { return _real_input.dataspace(); } + + bool is_pending() const { return _real_input.is_pending(); } + + int flush() + { + /* translate mouse position to child's coordinate system */ + Transformer::Delta delta = _transformer.delta(); + + int const num_ev = _real_input.flush(); + for (int i = 0; i < num_ev; i++) { + + Input::Event &ev = _ev_buf[i]; + + if ((ev.type() == Input::Event::MOTION) + || (ev.type() == Input::Event::WHEEL) + || (ev.keycode() == Input::BTN_LEFT) + || (ev.keycode() == Input::BTN_RIGHT) + || (ev.keycode() == Input::BTN_MIDDLE)) { + + ev = Input::Event(ev.type(), + ev.keycode(), + ev.ax() - delta.x, + ev.ay() - delta.y, + ev.rx(), + ev.ry()); + } + } + + return num_ev; + } + }; +} + +#endif /* _INPUT_H_ */ diff --git a/os/src/server/loader/input_root.h b/os/src/server/loader/input_root.h deleted file mode 100644 index b31b03777c..0000000000 --- a/os/src/server/loader/input_root.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * \brief Input root interface providing monitored input session to the child - * \author Christian Prochaska - * \date 2010-09-02 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INPUT_ROOT_H_ -#define _INPUT_ROOT_H_ - -#include -#include -#include - -namespace Input { - - class Root : public Genode::Root_component - { - private: - - /* local Input session component */ - Session_component *_isc; - - Nitpicker::Session_component *_nsc; - - protected: - - Session_component *_create_session(const char *args) - { - if (!_isc) { - _isc = new (md_alloc()) Session_component(ep(), _nsc); - return _isc; - } else { - PERR("Only one input session is allowed in the current implementation."); - return 0; - } - } - - public: - - /** - * Constructor - * - * \param session_ep entry point for managing ram session objects - * \param md_alloc meta-data allocator to be used by root component - */ - Root(Genode::Rpc_entrypoint *session_ep, - Genode::Allocator *md_alloc, - Nitpicker::Session_component *nsc) - : Genode::Root_component(session_ep, md_alloc), - _isc(0), _nsc(nsc) - { } - - ~Root() { destroy(md_alloc(), _isc); } - - void close(Genode::Session_capability cap) - { - destroy(md_alloc(), _isc); - _isc = 0; - } - }; -} - -#endif /* _INPUT_ROOT_H_ */ diff --git a/os/src/server/loader/input_session_component.cc b/os/src/server/loader/input_session_component.cc deleted file mode 100644 index ad92d2df7f..0000000000 --- a/os/src/server/loader/input_session_component.cc +++ /dev/null @@ -1,91 +0,0 @@ -/* - * \brief Input session component - * \author Christian Prochaska - * \date 2010-09-02 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* local includes */ -#include -#include - - -using namespace Input; - - -Session_component::Session_component(Genode::Rpc_entrypoint *ep, - Nitpicker::Session_component *nsc) -: _ep(ep), _nsc(nsc) -{ - /* connect to the "real" Input service */ - _isc = new (Genode::env()->heap()) Session_client(_nsc->real_input_session()); - _ev_buf = Genode::env()->rm_session()->attach(_isc->dataspace()); -} - - -Session_component::~Session_component() -{ - Genode::env()->rm_session()->detach(_ev_buf); - Genode::destroy(Genode::env()->heap(), _isc); -} - - -Genode::Dataspace_capability Session_component::dataspace() -{ - return _isc->dataspace(); -} - - -bool Session_component::is_pending() const { return _isc->is_pending(); } - - -int Session_component::flush() -{ - int num_ev = _isc->flush(); - - /* translate mouse position to child's coordinate system */ - - int client_x, client_y, client_buf_x, client_buf_y, - proxy_x, proxy_y, proxy_buf_x, proxy_buf_y; - - _nsc->loader_view_component()->get_viewport(&client_x, &client_y, 0, 0, &client_buf_x, &client_buf_y); - _nsc->proxy_view_component()->get_viewport(&proxy_x, &proxy_y, 0, 0, &proxy_buf_x, &proxy_buf_y); - - if (0) { - PDBG("app: x = %d, y = %d, buf_x = %d, buf_y = %d", client_x, client_y, client_buf_x, client_buf_y); - PDBG("plg: x = %d, y = %d, buf_x = %d, buf_y = %d", proxy_x, proxy_y, proxy_buf_x, proxy_buf_y); - } - - for (int i = 0; i < num_ev; i++) { - Input::Event *real_ev = &_ev_buf[i]; - - if ((real_ev->type() == Input::Event::MOTION) || - (real_ev->type() == Input::Event::WHEEL) || - (real_ev->keycode() == Input::BTN_LEFT) || - (real_ev->keycode() == Input::BTN_RIGHT) || - (real_ev->keycode() == Input::BTN_MIDDLE)) { - Input::Event ev(real_ev->type(), - real_ev->keycode(), - real_ev->ax() - (client_x + client_buf_x) + (proxy_x + proxy_buf_x), - real_ev->ay() - (client_y + client_buf_y) + (proxy_y + proxy_buf_y), - real_ev->rx(), - real_ev->ry()); - *real_ev = ev; - } - } - - return num_ev; -} diff --git a/os/src/server/loader/input_session_component.h b/os/src/server/loader/input_session_component.h deleted file mode 100644 index 8b0fa2fd7e..0000000000 --- a/os/src/server/loader/input_session_component.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * \brief Input session instance - * \author Christian Prochaska - * \date 2010-09-02 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _INPUT_SESSION_COMPONENT_H_ -#define _INPUT_SESSION_COMPONENT_H_ - -#include -#include -#include -#include - -namespace Nitpicker { class Session_component; } - -namespace Input { - - class Session_component : public Genode::Rpc_object - { - private: - - Session_client *_isc; - Genode::Rpc_entrypoint *_ep; - Nitpicker::Session_component *_nsc; - Input::Event *_ev_buf; - - public: - - /** - * Constructor - */ - Session_component(Genode::Rpc_entrypoint *ep, - Nitpicker::Session_component *nsc); - - /** - * Destructor - */ - ~Session_component(); - - - /***************************** - ** Input session interface ** - *****************************/ - - Genode::Dataspace_capability dataspace(); - bool is_pending() const; - int flush(); - }; -} - -#endif /* _INPUT_SESSION_COMPONENT_H_ */ diff --git a/os/src/server/loader/loader_child.h b/os/src/server/loader/loader_child.h deleted file mode 100644 index 921ca89005..0000000000 --- a/os/src/server/loader/loader_child.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * \brief Loader child interface - * \author Christian Prochaska - * \date 2009-10-05 - * - */ - -/* - * Copyright (C) 2009-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _LOADER_CHILD_H_ -#define _LOADER_CHILD_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* local includes */ -#include -#include - -namespace Loader { - - class Child : public Genode::Child_policy, - public Init::Child_policy_enforce_labeling - { - private: - - const char *_name; - - /* - * Entry point used for serving the parent interface - */ - enum { STACK_SIZE = 8*1024 }; - Genode::Rpc_entrypoint _entrypoint; - - Genode::Service_registry *_parent_services; - - Init::Child_policy_provide_rom_file _binary_policy; - - int _max_width; - int _max_height; - - /** - * Monitored Nitpicker service - */ - class Nitpicker_service : public Genode::Service - { - private: - - Nitpicker::Root _nitpicker_root; - - public: - - Nitpicker_service(Genode::Rpc_entrypoint *entrypoint, - Genode::Allocator *md_alloc, - Genode::Timed_semaphore *ready_sem) - : - Service("Nitpicker"), - _nitpicker_root(entrypoint, md_alloc, ready_sem) { } - - Genode::Session_capability session(const char *args) - { - return _nitpicker_root.session(args); - } - - void upgrade(Genode::Session_capability, const char *) { } - - void close(Genode::Session_capability cap) - { - /* - * Prevent view destruction. When view exists, the view - * will be destroyed along with the nitpicker session - * when the loader session gets closed. - */ - if (!_nitpicker_root.view(0, 0, 0, 0).valid()) - _nitpicker_root.close(cap); - } - - Nitpicker::View_capability view(int *w, int *h, int *buf_x, int *buf_y) - { - return _nitpicker_root.view(w, h, buf_x, buf_y); - } - - } _nitpicker_service; - - /** - * Monitored ROM service - */ - class Rom_service : public Genode::Service - { - private: - - Rom_root _rom_root; - - public: - Rom_service(Genode::Rpc_entrypoint *entrypoint, - Genode::Allocator *md_alloc, - Genode::Root_capability tar_server_root) - : - Genode::Service("ROM"), - _rom_root(entrypoint, entrypoint, md_alloc, tar_server_root) - { } - - Genode::Session_capability session(const char *args) - { - return _rom_root.session(args); - } - - void upgrade(Genode::Session_capability, const char *) { } - - void close(Genode::Session_capability cap) - { - _rom_root.close(cap); - } - } _rom_service; - - struct Resources - { - Genode::Ram_connection ram; - Genode::Cpu_connection cpu; - Genode::Rm_connection rm; - - Resources(char const *label, Genode::size_t ram_quota) - : ram(label), cpu(label) - { - /* deduce session costs from usable ram quota */ - Genode::size_t session_donations = Genode::Rm_connection::RAM_QUOTA + - Genode::Cpu_connection::RAM_QUOTA + - Genode::Ram_connection::RAM_QUOTA; - - if (ram_quota > session_donations) - ram_quota -= session_donations; - else ram_quota = 0; - - ram.ref_account(Genode::env()->ram_session_cap()); - Genode::env()->ram_session()->transfer_quota( - ram.cap(), ram_quota); - } - } _resources; - - /* must be declared after the service objects for the right destruction order */ - Genode::Child _child; - - public: - - Child(const char *name, - Genode::Dataspace_capability elf_ds, - Genode::Cap_session *cap_session, - Genode::size_t ram_quota, - Genode::Service_registry *parent_services, - Genode::Timed_semaphore *ready_sem, - int max_width, - int max_height, - Genode::Root_capability tar_server_root) - : Init::Child_policy_enforce_labeling(name), - _name(name), - _entrypoint(cap_session, STACK_SIZE, name, false), - _parent_services(parent_services), - _binary_policy("binary", elf_ds, &_entrypoint), - _max_width(max_width), - _max_height(max_height), - /* FIXME: temporarily replaced '_child.heap()' with 'env()->heap()' */ - _nitpicker_service(&_entrypoint, Genode::env()->heap(), ready_sem), - _rom_service(&_entrypoint, Genode::env()->heap(), tar_server_root), - _resources(name, ram_quota), - _child(elf_ds, _resources.ram.cap(), _resources.cpu.cap(), - _resources.rm.cap(), &_entrypoint, this) - { - _entrypoint.activate(); - } - - /**************************** - ** Child-policy interface ** - ****************************/ - - const char *name() const { return _name; } - - void filter_session_args(const char *service_name, char *args, Genode::size_t args_len) - { - using namespace Genode; - - Init::Child_policy_enforce_labeling::filter_session_args(0, args, args_len); - - if (!strcmp(service_name, "Nitpicker")) { - - /* - * Restrict the child's framebuffer size to the maximum - * size given by the client. - */ - - if (_max_width > -1) { - int fb_width = Arg_string::find_arg(args, "fb_width" ).long_value(_max_width); - if (!Arg_string::set_arg(args, args_len, "fb_width", - min(fb_width, _max_width))) { - PERR("could not set fb_width argument"); - } - } - if (_max_height > -1) { - int fb_height = Arg_string::find_arg(args, "fb_height" ).long_value(_max_height); - if (!Arg_string::set_arg(args, args_len, "fb_height", - min(fb_height, _max_height))) { - PERR("could not set fb_height argument"); - } - } - } - } - - Genode::Service *resolve_session_request(const char *service_name, - const char *args) - { - using namespace Genode; - - Service *service = 0; - - PDBG("service_name = %s", service_name); - - /* check for binary file request */ - if ((service = _binary_policy.resolve_session_request(service_name, args))) - return service; - - if (!strcmp(service_name, "Nitpicker")) - return &_nitpicker_service; - - if (!strcmp(service_name, "ROM")) - return &_rom_service; - - service = _parent_services->find(service_name); - if (!service) { - service = new (env()->heap()) Parent_service(service_name); - _parent_services->insert(service); - } - return service; - } - - Nitpicker::View_capability view(int *w, int *h, int *buf_x, int *buf_y) - { - return _nitpicker_service.view(w, h, buf_x, buf_y); - } - }; -} - -#endif /* _LOADER_CHILD_H_ */ diff --git a/os/src/server/loader/loader_root.h b/os/src/server/loader/loader_root.h deleted file mode 100644 index 90d0bec2d6..0000000000 --- a/os/src/server/loader/loader_root.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * \brief Loader root interface - * \author Christian Prochaska - * \date 2009-10-05 - */ - -/* - * Copyright (C) 2009-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _LOADER_ROOT_H_ -#define _LOADER_ROOT_H_ - -/* Genode includes */ -#include -#include - -/* local includes */ -#include - -namespace Loader { - - class Root : public Genode::Root_component - { - protected: - - Loader::Session_component *_create_session(const char *args) - { - using namespace Genode; - size_t ds_size = Arg_string::find_arg(args, "ds_size").long_value(0); - return new (md_alloc()) Loader::Session_component(ds_size); - } - - public: - - /** - * Constructor - * - * \param session_ep entry point for managing ram session objects - * \param md_alloc meta-data allocator to be used by root component - */ - Root(Genode::Rpc_entrypoint *session_ep, - Genode::Allocator *md_alloc) - : Genode::Root_component(session_ep, md_alloc) { } - }; -} - -#endif /* _LOADER_ROOT_H_ */ diff --git a/os/src/server/loader/loader_session_component.cc b/os/src/server/loader/loader_session_component.cc deleted file mode 100644 index 015c83783a..0000000000 --- a/os/src/server/loader/loader_session_component.cc +++ /dev/null @@ -1,165 +0,0 @@ -/* - * \brief Implementation of the Loader session interface - * \author Christian Prochaska - * \date 2009-10-06 - */ - -/* - * Copyright (C) 2009-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include - -/* local includes */ -#include - - -using namespace Loader; -using namespace Genode; - - -Session_component::Session_component(size_t input_ds_size) -: _tar_rom(0), - _tar_server_child_elf(0), - _tar_server_child(0), - _loader_child_elf(0), - _loader_child(0) -{ - PDBG("available quota = %zd / %zd", - env()->ram_session()->avail(), env()->ram_session()->quota()); - try { - if (input_ds_size > 0) - _input_ds = env()->ram_session()->alloc(input_ds_size); - } catch(Ram_session::Quota_exceeded) { - PERR("Quota exceeded!"); - } - -} - - -Session_component::~Session_component() -{ - destroy(env()->heap(), _loader_child); - destroy(env()->heap(), _loader_child_elf); - - destroy(env()->heap(), _tar_server_child); - destroy(env()->heap(), _tar_server_child_elf); - - destroy(env()->heap(), _tar_rom); - - env()->ram_session()->free(static_cap_cast(_input_ds)); - - PDBG("available quota = %zd / %zd", - env()->ram_session()->avail(), env()->ram_session()->quota()); -} - - -void Session_component::start(Start_args const &args, - int max_width, int max_height, - Alarm::Time timeout, - Name const &name) -{ - char *input_ds_addr = env()->rm_session()->attach(_input_ds); - - if (!input_ds_addr) - throw Start_failed(); - - if (!args.is_valid_string()) - throw Invalid_args(); - - _ram_quota = Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0); - - enum { LOADER_RAM_QUOTA = 512*1024 }; - enum { TAR_SERVER_RAM_QUOTA = 512*1024 }; - - /* - * In the demo scenario, the ram amount stated by the "ram_quota" - * argument is meant for both the loader and the child, so some memory - * gets reserved for the loader here. - */ - if (_ram_quota) - _ram_quota -= LOADER_RAM_QUOTA; - - if ((input_ds_addr[0] != 0x7f) || - (input_ds_addr[1] != 'E') || - (input_ds_addr[2] != 'L') || - (input_ds_addr[3] != 'F')) { - - /* dataspace presumably contains tar archive */ - - /* - * TAR server child - */ - - try { - _tar_server_child_elf = new (env()->heap()) Rom_connection("tar_rom", "tar_rom"); - _tar_server_child_elf_ds = _tar_server_child_elf->dataspace(); - } catch (Rom_connection::Rom_connection_failed) { - printf("Error: Could not access file \"%s\" from ROM service.\n", "tar_rom"); - throw Rom_access_failed(); - } - - _tar_server_child = new (env()->heap()) - Tar_server_child("tar_rom", - _tar_server_child_elf_ds, - TAR_SERVER_RAM_QUOTA, - &_cap_session, - &_tar_server_child_parent_services, - _input_ds); - - /* - * Deduce quota donations for RAM, RM, and CPU from available quota - */ - _ram_quota -= (Tar_server_child::DONATIONS + TAR_SERVER_RAM_QUOTA); - - try { - _loader_child_elf = new (env()->heap()) Rom_connection("init", "init"); - _loader_child_elf_ds = _loader_child_elf->dataspace(); - } catch (Rom_connection::Rom_connection_failed) { - printf("Error: Could not access file \"%s\" from ROM service.\n", "init"); - throw Rom_access_failed(); - } - - } else { - /* dataspace contains ELF binary */ - _loader_child_elf_ds = _input_ds; - } - - env()->rm_session()->detach(input_ds_addr); - - /* - * Loader child - */ - - _loader_child = new (env()->heap()) - Child(_tar_server_child ? "init" : name.string(), - _loader_child_elf_ds, - &_cap_session, - _ram_quota, - &_loader_child_parent_services, - &_ready_sem, - max_width, - max_height, - _tar_server_child ? _tar_server_child->tar_server_root() - : Root_capability()); - - try { - _ready_sem.down(timeout); - } catch (Genode::Timeout_exception) { - throw Plugin_start_timed_out(); - } catch (Genode::Nonblocking_exception) { - throw Plugin_start_timed_out(); - } -} - - -Nitpicker::View_capability Session_component::view(int *w, int *h, int *buf_x, int *buf_y) -{ - return _loader_child->view(w, h, buf_x, buf_y); -} diff --git a/os/src/server/loader/loader_session_component.h b/os/src/server/loader/loader_session_component.h deleted file mode 100644 index 5f740ebbab..0000000000 --- a/os/src/server/loader/loader_session_component.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * \brief Instance of the Loader session interface - * \author Christian Prochaska - * \date 2009-10-05 - */ - -/* - * Copyright (C) 2009-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _LOADER_SESSION_COMPONENT_H_ -#define _LOADER_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include - -/* local includes */ -#include -#include - -namespace Loader { - - class Session_component : public Genode::Rpc_object - { - private: - - Genode::Dataspace_capability _input_ds; - - Genode::Dataspace_capability _tar_ds; - Genode::Rom_connection *_tar_rom; - - Genode::Rom_connection *_tar_server_child_elf; - Genode::Dataspace_capability _tar_server_child_elf_ds; - Genode::Service_registry _tar_server_child_parent_services; - Tar_server_child *_tar_server_child; - - Genode::Rom_connection *_loader_child_elf; - Genode::Dataspace_capability _loader_child_elf_ds; - Genode::Service_registry _loader_child_parent_services; - Loader::Child *_loader_child; - - /* cap session for allocating capabilities for parent interfaces */ - Genode::Cap_connection _cap_session; - - Genode::size_t _ram_quota; - - Genode::Timed_semaphore _ready_sem; - - public: - - /** - * Constructor - */ - Session_component(Genode::size_t input_ds_size); - - /** - * Destructor - */ - ~Session_component(); - - - /****************************** - ** Loader session interface ** - ******************************/ - - Genode::Dataspace_capability dataspace() { return _input_ds; } - - void start(Start_args const &args, - int max_width, int max_height, - Genode::Alarm::Time timeout, - Name const &name); - - Nitpicker::View_capability view(int *w, int *h, int *buf_x, int *buf_y); - }; -} - -#endif /* _LOADER_SESSION_COMPONENT_H_ */ diff --git a/os/src/server/loader/loader_view_component.h b/os/src/server/loader/loader_view_component.h deleted file mode 100644 index f61fde60d9..0000000000 --- a/os/src/server/loader/loader_view_component.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * \brief Instance of the view interface provided to the client - * \author Christian Prochaska - * \date 2010-09-02 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _LOADER_VIEW_COMPONENT_H_ -#define _LOADER_VIEW_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include - -namespace Nitpicker { - - class Loader_view_component : public Genode::Rpc_object - { - private: - - View *_view; /* the wrapped view */ - int _x, _y, _w, _h, _buf_x, _buf_y; - - public: - - /** - * Constructor - */ - Loader_view_component(View_capability view_cap) - { - _view = new (Genode::env()->heap()) Nitpicker::View_client(view_cap); - } - - ~Loader_view_component() - { - Genode::destroy(Genode::env()->heap(), _view); - } - - - /****************************** - ** Nitpicker view interface ** - ******************************/ - - int viewport(int x, int y, int w, int h, - int buf_x, int buf_y, bool redraw) - { - _x = x; - _y = y; - _w = w; - _h = h; - _buf_x = buf_x; - _buf_y = buf_y; - return _view->viewport(x, y, w, h, buf_x, buf_y, redraw); - } - - int stack(Nitpicker::View_capability neighbor_cap, bool behind, bool redraw) - { - return _view->stack(neighbor_cap, behind, redraw); - } - - int title(Title const &title) - { - return _view->title(title.string()); - } - - void get_viewport(int *x, int *y, int *w, int *h, int *buf_x, int *buf_y) - { - if (x) *x = _x; - if (y) *y = _y; - if (w) *w = _w; - if (h) *h = _h; - if (buf_x) *buf_x = _buf_x; - if (buf_y) *buf_y = _buf_y; - } - }; -} - -#endif /* _LOADER_VIEW_COMPONENT_H_ */ diff --git a/os/src/server/loader/main.cc b/os/src/server/loader/main.cc index ed41632f73..bc03576c27 100644 --- a/os/src/server/loader/main.cc +++ b/os/src/server/loader/main.cc @@ -1,7 +1,7 @@ /* - * \brief Loader - * \author Christian Prochaska - * \date 2010-09-16 + * \brief Loader service + * \author Norman Feske + * \date 2012-04-17 */ /* @@ -12,21 +12,308 @@ */ /* Genode includes */ +#include +#include +#include #include +#include +#include +#include +#include /* local includes */ -#include +#include +#include +#include + + +namespace Loader { + + using namespace Genode; + + + class Session_component : public Rpc_object + { + private: + + struct Local_rom_service : Service + { + Rpc_entrypoint &_ep; + Parent_service _parent_rom_service; + Rom_module_registry &_rom_modules; + Lock _lock; + List _rom_sessions; + + void _close(Rom_session_component *rom) + { + _ep.dissolve(rom); + destroy(env()->heap(), rom); + _rom_sessions.remove(rom); + } + + Local_rom_service(Rpc_entrypoint &ep, + Rom_module_registry &rom_modules) + : + Service("virtual_rom"), + _ep(ep), + _parent_rom_service(Rom_session::service_name()), + _rom_modules(rom_modules) + { } + + ~Local_rom_service() + { + Lock::Guard guard(_lock); + + while (_rom_sessions.first()) { + _close(_rom_sessions.first()); } + } + + Genode::Session_capability session(const char *args) + { + /* try to find ROM module at local ROM service */ + try { + Lock::Guard guard(_lock); + + char name[Session::Name::MAX_SIZE]; + + /* extract filename from session arguments */ + Arg_string::find_arg(args, "filename") + .string(name, sizeof(name), ""); + + Rom_module &module = _rom_modules.lookup_and_lock(name); + + Rom_session_component *rom = new (env()->heap()) + Rom_session_component(module); + + _rom_sessions.insert(rom); + + return _ep.manage(rom); + + } catch (...) { } + + /* fall back to parent_rom_service */ + return _parent_rom_service.session(args); + } + + void close(Session_capability session) + { + Lock::Guard guard(_lock); + + Rpc_object_base *rom = _ep.obj_by_cap(session); + + Rom_session_component *component = + dynamic_cast(rom); + + if (component) { + _close(component); + return; + } + + _parent_rom_service.close(session); + } + + void upgrade(Session_capability session, const char *) { } + }; + + struct Local_nitpicker_service : Service + { + Rpc_entrypoint &ep; + + Signal_context_capability view_ready_sigh; + + Nitpicker::Session_component *open_session; + + Local_nitpicker_service(Rpc_entrypoint &ep) + : + Service("virtual_nitpicker"), ep(ep), open_session(0) + { } + + ~Local_nitpicker_service() + { + if (!open_session) + return; + + ep.dissolve(open_session); + destroy(env()->heap(), open_session); + } + + Genode::Session_capability session(const char *args) + { + if (open_session) + throw Unavailable(); + + /* + * XXX replace allocation from 'env()->heap()' with + * use of session-specific allocator + */ + open_session = new (env()->heap()) + Nitpicker::Session_component(ep, view_ready_sigh, args); + + return ep.manage(open_session); + } + + void upgrade(Genode::Session_capability session, const char *) { } + }; + + enum { STACK_SIZE = 2*4096 }; + + size_t _ram_quota; + size_t _subsystem_ram_quota_limit; + int _width, _height; + Rpc_entrypoint _ep; + Service_registry _parent_services; + Rom_module_registry _rom_modules; + Local_rom_service _rom_service; + Local_nitpicker_service _nitpicker_service; + Child *_child; + + /** + * Return virtual nitpicker session component + */ + Nitpicker::Session_component *_virtual_nitpicker_session() + { + if (!_nitpicker_service.open_session) + throw View_does_not_exist(); + + return _nitpicker_service.open_session; + } + + public: + + /** + * Constructor + */ + Session_component(size_t quota, Ram_session &ram, Cap_session &cap) + : + _ram_quota(quota), + _subsystem_ram_quota_limit(~0), + _width(-1), _height(-1), + _ep(&cap, STACK_SIZE, "session_ep"), + _rom_modules(ram, *env()->heap()), /* XXX remove env()->heap() */ + _rom_service(_ep, _rom_modules), + _nitpicker_service(_ep), + _child(0) + { } + + ~Session_component() + { + if (_child) + destroy(env()->heap(), _child); + } + + + /****************************** + ** Loader session interface ** + ******************************/ + + Dataspace_capability alloc_rom_module(Name const &name, size_t size) + { + return _rom_modules.alloc_rom_module(name.string(), size); + } + + void commit_rom_module(Name const &name) + { + try { + _rom_modules.commit_rom_module(name.string()); } + catch (Rom_module_registry::Lookup_failed) { + throw Rom_module_does_not_exist(); } + } + + void ram_quota(size_t quantum) + { + _subsystem_ram_quota_limit = quantum; + } + + void constrain_geometry(int width, int height) + { + _width = width, _height = height; + } + + void view_ready_sigh(Signal_context_capability sigh) + { + _nitpicker_service.view_ready_sigh = sigh; + } + + void start(Name const &binary_name, Name const &label) + { + if (_child) { + PWRN("cannot start subsystem twice"); + return; + } + + /* + * XXX account for ROM modules + */ + size_t const ram_quota = _subsystem_ram_quota_limit; + + /* + * XXX don't use 'env()->heap()' + */ + _child = new (env()->heap()) + Child(binary_name.string(), label.string(), _ep, + ram_quota, _parent_services, _rom_service, + _nitpicker_service, _width, _height); + } + + Nitpicker::View_capability view() + { + return _virtual_nitpicker_session()->loader_view(); + } + + View_geometry view_geometry() + { + return _virtual_nitpicker_session()->loader_view_geometry(); + } + }; + + + class Root : public Root_component + { + private: + + Ram_session &_ram; + Cap_session &_cap; + + protected: + + Session_component *_create_session(const char *args) + { + size_t quota = + Arg_string::find_arg(args, "ram_quota").long_value(0); + + return new (md_alloc()) Session_component(quota, _ram, _cap); + } + + public: + + /** + * Constructor + * + * \param session_ep entry point for managing ram session objects + * \param md_alloc meta-data allocator to be used by root + * component + */ + Root(Rpc_entrypoint &session_ep, Allocator &md_alloc, + Ram_session &ram, Cap_session &cap) + : + Root_component(&session_ep, &md_alloc), + _ram(ram), _cap(cap) + { } + }; +} -using namespace Genode; int main() { + using namespace Genode; + enum { STACK_SIZE = 8*1024 }; static Cap_connection cap; static Rpc_entrypoint ep(&cap, STACK_SIZE, "loader_ep"); - static Loader::Root loader_root(&ep, env()->heap()); - env()->parent()->announce(ep.manage(&loader_root)); + static Loader::Root root(ep, *env()->heap(), *env()->ram_session(), cap); + + env()->parent()->announce(ep.manage(&root)); sleep_forever(); return 0; diff --git a/os/src/server/loader/nitpicker.h b/os/src/server/loader/nitpicker.h new file mode 100644 index 0000000000..eccbe8919b --- /dev/null +++ b/os/src/server/loader/nitpicker.h @@ -0,0 +1,284 @@ +/* + * \brief Virtualized nitpicker session interface exposed to the subsystem + * \author Christian Prochaska + * \author Norman Feske + * \date 2009-10-05 + */ + +/* + * Copyright (C) 2009-2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _NITPICKER_H_ +#define _NITPICKER_H_ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include + +/* local includes */ +#include + +namespace Nitpicker { + + using namespace Genode; + + /** + * View interface provided to the loader client + */ + class Loader_view_component : public Rpc_object + { + private: + + View_client _view; /* wrapped view */ + + int _x, _y, _buf_x, _buf_y; + + public: + + /** + * Constructor + */ + Loader_view_component(View_capability view_cap) + : + _view(view_cap), _x(0), _y(0), _buf_x(0), _buf_y(0) + { } + + int x() const { return _x; } + int y() const { return _y; } + int buf_x() const { return _buf_x; } + int buf_y() const { return _buf_y; } + + + /****************************** + ** Nitpicker view interface ** + ******************************/ + + int viewport(int x, int y, int w, int h, + int buf_x, int buf_y, bool redraw) + { + _x = x, _y = y, _buf_x = buf_x, _buf_y = buf_y; + + return _view.viewport(x, y, w, h, buf_x, buf_y, redraw); + } + + int stack(View_capability neighbor_cap, bool behind, bool redraw) + { + return _view.stack(neighbor_cap, behind, redraw); + } + + int title(Title const &title) + { + return _view.title(title.string()); + } + }; + + + /** + * View interface exposed to the subsystem + */ + class View_component : public Rpc_object + { + private: + + View_client _view; /* wrapped view */ + Signal_context_capability _sigh; + bool _viewport_initialized; + int _x, _y, _w, _h, _buf_x, _buf_y; + + public: + + /** + * Constructor + */ + View_component(View_capability view_cap, + Signal_context_capability sigh) + : + _view(view_cap), _sigh(sigh), _viewport_initialized(false), + _x(0), _y(0), _w(0), _h(0), _buf_x(0), _buf_y(0) + { } + + int x() const { return _x; } + int y() const { return _y; } + int w() const { return _w; } + int h() const { return _h; } + int buf_x() const { return _buf_x; } + int buf_y() const { return _buf_y; } + + + /****************************** + ** Nitpicker view interface ** + ******************************/ + + int viewport(int x, int y, int w, int h, + int buf_x, int buf_y, bool redraw) + { + _x = x; _y = y; _w = w; _h = h; + _buf_x = buf_x; _buf_y = buf_y; + + if (_viewport_initialized) + return 0; + + _viewport_initialized = true; + + /* hide the view and let the application set the viewport */ + int result = _view.viewport(0, 0, 0, 0, 0, 0, true); + + /* signal readyness of the view */ + if (_sigh.valid()) + Signal_transmitter(_sigh).submit(); + + return result; + } + + int stack(View_capability neighbor_cap, bool behind, bool redraw) + { + /* + * Only one child view is supported, so the stack request can + * be ignored. + */ + return 0; + } + + int title(Title const &title) + { + return _view.title(title.string()); + } + }; + + + class Session_component : public Rpc_object, + public Input::Transformer + { + private: + + Rpc_entrypoint &_ep; + + int _fb_width, _fb_height; + + Nitpicker::Connection _nitpicker; + View_capability _nitpicker_view; + + View_component _proxy_view; + View_capability _proxy_view_cap; + + Loader_view_component _loader_view; + View_capability _loader_view_cap; + + Input::Session_component _proxy_input; + Input::Session_capability _proxy_input_cap; + + static long _session_arg(const char *arg, const char *key) { + return Arg_string::find_arg(arg, key).long_value(0); } + + public: + + /** + * Constructor + */ + Session_component(Rpc_entrypoint &ep, + Signal_context_capability view_ready_sigh, + const char *args) + : + _ep(ep), + + /* store the framebuffer size for view size constraining */ + _fb_width(_session_arg(args, "fb_width")), + _fb_height(_session_arg(args, "fb_height")), + + /* connect to the "real" Nitpicker service */ + _nitpicker(_fb_width, _fb_height), + + /* create Nitpicker view */ + _nitpicker_view(_nitpicker.create_view()), + + /* create proxy view component for the child */ + _proxy_view(_nitpicker_view, view_ready_sigh), + _proxy_view_cap(_ep.manage(&_proxy_view)), + + /* create view component accessed by the loader client */ + _loader_view(_nitpicker_view), + _loader_view_cap(_ep.manage(&_loader_view)), + + _proxy_input(_nitpicker.input_session(), *this), + _proxy_input_cap(_ep.manage(&_proxy_input)) + { } + + + /********************************* + ** Nitpicker session interface ** + *********************************/ + + Framebuffer::Session_capability framebuffer_session() + { + return _nitpicker.framebuffer_session(); + } + + Input::Session_capability input_session() + { + return _proxy_input_cap; + } + + View_capability create_view() + { + return _proxy_view_cap; + } + + void destroy_view(View_capability view) + { + _nitpicker.destroy_view(_nitpicker_view); + } + + int background(View_capability view) + { + /* not forwarding to real nitpicker session */ + return 0; + } + + + /********************************** + ** Input::Transformer interface ** + **********************************/ + + Input::Transformer::Delta delta() + { + /* translate mouse position to child's coordinate system */ + Input::Transformer::Delta result = { + _loader_view.x() + _loader_view.buf_x() + + _proxy_view.x() + _proxy_view.buf_x(), + _loader_view.y() + _loader_view.buf_y() + + _proxy_view.y() + _proxy_view.buf_y() }; + + return result; + } + + /** + * Return the client-specific wrapper view for the Nitpicker view + * showing the child content + */ + View_capability loader_view() { return _loader_view_cap; } + + /** + * Return geometry of loader view + */ + Loader::Session::View_geometry loader_view_geometry() + { + Loader::Session::View_geometry result = { + min(_proxy_view.w(), _fb_width), + min(_proxy_view.h(), _fb_height), + _proxy_view.buf_x(), + _proxy_view.buf_y() }; + + return result; + } + }; +} + +#endif /* _NITPICKER_H_ */ diff --git a/os/src/server/loader/nitpicker_root.h b/os/src/server/loader/nitpicker_root.h deleted file mode 100644 index 1081c54d1a..0000000000 --- a/os/src/server/loader/nitpicker_root.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * \brief Nitpicker root interface - * \author Christian Prochaska - * \date 2010-07-12 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _NITPICKER_ROOT_H_ -#define _NITPICKER_ROOT_H_ - -/* Genode includes */ -#include - -/* local includes */ -#include - -namespace Nitpicker { - - /** - * Shortcut for single-client root component - */ - typedef Genode::Root_component Root_component; - - class Root : public Root_component - { - private: - - Genode::Timed_semaphore *_ready_sem; - Nitpicker::Session_component *_nsc; - - protected: - - Nitpicker::Session_component *_create_session(const char *args) - { - _nsc = new (md_alloc()) Nitpicker::Session_component(ep(), _ready_sem, args); - return _nsc; - } - - public: - - /** - * Constructor - * - * \param session_ep entry point for managing ram session objects - * \param md_alloc meta-data allocator to be used by root component - */ - Root(Genode::Rpc_entrypoint *session_ep, - Genode::Allocator *md_alloc, - Genode::Timed_semaphore *ready_sem) - : Root_component(session_ep, md_alloc), _ready_sem(ready_sem), _nsc(0) - { } - - ~Root() - { - Genode::destroy(md_alloc(), _nsc); - } - - void close(Genode::Session_capability cap) - { - destroy(md_alloc(), _nsc); - _nsc = 0; - } - - Nitpicker::View_capability view(int *w, int *h, int *buf_x, int *buf_y) - { - if (_nsc) { - return _nsc->loader_view(w, h, buf_x, buf_y); - } else { - PERR("the plugin has not created a Nitpicker session yet"); - return Nitpicker::View_capability(); - } - } - }; -} - -#endif /* _NITPICKER_ROOT_H_ */ diff --git a/os/src/server/loader/nitpicker_session_component.cc b/os/src/server/loader/nitpicker_session_component.cc deleted file mode 100644 index 034e697cc5..0000000000 --- a/os/src/server/loader/nitpicker_session_component.cc +++ /dev/null @@ -1,152 +0,0 @@ -/* - * \brief Nitpicker session component - * \author Christian Prochaska - * \date 2010-09-02 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* local includes */ -#include -#include - - -using namespace Nitpicker; -using namespace Genode; - - -static long session_arg(const char *arg, const char *key) -{ - return Arg_string::find_arg(arg, key).long_value(0); -} - - -Session_component::Session_component(Rpc_entrypoint *ep, - Timed_semaphore *ready_sem, - const char *args) -: - /* connect to the "real" Nitpicker service */ - _nitpicker(session_arg(args, "fb_width"), - session_arg(args, "fb_height")), - _ep(ep), _ready_sem(ready_sem), _input_root(_ep, env()->heap(), this) -{ - _proxy_input_session = static_cap_cast(_input_root.session("ram_quota=256K")); -} - - -Session_component::~Session_component() -{ - if (_loader_view) { - _ep->dissolve(_loader_view); - destroy(env()->heap(), _loader_view); - } - - if (_proxy_view) { - _ep->dissolve(_proxy_view); - destroy(env()->heap(), _proxy_view); - } - - if (_proxy_input_session.valid()) - _input_root.close(_proxy_input_session); - - if (_nitpicker_view.valid()) - _nitpicker.destroy_view(_nitpicker_view); -} - - -Framebuffer::Session_capability Session_component::framebuffer_session() -{ - return _nitpicker.framebuffer_session(); -} - - -Input::Session_capability Session_component::input_session() -{ - return _proxy_input_session; -} - - -View_capability Nitpicker::Session_component::create_view() -{ - /* only one view is allowed */ - if (_proxy_view_cap.valid()) - return View_capability(); - - /* create Nitpicker view */ - _nitpicker_view = _nitpicker.create_view(); - - /* create proxy view component for the child */ - _proxy_view = new (env()->heap()) - View_component(_nitpicker_view, _ready_sem); - - /* create proxy view capability for the child */ - _proxy_view_cap = View_capability(_ep->manage(_proxy_view)); - - /* create view component accessed by the client */ - _loader_view = new (env()->heap()) - Loader_view_component(_nitpicker_view); - - /* create proxy view capability for the application */ - _loader_view_cap = View_capability(_ep->manage(_loader_view)); - - /* return proxy view capability */ - return _proxy_view_cap; -} - - -void Session_component::destroy_view(View_capability view) -{ - if (!_loader_view_cap.valid()) return; - - /* destroy proxy views */ - _ep->dissolve(_proxy_view); - destroy(env()->heap(), _proxy_view); - _proxy_view = 0; - - _ep->dissolve(_loader_view); - destroy(env()->heap(), _loader_view); - _loader_view = 0; - - /* destroy nitpicker view */ - _nitpicker.destroy_view(_nitpicker_view); -} - - -int Session_component::background(View_capability view) -{ - /* not forwarding to real nitpicker session */ - return 0; -} - - -View_capability Session_component::loader_view(int *w, int *h, int *buf_x, int *buf_y) -{ - /* return the view geometry as set by the child */ - if (_proxy_view) { - _proxy_view->get_viewport(0, 0, w, h, buf_x, buf_y); - } - return _loader_view_cap; -} - - -Input::Session_capability Session_component::real_input_session() -{ - return _nitpicker.input_session(); -} - - -Loader_view_component *Session_component::loader_view_component() -{ - return _loader_view; -} - - -View_component *Session_component::proxy_view_component() -{ - return _proxy_view; -} diff --git a/os/src/server/loader/nitpicker_session_component.h b/os/src/server/loader/nitpicker_session_component.h deleted file mode 100644 index 28f1aea469..0000000000 --- a/os/src/server/loader/nitpicker_session_component.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * \brief Instance of the Nitpicker session interface - * \author Christian Prochaska - * \date 2009-10-05 - */ - -/* - * Copyright (C) 2009-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _NITPICKER_SESSION_COMPONENT_H_ -#define _NITPICKER_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include - -/* local includes */ -#include -#include -#include - -namespace Nitpicker { - - class Session_component : public Genode::Rpc_object - { - private: - - Nitpicker::Connection _nitpicker; - View_capability _nitpicker_view; - View_capability _proxy_view_cap; - View_capability _loader_view_cap; - - Genode::Rpc_entrypoint *_ep; - Genode::Timed_semaphore *_ready_sem; - View_component *_proxy_view; - Loader_view_component *_loader_view; - - Input::Root _input_root; - Input::Session_capability _proxy_input_session; - - public: - - /** - * Constructor - * - * \param args session-construction arguments, in - * particular the filename - */ - Session_component(Genode::Rpc_entrypoint *ep, - Genode::Timed_semaphore *ready_sem, - const char *args); - - /** - * Destructor - */ - ~Session_component(); - - - /********************************* - ** Nitpicker session interface ** - *********************************/ - - Framebuffer::Session_capability framebuffer_session(); - Input::Session_capability input_session(); - View_capability create_view(); - void destroy_view(View_capability view); - int background(View_capability view); - - - /** - * Return the client-specific wrapper view for the Nitpicker view - * showing the child content - */ - View_capability loader_view(int *w, int *h, int *buf_x, int *buf_y); - - /** - * Request real input sub-session - * - * This method is not accessible to ipc clients. - */ - virtual Input::Session_capability real_input_session(); - - /** - * Request child view component - * - * This method is meant to be used by the input wrapper and not - * accessible to ipc clients. - */ - View_component *proxy_view_component(); - - /** - * Request client view component - * - * This method is meant to be used by the input wrapper and not - * accessible to ipc clients. - */ - Loader_view_component *loader_view_component(); - }; -} - -#endif /* _NITPICKER_SESSION_COMPONENT_H_ */ diff --git a/os/src/server/loader/nitpicker_view_component.h b/os/src/server/loader/nitpicker_view_component.h deleted file mode 100644 index 77701732c8..0000000000 --- a/os/src/server/loader/nitpicker_view_component.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * \brief Instance of the view interface used by the child - * \author Christian Prochaska - * \date 2009-10-21 - */ - -/* - * Copyright (C) 2009-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _NITPICKER_VIEW_COMPONENT_H_ -#define _NITPICKER_VIEW_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include -#include -#include - -namespace Nitpicker { - - class View_component : public Genode::Rpc_object - { - private: - - View_client _view; /* the wrapped view */ - - Genode::Timed_semaphore *_ready_sem; - - int _x, _y, _w, _h, _buf_x, _buf_y; - - bool _viewport_initialized; - - public: - - /** - * Constructor - */ - View_component(View_capability view_cap, Genode::Timed_semaphore *ready_sem) - : _view(view_cap), _ready_sem(ready_sem), _viewport_initialized(false) - { } - - - /****************************** - ** Nitpicker view interface ** - ******************************/ - - int viewport(int x, int y, int w, int h, - int buf_x, int buf_y, bool redraw) - { - _x = x; _y = y; - _w = w; _h = h; - _buf_x = buf_x; _buf_y = buf_y; - - if (_viewport_initialized) - return 0; - - _viewport_initialized = true; - - /* hide the view and let the application set the viewport */ - int result = _view.viewport(0, 0, 0, 0, 0, 0, true); - - /* viewport data is available -> loader can continue */ - _ready_sem->up(); - - return result; - } - - int stack(View_capability neighbor_cap, bool behind, bool redraw) - { - /* - * Only one child view is supported, so the stack request can - * be ignored. - */ - return 0; - } - - int title(Title const &title) - { - return _view.title(title.string()); - } - - void get_viewport(int *x, int *y, int *w, int *h, int *buf_x, int *buf_y) - { - if (x) *x = _x; - if (y) *y = _y; - if (w) *w = _w; - if (h) *h = _h; - if (buf_x) *buf_x = _buf_x; - if (buf_y) *buf_y = _buf_y; - } - }; -} - -#endif /* _NITPICKER_VIEW_COMPONENT_H_ */ diff --git a/os/src/server/loader/rom.h b/os/src/server/loader/rom.h new file mode 100644 index 0000000000..b33e663621 --- /dev/null +++ b/os/src/server/loader/rom.h @@ -0,0 +1,244 @@ +/* + * \brief ROM service exposed to the loaded subsystem + * \author Norman Feske + * \date 2012-04-17 + */ + +#ifndef _ROM_H_ +#define _ROM_H_ + +//#include +#include +#include +#include + +namespace Genode { + + class Rom_module : public List::Element + { + private: + + enum { MAX_NAME_LEN = 64 }; + char _name[MAX_NAME_LEN]; + + Ram_session &_ram; + Attached_ram_dataspace _fg; + Attached_ram_dataspace _bg; + + bool _bg_has_pending_data; + + Signal_context_capability _sigh; + + Lock _lock; + + public: + + Rom_module(char const *name, Ram_session &ram_session) + : + _ram(ram_session), + _fg(&_ram, 0), _bg(&_ram, 0), + _bg_has_pending_data(false), + _lock(Lock::LOCKED) + { + strncpy(_name, name, sizeof(_name)); + } + + bool has_name(char const *name) const + { + return strcmp(_name, name) == 0; + } + + void lock() { _lock.lock(); } + void unlock() { _lock.unlock(); } + + /** + * Return dataspace as handed out to loader session + * + * The loader session submits the data into the ROM module into + * the background dataspace. Once it is ready, the 'commit_bg()' + * function is called. + */ + Dataspace_capability bg_dataspace(size_t size) + { + /* let background buffer grow if needed */ + if (_bg.size() < size) + _bg.realloc(&_ram, size); + + return _bg.cap(); + } + + /** + * Return dataspace as handed out to ROM session client + */ + Rom_dataspace_capability fg_dataspace() + { + if (!_fg.size() && !_bg_has_pending_data) { + PERR("Error: no data loaded"); + return Rom_dataspace_capability(); + } + + /* + * Keep foreground if no background exists. Otherwise, use + * old background as new foreground. + */ + if (_bg_has_pending_data) { + _fg.swap(_bg); + _bg_has_pending_data = false; + } + + Dataspace_capability ds_cap = _fg.cap(); + return static_cap_cast(ds_cap); + } + + /** + * Set signal handler to inform about ROM module updates + * + * This function is indirectly called by the ROM session client. + */ + void sigh(Signal_context_capability sigh) { _sigh = sigh; } + + /** + * Commit data contained in background dataspace + * + * This function is indirectly called by the loader session. + */ + void commit_bg() + { + _bg_has_pending_data = true; + + if (_sigh.valid()) + Signal_transmitter(_sigh).submit(); + } + }; + + + struct Rom_module_lock_guard + { + Rom_module &rom; + + Rom_module_lock_guard(Rom_module &rom) : rom(rom) { } + + ~Rom_module_lock_guard() { rom.unlock(); } + }; + + + class Rom_module_registry + { + private: + + Lock _lock; + Ram_session &_ram_session; + Allocator &_md_alloc; + List _list; + + public: + + /** + * Exception type + */ + class Lookup_failed { }; + + /** + * Constructor + * + * \param ram_session RAM session used as backing store for + * module data + * \param md_alloc backing store for ROM module meta data + */ + Rom_module_registry(Ram_session &ram_session, Allocator &md_alloc) + : + _ram_session(ram_session), _md_alloc(md_alloc) + { } + + ~Rom_module_registry() + { + Lock::Guard guard(_lock); + + while (_list.first()) { + Rom_module *rom = _list.first(); + rom->lock(); + _list.remove(rom); + destroy(&_md_alloc, rom); + } + } + + /** + * Lookup ROM module by name + * + * \throw Lookup_failed + */ + Rom_module &lookup_and_lock(char const *name) + { + Lock::Guard guard(_lock); + + Rom_module *curr = _list.first(); + for (; curr; curr = curr->next()) { + if (curr->has_name(name)) { + curr->lock(); + return *curr; + } + } + throw Lookup_failed(); + } + + Dataspace_capability alloc_rom_module(char const *name, size_t size) + { + try { + Rom_module &module = lookup_and_lock(name); + Rom_module_lock_guard guard(module); + return module.bg_dataspace(size); + } + catch (Lookup_failed) { + + Lock::Guard guard(_lock); + + Rom_module *module = new (&_md_alloc) + Rom_module(name, _ram_session); + + Rom_module_lock_guard module_guard(*module); + + _list.insert(module); + + return module->bg_dataspace(size); + } + } + + /** + * \throw Lookup_failed + */ + void commit_rom_module(char const *name) + { + Rom_module &rom_module = lookup_and_lock(name); + rom_module.commit_bg(); + rom_module.unlock(); + } + }; + + + class Rom_session_component : public Rpc_object, + public List::Element + { + private: + + Rom_module &_rom_module; + + public: + + Rom_session_component(Rom_module &rom_module) + : _rom_module(rom_module) { } + + Rom_dataspace_capability dataspace() + { + Rom_module_lock_guard guard(_rom_module); + return _rom_module.fg_dataspace(); + } + + void sigh(Signal_context_capability sigh) + { + Rom_module_lock_guard guard(_rom_module); + _rom_module.sigh(sigh); + } + }; +} + +#endif /* _ROM_H_ */ diff --git a/os/src/server/loader/rom_root.h b/os/src/server/loader/rom_root.h deleted file mode 100644 index 10b55ea56c..0000000000 --- a/os/src/server/loader/rom_root.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * \brief ROM root interface for tar files - * \author Christian Prochaska - * \date 2010-08-26 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _ROM_ROOT_H_ -#define _ROM_ROOT_H_ - -/* Genode includes */ -#include - -/* local includes */ -#include "rom_session_component.h" - -class Rom_root : public Genode::Root_component -{ - private: - - /** - * Entry point for managing rom dataspaces - */ - Genode::Rpc_entrypoint *_ds_ep; - - Genode::Root_capability _tar_server_root; - - protected: - - Rom_session_component *_create_session(const char *args) - { - return new (md_alloc()) Rom_session_component(_ds_ep, args, _tar_server_root); - } - - public: - - /** - * Constructor - * - * \param session_ep entry point for managing ram session objects - * \param ds_ep entry point for managing dataspaces - * \param md_alloc meta-data allocator to be used by root component - * \param tar_server_root root capability for tar server - */ - Rom_root(Genode::Rpc_entrypoint *session_ep, - Genode::Rpc_entrypoint *ds_ep, - Genode::Allocator *md_alloc, - Genode::Root_capability tar_server_root) - : - Genode::Root_component(session_ep, md_alloc), - _ds_ep(ds_ep), _tar_server_root(tar_server_root) { } -}; - -#endif /* _ROM_ROOT_H_ */ diff --git a/os/src/server/loader/rom_session_component.cc b/os/src/server/loader/rom_session_component.cc deleted file mode 100644 index 9ac058e476..0000000000 --- a/os/src/server/loader/rom_session_component.cc +++ /dev/null @@ -1,70 +0,0 @@ -/* - * \brief ROM session component for tar files - * \author Christian Prochaska - * \date 2010-08-26 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include - - -using namespace Genode; - -Rom_session_component::Rom_session_component(Rpc_entrypoint *ds_ep, - const char *args, - Root_capability tar_server_root) -: _ds_ep(ds_ep), - _tar_server_client(0), - _parent_rom_connection(0) -{ - /* extract filename from session arguments */ - char fname_buf[32]; - Arg_string::find_arg(args, "filename").string(fname_buf, sizeof(fname_buf), ""); - - PDBG("filename = %s", fname_buf); - - if (tar_server_root.valid()) { - /* try to get the file from the tar server */ - _tar_server_client = new (env()->heap()) Root_client(tar_server_root); - char tar_args[256]; - snprintf(tar_args, sizeof(tar_args), "filename=\"%s\", ram_quota=4K", fname_buf); - _tar_server_session = static_cap_cast(_tar_server_client->session(tar_args)); - Rom_session_client rsc(_tar_server_session); - _ds_cap = rsc.dataspace(); - } - - if (!_ds_cap.valid()) { - /* no tar server started or file not found in tar archive -> ask parent */ - PDBG("file not found in tar archive, asking parent"); - try { - _parent_rom_connection = new (env()->heap()) Rom_connection(fname_buf); - _ds_cap = _parent_rom_connection->dataspace(); - } catch (Rom_connection::Rom_connection_failed) { - PDBG("could not find file %s", fname_buf); - throw Service::Invalid_args(); - } - } -} - - -Rom_session_component::~Rom_session_component() -{ - if (_tar_server_session.valid()) - _tar_server_client->close(_tar_server_session); - - destroy(env()->heap(), _tar_server_client); - destroy(env()->heap(), _parent_rom_connection); -} diff --git a/os/src/server/loader/rom_session_component.h b/os/src/server/loader/rom_session_component.h deleted file mode 100644 index cf1ddf0670..0000000000 --- a/os/src/server/loader/rom_session_component.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * \brief ROM session component for tar files - * \author Christian Prochaska - * \date 2010-08-26 - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _ROM_SESSION_COMPONENT_H_ -#define _ROM_SESSION_COMPONENT_H_ - -/* Genode includes */ -#include -#include -#include - -class Rom_session_component : public Genode::Rpc_object -{ - private: - - Genode::Rpc_entrypoint *_ds_ep; - Genode::Rom_dataspace_capability _ds_cap; - - Genode::Root_client *_tar_server_client; - Genode::Rom_session_capability _tar_server_session; - Genode::Rom_connection *_parent_rom_connection; - - public: - - /** - * Constructor - * - * \param ds_ep entry point to manage the dataspace - * corresponding the rom session - * \param args session-construction arguments, in - * particular the filename - */ - Rom_session_component(Genode::Rpc_entrypoint *ds_ep, - const char *args, - Genode::Root_capability tar_server_root); - - /** - * Destructor - */ - ~Rom_session_component(); - - - /*************************** - ** Rom session interface ** - ***************************/ - - Genode::Rom_dataspace_capability dataspace() { return _ds_cap; } - - void sigh(Genode::Signal_context_capability) { } -}; - -#endif /* _ROM_SESSION_COMPONENT_H_ */ diff --git a/os/src/server/loader/tar_server_child.h b/os/src/server/loader/tar_server_child.h deleted file mode 100644 index d6960da1fe..0000000000 --- a/os/src/server/loader/tar_server_child.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * \brief Tar service child - * \author Christian Prochaska - * \date 2010-08-26 - * - */ - -/* - * Copyright (C) 2010-2012 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _TAR_SERVER_CHILD_H_ -#define _TAR_SERVER_CHILD_H_ - -/* Genode includes */ -#include -#include -#include - -class Tar_server_child : public Genode::Child_policy, - public Init::Child_policy_enforce_labeling -{ - private: - - const char *_unique_name; - - /* - * Entry point used for serving the parent interface - */ - enum { STACK_SIZE = 8*1024 }; - Genode::Rpc_entrypoint _entrypoint; - - struct Resources - { - Genode::Ram_connection ram; - Genode::Cpu_connection cpu; - Genode::Rm_connection rm; - - /* session costs to be deduced from usable ram quota */ - enum { DONATIONS = Genode::Rm_connection::RAM_QUOTA + - Genode::Cpu_connection::RAM_QUOTA + - Genode::Ram_connection::RAM_QUOTA }; - - Resources(char const *label, Genode::size_t ram_quota) - : ram(label), cpu(label) - { - if (ram_quota > DONATIONS) - ram_quota -= DONATIONS; - else ram_quota = 0; - - ram.ref_account(Genode::env()->ram_session_cap()); - Genode::env()->ram_session()->transfer_quota( - ram.cap(), ram_quota); - } - } _resources; - - Genode::Child _child; - Genode::Service_registry *_parent_services; - - Genode::Lock _tar_server_ready_lock; - Genode::Root_capability _tar_server_root; - - Genode::Dataspace_capability _config_ds; - - Init::Child_policy_provide_rom_file _config_policy; - Init::Child_policy_provide_rom_file _tar_ds_policy; - - Genode::Dataspace_capability _create_config_ds() - { - using namespace Genode; - - Dataspace_capability ds_cap; - - /* the tar server asked for the config file containing the name of the tar file */ - const char *config_string = ""; - size_t config_size = strlen(config_string) + 1; - ds_cap = env()->ram_session()->alloc(config_size); - char *config_addr = env()->rm_session()->attach(ds_cap); - strncpy(config_addr, config_string, config_size); - env()->rm_session()->detach(config_addr); - - return ds_cap; - } - - public: - - enum { DONATIONS = Resources::DONATIONS }; - - Tar_server_child(const char *unique_name, - Genode::Dataspace_capability elf_ds, - Genode::size_t ram_quota, - Genode::Cap_session *cap_session, - Genode::Service_registry *parent_services, - Genode::Dataspace_capability tar_ds) - : Init::Child_policy_enforce_labeling(unique_name), - _unique_name(unique_name), - _entrypoint(cap_session, STACK_SIZE, unique_name, false), - _resources(unique_name, ram_quota), - _child(elf_ds, _resources.ram.cap(), _resources.cpu.cap(), - _resources.rm.cap(), &_entrypoint, this), - _parent_services(parent_services), - _tar_server_ready_lock(Genode::Cancelable_lock::LOCKED), - _config_ds(_create_config_ds()), - _config_policy("config", _config_ds, &_entrypoint), - _tar_ds_policy("tar_ds", tar_ds, &_entrypoint) - { - _entrypoint.activate(); - _tar_server_ready_lock.lock(); - } - - ~Tar_server_child() - { - using namespace Genode; - env()->ram_session()->free(static_cap_cast(_config_ds)); - } - - /**************************** - ** Child-policy interface ** - ****************************/ - - const char *name() const { return _unique_name; } - - void filter_session_args(const char *, char *args, Genode::size_t args_len) - { - Init::Child_policy_enforce_labeling::filter_session_args(0, args, args_len); - } - - bool announce_service(const char *name, - Genode::Root_capability root, - Genode::Allocator *alloc) - { - if (Genode::strcmp(name, "ROM") != 0) - return false; - - _tar_server_root = root; - _tar_server_ready_lock.unlock(); - return true; - } - - Genode::Service *resolve_session_request(const char *service_name, - const char *args) - { - using namespace Genode; - - PDBG("service_name = %s", service_name); - - Service *service = 0; - - /* check for config file request */ - if ((service = _config_policy.resolve_session_request(service_name, args))) - return service; - - /* check for tar_ds file request */ - if ((service = _tar_ds_policy.resolve_session_request(service_name, args))) - return service; - - service = _parent_services->find(service_name); - if (!service) { - service = new (env()->heap()) Parent_service(service_name); - _parent_services->insert(service); - } - return service; - } - - Genode::Root_capability tar_server_root() { return _tar_server_root; } -}; - -#endif /* _TAR_SERVER_CHILD_H_ */ diff --git a/os/src/server/loader/target.mk b/os/src/server/loader/target.mk index 987f776136..9759623c6b 100644 --- a/os/src/server/loader/target.mk +++ b/os/src/server/loader/target.mk @@ -1,8 +1,4 @@ TARGET = loader +LIBS = cxx env thread server process signal +SRC_CC = main.cc INC_DIR += $(PRG_DIR) -LIBS = cxx env thread server process signal timed_semaphore -SRC_CC = main.cc \ - loader_session_component.cc \ - rom_session_component.cc \ - nitpicker_session_component.cc \ - input_session_component.cc diff --git a/os/src/test/dynamic_config/loader/main.cc b/os/src/test/dynamic_config/loader/main.cc new file mode 100644 index 0000000000..e73cfab704 --- /dev/null +++ b/os/src/test/dynamic_config/loader/main.cc @@ -0,0 +1,64 @@ +/* + * \brief Test for changing the configuration of a loader plugin at runtime + * \author Christian Prochaska + * \date 2012-04-20 + */ + +/* + * Copyright (C) 2012 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include +#include +#include + + +using namespace Genode; + + +enum { CONFIG_SIZE = 100 }; + +static Loader::Connection loader(8*1024*1024); + + +static void update_config(int counter) +{ + Dataspace_capability config_ds = + loader.alloc_rom_module("config", CONFIG_SIZE); + + char *config_ds_addr = env()->rm_session()->attach(config_ds); + + snprintf(config_ds_addr, CONFIG_SIZE, + "%d", + counter); + + env()->rm_session()->detach(config_ds_addr); + + loader.commit_rom_module("config"); +} + + +int main(int, char **) +{ + update_config(-1); + + loader.start("test-dynamic_config", "test-label"); + + /* update slave config at regular intervals */ + int counter = 0; + for (;;) { + + static Timer::Connection timer; + timer.msleep(250); + update_config(counter++); + } + + sleep_forever(); + + return 0; +} diff --git a/os/src/test/dynamic_config/loader/target.mk b/os/src/test/dynamic_config/loader/target.mk new file mode 100644 index 0000000000..590d773130 --- /dev/null +++ b/os/src/test/dynamic_config/loader/target.mk @@ -0,0 +1,3 @@ +TARGET = test-dynamic_config_loader +SRC_CC = main.cc +LIBS = env diff --git a/os/src/test/loader/main.cc b/os/src/test/loader/main.cc index afcdc47258..f03aed0e4d 100644 --- a/os/src/test/loader/main.cc +++ b/os/src/test/loader/main.cc @@ -13,52 +13,45 @@ #include #include -#include #include #include -#include #include -#include using namespace Genode; int main(int argc, char **argv) { - Rom_connection rc("testnit"); - Dataspace_capability rom_ds = rc.dataspace(); - char *rom_ds_addr = (char*)env()->rm_session()->attach(rom_ds); + Loader::Connection loader(8*1024*1024); - size_t rom_ds_size = Dataspace_client(rom_ds).size(); - char args[256] = ""; - Arg_string::set_arg(args, sizeof(args),"ram_quota", "8M"); - Arg_string::set_arg(args, sizeof(args),"ds_size", rom_ds_size); + static Signal_receiver sig_rec; - Loader::Connection lc(args); - Dataspace_capability loader_ds = lc.dataspace(); - char *loader_ds_addr = (char*)env()->rm_session()->attach(loader_ds); + Signal_context sig_ctx; - memcpy(loader_ds_addr, rom_ds_addr, rom_ds_size); + loader.view_ready_sigh(sig_rec.manage(&sig_ctx)); - env()->rm_session()->detach(loader_ds_addr); - env()->rm_session()->detach(rom_ds_addr); + loader.start("testnit", "test-label"); - lc.start("ram_quota=4M", 800, 600, 1000, "testnit"); + sig_rec.wait_for_signal(); - int w, h, buf_x, buf_y; - Nitpicker::View_capability view_cap = lc.view(&w, &h, &buf_x, &buf_y); + Nitpicker::View_capability view_cap = loader.view(); - PDBG("w = %d, h = %d, buf_x = %d, buf_y = %d", w, h, buf_x, buf_y); + Loader::Session::View_geometry geometry = loader.view_geometry(); - Nitpicker::View_client vc(view_cap); - vc.stack(Nitpicker::View_capability(), true, false); + PDBG("w = %d, h = %d, buf_x = %d, buf_y = %d", + geometry.width, geometry.height, geometry.buf_x, geometry.buf_y); - Timer::Connection tc; + Nitpicker::View_client view(view_cap); + view.stack(Nitpicker::View_capability(), true, false); + + Timer::Connection timer; while(1) { - vc.viewport(0, 0, w, h, buf_x, buf_y, true); - tc.msleep(1000); - vc.viewport(50, 50, w, h, buf_x, buf_y, true); - tc.msleep(1000); + view.viewport(0, 0, geometry.width, geometry.height, + geometry.buf_x, geometry.buf_y, true); + timer.msleep(1000); + view.viewport(50, 50, geometry.width, geometry.height, + geometry.buf_x, geometry.buf_y, true); + timer.msleep(1000); } sleep_forever(); diff --git a/os/src/test/loader/target.mk b/os/src/test/loader/target.mk index 89b62db129..c856154832 100644 --- a/os/src/test/loader/target.mk +++ b/os/src/test/loader/target.mk @@ -1,3 +1,3 @@ TARGET = test-loader SRC_CC = main.cc -LIBS = cxx env +LIBS = cxx env signal