kernel_api/modules.rs
1//! Kernel modules.
2//!
3//! # Examples
4//!
5//! ```
6//! use kernel_api::modules::{kernel_module, Module};
7//! use kernel_api::sync::OnceLock;
8//!
9//! struct MyModuleContext {
10//! // ...
11//! # foo: i32,
12//! }
13//!
14//! static CONTEXT: OnceLock<MyModuleContext> = OnceLock::new();
15//!
16//! kernel_module! {
17//! type: MyModuleContext,
18//! name: "My Custom Module",
19//! author: "Popcorn Contributors",
20//! license: "MPL-2.0",
21//! }
22//!
23//! impl Module for MyModuleContext {
24//! fn early_init() -> Result<(), &'static str> {
25//! debug!("early init of `My Custom Module`");
26//! Ok(())
27//! }
28//!
29//! fn late_init() -> Result<(), &'static str> {
30//! debug!("late init of `My Custom Module`");
31//! // initialise context
32//! CONTEXT.get_or_init(Self::new);
33//! Ok(())
34//! }
35//! }
36//!
37//! impl MyModuleContext {
38//! fn new() -> Self {
39//! // ...
40//! # Self { foo: 5 }
41//! }
42//! }
43//! ```
44
45/// Registers a kernel module with the kernel.
46///
47/// The `type` argument should be a type implementing the [`Module`] trait.
48///
49/// Additionally, it also takes the following arguments in order:
50/// - `name` - a user facing name for the module
51/// - `description` (optional) - a user facing description of the module
52/// - `author` (optional) - the author of the module
53/// - `license` - An SPDX license identifier (currently only `MPL-*` is accepted)
54///
55/// # Examples
56///
57/// See the [module-level documentation](self).
58#[expect(rustdoc::missing_doc_code_examples, reason = "documented at module level")]
59#[macro_export]
60macro_rules! kernel_module {
61 (
62 type: $ty:ty,
63 name: $name:literal,
64 $(description: $description:literal,)?
65 $(author: $author:literal,)?
66 license: $license:tt$(,)?
67 ) => {
68 const _: () = {
69 $crate::kernel_module_license!(@license $license);
70 const fn __assert_module_implements_module<T: $crate::modules::Module>() {}
71 __assert_module_implements_module::<$ty>();
72 };
73 };
74}
75
76#[macro_export]
77#[doc(hidden)]
78macro_rules! kernel_module_license {
79 (@license "MPL-1.0") => {};
80 (@license "MPL-1.1") => {};
81 (@license "MPL-2.0") => {};
82}
83
84/// The top level trait for a kernel module.
85///
86/// This is to be implemented on a ZST to allow the module to hook into
87/// various points during kernel boot.
88///
89/// # Examples
90///
91/// See the [module-level documentation](self).
92#[expect(rustdoc::missing_doc_code_examples, reason = "documented at module level")]
93pub trait Module {
94 /// Called immediately upon kernel start.
95 ///
96 /// At this point many kernel features are unusable, such as
97 /// threading, async tasks, and memory allocation.
98 #[expect(clippy::missing_errors_doc, reason = "errors depend on implementor")]
99 #[expect(rustdoc::missing_doc_code_examples, reason = "not called by end users")]
100 fn early_init() -> Result<(), &'static str> { Ok(()) }
101
102 /// Called once the kernel is ready to start userspace applications.
103 #[expect(clippy::missing_errors_doc, reason = "errors depend on implementor")]
104 #[expect(rustdoc::missing_doc_code_examples, reason = "not called by end users")]
105 fn late_init() -> Result<(), &'static str> { Ok(()) }
106}