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}