1 // SPDX-License-Identifier: GPL-2.0
2
3 //! Crate for all kernel procedural macros.
4
5 mod concat_idents;
6 mod helpers;
7 mod module;
8 mod vtable;
9
10 use proc_macro::TokenStream;
11
12 /// Declares a kernel module.
13 ///
14 /// The `type` argument should be a type which implements the [`Module`]
15 /// trait. Also accepts various forms of kernel metadata.
16 ///
17 /// C header: [`include/linux/moduleparam.h`](../../../include/linux/moduleparam.h)
18 ///
19 /// [`Module`]: ../kernel/trait.Module.html
20 ///
21 /// # Examples
22 ///
23 /// ```ignore
24 /// use kernel::prelude::*;
25 ///
26 /// module!{
27 /// type: MyModule,
28 /// name: "my_kernel_module",
29 /// author: "Rust for Linux Contributors",
30 /// description: "My very own kernel module!",
31 /// license: "GPL",
32 /// params: {
33 /// my_i32: i32 {
34 /// default: 42,
35 /// permissions: 0o000,
36 /// description: "Example of i32",
37 /// },
38 /// writeable_i32: i32 {
39 /// default: 42,
40 /// permissions: 0o644,
41 /// description: "Example of i32",
42 /// },
43 /// },
44 /// }
45 ///
46 /// struct MyModule;
47 ///
48 /// impl kernel::Module for MyModule {
49 /// fn init() -> Result<Self> {
50 /// // If the parameter is writeable, then the kparam lock must be
51 /// // taken to read the parameter:
52 /// {
53 /// let lock = THIS_MODULE.kernel_param_lock();
54 /// pr_info!("i32 param is: {}\n", writeable_i32.read(&lock));
55 /// }
56 /// // If the parameter is read only, it can be read without locking
57 /// // the kernel parameters:
58 /// pr_info!("i32 param is: {}\n", my_i32.read());
59 /// Ok(Self)
60 /// }
61 /// }
62 /// ```
63 ///
64 /// # Supported argument types
65 /// - `type`: type which implements the [`Module`] trait (required).
66 /// - `name`: byte array of the name of the kernel module (required).
67 /// - `author`: byte array of the author of the kernel module.
68 /// - `description`: byte array of the description of the kernel module.
69 /// - `license`: byte array of the license of the kernel module (required).
70 /// - `alias`: byte array of alias name of the kernel module.
71 #[proc_macro]
module(ts: TokenStream) -> TokenStream72 pub fn module(ts: TokenStream) -> TokenStream {
73 module::module(ts)
74 }
75
76 /// Declares or implements a vtable trait.
77 ///
78 /// Linux's use of pure vtables is very close to Rust traits, but they differ
79 /// in how unimplemented functions are represented. In Rust, traits can provide
80 /// default implementation for all non-required methods (and the default
81 /// implementation could just return `Error::EINVAL`); Linux typically use C
82 /// `NULL` pointers to represent these functions.
83 ///
84 /// This attribute is intended to close the gap. Traits can be declared and
85 /// implemented with the `#[vtable]` attribute, and a `HAS_*` associated constant
86 /// will be generated for each method in the trait, indicating if the implementor
87 /// has overridden a method.
88 ///
89 /// This attribute is not needed if all methods are required.
90 ///
91 /// # Examples
92 ///
93 /// ```ignore
94 /// use kernel::prelude::*;
95 ///
96 /// // Declares a `#[vtable]` trait
97 /// #[vtable]
98 /// pub trait Operations: Send + Sync + Sized {
99 /// fn foo(&self) -> Result<()> {
100 /// Err(EINVAL)
101 /// }
102 ///
103 /// fn bar(&self) -> Result<()> {
104 /// Err(EINVAL)
105 /// }
106 /// }
107 ///
108 /// struct Foo;
109 ///
110 /// // Implements the `#[vtable]` trait
111 /// #[vtable]
112 /// impl Operations for Foo {
113 /// fn foo(&self) -> Result<()> {
114 /// # Err(EINVAL)
115 /// // ...
116 /// }
117 /// }
118 ///
119 /// assert_eq!(<Foo as Operations>::HAS_FOO, true);
120 /// assert_eq!(<Foo as Operations>::HAS_BAR, false);
121 /// ```
122 #[proc_macro_attribute]
vtable(attr: TokenStream, ts: TokenStream) -> TokenStream123 pub fn vtable(attr: TokenStream, ts: TokenStream) -> TokenStream {
124 vtable::vtable(attr, ts)
125 }
126
127 /// Concatenate two identifiers.
128 ///
129 /// This is useful in macros that need to declare or reference items with names
130 /// starting with a fixed prefix and ending in a user specified name. The resulting
131 /// identifier has the span of the second argument.
132 ///
133 /// # Examples
134 ///
135 /// ```ignore
136 /// use kernel::macro::concat_idents;
137 ///
138 /// macro_rules! pub_no_prefix {
139 /// ($prefix:ident, $($newname:ident),+) => {
140 /// $(pub(crate) const $newname: u32 = kernel::macros::concat_idents!($prefix, $newname);)+
141 /// };
142 /// }
143 ///
144 /// pub_no_prefix!(
145 /// binder_driver_return_protocol_,
146 /// BR_OK,
147 /// BR_ERROR,
148 /// BR_TRANSACTION,
149 /// BR_REPLY,
150 /// BR_DEAD_REPLY,
151 /// BR_TRANSACTION_COMPLETE,
152 /// BR_INCREFS,
153 /// BR_ACQUIRE,
154 /// BR_RELEASE,
155 /// BR_DECREFS,
156 /// BR_NOOP,
157 /// BR_SPAWN_LOOPER,
158 /// BR_DEAD_BINDER,
159 /// BR_CLEAR_DEATH_NOTIFICATION_DONE,
160 /// BR_FAILED_REPLY
161 /// );
162 ///
163 /// assert_eq!(BR_OK, binder_driver_return_protocol_BR_OK);
164 /// ```
165 #[proc_macro]
concat_idents(ts: TokenStream) -> TokenStream166 pub fn concat_idents(ts: TokenStream) -> TokenStream {
167 concat_idents::concat_idents(ts)
168 }
169