blob: 72cc72b3ff3bc3f2a856434be3c6116e28d52cdb [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#pragma once
#include <fbl/function.h>
#include <stdint.h>
#include <zircon/types.h>
// ACPI structures
struct acpi_rsdp {
uint8_t sig[8];
uint8_t checksum;
uint8_t oemid[6];
uint8_t revision;
uint32_t rsdt_address;
// rev 2+
uint32_t length;
uint64_t xsdt_address;
uint8_t extended_checksum;
uint8_t reserved[3];
} __PACKED;
#define ACPI_RSDP_SIG "RSD PTR "
// standard system description table header
struct acpi_sdt_header {
uint8_t sig[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
uint8_t oemid[6];
uint8_t oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
} __PACKED;
static_assert(sizeof(acpi_sdt_header) == 36, "");
struct acpi_rsdt_xsdt {
acpi_sdt_header header;
// array of uint32s or uint64 addresses are placed immediately afterwards
union {
uint32_t addr32[0];
uint64_t addr64[0];
};
} __PACKED;
#define ACPI_RSDT_SIG "RSDT"
#define ACPI_XSDT_SIG "XSDT"
struct acpi_madt_table {
acpi_sdt_header header;
uint32_t local_int_controller_address;
uint32_t flags;
} __PACKED;
#define ACPI_MADT_SIG "APIC"
struct acpi_sub_table_header {
uint8_t type;
uint8_t length;
} __PACKED;
struct acpi_generic_address_ {
uint8_t address_space_id;
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t access_size;
uint64_t address;
} __PACKED;
struct acpi_hpet_table {
acpi_sdt_header header;
uint32_t id;
acpi_generic_address_ address;
uint8_t sequence;
uint16_t minimum_tick;
uint8_t flags;
} __PACKED;
zx_status_t acpi_lite_init(zx_paddr_t rsdt);
void acpi_lite_dump_tables();
const acpi_sdt_header *acpi_get_table_by_sig(const char *sig);
const acpi_sdt_header *acpi_get_table_at_index(size_t index);
// MADT table describes processors and interrupt controllers
template <typename T, typename C>
static inline zx_status_t acpi_process_madt_entries(const uint8_t search_type, C callback) {
const acpi_madt_table *madt = reinterpret_cast<const acpi_madt_table *>(acpi_get_table_by_sig(ACPI_MADT_SIG));
if (!madt) {
return ZX_ERR_NOT_FOUND;
}
// bytewise array of the same table
const uint8_t *madt_array = (const uint8_t *)madt;
// walk the table off the end of the header, looking for the requested type
size_t off = sizeof(*madt);
while (off < madt->header.length) {
uint8_t type = madt_array[off];
uint8_t length = madt_array[off + 1];
if (type == search_type) {
callback(reinterpret_cast<const T *>(&madt_array[off]));
}
off += length;
}
return ZX_OK;
}
// type 0: local apic
struct acpi_madt_local_apic_entry {
acpi_sub_table_header header;
uint8_t processor_id;
uint8_t apic_id;
uint32_t flags;
} __PACKED;
#define ACPI_MADT_FLAG_ENABLED 0x1
// type 1: io apic
struct acpi_madt_io_apic_entry {
acpi_sub_table_header header;
uint8_t io_apic_id;
uint8_t reserved;
uint32_t io_apic_address;
uint32_t global_system_interrupt_base;
} __PACKED;
// type 2: interrupt source override
struct acpi_madt_int_source_override_entry {
acpi_sub_table_header header;
uint8_t bus;
uint8_t source;
uint32_t global_sys_interrupt;
uint16_t flags;
} __PACKED;
#define ACPI_MADT_FLAG_POLARITY_CONFORMS 0b00
#define ACPI_MADT_FLAG_POLARITY_HIGH 0b01
#define ACPI_MADT_FLAG_POLARITY_LOW 0b11
#define ACPI_MADT_FLAG_POLARITY_MASK 0b11
#define ACPI_MADT_FLAG_TRIGGER_CONFORMS 0b0000
#define ACPI_MADT_FLAG_TRIGGER_EDGE 0b0100
#define ACPI_MADT_FLAG_TRIGGER_LEVEL 0b1100
#define ACPI_MADT_FLAG_TRIGGER_MASK 0b1100
using MadtEntryCallback = fbl::Function<void(const void* ptr)>;
zx_status_t acpi_process_madt_entries_etc(const uint8_t search_type, const MadtEntryCallback&);
template <typename C>
static inline zx_status_t acpi_process_madt_local_apic_entries(C callback) {
return acpi_process_madt_entries<acpi_madt_local_apic_entry, C>(0, callback);
}
template <typename C>
static inline zx_status_t acpi_process_madt_io_apic_entries(C callback) {
return acpi_process_madt_entries<acpi_madt_io_apic_entry, C>(1, callback);
}
template <typename C>
static inline zx_status_t acpi_process_madt_int_source_override_entries(C callback) {
return acpi_process_madt_entries<acpi_madt_int_source_override_entry, C>(2, callback);
}