/* * \brief Utility for handling child configuration * \author Norman Feske * \date 2008-03-22 */ /* * Copyright (C) 2008-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__INIT__CHILD_CONFIG_H_ #define _INCLUDE__INIT__CHILD_CONFIG_H_ #include #include #include #include #include namespace Init { class Child_config; } class Init::Child_config { private: enum { CONFIGFILE_NAME_LEN = 64 }; char _filename[CONFIGFILE_NAME_LEN]; Genode::Ram_session_capability _ram_session_cap; Genode::Ram_dataspace_capability _config_ram_ds; public: /** * Constructor * * The provided RAM session is used to obtain a dataspace for * holding the copy of the child's configuration data unless the * configuration is supplied via a config file. Normally, the * child's RAM session should be used to account the consumed RAM * quota to the child. */ Child_config(Genode::Ram_session_capability ram_session, Genode::Xml_node start_node) : _ram_session_cap(ram_session) { using namespace Genode; /* * If the start node contains a 'filename' entry, we only keep * the information about the file name. */ _filename[0] = 0; try { Xml_node configfile_node = start_node.sub_node("configfile"); configfile_node.attribute("name") .value(_filename, sizeof(_filename)); return; } catch (...) { } /* * If the start node contains a 'config' entry, we copy this * entry into a fresh dataspace to be provided to our child. */ Ram_session_client rsc(_ram_session_cap); try { Xml_node config_node = start_node.sub_node("config"); const char *config = config_node.addr(); Genode::size_t config_size = config_node.size(); if (!config || !config_size) return; /* * Allocate RAM dataspace that is big enough to * hold the configuration and the null termination. */ _config_ram_ds = rsc.alloc(config_size + 1); /* * Make dataspace locally accessible, copy * configuration into the dataspace, and append * a string-terminating zero. */ void *addr = env()->rm_session()->attach(_config_ram_ds); Genode::memcpy(addr, config, config_size); static_cast(addr)[config_size] = 0; env()->rm_session()->detach(addr); } catch (Region_map::Attach_failed) { rsc.free(_config_ram_ds); return; } catch (Ram_session::Alloc_failed) { return; } catch (Xml_node::Nonexistent_sub_node) { } } /** * Destructor */ ~Child_config() { using namespace Genode; /* * The configuration data is either provided as a ROM session * (holding a complete configfile) or as a RAM dataspace * holding a copy of the start node's config entry. In the * latter case, the child's configuration resides in a * shadow copy kept in '_config_ram_ds'. */ if (_config_ram_ds.valid()) Ram_session_client(_ram_session_cap).free(_config_ram_ds); } /** * Return file name if configuration comes from a file * * If the configuration is provided inline, the method returns 0. */ char const *filename() const { return _filename[0] != 0 ? _filename : 0; } /** * Request dataspace holding the start node's configuration data * * This method returns a valid dataspace only when using an * inline configuration (if 'filename()' returns 0). */ Genode::Dataspace_capability dataspace() { return Genode::Dataspace_capability(_config_ram_ds); } }; #endif /* _INCLUDE__INIT__CHILD_CONFIG_H_ */