kernel/initcall/
driver.rs

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