blob: a0cc517ca8bca63a5a5a406efd07ccccd68cec64 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
library fuchsia.hardware.acpi;
using zx;
using fuchsia.mem;
/// ACPI Object Types.
/// See ACPI spec v6.4, 19.6.96 - ObjectType (Get Object Type).
type ObjectType = flexible enum {
ANY = 0;
INTEGER = 1;
STRING = 2;
BUFFER = 3;
PACKAGE = 4;
FIELD_UNIT = 5;
DEVICE = 6;
EVENT = 7;
METHOD = 8;
MUTEX = 9;
OPERATION_REGION = 10;
POWER_RESOURCE = 11;
THERMAL_ZONE = 13;
BUFFER_FIELD = 14;
DEBUG_OBJECT = 16;
};
/// ACPI status codes.
// These are identical to the ACPICA errors at
// //third_party/acpica/include/acpica/acexcep.h.
type Status = flexible enum {
/// Success.
OK = 0;
/// Unknown error occurred.
ERROR = 0x01;
/// Couldn't find ACPI tables.
NO_ACPI_TABLES = 0x02;
/// No namespace loaded.
NO_NAMESPACE = 0x03;
/// Ran out of memory.
NO_MEMORY = 0x04;
/// Requested entity not found.
NOT_FOUND = 0x05;
/// Required entity does not exist.
NOT_EXIST = 0x06;
/// Entity already exists.
ALREADY_EXISTS = 0x07;
/// Incorrect object type.
TYPE = 0x08;
/// Required object is missing.
NULL_OBJECT = 0x09;
/// Requested object does not exist.
NULL_ENTRY = 0x0a;
/// Provided buffer was too small.
BUFFER_OVERFLOW = 0x0b;
/// Internal stack overflow.
STACK_OVERFLOW = 0x0c;
/// Internal stack underflow.
STACK_UNDERFLOW = 0x0d;
/// Not implemented.
NOT_IMPLEMENTED = 0x0e;
/// Not supported.
NOT_SUPPORTED = 0x0f;
/// A predefined limit was exceeded.
LIMIT = 0x10;
/// A timeout expired.
TIME = 0x11;
/// A mutex was acquired in improper order.
ACQUIRE_DEADLOCK = 0x12;
/// A mutex was released in improper order.
RELEASE_DEADLOCK = 0x13;
/// Attempted to release a mutex without acquiring it.
NOT_ACQUIRED = 0x14;
/// Attempted to acquire a mutex twice.
ALREADY_ACQUIRED = 0x15;
/// Hardware did not respond to an I/O operation.
NO_HARDWARE_RESPONSE = 0x16;
/// There is no global lock.
NO_GLOBAL_LOCK = 0x17;
/// A control method was aborted.
ABORT_METHOD = 0x18;
/// Attempt was made to install a handler that is already installed.
SAME_HANDLER = 0x19;
/// A handler for this operation is not installed.
NO_HANDLER = 0x1a;
/// There are no more Owner IDs available for ACPI tables or control methods.
OWNER_ID_LIMIT = 0x1b;
/// The interface is not part of the current subsystem configuration.
NOT_CONFIGURED = 0x1c;
/// Permission denied for the requested operation.
ACCESS = 0x1d;
/// An I/O error occurred.
IO_ERROR = 0x1e;
/// Overflow during string-to-integer conversion.
NUMERIC_OVERFLOW = 0x1f;
/// Overflow during ASCII hex-to-binary conversion.
HEX_OVERFLOW = 0x20;
/// Overflow during ASCII decimal-to-binary conversion.
DECIMAL_OVERFLOW = 0x21;
/// Overflow during ASCII octal-to-binary conversion.
OCTAL_OVERFLOW = 0x22;
/// Reached the end of the table.
END_OF_TABLE = 0x23;
/// Invalid paramter supplied.
BAD_PARAMETER = 0x1001;
/// Invalid character in a name.
BAD_CHARACTER = 0x1002;
/// Invalid character in a pathname.
BAD_PATHNAME = 0x1003;
/// Package or buffer contained incorrect data.
BAD_DATA = 0x1004;
/// Invalid character in a hex constant.
BAD_HEX_CONSTANT = 0x1005;
/// Invalid character in an octal constant.
BAD_OCTAL_CONSTANT = 0x1006;
/// Invalid character in a decimal constant.
BAD_DECIMAL_CONSTANT = 0x1007;
/// Too few arguments passed to a method.
MISSING_ARGUMENTS = 0x1008;
/// Illegal null I/O addres.
BAD_ADDRESS = 0x1009;
/// Bad ACPI table signature.
BAD_TABLE_SIGNATURE = 0x2001;
/// Invalid field in ACPI table header.
BAD_TABLE_HEADER = 0x2002;
/// ACPI table checksum is incorrect.
BAD_TABLE_CHECKSUM = 0x2003;
/// Invalid value found in an ACPI table.
BAD_TABLE_VALUE = 0x2004;
/// The FADT or FACS has an improper length.
INVALID_TABLE_LENGTH = 0x2005;
/// Invalid AML opcode.
AML_BAD_OPCODE = 0x3001;
/// Missing operand.
AML_NO_OPERAND = 0x3002;
/// Operand has incorrect type.
AML_OPERAND_TYPE = 0x3003;
/// Operand has inappropriate or invalid value.
AML_OPERAND_VALUE = 0x3004;
/// Method tried to use uninitialized local variable.
AML_UNINITIALIZED_LOCAL = 0x3005;
/// Method tried to use uninitialized argument.
AML_UNINITIALIZED_ARG = 0x3006;
/// Method tried to use an empty package element.
AML_UNINITIALIZED_ELEMENT = 0x3007;
/// Overflow during numeric conversion.
AML_NUMERIC_OVERFLOW = 0x3008;
/// Tried to access beyond the end of an Operation Region.
AML_REGION_LIMIT = 0x3009;
/// Tried to access beyond the end of a buffer.
AML_BUFFER_LIMIT = 0x300a;
/// Tried to access beyond the end of a package.
AML_PACKAGE_LIMIT = 0x300b;
/// Tried to divide by zero.
AML_DIVIDE_BY_ZERO = 0x300c;
/// ACPI name contains invalid characters.
AML_BAD_NAME = 0x300d;
/// Couldn't resolve a reference.
AML_NAME_NOT_FOUND = 0x300e;
/// Internal error within the AML interpreter.
AML_INTERNAL = 0x300f;
/// Operation Region SpaceID is invalid.
AML_INVALID_SPACE_ID = 0x3010;
/// String is longer than 200 characters.
AML_STRING_LIMIT = 0x3011;
/// Method did not return a required value.
AML_NO_RETURN_VALUE = 0x3012;
/// Method reached maximum reentrancy limit.
AML_METHOD_LIMIT = 0x3013;
/// A thread tried to release a mutex it doesn't own.
AML_NOT_OWNER = 0x3014;
/// Mutex SyncLevel release mismatch.
AML_MUTEX_ORDER = 0x3015;
/// Attempt to release mutex that was not previously acquired.
AML_MUTEX_NOT_ACQUIRED = 0x3016;
/// Invalid resource type in resource list.
AML_INVALID_RESOURCE_TYPE = 0x3017;
/// Invalid Argx/Localx (x too large).
AML_INVALID_INDEX = 0x3018;
/// Bank value or Index value beyond the range of a register.
AML_REGISTER_LIMIT = 0x3019;
/// Break or Continue without a While.
AML_NO_WHILE = 0x301a;
/// Unaligned memory transfer on platform that doesn't support this.
AML_ALIGNMENT = 0x301b;
/// No End Tag in a resource list.
AML_NO_RESOURCE_END_TAG = 0x301c;
/// Invalid value in a resource.
AML_BAD_RESOURCE_VALUE = 0x301d;
/// Two references refer to each other.
AML_CIRCULAR_REFERENCE = 0x301e;
/// The length of a resource descriptor in the AML is incorrect.
AML_BAD_RESOURCE_LENGTH = 0x301f;
/// A memory, I/O, or PCI configuration address is invalid.
AML_ILLEGAL_ADDRESS = 0x3020;
/// An AML While loop exceeded the maximum execution time.
AML_LOOP_TIMEOUT = 0x3021;
/// A namespace node is uninitialized or unresolved.
AML_UNINITIALIZED_NODE = 0x3022;
/// A target operand of an incorrect type was encountered.
AML_TARGET_TYPE = 0x3023;
/// Violation of a fixed ACPI protocol.
AML_PROTOCOL = 0x3024;
/// The length of the buffer is invalid/incorrect.
AML_BUFFER_LENGTH = 0x3025;
};
/// Type that should be returned by |Device.EvaluateObject|.
type EvaluateObjectMode = flexible enum {
/// Return an Object.
PLAIN_OBJECT = 0;
/// Treat the returned buffer as a resource template. Parse it and return
/// any resources that are found.
PARSE_RESOURCES = 1;
};
/// A handle to an arbitrary path in the ACPI tree.
type Handle = struct {
/// Type of the object this handle refers to.
object_type ObjectType;
/// Relative path to the object this handle refers to.
path string:MAX;
};
/// Represents a Processor declaration.
type Processor = struct {
id uint32;
pblk_address uint64;
pblk_length uint32;
};
/// Represents a PowerResource.
type PowerResource = struct {
/// Deepest system sleep level that must be maintained to keep this resource
/// on.
system_level uint32;
/// Resource order that this power resource belongs to.
resource_order uint32;
};
// TODO(https://fxbug.dev/42110612): This is a hack to work around the fact that FIDL
// doesn't like unions with recursive types.
type ObjectList = struct {
value vector<Object>:<MAX, optional>;
};
/// Represents an object passed to or returned by
/// fuchsia.hardware.acpi/Device.EvaluateMethod().
type Object = flexible union {
1: integer_val uint64;
2: string_val string:MAX;
3: buffer_val vector<uint8>:MAX;
4: package_val ObjectList;
5: reference_val Handle;
6: processor_val Processor;
7: power_resource_val PowerResource;
};
/// Represents a resource.
type Resource = flexible resource union {
/// A region of physical memory.
1: mmio fuchsia.mem.Range;
/// An interrupt.
2: irq zx.Handle:INTERRUPT;
/// An I/O port.
3: pio zx.Handle:RESOURCE;
};
/// Result of evaluating an object, returned by Device.EvaluateObject().
type EncodedObject = flexible resource union {
/// Always returned for EvaluateObjectMode.PLAIN_OBJECT.
1: object Object;
/// Always returned for EvaluateObjectMode.PARSE_RESOURCES.
2: resources vector<Resource>:MAX;
};
/// Maximum number of arguments that can be passed to a method.
/// ACPI Spec 6.4, Section 19.6.84 "Method (Declare Control Method)".
const MAX_METHOD_ARG uint32 = 7;
/// Provides access to an ACPI device.
@discoverable
closed protocol Device {
/// If ACPI has determined this device is a bus, returns the bus ID.
/// Errors:
/// * ZX_ERR_BAD_STATE - the device is not a bus as far as ACPI is aware.
strict GetBusId() -> (struct {
/// Unique ID of this bus on the system.
/// This ID is not necessarily constant between boots of the same system,
/// but it remains stable for a single boot.
bus_id uint32;
}) error zx.Status;
/// Get the interrupt at `index` for this device.
/// Errors:
/// * ZX_ERR_OUT_OF_RANGE - `index` is out of range.
/// * ZX_ERR_INVALID_ARGS - the interrupt type described by ACPI is unrecognised.
/// * ZX_ERR_INTERNAL - an internal error occured (e.g. failure to evaluate ACPI tables).
strict MapInterrupt(struct {
index uint64;
}) -> (resource struct {
irq zx.Handle:INTERRUPT;
}) error zx.Status;
/// Get the I/O port at `index` for this device.
/// Errors:
/// * ZX_ERR_OUT_OF_RANGE - `index` is out of range.
/// * ZX_ERR_INTERNAL - an internal error occured (e.g. failure to evaluate ACPI tables).
strict GetPio(struct {
index uint32;
}) -> (resource struct {
pio zx.Handle:RESOURCE;
}) error zx.Status;
/// Get the MMIO region at `index` for this device.
/// Errors:
/// * ZX_ERR_OUT_OF_RANGE - `index` is out of range.
/// * ZX_ERR_INTERNAL - an internal error occured (e.g. failure to evaluate ACPI tables).
/// * ZX_ERR_INVALID_ARGS - the MMIO region described by ACPI is not page-aligned.
strict GetMmio(struct {
index uint32;
}) -> (resource struct {
mmio fuchsia.mem.Range;
}) error zx.Status;
/// Get the BTI at `index` for this device.
///
/// This operation is not supported on devices that exist on another bus (e.g. PCI) --
/// they should use their bus's GetBti() equivalent to access a BTI.
/// Errors:
/// * ZX_ERR_NOT_SUPPORTED - the device is not a pure ACPI device.
/// * ZX_ERR_OUT_OF_RANGE - `index` is out of range for the device.
strict GetBti(struct {
index uint32;
}) -> (resource struct {
bti zx.Handle:BTI;
}) error zx.Status;
/// Evaluate the object at the given |path|, relative to this device, with |parameters| as
/// arguments.
/// |mode| determines how the return value is treated, see
/// |fuchsia.hardware.acpi/EvaluateObjectMode|.
/// Paths cannot be absolute, and must only refer to children of this
/// device.
/// |result| is the result of the evaluation. See |fuchsia.hardware.acpi/EncodedObject| for more
/// information.
/// Errors:
/// * ACCESS - |path| does not refer to a child of this device.
/// * AML_* - internal errors while evaluating the AML bytecode.
/// * BAD_CHARACTER - an invalid character was found in the path.
/// * BAD_PATHNAME - the path contained at least one ill-formated entry.
/// * ERROR - An internal error occurred.
/// * NOT_FOUND - There is no object at the specified path.
/// * NOT_IMPLEMENTED - An unsupported |mode| or |parameters| was supplied, or evaluation
/// returned an unsupported Object type.
/// * TYPE - The object is of a type that cannot be evaluated.
strict EvaluateObject(struct {
path string:MAX;
mode EvaluateObjectMode;
parameters vector<Object>:<MAX_METHOD_ARG, optional>;
}) -> (resource struct {
result EncodedObject:<optional>;
}) error Status;
/// Install a Device Object Notification handler for the given notification
/// type. A device can only have a single notification handler at a time.
/// Errors:
/// * BAD_PARAMETER - if "mode" is invalid.
/// * ALREADY_EXISTS - if a handler is already installed.
strict InstallNotifyHandler(resource struct {
mode NotificationMode;
handler client_end:NotifyHandler;
}) -> () error Status;
/// Remove a Device Object Notification handler. Returns AE_OK if either the handler was
/// successfully removed, or if the device has no handler. Otherwise returns failure.
strict RemoveNotifyHandler() -> () error Status;
/// Acquire the ACPI global lock. This is only permitted for devices which
/// have a _GLK entry in their namespace. See ACPI v6.4, Section 6.5.7 "_GLK
/// (Global Lock)".
/// This method will not return until the global lock has been acquired.
/// Errors:
/// * ACCESS - if "_GLK" is not present, or if "_GLK" does not evaluate to 1.
strict AcquireGlobalLock() -> (resource struct {
handle client_end:GlobalLock;
}) error Status;
/// Install an address space handler for this device.
/// Errors:
/// * ALREADY_EXISTS - if a handler is already installed.
/// * NOT_SUPPORTED - the AddressSpace supplied is not supported.
strict InstallAddressSpaceHandler(resource struct {
space AddressSpace;
handler client_end:AddressSpaceHandler;
}) -> () error Status;
/// Set a device to be able to wake the system from suspend. The device must have a _PRW
/// (Power Resource for Wake) method. This method should be called from the driver suspend
/// hook, using the |requested_state| provided by the driver framework. If the device is unable
/// to wake the system from the requested sleep state, then the device will not be set as a
/// wake source.
/// Errors:
/// NOT_SUPPORTED - requested sleep state is deeper than the deepest sleep that the device can
/// wake the system from.
/// BAD_DATA - unable to get wake GPE information.
/// BAD_PARAMETER - could not get GPE information.
/// TYPE - GPE is not marked as a wake GPE.
/// NOT_EXIST - GPE register could not be found.
strict SetWakeDevice(struct {
requested_state uint8;
}) -> () error Status;
};
service Service {
device client_end:Device;
};