Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | |
| 3 | use crate::helpers::*; |
Asahi Lina | 39867fe | 2023-03-23 21:35:10 +0900 | [diff] [blame] | 4 | use proc_macro::{token_stream, Delimiter, Literal, TokenStream, TokenTree}; |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 5 | use std::fmt::Write; |
| 6 | |
Asahi Lina | 39867fe | 2023-03-23 21:35:10 +0900 | [diff] [blame] | 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 | |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 25 | struct ModInfoBuilder<'a> { |
| 26 | module: &'a str, |
| 27 | counter: usize, |
| 28 | buffer: String, |
| 29 | } |
| 30 | |
| 31 | impl<'a> ModInfoBuilder<'a> { |
| 32 | fn new(module: &'a str) -> Self { |
| 33 | ModInfoBuilder { |
| 34 | module, |
| 35 | counter: 0, |
| 36 | buffer: String::new(), |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | fn emit_base(&mut self, field: &str, content: &str, builtin: bool) { |
| 41 | let string = if builtin { |
| 42 | // Built-in modules prefix their modinfo strings by `module.`. |
| 43 | format!( |
| 44 | "{module}.{field}={content}\0", |
| 45 | module = self.module, |
| 46 | field = field, |
| 47 | content = content |
| 48 | ) |
| 49 | } else { |
| 50 | // Loadable modules' modinfo strings go as-is. |
| 51 | format!("{field}={content}\0", field = field, content = content) |
| 52 | }; |
| 53 | |
| 54 | write!( |
| 55 | &mut self.buffer, |
| 56 | " |
| 57 | {cfg} |
| 58 | #[doc(hidden)] |
| 59 | #[link_section = \".modinfo\"] |
| 60 | #[used] |
| 61 | pub static __{module}_{counter}: [u8; {length}] = *{string}; |
| 62 | ", |
| 63 | cfg = if builtin { |
| 64 | "#[cfg(not(MODULE))]" |
| 65 | } else { |
| 66 | "#[cfg(MODULE)]" |
| 67 | }, |
| 68 | module = self.module.to_uppercase(), |
| 69 | counter = self.counter, |
| 70 | length = string.len(), |
| 71 | string = Literal::byte_string(string.as_bytes()), |
| 72 | ) |
| 73 | .unwrap(); |
| 74 | |
| 75 | self.counter += 1; |
| 76 | } |
| 77 | |
| 78 | fn emit_only_builtin(&mut self, field: &str, content: &str) { |
| 79 | self.emit_base(field, content, true) |
| 80 | } |
| 81 | |
| 82 | fn emit_only_loadable(&mut self, field: &str, content: &str) { |
| 83 | self.emit_base(field, content, false) |
| 84 | } |
| 85 | |
| 86 | fn emit(&mut self, field: &str, content: &str) { |
| 87 | self.emit_only_builtin(field, content); |
| 88 | self.emit_only_loadable(field, content); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | #[derive(Debug, Default)] |
| 93 | struct ModuleInfo { |
| 94 | type_: String, |
| 95 | license: String, |
| 96 | name: String, |
| 97 | author: Option<String>, |
| 98 | description: Option<String>, |
Asahi Lina | 39867fe | 2023-03-23 21:35:10 +0900 | [diff] [blame] | 99 | alias: Option<Vec<String>>, |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | impl ModuleInfo { |
| 103 | fn parse(it: &mut token_stream::IntoIter) -> Self { |
| 104 | let mut info = ModuleInfo::default(); |
| 105 | |
| 106 | const EXPECTED_KEYS: &[&str] = |
| 107 | &["type", "name", "author", "description", "license", "alias"]; |
| 108 | const REQUIRED_KEYS: &[&str] = &["type", "name", "license"]; |
| 109 | let mut seen_keys = Vec::new(); |
| 110 | |
| 111 | loop { |
| 112 | let key = match it.next() { |
| 113 | Some(TokenTree::Ident(ident)) => ident.to_string(), |
| 114 | Some(_) => panic!("Expected Ident or end"), |
| 115 | None => break, |
| 116 | }; |
| 117 | |
| 118 | if seen_keys.contains(&key) { |
| 119 | panic!( |
| 120 | "Duplicated key \"{}\". Keys can only be specified once.", |
| 121 | key |
| 122 | ); |
| 123 | } |
| 124 | |
| 125 | assert_eq!(expect_punct(it), ':'); |
| 126 | |
| 127 | match key.as_str() { |
| 128 | "type" => info.type_ = expect_ident(it), |
Gary Guo | b13c988 | 2022-11-10 17:41:19 +0100 | [diff] [blame] | 129 | "name" => info.name = expect_string_ascii(it), |
| 130 | "author" => info.author = Some(expect_string(it)), |
| 131 | "description" => info.description = Some(expect_string(it)), |
| 132 | "license" => info.license = expect_string_ascii(it), |
Asahi Lina | 39867fe | 2023-03-23 21:35:10 +0900 | [diff] [blame] | 133 | "alias" => info.alias = Some(expect_string_array(it)), |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 134 | _ => panic!( |
| 135 | "Unknown key \"{}\". Valid keys are: {:?}.", |
| 136 | key, EXPECTED_KEYS |
| 137 | ), |
| 138 | } |
| 139 | |
| 140 | assert_eq!(expect_punct(it), ','); |
| 141 | |
| 142 | seen_keys.push(key); |
| 143 | } |
| 144 | |
| 145 | expect_end(it); |
| 146 | |
| 147 | for key in REQUIRED_KEYS { |
| 148 | if !seen_keys.iter().any(|e| e == key) { |
| 149 | panic!("Missing required key \"{}\".", key); |
| 150 | } |
| 151 | } |
| 152 | |
| 153 | let mut ordered_keys: Vec<&str> = Vec::new(); |
| 154 | for key in EXPECTED_KEYS { |
| 155 | if seen_keys.iter().any(|e| e == key) { |
| 156 | ordered_keys.push(key); |
| 157 | } |
| 158 | } |
| 159 | |
| 160 | if seen_keys != ordered_keys { |
| 161 | panic!( |
| 162 | "Keys are not ordered as expected. Order them like: {:?}.", |
| 163 | ordered_keys |
| 164 | ); |
| 165 | } |
| 166 | |
| 167 | info |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | pub(crate) fn module(ts: TokenStream) -> TokenStream { |
| 172 | let mut it = ts.into_iter(); |
| 173 | |
| 174 | let info = ModuleInfo::parse(&mut it); |
| 175 | |
| 176 | let mut modinfo = ModInfoBuilder::new(info.name.as_ref()); |
| 177 | if let Some(author) = info.author { |
| 178 | modinfo.emit("author", &author); |
| 179 | } |
| 180 | if let Some(description) = info.description { |
| 181 | modinfo.emit("description", &description); |
| 182 | } |
| 183 | modinfo.emit("license", &info.license); |
Asahi Lina | 39867fe | 2023-03-23 21:35:10 +0900 | [diff] [blame] | 184 | if let Some(aliases) = info.alias { |
| 185 | for alias in aliases { |
| 186 | modinfo.emit("alias", &alias); |
| 187 | } |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 188 | } |
| 189 | |
| 190 | // Built-in modules also export the `file` modinfo string. |
| 191 | let file = |
| 192 | std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable"); |
| 193 | modinfo.emit_only_builtin("file", &file); |
| 194 | |
| 195 | format!( |
| 196 | " |
| 197 | /// The module name. |
| 198 | /// |
| 199 | /// Used by the printing macros, e.g. [`info!`]. |
| 200 | const __LOG_PREFIX: &[u8] = b\"{name}\\0\"; |
| 201 | |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 202 | // SAFETY: `__this_module` is constructed by the kernel at load time and will not be |
| 203 | // freed until the module is unloaded. |
| 204 | #[cfg(MODULE)] |
| 205 | static THIS_MODULE: kernel::ThisModule = unsafe {{ |
Boqun Feng | f927589 | 2024-08-28 11:01:29 -0700 | [diff] [blame] | 206 | extern \"C\" {{ |
| 207 | static __this_module: kernel::types::Opaque<kernel::bindings::module>; |
| 208 | }} |
| 209 | |
| 210 | kernel::ThisModule::from_ptr(__this_module.get()) |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 211 | }}; |
| 212 | #[cfg(not(MODULE))] |
| 213 | static THIS_MODULE: kernel::ThisModule = unsafe {{ |
| 214 | kernel::ThisModule::from_ptr(core::ptr::null_mut()) |
| 215 | }}; |
| 216 | |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 217 | // Double nested modules, since then nobody can access the public items inside. |
| 218 | mod __module_init {{ |
| 219 | mod __module_init {{ |
| 220 | use super::super::{type_}; |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 221 | |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 222 | /// The \"Rust loadable module\" mark. |
| 223 | // |
| 224 | // This may be best done another way later on, e.g. as a new modinfo |
| 225 | // key or a new section. For the moment, keep it simple. |
| 226 | #[cfg(MODULE)] |
| 227 | #[doc(hidden)] |
| 228 | #[used] |
| 229 | static __IS_RUST_MODULE: () = (); |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 230 | |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 231 | static mut __MOD: Option<{type_}> = None; |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 232 | |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 233 | // Loadable modules need to export the `{{init,cleanup}}_module` identifiers. |
| 234 | /// # Safety |
| 235 | /// |
| 236 | /// This function must not be called after module initialization, because it may be |
| 237 | /// freed after that completes. |
| 238 | #[cfg(MODULE)] |
| 239 | #[doc(hidden)] |
| 240 | #[no_mangle] |
| 241 | #[link_section = \".init.text\"] |
| 242 | pub unsafe extern \"C\" fn init_module() -> core::ffi::c_int {{ |
| 243 | // SAFETY: This function is inaccessible to the outside due to the double |
| 244 | // module wrapping it. It is called exactly once by the C side via its |
| 245 | // unique name. |
| 246 | unsafe {{ __init() }} |
| 247 | }} |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 248 | |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 249 | #[cfg(MODULE)] |
| 250 | #[doc(hidden)] |
| 251 | #[no_mangle] |
| 252 | pub extern \"C\" fn cleanup_module() {{ |
| 253 | // SAFETY: |
| 254 | // - This function is inaccessible to the outside due to the double |
| 255 | // module wrapping it. It is called exactly once by the C side via its |
| 256 | // unique name, |
| 257 | // - furthermore it is only called after `init_module` has returned `0` |
| 258 | // (which delegates to `__init`). |
| 259 | unsafe {{ __exit() }} |
| 260 | }} |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 261 | |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 262 | // Built-in modules are initialized through an initcall pointer |
| 263 | // and the identifiers need to be unique. |
| 264 | #[cfg(not(MODULE))] |
| 265 | #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))] |
| 266 | #[doc(hidden)] |
| 267 | #[link_section = \"{initcall_section}\"] |
| 268 | #[used] |
| 269 | pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init; |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 270 | |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 271 | #[cfg(not(MODULE))] |
| 272 | #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)] |
| 273 | core::arch::global_asm!( |
| 274 | r#\".section \"{initcall_section}\", \"a\" |
| 275 | __{name}_initcall: |
| 276 | .long __{name}_init - . |
| 277 | .previous |
| 278 | \"# |
| 279 | ); |
| 280 | |
| 281 | #[cfg(not(MODULE))] |
| 282 | #[doc(hidden)] |
| 283 | #[no_mangle] |
| 284 | pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{ |
| 285 | // SAFETY: This function is inaccessible to the outside due to the double |
| 286 | // module wrapping it. It is called exactly once by the C side via its |
| 287 | // placement above in the initcall section. |
| 288 | unsafe {{ __init() }} |
| 289 | }} |
| 290 | |
| 291 | #[cfg(not(MODULE))] |
| 292 | #[doc(hidden)] |
| 293 | #[no_mangle] |
| 294 | pub extern \"C\" fn __{name}_exit() {{ |
| 295 | // SAFETY: |
| 296 | // - This function is inaccessible to the outside due to the double |
| 297 | // module wrapping it. It is called exactly once by the C side via its |
| 298 | // unique name, |
| 299 | // - furthermore it is only called after `__{name}_init` has returned `0` |
| 300 | // (which delegates to `__init`). |
| 301 | unsafe {{ __exit() }} |
| 302 | }} |
| 303 | |
| 304 | /// # Safety |
| 305 | /// |
| 306 | /// This function must only be called once. |
| 307 | unsafe fn __init() -> core::ffi::c_int {{ |
| 308 | match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{ |
| 309 | Ok(m) => {{ |
| 310 | // SAFETY: No data race, since `__MOD` can only be accessed by this |
| 311 | // module and there only `__init` and `__exit` access it. These |
| 312 | // functions are only called once and `__exit` cannot be called |
| 313 | // before or during `__init`. |
| 314 | unsafe {{ |
| 315 | __MOD = Some(m); |
| 316 | }} |
| 317 | return 0; |
| 318 | }} |
| 319 | Err(e) => {{ |
| 320 | return e.to_errno(); |
| 321 | }} |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 322 | }} |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 323 | }} |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 324 | |
| 325 | /// # Safety |
| 326 | /// |
| 327 | /// This function must |
| 328 | /// - only be called once, |
| 329 | /// - be called after `__init` has been called and returned `0`. |
| 330 | unsafe fn __exit() {{ |
| 331 | // SAFETY: No data race, since `__MOD` can only be accessed by this module |
| 332 | // and there only `__init` and `__exit` access it. These functions are only |
| 333 | // called once and `__init` was already called. |
| 334 | unsafe {{ |
| 335 | // Invokes `drop()` on `__MOD`, which should be used for cleanup. |
| 336 | __MOD = None; |
| 337 | }} |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 338 | }} |
Benno Lossin | a4dec33 | 2024-04-01 18:52:50 +0000 | [diff] [blame] | 339 | |
| 340 | {modinfo} |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 341 | }} |
| 342 | }} |
Miguel Ojeda | 1fbde52 | 2021-07-03 16:56:17 +0200 | [diff] [blame] | 343 | ", |
| 344 | type_ = info.type_, |
| 345 | name = info.name, |
| 346 | modinfo = modinfo.buffer, |
| 347 | initcall_section = ".initcall6.init" |
| 348 | ) |
| 349 | .parse() |
| 350 | .expect("Error parsing formatted string into token stream.") |
| 351 | } |