hw: provide ACPI infos via platform_info ROM

in uefi/mbi2 boot case

Issue #2242
This commit is contained in:
Alexander Boettcher 2017-08-11 14:29:16 +02:00 committed by Christian Helmuth
parent 972031cbbc
commit 6792456e4e
7 changed files with 133 additions and 11 deletions

View File

@ -181,8 +181,9 @@ Platform::Platform()
Hw::PAGE_FLAGS_KERN_TEXT));
Boot_info & bootinfo =
*construct_at<Boot_info>(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) {

View File

@ -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();
};

View File

@ -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 <typename FUNC>
void for_each_mem(FUNC functor)
template <typename FUNC_MEM, typename FUNC_ACPI>
void for_each_tag(FUNC_MEM mem_fn, FUNC_ACPI acpi_fn)
{
addr_t const size = read<Multiboot2_info::Size>();
@ -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>() == 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<Hw::Acpi_rsdp *>(rsdp_addr);
if (rsdp->valid() &&
sizeof(*rsdp) >= tag.read<Tag::Size>() - sizeof_tag)
acpi_fn(*rsdp);
}
tag_addr += align_addr(tag.read<Tag::Size>(), Tag::LOG2_SIZE);
}
}

View File

@ -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<Multiboot2_info::Memory::Type>();
if (type != Multiboot2_info::Memory::Type::MEMORY)
@ -75,7 +75,8 @@ Bootstrap::Platform::Board::Board()
uint64_t const size = m.read<Multiboot2_info::Memory::Size>();
lambda(base, size);
});
},
[&] (Hw::Acpi_rsdp const &rsdp) { acpi_rsdp = rsdp; });
return;
}

View File

@ -14,11 +14,73 @@
#include <bios_data_area.h>
#include <platform.h>
#include <kernel/kernel.h>
#include <map_local.h>
#include <util/xml_generator.h>
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<addr_t>(phys_ptr);
addr_t const virt_addr = reinterpret_cast<addr_t>(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<char *>(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,

View File

@ -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 <base/fixed_stdint.h>
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 */

View File

@ -15,6 +15,7 @@
#define _SRC__LIB__HW__BOOT_INFO_H_
#include <hw/mmio_space.h>
#include <hw/acpi_rsdp.h>
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_ */