new server 'rom_fallback'

Forwards a ROM ssesion request to a list of label prefixes.

Fixes #26
This commit is contained in:
Emery Hemingway
2016-07-21 13:44:17 +02:00
committed by Norman Feske
parent 1e0fa7571c
commit 3af80e2d88
4 changed files with 256 additions and 0 deletions

92
run/rom_fallback.run Normal file
View 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

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

View 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);
}

View File

@@ -0,0 +1,3 @@
TARGET = rom_fallback
SRC_CC = component.cc
LIBS = base