x86: use report_rom for acpi and pci driver

Issue #1542
This commit is contained in:
Alexander Boettcher 2015-05-26 20:12:17 +02:00 committed by Christian Helmuth
parent 66e5796017
commit 1c38d4903b
21 changed files with 519 additions and 690 deletions

View File

@ -7,6 +7,7 @@ proc append_platform_drv_build_components {} {
lappend_if [have_platform_drv] build_components drivers/platform
lappend_if [have_spec acpi] build_components drivers/acpi
lappend_if [have_spec acpi] build_components server/report_rom
lappend_if [have_spec pci] build_components drivers/pci
}
@ -15,6 +16,7 @@ proc append_platform_drv_boot_modules {} {
lappend_if [have_platform_drv] boot_modules platform_drv
lappend_if [have_spec acpi] boot_modules acpi_drv
lappend_if [have_spec acpi] boot_modules report_rom
lappend_if [have_spec pci] boot_modules pci_drv
lappend_if [have_spec nova] boot_modules pci_device_pd
}
@ -37,7 +39,6 @@ proc append_platform_drv_config {} {
if {[have_platform_drv]} {
append config {
<start name="platform_drv">
<resource name="RAM" quantum="1M" />
<provides>
@ -50,41 +51,78 @@ proc append_platform_drv_config {} {
if {[have_spec acpi]} {
append config "
append config "
<start name=\"acpi_drv\" [platform_drv_priority]>"
append config {
<resource name="RAM" quantum="5M" constrain_phys="yes"/>
append config {
<resource name="RAM" quantum="2M"/>
<route>
<service name="LOG"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="Report"> <child name="acpi_report_rom"/> </service>
</route>
</start>}
append config "
<start name=\"acpi_report_rom\" [platform_drv_priority]>"
append config {
<binary name="report_rom"/>
<resource name="RAM" quantum="2M"/>
<provides>
<service name="PCI"/>
<service name="IRQ" />
<service name="ROM" />
<service name="Report" />
</provides>
<route> <any-service> <parent/> </any-service> </route>
<config>
<policy label="acpi_drv"> <pci class="ALL"/> </policy>}
append config [platform_drv_policy]
append config {
<rom> <policy label="pci_drv -> acpi" report="acpi_drv -> acpi"/> </rom>
</config>
<route>
<service name="LOG"> <parent/> </service>
<service name="SIGNAL"> <parent/> </service>
<service name="CAP"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>}
}
if {[expr ![have_spec acpi] && [have_spec pci]]} {
if {[have_spec pci]} {
append config "
append config "
<start name=\"pci_drv\" [platform_drv_priority]>"
append config {
append config {
<resource name="RAM" quantum="3M" constrain_phys="yes"/>
<provides> <service name="PCI"/> </provides>
<route> <any-service> <parent/> </any-service> </route>
<route>}
if {[have_spec acpi]} {
append config {
<service name="ROM">
<if-arg key="label" value="acpi"/> <child name="acpi_report_rom"/>
</service>}
}
append config {
<any-service> <parent/> </any-service>
</route>}
if {[have_spec acpi]} {
append config {
<config>}
append config [platform_drv_policy]
} else {
append config {
append config {
<config acpi="no">}
}
append config [platform_drv_policy]
append config {
</config>
</start>}

View File

@ -9,11 +9,10 @@ set build_components {
test/input
}
lappend_if [have_spec acpi] build_components drivers/acpi
lappend_if [have_spec pci] build_components drivers/pci
lappend_if [have_spec pci] build_components drivers/pci/device_pd
lappend_if [have_spec platform_arndale] build_components drivers/platform
lappend_if [have_spec gpio] build_components drivers/gpio
lappend_if [have_spec gpio] build_components drivers/gpio
source ${genode_dir}/repos/base/run/platform_drv.inc
append_platform_drv_build_components
build $build_components
@ -42,12 +41,6 @@ append config {
<any-service> <parent/> <any-child/> </any-service>
</default-route>}
append_if [have_spec platform_arndale] config {
<start name="platform_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="Regulator"/></provides>
</start>}
append_if [have_spec gpio] config {
<start name="gpio_drv">
<resource name="RAM" quantum="4M"/>
@ -55,33 +48,7 @@ append_if [have_spec gpio] config {
<config/>
</start>}
append_if [have_spec acpi] config {
<start name="acpi">
<resource name="RAM" quantum="8M" constrain_phys="yes"/>
<binary name="acpi_drv"/>
<provides>
<service name="PCI"/>
<service name="IRQ" />
</provides>
<config>
<policy label="acpi_drv">
<pci class="ALL"/>
</policy>
<policy label="usb_drv">
<pci class="USB"/>
</policy>
</config>
<route>
<service name="PCI"> <any-child /> </service>
<any-service> <parent/> <any-child /> </any-service>
</route>
</start>}
append_if [expr ![have_spec acpi] && [have_spec pci]] config {
<start name="pci_drv">
<resource name="RAM" quantum="5M" constrain_phys="yes"/>
<provides><service name="PCI"/></provides>
</start>}
append_platform_drv_config
append config {
<start name="timer">
@ -111,12 +78,10 @@ set boot_modules {
core init timer usb_drv test-input
}
lappend_if [have_spec acpi] boot_modules acpi_drv
lappend_if [have_spec pci] boot_modules pci_drv
lappend_if [have_spec nova] boot_modules pci_device_pd
lappend_if [have_spec platform_arndale] boot_modules platform_drv
lappend_if [have_spec gpio] boot_modules gpio_drv
append_platform_drv_boot_modules
build_boot_image $boot_modules
append qemu_args " -m 256 -usb -usbdevice mouse -usbdevice keyboard"

View File

@ -49,7 +49,7 @@ class Genode::Irq_proxy : public THREAD,
char _name[32];
Lock _startup_lock;
long _irq_number;
unsigned _irq_number;
Lock _mutex; /* protects this object */
int _num_sharers; /* number of clients sharing this IRQ */
@ -86,9 +86,9 @@ class Genode::Irq_proxy : public THREAD,
** Implementation **
********************/
const char *_construct_name(long irq_number)
const char *_construct_name(unsigned irq_number)
{
snprintf(_name, sizeof(_name), "irqproxy%02lx", irq_number);
snprintf(_name, sizeof(_name), "irqproxy%02x", irq_number);
return _name;
}
@ -128,7 +128,7 @@ class Genode::Irq_proxy : public THREAD,
public:
Irq_proxy(long irq_number)
Irq_proxy(unsigned irq_number)
:
THREAD(_construct_name(irq_number)),
_startup_lock(Lock::LOCKED), _irq_number(irq_number),
@ -186,7 +186,7 @@ class Genode::Irq_proxy : public THREAD,
s->notify();
}
long irq_number() const { return _irq_number; }
unsigned irq_number() const { return _irq_number; }
virtual bool add_sharer(Irq_sigh *s)
{
@ -217,7 +217,10 @@ class Genode::Irq_proxy : public THREAD,
}
template <typename PROXY>
static PROXY *get_irq_proxy(long irq_number, Range_allocator *irq_alloc = 0)
static PROXY *get_irq_proxy(unsigned irq_number,
Range_allocator *irq_alloc = 0,
Genode::Irq_session::Trigger trigger = Genode::Irq_session::TRIGGER_UNCHANGED,
Genode::Irq_session::Polarity polarity = Genode::Irq_session::POLARITY_UNCHANGED)
{
static List<Irq_proxy> proxies;
static Lock proxies_lock;
@ -233,7 +236,8 @@ class Genode::Irq_proxy : public THREAD,
if (!irq_alloc || irq_alloc->alloc_addr(1, irq_number).is_error())
return 0;
PROXY *new_proxy = new (env()->heap()) PROXY(irq_number);
PROXY *new_proxy = new (env()->heap()) PROXY(irq_number, trigger,
polarity);
proxies.insert(new_proxy);
return new_proxy;
}

View File

@ -2,6 +2,8 @@
# Build
#
assert_spec x86
set build_components {
core init
drivers/input
@ -46,6 +48,9 @@ append config {
<service name="RM"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="SIGNAL"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
</route>
</start>
@ -58,6 +63,8 @@ append config {
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="SIGNAL"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
<service name="PCI"> <any-child/> </service>
</route>
</start>
@ -93,6 +100,7 @@ set boot_modules {
test-input
}
# platform-specific modules
append_platform_drv_boot_modules
build_boot_image $boot_modules

View File

@ -1,6 +1,7 @@
/*
* \brief ACPI parsing and PCI rewriting code
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \author Alexander Boettcher
* \date 2012-02-25
*
* This code parses the DSDT and SSDT-ACPI tables and extracts the PCI-bridge
@ -10,15 +11,17 @@
*/
/*
* Copyright (C) 2009-2013 Genode Labs GmbH
* Copyright (C) 2009-2015 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.
*/
/* base includes */
#include <io_mem_session/connection.h>
#include <pci_session/connection.h>
#include <pci_device/client.h>
/* os includes */
#include <os/reporter.h>
#include <os/attached_rom_dataspace.h>
#include "acpi.h"
@ -165,7 +168,7 @@ class Irq_override : public List<Irq_override>::Element
return &_list;
}
bool match(uint32_t irq) const { return irq == _irq; }
uint32_t irq() const { return _irq; }
uint32_t gsi() const { return _gsi; }
uint32_t flags() const { return _flags; }
};
@ -373,8 +376,9 @@ class Pci_routing : public List<Pci_routing>::Element
/**
* Accessors
*/
uint32_t pin() const { return _pin; }
uint32_t gsi() const { return _gsi; }
uint32_t pin() const { return _pin; }
uint32_t gsi() const { return _gsi; }
uint32_t device() const { return _adr >> 16; }
/* debug */
void dump() { if (verbose) PDBG("Pci: adr %x pin %x gsi: %u", _adr, _pin, _gsi); }
@ -818,7 +822,6 @@ class Element : public List<Element>::Element
}
}
bool is_device() { return _type == SUB_DEVICE; }
bool is_device_name() { return _type == DEVICE_NAME; }
/**
@ -852,6 +855,9 @@ class Element : public List<Element>::Element
uint32_t size_len() const { return _size_len; }
uint8_t const *data() const { return _data; }
bool valid() const { return _valid; }
uint32_t bdf() const { return _bdf; }
bool is_device() const { return _type == SUB_DEVICE; }
static bool supported_acpi_format()
{
@ -996,44 +1002,6 @@ class Element : public List<Element>::Element
}
throw -1;
}
static void create_config_file(char * text, size_t max)
{
Pci_config_space *e = Pci_config_space::list()->first();
int len = snprintf(text, max, "<config>");
text += len;
max -= len;
for (; e; e = e->next())
{
using namespace Genode;
len = snprintf(text, max, "<bdf><start>%u</start>", e->_bdf_start);
text += len;
max -= len;
len = snprintf(text, max, "<count>%u</count>" , e->_func_count);
text += len;
max -= len;
len = snprintf(text, max, "<base>0x%lx</base></bdf>" , e->_base);
text += len;
max -= len;
}
Attached_rom_dataspace rom("config");
char * rom_text = rom.local_addr<char>();
size_t rom_len = strlen(rom_text);
if (max > rom_len - 9) {
rom_text += 9;
rom_len -= 9;
memcpy(text, rom_text, rom_len);
text += rom_len;
max -= rom_len;
} else
PERR("could not add pci_drv policy");
if (max < 2)
PERR("config file could not be generated, buffer to small");
}
};
@ -1215,157 +1183,6 @@ class Acpi_table
};
/**
* Pci::Device_client extensions identifies bridges and adds IRQ line re-write
*/
class Pci_client : public ::Pci::Device_client
{
public:
Pci_client(Pci::Device_capability &cap) : ::Pci::Device_client(cap) { }
/**
* Return true if this is a PCI-PCI bridge
*/
bool is_bridge()
{
enum { BRIDGE_CLASS = 0x6 };
if ((class_code() >> 16) != BRIDGE_CLASS)
return false;
/* see PCI bridge spec (3.2) */
enum { BRIDGE = 0x1 };
uint16_t header = config_read(0xe, ::Pci::Device::ACCESS_16BIT);
/* skip multi function flag 0x80) */
return ((header & 0x3f) != BRIDGE) ? false : true;
}
/**
* Return bus-device function of this device
*/
uint32_t bdf()
{
uint8_t bus, dev, func;
bus_address(&bus, &dev, &func);
return (bus << 8) | ((dev & 0x1f) << 3) | (func & 0x7);
}
/**
* Return IRQ pin
*/
uint32_t irq_pin()
{
return ((config_read(0x3c, ::Pci::Device::ACCESS_32BIT) >> 8) & 0xf);
}
/**
* Return IRQ line
*/
uint8_t irq_line()
{
return (config_read(0x3c, ::Pci::Device::ACCESS_8BIT));
}
/**
* Write line to config space
*/
void irq_line(uint32_t gsi)
{
config_write(0x3c, gsi, ::Pci::Device::ACCESS_8BIT);
}
};
/**
* List of PCI-bridge devices
*/
class Pci_bridge : public List<Pci_bridge>::Element
{
private:
/* PCI config space fields of bridge */
uint32_t _bdf;
uint32_t _secondary_bus;
uint32_t _subordinate_bus;
Pci_bridge(Pci_client &client) : _bdf(client.bdf())
{
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */
uint32_t bus = client.config_read(0x18, ::Pci::Device::ACCESS_32BIT);
_secondary_bus = (bus >> 8) & 0xff;
_subordinate_bus = (bus >> 16) & 0xff;
if (verbose)
PDBG("New bridge: bdf %x se: %u su: %u", _bdf, _secondary_bus, _subordinate_bus);
}
static List<Pci_bridge> *_list()
{
static List<Pci_bridge> list;
return &list;
}
public:
/**
* Scan PCI bus for bridges
*/
Pci_bridge(Pci::Session_capability &session)
{
Pci::Session_client pci(session);
Pci::Device_capability device_cap = pci.first_device(), prev_device_cap;
/* search for bridges */
while (device_cap.valid()) {
prev_device_cap = device_cap;
Pci_client device(device_cap);
if (device.is_bridge())
_list()->insert(new (env()->heap()) Pci_bridge(device));
device_cap = pci.next_device(device_cap);
pci.release_device(prev_device_cap);
}
}
/**
* Locate BDF of bridge belonging to given bdf
*/
static uint32_t bridge_bdf(uint32_t bdf)
{
Pci_bridge *bridge = _list()->first();
uint32_t bus = bdf >> 8;
for (; bridge; bridge = bridge->next())
if (bridge->_secondary_bus <= bus && bridge->_subordinate_bus >= bus)
return bridge->_bdf;
return 0;
}
};
/**
* Debugging
*/
static void dump_bdf(uint32_t a, uint32_t b, uint32_t pin)
{
if (verbose)
PDBG("Device bdf %02x:%02x.%u (%x) bridge %02x:%02x.%u (%x) Pin: %u",
(a >> 8), (a >> 3) & 0x1f, (a & 0x7), a,
(b >> 8), (b >> 3) & 0x1f, (b & 0x7), b, pin);
}
static void dump_rewrite(uint32_t bdf, uint8_t line, uint8_t gsi)
{
PINF("Rewriting %02x:%02x.%u IRQ: %02u -> GSI: %02u",
(bdf >> 8), (bdf >> 3) & 0x1f, (bdf & 0x7), line, gsi);
}
/**
* Parse acpi table
*/
@ -1375,73 +1192,64 @@ static void init_acpi_table()
}
/**
* Create config file for pci_drv
*/
void Acpi::create_pci_config_file(char * config_space,
Genode::size_t config_space_max)
void Acpi::generate_report()
{
init_acpi_table();
Element::create_config_file(config_space, config_space_max);
}
enum { REPORT_SIZE = 4 * 4096 };
static Reporter acpi("acpi", REPORT_SIZE);
acpi.enabled(true);
/**
* Rewrite GSIs of PCI config space
*/
void Acpi::configure_pci_devices(Pci::Session_capability &session)
{
init_acpi_table();
static Pci_bridge bridge(session);
Genode::Reporter::Xml_generator xml(acpi, [&] () {
for (Pci_config_space *e = Pci_config_space::list()->first(); e;
e = e->next())
{
xml.node("bdf", [&] () {
char number[20];
Genode::snprintf(number, sizeof(number), "%u", e->_bdf_start);
xml.attribute("start", number);
Genode::snprintf(number, sizeof(number), "%u", e->_func_count);
xml.attribute("count", number);
Genode::snprintf(number, sizeof(number), "0x%lx", e->_base);
xml.attribute("base", number);
});
}
/* if no _PIC method could be found don't rewrite */
bool acpi_rewrite = Element::supported_acpi_format();
for (Irq_override *i = Irq_override::list()->first(); i; i = i->next())
{
xml.node("irq_override", [&] () {
char number[8];
Genode::snprintf(number, sizeof(number), "%u", i->irq());
xml.attribute("irq", number);
Genode::snprintf(number, sizeof(number), "%u", i->gsi());
xml.attribute("gsi", number);
Genode::snprintf(number, sizeof(number), "0x%x", i->flags());
xml.attribute("flags", number);
});
}
if (acpi_rewrite)
PINF("ACPI table format is supported - rewrite GSIs");
else
PWRN("ACPI table format not supported - will not rewrite GSIs");
{
Element *e = Element::list()->first();
Pci::Session_client pci(session);
Pci::Device_capability device_cap = pci.first_device(), prev_device_cap;
for (; e; e = e->next()) {
if (!e->is_device())
continue;
while (device_cap.valid()) {
prev_device_cap = device_cap;
Pci_client device(device_cap);
/* rewrite IRQs */
if (acpi_rewrite && !device.is_bridge()) {
uint32_t device_bdf = device.bdf();
uint32_t bridge_bdf = Pci_bridge::bridge_bdf(device_bdf);
uint32_t irq_pin = device.irq_pin();
if (irq_pin) {
dump_bdf(device_bdf, bridge_bdf, irq_pin - 1);
try {
uint8_t gsi = Element::search_gsi(device_bdf, bridge_bdf, irq_pin - 1);
dump_rewrite(device_bdf, device.irq_line(), gsi);
device.irq_line(gsi);
} catch (...) { }
Pci_routing *r = e->pci_list()->first();
for (; r; r = r->next()) {
xml.node("routing", [&] () {
char number[8];
Genode::snprintf(number, sizeof(number), "0x%x", r->gsi());
xml.attribute("gsi", number);
Genode::snprintf(number, sizeof(number), "0x%x", e->bdf());
xml.attribute("bridge_bdf", number);
Genode::snprintf(number, sizeof(number), "0x%x", r->device());
xml.attribute("device", number);
Genode::snprintf(number, sizeof(number), "0x%x", r->pin());
xml.attribute("device_pin", number);
});
}
}
}
device_cap = pci.next_device(device_cap);
pci.release_device(prev_device_cap);
}
}
/**
* Search override structures
*/
unsigned Acpi::override(unsigned irq, unsigned *mode)
{
for (Irq_override *i = Irq_override::list()->first(); i; i = i->next())
if (i->match(irq)) {
*mode = i->flags();
return i->gsi();
}
*mode = 0;
return irq;
});
}

View File

@ -14,26 +14,12 @@
#ifndef _ACPI_H_
#define _ACPI_H_
#include <pci_session/capability.h>
namespace Acpi
{
/**
* Generate config file for pci_drv containing pointers to the
* extended PCI config space (since PCI Express)
* Generate report rom
*/
void create_pci_config_file(char * config_space,
Genode::size_t config_space_max);
/**
* Rewrite PCI-config space with GSIs found in ACPI tables.
*/
void configure_pci_devices(Pci::Session_capability &session);
/**
* Return override GSI for IRQ
*/
unsigned override(unsigned irq, unsigned *mode);
void generate_report();
}
#endif /* _ACPI_H_ */

View File

@ -2,321 +2,36 @@
* \brief Service and session interface
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-02-25
*
* The 'acpi_drv' provides the 'PCI' after rewriting the IRQ information of PCI
* devices. For this it uses the 'pci_drv' as a client and forwards the session
* capability of the 'pci_drv' afterwards
*/
/*
* Copyright (C) 2009-2013 Genode Labs GmbH
* Copyright (C) 2009-2015 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.
*/
#include <os/slave.h>
#include <base/printf.h>
#include <base/env.h>
#include <base/sleep.h>
#include <cap_session/connection.h>
#include <pci_session/client.h>
#include <irq_session/connection.h>
#include <root/component.h>
#include <os/reporter.h>
#include "acpi.h"
/**
* IRQ service
*/
namespace Irq {
typedef Genode::Rpc_object<Genode::Typed_root<Genode::Irq_session> > Irq_session;
/**
* Root interface of IRQ service
*/
class Root : public Irq_session
{
private:
Genode::Irq_session::Trigger _mode2trigger(unsigned mode)
{
enum { EDGE = 0x4, LEVEL = 0xc };
switch (mode & 0xc) {
case EDGE:
return Genode::Irq_session::TRIGGER_EDGE;
case LEVEL:
return Genode::Irq_session::TRIGGER_LEVEL;
default:
return Genode::Irq_session::TRIGGER_UNCHANGED;
}
}
Genode::Irq_session::Polarity _mode2polarity(unsigned mode)
{
using namespace Genode;
enum { HIGH = 0x1, LOW = 0x3 };
switch (mode & 0x3) {
case HIGH:
return Genode::Irq_session::POLARITY_HIGH;
case LOW:
return Genode::Irq_session::POLARITY_LOW;
default:
return Genode::Irq_session::POLARITY_UNCHANGED;
}
}
public:
/**
* Remap IRQ number and create IRQ session at parent
*/
Genode::Session_capability session(Root::Session_args const &args,
Genode::Affinity const &)
{
using namespace Genode;
if (!args.is_valid_string()) throw Root::Invalid_args();
long irq_number = Arg_string::find_arg(args.string(), "irq_number").long_value(-1);
long msi = Arg_string::find_arg(args.string(), "device_config_phys").long_value(0);
/* check for 'MADT' overrides */
unsigned mode;
long irq_legacy = Acpi::override(irq_number, &mode);
/* rewrite IRQ solely if this is not a MSI request */
if (!msi)
irq_number = irq_legacy;
/* allocate IRQ at parent*/
try {
Irq_connection irq(irq_number, _mode2trigger(mode),
_mode2polarity(mode), msi);
irq.on_destruction(Irq_connection::KEEP_OPEN);
return irq.cap();
} catch (...) { throw Root::Unavailable(); }
}
/**
* Close session at parent
*/
void close(Genode::Session_capability session) {
Genode::env()->parent()->close(session); }
void upgrade(Genode::Session_capability session, Upgrade_args const &args) { }
};
}
namespace Pci {
struct Provider
{
bool ready_to_use() { return root().valid(); }
virtual Genode::Root_capability root() = 0;
};
/**
* Root interface of PCI service
*/
class Root : public Genode::Rpc_object<Genode::Typed_root<Pci::Session> >
{
private:
Provider &_pci_provider;
Genode::Ram_session_capability _slave_ram_cap;
public:
Root(Provider &pci_provider,
Genode::Ram_session_capability ram_cap)
: _pci_provider(pci_provider), _slave_ram_cap(ram_cap) { }
Genode::Session_capability session(Session_args const &args,
Genode::Affinity const &affinity)
{
if (!args.is_valid_string()) throw Invalid_args();
if (!_pci_provider.ready_to_use())
throw Unavailable();
try {
return Genode::Root_client(_pci_provider.root())
.session(args.string(), affinity);
} catch (...) {
throw Unavailable();
}
}
void close(Genode::Session_capability session) {
Genode::Root_client(_pci_provider.root()).close(session); }
void upgrade(Genode::Session_capability s,
Upgrade_args const & args)
{
if (!s.valid() || !args.is_valid_string() ||
!_slave_ram_cap.valid())
throw Invalid_args();
using namespace Genode;
size_t ram_quota = Arg_string::find_arg(args.string(), "ram_quota").ulong_value(0);
Ram_session_client acpi_ram(env()->ram_session_cap());
if (acpi_ram.transfer_quota(_slave_ram_cap, ram_quota))
throw Invalid_args();
try { Root_client(_pci_provider.root()).upgrade(s, args); }
catch (...) {
PDBG("notification about upgrade failed");
throw Invalid_args();
}
}
};
}
static Irq::Root irq_root;
static Genode::Local_service local_irq("IRQ", &irq_root);
class Pci_policy : public Genode::Slave_policy, public Pci::Provider
{
private:
Genode::Root_capability _cap;
Genode::Rpc_entrypoint &_pci_ep;
Genode::Rpc_entrypoint &_irq_ep;
Genode::Lock _lock;
protected:
Genode::Service *resolve_session_request(const char *service_name,
const char *args) override
{
if (!Genode::strcmp(service_name, "IRQ"))
return &local_irq;
return Genode::Slave_policy::resolve_session_request(service_name,
args);
}
char const **_permitted_services() const
{
static char const *permitted_services[] = { "CPU", "CAP", "RM",
"LOG", "IO_PORT", "PD",
"ROM", "RAM", "SIGNAL",
"IO_MEM", 0 };
return permitted_services;
}
/**
* Parse ACPI tables and announce slave PCI service
*/
void _acpi_session(Genode::Ram_session_capability ram_cap)
{
Pci::Session_capability session;
const char *args = "label=\"acpi_drv\", ram_quota=16K";
try {
using namespace Genode;
session = static_cap_cast<Pci::Session>(Root_client(_cap)
.session(args, Genode::Affinity()));
} catch (...) { return; }
Acpi::configure_pci_devices(session);
/* announce PCI/IRQ services to parent */
static Pci::Root pci_root(*this, ram_cap);
Genode::env()->parent()->announce(_pci_ep.manage(&pci_root));
Genode::env()->parent()->announce(_irq_ep.manage(&irq_root));
Genode::Root_client(_cap).close(session);
}
public:
Pci_policy(Genode::Rpc_entrypoint &slave_ep,
Genode::Rpc_entrypoint &pci_ep,
Genode::Rpc_entrypoint &irq_ep)
:
Slave_policy("pci_drv", slave_ep, Genode::env()->ram_session()),
_pci_ep(pci_ep), _irq_ep(irq_ep), _lock(Genode::Lock::LOCKED)
{ }
bool announce_service(const char *service_name,
Genode::Root_capability root,
Genode::Allocator *alloc,
Genode::Server *server)
{
/* wait for 'pci_drv' to announce the PCI service */
if (Genode::strcmp(service_name, "PCI"))
return false;
_cap = root;
/* unblock main thread blocked in wait_for_pci_drv */
_lock.unlock();
return true;
}
void wait_for_pci_drv(Genode::Ram_session_capability slave_ram_cap)
{
/* wait until pci drv is ready */
_lock.lock();
/* connect session and start ACPI parsing */
_acpi_session(slave_ram_cap);
}
Genode::Root_capability root() { return _cap; }
};
int main(int argc, char **argv)
{
using namespace Genode;
enum { STACK_SIZE = 2*4096, ACPI_MEMORY_SIZE = 2 * 1024 * 1024 };
/* reserve portion for acpi and give rest to pci_drv */
Genode::addr_t avail_size = Genode::env()->ram_session()->avail();
if (avail_size < ACPI_MEMORY_SIZE) {
PERR("not enough memory");
return 1;
try {
Acpi::generate_report();
} catch (Genode::Xml_generator::Buffer_exceeded) {
PERR("ACPI report too large - failure");
throw;
} catch (...) {
PERR("Unknown exception occured - failure");
throw;
}
avail_size -= ACPI_MEMORY_SIZE;
PINF("available memory for ACPI %d kiB, for PCI_DRV %lu kiB",
ACPI_MEMORY_SIZE / 1024, avail_size / 1024);
static Cap_connection cap;
static Rpc_entrypoint ep(&cap, STACK_SIZE, "acpi_ep");
/* IRQ service */
static Cap_connection irq_cap;
static Rpc_entrypoint irq_ep(&irq_cap, STACK_SIZE, "acpi_irq_ep");
/* use 'pci_drv' as slave service */
static Rpc_entrypoint pci_ep(&cap, STACK_SIZE, "pci_slave");
static Pci_policy pci_policy(pci_ep, ep, irq_ep);
/* generate config file for pci_drv */
char buf[1024];
Acpi::create_pci_config_file(buf, sizeof(buf));
pci_policy.configure(buf);
/* use 'pci_drv' as slave service */
static Genode::Slave pci_slave(pci_ep, pci_policy, avail_size);
/* wait until pci drv is online and then make the acpi work */
pci_policy.wait_for_pci_drv(pci_slave.ram().cap());
Genode::sleep_forever();
return 0;
}

View File

@ -20,6 +20,7 @@
/* PCI driver include */
#include "irq.h"
#include "pci_session_component.h"
namespace Pci {
@ -194,10 +195,13 @@ class Pci::Irq_component : public Proxy
public:
Irq_component(unsigned gsi)
Irq_component(unsigned gsi, Genode::Irq_session::Trigger trigger,
Genode::Irq_session::Polarity polarity)
:
Proxy(gsi), _irq(gsi), _irq_dispatcher(irq_thread.sig_rec(), *this,
&::Proxy::notify_about_irq),
Proxy(gsi),
_irq(gsi, trigger, polarity),
_irq_dispatcher(irq_thread.sig_rec(), *this,
&::Proxy::notify_about_irq),
_associated(false)
{ }
};
@ -234,7 +238,7 @@ Pci::Irq_session_component::Irq_session_component(unsigned irq,
_gsi(irq)
{
/* invalid irq number for pci_devices */
if (irq >= INVALID_IRQ)
if (_gsi >= INVALID_IRQ)
return;
if (pci_config_space != ~0UL) {
@ -262,9 +266,20 @@ Pci::Irq_session_component::Irq_session_component(unsigned irq,
}
}
Genode::Irq_session::Trigger trigger;
Genode::Irq_session::Polarity polarity;
_gsi = Pci::Irq_override::irq_override(_gsi, trigger, polarity);
if (_gsi != irq || trigger != Genode::Irq_session::TRIGGER_UNCHANGED ||
polarity != Genode::Irq_session::POLARITY_UNCHANGED)
PINF("IRQ override %u->%u trigger mode=%s polarity=%s", irq, _gsi,
trigger == Genode::Irq_session::TRIGGER_LEVEL ? "LEVEL" : trigger == Genode::Irq_session::TRIGGER_EDGE ? "EDGE" : "UNCHANGED",
polarity == Genode::Irq_session::POLARITY_HIGH ? "HIGH" : polarity == Genode::Irq_session::POLARITY_LOW ? "LOW" : "UNCHANGED");
try {
/* check if shared IRQ object was used before */
if (Proxy::get_irq_proxy<Irq_component>(_gsi, &irq_alloc))
if (Proxy::get_irq_proxy<Irq_component>(_gsi, &irq_alloc, trigger,
polarity))
return;
} catch (Genode::Parent::Service_denied) { }
@ -319,3 +334,15 @@ void Pci::Irq_session_component::sigh(Genode::Signal_context_capability sigh)
if (!old.valid() && sigh.valid())
irq_obj->add_sharer(&_irq_sigh);
}
unsigned short Pci::Irq_routing::rewrite(unsigned char bus, unsigned char dev,
unsigned char func, unsigned char pin)
{
for (Irq_routing *i = list()->first(); i; i = i->next())
if ((dev == i->_device) && (pin - 1 == i->_device_pin) &&
(i->_bridge_bdf == Pci::bridge_bdf(bus)))
return i->_gsi;
return 0;
}

View File

@ -24,7 +24,11 @@
#include <platform/irq_proxy.h>
namespace Pci { class Irq_session_component; }
namespace Pci {
class Irq_session_component;
class Irq_override;
class Irq_routing;
}
class Pci::Irq_session_component : public Genode::Rpc_object<Genode::Irq_session>,
@ -64,3 +68,113 @@ class Pci::Irq_session_component : public Genode::Rpc_object<Genode::Irq_session
Info info() override {
return { .type = Genode::Irq_session::Info::Type::INVALID }; }
};
/**
* List that holds interrupt override information
*/
class Pci::Irq_override : public Genode::List<Pci::Irq_override>::Element
{
private:
unsigned short _irq; /* source IRQ */
unsigned short _gsi; /* target GSI */
Genode::Irq_session::Trigger _trigger; /* interrupt trigger mode */
Genode::Irq_session::Polarity _polarity; /* interrupt polarity */
Genode::Irq_session::Trigger _mode2trigger(unsigned mode)
{
enum { EDGE = 0x4, LEVEL = 0xc };
switch (mode & 0xc) {
case EDGE:
return Genode::Irq_session::TRIGGER_EDGE;
case LEVEL:
return Genode::Irq_session::TRIGGER_LEVEL;
default:
return Genode::Irq_session::TRIGGER_UNCHANGED;
}
}
Genode::Irq_session::Polarity _mode2polarity(unsigned mode)
{
using namespace Genode;
enum { HIGH = 0x1, LOW = 0x3 };
switch (mode & 0x3) {
case HIGH:
return Genode::Irq_session::POLARITY_HIGH;
case LOW:
return Genode::Irq_session::POLARITY_LOW;
default:
return Genode::Irq_session::POLARITY_UNCHANGED;
}
}
public:
Irq_override(unsigned irq, unsigned gsi, unsigned mode)
:
_irq(irq), _gsi(gsi),
_trigger(_mode2trigger(mode)), _polarity(_mode2polarity(mode))
{ }
static Genode::List<Irq_override> *list()
{
static Genode::List<Irq_override> _list;
return &_list;
}
unsigned short irq() const { return _irq; }
unsigned short gsi() const { return _gsi; }
Genode::Irq_session::Trigger trigger() const { return _trigger; }
Genode::Irq_session::Polarity polarity() const { return _polarity; }
static unsigned irq_override (unsigned irq,
Genode::Irq_session::Trigger &trigger,
Genode::Irq_session::Polarity &polarity)
{
for (Irq_override *i = list()->first(); i; i = i->next())
if (i->irq() == irq) {
trigger = i->trigger();
polarity = i->polarity();
return i->gsi();
}
trigger = Genode::Irq_session::TRIGGER_UNCHANGED;
polarity = Genode::Irq_session::POLARITY_UNCHANGED;
return irq;
}
};
/**
* List that holds interrupt rewrite information
*/
class Pci::Irq_routing : public Genode::List<Pci::Irq_routing>::Element
{
private:
unsigned short _gsi;
unsigned short _bridge_bdf;
unsigned short _device;
unsigned char _device_pin;
public:
static Genode::List<Irq_routing> *list()
{
static Genode::List<Irq_routing> _list;
return &_list;
}
Irq_routing(unsigned short gsi, unsigned short bridge_bdf,
unsigned char device, unsigned char device_pin)
:
_gsi(gsi), _bridge_bdf(bridge_bdf), _device(device),
_device_pin(device_pin)
{ }
static unsigned short rewrite(unsigned char bus, unsigned char dev,
unsigned char func, unsigned char pin);
};

View File

@ -17,6 +17,7 @@
#include <cap_session/connection.h>
#include <os/slave.h>
#include <os/attached_rom_dataspace.h>
#include "pci_session_component.h"
#include "pci_device_config.h"
@ -106,14 +107,44 @@ int main(int argc, char **argv)
*/
static Sliced_heap sliced_heap(env()->ram_session(), env()->rm_session());
/**
* If we are running with ACPI support, wait for the first report_rom
*/
bool wait_for_acpi = true;
char * report_addr = nullptr;
try {
char yesno[4];
Genode::config()->xml_node().attribute("acpi").value(yesno, sizeof(yesno));
wait_for_acpi = strcmp(yesno, "no");
} catch (...) { }
if (wait_for_acpi) {
static Attached_rom_dataspace acpi_rom("acpi");
Signal_receiver sig_rec;
Signal_context sig_ctx;
Signal_context_capability sig_cap = sig_rec.manage(&sig_ctx);
acpi_rom.sigh(sig_cap);
while (!acpi_rom.is_valid()) {
sig_rec.wait_for_signal();
acpi_rom.update();
}
report_addr = acpi_rom.local_addr<char>();
sig_rec.dissolve(&sig_ctx);
}
/*
* Let the entry point serve the PCI root interface
*/
static Pci::Root root(&ep, &sliced_heap, PCI_DEVICE_PD_RAM_QUOTA,
device_pd_root);
device_pd_root, report_addr);
env()->parent()->announce(ep.manage(&root));
sleep_forever();
Genode::sleep_forever();
return 0;
}

View File

@ -0,0 +1,56 @@
/*
* \brief PCI bridge discovery
* \author Sebastian Sumpf <sebastian.sumpf@genode-labs.com>
* \date 2012-02-25
*/
/*
* Copyright (C) 2009-2015 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.
*/
#pragma once
namespace Pci { class Bridge; }
#include <util/list.h>
/**
* List of PCI-bridge devices
*/
class Pci::Bridge : public Genode::List<Bridge>::Element
{
private:
/* PCI config space fields of bridge */
unsigned char _bus;
unsigned char _dev;
unsigned char _fun;
unsigned char _secondary_bus;
unsigned char _subordinate_bus;
public:
Bridge(unsigned char bus, unsigned char dev, unsigned char fun,
unsigned char secondary_bus, unsigned char subordinate_bus)
:
_bus(bus), _dev(dev), _fun(fun), _secondary_bus(secondary_bus),
_subordinate_bus(subordinate_bus)
{ }
bool part_of (unsigned char bus) const
{
return _secondary_bus <= bus && bus <= _subordinate_bus;
}
unsigned short bdf()
{
unsigned short bdf = _bus;
bdf = (bdf << 8) | ((_dev & 0x1f) << 3) | (_fun & 0x7);
return bdf;
}
};

View File

@ -83,11 +83,6 @@ void Pci::Device_component::config_write(unsigned char address, unsigned value,
case 0xd: /* Latency timer */
if (size == Access_size::ACCESS_8BIT)
break;
case PCI_IRQ_LINE:
/* permitted up to now solely for acpi driver */
if (address == PCI_IRQ_LINE && _rewrite_irq_line &&
size == Access_size::ACCESS_8BIT)
break;
default:
PWRN("%x:%x:%x write access to address=%x value=0x%x "
" size=0x%x got dropped", _device_config.bus_number(),

View File

@ -42,7 +42,6 @@ class Pci::Device_component : public Genode::Rpc_object<Pci::Device>,
Pci::Session_component *_session;
unsigned short _irq_line;
Irq_session_component _irq_session;
bool _rewrite_irq_line;
enum {
IO_BLOCK_SIZE = sizeof(Genode::Io_port_connection) *
@ -107,16 +106,34 @@ class Pci::Device_component : public Genode::Rpc_object<Pci::Device>,
/**
* Disable MSI if already enabled.
*/
unsigned _disable_msi(unsigned irq)
unsigned _configure_irq(unsigned irq)
{
using Genode::uint16_t;
using Genode::uint8_t;
uint8_t has_irq = _device_config.read(&_config_access, PCI_IRQ_PIN,
Pci::Device::ACCESS_8BIT);
if (!has_irq)
uint8_t pin = _device_config.read(&_config_access, PCI_IRQ_PIN,
Pci::Device::ACCESS_8BIT);
if (!pin)
return Irq_session_component::INVALID_IRQ;
/* lookup rewrite information as provided by acpi table */
uint16_t irq_r = Irq_routing::rewrite(_device_config.bus_number(),
_device_config.device_number(),
_device_config.function_number(),
pin);
if (irq_r) {
PINF("%x:%x.%x rewriting IRQ: %u -> %u",
_device_config.bus_number(),
_device_config.device_number(),
_device_config.function_number(), irq, irq_r);
if (_irq_line != irq_r)
_device_config.write(&_config_access, PCI_IRQ_LINE, irq_r,
Pci::Device::ACCESS_8BIT);
_irq_line = irq = irq_r;
}
uint16_t cap = _msi_cap();
if (!cap)
return irq;
@ -163,14 +180,13 @@ class Pci::Device_component : public Genode::Rpc_object<Pci::Device>,
Device_component(Device_config device_config, Genode::addr_t addr,
Genode::Rpc_entrypoint *ep,
Pci::Session_component * session,
bool rewrite_irq_line, bool use_msi)
bool use_msi)
:
_device_config(device_config), _config_space(addr),
_ep(ep), _session(session),
_irq_line(_device_config.read(&_config_access, PCI_IRQ_LINE,
Pci::Device::ACCESS_8BIT)),
_irq_session(_disable_msi(_irq_line), (!use_msi || !_msi_cap()) ? ~0UL : _config_space),
_rewrite_irq_line(rewrite_irq_line),
_irq_session(_configure_irq(_irq_line), (!use_msi || !_msi_cap()) ? ~0UL : _config_space),
_slab_ioport(0, &_slab_ioport_block),
_slab_iomem(0, &_slab_iomem_block)
{
@ -350,10 +366,12 @@ class Pci::Device_component : public Genode::Rpc_object<Pci::Device>,
msi_64 ? "64bit" : "32bit",
_irq_session.msi_data(), _irq_session.msi_address());
else
PINF("%x:%x.%x uses IRQ, vector 0x%x",
PINF("%x:%x.%x uses IRQ, vector 0x%x%s",
_device_config.bus_number(),
_device_config.device_number(),
_device_config.function_number(), _irq_line);
_device_config.function_number(), _irq_line,
msi_cap ? (msi_64 ? ", MSI 64bit capable" :
", MSI 32bit capable") : "");
return _irq_session.cap();
}

View File

@ -25,7 +25,6 @@
/* os */
#include <io_mem_session/connection.h>
#include <os/config.h>
#include <os/session_policy.h>
#include <pci_session/pci_session.h>
@ -36,6 +35,7 @@
namespace Pci {
bool bus_valid(int bus = 0);
unsigned short bridge_bdf(unsigned char bus);
}
namespace Pci {
@ -59,6 +59,7 @@ namespace Pci {
static Genode::Bit_array<MAX_PCI_DEVICES> bdf_in_use;
/**
* Scan PCI buses for a device
*
@ -530,8 +531,7 @@ namespace Pci {
* device and return its capability.
*/
try {
Device_component * dev = new (_device_slab) Device_component(config, config_space, _ep, this,
!Genode::strcmp(_label.string(), "acpi_drv"), msi_usage());
Device_component * dev = new (_device_slab) Device_component(config, config_space, _ep, this, msi_usage());
/* if more than one driver uses the device - warn about */
if (bdf_in_use.get(Device_config::MAX_BUSES * bus +
@ -658,35 +658,62 @@ namespace Pci {
/* Ram_session for allocation of dma capable dataspaces */
Genode::Ram_connection _ram;
void _parse_config()
void _parse_report_rom(const char * acpi_rom)
{
using namespace Genode;
/* check for config file first */
try { config(); } catch (...) { return; }
try {
Xml_node xml_acpi(acpi_rom);
if (!xml_acpi.has_type("acpi"))
throw 1;
unsigned i;
for (i = 0; i < config()->xml_node().num_sub_nodes(); i++)
for (i = 0; i < xml_acpi.num_sub_nodes(); i++)
{
Xml_node node = config()->xml_node().sub_node(i);
Xml_node node = xml_acpi.sub_node(i);
if (!node.has_type("bdf"))
continue;
if (node.has_type("bdf")) {
uint32_t bdf_start = 0;
uint32_t func_count = 0;
addr_t base = 0;
node.sub_node("start").value(&bdf_start);
node.sub_node("count").value(&func_count);
node.sub_node("base").value(&base);
uint32_t bdf_start = 0;
uint32_t func_count = 0;
addr_t base = 0;
PINF("%2u BDF start %x, functions: 0x%x, physical base "
"0x%lx", i, bdf_start, func_count, base);
node.attribute("start").value(&bdf_start);
node.attribute("count").value(&func_count);
node.attribute("base").value(&base);
Session_component::add_config_space(bdf_start,
func_count, base);
Session_component::add_config_space(bdf_start,
func_count,
base);
}
if (node.has_type("irq_override")) {
unsigned irq = 0xff;
unsigned gsi = 0xff;
unsigned flags = 0xff;
node.attribute("irq").value(&irq);
node.attribute("gsi").value(&gsi);
node.attribute("flags").value(&flags);
using Pci::Irq_override;
Irq_override::list()->insert(new (env()->heap()) Irq_override(irq, gsi, flags));
}
if (node.has_type("routing")) {
unsigned gsi;
unsigned bridge_bdf;
unsigned device;
unsigned device_pin;
node.attribute("gsi").value(&gsi);
node.attribute("bridge_bdf").value(&bridge_bdf);
node.attribute("device").value(&device);
node.attribute("device_pin").value(&device_pin);
Irq_routing::list()->insert(new (env()->heap()) Irq_routing(gsi, bridge_bdf, device, device_pin));
}
}
} catch (...) {
PERR("PCI config space data could not be parsed.");
@ -728,7 +755,8 @@ namespace Pci {
*/
Root(Genode::Rpc_entrypoint *ep, Genode::Allocator *md_alloc,
Genode::size_t pci_device_pd_ram_quota,
Genode::Root_capability &device_pd_root)
Genode::Root_capability &device_pd_root,
const char *acpi_rom)
:
Genode::Root_component<Session_component>(ep, md_alloc),
_device_pd_root(device_pd_root),
@ -736,14 +764,15 @@ namespace Pci {
_ram("dma", 0, (device_pd_root.valid() && sizeof(void *) == 4) ?
0xc0000000UL : 0x100000000ULL)
{
_parse_config();
/* enforce initial bus scan */
bus_valid();
if (acpi_rom)
_parse_report_rom(acpi_rom);
/* associate _ram session with ram_session of process */
_ram.ref_account(Genode::env()->ram_session_cap());
Genode::env()->ram_session()->transfer_quota(_ram.cap(), 0x1000);
/* enforce initial bus scan */
bus_valid();
}
};

View File

@ -12,6 +12,27 @@
*/
#include "pci_session_component.h"
#include "pci_bridge.h"
static Genode::List<Pci::Bridge> *bridges()
{
static Genode::List<Pci::Bridge> list;
return &list;
}
unsigned short Pci::bridge_bdf(unsigned char bus)
{
for (Pci::Bridge *bridge = bridges()->first(); bridge;
bridge = bridge->next())
{
if (bridge->part_of(bus))
return bridge->bdf();
}
return 0;
}
/**
* Check if given PCI bus was found on initial scan
@ -24,7 +45,7 @@ bool Pci::bus_valid(int bus)
{
bool valid[Device_config::MAX_BUSES];
void scan_bus(Config_access &config_access, int bus = 0)
void scan_bus(Config_access &config_access, unsigned char bus = 0)
{
for (int dev = 0; dev < Device_config::MAX_DEVICES; ++dev) {
for (int fun = 0; fun < Device_config::MAX_FUNCTIONS; ++fun) {
@ -43,9 +64,15 @@ bool Pci::bus_valid(int bus)
/* scan behind bridge */
if (config.is_pci_bridge()) {
int sub_bus = config.read(&config_access,
/* PCI bridge spec 3.2.5.3, 3.2.5.4 */
unsigned char sec_bus = config.read(&config_access,
0x19, Device::ACCESS_8BIT);
scan_bus(config_access, sub_bus);
unsigned char sub_bus = config.read(&config_access,
0x20, Device::ACCESS_8BIT);
bridges()->insert(new (Genode::env()->heap()) Bridge(bus, dev, fun, sec_bus, sub_bus));
scan_bus(config_access, sec_bus);
}
}
}

View File

@ -214,6 +214,7 @@ append_if $use_wifi_driver config {
<service name="Rtc"> <any-child/> </service>
<service name="File_system"> <child name="config_fs"/> </service>
<service name="ROM"> <if-arg key="label" value="wlan_configuration" /> <child name="config_rom" /> </service>
<service name="Report"> <child name="report_rom"/> </service>
<any-service> <parent/> <any-child /> </any-service>
</route>
</start>}

View File

@ -57,7 +57,7 @@ append config {
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <any-child/> <parent/> </any-service>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
@ -67,7 +67,10 @@ append config {
append_if [have_include "power_on/qemu"] config {
<start name="uart_drv">
<resource name="RAM" quantum="1M"/>
<provides><service name="Terminal"/></provides>
<provides>
<service name="Terminal"/>
<service name="Uart"/>
</provides>
<config>
<policy label="noux" uart="1"/>
</config>

View File

@ -107,7 +107,7 @@ append config {
<service name="SIGNAL"/>
</parent-provides>
<default-route>
<any-service> <any-child/> <parent/> </any-service>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>

View File

@ -214,7 +214,8 @@ append config_of_app {
</vfs>
</libc>
</config>
<route>}
<route>
<service name="Report"> <child name="report_rom" /> </service>}
append_if [expr $use_ram_fs] config_of_app {
<service name="File_system">

View File

@ -86,6 +86,7 @@ append config_of_app {
<route>
<service name="Framebuffer"> <child name="fb_drv" /> </service>
<service name="Input"> <child name="input_merger" /> </service>
<service name="Report"> <child name="report_rom" /> </service>
<any-service> <parent/> <any-child /> </any-service>
</route>
<config>
@ -156,6 +157,7 @@ append config_of_app {
<service name="File_system"> <child name="rump_fs"/> </service>
<service name="Framebuffer"> <child name="nit_fb" /> </service>
<service name="Input"> <child name="nit_fb" /> </service>
<service name="Report"><child name="report_rom" /></service>
<service name="ROM">
<if-arg key="label" value="usb_devices"/> <child name="report_rom"/>
</service>

View File

@ -124,6 +124,7 @@ append_if [expr $use_usb] config {
</config>
<route>
<service name="IRQ"><child name="acpi_drv" /></service>
<service name="Report"><child name="report_rom" /></service>
<any-service> <parent /> <any-child /></any-service>
</route>
</start>