mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 02:40:08 +00:00
parent
3e8ffe179b
commit
8f0a012345
@ -21,11 +21,7 @@ namespace Genode {
|
||||
|
||||
namespace Acpica {
|
||||
|
||||
struct Wait_acpi_ready { bool enabled; };
|
||||
struct Act_as_acpi_drv { bool enabled; };
|
||||
|
||||
void init(Genode::Env &, Genode::Allocator &, Wait_acpi_ready,
|
||||
Act_as_acpi_drv);
|
||||
void init(Genode::Env &, Genode::Allocator &);
|
||||
void use_platform_drv();
|
||||
}
|
||||
|
||||
|
@ -9,47 +9,25 @@ if {
|
||||
|
||||
set build_components {
|
||||
core init timer
|
||||
drivers/ps2
|
||||
server/dynamic_rom
|
||||
server/event_filter
|
||||
server/report_rom
|
||||
drivers/platform
|
||||
server/event_dump
|
||||
app/pci_decode
|
||||
app/acpica
|
||||
app/acpi_event
|
||||
}
|
||||
|
||||
set use_acpica_as_acpi_drv 0
|
||||
|
||||
source ${genode_dir}/repos/base/run/platform_drv.inc
|
||||
|
||||
if {!$use_acpica_as_acpi_drv} {
|
||||
|
||||
# override default platform driver policy
|
||||
proc platform_drv_policy {} {
|
||||
return {
|
||||
<policy label_prefix="ps2_drv"> <device name="PS2"/> </policy>
|
||||
<policy label_prefix="acpica"> <pci class="ALL"/> </policy>}
|
||||
}
|
||||
|
||||
# add routing information
|
||||
proc platform_drv_add_routing {} {
|
||||
return {
|
||||
<service name="ROM" label="acpi_ready"> <child name="acpi_state"/> </service>}
|
||||
}
|
||||
|
||||
# override default config to react on 'acpi_ready' ROM change
|
||||
proc platform_drv_config_config {} {
|
||||
return {
|
||||
<config acpi_ready="yes">}
|
||||
}
|
||||
}
|
||||
|
||||
append_platform_drv_build_components
|
||||
|
||||
build $build_components
|
||||
|
||||
create_boot_directory
|
||||
|
||||
import_from_depot [depot_user]/src/dynamic_rom \
|
||||
[depot_user]/src/event_filter \
|
||||
[depot_user]/src/pc_usb_host_drv \
|
||||
[depot_user]/src/ps2_drv \
|
||||
[depot_user]/src/rom_filter \
|
||||
[depot_user]/src/report_rom \
|
||||
[depot_user]/src/usb_hid_drv
|
||||
|
||||
set config {
|
||||
<config>
|
||||
<parent-provides>
|
||||
@ -65,91 +43,80 @@ set config {
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<default caps="100"/>
|
||||
<start name="timer">
|
||||
|
||||
<start name="timer" caps="100">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>}
|
||||
</start>
|
||||
|
||||
append_if [expr !$use_acpica_as_acpi_drv] config {
|
||||
<start name="acpica" caps="200">
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<config ld_verbose="yes" reset="no" poweroff="no" report="yes" acpi_ready="yes">
|
||||
<start name="drivers_reports" caps="100">
|
||||
<binary name="report_rom"/>
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides>
|
||||
<service name="Report"/>
|
||||
<service name="ROM"/>
|
||||
</provides>
|
||||
<config verbose="no">
|
||||
<policy label="pci_decode -> system" report="acpi_drv -> acpi"/>
|
||||
<policy label="rom_filter -> pci_devices" report="pci_decode -> devices"/>
|
||||
<policy label="usb_hid_drv -> report" report="usb_drv -> devices"/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="acpi_drv" caps="350">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<route>
|
||||
<service name="ROM" label="system"> <child name="dynamic_rom"/> </service>
|
||||
<service name="Report"> <child name="acpi_state"/> </service>
|
||||
<service name="Report"> <child name="drivers_reports"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
</start>
|
||||
|
||||
append config {
|
||||
<start name="acpi_state">
|
||||
<binary name="report_rom"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides>
|
||||
<service name="ROM" />
|
||||
<service name="Report" />
|
||||
</provides>
|
||||
<config verbose="yes">
|
||||
<policy label="platform_drv -> acpi_ready" report="acpica -> acpi_ready"/>
|
||||
<policy label="acpi_event -> acpi_ac" report="acpica -> acpi_ac"/>
|
||||
<policy label="acpi_event -> acpi_battery" report="acpica -> acpi_battery"/>
|
||||
<policy label="acpi_event -> acpi_ec" report="acpica -> acpi_ec"/>
|
||||
<policy label="acpi_event -> acpi_fixed" report="acpica -> acpi_fixed"/>
|
||||
<policy label="acpi_event -> acpi_lid" report="acpica -> acpi_lid"/>
|
||||
<policy label="acpi_event -> acpi_hid" report="acpica -> acpi_hid"/>
|
||||
</config>
|
||||
<start name="pci_decode" caps="350">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<route>
|
||||
<any-service> <parent/> </any-service>
|
||||
<service name="ROM" label="system"> <child name="drivers_reports"/> </service>
|
||||
<service name="Report"> <child name="drivers_reports"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
</start>
|
||||
|
||||
append config {
|
||||
<start name="dynamic_rom">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides><service name="ROM"/></provides>
|
||||
<config verbose="yes">
|
||||
<rom name="system">
|
||||
<inline description="set system state to 'normal'">
|
||||
<system state="normal"/>
|
||||
</inline>
|
||||
<sleep milliseconds="5000" />
|
||||
<inline description="set system state to 'reset'">
|
||||
<system state="reset"/>
|
||||
</inline>
|
||||
<!--
|
||||
<inline description="set system state to 'poweroff'">
|
||||
<system state="poweroff"/>
|
||||
</inline>
|
||||
-->
|
||||
<sleep milliseconds="500" />
|
||||
</rom>
|
||||
</config>
|
||||
</start>}
|
||||
|
||||
append config {
|
||||
<start name="event_filter">
|
||||
<resource name="RAM" quantum="1M" />
|
||||
<provides> <service name="Event" /> </provides>
|
||||
<config>
|
||||
<output>
|
||||
<merge>
|
||||
<input name="ps2"/>
|
||||
<input name="acpi"/>
|
||||
</merge>
|
||||
<start name="rom_filter" caps="70">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="ROM"/> </provides>
|
||||
<config buffer="32K">
|
||||
<input name="devices"/>
|
||||
<input name="pci_devices"/>
|
||||
<output node="devices">
|
||||
<input name="devices" skip_toplevel="yes"/>
|
||||
<input name="pci_devices" skip_toplevel="yes"/>
|
||||
</output>
|
||||
<policy label="ps2" input="ps2"/>
|
||||
<policy label="acpi" input="acpi"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Event"> <child name="event_dump" /> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
<service name="ROM" label="pci_devices"> <child name="drivers_reports"/> </service>
|
||||
<service name="LOG"> <parent/> </service>
|
||||
<service name="PD"> <parent/> </service>
|
||||
<service name="CPU"> <parent/> </service>
|
||||
<service name="ROM"> <parent/> </service>
|
||||
</route>
|
||||
</start>}
|
||||
</start>
|
||||
|
||||
append config {
|
||||
<start name="ps2_drv">
|
||||
<start name="platform_drv" caps="400" managing_system="yes">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides>
|
||||
<service name="Platform"/>
|
||||
</provides>
|
||||
<config>
|
||||
<policy label_prefix="ps2_drv"> <device name="ps2"/> </policy>
|
||||
<policy label_prefix="usb_drv" info="yes"> <pci class="USB"/> </policy>
|
||||
<policy label_prefix="acpica"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="ROM" label="devices"> <child name="rom_filter"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="ps2_drv" caps="100">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<config verbose_keyboard="no" verbose_mouse="no" verbose_scancodes="no"/>
|
||||
<route>
|
||||
@ -160,17 +127,93 @@ append config {
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="event_dump">
|
||||
<start name="usb_drv" caps="200">
|
||||
<binary name="pc_usb_host_drv"/>
|
||||
<resource name="RAM" quantum="20M"/>
|
||||
<provides> <service name="Usb"/> </provides>
|
||||
<config bios_handoff="no">
|
||||
<report devices="yes"/>
|
||||
<policy label_prefix="usb_hid_drv" class="0x3"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Report"> <child name="drivers_reports"/> </service>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="usb_hid_drv" caps="140">
|
||||
<resource name="RAM" quantum="10M"/>
|
||||
<config use_report="yes"/>
|
||||
<route>
|
||||
<service name="ROM" label="report"> <child name="drivers_reports"/> </service>
|
||||
<service name="Event"> <child name="event_filter" label="usb"/> </service>
|
||||
<service name="Usb"> <child name="usb_drv"/> </service>
|
||||
<any-service><parent/><any-child/></any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="event_filter" caps="100">
|
||||
<resource name="RAM" quantum="1M" />
|
||||
<provides> <service name="Event" /> </provides>
|
||||
<config>
|
||||
<output>
|
||||
<merge>
|
||||
<input name="ps2"/>
|
||||
<input name="acpi"/>
|
||||
<input name="usb"/>
|
||||
</merge>
|
||||
</output>
|
||||
<policy label="ps2" input="ps2"/>
|
||||
<policy label="acpi" input="acpi"/>
|
||||
<policy label="usb" input="usb"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Event"> <child name="event_dump" /> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="event_dump" caps="100">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides> <service name="Event"/> </provides>
|
||||
<route>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
</start>
|
||||
|
||||
append config {
|
||||
<start name="acpi_event">
|
||||
<start name="acpica" caps="200">
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<config ld_verbose="yes" reset="yes" poweroff="yes" report="yes">
|
||||
</config>
|
||||
<route>
|
||||
<service name="ROM" label="system"> <child name="dynamic_rom"/> </service>
|
||||
<service name="Report"> <child name="acpi_state"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="acpi_state" caps="100">
|
||||
<binary name="report_rom"/>
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides>
|
||||
<service name="ROM" />
|
||||
<service name="Report" />
|
||||
</provides>
|
||||
<config verbose="yes">
|
||||
<policy label="acpi_event -> acpi_ac" report="acpica -> acpi_ac"/>
|
||||
<policy label="acpi_event -> acpi_battery" report="acpica -> acpi_battery"/>
|
||||
<policy label="acpi_event -> acpi_ec" report="acpica -> acpi_ec"/>
|
||||
<policy label="acpi_event -> acpi_fixed" report="acpica -> acpi_fixed"/>
|
||||
<policy label="acpi_event -> acpi_lid" report="acpica -> acpi_lid"/>
|
||||
<policy label="acpi_event -> acpi_hid" report="acpica -> acpi_hid"/>
|
||||
</config>
|
||||
<route>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="acpi_event" caps="100">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<config>
|
||||
<!-- example mapping - adapt to your target notebook !!! -->
|
||||
@ -196,42 +239,57 @@ append config {
|
||||
<service name="Event"> <child name="event_filter" label="acpi"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
</start>
|
||||
|
||||
append_platform_drv_config
|
||||
<start name="dynamic_rom" caps="100">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides><service name="ROM"/></provides>
|
||||
<config verbose="yes">
|
||||
<rom name="system">
|
||||
<inline description="set system state to 'normal'">
|
||||
<system state="normal"/>
|
||||
</inline>
|
||||
<sleep milliseconds="5000" />
|
||||
<!--
|
||||
<inline description="set system state to 'reset'">
|
||||
<system state="reset"/>
|
||||
</inline>
|
||||
<sleep milliseconds="5000" />
|
||||
<inline description="set system state to 'poweroff'">
|
||||
<system state="poweroff"/>
|
||||
</inline>
|
||||
<sleep milliseconds="500" />
|
||||
-->
|
||||
</rom>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
append config {
|
||||
</config>
|
||||
</config>
|
||||
}
|
||||
|
||||
install_config $config
|
||||
|
||||
# non PCI devices for platform_drv, e.g. ps2/pit
|
||||
file copy [select_from_repositories board/[board]/devices] [run_dir]/genode/devices
|
||||
|
||||
set boot_modules {
|
||||
core init
|
||||
ld.lib.so
|
||||
timer
|
||||
ps2_drv
|
||||
event_filter
|
||||
report_rom
|
||||
dynamic_rom
|
||||
core init ld.lib.so
|
||||
timer platform_drv pci_decode acpi_drv
|
||||
acpica
|
||||
acpi_event
|
||||
event_dump
|
||||
}
|
||||
|
||||
append_platform_drv_boot_modules
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
append qemu_args "-nographic "
|
||||
|
||||
run_genode_until {\[init -\> acpi.*SCI IRQ:.*\n} 30
|
||||
|
||||
if {![have_include "power_on/qemu"]} {
|
||||
run_genode_until {\[init -\> acpi.*SCI IRQ:.*\n} 30
|
||||
exit 0
|
||||
}
|
||||
|
||||
run_genode_until {.*PS2 uses IRQ, vector 0xc.*} 30
|
||||
|
||||
set spawn_id $qemu_spawn_id
|
||||
|
||||
sleep 1
|
||||
|
@ -27,15 +27,6 @@ changes of the 'state' attribute:
|
||||
|
||||
!<system state="something"/>
|
||||
|
||||
Additionally, if the config attributes 'acpi_ready' is set to yes, the
|
||||
application generates a reports named 'acpi_ready' and set the state to
|
||||
|
||||
!<system state="acpi_ready"/>
|
||||
|
||||
after finishing the ACPI bring up. This is used by platform_drv to finally
|
||||
announce the Platform session, so that drivers can start after acpica has
|
||||
finished.
|
||||
|
||||
If the ROM changes to 'state="reset"' the application tries to reset the
|
||||
machine immediately.
|
||||
If the ROM changes to 'state="poweroff"' the application tries to poweroff
|
||||
@ -45,22 +36,9 @@ The attempt to reset or to poweroff may fail. One reason, we have seen so far,
|
||||
is that the required resources are already owned by other components in the
|
||||
system.
|
||||
|
||||
Furthermore the ACPICA library triggers depended on the ACPI table content
|
||||
I/O operations on various PCI devices and partly re-configure it. Because of
|
||||
this a policy rule at the platform driver is required, that permits access
|
||||
to the required devices.
|
||||
|
||||
Acpica as acpi_drv replacement
|
||||
------------------------------
|
||||
|
||||
The application acpica may also be run as replacement of the original acpi_drv
|
||||
when the 'act_as_acpi_drv' attribute is set to yes:
|
||||
|
||||
! <config ... acpi_ready="yes" act_as_acpi_drv="yes"/>
|
||||
|
||||
The acpica driver will parse in this mode the ACPI tables and will generate
|
||||
the same content in the ACPI report, which is transformed by a report_rom
|
||||
service into a ACPI ROM expected initially by the platform driver.
|
||||
Furthermore the ACPICA library may trigger, dependent on the ACPI ASL code,
|
||||
various I/O port and I/O mem accesses to hardware. Accesses to PCI devices are
|
||||
ignored and dropped by this component.
|
||||
|
||||
Excerpt of important parts of the acpica configuration
|
||||
------------------------------------------------------
|
||||
@ -68,7 +46,7 @@ Excerpt of important parts of the acpica configuration
|
||||
!<start name="acpica">
|
||||
! <!-- <binary name="debug-acpica"/> -->
|
||||
! ...
|
||||
! <config reset="no" poweroff="no" report="yes" acpi_ready="yes" act_as_acpi_drv="no"/>
|
||||
! <config reset="no" poweroff="no" report="yes"/>
|
||||
! <route>
|
||||
! <service name="ROM" label="system"> <child name="..."/> </service>
|
||||
! <service name="Report"> <child name="..."/> </service>
|
||||
|
@ -1,139 +0,0 @@
|
||||
/*
|
||||
* \brief Handle PCI Root bridge
|
||||
* \author Alexander Boettcher
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
class Bridge {
|
||||
|
||||
private:
|
||||
|
||||
ACPI_HANDLE _bridge;
|
||||
|
||||
unsigned bdf_bridge(ACPI_HANDLE bridge)
|
||||
{
|
||||
/* address (high word = device, low word = function) (6.1.1) */
|
||||
unsigned bridge_adr = 0;
|
||||
/* Base bus number (6.5.5) */
|
||||
unsigned bridge_bbn = 0;
|
||||
/* Segment object located under host bridge (6.5.6) */
|
||||
unsigned bridge_seg = 0;
|
||||
|
||||
Acpica::Buffer<ACPI_OBJECT> adr;
|
||||
ACPI_STATUS res = AcpiEvaluateObjectTyped(bridge,
|
||||
ACPI_STRING("_ADR"),
|
||||
nullptr, &adr,
|
||||
ACPI_TYPE_INTEGER);
|
||||
|
||||
if (res != AE_OK) {
|
||||
Genode::error("could not detect address of bridge - ", res);
|
||||
return 0;
|
||||
} else
|
||||
bridge_adr = adr.object.Integer.Value;
|
||||
|
||||
Acpica::Buffer<ACPI_OBJECT> bbn;
|
||||
res = AcpiEvaluateObjectTyped(bridge, ACPI_STRING("_BBN"),
|
||||
nullptr, &bbn, ACPI_TYPE_INTEGER);
|
||||
if (res != AE_OK) {
|
||||
Genode::warning("_BBN missing for bridge");
|
||||
} else
|
||||
bridge_bbn = bbn.object.Integer.Value;
|
||||
|
||||
Acpica::Buffer<ACPI_OBJECT> seg;
|
||||
res = AcpiEvaluateObjectTyped(bridge, ACPI_STRING("_SEG"),
|
||||
nullptr, &seg, ACPI_TYPE_INTEGER);
|
||||
|
||||
/* according to ACPI spec assume segment 0 if method unavailable */
|
||||
if (res == AE_OK)
|
||||
bridge_seg = seg.object.Integer.Value;
|
||||
|
||||
unsigned const bridge_bdf = ((0xffffU & bridge_seg) << 16) |
|
||||
((0x00ffU & bridge_bbn) << 8) |
|
||||
(0xffU & ((bridge_adr >> 16) << 3)) |
|
||||
(bridge_adr & 0x7);
|
||||
|
||||
return bridge_bdf;
|
||||
}
|
||||
|
||||
void _gen_bridge(ACPI_HANDLE bridge, Genode::Xml_generator &xml,
|
||||
unsigned const bridge_bdf)
|
||||
{
|
||||
Acpica::Buffer<char [2 * 4096]> irqs;
|
||||
ACPI_STATUS res = AcpiGetIrqRoutingTable (bridge, &irqs);
|
||||
if (res != AE_OK) {
|
||||
Genode::error("buffer for PCI IRQ routing information to "
|
||||
"small - ", irqs.Length, " required");
|
||||
return;
|
||||
}
|
||||
|
||||
ACPI_PCI_ROUTING_TABLE *s = reinterpret_cast<ACPI_PCI_ROUTING_TABLE *>(irqs.Pointer);
|
||||
ACPI_PCI_ROUTING_TABLE *e = reinterpret_cast<ACPI_PCI_ROUTING_TABLE *>(reinterpret_cast<unsigned long>(&irqs) + irqs.Length);
|
||||
for (ACPI_PCI_ROUTING_TABLE *c = s; c < e && c->Length; ) {
|
||||
|
||||
using Genode::Hex;
|
||||
using Genode::String;
|
||||
|
||||
xml.node("routing", [&] () {
|
||||
xml.attribute("gsi", String<16>(Hex(c->SourceIndex)));
|
||||
xml.attribute("bridge_bdf", String<16>(Hex(bridge_bdf)));
|
||||
xml.attribute("device", String<16>(Hex((c->Address >> 16) & 0x1f)));
|
||||
xml.attribute("device_pin", String<16>(Hex(c->Pin)));
|
||||
});
|
||||
|
||||
c = reinterpret_cast<ACPI_PCI_ROUTING_TABLE *>(reinterpret_cast<unsigned long>(c) + c->Length);
|
||||
}
|
||||
}
|
||||
|
||||
void _sub_bridges(ACPI_HANDLE handle, Genode::Xml_generator &xml)
|
||||
{
|
||||
ACPI_STATUS res = AcpiEvaluateObject(handle, ACPI_STRING("_PRT"),
|
||||
nullptr, nullptr);
|
||||
|
||||
if (res != AE_OK)
|
||||
return;
|
||||
|
||||
/* got another bridge, generate irq routing information to xml */
|
||||
Bridge::_gen_bridge(handle, xml, bdf_bridge(handle));
|
||||
|
||||
ACPI_HANDLE child = nullptr;
|
||||
|
||||
/* lookup next bridge behind the bridge */
|
||||
while (AE_OK == (res = AcpiGetNextObject(ACPI_TYPE_DEVICE, handle,
|
||||
child, &child)))
|
||||
{
|
||||
_sub_bridges(child, xml);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Bridge(void *, ACPI_HANDLE bridge)
|
||||
:
|
||||
_bridge(bridge)
|
||||
{ }
|
||||
|
||||
static ACPI_STATUS detect(ACPI_HANDLE bridge, UINT32, void * m,
|
||||
void **return_bridge);
|
||||
|
||||
void generate(Genode::Xml_generator &xml)
|
||||
{
|
||||
unsigned const root_bridge_bdf = bdf_bridge(_bridge);
|
||||
|
||||
xml.node("root_bridge", [&] () {
|
||||
xml.attribute("bdf", Genode::String<8>(Genode::Hex(root_bridge_bdf)));
|
||||
});
|
||||
|
||||
/* irq routing information of this (pci root) bridge */
|
||||
_gen_bridge(_bridge, xml, root_bridge_bdf);
|
||||
|
||||
/* lookup all pci-to-pci bridges and add irq routing information */
|
||||
_sub_bridges(_bridge, xml);
|
||||
}
|
||||
};
|
@ -123,7 +123,7 @@ struct Acpica::Main
|
||||
void *context;
|
||||
} irq_handler;
|
||||
|
||||
void init_acpica(Acpica::Wait_acpi_ready, Acpica::Act_as_acpi_drv);
|
||||
void init_acpica();
|
||||
|
||||
Main(Genode::Env &env)
|
||||
:
|
||||
@ -134,14 +134,11 @@ struct Acpica::Main
|
||||
bool const enable_reset = config.xml().attribute_value("reset", false);
|
||||
bool const enable_poweroff = config.xml().attribute_value("poweroff", false);
|
||||
bool const enable_report = config.xml().attribute_value("report", false);
|
||||
bool const enable_ready = config.xml().attribute_value("acpi_ready", false);
|
||||
bool const act_as_acpi_drv = config.xml().attribute_value("act_as_acpi_drv", false);
|
||||
|
||||
if (enable_report)
|
||||
report = new (heap) Acpica::Reportstate(env);
|
||||
|
||||
init_acpica(Wait_acpi_ready{enable_ready},
|
||||
Act_as_acpi_drv{act_as_acpi_drv});
|
||||
init_acpica();
|
||||
|
||||
if (enable_report)
|
||||
report->enable();
|
||||
@ -162,16 +159,6 @@ struct Acpica::Main
|
||||
|
||||
sci_conn->sigh(sci_irq);
|
||||
sci_conn->ack_irq();
|
||||
|
||||
if (!enable_ready)
|
||||
return;
|
||||
|
||||
/* we are ready - signal it via changing system state */
|
||||
static Genode::Reporter _system_rom(env, "system", "acpi_ready");
|
||||
_system_rom.enabled(true);
|
||||
Genode::Reporter::Xml_generator xml(_system_rom, [&] () {
|
||||
xml.attribute("state", "acpi_ready");
|
||||
});
|
||||
}
|
||||
|
||||
void acpi_irq()
|
||||
@ -213,7 +200,6 @@ struct Acpica::Main
|
||||
#include "lid.h"
|
||||
#include "sb.h"
|
||||
#include "ec.h"
|
||||
#include "bridge.h"
|
||||
#include "fujitsu.h"
|
||||
|
||||
ACPI_STATUS init_pic_mode()
|
||||
@ -233,26 +219,10 @@ ACPI_STATUS init_pic_mode()
|
||||
&arguments, nullptr);
|
||||
}
|
||||
|
||||
ACPI_STATUS Bridge::detect(ACPI_HANDLE bridge, UINT32, void * m,
|
||||
void **return_bridge)
|
||||
|
||||
void Acpica::Main::init_acpica()
|
||||
{
|
||||
Acpica::Main * main = reinterpret_cast<Acpica::Main *>(m);
|
||||
Bridge * dev_obj = new (main->heap) Bridge(main->report, bridge);
|
||||
|
||||
if (*return_bridge == (void *)PCI_ROOT_HID_STRING)
|
||||
Genode::log("detected - bridge - PCI root bridge");
|
||||
if (*return_bridge == (void *)PCI_EXPRESS_ROOT_HID_STRING)
|
||||
Genode::log("detected - bridge - PCIE root bridge");
|
||||
|
||||
*return_bridge = dev_obj;
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
void Acpica::Main::init_acpica(Wait_acpi_ready wait_acpi_ready,
|
||||
Act_as_acpi_drv act_as_acpi_drv)
|
||||
{
|
||||
Acpica::init(env, heap, wait_acpi_ready, act_as_acpi_drv);
|
||||
Acpica::init(env, heap);
|
||||
|
||||
/* enable debugging: */
|
||||
if (false) {
|
||||
@ -428,32 +398,6 @@ void Acpica::Main::init_acpica(Wait_acpi_ready wait_acpi_ready,
|
||||
Genode::error("AcpiGetDevices (FUJ02E3) failed, status=", status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (act_as_acpi_drv.enabled) {
|
||||
/* lookup PCI root bridge */
|
||||
void * pci_bridge = (void *)PCI_ROOT_HID_STRING;
|
||||
status = AcpiGetDevices(ACPI_STRING(PCI_ROOT_HID_STRING), Bridge::detect,
|
||||
this, &pci_bridge);
|
||||
if (status != AE_OK || pci_bridge == (void *)PCI_ROOT_HID_STRING)
|
||||
pci_bridge = nullptr;
|
||||
|
||||
/* lookup PCI Express root bridge */
|
||||
void * pcie_bridge = (void *)PCI_EXPRESS_ROOT_HID_STRING;
|
||||
status = AcpiGetDevices(ACPI_STRING(PCI_EXPRESS_ROOT_HID_STRING),
|
||||
Bridge::detect, this, &pcie_bridge);
|
||||
if (status != AE_OK || pcie_bridge == (void *)PCI_EXPRESS_ROOT_HID_STRING)
|
||||
pcie_bridge = nullptr;
|
||||
|
||||
if (pcie_bridge && pci_bridge)
|
||||
Genode::log("PCI and PCIE root bridge found - using PCIE for IRQ "
|
||||
"routing information");
|
||||
|
||||
Bridge *bridge = pcie_bridge ? reinterpret_cast<Bridge *>(pcie_bridge)
|
||||
: reinterpret_cast<Bridge *>(pci_bridge);
|
||||
|
||||
/* Generate report for platform driver */
|
||||
Acpica::generate_report(env, bridge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,174 +0,0 @@
|
||||
/*
|
||||
* \brief Generate XML report
|
||||
* \author Alexander Boettcher
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2018 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#include <base/env.h>
|
||||
#include <os/reporter.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "bridge.h"
|
||||
|
||||
using namespace Acpica;
|
||||
|
||||
using Genode::Reporter;
|
||||
|
||||
extern void AcpiGenodeFreeIOMem(ACPI_PHYSICAL_ADDRESS const phys, ACPI_SIZE const size);
|
||||
|
||||
static void add_madt(ACPI_TABLE_MADT const * const madt,
|
||||
Reporter::Xml_generator &xml)
|
||||
{
|
||||
typedef ACPI_SUBTABLE_HEADER Madt_sub;
|
||||
|
||||
using Genode::String;
|
||||
|
||||
for_each_element(madt, (Madt_sub *) nullptr, [&](Madt_sub const * const s) {
|
||||
|
||||
if (s->Type != ACPI_MADT_TYPE_INTERRUPT_OVERRIDE)
|
||||
return;
|
||||
|
||||
typedef ACPI_MADT_INTERRUPT_OVERRIDE Irq;
|
||||
Irq const * const irq = reinterpret_cast<Irq const * const>(s);
|
||||
|
||||
xml.node("irq_override", [&] () {
|
||||
xml.attribute("irq", irq->SourceIrq);
|
||||
xml.attribute("gsi", irq->GlobalIrq);
|
||||
xml.attribute("flags", String<16>(Genode::Hex(irq->IntiFlags)));
|
||||
xml.attribute("bus", irq->Bus);
|
||||
});
|
||||
}, [](Madt_sub const * const s) { return s->Length; });
|
||||
}
|
||||
|
||||
static void add_mcfg(ACPI_TABLE_MCFG const * const mcfg,
|
||||
Reporter::Xml_generator &xml)
|
||||
{
|
||||
using namespace Genode;
|
||||
|
||||
typedef ACPI_MCFG_ALLOCATION Mcfg_sub;
|
||||
|
||||
for_each_element(mcfg, (Mcfg_sub *) nullptr, [&](Mcfg_sub const * const e) {
|
||||
|
||||
/* bus_count * up to 32 devices * 8 function per device * 4k */
|
||||
uint32_t const bus_count = e->EndBusNumber - e->StartBusNumber + 1;
|
||||
uint32_t const func_count = bus_count * 32 * 8;
|
||||
uint32_t const bus_start = e->StartBusNumber * 32 * 8;
|
||||
|
||||
xml.node("bdf", [&] () {
|
||||
xml.attribute("start", bus_start);
|
||||
xml.attribute("count", func_count);
|
||||
xml.attribute("base", String<24>(Hex(e->Address)));
|
||||
});
|
||||
|
||||
/* force freeing I/O mem so that platform driver can use it XXX */
|
||||
AcpiGenodeFreeIOMem(e->Address, 0x1000UL * func_count);
|
||||
|
||||
}, [](Mcfg_sub const * const e) { return sizeof(*e); });
|
||||
}
|
||||
|
||||
static void add_dmar(ACPI_TABLE_DMAR const * const dmar_table,
|
||||
Reporter::Xml_generator &xml)
|
||||
{
|
||||
using Genode::String;
|
||||
using Genode::Hex;
|
||||
|
||||
auto scope_length = [](ACPI_DMAR_DEVICE_SCOPE const * const e) {
|
||||
return e->Length; };
|
||||
|
||||
auto scope_lambda = [&](ACPI_DMAR_DEVICE_SCOPE const * const e) {
|
||||
xml.node("scope", [&] () {
|
||||
xml.attribute("bus_start", e->Bus);
|
||||
xml.attribute("type", e->EntryType);
|
||||
|
||||
unsigned const count = (e->Length < 6) ? 0 : ((e->Length - 6) / 2);
|
||||
|
||||
ACPI_DMAR_PCI_PATH * path = ACPI_CAST_PTR(ACPI_DMAR_PCI_PATH, e + 1);
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
xml.node("path", [&] () {
|
||||
xml.attribute("dev", String<8>(Hex(path->Device)));
|
||||
xml.attribute("func", String<8>(Hex(path->Function)));
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
for_each_element(dmar_table, (ACPI_DMAR_HEADER *) nullptr, [&](ACPI_DMAR_HEADER const * const e) {
|
||||
if (e->Type == ACPI_DMAR_TYPE_RESERVED_MEMORY) {
|
||||
ACPI_DMAR_RESERVED_MEMORY const * const dmar = ACPI_CAST_PTR (ACPI_DMAR_RESERVED_MEMORY, e);
|
||||
|
||||
xml.node("rmrr", [&] () {
|
||||
xml.attribute("start", String<24>(Hex(dmar->BaseAddress)));
|
||||
xml.attribute("end" , String<24>(Hex(dmar->EndAddress)));
|
||||
|
||||
for_each_element(dmar, (ACPI_DMAR_DEVICE_SCOPE *) nullptr,
|
||||
scope_lambda, scope_length);
|
||||
});
|
||||
} else
|
||||
if (e->Type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
|
||||
ACPI_DMAR_HARDWARE_UNIT const * const drhd = ACPI_CAST_PTR (ACPI_DMAR_HARDWARE_UNIT, e);
|
||||
|
||||
xml.node("drhd", [&] () {
|
||||
xml.attribute("phys", String<24>(Hex(drhd->Address)));
|
||||
xml.attribute("flags", String<4>(Hex(drhd->Flags)));
|
||||
xml.attribute("segment", String<8>(Hex(drhd->Segment)));
|
||||
|
||||
for_each_element(drhd, (ACPI_DMAR_DEVICE_SCOPE *) nullptr,
|
||||
scope_lambda, scope_length);
|
||||
});
|
||||
}
|
||||
}, [](ACPI_DMAR_HEADER const * const e) { return e->Length; });
|
||||
}
|
||||
|
||||
static void add_ivdb(ACPI_TABLE_IVRS const * const ivrs_table,
|
||||
Reporter::Xml_generator &xml)
|
||||
{
|
||||
typedef ACPI_IVRS_HEADER Ivdb;
|
||||
|
||||
for_each_element(ivrs_table, (Ivdb *) nullptr, [&](Ivdb const * const e) {
|
||||
xml.node("ivdb", [&] () {
|
||||
xml.attribute("type", e->Type);
|
||||
});
|
||||
}, [](Ivdb const * const e) { return e->Length; });
|
||||
}
|
||||
|
||||
void Acpica::generate_report(Genode::Env &env, Bridge *pci_root_bridge)
|
||||
{
|
||||
enum { REPORT_SIZE = 5 * 4096 };
|
||||
static Reporter acpi(env, "acpi", "acpi", REPORT_SIZE);
|
||||
acpi.enabled(true);
|
||||
|
||||
Reporter::Xml_generator xml(acpi, [&] () {
|
||||
ACPI_TABLE_HEADER *header = nullptr;
|
||||
|
||||
ACPI_STATUS status = AcpiGetTable((char *)ACPI_SIG_MADT, 0, &header);
|
||||
if (status == AE_OK)
|
||||
add_madt(reinterpret_cast<ACPI_TABLE_MADT *>(header), xml);
|
||||
|
||||
status = AcpiGetTable((char *)ACPI_SIG_MCFG, 0, &header);
|
||||
if (status == AE_OK)
|
||||
add_mcfg(reinterpret_cast<ACPI_TABLE_MCFG *>(header), xml);
|
||||
|
||||
for (unsigned instance = 1; ; instance ++) {
|
||||
|
||||
status = AcpiGetTable(ACPI_STRING(ACPI_SIG_DMAR), instance,
|
||||
&header);
|
||||
if (status != AE_OK)
|
||||
break;
|
||||
|
||||
add_dmar(reinterpret_cast<ACPI_TABLE_DMAR *>(header), xml);
|
||||
}
|
||||
|
||||
status = AcpiGetTable((char *)ACPI_SIG_IVRS, 0, &header);
|
||||
if (status == AE_OK)
|
||||
add_ivdb(reinterpret_cast<ACPI_TABLE_IVRS *>(header), xml);
|
||||
|
||||
if (pci_root_bridge)
|
||||
pci_root_bridge->generate(xml);
|
||||
});
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
TARGET := acpica
|
||||
SRC_CC := os.cc printf.cc report.cc
|
||||
SRC_CC := os.cc printf.cc
|
||||
REQUIRES := x86
|
||||
LIBS += base acpica
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2016-2022 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -14,7 +14,7 @@
|
||||
/* Genode includes */
|
||||
#include <util/reconstructible.h>
|
||||
#include <acpica/acpica.h>
|
||||
#include <legacy/x86/platform_session/client.h>
|
||||
#include <platform_session/connection.h>
|
||||
|
||||
#include "env.h"
|
||||
|
||||
@ -27,24 +27,9 @@ struct Acpica::Env
|
||||
Genode::Env &env;
|
||||
Genode::Allocator &heap;
|
||||
|
||||
Wait_acpi_ready const wait_acpi_ready;
|
||||
Genode::Constructible<Platform::Connection> platform;
|
||||
|
||||
Genode::Parent::Service_name announce_for_acpica {
|
||||
wait_acpi_ready.enabled ? "Acpi" : Platform::Session::service_name() };
|
||||
|
||||
Genode::Parent::Client parent_client;
|
||||
|
||||
Genode::Id_space<Genode::Parent::Client>::Element id_space_element {
|
||||
parent_client, env.id_space() };
|
||||
|
||||
Genode::Constructible<Genode::Capability<Platform::Session>> cap;
|
||||
Genode::Constructible<Platform::Client> platform;
|
||||
|
||||
Env(Genode::Env &env, Genode::Allocator &heap,
|
||||
Wait_acpi_ready wait_acpi_ready)
|
||||
:
|
||||
env(env), heap(heap), wait_acpi_ready(wait_acpi_ready)
|
||||
{ }
|
||||
Env(Genode::Env &env, Genode::Allocator &heap) : env(env), heap(heap) { }
|
||||
};
|
||||
|
||||
static Genode::Constructible<Acpica::Env> instance;
|
||||
@ -54,25 +39,16 @@ Genode::Allocator & Acpica::heap() { return instance->heap; }
|
||||
Genode::Env & Acpica::env() { return instance->env; }
|
||||
Platform::Client & Acpica::platform()
|
||||
{
|
||||
if (!instance->cap.constructed()) {
|
||||
instance->cap.construct(Genode::reinterpret_cap_cast<Platform::Session>(
|
||||
instance->env.session(instance->announce_for_acpica,
|
||||
instance->id_space_element.id(),
|
||||
"ram_quota=48K", Genode::Affinity())));
|
||||
if (!instance->platform.constructed())
|
||||
instance->platform.construct(instance->env);
|
||||
|
||||
instance->platform.construct(*instance->cap);
|
||||
}
|
||||
return *instance->platform;
|
||||
}
|
||||
|
||||
|
||||
void Acpica::init(Genode::Env &env, Genode::Allocator &heap,
|
||||
Wait_acpi_ready const wait_acpi_ready,
|
||||
Act_as_acpi_drv const act_as_acpi_drv)
|
||||
void Acpica::init(Genode::Env &env, Genode::Allocator &heap)
|
||||
{
|
||||
instance.construct(env, heap, wait_acpi_ready);
|
||||
instance.construct(env, heap);
|
||||
|
||||
/* if not running as acpi_drv, block until original acpi_drv is done */
|
||||
if (!act_as_acpi_drv.enabled)
|
||||
platform();
|
||||
platform();
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
#include <base/env.h>
|
||||
#include <base/allocator.h>
|
||||
#include <legacy/x86/platform_session/client.h>
|
||||
#include <platform_session/client.h>
|
||||
|
||||
namespace Acpica {
|
||||
Genode::Env & env();
|
||||
|
@ -12,7 +12,6 @@
|
||||
*/
|
||||
|
||||
#include <base/log.h>
|
||||
#include <io_port_session/connection.h>
|
||||
|
||||
#include "env.h"
|
||||
|
||||
@ -51,49 +50,11 @@ ACPI_STATUS AcpiOsInitialize (void) { return AE_OK; }
|
||||
ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
UINT64 *value, UINT32 width)
|
||||
{
|
||||
Platform::Device_capability cap = Acpica::platform().first_device();
|
||||
using namespace Genode;
|
||||
|
||||
while (cap.valid()) {
|
||||
Platform::Device_client client(cap);
|
||||
Bdf bdf(pcidev->Bus, pcidev->Device, pcidev->Function);
|
||||
|
||||
unsigned char bus, dev, fn;
|
||||
client.bus_address(&bus, &dev, &fn);
|
||||
|
||||
if (pcidev->Bus == bus && pcidev->Device == dev &&
|
||||
pcidev->Function == fn) {
|
||||
|
||||
Platform::Device_client::Access_size access_size;
|
||||
switch (width) {
|
||||
case 8:
|
||||
access_size = Platform::Device_client::Access_size::ACCESS_8BIT;
|
||||
break;
|
||||
case 16:
|
||||
access_size = Platform::Device_client::Access_size::ACCESS_16BIT;
|
||||
break;
|
||||
case 32:
|
||||
access_size = Platform::Device_client::Access_size::ACCESS_32BIT;
|
||||
break;
|
||||
default:
|
||||
Genode::error(__func__, " : unsupported access size ", width);
|
||||
Acpica::platform().release_device(client.rpc_cap());
|
||||
return AE_ERROR;
|
||||
};
|
||||
|
||||
if (reg >= 0x100)
|
||||
Genode::warning(__func__, " ", Genode::Hex(reg),
|
||||
" out of supported config space range ",
|
||||
" -> wrong location will be read");
|
||||
|
||||
*value = client.config_read(reg, access_size);
|
||||
|
||||
Acpica::platform().release_device(client.rpc_cap());
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
cap = Acpica::platform().next_device(cap);
|
||||
|
||||
Acpica::platform().release_device(client.rpc_cap());
|
||||
}
|
||||
error(__func__, " ", bdf, " ", Hex(reg), " width=", width);
|
||||
|
||||
*value = ~0U;
|
||||
return AE_OK;
|
||||
@ -102,49 +63,11 @@ ACPI_STATUS AcpiOsReadPciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
ACPI_STATUS AcpiOsWritePciConfiguration (ACPI_PCI_ID *pcidev, UINT32 reg,
|
||||
UINT64 value, UINT32 width)
|
||||
{
|
||||
Platform::Device_capability cap = Acpica::platform().first_device();
|
||||
using namespace Genode;
|
||||
|
||||
while (cap.valid()) {
|
||||
Platform::Device_client client(cap);
|
||||
Bdf bdf(pcidev->Bus, pcidev->Device, pcidev->Function);
|
||||
|
||||
unsigned char bus, dev, fn;
|
||||
client.bus_address(&bus, &dev, &fn);
|
||||
|
||||
if (pcidev->Bus == bus && pcidev->Device == dev &&
|
||||
pcidev->Function == fn) {
|
||||
|
||||
Platform::Device_client::Access_size access_size;
|
||||
switch (width) {
|
||||
case 8:
|
||||
access_size = Platform::Device_client::Access_size::ACCESS_8BIT;
|
||||
break;
|
||||
case 16:
|
||||
access_size = Platform::Device_client::Access_size::ACCESS_16BIT;
|
||||
break;
|
||||
case 32:
|
||||
access_size = Platform::Device_client::Access_size::ACCESS_32BIT;
|
||||
break;
|
||||
default:
|
||||
Genode::error(__func__, " : unsupported access size ", width);
|
||||
Acpica::platform().release_device(client.rpc_cap());
|
||||
return AE_ERROR;
|
||||
};
|
||||
|
||||
client.config_write(reg, value, access_size);
|
||||
|
||||
if (reg >= 0x100)
|
||||
Genode::warning(__func__, " ", Genode::Hex(reg),
|
||||
" out of supported config space range ",
|
||||
" -> wrong location will be written");
|
||||
|
||||
Acpica::platform().release_device(client.rpc_cap());
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
cap = Acpica::platform().next_device(cap);
|
||||
|
||||
Acpica::platform().release_device(client.rpc_cap());
|
||||
}
|
||||
error(__func__, " ", bdf, " ", Hex(reg), "=", Hex(value), " width=", width);
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user