Re-implementation of the loader service, ref #187

The original loader service was primarily motivated by the
browser-plugin scenario presented on our live CD. The new version
implements a more general session interface, which widens the
application scope of the service and, at the same time, reduces its
implementation complexity.

The complexity reduction is achieved by removing the original limitation
of supplying the new sub system as a single binary blob only. The server
used to implement heuristics and functionality for dealing with
different kinds of blobs such as ELF images or TAR archives. This has
been replaced by a session-local ROM service, which can be equipped with
an arbitrary number of ROM modules supplied by the loader client prior
starting the new sub system. Even though the TAR support has been
removed, a separate instance of the 'tar_rom' service can be used within
the subsystem to provide the formerly built-in functionality.
This commit is contained in:
Norman Feske 2012-04-17 18:46:14 +02:00
parent e9814e0692
commit bcf6714eff
32 changed files with 1474 additions and 1767 deletions

View File

@ -21,35 +21,34 @@
namespace Loader {
struct Session_client : Genode::Rpc_client<Session>
struct Session_client : Rpc_client<Session>
{
Session_client(Loader::Session_capability session)
: Genode::Rpc_client<Session>(session) { }
explicit Session_client(Loader::Session_capability session)
: Rpc_client<Session>(session) { }
Dataspace_capability alloc_rom_module(Name const &name, size_t size) {
return call<Rpc_alloc_rom_module>(name, size); }
/******************************
** Loader-session interface **
******************************/
void commit_rom_module(Name const &name) {
call<Rpc_commit_rom_module>(name); }
Genode::Dataspace_capability dataspace() {
return call<Rpc_dataspace>(); }
void ram_quota(size_t quantum) {
call<Rpc_ram_quota>(quantum); }
void start(Start_args const &args,
int max_width, int max_height,
Genode::Alarm::Time timeout,
Name const &name = "")
{
call<Rpc_start>(args, max_width, max_height, timeout, name);
}
void constrain_geometry(int width, int height) {
call<Rpc_constrain_geometry>(width, height); }
Nitpicker::View_capability view(int *w, int *h, int *buf_x, int *buf_y)
{
int dummy = 0;
return call<Rpc_view>(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<Rpc_view_ready_sigh>(sigh); }
void start(Name const &binary, Name const &label = "") {
call<Rpc_start>(binary, label); }
Nitpicker::View_capability view() {
return call<Rpc_view>(); }
View_geometry view_geometry() {
return call<Rpc_view_geometry>(); }
};
}

View File

@ -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>, 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>(session(args)),
Genode::Connection<Session>(session("ram_quota=%zd", ram_quota)),
Session_client(cap())
{ }
};

View File

@ -1,6 +1,7 @@
/*
* \brief Loader session interface
* \author Christian Prochaska
* \author Norman Feske
* \date 2009-10-05
*/
@ -18,56 +19,131 @@
#include <base/rpc_args.h>
#include <dataspace/capability.h>
#include <nitpicker_view/capability.h>
#include <rom_session/connection.h>
#include <os/alarm.h>
#include <base/signal.h>
#include <session/session.h>
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);
};
}

View File

@ -0,0 +1,42 @@
build "core init drivers/timer server/loader test/dynamic_config"
create_boot_directory
install_config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="CPU"/>
<service name="RM"/>
<service name="CAP"/>
<service name="PD"/>
<service name="IRQ"/>
<service name="IO_PORT"/>
<service name="SIGNAL"/>
<service name="LOG"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="loader">
<resource name="RAM" quantum="1M"/>
<provides><service name="Loader"/></provides>
</start>
<start name="test-dynamic_config_loader">
<resource name="RAM" quantum="10M"/>
</start>
</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"

111
os/run/loader.run Normal file
View File

