blob: b58cbc045e5b9f1a2f25d33f4b39ccc9973c1de2 [file] [log] [blame]
// Copyright 2020 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
#ifndef ZIRCON_KERNEL_LIB_ACPI_LITE_INCLUDE_LIB_ACPI_LITE_STRUCTURES_H_
#define ZIRCON_KERNEL_LIB_ACPI_LITE_INCLUDE_LIB_ACPI_LITE_STRUCTURES_H_
#include <lib/acpi_lite/internal.h>
#include <stdint.h>
#include <zircon/compiler.h>
#include <zircon/types.h>
namespace acpi_lite {
// First byte and length of the x86 BIOS read-only area, [0xe0'000, 0xff'fff].
//
// Reference: ACPI v6.3, Section 5.2.5.1
constexpr zx_paddr_t kBiosReadOnlyAreaStart = 0xe0'000;
constexpr size_t kBiosReadOnlyAreaLength = 0x20'000;
// ACPI signature.
//
// Signatures are 4 byte ASCII strings. We represent them as an integer.
struct AcpiSignature {
// Value, in big-endian format to match the in-memory representation.
//
// For example, on little-endian systems the signature "1234" will have a value
// 0x34'33'32'31, with bytes reversed.
uint32_t value;
// Create an AcpiSignature from a C-style string.
AcpiSignature() = default;
explicit constexpr AcpiSignature(const char name[4])
: value(acpi_lite::HostToBe32(name[0] << 24 | name[1] << 16 | name[2] << 8 | name[3])) {}
// Operators.
friend bool operator==(const AcpiSignature& left, const AcpiSignature& right) {
return left.value == right.value;
}
friend bool operator!=(const AcpiSignature& left, const AcpiSignature& right) {
return left.value != right.value;
}
// Write the signature into the given buffer.
//
// Buffer must have a length of at least 5.
void WriteToBuffer(char* buffer) const;
// Length of the signature when represented as ASCII.
static constexpr int kAsciiLength = 4;
} __PACKED;
// Root System Description Pointer (RSDP)
//
// Reference: ACPI v6.3 Section 5.2.5.3.
struct AcpiRsdp {
AcpiSignature sig1; // "RSD "
AcpiSignature sig2; // "PTR "
uint8_t checksum;
uint8_t oemid[6];
uint8_t revision;
uint32_t rsdt_address;
static constexpr auto kSignature1 = AcpiSignature("RSD ");
static constexpr auto kSignature2 = AcpiSignature("PTR ");
} __PACKED;
static_assert(sizeof(AcpiRsdp) == 20);
struct AcpiRsdpV2 {
// rev 1
AcpiRsdp v1;
// rev 2+
uint32_t length;
uint64_t xsdt_address;
uint8_t extended_checksum;
uint8_t reserved[3];
size_t size() const { return length; }
} __PACKED;
static_assert(sizeof(AcpiRsdpV2) == 36);
// Standard system description table header, used as the header of
// multiple structures below.
//
// Reference: ACPI v6.3 Section 5.2.6.
struct AcpiSdtHeader {
AcpiSignature sig;
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;
size_t size() const { return length; }
} __PACKED;
static_assert(sizeof(AcpiSdtHeader) == 36);
// Root System Description Table (RSDT) and Extended System Description Table (XSDT)
//
// Reference: ACPI v6.3 Section 5.2.7 -- 5.2.8.
struct AcpiRsdt {
AcpiSdtHeader header;
// array of uint32s are placed immediately afterwards
uint32_t addr32[0];
size_t size() const { return header.length; }
static constexpr auto kSignature = AcpiSignature("RSDT");
} __PACKED;
static_assert(sizeof(AcpiRsdt) == 36);
struct AcpiXsdt {
AcpiSdtHeader header;
// array of uint64s are placed immediately afterwards
uint64_t addr64[0];
size_t size() const { return header.length; }
static constexpr auto kSignature = AcpiSignature("XSDT");
} __PACKED;
static_assert(sizeof(AcpiXsdt) == 36);
// ACPI Generic Address
//
// Reference: ACPI v6.3 Section 5.2.3.2
struct AcpiGenericAddress {
uint8_t address_space_id;
uint8_t register_bit_width;
uint8_t register_bit_offset;
uint8_t access_size;
uint64_t address;
} __PACKED;
static_assert(sizeof(AcpiGenericAddress) == 12);
#define ACPI_ADDR_SPACE_MEMORY 0
#define ACPI_ADDR_SPACE_IO 1
// Fixed ACPI Description Table
//
// Reference: ACPI v6.3 Section 5.2.9.
struct AcpiFadt {
AcpiSdtHeader header;
uint32_t firmware_ctrl;
uint32_t dsdt;
uint8_t _reserved;
uint8_t preferred_pm_profile;
uint16_t sci_int;
uint32_t smi_cmd;
uint8_t acpi_enable;
uint8_t acpi_disable;
uint8_t s4bios_req;
uint8_t pstate_cnt;
uint32_t pm1a_evt_blk;
uint32_t pm1b_evt_blk;
uint32_t pm1a_cnt_blk;
uint32_t pm1b_cnt_blk;
uint32_t pm2_cnt_blk;
uint32_t pm_tmr_blk;
uint32_t gpe0_blk;
uint32_t gpe1_blk;
uint8_t pm1_evt_len;
uint8_t pm1_cnt_len;
uint8_t pm2_cnt_len;
uint8_t pm_tmr_len;
uint8_t gpe0_blk_len;
uint8_t gpe1_blk_len;
uint8_t gpe1_base;
uint8_t cst_cnt;
uint16_t p_lvl2_lat;
uint16_t p_lvl3_lat;
uint16_t flush_size;
uint16_t flush_stride;
uint8_t duty_offset;
uint8_t duty_width;
uint8_t day_alrm;
uint8_t mon_alrm;
uint8_t century;
uint16_t iapc_boot_arch;
uint8_t _reserved2;
uint32_t flags;
AcpiGenericAddress reset_reg;
uint8_t reset_value;
uint16_t arm_boot_arch;
uint8_t fadt_minor_version;
uint64_t x_firmware_ctrl;
uint64_t x_dsdt;
AcpiGenericAddress x_pm1a_evt_blk;
AcpiGenericAddress x_pm1b_evt_blk;
AcpiGenericAddress x_pm1a_cnt_blk;
AcpiGenericAddress x_pm1b_cnt_blk;
AcpiGenericAddress x_pm2_cnt_blk;
AcpiGenericAddress x_pm_tmr_blk;
AcpiGenericAddress x_gpe0_blk;
AcpiGenericAddress x_gpe1_blk;
// Optional entries. See ACPI v6.3 Section 4.8.3.7
//
// Not included here to avoid acpi_lite from refusing to read a too-short
// struct on platforms that don't include the fields.
//
// TODO(https://fxbug.dev/42170568): Add these fields once optional entries are handled
//
// AcpiGenericAddress sleep_control_reg; // optional
// AcpiGenericAddress sleep_status_reg; // optional
// uint64_t hypervisor_vendor_identity; // optional
size_t size() const { return header.length; }
static constexpr auto kSignature = AcpiSignature("FACP");
} __PACKED;
static_assert(sizeof(AcpiFadt) == 244);
// Firmware ACPI Control Structure
//
// Reference: ACPI v6.3 Section 5.2.10.
struct AcpiFacs {
AcpiSignature sig;
uint32_t length;
uint32_t hardware_signature;
uint32_t firmware_waking_vector;
uint32_t global_lock;
uint32_t flags;
uint64_t x_firmware_waking_vector;
uint8_t version;
uint8_t _reserved[3];
uint32_t ospm_flags;
uint8_t _reserved2[24];
size_t size() const { return length; }
static constexpr auto kSignature = AcpiSignature("FACS");
} __PACKED;
static_assert(sizeof(AcpiFacs) == 64);
// Multiple APIC Description Table
//
// The table is followed by interrupt control structures, each with
// a "AcpiSubTableHeader" header.
//
// Reference: ACPI v6.3 5.2.12.
struct AcpiMadtTable {
AcpiSdtHeader header;
uint32_t local_int_controller_address;
uint32_t flags;
size_t size() const { return header.length; }
static constexpr auto kSignature = AcpiSignature("APIC");
} __PACKED;
static_assert(sizeof(AcpiMadtTable) == 44);
struct AcpiSubTableHeader {
uint8_t type;
uint8_t length;
size_t size() const { return length; }
} __PACKED;
static_assert(sizeof(AcpiSubTableHeader) == 2);
// High Precision Event Timer Table
//
// Reference: IA-PC HPET (High Precision Event Timers) v1.0a, Section 3.2.4.
struct AcpiHpetTable {
AcpiSdtHeader header;
uint32_t id;
AcpiGenericAddress address;
uint8_t sequence;
uint16_t minimum_tick;
uint8_t flags;
size_t size() const { return header.length; }
static constexpr auto kSignature = AcpiSignature("HPET");
} __PACKED;
static_assert(sizeof(AcpiHpetTable) == 56);
// SRAT table and descriptors.
//
// Reference: ACPI v6.3 Section 5.2.16.
struct AcpiSratTable {
AcpiSdtHeader header;
uint32_t _reserved; // should be 1
uint64_t _reserved2;
size_t size() const { return header.length; }
static constexpr auto kSignature = AcpiSignature("SRAT");
} __PACKED;
static_assert(sizeof(AcpiSratTable) == 48);
// Type 0: processor local apic/sapic affinity structure
//
// Reference: ACPI v6.3 Section 5.2.16.1.
#define ACPI_SRAT_TYPE_PROCESSOR_AFFINITY 0
struct AcpiSratProcessorAffinityEntry {
AcpiSubTableHeader header;
uint8_t proximity_domain_low;
uint8_t apic_id;
uint32_t flags;
uint8_t sapic_eid;
uint8_t proximity_domain_high[3];
uint32_t clock_domain;
uint32_t proximity_domain() const;
size_t size() const { return header.length; }
} __PACKED;
static_assert(sizeof(AcpiSratProcessorAffinityEntry) == 16);
#define ACPI_SRAT_FLAG_ENABLED 1
// Type 1: memory affinity structure
//
// Reference: ACPI v6.3 Section 5.2.16.2.
#define ACPI_SRAT_TYPE_MEMORY_AFFINITY 1
struct AcpiSratMemoryAffinityEntry {
AcpiSubTableHeader header;
uint32_t proximity_domain;
uint16_t _reserved;
uint32_t base_address_low;
uint32_t base_address_high;
uint32_t length_low;
uint32_t length_high;
uint32_t _reserved2;
uint32_t flags;
uint32_t _reserved3;
uint32_t _reserved4;
size_t size() const { return header.length; }
} __PACKED;
static_assert(sizeof(AcpiSratMemoryAffinityEntry) == 40);
// Type 2: processor x2apic affinity structure
//
// Reference: ACPI v6.3 Section 5.2.16.3.
#define ACPI_SRAT_TYPE_PROCESSOR_X2APIC_AFFINITY 2
struct AcpiSratProcessorX2ApicAffinityEntry {
AcpiSubTableHeader header;
uint16_t _reserved;
uint32_t proximity_domain;
uint32_t x2apic_id;
uint32_t flags;
uint32_t clock_domain;
uint32_t _reserved2;
size_t size() const { return header.length; }
} __PACKED;
static_assert(sizeof(AcpiSratProcessorX2ApicAffinityEntry) == 24);
// Multiple APIC Description Table (MADT) entries.
// MADT entry type 0: Processor Local APIC (ACPI v6.3 Section 5.2.12.2)
#define ACPI_MADT_TYPE_LOCAL_APIC 0
struct AcpiMadtLocalApicEntry {
AcpiSubTableHeader header;
uint8_t processor_id;
uint8_t apic_id;
uint32_t flags;
size_t size() const { return header.length; }
} __PACKED;
static_assert(sizeof(AcpiMadtLocalApicEntry) == 8);
#define ACPI_MADT_FLAG_ENABLED 0x1
// MADT entry type 1: I/O APIC (ACPI v6.3 Section 5.2.12.3)
#define ACPI_MADT_TYPE_IO_APIC 1
struct AcpiMadtIoApicEntry {
AcpiSubTableHeader header;
uint8_t io_apic_id;
uint8_t reserved;
uint32_t io_apic_address;
uint32_t global_system_interrupt_base;
size_t size() const { return header.length; }
} __PACKED;
static_assert(sizeof(AcpiMadtIoApicEntry) == 12);
// MADT entry type 2: Interrupt Source Override (ACPI v6.3 Section 5.2.12.5)
#define ACPI_MADT_TYPE_INT_SOURCE_OVERRIDE 2
struct AcpiMadtIntSourceOverrideEntry {
AcpiSubTableHeader header;
uint8_t bus;
uint8_t source;
uint32_t global_sys_interrupt;
uint16_t flags;
size_t size() const { return header.length; }
} __PACKED;
static_assert(sizeof(AcpiMadtIntSourceOverrideEntry) == 10);
#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
// DBG2 table
struct AcpiDbg2Table {
AcpiSdtHeader header;
uint32_t offset;
uint32_t num_entries;
size_t size() const { return header.length; }
static constexpr auto kSignature = AcpiSignature("DBG2");
} __PACKED;
static_assert(sizeof(AcpiDbg2Table) == 44);
struct AcpiDbg2Device {
uint8_t revision;
uint16_t length;
uint8_t register_count;
uint16_t namepath_length;
uint16_t namepath_offset;
uint16_t oem_data_length;
uint16_t oem_data_offset;
uint16_t port_type;
uint16_t port_subtype;
uint16_t reserved;
uint16_t base_address_offset;
uint16_t address_size_offset;
size_t size() const { return length; }
} __PACKED;
static_assert(sizeof(AcpiDbg2Device) == 22);
// debug port types
#define ACPI_DBG2_TYPE_SERIAL_PORT 0x8000
#define ACPI_DBG2_TYPE_1394_PORT 0x8001
#define ACPI_DBG2_TYPE_USB_PORT 0x8002
#define ACPI_DBG2_TYPE_NET_PORT 0x8003
// debug port subtypes
#define ACPI_DBG2_SUBTYPE_16550_COMPATIBLE 0x0000
#define ACPI_DBG2_SUBTYPE_16550_SUBSET 0x0001
#define ACPI_DBG2_SUBTYPE_1394_STANDARD 0x0000
#define ACPI_DBG2_SUBTYPE_USB_XHCI 0x0000
#define ACPI_DBG2_SUBTYPE_USB_EHCI 0x0001
} // namespace acpi_lite
#endif // ZIRCON_KERNEL_LIB_ACPI_LITE_INCLUDE_LIB_ACPI_LITE_STRUCTURES_H_