acpica_bindings/interface/handler/
handler_trait.rs

1#[cfg(not(all(feature = "builtin_cache", feature = "builtin_lock",)))]
2use crate::types::{AcpiAllocationError, AcpiCpuFlags};
3
4use core::ffi::c_void;
5
6use alloc::string::String;
7
8use crate::{
9    interface::status::AcpiError,
10    types::{
11        tables::AcpiTableHeader, AcpiInterruptCallback, AcpiInterruptCallbackTag, AcpiIoAddress,
12        AcpiMappingError, AcpiPciId, AcpiPhysicalAddress, AcpiPredefinedNames, AcpiThreadCallback,
13    },
14};
15
16/// The interface between ACPICA and the host OS. Each method in this trait is mapped to an `AcpiOs...` function,
17/// which will be called on the object registered with [`register_interface`].
18///
19/// # Optional Methods
20///
21/// Some methods are only present if certain features of the crate are enabled or disabled:
22/// * `create_cache`, `delete_cache`, `purge_cache`, `acquire_object`, and `release_object`
23///     are only present if the crate feature `builtin_cache` is disabled
24/// * `create_lock`, `delete_lock`, `acquire_lock`, and `release_lock`
25///     are only present if the crate feature `builtin_lock` is disabled
26/// * `create_semaphore`, `delete_semaphore`, `wait_semaphore`, and `signal_semaphore`
27///     are only present if the crate feature `builtin_semaphore` is disabled
28///
29/// # Safety
30/// This trait is unsafe to implement because some functions have restrictions on their
31/// implementation as well as their caller. This is indicated per method under the heading "Implementation Safety".
32///
33/// As well as this, it is undefined behaviour for a panic to unwind across an FFI boundary from rust code to C code.
34/// Users of this library who have panic unwinding enabled are responsible for ensuring that a panic never unwinds out of a method in this trait.
35/// If the OS is built with `panic=abort`, this is not an issue.
36///
37/// [`register_interface`]: crate::register_interface
38pub unsafe trait AcpiHandler {
39    /// Method called when ACPICA initialises. The default implementation of this method is a no-op.
40    ///
41    /// # Safety
42    /// * This method is only called from `AcpiOsInitialize`
43    unsafe fn initialize(&mut self) -> Result<(), AcpiError> {
44        Ok(())
45    }
46
47    /// Method called when ACPICA shuts down. The default implementation of this method is a no-op
48    ///
49    /// # Safety
50    /// * This method is only called from `AcpiOsTerminate`
51    /// * After this method is called, the object will be dropped and no other methods will be called
52    unsafe fn terminate(&mut self) -> Result<(), AcpiError> {
53        Ok(())
54    }
55
56    /// Gets a physical pointer to the RSDP.
57    ///
58    /// # Implementation Safety
59    /// * The returned pointer must point to the system's RSDP.
60    fn get_root_pointer(&mut self) -> AcpiPhysicalAddress;
61
62    /// Allows the OS to specify an override for a predefined object in the ACPI namespace.
63    /// The returned string will be converted to a [`CString`], so the FFI handler for this
64    /// method will panic if it contains null bytes.
65    ///
66    /// # Safety
67    /// * This function is only called from `AcpiOsPredefinedOverride`
68    ///
69    /// [`CString`]: alloc::ffi::CString
70    #[allow(unused_variables)]
71    unsafe fn predefined_override(
72        &mut self,
73        predefined_object: &AcpiPredefinedNames,
74    ) -> Result<Option<String>, AcpiError> {
75        Ok(None)
76    }
77
78    /// Allows the OS to override an ACPI table using a logical address.
79    /// This method is called once on each ACPI table in the order they are listed in the DSDT/XSDT,
80    /// and when tables are loaded by the `Load` AML instruction. To keep the original table, return `Ok(None)`.
81    ///
82    /// To override the table using a physical address instead, use [`physical_table_override`]
83    ///
84    /// # Safety
85    /// * This method is only called from `AcpiOsTableOverride`
86    ///
87    /// [`physical_table_override`]: AcpiHandler::physical_table_override
88    #[allow(unused_variables)]
89    unsafe fn table_override(
90        &mut self,
91        table: &AcpiTableHeader,
92    ) -> Result<Option<AcpiTableHeader>, AcpiError> {
93        Ok(None)
94    }
95
96    /// Allows the OS to override an ACPI table using a physical address.
97    /// To keep the original table, return `Ok(None)`
98    ///
99    /// # Safety
100    /// * This method is only called from `AcpiOsPhysicalTableOverride`
101    ///
102    /// # Implementation Safety
103    /// * The returned physical address must point to a valid new ACPI table with the returned length
104    /// * The memory indicated by the returned pointer and length is now managed by ACPICA and must
105    ///     not be written to while ACPICA is active
106    #[allow(unused_variables)]
107    unsafe fn physical_table_override(
108        &mut self,
109        table: &AcpiTableHeader,
110    ) -> Result<Option<(AcpiPhysicalAddress, u32)>, AcpiError> {
111        Ok(None)
112    }
113
114    /// Map `length` bytes of physical memory starting at `physical_address`, and return the virtual address where they have been mapped.
115    ///
116    /// # Safety
117    /// * This function is only called from `AcpiOsMapMemory`
118    /// * The memory at `physical_address` is valid for writes for `length` bytes
119    ///
120    /// # Implementation Safety
121    /// * The memory must stay mapped until `unmap_memory` is called.
122    unsafe fn map_memory(
123        &mut self,
124        physical_address: AcpiPhysicalAddress,
125        length: usize,
126    ) -> Result<*mut u8, AcpiMappingError>;
127
128    /// Unmap `length` pages bytes of memory which were previously allocated with [`map_memory`]
129    ///
130    /// # Safety
131    /// * This function is only called from `AcpiOsUnmapMemory`
132    /// * `address` is a pointer which was previously returned from [`map_memory`]
133    ///
134    /// [`map_memory`]: AcpiHandler::map_memory
135    unsafe fn unmap_memory(&mut self, address: *mut u8, length: usize);
136
137    /// Translate a logical address to the physical address it's mapped to.
138    ///
139    /// # Return value
140    /// * `Ok(Some(address))`: The translation was successful
141    /// * `Ok(None)`: The translation was successful but the virtual address is not mapped
142    /// * `Err(e)`: There was an error carrying out the translation
143    fn get_physical_address(
144        &mut self,
145        logical_address: *mut u8,
146    ) -> Result<Option<AcpiPhysicalAddress>, AcpiError>;
147
148    /// Read a [`u8`] from the given physical address.
149    ///
150    /// # Safety
151    /// * The given physical address is valid for reads
152    /// * This method is only called from `AcpiOsReadMemory`
153    ///
154    /// # Implementation Safety
155    /// * As this read could be from memory mapped IO, the read should be volatile
156    ///
157    /// If you want your implementation of this method to look the same as [`read_physical_u16`], [`..._u32`], and [`..._u64`],
158    /// Read the documentation for these methods before implementing this one as the size of the type makes a difference in implementing the method soundly.
159    ///
160    /// [`read_physical_u16`]: AcpiHandler::read_physical_u16
161    /// [`..._u32`]: AcpiHandler::read_physical_u32
162    /// [`..._u64`]: AcpiHandler::read_physical_u64
163    unsafe fn read_physical_u8(&mut self, address: AcpiPhysicalAddress) -> Result<u8, AcpiError>;
164
165    /// Read a [`u16`] from the given physical address.
166    ///
167    /// # Safety
168    /// * The given physical address is valid for reads
169    /// * This method is only called from `AcpiOsReadMemory`
170    ///
171    /// # Implementation Safety
172    /// * As this read could be from memory mapped IO, the read should be volatile
173    /// * The physical address may not be 2 byte aligned, so the read should be unaligned
174    ///
175    /// These requirements can be difficult to satisfy at the same time.
176    /// If you are alright with using unstable compiler intrinsics, the [`core::intrinsics::unaligned_volatile_load`] method.
177    /// Otherwise, it is possible to read the data as a `[u8; 2]` and then transmute it into a [`u16`].
178    unsafe fn read_physical_u16(&mut self, address: AcpiPhysicalAddress) -> Result<u16, AcpiError>;
179
180    /// Read a [`u32`] from the given physical address.
181    ///
182    /// # Safety
183    /// * The given physical address is valid for reads
184    /// * This method is only called from `AcpiOsReadMemory`
185    ///
186    /// # Implementation Safety
187    /// * As this read could be from memory mapped IO, the read should be volatile
188    /// * The physical address may not be 4 byte aligned, so the read should be unaligned
189    ///
190    /// These requirements can be difficult to satisfy at the same time.
191    /// If you are alright with using unstable compiler intrinsics, the [`core::intrinsics::unaligned_volatile_load`] method.
192    /// Otherwise, it is possible to read the data as a `[u8; 4]` and then transmute it into a [`u32`].
193    unsafe fn read_physical_u32(&mut self, address: AcpiPhysicalAddress) -> Result<u32, AcpiError>;
194
195    /// Read a [`u64`] from the given physical address.
196    ///
197    /// # Safety
198    /// * The given physical address is valid for reads
199    /// * This method is only called from `AcpiOsReadMemory`
200    ///
201    /// # Implementation Safety
202    /// * As this read could be from memory mapped IO, the read should be volatile
203    /// * The physical address may not be 8 byte aligned, so the read should be unaligned
204    ///
205    /// These requirements can be difficult to satisfy at the same time.
206    /// If you are alright with using unstable compiler intrinsics, the [`core::intrinsics::unaligned_volatile_load`] method.
207    /// Otherwise, it is possible to read the data as a `[u8; 8]` and then transmute it into a [`u64`].
208    unsafe fn read_physical_u64(&mut self, address: AcpiPhysicalAddress) -> Result<u64, AcpiError>;
209
210    /// Read a [`u8`] from the given physical address.
211    ///
212    /// # Safety
213    /// * The given physical address is valid for writes
214    /// * This method is only called from `AcpiOsWriteMemory`
215    ///
216    /// # Implementation Safety
217    /// * As this read could be to memory mapped IO, the write should be volatile
218    ///
219    /// If you want your implementation of this method to look the same as [`write_physical_u16`], [`..._u32`], and [`..._u64`],
220    /// Read the documentation for these methods before implementing this one as the size of the type makes a difference in implementing the method soundly.
221    ///
222    /// [`write_physical_u16`]: AcpiHandler::write_physical_u16
223    /// [`..._u32`]: AcpiHandler::write_physical_u32
224    /// [`..._u64`]: AcpiHandler::write_physical_u64
225    unsafe fn write_physical_u8(
226        &mut self,
227        address: AcpiPhysicalAddress,
228        value: u8,
229    ) -> Result<(), AcpiError>;
230
231    /// Read a [`u16`] from the given physical address.
232    ///
233    /// # Safety
234    /// * The given physical address is valid for writes
235    /// * This method is only called from `AcpiOsWriteMemory`
236    ///
237    /// # Implementation Safety
238    /// * As this read could be to memory mapped IO, the write should be volatile
239    /// * The physical address may not be 2 byte aligned, so the read should be unaligned
240    ///
241    /// These requirements can be difficult to satisfy at the same time.
242    /// If you are alright with using unstable compiler intrinsics, the [`core::intrinsics::unaligned_volatile_store`] method.
243    /// Otherwise, it is possible to transmute the data into a `[u8; 2]` before writing it.
244    unsafe fn write_physical_u16(
245        &mut self,
246        address: AcpiPhysicalAddress,
247        value: u16,
248    ) -> Result<(), AcpiError>;
249
250    /// Read a [`u32`] from the given physical address.
251    ///
252    /// # Safety
253    /// * The given physical address is valid for writes
254    /// * This method is only called from `AcpiOsWriteMemory`
255    ///
256    /// # Implementation Safety
257    /// * As this read could be to memory mapped IO, the write should be volatile
258    /// * The physical address may not be 4 byte aligned, so the read should be unaligned
259    ///
260    /// These requirements can be difficult to satisfy at the same time.
261    /// If you are alright with using unstable compiler intrinsics, the [`core::intrinsics::unaligned_volatile_store`] method.
262    /// Otherwise, it is possible to transmute the data into a `[u8; 4]` before writing it.
263    unsafe fn write_physical_u32(
264        &mut self,
265        address: AcpiPhysicalAddress,
266        value: u32,
267    ) -> Result<(), AcpiError>;
268
269    /// Read a [`u64`] from the given physical address.
270    ///
271    /// # Safety
272    /// * The given physical address is valid for writes
273    /// * This method is only called from `AcpiOsWriteMemory`
274    ///
275    /// # Implementation Safety
276    /// * As this read could be to memory mapped IO, the write should be volatile
277    /// * The physical address may not be 8 byte aligned, so the read should be unaligned
278    ///
279    /// These requirements can be difficult to satisfy at the same time.
280    /// If you are alright with using unstable compiler intrinsics, the [`core::intrinsics::unaligned_volatile_store`] method.
281    /// Otherwise, it is possible to transmute the data into a `[u8; 8]` before writing it.
282    unsafe fn write_physical_u64(
283        &mut self,
284        address: AcpiPhysicalAddress,
285        value: u64,
286    ) -> Result<(), AcpiError>;
287
288    /// Check whether `pointer` is valid for reads of `length` bytes.
289    /// This is only in terms of the memory being mapped with the right permissions and valid, not in terms of rust's ownership rules.
290    ///
291    /// # Return Value
292    /// * `true` if the pointer is valid for `length` bytes of reads
293    /// * `false` if the pointer is not valid
294    ///
295    /// # Safety
296    /// * This method is only called from `AcpiOsReadable`
297    unsafe fn readable(&mut self, pointer: *mut c_void, length: usize) -> bool;
298
299    /// Check whether `pointer` is valid for writes of `length` bytes.
300    /// This is only in terms of the memory being mapped with the right permissions and valid, not in terms of rust's ownership rules.
301    ///
302    /// # Return Value
303    /// * `true` if the pointer is valid for `length` bytes of writes
304    /// * `false` if the pointer is not valid
305    ///
306    /// # Safety
307    /// * This method is only called from `AcpiOsWritable`
308    unsafe fn writable(&mut self, pointer: *mut c_void, length: usize) -> bool;
309
310    /// Register the given `callback` to run in the interrupt handler for the given `interrupt_number`
311    ///
312    /// # Safety
313    /// * This method is only called from `AcpiOsInstallInterruptHandler`
314    unsafe fn install_interrupt_handler(
315        &mut self,
316        interrupt_number: u32,
317        callback: AcpiInterruptCallback,
318    ) -> Result<(), AcpiError>;
319
320    /// Remove an interrupt handler which was previously registered with [`install_interrupt_handler`].
321    /// The passed `tag` should be compared to each registered handler using [`is_tag`], and whichever handler returns `true` should be removed.
322    /// If no handler is found, [`AcpiError::NotExist`] should be returned.
323    ///
324    /// # Safety
325    /// * This method is only called from `AcpiOsRemoveInterruptHandler`
326    ///
327    /// # Implementation Safety
328    /// * If the handler is found, it must be removed and not called again and [`Ok`] returned.
329    /// * If the handler is not found, [`AcpiError::NotExist`] must be returned.
330    ///
331    /// [`install_interrupt_handler`]: AcpiHandler::install_interrupt_handler
332    /// [`is_tag`]: AcpiInterruptCallback::is_tag
333    unsafe fn remove_interrupt_handler(
334        &mut self,
335        interrupt_number: u32,
336        tag: AcpiInterruptCallbackTag,
337    ) -> Result<(), AcpiError>;
338
339    /// Gets the thread ID of the kernel thread this method is called from.
340    ///
341    /// # Implementation safety
342    /// * The returned thread ID must be and must be unique to the executing thread
343    /// * The thread ID may not be 0 and may not be equal to [`u64::MAX`]
344    fn get_thread_id(&mut self) -> u64;
345
346    /// Run the callback in a new kernel thread. The [`call`] method of the given `callback` must be run, and then the kernel thread should be destroyed.
347    /// The OS should keep track of which kernel threads were spawned using this method so that [`wait_for_events`] can be implemented correctly.
348    ///
349    /// # Safety
350    /// * This method is only called from `AcpiOsExecute`
351    ///
352    /// # Return value
353    /// * `Ok(())`: The thread is queued and ready to execute
354    /// * `Err(e)`: There was an error creating the thread
355    ///
356    /// [`call`]: AcpiThreadCallback::call
357    /// [`wait_for_events`]: AcpiHandler::wait_for_events
358    unsafe fn execute(
359        &mut self,
360        // callback_type: AcpiExecuteType,
361        callback: AcpiThreadCallback,
362    ) -> Result<(), AcpiError>;
363
364    /// Waits for all tasks run with [`execute`] to complete before returning.
365    ///
366    /// # Safety
367    /// * This method is only called from `AcpiOsWaitEventsComplete`
368    ///
369    /// # Implementation Safety
370    /// * This method must not return until all
371    ///
372    /// [`execute`]: AcpiHandler::execute
373    unsafe fn wait_for_events(&mut self);
374
375    /// Sleep the current kernel thread for the given number of milliseconds
376    ///
377    /// # Safety
378    /// * This method is only called from `AcpiOsSleep`
379    ///
380    /// # Implementation Safety
381    /// * This method must not return until the given number of milliseconds has elapsed. The OS should attempt not to overshoot the target time by too much.
382    unsafe fn sleep(&mut self, millis: usize);
383
384    /// Loop for the given number of microseconds, without sleeping the kernel thread
385    ///
386    /// # Safety
387    /// * This method is only called from `AcpiOsStall`
388    ///
389    /// # Implementation Safety
390    /// * This method must not return until the given number of microseconds has elapsed. The OS should attempt not to overshoot the target time by too much.
391    unsafe fn stall(&mut self, micros: usize);
392
393    /// Print a message to the kernel's output.
394    ///
395    /// Multiple calls to `printf` may be used to print a single line of output, and ACPICA will write a newline character at the end of each line.
396    /// For this reason, the OS should not add its own newline characters or this could break formatting.
397    /// If your kernel has a macro which behaves like the standard `print!` macro, the implementation of this method can be as simple as
398    ///
399    /// ```ignore
400    /// fn printf(&mut self, message: core::fmt::Arguments) {
401    ///     print!("{message}");
402    /// }
403    /// ```
404    fn printf(&mut self, message: core::fmt::Arguments);
405
406    /// Read a [`u8`] from the given port
407    ///
408    /// # Safety
409    /// * This method is only called from `AcpiOsReadPort`
410    unsafe fn read_port_u8(&mut self, address: AcpiIoAddress) -> Result<u8, AcpiError>;
411
412    /// Read a [`u16`] from the given port
413    ///
414    /// # Safety
415    /// * This method is only called from `AcpiOsReadPort`
416    unsafe fn read_port_u16(&mut self, address: AcpiIoAddress) -> Result<u16, AcpiError>;
417
418    /// Read a [`u32`] from the given port
419    ///
420    /// # Safety
421    /// * This method is only called from `AcpiOsReadPort`
422    unsafe fn read_port_u32(&mut self, address: AcpiIoAddress) -> Result<u32, AcpiError>;
423
424    /// Write a [`u8`] to the given port
425    ///
426    /// # Safety
427    /// * This method is only called from `AcpiOsWritePort`
428    unsafe fn write_port_u8(&mut self, address: AcpiIoAddress, value: u8) -> Result<(), AcpiError>;
429
430    /// Write a [`u16`] to the given port
431    ///
432    /// # Safety
433    /// * This method is only called from `AcpiOsWritePort`
434    unsafe fn write_port_u16(
435        &mut self,
436        address: AcpiIoAddress,
437        value: u16,
438    ) -> Result<(), AcpiError>;
439
440    /// Write a [`u32`] to the given port
441    ///
442    /// # Safety
443    /// * This method is only called from `AcpiOsWritePort`
444    unsafe fn write_port_u32(
445        &mut self,
446        address: AcpiIoAddress,
447        value: u32,
448    ) -> Result<(), AcpiError>;
449
450    /// Called just before the system enters a sleep state.
451    /// This method allows the OS to do any final processing before entering the new state.
452    /// The default implementation is a no-op.
453    ///
454    /// # Safety
455    /// * This method is only called from `AcpiOsEnterSleep`
456    ///
457    // TODO: Figure out what reg_a and reg_b are and add docs
458    #[allow(unused_variables)]
459    unsafe fn enter_sleep(&mut self, state: u8, reg_a: u32, reg_b: u32) -> Result<(), AcpiError> {
460        Ok(())
461    }
462
463    /// Get the value of the system timer in 100 nanosecond units
464    ///
465    /// # Safety
466    /// * This method is only called from `AcpiOsGetTimer`
467    ///
468    /// # Implementation Safety
469    /// * The timer must not decrease i.e. later calls to this function must return a greater value
470    // TODO: There might be more safety conditions
471    unsafe fn get_timer(&mut self) -> u64;
472
473    /// Read a [`u8`] from the configuration space of the given PCI ID and return it.
474    /// `register` is the offset of the value to read in bytes.
475    ///
476    /// # Safety
477    /// * This method is only called from `AcpiOsReadPciConfiguration`
478    /// * The read is sound i.e. it has no memory-safety related side-effects.
479    unsafe fn read_pci_config_u8(
480        &mut self,
481        id: AcpiPciId,
482        register: usize,
483    ) -> Result<u8, AcpiError>;
484
485    /// Read a [`u16`] from the configuration space of the given PCI ID and return it.
486    /// `register` is the offset of the value to read in bytes.
487    ///
488    /// # Safety
489    /// * This method is only called from `AcpiOsReadPciConfiguration`
490    /// * The read is sound i.e. it has no memory-safety related side-effects.
491    unsafe fn read_pci_config_u16(
492        &mut self,
493        id: AcpiPciId,
494        register: usize,
495    ) -> Result<u16, AcpiError>;
496
497    /// Read a [`u32`] from the configuration space of the given PCI ID and return it.
498    /// `register` is the offset of the value to read in bytes.
499    ///
500    /// # Safety
501    /// * This method is only called from `AcpiOsReadPciConfiguration`
502    /// * The read is sound i.e. it has no memory-safety related side-effects.
503    unsafe fn read_pci_config_u32(
504        &mut self,
505        id: AcpiPciId,
506        register: usize,
507    ) -> Result<u32, AcpiError>;
508
509    /// Read a [`u64`] from the configuration space of the given PCI ID and return it.
510    /// `register` is the offset of the value to read in bytes.
511    ///
512    /// # Safety
513    /// * This method is only called from `AcpiOsReadPciConfiguration`
514    /// * The read is sound i.e. it has no memory-safety related side-effects.
515    unsafe fn read_pci_config_u64(
516        &mut self,
517        id: AcpiPciId,
518        register: usize,
519    ) -> Result<u64, AcpiError>;
520
521    /// Write a [`u8`] to the configuration space of the given PCI ID.
522    /// `register` is the offset of the value to read in bytes.
523    ///
524    /// # Safety
525    /// * This method is only called from `AcpiOsWritePciConfiguration`
526    /// * The write is sound i.e. it has no memory-safety related side-effects.
527    unsafe fn write_pci_config_u8(
528        &mut self,
529        id: AcpiPciId,
530        register: usize,
531        value: u8,
532    ) -> Result<(), AcpiError>;
533
534    /// Write a [`u16`] to the configuration space of the given PCI ID.
535    /// `register` is the offset of the value to read in bytes.
536    ///
537    /// # Safety
538    /// * This method is only called from `AcpiOsRWriteciConfiguration`
539    /// * The write is sound i.e. it has no memory-safety related side-effects.
540    unsafe fn write_pci_config_u16(
541        &mut self,
542        id: AcpiPciId,
543        register: usize,
544        value: u16,
545    ) -> Result<(), AcpiError>;
546
547    /// Write a [`u32`] to the configuration space of the given PCI ID.
548    /// `register` is the offset of the value to read in bytes.
549    ///
550    /// # Safety
551    /// * This method is only called from `AcpiOsRWriteciConfiguration`
552    /// * The write is sound i.e. it has no memory-safety related side-effects.
553    unsafe fn write_pci_config_u32(
554        &mut self,
555        id: AcpiPciId,
556        register: usize,
557        value: u32,
558    ) -> Result<(), AcpiError>;
559
560    /// Write a [`u64`] to the configuration space of the given PCI ID.
561    /// `register` is the offset of the value to read in bytes.
562    ///
563    /// # Safety
564    /// * This method is only called from `AcpiOsRWriteciConfiguration`
565    /// * The write is sound i.e. it has no memory-safety related side-effects.
566    unsafe fn write_pci_config_u64(
567        &mut self,
568        id: AcpiPciId,
569        register: usize,
570        value: u64,
571    ) -> Result<(), AcpiError>;
572
573    /// Called when the AML `Fatal` opcode is encountered. The OS can return from this method, or kill the thread executing the AML.
574    ///
575    /// # Safety
576    /// * This method is only called from `AcpiOsSignal`
577    unsafe fn signal_fatal(
578        &mut self,
579        fatal_type: u32,
580        code: u32,
581        argument: u32,
582    ) -> Result<(), AcpiError>;
583
584    /// Called when the AML `Breakpoint` opcode is encountered.
585    ///
586    /// # Safety
587    /// * This method is only called from `AcpiOsSignal`
588    unsafe fn signal_breakpoint(&mut self, message: &str) -> Result<(), AcpiError>;
589
590    // TODO: Verify the info in the docs for these cache methods
591
592    /// Creates a cache for ACPICA to store objects in to avoid lots of small heap allocations.
593    ///
594    /// This method is only present in the trait if the `builtin_cache` feature is not set.
595    /// Otherwise, ACPICA's builtin implementation is used.
596    ///
597    /// The cache stores up to `max_depth` objects of size `object_size`.
598    /// The OS is responsible for allocating and de-allocating objects within the cache.
599    ///
600    /// The OS returns a type-erased pointer which can safely be passed via FFI,
601    /// but the pointer may point to any type.
602    ///
603    /// # Safety
604    /// * This method is only called from `AcpiCreateCache`.
605    ///
606    /// [`Vec`]: alloc::vec::Vec
607    /// [`BitVec`]: bitvec::vec::BitVec
608    #[cfg(not(feature = "builtin_cache"))]
609    unsafe fn create_cache(
610        &mut self,
611        cache_name: &str,
612        object_size: u16,
613        max_depth: u16,
614    ) -> Result<*mut c_void, AcpiError>;
615
616    /// Deletes a cache which was previously created by [`create_cache`].
617    ///
618    /// This method is only present in the trait if the `builtin_cache` feature is not set.
619    ///
620    /// The OS is responsible for deallocating the backing memory of the cache.
621    ///
622    /// # Safety
623    /// * This method is only called from `AcpiDeleteCache`
624    /// * `cache` is a pointer which was previously returned from [`create_cache`]
625    /// * After this method is called, other cache methods will not be called for this cache
626    ///
627    /// [`create_cache`]: AcpiHandler::create_cache
628    #[cfg(not(feature = "builtin_cache"))]
629    unsafe fn delete_cache(&mut self, cache: *mut c_void) -> Result<(), AcpiAllocationError>;
630
631    /// Removes all items from a cache.
632    ///
633    /// This method is only present in the trait if the `builtin_cache` feature is not set
634    ///
635    /// This method should mark all slots in the cache as empty, but not deallocate the backing memory
636    ///
637    /// # Safety
638    /// * This method is only called from `AcpiPurgeCache`
639    /// * `cache` is a pointer which was previously returned from [`create_cache`]
640    ///
641    /// [`create_cache`]: AcpiHandler::create_cache
642    #[cfg(not(feature = "builtin_cache"))]
643    unsafe fn purge_cache(&mut self, cache: *mut c_void);
644
645    /// Allocates an object inside a cache.
646    ///
647    /// This method is only present in the trait if the `builtin_cache` feature is not set.
648    ///
649    /// This method should return a pointer to a free slot in the cache, or `None` if all slots are full.
650    ///
651    /// # Safety
652    /// * This method is only called from `AcpiPurgeCache`.
653    /// * `cache` is a pointer which was previously returned from [`create_cache`].
654    ///
655    /// # Implementation safety
656    /// * The returned pointer must be free for writes for the object size passed to [`create_cache`]
657    ///     - i.e. it must not be being used by rust code, and it must not have been returned from this method before,
658    ///     unless it has been explicitly freed using [`release_object`] or [`purge_cache`].
659    ///
660    /// [`create_cache`]: AcpiHandler::create_cache
661    /// [`release_object`]: AcpiHandler::release_object
662    /// [`purge_cache`]: AcpiHandler::purge_cache
663    #[cfg(not(feature = "builtin_cache"))]
664    unsafe fn acquire_object(&mut self, cache: *mut c_void) -> Option<*mut u8>;
665
666    /// Marks an object as free in a cache.
667    ///
668    /// This method is only present in the trait if the `builtin_cache` feature is not set.
669    ///
670    /// This method should mark the given object within the cache as free - i.e. allow it to be allocated again by [`acquire_object`].
671    ///
672    /// # Safety
673    /// * This method is only called from `AcpiReleaseObject`.
674    /// * `cache` is a pointer which was previously returned from [`create_cache`].
675    /// * `object` is a pointer which was previously returned from [`acquire_object`].
676    ///
677    /// [`acquire_object`]: AcpiHandler::acquire_object
678    /// [`create_cache`]: AcpiHandler::create_cache
679    #[cfg(not(feature = "builtin_cache"))]
680    unsafe fn release_object(&mut self, cache: *mut c_void, object: *mut u8);
681
682    #[allow(missing_docs)] // TODO: docs
683    #[cfg(not(feature = "builtin_lock"))]
684    unsafe fn create_lock(&mut self) -> Result<*mut c_void, AcpiError>;
685
686    #[allow(missing_docs)] // TODO: docs
687    #[cfg(not(feature = "builtin_lock"))]
688    unsafe fn delete_lock(&mut self, lock: *mut c_void);
689
690    #[allow(missing_docs)] // TODO: docs
691    #[cfg(not(feature = "builtin_lock"))]
692    unsafe fn acquire_lock(&mut self, handle: *mut c_void) -> AcpiCpuFlags;
693
694    #[allow(missing_docs)] // TODO: docs
695    #[cfg(not(feature = "builtin_lock"))]
696    unsafe fn release_lock(&mut self, handle: *mut c_void, flags: AcpiCpuFlags);
697
698    #[allow(missing_docs)] // TODO: docs
699    #[cfg(not(feature = "builtin_semaphore"))]
700    unsafe fn create_semaphore(
701        &mut self,
702        max_units: u32,
703        initial_units: u32,
704    ) -> Result<*mut c_void, AcpiError>;
705
706    #[allow(missing_docs)] // TODO: docs
707    #[cfg(not(feature = "builtin_semaphore"))]
708    unsafe fn delete_semaphore(&mut self, handle: *mut c_void) -> Result<(), AcpiError>;
709
710    #[allow(missing_docs)] // TODO: docs
711    #[cfg(not(feature = "builtin_semaphore"))]
712    unsafe fn wait_semaphore(
713        &mut self,
714        handle: *mut c_void,
715        units: u32,
716        timeout: u16,
717    ) -> Result<(), AcpiError>;
718
719    #[allow(missing_docs)] // TODO: docs
720    #[cfg(not(feature = "builtin_semaphore"))]
721    unsafe fn signal_semaphore(&mut self, handle: *mut c_void, units: u32)
722        -> Result<(), AcpiError>;
723}