From 6792456e4e40066a66758af7e2141561fbf0c891 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Fri, 11 Aug 2017 14:29:16 +0200 Subject: [PATCH] hw: provide ACPI infos via platform_info ROM in uefi/mbi2 boot case Issue #2242 --- repos/base-hw/src/bootstrap/platform.cc | 5 +- repos/base-hw/src/bootstrap/platform.h | 1 + .../src/bootstrap/spec/x86_64/multiboot2.h | 21 ++++-- .../src/bootstrap/spec/x86_64/platform.cc | 5 +- .../src/core/spec/x86_64/platform_support.cc | 64 ++++++++++++++++++- repos/base-hw/src/lib/hw/acpi_rsdp.h | 40 ++++++++++++ repos/base-hw/src/lib/hw/boot_info.h | 8 ++- 7 files changed, 133 insertions(+), 11 deletions(-) create mode 100644 repos/base-hw/src/lib/hw/acpi_rsdp.h diff --git a/repos/base-hw/src/bootstrap/platform.cc b/repos/base-hw/src/bootstrap/platform.cc index c57497c35..c5f040039 100644 --- a/repos/base-hw/src/bootstrap/platform.cc +++ b/repos/base-hw/src/bootstrap/platform.cc @@ -181,8 +181,9 @@ Platform::Platform() Hw::PAGE_FLAGS_KERN_TEXT)); Boot_info & bootinfo = *construct_at(bi_base, (addr_t)&core_pd->table, - (addr_t)&core_pd->array, - core_pd->mappings, board.core_mmio); + (addr_t)&core_pd->array, + core_pd->mappings, board.core_mmio, + board.acpi_rsdp); /* add all left RAM to bootinfo */ ram_alloc.for_each_free_region([&] (Memory_region const & r) { diff --git a/repos/base-hw/src/bootstrap/platform.h b/repos/base-hw/src/bootstrap/platform.h index 75de0185e..fe1ee586e 100644 --- a/repos/base-hw/src/bootstrap/platform.h +++ b/repos/base-hw/src/bootstrap/platform.h @@ -45,6 +45,7 @@ class Bootstrap::Platform Memory_region_array early_ram_regions; Memory_region_array late_ram_regions; Mmio_space const core_mmio; + Hw::Acpi_rsdp acpi_rsdp; Board(); }; diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/multiboot2.h b/repos/base-hw/src/bootstrap/spec/x86_64/multiboot2.h index 01f72fdb8..4617caa23 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/multiboot2.h +++ b/repos/base-hw/src/bootstrap/spec/x86_64/multiboot2.h @@ -28,7 +28,10 @@ class Genode::Multiboot2_info : Mmio struct Tag : Genode::Mmio { enum { LOG2_SIZE = 3 }; - struct Type : Register <0x00, 32> { enum { END = 0, MEMORY = 6 }; }; + struct Type : Register <0x00, 32> + { + enum { END = 0, MEMORY = 6, ACPI_RSDP = 15 }; + }; struct Size : Register <0x04, 32> { }; Tag(addr_t addr) : Mmio(addr) { } @@ -50,8 +53,8 @@ class Genode::Multiboot2_info : Mmio Multiboot2_info(addr_t mbi) : Mmio(mbi) { } - template - void for_each_mem(FUNC functor) + template + void for_each_tag(FUNC_MEM mem_fn, FUNC_ACPI acpi_fn) { addr_t const size = read(); @@ -69,10 +72,20 @@ class Genode::Multiboot2_info : Mmio for (; mem_start < mem_end; mem_start += Memory::SIZE) { Memory mem(mem_start); - functor(mem); + mem_fn(mem); } } + if (tag.read() == Tag::Type::ACPI_RSDP) { + size_t const sizeof_tag = 1UL << Tag::LOG2_SIZE; + addr_t const rsdp_addr = tag_addr + sizeof_tag; + + Hw::Acpi_rsdp * rsdp = reinterpret_cast(rsdp_addr); + if (rsdp->valid() && + sizeof(*rsdp) >= tag.read() - sizeof_tag) + acpi_fn(*rsdp); + } + tag_addr += align_addr(tag.read(), Tag::LOG2_SIZE); } } diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc index bd69b4333..1eba9792c 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc @@ -65,7 +65,7 @@ Bootstrap::Platform::Board::Board() if (__initial_ax == Multiboot2_info::MAGIC) { Multiboot2_info mbi2(__initial_bx); - mbi2.for_each_mem([&] (Multiboot2_info::Memory const & m) { + mbi2.for_each_tag([&] (Multiboot2_info::Memory const & m) { uint32_t const type = m.read(); if (type != Multiboot2_info::Memory::Type::MEMORY) @@ -75,7 +75,8 @@ Bootstrap::Platform::Board::Board() uint64_t const size = m.read(); lambda(base, size); - }); + }, + [&] (Hw::Acpi_rsdp const &rsdp) { acpi_rsdp = rsdp; }); return; } diff --git a/repos/base-hw/src/core/spec/x86_64/platform_support.cc b/repos/base-hw/src/core/spec/x86_64/platform_support.cc index 0cedb682d..e9ff36f6e 100644 --- a/repos/base-hw/src/core/spec/x86_64/platform_support.cc +++ b/repos/base-hw/src/core/spec/x86_64/platform_support.cc @@ -14,11 +14,73 @@ #include #include #include +#include + +#include using namespace Genode; -void Platform::_init_additional() { }; +void Platform::_init_additional() +{ + /* export x86 platform specific infos */ + + unsigned const pages = 1; + size_t const rom_size = pages << get_page_size_log2(); + void *phys_ptr = nullptr; + void *virt_ptr = nullptr; + const char *rom_name = "platform_info"; + + if (!ram_alloc()->alloc(get_page_size(), &phys_ptr)) { + error("could not setup platform_info ROM - ram allocation error"); + return; + } + + if (!region_alloc()->alloc(rom_size, &virt_ptr)) { + error("could not setup platform_info ROM - region allocation error"); + ram_alloc()->free(phys_ptr); + return; + } + + addr_t const phys_addr = reinterpret_cast(phys_ptr); + addr_t const virt_addr = reinterpret_cast(virt_ptr); + + if (!map_local(phys_addr, virt_addr, pages, Hw::PAGE_FLAGS_KERN_DATA)) { + error("could not setup platform_info ROM - map error"); + region_alloc()->free(virt_ptr); + ram_alloc()->free(phys_ptr); + return; + } + + Genode::Xml_generator xml(reinterpret_cast(virt_addr), + rom_size, rom_name, [&] () + { + xml.node("acpi", [&] () { + uint32_t const revision = _boot_info().acpi_rsdp.revision; + uint32_t const rsdt = _boot_info().acpi_rsdp.rsdt; + uint64_t const xsdt = _boot_info().acpi_rsdp.xsdt; + + if (revision && (rsdt || xsdt)) { + xml.attribute("revision", revision); + if (rsdt) + xml.attribute("rsdt", String<32>(Hex(rsdt))); + + if (xsdt) + xml.attribute("xsdt", String<32>(Hex(xsdt))); + } + }); + }); + + if (!unmap_local(virt_addr, pages)) { + error("could not setup platform_info ROM - unmap error"); + return; + } + + region_alloc()->free(virt_ptr); + + _rom_fs.insert( + new (core_mem_alloc()) Rom_module(phys_addr, rom_size, rom_name)); +} void Platform::setup_irq_mode(unsigned irq_number, unsigned trigger, diff --git a/repos/base-hw/src/lib/hw/acpi_rsdp.h b/repos/base-hw/src/lib/hw/acpi_rsdp.h new file mode 100644 index 000000000..0da13936c --- /dev/null +++ b/repos/base-hw/src/lib/hw/acpi_rsdp.h @@ -0,0 +1,40 @@ +/* + * \brief ACPI RSDP structure + * \author Alexander Boettcher + * \date 2017-08-15 + */ + +/* + * Copyright (C) 2017 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. + */ + +#ifndef _SRC__LIB__HW__ACPI_RSDP_H +#define _SRC__LIB__HW__ACPI_RSDP_H + +#include + +namespace Hw { + struct Acpi_rsdp; +} + +struct Hw::Acpi_rsdp +{ + Genode::uint64_t signature; + Genode::uint8_t checksum; + char oem[6]; + Genode::uint8_t revision; + Genode::uint32_t rsdt; + Genode::uint32_t length; + Genode::uint64_t xsdt; + Genode::uint32_t reserved; + + bool valid() { + const char sign[] = "RSD PTR "; + return signature == *(Genode::uint64_t *)sign; + } +} __attribute__((packed)); + +#endif /* _SRC__LIB__HW__ACPI_RSDP_H */ diff --git a/repos/base-hw/src/lib/hw/boot_info.h b/repos/base-hw/src/lib/hw/boot_info.h index c0223d859..d0946fabf 100644 --- a/repos/base-hw/src/lib/hw/boot_info.h +++ b/repos/base-hw/src/lib/hw/boot_info.h @@ -15,6 +15,7 @@ #define _SRC__LIB__HW__BOOT_INFO_H_ #include +#include namespace Hw { struct Boot_info; } @@ -27,13 +28,16 @@ struct Hw::Boot_info Mapping_pool const elf_mappings; Mmio_space const mmio_space; Memory_region_array ram_regions; + Acpi_rsdp const acpi_rsdp; Boot_info(addr_t const table, addr_t const table_alloc, Mapping_pool const elf_mappings, - Mmio_space const mmio_space) + Mmio_space const mmio_space, + Acpi_rsdp const &acpi_rsdp) : table(table), table_allocator(table_alloc), - elf_mappings(elf_mappings), mmio_space(mmio_space) {} + elf_mappings(elf_mappings), mmio_space(mmio_space), + acpi_rsdp(acpi_rsdp) {} }; #endif /* _SRC__LIB__HW__BOOT_INFO_H_ */