/* * \brief Convenience helper for running a service as child process * \author Norman Feske * \author Christian Helmuth * \date 2012-01-25 */ /* * Copyright (C) 2012-2013 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 _INCLUDE__OS__SLAVE_H_ #define _INCLUDE__OS__SLAVE_H_ /* Genode includes */ #include #include #include #include #include #include #include #include namespace Genode { class Slave_policy; class Slave; } /** * Slave-policy class * * This class provides a convenience policy for single-service slaves using a * white list of parent services. */ class Genode::Slave_policy : public Genode::Child_policy { protected: /** * Return white list of services the slave is permitted to use * * The list is terminated via a null pointer. */ virtual char const **_permitted_services() const = 0; private: char const *_label; Genode::Service_registry _parent_services; Genode::Rpc_entrypoint &_entrypoint; Genode::Rom_connection _binary_rom; Init::Child_policy_enforce_labeling _labeling_policy; Init::Child_policy_provide_rom_file _binary_policy; Genode::Child_policy_dynamic_rom_file _config_policy; bool _service_permitted(const char *service_name) { for (const char **s = _permitted_services(); *s; ++s) if (!Genode::strcmp(service_name, *s)) return true; return false; } public: /** * Slave-policy constructor * * \param label name of the program to start * \param entrypoint entrypoint used to provide local services * such as the config ROM service * \param ram RAM session used for buffering config data * * If 'ram' is set to 0, no configuration can be supplied to the * slave. */ Slave_policy(const char *label, Genode::Rpc_entrypoint &entrypoint, Genode::Ram_session *ram = 0, const char *binary = nullptr) : _label(label), _entrypoint(entrypoint), _binary_rom(binary ? binary : _label, _label), _labeling_policy(_label), _binary_policy("binary", _binary_rom.dataspace(), &_entrypoint), _config_policy("config", _entrypoint, ram) { } Genode::Dataspace_capability binary() { return _binary_rom.dataspace(); } /** * Assign new configuration to slave */ void configure(char const *config) { _config_policy.load(config, Genode::strlen(config) + 1); } void configure(char const *config, size_t len) { _config_policy.load(config, len); } /**************************** ** Child_policy interface ** ****************************/ const char *name() const { return _label; } Genode::Service *resolve_session_request(const char *service_name, const char *args) { Genode::Service *service = 0; /* check for binary file request */ if ((service = _binary_policy.resolve_session_request(service_name, args))) return service; /* check for config file request */ if ((service = _config_policy.resolve_session_request(service_name, args))) return service; if (!_service_permitted(service_name)) { PERR("%s: illegal session request of service \"%s\"", name(), service_name); return 0; } /* fill parent service registry on demand */ if (!(service = _parent_services.find(service_name))) { service = new (Genode::env()->heap()) Genode::Parent_service(service_name); _parent_services.insert(service); } /* return parent service */ return service; } void filter_session_args(const char *service, char *args, Genode::size_t args_len) { _labeling_policy.filter_session_args(service, args, args_len); } }; class Genode::Slave { private: struct Resources { Genode::Pd_connection pd; Genode::Ram_connection ram; Genode::Cpu_connection cpu; Genode::Rm_connection rm; class Quota_exceeded : public Genode::Exception { }; Resources(const char *label, Genode::size_t ram_quota, Ram_session_capability ram_ref_cap) : pd(label), ram(label), cpu(label) { ram.ref_account(ram_ref_cap); Ram_session_client ram_ref(ram_ref_cap); if (ram_ref.transfer_quota(ram.cap(), ram_quota)) throw Quota_exceeded(); } }; Resources _resources; Genode::Child _child; public: Slave(Genode::Rpc_entrypoint &entrypoint, Slave_policy &slave_policy, Genode::size_t ram_quota, Ram_session_capability ram_ref_cap = env()->ram_session_cap()) : _resources(slave_policy.name(), ram_quota, ram_ref_cap), _child(slave_policy.binary(), _resources.pd.cap(), _resources.ram.cap(), _resources.cpu.cap(), _resources.rm.cap(), &entrypoint, &slave_policy) { } Genode::Ram_connection &ram() { return _resources.ram; } /*************************************** ** Wrappers of the 'Child' interface ** ***************************************/ void yield(Genode::Parent::Resource_args const &args) { _child.yield(args); } void notify_resource_avail() const { _child.notify_resource_avail(); } }; #endif /* _INCLUDE__OS__SLAVE_H_ */