genode/gems/src/server/d3m/main.cc

293 lines
7.8 KiB
C++
Raw Normal View History

/*
* \brief Demo device-driver manager (d3m)
* \author Christian Helmuth
* \author Norman Feske
* \date 2010-09-21
*
* D3m is a simple device-driver manager for demo purposes. Currently, it copes
* with the following tasks:
*
* - Merge events of input drivers for PS/2 and USB HID
* - Probe boot device using the ATAPI and USB storage drivers
*/
/*
2013-01-10 21:44:47 +01:00
* 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.
*/
/* Genode includes */
#include <os/slave.h>
#include <base/printf.h>
#include <base/sleep.h>
#include <base/env.h>
#include <rom_session/connection.h>
#include <cap_session/connection.h>
#include <nic_session/client.h>
/* local includes */
#include <input_service.h>
#include <nic_service.h>
#include <block_service.h>
class Ipxe_policy : public Genode::Slave_policy, public Nic::Provider
{
Genode::Root_capability _cap;
bool _announced;
Genode::Lock _lock;
protected:
char const **_permitted_services() const
{
static char const *permitted_services[] = {
"CAP", "RM", "LOG", "SIGNAL", "Timer", "PCI",
"IO_MEM", "IO_PORT", "IRQ", 0 };
return permitted_services;
};
public:
Ipxe_policy(Genode::Rpc_entrypoint &entrypoint)
:
Slave_policy("nic_drv", entrypoint),
_announced(false),
_lock(Genode::Lock::LOCKED)
{ }
bool announce_service(const char *service_name,
Genode::Root_capability root,
Genode::Allocator *alloc,
Genode::Server *server)
{
if (Genode::strcmp(service_name, "Nic"))
return false;
_cap = root;
return true;
}
/**
* Nic::Provider interface
*/
Genode::Root_capability root() { return _cap; }
};
struct Ps2_policy : public Genode::Slave_policy
{
private:
Input::Source_registry &_input_source_registry;
Input::Source _input_source_registry_entry;
protected:
char const **_permitted_services() const
{
static char const *allowed_services[] = {
"CAP", "RM", "IO_PORT", "IRQ", "LOG", 0 };
return allowed_services;
};
public:
Ps2_policy(Genode::Rpc_entrypoint &entrypoint,
Input::Source_registry &input_source_registry)
:
Genode::Slave_policy("ps2_drv", entrypoint),
_input_source_registry(input_source_registry)
{ }
bool announce_service(const char *service_name,
Genode::Root_capability root,
Genode::Allocator *alloc,
Genode::Server *server)
{
if (Genode::strcmp(service_name, "Input"))
return false;
_input_source_registry_entry.connect(root);
_input_source_registry.add_source(&_input_source_registry_entry);
return true;
}
};
struct Usb_policy : public Genode::Slave_policy
{
private:
Input::Source_registry &_input_source_registry;
Input::Source _input_source_registry_entry;
Block::Driver_registry &_block_driver_registry;
Block::Driver _block_driver;
protected:
const char **_permitted_services() const
{
static const char *permitted_services[] = {
"CAP", "RM", "IO_PORT", "IO_MEM", "IRQ", "LOG", "PCI",
"Timer", "SIGNAL", 0 };
return permitted_services;
};
public:
Support for dynamic ROM sessions, fix #170 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'.
2012-04-04 17:07:19 +02:00
Usb_policy(Genode::Rpc_entrypoint &entrypoint,
Input::Source_registry &input_source_registry,
Block::Driver_registry &block_driver_registry,
Genode::Ram_session *ram,
char const *config)
:
Support for dynamic ROM sessions, fix #170 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'.
2012-04-04 17:07:19 +02:00
Genode::Slave_policy("usb_drv", entrypoint, ram),
_input_source_registry(input_source_registry),
_block_driver_registry(block_driver_registry)
Support for dynamic ROM sessions, fix #170 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'.
2012-04-04 17:07:19 +02:00
{
configure(config);
}
bool announce_service(const char *service_name,
Genode::Root_capability root,
Genode::Allocator *alloc,
Genode::Server *server)
{
if (Genode::strcmp(service_name, "Input") == 0) {
_input_source_registry_entry.connect(root);
_input_source_registry.add_source(&_input_source_registry_entry);
return true;
}
if (Genode::strcmp(service_name, "Block") == 0) {
_block_driver.init("usb_drv", root);
_block_driver_registry.add_driver(&_block_driver);
return true;
}
return false;
}
};
class Atapi_policy : public Genode::Slave_policy
{
private:
Block::Driver_registry &_block_driver_registry;
Block::Driver _block_driver;
protected:
const char **_permitted_services() const
{
static const char *permitted_services[] = {
"CAP", "RM", "LOG", "SIGNAL", "Timer", "PCI", "IO_MEM",
"IO_PORT", "IRQ", 0 };
return permitted_services;
};
public:
Atapi_policy(Genode::Rpc_entrypoint &entrypoint,
Block::Driver_registry &block_driver_registry)
:
Genode::Slave_policy("atapi_drv", entrypoint),
_block_driver_registry(block_driver_registry) { }
bool announce_service(char const *service_name,
Genode::Root_capability root,
Genode::Allocator *alloc,
Genode::Server *server)
{
if (Genode::strcmp(service_name, "Block"))
return false;
_block_driver.init(name(), root);
_block_driver_registry.add_driver(&_block_driver);
return true;
}
};
int main(int argc, char **argv)
{
using namespace Genode;
enum { STACK_SIZE = 2*4096 };
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "d3m_ep");
/*
* Registry of input-event sources
*
* Upon startup of the USB HID and PS/2 drivers, this registry gets
* populated when each of the drivers announces its respective 'Input'
* service.
*/
static Input::Source_registry input_source_registry;
/*
* Registry for boot block device
*/
static Block::Driver_registry block_driver_registry;
/* create PS/2 driver */
static Rpc_entrypoint ps2_ep(&cap, STACK_SIZE, "ps2_slave");
static Ps2_policy ps2_policy(ps2_ep, input_source_registry);
static Genode::Slave ps2_slave(ps2_ep, ps2_policy, 512*1024);
/* create USB driver */
Support for dynamic ROM sessions, fix #170 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'.
2012-04-04 17:07:19 +02:00
char const *config = "<config><hid/><storage/></config>";
static Rpc_entrypoint usb_ep(&cap, STACK_SIZE, "usb_slave");
static Usb_policy usb_policy(usb_ep, input_source_registry,
Support for dynamic ROM sessions, fix #170 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'.
2012-04-04 17:07:19 +02:00
block_driver_registry, env()->ram_session(),
config);
2012-01-30 23:55:54 +01:00
static Genode::Slave usb_slave(usb_ep, usb_policy, 3*1024*1024);
/* create ATAPI driver */
static Rpc_entrypoint atapi_ep(&cap, STACK_SIZE, "atapi_slave");
static Atapi_policy atapi_policy(atapi_ep, block_driver_registry);
static Genode::Slave atapi_slave(atapi_ep, atapi_policy, 1024*1024);
/* initialize input service */
static Input::Root input_root(&ep, env()->heap(), input_source_registry);
env()->parent()->announce(ep.manage(&input_root));
/*
* Always announce 'Nic' service, throw 'Unavailable' during session
* request if no appropriate driver could be found.
*/
static Rpc_entrypoint nic_ep(&cap, STACK_SIZE, "nic_slave");
static Ipxe_policy nic_policy(nic_ep);
static Genode::Slave nic_slave(nic_ep, nic_policy, 2048 * 1024);
static Nic::Root nic_root(nic_policy);
env()->parent()->announce(ep.manage(&nic_root));
/*
* Announce 'Block' service
*
* We use a distinct entrypoint for the block driver because otherwise, a
* long-taking block session request may defer other session requests
* (i.e., input session). By using a different entrypoint, the GUI can
* start even if the boot-device probing failed completely.
*/
{
static Rpc_entrypoint ep(&cap, STACK_SIZE, "d3m_block_ep");
static Block::Root block_root(block_driver_registry);
env()->parent()->announce(ep.manage(&block_root));
}
Genode::sleep_forever();
return 0;
}