kernel/initcall/driver.rs
1use core::ptr::read_volatile;
2
3use crate::early_println;
4
5/// A macro used to register driver initialization functions to be called during the system boot process.
6///
7/// This macro places the function pointer into the `.initcall.driver` section of the binary,
8/// allowing the kernel to discover and call all driver initialization functions at the appropriate time.
9///
10/// # Parameters
11///
12/// * `$func` - A function with the signature `fn()` that register a driver
13///
14/// # Examples
15///
16/// ```
17/// fn register_my_driver() {
18/// // Driver registration logic here
19/// }
20///
21/// driver_initcall!(register_my_driver);
22/// ```
23///
24/// # Safety
25///
26/// This macro relies on linker sections and should only be used for functions that are
27/// safe to call during the kernel's driver initialization phase.
28///
29#[macro_export]
30macro_rules! driver_initcall {
31 ($func:ident) => {
32 #[unsafe(link_section = ".initcall.driver")]
33 #[used(linker)]
34 static __DRIVER_INITCALL__ : fn() = $func;
35 };
36}
37
38
39unsafe extern "C" {
40 static __INITCALL_DRIVER_START: usize;
41 static __INITCALL_DRIVER_END: usize;
42}
43
44pub fn driver_initcall_call() {
45 unsafe {
46 let size = core::mem::size_of::<fn()>();
47
48 early_println!("Running driver initcalls... ");
49 let mut func_addr = &__INITCALL_DRIVER_START as *const usize as usize;
50 let end_addr = &__INITCALL_DRIVER_END as *const usize as usize;
51
52 while func_addr < end_addr {
53 let initcall = read_volatile(func_addr as *const fn());
54
55 initcall();
56
57 func_addr += size;
58 }
59 }
60}