new server 'rom_fallback'
Forwards a ROM ssesion request to a list of label prefixes. Fixes #26
This commit is contained in:
committed by
Norman Feske
parent
1e0fa7571c
commit
3af80e2d88
92
run/rom_fallback.run
Normal file
92
run/rom_fallback.run
Normal file
@@ -0,0 +1,92 @@
|
||||
#
|
||||
# \brief Test of 'rom_fallback' server
|
||||
# \author Emery Hemingway
|
||||
# \date 2016-07-21
|
||||
#
|
||||
|
||||
|
||||
set build_components {
|
||||
core init
|
||||
drivers/timer
|
||||
server/rom_fallback
|
||||
server/report_rom
|
||||
test/libc
|
||||
}
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
append config {
|
||||
<config verbose="yes">
|
||||
<parent-provides>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="PD"/>
|
||||
<service name="RAM"/>
|
||||
<service name="RM"/>
|
||||
<service name="ROM"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service>
|
||||
<child name="rom_fallback"/>
|
||||
<parent/> <any-child/>
|
||||
</any-service>
|
||||
</default-route>
|
||||
|
||||
<start name="report_rom">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="ROM"/> </provides>
|
||||
<config/>
|
||||
<route> <any-service> <parent/> </any-service> </route>
|
||||
</start>
|
||||
|
||||
<start name="rom_fallback">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="ROM"/> </provides>
|
||||
<config>
|
||||
<fallback label="report"/>
|
||||
<fallback/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="ROM" label_prefix="report ->">
|
||||
<child name="report_rom"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Timer"/> </provides>
|
||||
</start>
|
||||
|
||||
<start name="test-libc">
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<config>
|
||||
<libc stdout="/log" stderr="log">
|
||||
<vfs> <log/> </vfs>
|
||||
</libc>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
</config>
|
||||
}
|
||||
|
||||
install_config $config
|
||||
|
||||
# generic modules
|
||||
set boot_modules {
|
||||
core init ld.lib.so
|
||||
libc.lib.so
|
||||
libm.lib.so
|
||||
report_rom
|
||||
rom_fallback
|
||||
test-libc
|
||||
timer
|
||||
}
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args " -nographic"
|
||||
|
||||
run_genode_until {child "test-libc" exited with exit value 0} 60
|
||||
17
src/server/rom_fallback/README
Normal file
17
src/server/rom_fallback/README
Normal file
@@ -0,0 +1,17 @@
|
||||
Rom_fallback serves ROM sessions by opening sessions at its parent
|
||||
using a list of labels, returning the first successfully opened sessions.
|
||||
|
||||
In the following configuration example an attempt is made to forwarded a
|
||||
session from the parent before the sibling 'fs_rom'.
|
||||
! <start name="rom_fallback">
|
||||
! <.../>
|
||||
! <config>
|
||||
! <fallback/>
|
||||
! <fallback label="fs"/>
|
||||
! </config>
|
||||
! <route>
|
||||
! <service name="ROM" label_prefix="fs ->">
|
||||
! <child name="fs_rom"/> </service>
|
||||
! <any-service> <parent/> </any-service>
|
||||
! </route>
|
||||
! </start>
|
||||
144
src/server/rom_fallback/component.cc
Normal file
144
src/server/rom_fallback/component.cc
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* \brief Service fallback server
|
||||
* \author Emery Hemingway
|
||||
* \date 2016-07-21
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016 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/attached_rom_dataspace.h>
|
||||
#include <rom_session/capability.h>
|
||||
#include <base/service.h>
|
||||
#include <base/heap.h>
|
||||
#include <base/session_label.h>
|
||||
#include <base/component.h>
|
||||
|
||||
namespace Rom_fallback {
|
||||
using namespace Genode;
|
||||
struct Main;
|
||||
}
|
||||
|
||||
struct Rom_fallback::Main : Rpc_object<Typed_root<Rom_session>>
|
||||
{
|
||||
struct Fallback_label;
|
||||
typedef List<Fallback_label> Fallback_labels;
|
||||
|
||||
struct Fallback_label : Session_label, Fallback_labels::Element
|
||||
{
|
||||
using Session_label::Session_label;
|
||||
};
|
||||
|
||||
Fallback_labels fallbacks;
|
||||
|
||||
Env &env;
|
||||
|
||||
Attached_rom_dataspace config_rom { env, "config" };
|
||||
|
||||
Heap heap { env.ram(), env.rm() };
|
||||
Slab slab { sizeof(Fallback_label), 4096, &heap };
|
||||
|
||||
Parent_service parent_service { "ROM" };
|
||||
|
||||
void load_config()
|
||||
{
|
||||
while (Fallback_label *f = fallbacks.first()) {
|
||||
fallbacks.remove(f);
|
||||
destroy(slab, f);
|
||||
}
|
||||
|
||||
/* keep a pointer to last element of the list for inserting */
|
||||
Fallback_label *last = nullptr;
|
||||
config_rom.xml().for_each_sub_node("fallback", [&] (Xml_node node) {
|
||||
typedef String<Session_label::capacity()> Label;
|
||||
|
||||
Fallback_label *fallback = new (slab)
|
||||
Fallback_label(node.attribute_value("label", Label()).string());
|
||||
fallbacks.insert(fallback, last);
|
||||
last = fallback;
|
||||
});
|
||||
}
|
||||
|
||||
void update_config()
|
||||
{
|
||||
config_rom.update();
|
||||
load_config();
|
||||
}
|
||||
|
||||
Genode::Signal_handler<Main> update_handler
|
||||
{ env.ep(), *this, &Main::update_config };
|
||||
|
||||
Main(Genode::Env &env) : env(env)
|
||||
{
|
||||
config_rom.sigh(update_handler);
|
||||
load_config();
|
||||
|
||||
env.parent().announce(env.ep().manage(*this));
|
||||
}
|
||||
|
||||
|
||||
/****************************
|
||||
** Root session interface **
|
||||
****************************/
|
||||
|
||||
Session_capability session(Session_args const &args,
|
||||
Affinity const &affinity) override
|
||||
{
|
||||
Session_label const original = label_from_args(args.string());
|
||||
|
||||
enum { ARGS_MAX_LEN = 256 };
|
||||
char new_args[ARGS_MAX_LEN];
|
||||
|
||||
for (Fallback_label *f = fallbacks.first(); f; f = f->next()) {
|
||||
Session_label &prefix = *f;
|
||||
|
||||
/* create new label */
|
||||
Session_label const new_label = prefix == "" ?
|
||||
original : prefixed_label(prefix, original);
|
||||
|
||||
/* create a new argument set */
|
||||
strncpy(new_args, args.string(), sizeof(new_args));
|
||||
Arg_string::set_arg_string(new_args, sizeof(new_args), "label",
|
||||
new_label.string());
|
||||
|
||||
/* try this service */
|
||||
try { return parent_service.session(new_args, affinity); }
|
||||
|
||||
catch (Parent::Service_denied) {
|
||||
warning("'", new_label, "' was denied"); }
|
||||
|
||||
catch (Service::Unavailable) {
|
||||
warning("'", new_label, "' is unavailable"); }
|
||||
|
||||
catch (Service::Invalid_args) {
|
||||
warning("'", new_label, "' received invalid args"); }
|
||||
|
||||
catch (Service::Quota_exceeded) {
|
||||
warning("'", new_label, "' quota donation was insufficient"); }
|
||||
}
|
||||
|
||||
error("no service found for ROM '", original.string(), "'");
|
||||
throw Root::Unavailable();
|
||||
}
|
||||
|
||||
void upgrade(Session_capability, Upgrade_args const &args) override
|
||||
{
|
||||
warning("discarding rom upgrade '", args.string(), "'");
|
||||
}
|
||||
|
||||
void close(Session_capability session) override
|
||||
{
|
||||
parent_service.close(session);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void Component::construct(Genode::Env &env)
|
||||
{
|
||||
static Rom_fallback::Main inst(env);
|
||||
}
|
||||
3
src/server/rom_fallback/target.mk
Normal file
3
src/server/rom_fallback/target.mk
Normal file
@@ -0,0 +1,3 @@
|
||||
TARGET = rom_fallback
|
||||
SRC_CC = component.cc
|
||||
LIBS = base
|
||||
Reference in New Issue
Block a user