mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-29 01:58:55 +00:00
9a00ad7ae3
This patch introduces support for ROM sessions that update their provided data during the lifetime of the session. The 'Rom_session' interface had been extended with the new 'release()' and 'sigh()' functions, which are needed to support the new protocol. All ROM services have been updated to the new interface. Furthermore, the patch changes the child policy of init with regard to the handling of configuration files. The 'Init::Child' used to always provide the ROM dataspace with the child's config file via a locally implemented ROM service. However, for dynamic ROM sessions, we need to establish a session to the real supplier of the ROM data. This is achieved by using a new 'Child_policy_redirect_rom_file' policy to handle the 'configfile' rather than handling the 'configfile' case entirely within 'Child_config'. To see the new facility in action, the new 'os/run/dynamic_config.run' script provides a simple scenario. The config file of the test program is provided by a service, which generates and updates the config data at regular intervals. In addition, new support has been added to let slaves use dynamic reconfiguration. By using the new 'Child_policy_dynamic_rom_file', the configuration of a slave can be changed dynamically at runtime via the new 'configure()' function. The config is provided as plain null-terminated string (instead of a dataspace capability) because we need to buffer the config data anyway. So there is no benefit of using a dataspace. For buffering configuration data, a 'Ram_session' must be supplied. If no 'Ram_session' is specified at construction time of a 'Slave_policy', no config is supplied to the slave (which is still a common case). An example for dynamically reconfiguring a slave is provided by 'os/run/dynamic_config_slave.run'.
141 lines
3.8 KiB
C++
141 lines
3.8 KiB
C++
/*
|
|
* \brief Utility for handling child configuration
|
|
* \author Norman Feske
|
|
* \date 2008-03-22
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2008-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 _INCLUDE__INIT__CHILD_CONFIG_H_
|
|
#define _INCLUDE__INIT__CHILD_CONFIG_H_
|
|
|
|
#include <base/env.h>
|
|
#include <base/printf.h>
|
|
#include <util/xml_node.h>
|
|
#include <rom_session/connection.h>
|
|
#include <ram_session/client.h>
|
|
|
|
namespace Init {
|
|
|
|
class 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<char *>(addr)[config_size] = 0;
|
|
env()->rm_session()->detach(addr);
|
|
|
|
} catch (Rm_session::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 function returns 0.
|
|
*/
|
|
char const *filename() const {
|
|
return _filename[0] != 0 ? _filename : 0; }
|
|
|
|
/**
|
|
* Request dataspace holding the start node's configuration data
|
|
*
|
|
* This function 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_ */
|