153 lines
3.5 KiB
C++
153 lines
3.5 KiB
C++
/*
|
|
* \brief ROM service
|
|
* \author Norman Feske
|
|
* \date 2014-01-11
|
|
*/
|
|
|
|
/*
|
|
* Copyright (C) 2014 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_SERVICE_H_
|
|
#define _ROM_SERVICE_H_
|
|
|
|
/* Genode includes */
|
|
#include <util/arg_string.h>
|
|
#include <util/xml_node.h>
|
|
#include <rom_session/rom_session.h>
|
|
#include <root/component.h>
|
|
|
|
/* local includes */
|
|
#include <rom_registry.h>
|
|
|
|
namespace Rom {
|
|
class Session_component;
|
|
class Root;
|
|
|
|
using Genode::Xml_node;
|
|
}
|
|
|
|
|
|
class Rom::Session_component : public Genode::Rpc_object<Genode::Rom_session>,
|
|
public Reader
|
|
{
|
|
private:
|
|
|
|
Registry_for_reader &_registry;
|
|
Module const &_module;
|
|
|
|
Lazy_volatile_object<Genode::Attached_ram_dataspace> _ds;
|
|
|
|
Genode::Signal_context_capability _sigh;
|
|
|
|
public:
|
|
|
|
Session_component(Registry_for_reader ®istry,
|
|
Rom::Module::Name const &name)
|
|
:
|
|
_registry(registry), _module(_registry.lookup(*this, name))
|
|
{ }
|
|
|
|
~Session_component()
|
|
{
|
|
_registry.release(*this, _module);
|
|
}
|
|
|
|
Genode::Rom_dataspace_capability dataspace() override
|
|
{
|
|
using namespace Genode;
|
|
|
|
/* replace dataspace by new one */
|
|
/* XXX we could keep the old dataspace if the size fits */
|
|
_ds.construct(env()->ram_session(), _module.size());
|
|
|
|
/* fill dataspace content with report contained in module */
|
|
_module.read_content(_ds->local_addr<char>(), _ds->size());
|
|
|
|
/* cast RAM into ROM dataspace capability */
|
|
Dataspace_capability ds_cap = static_cap_cast<Dataspace>(_ds->cap());
|
|
|
|
return static_cap_cast<Rom_dataspace>(ds_cap);
|
|
}
|
|
|
|
void sigh(Genode::Signal_context_capability sigh) override
|
|
{
|
|
_sigh = sigh;
|
|
}
|
|
|
|
/**
|
|
* Implementation of 'Reader' interface
|
|
*/
|
|
void notify_module_changed() const override
|
|
{
|
|
if (_sigh.valid())
|
|
Genode::Signal_transmitter(_sigh).submit();
|
|
}
|
|
};
|
|
|
|
|
|
class Rom::Root : public Genode::Root_component<Session_component>
|
|
{
|
|
private:
|
|
|
|
Registry_for_reader &_registry;
|
|
Xml_node const &_config;
|
|
|
|
typedef Rom::Module::Name Label;
|
|
|
|
/**
|
|
* Determine module name for label according to the configured policy
|
|
*/
|
|
Rom::Module::Name _module_name(Label const &label) const
|
|
{
|
|
try {
|
|
for (Xml_node node = _config.sub_node("policy");
|
|
true; node = node.next("policy")) {
|
|
|
|
if (!node.has_attribute("label")
|
|
|| !node.has_attribute("report")
|
|
|| !node.attribute("label").has_value(label.string()))
|
|
continue;
|
|
|
|
char report[Rom::Module::Name::capacity()];
|
|
node.attribute("report").value(report, sizeof(report));
|
|
return Rom::Module::Name(report);
|
|
}
|
|
} catch (Xml_node::Nonexistent_sub_node) { }
|
|
|
|
PWRN("no valid policy for label \"%s\"", label.string());
|
|
throw Root::Invalid_args();
|
|
}
|
|
|
|
protected:
|
|
|
|
Session_component *_create_session(const char *args) override
|
|
{
|
|
using namespace Genode;
|
|
|
|
/* read label of ROM module from args */
|
|
char label[Label::capacity()];
|
|
Arg_string::find_arg(args, "label").string(label, sizeof(label), "");
|
|
|
|
return new (md_alloc())
|
|
Session_component(_registry, _module_name(Label(label)));
|
|
}
|
|
|
|
public:
|
|
|
|
Root(Server::Entrypoint &ep,
|
|
Genode::Allocator &md_alloc,
|
|
Registry_for_reader ®istry,
|
|
Xml_node const &config)
|
|
:
|
|
Genode::Root_component<Session_component>(&ep.rpc_ep(), &md_alloc),
|
|
_registry(registry),
|
|
_config(config)
|
|
{ }
|
|
};
|
|
|
|
#endif /* _ROM_SERVICE_H_ */
|