diff --git a/repos/os/src/drivers/acpi/acpi.cc b/repos/os/src/drivers/acpi/acpi.cc index a5b08ac989..3c59118fdd 100644 --- a/repos/os/src/drivers/acpi/acpi.cc +++ b/repos/os/src/drivers/acpi/acpi.cc @@ -11,7 +11,7 @@ */ /* - * Copyright (C) 2009-2015 Genode Labs GmbH + * Copyright (C) 2009-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. @@ -19,6 +19,7 @@ /* base includes */ #include +#include #include /* os includes */ @@ -137,10 +138,10 @@ struct Dmar_struct_header : Generic } while (addr < dmar_entry_end()); } - struct Dmar_struct_header * clone() + struct Dmar_struct_header * clone(Genode::Allocator &alloc) { size_t const size = dmar_entry_end() - reinterpret_cast(this); - char * clone = new (env()->heap()) char[size]; + char * clone = new (&alloc) char[size]; memcpy(clone, this, size); return reinterpret_cast(clone); @@ -371,7 +372,7 @@ class Table_wrapper /** * Parse override structures */ - void parse_madt() + void parse_madt(Genode::Allocator &alloc) { Apic_struct *apic = _table->apic_struct(); for (; apic < _table->end(); apic = apic->next()) { @@ -382,12 +383,12 @@ class Table_wrapper PINF("MADT IRQ %u -> GSI %u flags: %x", o->irq, o->gsi, o->flags); - Irq_override::list()->insert(new (env()->heap()) + Irq_override::list()->insert(new (&alloc) Irq_override(o->irq, o->gsi, o->flags)); } } - void parse_mcfg() const + void parse_mcfg(Genode::Allocator &alloc) const { Mcfg_struct *mcfg = _table->mcfg_struct(); for (; mcfg < _table->mcfg_end(); mcfg = mcfg->next()) { @@ -400,11 +401,11 @@ class Table_wrapper uint32_t bus_start = mcfg->pci_bus_start * 32 * 8; Pci_config_space::list()->insert( - new (env()->heap()) Pci_config_space(bus_start, func_count, mcfg->base)); + new (&alloc) Pci_config_space(bus_start, func_count, mcfg->base)); } } - void parse_dmar() const + void parse_dmar(Genode::Allocator &alloc) const { Dmar_struct_header *head = _table->dmar_header(); PLOG("%u bit DMA physical addressable%s\n", head->width + 1, @@ -415,7 +416,7 @@ class Table_wrapper PLOG("DMA remapping structure type=%u", dmar.read()); }); - Dmar_entry::list()->insert(new (env()->heap()) Dmar_entry(head->clone())); + Dmar_entry::list()->insert(new (&alloc) Dmar_entry(head->clone(alloc))); } Table_wrapper(addr_t base) : _base(base), _table(0) @@ -487,14 +488,14 @@ class Element : public List::Element uint8_t _type; /* the type of this element */ uint32_t _size; /* size in bytes */ uint32_t _size_len; /* length of size in bytes */ - char *_name; /* name of element */ + char _name[64]; /* name of element */ uint32_t _name_len; /* length of name in bytes */ uint32_t _bdf; /* bus device function */ uint8_t const *_data; /* pointer to the data section */ uint32_t _para_len; /* parameters to be skipped */ bool _valid; /* true if this is a valid element */ bool _routed; /* has the PCI information been read */ - List *_pci; /* list of PCI routing elements for this element */ + List _pci; /* list of PCI routing elements for this element */ /* packages we are looking for */ enum { DEVICE = 0x5b, SUB_DEVICE = 0x82, DEVICE_NAME = 0x8, SCOPE = 0x10, METHOD = 0x14, PACKAGE_OP = 0x12 }; @@ -655,8 +656,7 @@ class Element : public List::Element /* is absolute name */ if (*name == ROOT_PREFIX || !parent) { - _name = (char *)env()->heap()->alloc(_name_len); - memcpy(_name, name + prefix_len, _name_len); + memcpy(_name, name + prefix_len, min(sizeof(_name), _name_len)); } else { /* skip parts */ @@ -665,7 +665,11 @@ class Element : public List::Element /* skip parent prefix */ for (uint32_t p = 0; name[p] == PARENT_PREFIX; p++, parent_len -= NAME_LEN) ; - _name = (char *)env()->heap()->alloc(_name_len + parent_len); + + if (_name_len + parent_len > sizeof(_name)) { + PERR("name is not large enough"); + throw -1; + } memcpy(_name, parent->_name, parent_len); memcpy(_name + parent_len, name + prefix_len, _name_len); @@ -747,7 +751,7 @@ class Element : public List::Element * Try to locate _PRT table and its GSI values for device * (data has to be located within the device data) */ - void _direct_prt(Element *dev) + void _direct_prt(Genode::Allocator &alloc, Element *dev) { uint32_t len = 0; @@ -771,11 +775,11 @@ class Element : public List::Element } if (i == 4) { - Pci_routing * r = new (env()->heap()) Pci_routing(val[0], val[1], val[3]); + Pci_routing * r = new (&alloc) Pci_routing(val[0], val[1], val[3]); /* set _ADR, _PIN, _GSI */ - dev->pci_list()->insert(r); - dev->pci_list()->first()->dump(); + dev->pci_list().insert(r); + dev->pci_list().first()->dump(); } len = len ? (e.data() - (_data + offset)) + e.size() : 1; @@ -785,7 +789,7 @@ class Element : public List::Element /** * Search for _PRT outside of device */ - void _indirect_prt(Element *dev) + void _indirect_prt(Genode::Allocator &alloc, Element *dev) { uint32_t name_len; uint32_t found = 0; @@ -805,7 +809,7 @@ class Element : public List::Element for (uint32_t skip = 0; skip <= dev->_name_len / NAME_LEN; skip++) { Element *e = dev->_compare(name, skip * NAME_LEN); if (e) - e->_direct_prt(dev); + e->_direct_prt(alloc, dev); } } else @@ -815,9 +819,11 @@ class Element : public List::Element Element(uint8_t const *data = 0, bool package_op4 = false) : - _type(0), _size(0), _size_len(0), _name(0), _name_len(0), _bdf(0), - _data(data), _para_len(0), _valid(false), _routed(false), _pci(0) + _type(0), _size(0), _size_len(0), _name_len(0), _bdf(0), + _data(data), _para_len(0), _valid(false), _routed(false) { + _name[0] = '\0'; + if (!data) return; @@ -900,18 +906,14 @@ class Element : public List::Element _type = other._type; _size = other._size; _size_len = other._size_len; + memcpy(_name, other._name, sizeof(_name)); _name_len = other._name_len; _bdf = other._bdf; _data = other._data; + _para_len = other._para_len; _valid = other._valid; _routed = other._routed; _pci = other._pci; - _para_len = other._para_len; - - if (other._name) { - _name = (char *)env()->heap()->alloc(other._name_len); - memcpy(_name, other._name, _name_len); - } } bool is_device_name() { return _type == DEVICE_NAME; } @@ -933,11 +935,7 @@ class Element : public List::Element public: - virtual ~Element() - { - if (_name) - env()->heap()->free(_name, _name_len); - } + virtual ~Element() { } /** * Accessors @@ -969,7 +967,7 @@ class Element : public List::Element return &_list; } - static void clean_list() + static void clean_list(Genode::Allocator &alloc) { unsigned long freed_up = 0; @@ -985,7 +983,7 @@ class Element : public List::Element Element * next = element->next(); Element::list()->remove(element); - destroy(env()->heap(), element); + destroy(&alloc, element); element = next; } @@ -996,17 +994,12 @@ class Element : public List::Element /** * Return list of PCI information for this element */ - List *pci_list() - { - if (!_pci) - _pci = new (env()->heap()) List(); - return _pci; - } + List & pci_list() { return _pci; } /** * Parse elements of table */ - static void parse(Generic *table) + static void parse(Genode::Allocator &alloc, Generic *table) { uint8_t const *data = table->data(); for (; data < table->data() + table->size; data++) { @@ -1018,7 +1011,7 @@ class Element : public List::Element if (data + e.size() > table->data() + table->size) break; - Element *i = new (env()->heap()) Element(e); + Element *i = new (&alloc) Element(e); list()->insert(i); /* skip header */ @@ -1031,13 +1024,13 @@ class Element : public List::Element data += e._para_len; } - parse_bdf(); + parse_bdf(alloc); } /** * Parse BDF and GSI information */ - static void parse_bdf() + static void parse_bdf(Genode::Allocator &alloc) { for (Element *e = list()->first(); e; e = e->next()) { @@ -1064,8 +1057,8 @@ class Element : public List::Element if (verbose) PDBG("Scanning device %x", e->_bdf); - prt->_direct_prt(e); - prt->_indirect_prt(e); + prt->_direct_prt(alloc, e); + prt->_indirect_prt(alloc, e); } e->_routed = true; @@ -1083,7 +1076,7 @@ class Element : public List::Element if (!e->is_device() || e->_bdf != bridge_bdf) continue; - Pci_routing *r = e->pci_list()->first(); + Pci_routing *r = e->pci_list().first(); for (; r; r = r->next()) { if (r->match_bdf(device_bdf) && r->pin() == pin) { if (verbose) PDBG("Found GSI: %u device : %x pin %u", @@ -1104,6 +1097,9 @@ class Acpi_table { private: + Genode::Env &env; + Genode::Allocator &alloc; + /* BIOS range to scan for RSDP */ enum { BIOS_BASE = 0xe0000, BIOS_SIZE = 0x20000 }; @@ -1118,7 +1114,7 @@ class Acpi_table if (!io_ds.valid()) throw -1; - uint8_t *ret = env()->rm_session()->attach(io_ds, size); + uint8_t *ret = env.rm().attach(io_ds, size); cap = io_mem.cap(); return ret; } @@ -1146,25 +1142,25 @@ class Acpi_table try { area = _search_rsdp(_map_io(BIOS_BASE, BIOS_SIZE, cap)); return area; - } catch (...) { env()->parent()->close(cap); } + } catch (...) { env.parent().close(cap); } /* search EBDA (BIOS addr + 0x40e) */ try { area = _map_io(0x0, 0x1000, cap); if (area) { unsigned short base = (*reinterpret_cast(area + 0x40e)) << 4; - env()->parent()->close(cap); + env.parent().close(cap); area = _map_io(base, 1024, cap); area = _search_rsdp(area); } return area; - } catch (...) { env()->parent()->close(cap); } + } catch (...) { env.parent().close(cap); } return 0; } template - void _parse_tables(T * entries, uint32_t count) + void _parse_tables(Genode::Allocator &alloc, T * entries, uint32_t count) { /* search for SSDT and DSDT tables */ for (uint32_t i = 0; i < count; i++) { @@ -1181,23 +1177,23 @@ class Acpi_table if (verbose) PDBG("Found %s", table.name()); - Element::parse(table.table()); + Element::parse(alloc, table.table()); } if (table.is_madt()) { PDBG("Found MADT"); - table.parse_madt(); + table.parse_madt(alloc); } if (table.is_mcfg()) { PDBG("Found MCFG"); - table.parse_mcfg(); + table.parse_mcfg(alloc); } if (table.is_dmar()) { PDBG("Found DMAR"); - table.parse_dmar(); + table.parse_dmar(alloc); } } @@ -1207,7 +1203,7 @@ class Acpi_table if (verbose) PDBG("Found dsdt %s", table.name()); - Element::parse(table.table()); + Element::parse(alloc, table.table()); } } } @@ -1216,7 +1212,8 @@ class Acpi_table public: - Acpi_table() + Acpi_table(Genode::Env &env, Genode::Allocator &alloc) + : env(env), alloc(alloc) { Io_mem_session_capability io_mem; @@ -1224,7 +1221,7 @@ class Acpi_table struct rsdp { char signature[8]; - uint8_t checksum; + uint8_t checksum; char oemid[6]; uint8_t revision; /* table pointer at 16 byte offset in RSDP structure (5.2.5.3) */ @@ -1233,7 +1230,7 @@ class Acpi_table uint32_t len; uint64_t xsdt; uint8_t checksum_extended; - uint8_t reserved[3]; + uint8_t reserved[3]; } __attribute__((packed)); struct rsdp * rsdp = reinterpret_cast(ptr_rsdp); @@ -1255,22 +1252,22 @@ class Acpi_table addr_t const xsdt = rsdp->xsdt; uint8_t const acpi_revision = rsdp->revision; /* drop rsdp io_mem mapping since rsdt/xsdt may overlap */ - env()->parent()->close(io_mem); + env.parent().close(io_mem); if (acpi_revision != 0 && xsdt && sizeof(addr_t) != sizeof(uint32_t)) { /* running 64bit and xsdt is valid */ Table_wrapper table(xsdt); uint64_t * entries = reinterpret_cast(table.table() + 1); - _parse_tables(entries, table.entry_count(entries)); + _parse_tables(alloc, entries, table.entry_count(entries)); } else { /* running (32bit) or (64bit and xsdt isn't valid) */ Table_wrapper table(rsdt); uint32_t * entries = reinterpret_cast(table.table() + 1); - _parse_tables(entries, table.entry_count(entries)); + _parse_tables(alloc, entries, table.entry_count(entries)); } /* free up memory of elements not of any use */ - Element::clean_list(); + Element::clean_list(alloc); /* free up io memory */ acpi_memory().free_io_memory(); @@ -1278,15 +1275,6 @@ class Acpi_table }; -/** - * Parse acpi table - */ -static void init_acpi_table() -{ - static Acpi_table table; -} - - static void attribute_hex(Xml_generator &xml, char const *name, unsigned long long value) { @@ -1296,9 +1284,10 @@ static void attribute_hex(Xml_generator &xml, char const *name, } -void Acpi::generate_report() +void Acpi::generate_report(Genode::Env &env, Genode::Allocator &alloc) { - init_acpi_table(); + /* parse table */ + Acpi_table acpi_table(env, alloc); enum { REPORT_SIZE = 4 * 4096 }; static Reporter acpi("acpi", "acpi", REPORT_SIZE); @@ -1373,7 +1362,7 @@ void Acpi::generate_report() if (!e->is_device()) continue; - Pci_routing *r = e->pci_list()->first(); + Pci_routing *r = e->pci_list().first(); for (; r; r = r->next()) { xml.node("routing", [&] () { attribute_hex(xml, "gsi", r->gsi()); diff --git a/repos/os/src/drivers/acpi/acpi.h b/repos/os/src/drivers/acpi/acpi.h index 3f17115433..6ddd296906 100644 --- a/repos/os/src/drivers/acpi/acpi.h +++ b/repos/os/src/drivers/acpi/acpi.h @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2009-2013 Genode Labs GmbH + * Copyright (C) 2009-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. @@ -14,12 +14,16 @@ #ifndef _ACPI_H_ #define _ACPI_H_ +/* Genode includes */ +#include + + namespace Acpi { /** * Generate report rom */ - void generate_report(); + void generate_report(Genode::Env&, Genode::Allocator&); } #endif /* _ACPI_H_ */ diff --git a/repos/os/src/drivers/acpi/main.cc b/repos/os/src/drivers/acpi/main.cc index e577ce870a..5edc2b0511 100644 --- a/repos/os/src/drivers/acpi/main.cc +++ b/repos/os/src/drivers/acpi/main.cc @@ -5,33 +5,53 @@ */ /* - * Copyright (C) 2009-2015 Genode Labs GmbH + * Copyright (C) 2009-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. */ -#include -#include +/* Genode includes */ +#include +#include +#include +#include -#include +/* local includes */ +#include -#include "acpi.h" -int main(int argc, char **argv) -{ +namespace Acpi { using namespace Genode; - try { - Acpi::generate_report(); - } catch (Genode::Xml_generator::Buffer_exceeded) { - PERR("ACPI report too large - failure"); - throw; - } catch (...) { - PERR("Unknown exception occured - failure"); - throw; - } - - Genode::sleep_forever(); - return 0; + struct Main; +} + +struct Acpi::Main +{ + Genode::Env &env; + Genode::Heap heap { env.ram(), env.rm() }; + + Main(Env &env) : env(env) + { + try { + Acpi::generate_report(env, heap); + } catch (Genode::Xml_generator::Buffer_exceeded) { + Genode::error("ACPI report too large - failure"); + throw; + } catch (...) { + Genode::error("Unknown exception occured - failure"); + throw; + } + } +}; + + +/*************** + ** Component ** + ***************/ + +namespace Component { + Genode::size_t stack_size() { return 2*1024*sizeof(long); } + void construct(Genode::Env &env) { static Acpi::Main main(env); } }