@ -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 {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>}
append_if [have_spec sdl] config {
<start name="fb_sdl">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="Input"/>
<service name="Framebuffer"/>
</provides>
</start>}
append_if [have_spec pci] config {
<start name="pci_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="PCI"/></provides>
</start>}
append_if [have_spec vesa] config {
<start name="vesa_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="Framebuffer"/></provides>
</start>}
append_if [have_spec pl11x] config {
<start name="pl11x_drv">
<resource name="RAM" quantum="2M"/>
<provides><service name="Framebuffer"/></provides>
</start>}
append_if [have_spec ps2] config {
<start name="ps2_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="Input"/></provides>
</start> }
append config {
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="nitpicker">
<resource name="RAM" quantum="1M"/>
<provides><service name="Nitpicker"/></provides>
</start>
<start name="loader">
<resource name="RAM" quantum="1M"/>
<provides><service name="Loader"/></provides>
</start>
<start name="test-loader">
<resource name="RAM" quantum="1G"/>
</start>
</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

View File

@ -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.

View File

@ -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 <base/child.h>
#include <util/arg_string.h>
#include <init/child_policy.h>
#include <ram_session/connection.h>
#include <cpu_session/connection.h>
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<Rom_session>(_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_ */

View File

@ -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 <base/rpc_server.h>
#include <input/event.h>
#include <input/keycodes.h>
#include <input_session/client.h>
namespace Input {
using namespace Genode;
struct Transformer
{
struct Delta { int const x, y; };
virtual Delta delta() = 0;
};
class Session_component : public Rpc_object<Session>
{
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_ */

View File

@ -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 <root/component.h>
#include <nitpicker_session_component.h>
#include <input_session_component.h>
namespace Input {
class Root : public Genode::Root_component<Session_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_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_ */

View File

@ -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 <base/env.h>
#include <base/printf.h>
#include <dataspace/client.h>
#include <input/keycodes.h>
#include <input_session/client.h>
/* local includes */
#include <nitpicker_session_component.h>
#include <input_session_component.h>
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;
}

View File

@ -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 <base/rpc_server.h>
#include <input/event.h>
#include <input_session/client.h>
#include <input_session/input_session.h>
namespace Nitpicker { class Session_component; }
namespace Input {
class Session_component : public Genode::Rpc_object<Session>
{
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_ */

View File

@ -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 <base/child.h>
#include <base/service.h>
#include <util/arg_string.h>
#include <init/child_policy.h>
#include <os/timed_semaphore.h>
/* local includes */
#include <nitpicker_root.h>
#include <rom_root.h>
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_ */

View File

@ -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 <root/component.h>
#include <util/arg_string.h>
/* local includes */
#include <loader_session_component.h>
namespace Loader {
class Root : public Genode::Root_component<Loader::Session_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<Loader::Session_component>(session_ep, md_alloc) { }
};
}
#endif /* _LOADER_ROOT_H_ */

View File

@ -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 <base/printf.h>
#include <root/root.h>
#include <dataspace/client.h>
/* local includes */
#include <loader_session_component.h>
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<Ram_dataspace>(_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);
}

View File

@ -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 <loader_session/loader_session.h>
#include <rom_session/connection.h>
#include <ram_session/connection.h>
#include <cpu_session/connection.h>
#include <cap_session/connection.h>
#include <nitpicker_view/capability.h>
#include <base/rpc_server.h>
/* local includes */
#include <tar_server_child.h>
#include <loader_child.h>
namespace Loader {
class Session_component : public Genode::Rpc_object<Session>
{
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_ */

View File

@ -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 <nitpicker_view/capability.h>
#include <nitpicker_view/client.h>
#include <nitpicker_view/nitpicker_view.h>
#include <base/rpc_server.h>
#include <base/env.h>
namespace Nitpicker {
class Loader_view_component : public Genode::Rpc_object<View>
{
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_ */

View File

@ -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 <base/env.h>
#include <base/rpc_server.h>
#include <base/signal.h>
#include <base/sleep.h>
#include <loader_session/loader_session.h>
#include <cap_session/connection.h>
#include <nitpicker_view/capability.h>
#include <root/component.h>
/* local includes */
#include <loader_root.h>
#include <child.h>
#include <nitpicker.h>
#include <rom.h>
namespace Loader {
using namespace Genode;
class Session_component : public Rpc_object<Session>
{
private:
struct Local_rom_service : Service
{
Rpc_entrypoint &_ep;
Parent_service _parent_rom_service;
Rom_module_registry &_rom_modules;
Lock _lock;
List<Rom_session_component> _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_session_component *>(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<Session_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_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;

View File

@ -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 <util/arg_string.h>
#include <util/misc_math.h>
#include <base/signal.h>
#include <nitpicker_session/connection.h>
#include <nitpicker_session/nitpicker_session.h>
#include <nitpicker_view/client.h>
/* local includes */
#include <input.h>
namespace Nitpicker {
using namespace Genode;
/**
* View interface provided to the loader client
*/
class Loader_view_component : public Rpc_object<View>
{
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<View>
{
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<Session>,
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_ */

View File

@ -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 <root/component.h>
/* local includes */
#include <nitpicker_session_component.h>
namespace Nitpicker {
/**
* Shortcut for single-client root component
*/
typedef Genode::Root_component<Session_component, Genode::Single_client> 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_ */

View File

@ -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 <nitpicker_session_component.h>
#include <input_root.h>
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::Session>(_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;
}

View File

@ -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 <nitpicker_session/connection.h>
#include <nitpicker_session/nitpicker_session.h>
#include <nitpicker_view/capability.h>
#include <os/timed_semaphore.h>
/* local includes */
#include <input_root.h>
#include <loader_view_component.h>
#include <nitpicker_view_component.h>
namespace Nitpicker {
class Session_component : public Genode::Rpc_object<Session>
{
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_ */

View File

@ -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 <nitpicker_view/capability.h>
#include <nitpicker_view/client.h>
#include <base/rpc_server.h>
#include <base/env.h>
#include <os/timed_semaphore.h>
namespace Nitpicker {
class View_component : public Genode::Rpc_object<View>
{
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_ */

244
os/src/server/loader/rom.h Normal file
View File

@ -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 <util/string.h>
#include <rom_session/rom_session.h>
#include <base/rpc_server.h>
#include <os/attached_ram_dataspace.h>
namespace Genode {
class Rom_module : public List<Rom_module>::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<Rom_dataspace>(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<Rom_module> _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<Rom_session>,
public List<Rom_session_component>::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_ */

View File

@ -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 <root/component.h>
/* local includes */
#include "rom_session_component.h"
class Rom_root : public Genode::Root_component<Rom_session_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<Rom_session_component>(session_ep, md_alloc),
_ds_ep(ds_ep), _tar_server_root(tar_server_root) { }
};
#endif /* _ROM_ROOT_H_ */

View File

@ -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 <base/printf.h>
#include <base/service.h>
#include <dataspace/client.h>
#include <util/arg_string.h>
#include <rom_session/client.h>
#include <rom_session_component.h>
#include <rom_session/connection.h>
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<Rom_session>(_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);
}

View File

@ -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 <base/rpc_server.h>
#include <root/client.h>
#include <rom_session/connection.h>
class Rom_session_component : public Genode::Rpc_object<Genode::Rom_session>
{
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_ */

View File

@ -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 <base/child.h>
#include <base/service.h>
#include <init/child_policy.h>
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 = "<config><archive name=\"tar_ds\"/></config>";
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<Ram_dataspace>(_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_ */

View File

@ -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

View File

@ -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 <base/snprintf.h>
#include <base/sleep.h>
#include <timer_session/connection.h>
#include <loader_session/connection.h>
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,
"<config><counter>%d</counter></config>",
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;
}

View File

@ -0,0 +1,3 @@
TARGET = test-dynamic_config_loader
SRC_CC = main.cc
LIBS = env

View File

@ -13,52 +13,45 @@
#include <base/printf.h>
#include <base/sleep.h>
#include <dataspace/client.h>
#include <loader_session/connection.h>
#include <nitpicker_view/client.h>
#include <rom_session/connection.h>
#include <timer_session/connection.h>
#include <util/arg_string.h>
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();

View File

@ -1,3 +1,3 @@
TARGET = test-loader
SRC_CC = main.cc
LIBS = cxx env
LIBS = cxx env signal