xref: /linux/rust/macros/module.rs (revision e119c2fe8c78632188f6cdeae620951a7032855a)
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 
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> {
33     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 
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 
86     fn emit_only_builtin(&mut self, field: &str, content: &str, param: bool) {
87         self.emit_base(field, content, true, param)
88     }
89 
90     fn emit_only_loadable(&mut self, field: &str, content: &str, param: bool) {
91         self.emit_base(field, content, false, param)
92     }
93 
94     fn emit(&mut self, field: &str, content: &str) {
95         self.emit_internal(field, content, false);
96     }
97 
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 
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 
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}\").as_bytes_with_nul()
137                                 }} else {{
138                                     ::kernel::c_str!(\"{module_name}.{param_name}\")
139                                         .as_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 
172 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 
188 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     params: Option<Vec<Parameter>>,
209 }
210 
211 #[derive(Debug)]
212 struct Parameter {
213     name: String,
214     ptype: String,
215     default: String,
216     description: String,
217 }
218 
219 fn expect_params(it: &mut token_stream::IntoIter) -> Vec<Parameter> {
220     let params = expect_group(it);
221     assert_eq!(params.delimiter(), Delimiter::Brace);
222     let mut it = params.stream().into_iter();
223     let mut parsed = Vec::new();
224 
225     loop {
226         let param_name = match it.next() {
227             Some(TokenTree::Ident(ident)) => ident.to_string(),
228             Some(_) => panic!("Expected Ident or end"),
229             None => break,
230         };
231 
232         assert_eq!(expect_punct(&mut it), ':');
233         let param_type = expect_ident(&mut it);
234         let group = expect_group(&mut it);
235         assert_eq!(group.delimiter(), Delimiter::Brace);
236         assert_eq!(expect_punct(&mut it), ',');
237 
238         let mut param_it = group.stream().into_iter();
239         let param_default = expect_param_default(&mut param_it);
240         let param_description = expect_string_field(&mut param_it, "description");
241         expect_end(&mut param_it);
242 
243         parsed.push(Parameter {
244             name: param_name,
245             ptype: param_type,
246             default: param_default,
247             description: param_description,
248         })
249     }
250 
251     parsed
252 }
253 
254 impl ModuleInfo {
255     fn parse(it: &mut token_stream::IntoIter) -> Self {
256         let mut info = ModuleInfo::default();
257 
258         const EXPECTED_KEYS: &[&str] = &[
259             "type",
260             "name",
261             "authors",
262             "description",
263             "license",
264             "alias",
265             "firmware",
266             "params",
267         ];
268         const REQUIRED_KEYS: &[&str] = &["type", "name", "license"];
269         let mut seen_keys = Vec::new();
270 
271         loop {
272             let key = match it.next() {
273                 Some(TokenTree::Ident(ident)) => ident.to_string(),
274                 Some(_) => panic!("Expected Ident or end"),
275                 None => break,
276             };
277 
278             if seen_keys.contains(&key) {
279                 panic!("Duplicated key \"{key}\". Keys can only be specified once.");
280             }
281 
282             assert_eq!(expect_punct(it), ':');
283 
284             match key.as_str() {
285                 "type" => info.type_ = expect_ident(it),
286                 "name" => info.name = expect_string_ascii(it),
287                 "authors" => info.authors = Some(expect_string_array(it)),
288                 "description" => info.description = Some(expect_string(it)),
289                 "license" => info.license = expect_string_ascii(it),
290                 "alias" => info.alias = Some(expect_string_array(it)),
291                 "firmware" => info.firmware = Some(expect_string_array(it)),
292                 "params" => info.params = Some(expect_params(it)),
293                 _ => panic!("Unknown key \"{key}\". Valid keys are: {EXPECTED_KEYS:?}."),
294             }
295 
296             assert_eq!(expect_punct(it), ',');
297 
298             seen_keys.push(key);
299         }
300 
301         expect_end(it);
302 
303         for key in REQUIRED_KEYS {
304             if !seen_keys.iter().any(|e| e == key) {
305                 panic!("Missing required key \"{key}\".");
306             }
307         }
308 
309         let mut ordered_keys: Vec<&str> = Vec::new();
310         for key in EXPECTED_KEYS {
311             if seen_keys.iter().any(|e| e == key) {
312                 ordered_keys.push(key);
313             }
314         }
315 
316         if seen_keys != ordered_keys {
317             panic!("Keys are not ordered as expected. Order them like: {ordered_keys:?}.");
318         }
319 
320         info
321     }
322 }
323 
324 pub(crate) fn module(ts: TokenStream) -> TokenStream {
325     let mut it = ts.into_iter();
326 
327     let info = ModuleInfo::parse(&mut it);
328 
329     // Rust does not allow hyphens in identifiers, use underscore instead.
330     let ident = info.name.replace('-', "_");
331     let mut modinfo = ModInfoBuilder::new(ident.as_ref());
332     if let Some(authors) = &info.authors {
333         for author in authors {
334             modinfo.emit("author", author);
335         }
336     }
337     if let Some(description) = &info.description {
338         modinfo.emit("description", description);
339     }
340     modinfo.emit("license", &info.license);
341     if let Some(aliases) = &info.alias {
342         for alias in aliases {
343             modinfo.emit("alias", alias);
344         }
345     }
346     if let Some(firmware) = &info.firmware {
347         for fw in firmware {
348             modinfo.emit("firmware", fw);
349         }
350     }
351 
352     // Built-in modules also export the `file` modinfo string.
353     let file =
354         std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable");
355     modinfo.emit_only_builtin("file", &file, false);
356 
357     modinfo.emit_params(&info);
358 
359     format!(
360         "
361             /// The module name.
362             ///
363             /// Used by the printing macros, e.g. [`info!`].
364             const __LOG_PREFIX: &[u8] = b\"{name}\\0\";
365 
366             // SAFETY: `__this_module` is constructed by the kernel at load time and will not be
367             // freed until the module is unloaded.
368             #[cfg(MODULE)]
369             static THIS_MODULE: ::kernel::ThisModule = unsafe {{
370                 extern \"C\" {{
371                     static __this_module: ::kernel::types::Opaque<::kernel::bindings::module>;
372                 }}
373 
374                 ::kernel::ThisModule::from_ptr(__this_module.get())
375             }};
376             #[cfg(not(MODULE))]
377             static THIS_MODULE: ::kernel::ThisModule = unsafe {{
378                 ::kernel::ThisModule::from_ptr(::core::ptr::null_mut())
379             }};
380 
381             /// The `LocalModule` type is the type of the module created by `module!`,
382             /// `module_pci_driver!`, `module_platform_driver!`, etc.
383             type LocalModule = {type_};
384 
385             impl ::kernel::ModuleMetadata for {type_} {{
386                 const NAME: &'static ::kernel::str::CStr = ::kernel::c_str!(\"{name}\");
387             }}
388 
389             // Double nested modules, since then nobody can access the public items inside.
390             mod __module_init {{
391                 mod __module_init {{
392                     use super::super::{type_};
393                     use pin_init::PinInit;
394 
395                     /// The \"Rust loadable module\" mark.
396                     //
397                     // This may be best done another way later on, e.g. as a new modinfo
398                     // key or a new section. For the moment, keep it simple.
399                     #[cfg(MODULE)]
400                     #[doc(hidden)]
401                     #[used(compiler)]
402                     static __IS_RUST_MODULE: () = ();
403 
404                     static mut __MOD: ::core::mem::MaybeUninit<{type_}> =
405                         ::core::mem::MaybeUninit::uninit();
406 
407                     // Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
408                     /// # Safety
409                     ///
410                     /// This function must not be called after module initialization, because it may be
411                     /// freed after that completes.
412                     #[cfg(MODULE)]
413                     #[doc(hidden)]
414                     #[no_mangle]
415                     #[link_section = \".init.text\"]
416                     pub unsafe extern \"C\" fn init_module() -> ::kernel::ffi::c_int {{
417                         // SAFETY: This function is inaccessible to the outside due to the double
418                         // module wrapping it. It is called exactly once by the C side via its
419                         // unique name.
420                         unsafe {{ __init() }}
421                     }}
422 
423                     #[cfg(MODULE)]
424                     #[doc(hidden)]
425                     #[used(compiler)]
426                     #[link_section = \".init.data\"]
427                     static __UNIQUE_ID___addressable_init_module: unsafe extern \"C\" fn() -> i32 = init_module;
428 
429                     #[cfg(MODULE)]
430                     #[doc(hidden)]
431                     #[no_mangle]
432                     #[link_section = \".exit.text\"]
433                     pub extern \"C\" fn cleanup_module() {{
434                         // SAFETY:
435                         // - This function is inaccessible to the outside due to the double
436                         //   module wrapping it. It is called exactly once by the C side via its
437                         //   unique name,
438                         // - furthermore it is only called after `init_module` has returned `0`
439                         //   (which delegates to `__init`).
440                         unsafe {{ __exit() }}
441                     }}
442 
443                     #[cfg(MODULE)]
444                     #[doc(hidden)]
445                     #[used(compiler)]
446                     #[link_section = \".exit.data\"]
447                     static __UNIQUE_ID___addressable_cleanup_module: extern \"C\" fn() = cleanup_module;
448 
449                     // Built-in modules are initialized through an initcall pointer
450                     // and the identifiers need to be unique.
451                     #[cfg(not(MODULE))]
452                     #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))]
453                     #[doc(hidden)]
454                     #[link_section = \"{initcall_section}\"]
455                     #[used(compiler)]
456                     pub static __{ident}_initcall: extern \"C\" fn() ->
457                         ::kernel::ffi::c_int = __{ident}_init;
458 
459                     #[cfg(not(MODULE))]
460                     #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)]
461                     ::core::arch::global_asm!(
462                         r#\".section \"{initcall_section}\", \"a\"
463                         __{ident}_initcall:
464                             .long   __{ident}_init - .
465                             .previous
466                         \"#
467                     );
468 
469                     #[cfg(not(MODULE))]
470                     #[doc(hidden)]
471                     #[no_mangle]
472                     pub extern \"C\" fn __{ident}_init() -> ::kernel::ffi::c_int {{
473                         // SAFETY: This function is inaccessible to the outside due to the double
474                         // module wrapping it. It is called exactly once by the C side via its
475                         // placement above in the initcall section.
476                         unsafe {{ __init() }}
477                     }}
478 
479                     #[cfg(not(MODULE))]
480                     #[doc(hidden)]
481                     #[no_mangle]
482                     pub extern \"C\" fn __{ident}_exit() {{
483                         // SAFETY:
484                         // - This function is inaccessible to the outside due to the double
485                         //   module wrapping it. It is called exactly once by the C side via its
486                         //   unique name,
487                         // - furthermore it is only called after `__{ident}_init` has
488                         //   returned `0` (which delegates to `__init`).
489                         unsafe {{ __exit() }}
490                     }}
491 
492                     /// # Safety
493                     ///
494                     /// This function must only be called once.
495                     unsafe fn __init() -> ::kernel::ffi::c_int {{
496                         let initer =
497                             <{type_} as ::kernel::InPlaceModule>::init(&super::super::THIS_MODULE);
498                         // SAFETY: No data race, since `__MOD` can only be accessed by this module
499                         // and there only `__init` and `__exit` access it. These functions are only
500                         // called once and `__exit` cannot be called before or during `__init`.
501                         match unsafe {{ initer.__pinned_init(__MOD.as_mut_ptr()) }} {{
502                             Ok(m) => 0,
503                             Err(e) => e.to_errno(),
504                         }}
505                     }}
506 
507                     /// # Safety
508                     ///
509                     /// This function must
510                     /// - only be called once,
511                     /// - be called after `__init` has been called and returned `0`.
512                     unsafe fn __exit() {{
513                         // SAFETY: No data race, since `__MOD` can only be accessed by this module
514                         // and there only `__init` and `__exit` access it. These functions are only
515                         // called once and `__init` was already called.
516                         unsafe {{
517                             // Invokes `drop()` on `__MOD`, which should be used for cleanup.
518                             __MOD.assume_init_drop();
519                         }}
520                     }}
521                     {modinfo}
522                 }}
523             }}
524             mod module_parameters {{
525                 {params}
526             }}
527         ",
528         type_ = info.type_,
529         name = info.name,
530         ident = ident,
531         modinfo = modinfo.buffer,
532         params = modinfo.param_buffer,
533         initcall_section = ".initcall6.init"
534     )
535     .parse()
536     .expect("Error parsing formatted string into token stream.")
537 }
538