xref: /linux/rust/macros/module.rs (revision c84d574698bad2c02aad506dfe712f83cbe3b771)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 use crate::helpers::*;
4 use proc_macro::{token_stream, Delimiter, Literal, TokenStream, TokenTree};
5 use std::fmt::Write;
6 
expect_string_array(it: &mut token_stream::IntoIter) -> Vec<String>7 fn expect_string_array(it: &mut token_stream::IntoIter) -> Vec<String> {
8     let group = expect_group(it);
9     assert_eq!(group.delimiter(), Delimiter::Bracket);
10     let mut values = Vec::new();
11     let mut it = group.stream().into_iter();
12 
13     while let Some(val) = try_string(&mut it) {
14         assert!(val.is_ascii(), "Expected ASCII string");
15         values.push(val);
16         match it.next() {
17             Some(TokenTree::Punct(punct)) => assert_eq!(punct.as_char(), ','),
18             None => break,
19             _ => panic!("Expected ',' or end of array"),
20         }
21     }
22     values
23 }
24 
25 struct ModInfoBuilder<'a> {
26     module: &'a str,
27     counter: usize,
28     buffer: String,
29     param_buffer: String,
30 }
31 
32 impl<'a> ModInfoBuilder<'a> {
new(module: &'a str) -> Self33     fn new(module: &'a str) -> Self {
34         ModInfoBuilder {
35             module,
36             counter: 0,
37             buffer: String::new(),
38             param_buffer: String::new(),
39         }
40     }
41 
emit_base(&mut self, field: &str, content: &str, builtin: bool, param: bool)42     fn emit_base(&mut self, field: &str, content: &str, builtin: bool, param: bool) {
43         let string = if builtin {
44             // Built-in modules prefix their modinfo strings by `module.`.
45             format!(
46                 "{module}.{field}={content}\0",
47                 module = self.module,
48                 field = field,
49                 content = content
50             )
51         } else {
52             // Loadable modules' modinfo strings go as-is.
53             format!("{field}={content}\0")
54         };
55 
56         let buffer = if param {
57             &mut self.param_buffer
58         } else {
59             &mut self.buffer
60         };
61 
62         write!(
63             buffer,
64             "
65                 {cfg}
66                 #[doc(hidden)]
67                 #[cfg_attr(not(target_os = \"macos\"), link_section = \".modinfo\")]
68                 #[used(compiler)]
69                 pub static __{module}_{counter}: [u8; {length}] = *{string};
70             ",
71             cfg = if builtin {
72                 "#[cfg(not(MODULE))]"
73             } else {
74                 "#[cfg(MODULE)]"
75             },
76             module = self.module.to_uppercase(),
77             counter = self.counter,
78             length = string.len(),
79             string = Literal::byte_string(string.as_bytes()),
80         )
81         .unwrap();
82 
83         self.counter += 1;
84     }
85 
emit_only_builtin(&mut self, field: &str, content: &str, param: bool)86     fn emit_only_builtin(&mut self, field: &str, content: &str, param: bool) {
87         self.emit_base(field, content, true, param)
88     }
89 
emit_only_loadable(&mut self, field: &str, content: &str, param: bool)90     fn emit_only_loadable(&mut self, field: &str, content: &str, param: bool) {
91         self.emit_base(field, content, false, param)
92     }
93 
emit(&mut self, field: &str, content: &str)94     fn emit(&mut self, field: &str, content: &str) {
95         self.emit_internal(field, content, false);
96     }
97 
emit_internal(&mut self, field: &str, content: &str, param: bool)98     fn emit_internal(&mut self, field: &str, content: &str, param: bool) {
99         self.emit_only_builtin(field, content, param);
100         self.emit_only_loadable(field, content, param);
101     }
102 
emit_param(&mut self, field: &str, param: &str, content: &str)103     fn emit_param(&mut self, field: &str, param: &str, content: &str) {
104         let content = format!("{param}:{content}", param = param, content = content);
105         self.emit_internal(field, &content, true);
106     }
107 
emit_params(&mut self, info: &ModuleInfo)108     fn emit_params(&mut self, info: &ModuleInfo) {
109         let Some(params) = &info.params else {
110             return;
111         };
112 
113         for param in params {
114             let ops = param_ops_path(&param.ptype);
115 
116             // Note: The spelling of these fields is dictated by the user space
117             // tool `modinfo`.
118             self.emit_param("parmtype", &param.name, &param.ptype);
119             self.emit_param("parm", &param.name, &param.description);
120 
121             write!(
122                 self.param_buffer,
123                 "
124                 pub(crate) static {param_name}:
125                     ::kernel::module_param::ModuleParamAccess<{param_type}> =
126                         ::kernel::module_param::ModuleParamAccess::new({param_default});
127 
128                 const _: () = {{
129                     #[link_section = \"__param\"]
130                     #[used]
131                     static __{module_name}_{param_name}_struct:
132                         ::kernel::module_param::KernelParam =
133                         ::kernel::module_param::KernelParam::new(
134                             ::kernel::bindings::kernel_param {{
135                                 name: if ::core::cfg!(MODULE) {{
136                                     ::kernel::c_str!(\"{param_name}\").to_bytes_with_nul()
137                                 }} else {{
138                                     ::kernel::c_str!(\"{module_name}.{param_name}\")
139                                         .to_bytes_with_nul()
140                                 }}.as_ptr(),
141                                 // SAFETY: `__this_module` is constructed by the kernel at load
142                                 // time and will not be freed until the module is unloaded.
143                                 #[cfg(MODULE)]
144                                 mod_: unsafe {{
145                                     core::ptr::from_ref(&::kernel::bindings::__this_module)
146                                         .cast_mut()
147                                 }},
148                                 #[cfg(not(MODULE))]
149                                 mod_: ::core::ptr::null_mut(),
150                                 ops: core::ptr::from_ref(&{ops}),
151                                 perm: 0, // Will not appear in sysfs
152                                 level: -1,
153                                 flags: 0,
154                                 __bindgen_anon_1: ::kernel::bindings::kernel_param__bindgen_ty_1 {{
155                                     arg: {param_name}.as_void_ptr()
156                                 }},
157                             }}
158                         );
159                 }};
160                 ",
161                 module_name = info.name,
162                 param_type = param.ptype,
163                 param_default = param.default,
164                 param_name = param.name,
165                 ops = ops,
166             )
167             .unwrap();
168         }
169     }
170 }
171 
param_ops_path(param_type: &str) -> &'static str172 fn param_ops_path(param_type: &str) -> &'static str {
173     match param_type {
174         "i8" => "::kernel::module_param::PARAM_OPS_I8",
175         "u8" => "::kernel::module_param::PARAM_OPS_U8",
176         "i16" => "::kernel::module_param::PARAM_OPS_I16",
177         "u16" => "::kernel::module_param::PARAM_OPS_U16",
178         "i32" => "::kernel::module_param::PARAM_OPS_I32",
179         "u32" => "::kernel::module_param::PARAM_OPS_U32",
180         "i64" => "::kernel::module_param::PARAM_OPS_I64",
181         "u64" => "::kernel::module_param::PARAM_OPS_U64",
182         "isize" => "::kernel::module_param::PARAM_OPS_ISIZE",
183         "usize" => "::kernel::module_param::PARAM_OPS_USIZE",
184         t => panic!("Unsupported parameter type {}", t),
185     }
186 }
187 
expect_param_default(param_it: &mut token_stream::IntoIter) -> String188 fn expect_param_default(param_it: &mut token_stream::IntoIter) -> String {
189     assert_eq!(expect_ident(param_it), "default");
190     assert_eq!(expect_punct(param_it), ':');
191     let sign = try_sign(param_it);
192     let default = try_literal(param_it).expect("Expected default param value");
193     assert_eq!(expect_punct(param_it), ',');
194     let mut value = sign.map(String::from).unwrap_or_default();
195     value.push_str(&default);
196     value
197 }
198 
199 #[derive(Debug, Default)]
200 struct ModuleInfo {
201     type_: String,
202     license: String,
203     name: String,
204     authors: Option<Vec<String>>,
205     description: Option<String>,
206     alias: Option<Vec<String>>,
207     firmware: Option<Vec<String>>,
208     imports_ns: Option<Vec<String>>,
209     params: Option<Vec<Parameter>>,
210 }
211 
212 #[derive(Debug)]
213 struct Parameter {
214     name: String,
215     ptype: String,
216     default: String,
217     description: String,
218 }
219 
expect_params(it: &mut token_stream::IntoIter) -> Vec<Parameter>220 fn expect_params(it: &mut token_stream::IntoIter) -> Vec<Parameter> {
221     let params = expect_group(it);
222     assert_eq!(params.delimiter(), Delimiter::Brace);
223     let mut it = params.stream().into_iter();
224     let mut parsed = Vec::new();
225 
226     loop {
227         let param_name = match it.next() {
228             Some(TokenTree::Ident(ident)) => ident.to_string(),
229             Some(_) => panic!("Expected Ident or end"),
230             None => break,
231         };
232 
233         assert_eq!(expect_punct(&mut it), ':');
234         let param_type = expect_ident(&mut it);
235         let group = expect_group(&mut it);
236         assert_eq!(group.delimiter(), Delimiter::Brace);
237         assert_eq!(expect_punct(&mut it), ',');
238 
239         let mut param_it = group.stream().into_iter();
240         let param_default = expect_param_default(&mut param_it);
241         let param_description = expect_string_field(&mut param_it, "description");
242         expect_end(&mut param_it);
243 
244         parsed.push(Parameter {
245             name: param_name,
246             ptype: param_type,
247             default: param_default,
248             description: param_description,
249         })
250     }
251 
252     parsed
253 }
254 
255 impl ModuleInfo {
parse(it: &mut token_stream::IntoIter) -> Self256     fn parse(it: &mut token_stream::IntoIter) -> Self {
257         let mut info = ModuleInfo::default();
258 
259         const EXPECTED_KEYS: &[&str] = &[
260             "type",
261             "name",
262             "authors",
263             "description",
264             "license",
265             "alias",
266             "firmware",
267             "imports_ns",
268             "params",
269         ];
270         const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
271         let mut seen_keys = Vec::new();
272 
273         loop {
274             let key = match it.next() {
275                 Some(TokenTree::Ident(ident)) => ident.to_string(),
276                 Some(_) => panic!("Expected Ident or end"),
277                 None => break,
278             };
279 
280             if seen_keys.contains(&key) {
281                 panic!("Duplicated key \"{key}\". Keys can only be specified once.");
282             }
283 
284             assert_eq!(expect_punct(it), ':');
285 
286             match key.as_str() {
287                 "type" => info.type_ = expect_ident(it),
288                 "name" => info.name = expect_string_ascii(it),
289                 "authors" => info.authors = Some(expect_string_array(it)),
290                 "description" => info.description = Some(expect_string(it)),
291                 "license" => info.license = expect_string_ascii(it),
292                 "alias" => info.alias = Some(expect_string_array(it)),
293                 "firmware" => info.firmware = Some(expect_string_array(it)),
294                 "imports_ns" => info.imports_ns = Some(expect_string_array(it)),
295                 "params" => info.params = Some(expect_params(it)),
296                 _ => panic!("Unknown key \"{key}\". Valid keys are: {EXPECTED_KEYS:?}."),
297             }
298 
299             assert_eq!(expect_punct(it), ',');
300 
301             seen_keys.push(key);
302         }
303 
304         expect_end(it);
305 
306         for key in REQUIRED_KEYS {
307             if !seen_keys.iter().any(|e| e == key) {
308                 panic!("Missing required key \"{key}\".");
309             }
310         }
311 
312         let mut ordered_keys: Vec<&str> = Vec::new();
313         for key in EXPECTED_KEYS {
314             if seen_keys.iter().any(|e| e == key) {
315                 ordered_keys.push(key);
316             }
317         }
318 
319         if seen_keys != ordered_keys {
320             panic!("Keys are not ordered as expected. Order them like: {ordered_keys:?}.");
321         }
322 
323         info
324     }
325 }
326 
module(ts: TokenStream) -> TokenStream327 pub(crate) fn module(ts: TokenStream) -> TokenStream {
328     let mut it = ts.into_iter();
329 
330     let info = ModuleInfo::parse(&mut it);
331 
332     // Rust does not allow hyphens in identifiers, use underscore instead.
333     let ident = info.name.replace('-', "_");
334     let mut modinfo = ModInfoBuilder::new(ident.as_ref());
335     if let Some(authors) = &info.authors {
336         for author in authors {
337             modinfo.emit("author", author);
338         }
339     }
340     if let Some(description) = &info.description {
341         modinfo.emit("description", description);
342     }
343     modinfo.emit("license", &info.license);
344     if let Some(aliases) = &info.alias {
345         for alias in aliases {
346             modinfo.emit("alias", alias);
347         }
348     }
349     if let Some(firmware) = &info.firmware {
350         for fw in firmware {
351             modinfo.emit("firmware", fw);
352         }
353     }
354     if let Some(imports) = &info.imports_ns {
355         for ns in imports {
356             modinfo.emit("import_ns", ns);
357         }
358     }
359 
360     // Built-in modules also export the `file` modinfo string.
361     let file =
362         std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable");
363     modinfo.emit_only_builtin("file", &file, false);
364 
365     modinfo.emit_params(&info);
366 
367     format!(
368         "
369             /// The module name.
370             ///
371             /// Used by the printing macros, e.g. [`info!`].
372             const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
373 
374             // SAFETY: `__this_module` is constructed by the kernel at load time and will not be
375             // freed until the module is unloaded.
376             #[cfg(MODULE)]
377             static THIS_MODULE: ::kernel::ThisModule = unsafe {{
378                 extern \"C\" {{
379                     static __this_module: ::kernel::types::Opaque<::kernel::bindings::module>;
380                 }}
381 
382                 ::kernel::ThisModule::from_ptr(__this_module.get())
383             }};
384             #[cfg(not(MODULE))]
385             static THIS_MODULE: ::kernel::ThisModule = unsafe {{
386                 ::kernel::ThisModule::from_ptr(::core::ptr::null_mut())
387             }};
388 
389             /// The `LocalModule` type is the type of the module created by `module!`,
390             /// `module_pci_driver!`, `module_platform_driver!`, etc.
391             type LocalModule = {type_};
392 
393             impl ::kernel::ModuleMetadata for {type_} {{
394                 const NAME: &'static ::kernel::str::CStr = c\"{name}\";
395             }}
396 
397             // Double nested modules, since then nobody can access the public items inside.
398             mod __module_init {{
399                 mod __module_init {{
400                     use super::super::{type_};
401                     use pin_init::PinInit;
402 
403                     /// The \"Rust loadable module\" mark.
404                     //
405                     // This may be best done another way later on, e.g. as a new modinfo
406                     // key or a new section. For the moment, keep it simple.
407                     #[cfg(MODULE)]
408                     #[doc(hidden)]
409                     #[used(compiler)]
410                     static __IS_RUST_MODULE: () = ();
411 
412                     static mut __MOD: ::core::mem::MaybeUninit<{type_}> =
413                         ::core::mem::MaybeUninit::uninit();
414 
415                     // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
416                     /// # Safety
417                     ///
418                     /// This function must not be called after module initialization, because it may be
419                     /// freed after that completes.
420                     #[cfg(MODULE)]
421                     #[doc(hidden)]
422                     #[no_mangle]
423                     #[link_section = \".init.text\"]
424                     pub unsafe extern \"C\" fn init_module() -> ::kernel::ffi::c_int {{
425                         // SAFETY: This function is inaccessible to the outside due to the double
426                         // module wrapping it. It is called exactly once by the C side via its
427                         // unique name.
428                         unsafe {{ __init() }}
429                     }}
430 
431                     #[cfg(MODULE)]
432                     #[doc(hidden)]
433                     #[used(compiler)]
434                     #[link_section = \".init.data\"]
435                     static __UNIQUE_ID___addressable_init_module: unsafe extern \"C\" fn() -> i32 = init_module;
436 
437                     #[cfg(MODULE)]
438                     #[doc(hidden)]
439                     #[no_mangle]
440                     #[link_section = \".exit.text\"]
441                     pub extern \"C\" fn cleanup_module() {{
442                         // SAFETY:
443                         // - This function is inaccessible to the outside due to the double
444                         //   module wrapping it. It is called exactly once by the C side via its
445                         //   unique name,
446                         // - furthermore it is only called after `init_module` has returned `0`
447                         //   (which delegates to `__init`).
448                         unsafe {{ __exit() }}
449                     }}
450 
451                     #[cfg(MODULE)]
452                     #[doc(hidden)]
453                     #[used(compiler)]
454                     #[link_section = \".exit.data\"]
455                     static __UNIQUE_ID___addressable_cleanup_module: extern \"C\" fn() = cleanup_module;
456 
457                     // Built-in modules are initialized through an initcall pointer
458                     // and the identifiers need to be unique.
459                     #[cfg(not(MODULE))]
460                     #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
461                     #[doc(hidden)]
462                     #[link_section = \"{initcall_section}\"]
463                     #[used(compiler)]
464                     pub static __{ident}_initcall: extern \"C\" fn() ->
465                         ::kernel::ffi::c_int = __{ident}_init;
466 
467                     #[cfg(not(MODULE))]
468                     #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
469                     ::core::arch::global_asm!(
470                         r#\".section \"{initcall_section}\", \"a\"
471                         __{ident}_initcall:
472                             .long   __{ident}_init - .
473                             .previous
474                         \"#
475                     );
476 
477                     #[cfg(not(MODULE))]
478                     #[doc(hidden)]
479                     #[no_mangle]
480                     pub extern \"C\" fn __{ident}_init() -> ::kernel::ffi::c_int {{
481                         // SAFETY: This function is inaccessible to the outside due to the double
482                         // module wrapping it. It is called exactly once by the C side via its
483                         // placement above in the initcall section.
484                         unsafe {{ __init() }}
485                     }}
486 
487                     #[cfg(not(MODULE))]
488                     #[doc(hidden)]
489                     #[no_mangle]
490                     pub extern \"C\" fn __{ident}_exit() {{
491                         // SAFETY:
492                         // - This function is inaccessible to the outside due to the double
493                         //   module wrapping it. It is called exactly once by the C side via its
494                         //   unique name,
495                         // - furthermore it is only called after `__{ident}_init` has
496                         //   returned `0` (which delegates to `__init`).
497                         unsafe {{ __exit() }}
498                     }}
499 
500                     /// # Safety
501                     ///
502                     /// This function must only be called once.
503                     unsafe fn __init() -> ::kernel::ffi::c_int {{
504                         let initer =
505                             <{type_} as ::kernel::InPlaceModule>::init(&super::super::THIS_MODULE);
506                         // SAFETY: No data race, since `__MOD` can only be accessed by this module
507                         // and there only `__init` and `__exit` access it. These functions are only
508                         // called once and `__exit` cannot be called before or during `__init`.
509                         match unsafe {{ initer.__pinned_init(__MOD.as_mut_ptr()) }} {{
510                             Ok(m) => 0,
511                             Err(e) => e.to_errno(),
512                         }}
513                     }}
514 
515                     /// # Safety
516                     ///
517                     /// This function must
518                     /// - only be called once,
519                     /// - be called after `__init` has been called and returned `0`.
520                     unsafe fn __exit() {{
521                         // SAFETY: No data race, since `__MOD` can only be accessed by this module
522                         // and there only `__init` and `__exit` access it. These functions are only
523                         // called once and `__init` was already called.
524                         unsafe {{
525                             // Invokes `drop()` on `__MOD`, which should be used for cleanup.
526                             __MOD.assume_init_drop();
527                         }}
528                     }}
529                     {modinfo}
530                 }}
531             }}
532             mod module_parameters {{
533                 {params}
534             }}
535         ",
536         type_ = info.type_,
537         name = info.name,
538         ident = ident,
539         modinfo = modinfo.buffer,
540         params = modinfo.param_buffer,
541         initcall_section = ".initcall6.init"
542     )
543     .parse()
544     .expect("Error parsing formatted string into token stream.")
545 }
546