acpica_bindings/interface/
status.rs

1//! The [`AcpiError`] error type
2
3// Adapted from source/include/acexcep.h
4
5use core::fmt::Display;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[repr(transparent)]
9pub(crate) struct AcpiStatus(u32);
10
11/// An error which ACPICA produced, or which can be given to ACPICA
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13#[repr(u32)]
14#[non_exhaustive]
15pub enum AcpiError {
16    /*
17     * Environmental exceptions
18     */
19    /// Unspecified error
20    Error = 0x0001 | AcpiError::AE_CODE_ENVIRONMENTAL,
21    /// ACPI tables could not be found
22    NoAcpiTables = 0x0002 | AcpiError::AE_CODE_ENVIRONMENTAL,
23    /// A namespace has not been loaded
24    NoNamespace = 0x0003 | AcpiError::AE_CODE_ENVIRONMENTAL,
25    /// Insufficient dynamic memory
26    NoMemory = 0x0004 | AcpiError::AE_CODE_ENVIRONMENTAL,
27    /// A requested entity is not found
28    NotFound = 0x0005 | AcpiError::AE_CODE_ENVIRONMENTAL,
29    /// A required entity does not exist
30    NotExist = 0x0006 | AcpiError::AE_CODE_ENVIRONMENTAL,
31    /// An entity already exists
32    AlreadyExists = 0x0007 | AcpiError::AE_CODE_ENVIRONMENTAL,
33    /// The object type is incorrect
34    Type = 0x0008 | AcpiError::AE_CODE_ENVIRONMENTAL,
35    /// A required object was missing
36    NullObject = 0x0009 | AcpiError::AE_CODE_ENVIRONMENTAL,
37    /// The requested object does not exist
38    NullEntry = 0x000A | AcpiError::AE_CODE_ENVIRONMENTAL,
39    /// The buffer provided is too small
40    BufferOverflow = 0x000B | AcpiError::AE_CODE_ENVIRONMENTAL,
41    /// An internal stack overflowed
42    StackOverflow = 0x000C | AcpiError::AE_CODE_ENVIRONMENTAL,
43    /// An internal stack underflowed
44    StackUnderflow = 0x000D | AcpiError::AE_CODE_ENVIRONMENTAL,
45    /// The feature is not implemented
46    NotImplemented = 0x000E | AcpiError::AE_CODE_ENVIRONMENTAL,
47    /// The feature is not supported
48    Support = 0x000F | AcpiError::AE_CODE_ENVIRONMENTAL,
49    /// A predefined limit was exceeded
50    Limit = 0x0010 | AcpiError::AE_CODE_ENVIRONMENTAL,
51    /// A time limit or timeout expired
52    Time = 0x0011 | AcpiError::AE_CODE_ENVIRONMENTAL,
53    /// Internal error, attempt was made to acquire a mutex in improper order
54    AcquireDeadlock = 0x0012 | AcpiError::AE_CODE_ENVIRONMENTAL,
55    /// Internal error, attempt was made to release a mutex in improper order
56    ReleaseDeadlock = 0x0013 | AcpiError::AE_CODE_ENVIRONMENTAL,
57    /// An attempt to release a mutex or Global Lock without a previous acquire
58    NotAcquired = 0x0014 | AcpiError::AE_CODE_ENVIRONMENTAL,
59    /// Internal error, attempt was made to acquire a mutex twice
60    AlreadyAcquired = 0x0015 | AcpiError::AE_CODE_ENVIRONMENTAL,
61    /// Hardware did not respond after an I/O operation
62    NoHardwareResponse = 0x0016 | AcpiError::AE_CODE_ENVIRONMENTAL,
63    /// There is no FACS Global Lock
64    NoGlobalLock = 0x0017 | AcpiError::AE_CODE_ENVIRONMENTAL,
65    /// A control method was aborted
66    AbortMethod = 0x0018 | AcpiError::AE_CODE_ENVIRONMENTAL,
67    /// Attempt was made to install the same handler that is already installed
68    SameHandler = 0x0019 | AcpiError::AE_CODE_ENVIRONMENTAL,
69    /// A handler for the operation is not installed
70    NoHandler = 0x001A | AcpiError::AE_CODE_ENVIRONMENTAL,
71    /// There are no more Owner IDs available for ACPI tables or control methods
72    OwnerIdLimit = 0x001B | AcpiError::AE_CODE_ENVIRONMENTAL,
73    /// The interface is not part of the current subsystem configuration
74    NotConfigured = 0x001C | AcpiError::AE_CODE_ENVIRONMENTAL,
75    /// Permission denied for the requested operation
76    Access = 0x001D | AcpiError::AE_CODE_ENVIRONMENTAL,
77    /// An I/O error occurred
78    IoError = 0x001E | AcpiError::AE_CODE_ENVIRONMENTAL,
79    /// Overflow during string-to-integer conversion
80    NumericOverflow = 0x001F | AcpiError::AE_CODE_ENVIRONMENTAL,
81    /// Overflow during ASCII hex-to-binary conversion
82    HexOverflow = 0x0020 | AcpiError::AE_CODE_ENVIRONMENTAL,
83    /// Overflow during ASCII decimal-to-binary conversion
84    DecimalOverflow = 0x0021 | AcpiError::AE_CODE_ENVIRONMENTAL,
85    /// Overflow during ASCII octal-to-binary conversion
86    OctalOverflow = 0x0022 | AcpiError::AE_CODE_ENVIRONMENTAL,
87    /// Reached the end of table
88    EndOfTable = 0x0023 | AcpiError::AE_CODE_ENVIRONMENTAL,
89
90    /*
91     * Programmer exceptions
92     */
93    /// A parameter is out of range or invalid
94    BadParameter = 0x0001 | AcpiError::AE_CODE_PROGRAMMER,
95    /// An invalid character was found in a name
96    BadCharacter = 0x0002 | AcpiError::AE_CODE_PROGRAMMER,
97    /// An invalid character was found in a pathname
98    BadPathname = 0x0003 | AcpiError::AE_CODE_PROGRAMMER,
99    /// A package or buffer contained incorrect data
100    BadData = 0x0004 | AcpiError::AE_CODE_PROGRAMMER,
101    /// Invalid character in a Hex constant
102    BadHexConstant = 0x0005 | AcpiError::AE_CODE_PROGRAMMER,
103    /// Invalid character in an Octal constant
104    BadOctalConstant = 0x0006 | AcpiError::AE_CODE_PROGRAMMER,
105    /// Invalid character in a Decimal constant
106    BadDecimalConstant = 0x0007 | AcpiError::AE_CODE_PROGRAMMER,
107    /// Too few arguments were passed to a control method
108    MissingArguments = 0x0008 | AcpiError::AE_CODE_PROGRAMMER,
109    /// An illegal null I/O address
110    BadAddress = 0x0009 | AcpiError::AE_CODE_PROGRAMMER,
111
112    /*
113     * Acpi table exceptions
114     */
115    /// An ACPI table has an invalid signature
116    BadSignature = 0x0001 | AcpiError::AE_CODE_ACPI_TABLES,
117    /// Invalid field in an ACPI table header
118    BadHeader = 0x0002 | AcpiError::AE_CODE_ACPI_TABLES,
119    /// An ACPI table checksum is not correct
120    BadChecksum = 0x0003 | AcpiError::AE_CODE_ACPI_TABLES,
121    /// An invalid value was found in a table
122    BadValue = 0x0004 | AcpiError::AE_CODE_ACPI_TABLES,
123    /// The FADT or FACS has improper length
124    InvalidTableLength = 0x0005 | AcpiError::AE_CODE_ACPI_TABLES,
125
126    /*
127     * AML exceptions. These are caused by problems with
128     * the actual AML byte stream
129     */
130    /// Invalid AML opcode encountered
131    AmlBadOpcode = 0x0001 | AcpiError::AE_CODE_AML,
132    /// A required operand is missing
133    AmlNoOperand = 0x0002 | AcpiError::AE_CODE_AML,
134    /// An operand of an incorrect type was encountered
135    AmlOperandType = 0x0003 | AcpiError::AE_CODE_AML,
136    /// The operand had an inappropriate or invalid value
137    AmlOperandValue = 0x0004 | AcpiError::AE_CODE_AML,
138    /// Method tried to use an uninitialized local variable
139    AmlUninitializedLocal = 0x0005 | AcpiError::AE_CODE_AML,
140    /// Method tried to use an uninitialized argument
141    AmlUninitializedArg = 0x0006 | AcpiError::AE_CODE_AML,
142    /// Method tried to use an empty package element
143    AmlUninitializedElement = 0x0007 | AcpiError::AE_CODE_AML,
144    /// Overflow during BCD conversion or other
145    AmlNumericOverflow = 0x0008 | AcpiError::AE_CODE_AML,
146    /// Tried to access beyond the end of an Operation Region
147    AmlRegionLimit = 0x0009 | AcpiError::AE_CODE_AML,
148    /// Tried to access beyond the end of a buffer
149    AmlBufferLimit = 0x000A | AcpiError::AE_CODE_AML,
150    /// Tried to access beyond the end of a package
151    AmlPackageLimit = 0x000B | AcpiError::AE_CODE_AML,
152    /// During execution of AML Divide operator
153    AmlDivideByZero = 0x000C | AcpiError::AE_CODE_AML,
154    /// An ACPI name contains invalid character(s)
155    AmlBadName = 0x000D | AcpiError::AE_CODE_AML,
156    /// Could not resolve a named reference
157    AmlNameNotFound = 0x000E | AcpiError::AE_CODE_AML,
158    /// An internal error within the interpreter
159    AmlInternal = 0x000F | AcpiError::AE_CODE_AML,
160    /// An Operation Region SpaceID is invalid
161    AmlInvalidSpaceId = 0x0010 | AcpiError::AE_CODE_AML,
162    /// String is longer than 200 characters
163    AmlStringLimit = 0x0011 | AcpiError::AE_CODE_AML,
164    /// A method did not return a required value
165    AmlNoReturnValue = 0x0012 | AcpiError::AE_CODE_AML,
166    /// A control method reached the maximum reentrancy limit of 255
167    AmlMethodLimit = 0x0013 | AcpiError::AE_CODE_AML,
168    /// A thread tried to release a mutex that it does not own
169    AmlNotOwner = 0x0014 | AcpiError::AE_CODE_AML,
170    /// Mutex SyncLevel release mismatch
171    AmlMutexOrder = 0x0015 | AcpiError::AE_CODE_AML,
172    /// Attempt to release a mutex that was not previously acquired
173    AmlMutexNotAcquired = 0x0016 | AcpiError::AE_CODE_AML,
174    /// Invalid resource type in resource list
175    AmlInvalidResourceType = 0x0017 | AcpiError::AE_CODE_AML,
176    /// Invalid Argx or Localx (x too large)
177    AmlInvalidIndex = 0x0018 | AcpiError::AE_CODE_AML,
178    /// Bank value or Index value beyond range of register
179    AmlRegisterLimit = 0x0019 | AcpiError::AE_CODE_AML,
180    /// Break or Continue without a While
181    AmlNoWhile = 0x001A | AcpiError::AE_CODE_AML,
182    /// Non-aligned memory transfer on platform that does not support this
183    AmlAlignment = 0x001B | AcpiError::AE_CODE_AML,
184    /// No End Tag in a resource list
185    AmlNoResourceEndTag = 0x001C | AcpiError::AE_CODE_AML,
186    /// Invalid value of a resource element
187    AmlBadResourceValue = 0x001D | AcpiError::AE_CODE_AML,
188    /// Two references refer to each other
189    AmlCircularReference = 0x001E | AcpiError::AE_CODE_AML,
190    /// The length of a Resource Descriptor in the AML is incorrect
191    AmlBadResourceLength = 0x001F | AcpiError::AE_CODE_AML,
192    /// A memory, I/O, or PCI configuration address is invalid
193    AmlIllegalAddress = 0x0020 | AcpiError::AE_CODE_AML,
194    /// An AML While loop exceeded the maximum execution time
195    AmlLoopTimeout = 0x0021 | AcpiError::AE_CODE_AML,
196    /// A namespace node is uninitialized or unresolved
197    AmlUninitializedNode = 0x0022 | AcpiError::AE_CODE_AML,
198    /// A target operand of an incorrect type was encountered
199    AmlTargetType = 0x0023 | AcpiError::AE_CODE_AML,
200    /// Violation of a fixed ACPI protocol
201    AmlProtocol = 0x0024 | AcpiError::AE_CODE_AML,
202    /// The length of the buffer is invalid/incorrect
203    AmlBufferLength = 0x0025 | AcpiError::AE_CODE_AML,
204
205    /*
206     * Internal exceptions used for control
207     */
208    /// A Method returned a value
209    ControlReturnValue = 0x0001 | AcpiError::AE_CODE_CONTROL,
210    /// Method is calling another method
211    ControlPending = 0x0002 | AcpiError::AE_CODE_CONTROL,
212    /// Terminate the executing method
213    ControlTerminate = 0x0003 | AcpiError::AE_CODE_CONTROL,
214    /// An If or While predicate result
215    ControlTrue = 0x0004 | AcpiError::AE_CODE_CONTROL,
216    /// An If or While predicate result
217    ControlFalse = 0x0005 | AcpiError::AE_CODE_CONTROL,
218    /// Maximum search depth has been reached
219    ControlDepth = 0x0006 | AcpiError::AE_CODE_CONTROL,
220    /// An If or While predicate is false
221    ControlEnd = 0x0007 | AcpiError::AE_CODE_CONTROL,
222    /// Transfer control to called method
223    ControlTransfer = 0x0008 | AcpiError::AE_CODE_CONTROL,
224    /// A Break has been executed
225    ControlBreak = 0x0009 | AcpiError::AE_CODE_CONTROL,
226    /// A Continue has been executed
227    ControlContinue = 0x000A | AcpiError::AE_CODE_CONTROL,
228    /// Used to skip over bad opcodes
229    ControlParseContinue = 0x000B | AcpiError::AE_CODE_CONTROL,
230    /// Used to implement AML While loops
231    ControlParsePending = 0x000C | AcpiError::AE_CODE_CONTROL,
232
233    /// Unknown error
234    Unknown,
235}
236
237impl AcpiError {
238    const AE_CODE_ENVIRONMENTAL: u32 = 0x0000;
239    const AE_CODE_PROGRAMMER: u32 = 0x1000;
240    const AE_CODE_ACPI_TABLES: u32 = 0x2000;
241    const AE_CODE_AML: u32 = 0x3000;
242    const AE_CODE_CONTROL: u32 = 0x4000;
243    const AE_CODE_MASK: u32 = 0xF000;
244}
245
246/// A general type of [`AcpiError`]
247#[derive(Debug, Clone, Copy, PartialEq, Eq)]
248#[non_exhaustive]
249pub enum AcpiErrorClass {
250    /// The error was either internal to ACPICA or was caused by an error in the execution environment or hardware
251    Environmental,
252    /// The error was caused by a software bug
253    Programmer,
254    /// An ACPI table was invalid
255    AcpiTables,
256    /// An error occurred while parsing or executing AML code
257    Aml,
258    /// Internal errors used for control flow within ACPICA
259    Control,
260    /// The error type was unknown to the rust bindings to ACPICA
261    Unknown,
262}
263
264impl AcpiError {
265    /// Gets the general type of error
266    #[must_use]
267    pub const fn class(&self) -> AcpiErrorClass {
268        if let Self::Unknown = self {
269            return AcpiErrorClass::Unknown;
270        }
271
272        match *self as u32 & Self::AE_CODE_MASK {
273            _e @ Self::AE_CODE_ENVIRONMENTAL => AcpiErrorClass::Environmental,
274            _e @ Self::AE_CODE_PROGRAMMER => AcpiErrorClass::Programmer,
275            _e @ Self::AE_CODE_ACPI_TABLES => AcpiErrorClass::AcpiTables,
276            _e @ Self::AE_CODE_AML => AcpiErrorClass::Aml,
277            _e @ Self::AE_CODE_CONTROL => AcpiErrorClass::Control,
278            _ => AcpiErrorClass::Unknown,
279        }
280    }
281}
282
283pub(crate) trait AcpiErrorAsStatusExt {
284    fn to_acpi_status(&self) -> AcpiStatus;
285}
286
287impl AcpiErrorAsStatusExt for Result<(), AcpiError> {
288    fn to_acpi_status(&self) -> AcpiStatus {
289        match self {
290            Ok(()) => AcpiStatus(0),
291            Err(e) => e.to_acpi_status(),
292        }
293    }
294}
295
296impl AcpiErrorAsStatusExt for AcpiError {
297    fn to_acpi_status(&self) -> AcpiStatus {
298        if let AcpiError::Unknown = self {
299            AcpiStatus(Self::Error as u32)
300        } else {
301            AcpiStatus(*self as u32)
302        }
303    }
304}
305
306impl AcpiStatus {
307    pub const OK: Self = Self(0);
308
309    #[allow(clippy::too_many_lines)]
310    pub fn as_result(self) -> Result<(), AcpiError> {
311        match self.0 {
312            0 => Ok(()),
313            e if e == 0x0001 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::Error),
314            e if e == 0x0002 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NoAcpiTables),
315            e if e == 0x0003 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NoNamespace),
316            e if e == 0x0004 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NoMemory),
317            e if e == 0x0005 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NotFound),
318            e if e == 0x0006 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NotExist),
319            e if e == 0x0007 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::AlreadyExists),
320            e if e == 0x0008 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::Type),
321            e if e == 0x0009 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NullObject),
322            e if e == 0x000A | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NullEntry),
323            e if e == 0x000B | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::BufferOverflow),
324            e if e == 0x000C | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::StackOverflow),
325            e if e == 0x000D | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::StackUnderflow),
326            e if e == 0x000E | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NotImplemented),
327            e if e == 0x000F | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::Support),
328            e if e == 0x0010 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::Limit),
329            e if e == 0x0011 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::Time),
330            e if e == 0x0012 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::AcquireDeadlock),
331            e if e == 0x0013 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::ReleaseDeadlock),
332            e if e == 0x0014 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NotAcquired),
333            e if e == 0x0015 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::AlreadyAcquired),
334            e if e == 0x0016 | AcpiError::AE_CODE_ENVIRONMENTAL => {
335                Err(AcpiError::NoHardwareResponse)
336            }
337            e if e == 0x0017 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NoGlobalLock),
338            e if e == 0x0018 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::AbortMethod),
339            e if e == 0x0019 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::SameHandler),
340            e if e == 0x001A | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NoHandler),
341            e if e == 0x001B | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::OwnerIdLimit),
342            e if e == 0x001C | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NotConfigured),
343            e if e == 0x001D | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::Access),
344            e if e == 0x001E | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::IoError),
345            e if e == 0x001F | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::NumericOverflow),
346            e if e == 0x0020 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::HexOverflow),
347            e if e == 0x0021 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::DecimalOverflow),
348            e if e == 0x0022 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::OctalOverflow),
349            e if e == 0x0023 | AcpiError::AE_CODE_ENVIRONMENTAL => Err(AcpiError::EndOfTable),
350            e if e == 0x0001 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::BadParameter),
351            e if e == 0x0002 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::BadCharacter),
352            e if e == 0x0003 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::BadPathname),
353            e if e == 0x0004 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::BadData),
354            e if e == 0x0005 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::BadHexConstant),
355            e if e == 0x0006 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::BadOctalConstant),
356            e if e == 0x0007 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::BadDecimalConstant),
357            e if e == 0x0008 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::MissingArguments),
358            e if e == 0x0009 | AcpiError::AE_CODE_PROGRAMMER => Err(AcpiError::BadAddress),
359            e if e == 0x0001 | AcpiError::AE_CODE_ACPI_TABLES => Err(AcpiError::BadSignature),
360            e if e == 0x0002 | AcpiError::AE_CODE_ACPI_TABLES => Err(AcpiError::BadHeader),
361            e if e == 0x0003 | AcpiError::AE_CODE_ACPI_TABLES => Err(AcpiError::BadChecksum),
362            e if e == 0x0004 | AcpiError::AE_CODE_ACPI_TABLES => Err(AcpiError::BadValue),
363            e if e == 0x0005 | AcpiError::AE_CODE_ACPI_TABLES => Err(AcpiError::InvalidTableLength),
364            e if e == 0x0001 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlBadOpcode),
365            e if e == 0x0002 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlNoOperand),
366            e if e == 0x0003 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlOperandType),
367            e if e == 0x0004 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlOperandValue),
368            e if e == 0x0005 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlUninitializedLocal),
369            e if e == 0x0006 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlUninitializedArg),
370            e if e == 0x0007 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlUninitializedElement),
371            e if e == 0x0008 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlNumericOverflow),
372            e if e == 0x0009 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlRegionLimit),
373            e if e == 0x000A | AcpiError::AE_CODE_AML => Err(AcpiError::AmlBufferLimit),
374            e if e == 0x000B | AcpiError::AE_CODE_AML => Err(AcpiError::AmlPackageLimit),
375            e if e == 0x000C | AcpiError::AE_CODE_AML => Err(AcpiError::AmlDivideByZero),
376            e if e == 0x000D | AcpiError::AE_CODE_AML => Err(AcpiError::AmlBadName),
377            e if e == 0x000E | AcpiError::AE_CODE_AML => Err(AcpiError::AmlNameNotFound),
378            e if e == 0x000F | AcpiError::AE_CODE_AML => Err(AcpiError::AmlInternal),
379            e if e == 0x0010 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlInvalidSpaceId),
380            e if e == 0x0011 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlStringLimit),
381            e if e == 0x0012 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlNoReturnValue),
382            e if e == 0x0013 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlMethodLimit),
383            e if e == 0x0014 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlNotOwner),
384            e if e == 0x0015 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlMutexOrder),
385            e if e == 0x0016 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlMutexNotAcquired),
386            e if e == 0x0017 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlInvalidResourceType),
387            e if e == 0x0018 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlInvalidIndex),
388            e if e == 0x0019 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlRegisterLimit),
389            e if e == 0x001A | AcpiError::AE_CODE_AML => Err(AcpiError::AmlNoWhile),
390            e if e == 0x001B | AcpiError::AE_CODE_AML => Err(AcpiError::AmlAlignment),
391            e if e == 0x001C | AcpiError::AE_CODE_AML => Err(AcpiError::AmlNoResourceEndTag),
392            e if e == 0x001D | AcpiError::AE_CODE_AML => Err(AcpiError::AmlBadResourceValue),
393            e if e == 0x001E | AcpiError::AE_CODE_AML => Err(AcpiError::AmlCircularReference),
394            e if e == 0x001F | AcpiError::AE_CODE_AML => Err(AcpiError::AmlBadResourceLength),
395            e if e == 0x0020 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlIllegalAddress),
396            e if e == 0x0021 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlLoopTimeout),
397            e if e == 0x0022 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlUninitializedNode),
398            e if e == 0x0023 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlTargetType),
399            e if e == 0x0024 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlProtocol),
400            e if e == 0x0025 | AcpiError::AE_CODE_AML => Err(AcpiError::AmlBufferLength),
401            e if e == 0x0001 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlReturnValue),
402            e if e == 0x0002 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlPending),
403            e if e == 0x0003 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlTerminate),
404            e if e == 0x0004 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlTrue),
405            e if e == 0x0005 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlFalse),
406            e if e == 0x0006 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlDepth),
407            e if e == 0x0007 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlEnd),
408            e if e == 0x0008 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlTransfer),
409            e if e == 0x0009 | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlBreak),
410            e if e == 0x000A | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlContinue),
411            e if e == 0x000B | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlParseContinue),
412            e if e == 0x000C | AcpiError::AE_CODE_CONTROL => Err(AcpiError::ControlParsePending),
413
414            _ => Err(AcpiError::Unknown),
415        }
416    }
417}
418
419impl Display for AcpiError {
420    #[allow(clippy::too_many_lines)]
421    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
422        let err_string = match self {
423            Self::Error => "Unspecified error",
424            Self::NoAcpiTables => "ACPI tables could not be found",
425            Self::NoNamespace => "A namespace has not been loaded",
426            Self::NoMemory => "Insufficient dynamic memory",
427            Self::NotFound => "A requested entity is not found",
428            Self::NotExist => "A required entity does not exist",
429            Self::AlreadyExists => "An entity already exists",
430            Self::Type => "The object type is incorrect",
431            Self::NullObject => "A required object was missing",
432            Self::NullEntry => "The requested object does not exist",
433            Self::BufferOverflow => "The buffer provided is too small",
434            Self::StackOverflow => "An internal stack overflowed",
435            Self::StackUnderflow => "An internal stack underflowed",
436            Self::NotImplemented => "The feature is not implemented",
437            Self::Support => "The feature is not supported",
438            Self::Limit => "A predefined limit was exceeded",
439            Self::Time => "A time limit or timeout expired",
440            Self::AcquireDeadlock => {
441                "Internal error, attempt was made to acquire a mutex in improper order"
442            }
443            Self::ReleaseDeadlock => {
444                "Internal error, attempt was made to release a mutex in improper order"
445            }
446            Self::NotAcquired => {
447                "An attempt to release a mutex or Global Lock without a previous acquire"
448            }
449            Self::AlreadyAcquired => "Internal error, attempt was made to acquire a mutex twice",
450            Self::NoHardwareResponse => "Hardware did not respond after an I/O operation",
451            Self::NoGlobalLock => "There is no FACS Global Lock",
452            Self::AbortMethod => "A control method was aborted",
453            Self::SameHandler => {
454                "Attempt was made to install the same handler that is already installed"
455            }
456            Self::NoHandler => "A handler for the operation is not installed",
457            Self::OwnerIdLimit => {
458                "There are no more Owner IDs available for ACPI tables or control methods"
459            }
460            Self::NotConfigured => {
461                "The interface is not part of the current subsystem configuration"
462            }
463            Self::Access => "Permission denied for the requested operation",
464            Self::IoError => "An I/O error occurred",
465            Self::NumericOverflow => "Overflow during string-to-integer conversion",
466            Self::HexOverflow => "Overflow during ASCII hex-to-binary conversion",
467            Self::DecimalOverflow => "Overflow during ASCII decimal-to-binary conversion",
468            Self::OctalOverflow => "Overflow during ASCII octal-to-binary conversion",
469            Self::EndOfTable => "Reached the end of table",
470            Self::BadParameter => "A parameter is out of range or invalid",
471            Self::BadCharacter => "An invalid character was found in a name",
472            Self::BadPathname => "An invalid character was found in a pathname",
473            Self::BadData => "A package or buffer contained incorrect data",
474            Self::BadHexConstant => "Invalid character in a Hex constant",
475            Self::BadOctalConstant => "Invalid character in an Octal constant",
476            Self::BadDecimalConstant => "Invalid character in a Decimal constant",
477            Self::MissingArguments => "Too few arguments were passed to a control method",
478            Self::BadAddress => "An illegal null I/O address",
479            Self::BadSignature => "An ACPI table has an invalid signature",
480            Self::BadHeader => "Invalid field in an ACPI table header",
481            Self::BadChecksum => "An ACPI table checksum is not correct",
482            Self::BadValue => "An invalid value was found in a table",
483            Self::InvalidTableLength => "The FADT or FACS has improper length",
484            Self::AmlBadOpcode => "Invalid AML opcode encountered",
485            Self::AmlNoOperand => "A required operand is missing",
486            Self::AmlOperandType => "An operand of an incorrect type was encountered",
487            Self::AmlOperandValue => "The operand had an inappropriate or invalid value",
488            Self::AmlUninitializedLocal => "Method tried to use an uninitialized local variable",
489            Self::AmlUninitializedArg => "Method tried to use an uninitialized argument",
490            Self::AmlUninitializedElement => "Method tried to use an empty package element",
491            Self::AmlNumericOverflow => "Overflow during BCD conversion or other",
492            Self::AmlRegionLimit => "Tried to access beyond the end of an Operation Region",
493            Self::AmlBufferLimit => "Tried to access beyond the end of a buffer",
494            Self::AmlPackageLimit => "Tried to access beyond the end of a package",
495            Self::AmlDivideByZero => "During execution of AML Divide operator",
496            Self::AmlBadName => "An ACPI name contains invalid character(s)",
497            Self::AmlNameNotFound => "Could not resolve a named reference",
498            Self::AmlInternal => "An internal error within the interpreter",
499            Self::AmlInvalidSpaceId => "An Operation Region SpaceID is invalid",
500            Self::AmlStringLimit => "String is longer than 200 characters",
501            Self::AmlNoReturnValue => "A method did not return a required value",
502            Self::AmlMethodLimit => "A control method reached the maximum reentrancy limit of 255",
503            Self::AmlNotOwner => "A thread tried to release a mutex that it does not own",
504            Self::AmlMutexOrder => "Mutex SyncLevel release mismatch",
505            Self::AmlMutexNotAcquired => {
506                "Attempt to release a mutex that was not previously acquired"
507            }
508            Self::AmlInvalidResourceType => "Invalid resource type in resource list",
509            Self::AmlInvalidIndex => "Invalid Argx or Localx (x too large)",
510            Self::AmlRegisterLimit => "Bank value or Index value beyond range of register",
511            Self::AmlNoWhile => "Break or Continue without a While",
512            Self::AmlAlignment => {
513                "Non-aligned memory transfer on platform that does not support this"
514            }
515            Self::AmlNoResourceEndTag => "No End Tag in a resource list",
516            Self::AmlBadResourceValue => "Invalid value of a resource element",
517            Self::AmlCircularReference => "Two references refer to each other",
518            Self::AmlBadResourceLength => {
519                "The length of a Resource Descriptor in the AML is incorrect"
520            }
521            Self::AmlIllegalAddress => "A memory, I/O, or PCI configuration address is invalid",
522            Self::AmlLoopTimeout => "An AML While loop exceeded the maximum execution time",
523            Self::AmlUninitializedNode => "A namespace node is uninitialized or unresolved",
524            Self::AmlTargetType => "A target operand of an incorrect type was encountered",
525            Self::AmlProtocol => "Violation of a fixed ACPI protocol",
526            Self::AmlBufferLength => "The length of the buffer is invalid/incorrect",
527            Self::ControlReturnValue => "A Method returned a value",
528            Self::ControlPending => "Method is calling another method",
529            Self::ControlTerminate => "Terminate the executing method",
530            Self::ControlTrue | Self::ControlFalse => "An If or While predicate result",
531            Self::ControlDepth => "Maximum search depth has been reached",
532            Self::ControlEnd => "An If or While predicate is false",
533            Self::ControlTransfer => "Transfer control to called method",
534            Self::ControlBreak => "A Break has been executed",
535            Self::ControlContinue => "A Continue has been executed",
536            Self::ControlParseContinue => "Used to skip over bad opcodes",
537            Self::ControlParsePending => "Used to implement AML While loops",
538
539            Self::Unknown => "Unknown error",
540        };
541
542        f.write_str(err_string)
543    }
544}
545
546/// Tests that [`as_result`][AcpiStatus::as_result] is the inverse of [`as_acpi_status`][AcpiError::as_acpi_status]
547#[test]
548fn test_as_result() {
549    assert_eq!(AcpiStatus(0).as_result(), Ok(()));
550
551    for i in 1..0x4f00 {
552        let error = AcpiStatus(i)
553            .as_result()
554            .expect_err("An AcpiStatus with a non-0 value should not map to Ok");
555
556        if error == AcpiError::Unknown {
557            continue;
558        }
559
560        assert_eq!(error.to_acpi_status().0, i);
561    }
562}
563
564/// Tests that [`class`][`AcpiError::class`] returns correct values
565#[test]
566fn test_error_class() {
567    assert_eq!(AcpiError::Error.class(), AcpiErrorClass::Environmental);
568    assert_eq!(
569        AcpiError::StackOverflow.class(),
570        AcpiErrorClass::Environmental
571    );
572    assert_eq!(AcpiError::BadParameter.class(), AcpiErrorClass::Programmer);
573    assert_eq!(
574        AcpiError::MissingArguments.class(),
575        AcpiErrorClass::Programmer
576    );
577    assert_eq!(AcpiError::BadSignature.class(), AcpiErrorClass::AcpiTables);
578    assert_eq!(AcpiError::BadChecksum.class(), AcpiErrorClass::AcpiTables);
579    assert_eq!(AcpiError::AmlBadOpcode.class(), AcpiErrorClass::Aml);
580    assert_eq!(AcpiError::AmlInternal.class(), AcpiErrorClass::Aml);
581    assert_eq!(AcpiError::ControlPending.class(), AcpiErrorClass::Control);
582    assert_eq!(AcpiError::ControlContinue.class(), AcpiErrorClass::Control);
583
584    assert_eq!(AcpiError::Unknown.class(), AcpiErrorClass::Unknown);
585}