xref: /openbmc/linux/rust/macros/lib.rs (revision 0cb4228f)
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]
72 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]
123 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]
166 pub fn concat_idents(ts: TokenStream) -> TokenStream {
167     concat_idents::concat_idents(ts)
168 }
169