1*1fbde52bSMiguel Ojeda // SPDX-License-Identifier: GPL-2.0 2*1fbde52bSMiguel Ojeda 3*1fbde52bSMiguel Ojeda use crate::helpers::*; 4*1fbde52bSMiguel Ojeda use proc_macro::{token_stream, Literal, TokenStream, TokenTree}; 5*1fbde52bSMiguel Ojeda use std::fmt::Write; 6*1fbde52bSMiguel Ojeda 7*1fbde52bSMiguel Ojeda struct ModInfoBuilder<'a> { 8*1fbde52bSMiguel Ojeda module: &'a str, 9*1fbde52bSMiguel Ojeda counter: usize, 10*1fbde52bSMiguel Ojeda buffer: String, 11*1fbde52bSMiguel Ojeda } 12*1fbde52bSMiguel Ojeda 13*1fbde52bSMiguel Ojeda impl<'a> ModInfoBuilder<'a> { 14*1fbde52bSMiguel Ojeda fn new(module: &'a str) -> Self { 15*1fbde52bSMiguel Ojeda ModInfoBuilder { 16*1fbde52bSMiguel Ojeda module, 17*1fbde52bSMiguel Ojeda counter: 0, 18*1fbde52bSMiguel Ojeda buffer: String::new(), 19*1fbde52bSMiguel Ojeda } 20*1fbde52bSMiguel Ojeda } 21*1fbde52bSMiguel Ojeda 22*1fbde52bSMiguel Ojeda fn emit_base(&mut self, field: &str, content: &str, builtin: bool) { 23*1fbde52bSMiguel Ojeda let string = if builtin { 24*1fbde52bSMiguel Ojeda // Built-in modules prefix their modinfo strings by `module.`. 25*1fbde52bSMiguel Ojeda format!( 26*1fbde52bSMiguel Ojeda "{module}.{field}={content}\0", 27*1fbde52bSMiguel Ojeda module = self.module, 28*1fbde52bSMiguel Ojeda field = field, 29*1fbde52bSMiguel Ojeda content = content 30*1fbde52bSMiguel Ojeda ) 31*1fbde52bSMiguel Ojeda } else { 32*1fbde52bSMiguel Ojeda // Loadable modules' modinfo strings go as-is. 33*1fbde52bSMiguel Ojeda format!("{field}={content}\0", field = field, content = content) 34*1fbde52bSMiguel Ojeda }; 35*1fbde52bSMiguel Ojeda 36*1fbde52bSMiguel Ojeda write!( 37*1fbde52bSMiguel Ojeda &mut self.buffer, 38*1fbde52bSMiguel Ojeda " 39*1fbde52bSMiguel Ojeda {cfg} 40*1fbde52bSMiguel Ojeda #[doc(hidden)] 41*1fbde52bSMiguel Ojeda #[link_section = \".modinfo\"] 42*1fbde52bSMiguel Ojeda #[used] 43*1fbde52bSMiguel Ojeda pub static __{module}_{counter}: [u8; {length}] = *{string}; 44*1fbde52bSMiguel Ojeda ", 45*1fbde52bSMiguel Ojeda cfg = if builtin { 46*1fbde52bSMiguel Ojeda "#[cfg(not(MODULE))]" 47*1fbde52bSMiguel Ojeda } else { 48*1fbde52bSMiguel Ojeda "#[cfg(MODULE)]" 49*1fbde52bSMiguel Ojeda }, 50*1fbde52bSMiguel Ojeda module = self.module.to_uppercase(), 51*1fbde52bSMiguel Ojeda counter = self.counter, 52*1fbde52bSMiguel Ojeda length = string.len(), 53*1fbde52bSMiguel Ojeda string = Literal::byte_string(string.as_bytes()), 54*1fbde52bSMiguel Ojeda ) 55*1fbde52bSMiguel Ojeda .unwrap(); 56*1fbde52bSMiguel Ojeda 57*1fbde52bSMiguel Ojeda self.counter += 1; 58*1fbde52bSMiguel Ojeda } 59*1fbde52bSMiguel Ojeda 60*1fbde52bSMiguel Ojeda fn emit_only_builtin(&mut self, field: &str, content: &str) { 61*1fbde52bSMiguel Ojeda self.emit_base(field, content, true) 62*1fbde52bSMiguel Ojeda } 63*1fbde52bSMiguel Ojeda 64*1fbde52bSMiguel Ojeda fn emit_only_loadable(&mut self, field: &str, content: &str) { 65*1fbde52bSMiguel Ojeda self.emit_base(field, content, false) 66*1fbde52bSMiguel Ojeda } 67*1fbde52bSMiguel Ojeda 68*1fbde52bSMiguel Ojeda fn emit(&mut self, field: &str, content: &str) { 69*1fbde52bSMiguel Ojeda self.emit_only_builtin(field, content); 70*1fbde52bSMiguel Ojeda self.emit_only_loadable(field, content); 71*1fbde52bSMiguel Ojeda } 72*1fbde52bSMiguel Ojeda } 73*1fbde52bSMiguel Ojeda 74*1fbde52bSMiguel Ojeda #[derive(Debug, Default)] 75*1fbde52bSMiguel Ojeda struct ModuleInfo { 76*1fbde52bSMiguel Ojeda type_: String, 77*1fbde52bSMiguel Ojeda license: String, 78*1fbde52bSMiguel Ojeda name: String, 79*1fbde52bSMiguel Ojeda author: Option<String>, 80*1fbde52bSMiguel Ojeda description: Option<String>, 81*1fbde52bSMiguel Ojeda alias: Option<String>, 82*1fbde52bSMiguel Ojeda } 83*1fbde52bSMiguel Ojeda 84*1fbde52bSMiguel Ojeda impl ModuleInfo { 85*1fbde52bSMiguel Ojeda fn parse(it: &mut token_stream::IntoIter) -> Self { 86*1fbde52bSMiguel Ojeda let mut info = ModuleInfo::default(); 87*1fbde52bSMiguel Ojeda 88*1fbde52bSMiguel Ojeda const EXPECTED_KEYS: &[&str] = 89*1fbde52bSMiguel Ojeda &["type", "name", "author", "description", "license", "alias"]; 90*1fbde52bSMiguel Ojeda const REQUIRED_KEYS: &[&str] = &["type", "name", "license"]; 91*1fbde52bSMiguel Ojeda let mut seen_keys = Vec::new(); 92*1fbde52bSMiguel Ojeda 93*1fbde52bSMiguel Ojeda loop { 94*1fbde52bSMiguel Ojeda let key = match it.next() { 95*1fbde52bSMiguel Ojeda Some(TokenTree::Ident(ident)) => ident.to_string(), 96*1fbde52bSMiguel Ojeda Some(_) => panic!("Expected Ident or end"), 97*1fbde52bSMiguel Ojeda None => break, 98*1fbde52bSMiguel Ojeda }; 99*1fbde52bSMiguel Ojeda 100*1fbde52bSMiguel Ojeda if seen_keys.contains(&key) { 101*1fbde52bSMiguel Ojeda panic!( 102*1fbde52bSMiguel Ojeda "Duplicated key \"{}\". Keys can only be specified once.", 103*1fbde52bSMiguel Ojeda key 104*1fbde52bSMiguel Ojeda ); 105*1fbde52bSMiguel Ojeda } 106*1fbde52bSMiguel Ojeda 107*1fbde52bSMiguel Ojeda assert_eq!(expect_punct(it), ':'); 108*1fbde52bSMiguel Ojeda 109*1fbde52bSMiguel Ojeda match key.as_str() { 110*1fbde52bSMiguel Ojeda "type" => info.type_ = expect_ident(it), 111*1fbde52bSMiguel Ojeda "name" => info.name = expect_byte_string(it), 112*1fbde52bSMiguel Ojeda "author" => info.author = Some(expect_byte_string(it)), 113*1fbde52bSMiguel Ojeda "description" => info.description = Some(expect_byte_string(it)), 114*1fbde52bSMiguel Ojeda "license" => info.license = expect_byte_string(it), 115*1fbde52bSMiguel Ojeda "alias" => info.alias = Some(expect_byte_string(it)), 116*1fbde52bSMiguel Ojeda _ => panic!( 117*1fbde52bSMiguel Ojeda "Unknown key \"{}\". Valid keys are: {:?}.", 118*1fbde52bSMiguel Ojeda key, EXPECTED_KEYS 119*1fbde52bSMiguel Ojeda ), 120*1fbde52bSMiguel Ojeda } 121*1fbde52bSMiguel Ojeda 122*1fbde52bSMiguel Ojeda assert_eq!(expect_punct(it), ','); 123*1fbde52bSMiguel Ojeda 124*1fbde52bSMiguel Ojeda seen_keys.push(key); 125*1fbde52bSMiguel Ojeda } 126*1fbde52bSMiguel Ojeda 127*1fbde52bSMiguel Ojeda expect_end(it); 128*1fbde52bSMiguel Ojeda 129*1fbde52bSMiguel Ojeda for key in REQUIRED_KEYS { 130*1fbde52bSMiguel Ojeda if !seen_keys.iter().any(|e| e == key) { 131*1fbde52bSMiguel Ojeda panic!("Missing required key \"{}\".", key); 132*1fbde52bSMiguel Ojeda } 133*1fbde52bSMiguel Ojeda } 134*1fbde52bSMiguel Ojeda 135*1fbde52bSMiguel Ojeda let mut ordered_keys: Vec<&str> = Vec::new(); 136*1fbde52bSMiguel Ojeda for key in EXPECTED_KEYS { 137*1fbde52bSMiguel Ojeda if seen_keys.iter().any(|e| e == key) { 138*1fbde52bSMiguel Ojeda ordered_keys.push(key); 139*1fbde52bSMiguel Ojeda } 140*1fbde52bSMiguel Ojeda } 141*1fbde52bSMiguel Ojeda 142*1fbde52bSMiguel Ojeda if seen_keys != ordered_keys { 143*1fbde52bSMiguel Ojeda panic!( 144*1fbde52bSMiguel Ojeda "Keys are not ordered as expected. Order them like: {:?}.", 145*1fbde52bSMiguel Ojeda ordered_keys 146*1fbde52bSMiguel Ojeda ); 147*1fbde52bSMiguel Ojeda } 148*1fbde52bSMiguel Ojeda 149*1fbde52bSMiguel Ojeda info 150*1fbde52bSMiguel Ojeda } 151*1fbde52bSMiguel Ojeda } 152*1fbde52bSMiguel Ojeda 153*1fbde52bSMiguel Ojeda pub(crate) fn module(ts: TokenStream) -> TokenStream { 154*1fbde52bSMiguel Ojeda let mut it = ts.into_iter(); 155*1fbde52bSMiguel Ojeda 156*1fbde52bSMiguel Ojeda let info = ModuleInfo::parse(&mut it); 157*1fbde52bSMiguel Ojeda 158*1fbde52bSMiguel Ojeda let mut modinfo = ModInfoBuilder::new(info.name.as_ref()); 159*1fbde52bSMiguel Ojeda if let Some(author) = info.author { 160*1fbde52bSMiguel Ojeda modinfo.emit("author", &author); 161*1fbde52bSMiguel Ojeda } 162*1fbde52bSMiguel Ojeda if let Some(description) = info.description { 163*1fbde52bSMiguel Ojeda modinfo.emit("description", &description); 164*1fbde52bSMiguel Ojeda } 165*1fbde52bSMiguel Ojeda modinfo.emit("license", &info.license); 166*1fbde52bSMiguel Ojeda if let Some(alias) = info.alias { 167*1fbde52bSMiguel Ojeda modinfo.emit("alias", &alias); 168*1fbde52bSMiguel Ojeda } 169*1fbde52bSMiguel Ojeda 170*1fbde52bSMiguel Ojeda // Built-in modules also export the `file` modinfo string. 171*1fbde52bSMiguel Ojeda let file = 172*1fbde52bSMiguel Ojeda std::env::var("RUST_MODFILE").expect("Unable to fetch RUST_MODFILE environmental variable"); 173*1fbde52bSMiguel Ojeda modinfo.emit_only_builtin("file", &file); 174*1fbde52bSMiguel Ojeda 175*1fbde52bSMiguel Ojeda format!( 176*1fbde52bSMiguel Ojeda " 177*1fbde52bSMiguel Ojeda /// The module name. 178*1fbde52bSMiguel Ojeda /// 179*1fbde52bSMiguel Ojeda /// Used by the printing macros, e.g. [`info!`]. 180*1fbde52bSMiguel Ojeda const __LOG_PREFIX: &[u8] = b\"{name}\\0\"; 181*1fbde52bSMiguel Ojeda 182*1fbde52bSMiguel Ojeda /// The \"Rust loadable module\" mark, for `scripts/is_rust_module.sh`. 183*1fbde52bSMiguel Ojeda // 184*1fbde52bSMiguel Ojeda // This may be best done another way later on, e.g. as a new modinfo 185*1fbde52bSMiguel Ojeda // key or a new section. For the moment, keep it simple. 186*1fbde52bSMiguel Ojeda #[cfg(MODULE)] 187*1fbde52bSMiguel Ojeda #[doc(hidden)] 188*1fbde52bSMiguel Ojeda #[used] 189*1fbde52bSMiguel Ojeda static __IS_RUST_MODULE: () = (); 190*1fbde52bSMiguel Ojeda 191*1fbde52bSMiguel Ojeda static mut __MOD: Option<{type_}> = None; 192*1fbde52bSMiguel Ojeda 193*1fbde52bSMiguel Ojeda // SAFETY: `__this_module` is constructed by the kernel at load time and will not be 194*1fbde52bSMiguel Ojeda // freed until the module is unloaded. 195*1fbde52bSMiguel Ojeda #[cfg(MODULE)] 196*1fbde52bSMiguel Ojeda static THIS_MODULE: kernel::ThisModule = unsafe {{ 197*1fbde52bSMiguel Ojeda kernel::ThisModule::from_ptr(&kernel::bindings::__this_module as *const _ as *mut _) 198*1fbde52bSMiguel Ojeda }}; 199*1fbde52bSMiguel Ojeda #[cfg(not(MODULE))] 200*1fbde52bSMiguel Ojeda static THIS_MODULE: kernel::ThisModule = unsafe {{ 201*1fbde52bSMiguel Ojeda kernel::ThisModule::from_ptr(core::ptr::null_mut()) 202*1fbde52bSMiguel Ojeda }}; 203*1fbde52bSMiguel Ojeda 204*1fbde52bSMiguel Ojeda // Loadable modules need to export the `{{init,cleanup}}_module` identifiers. 205*1fbde52bSMiguel Ojeda #[cfg(MODULE)] 206*1fbde52bSMiguel Ojeda #[doc(hidden)] 207*1fbde52bSMiguel Ojeda #[no_mangle] 208*1fbde52bSMiguel Ojeda pub extern \"C\" fn init_module() -> core::ffi::c_int {{ 209*1fbde52bSMiguel Ojeda __init() 210*1fbde52bSMiguel Ojeda }} 211*1fbde52bSMiguel Ojeda 212*1fbde52bSMiguel Ojeda #[cfg(MODULE)] 213*1fbde52bSMiguel Ojeda #[doc(hidden)] 214*1fbde52bSMiguel Ojeda #[no_mangle] 215*1fbde52bSMiguel Ojeda pub extern \"C\" fn cleanup_module() {{ 216*1fbde52bSMiguel Ojeda __exit() 217*1fbde52bSMiguel Ojeda }} 218*1fbde52bSMiguel Ojeda 219*1fbde52bSMiguel Ojeda // Built-in modules are initialized through an initcall pointer 220*1fbde52bSMiguel Ojeda // and the identifiers need to be unique. 221*1fbde52bSMiguel Ojeda #[cfg(not(MODULE))] 222*1fbde52bSMiguel Ojeda #[cfg(not(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS))] 223*1fbde52bSMiguel Ojeda #[doc(hidden)] 224*1fbde52bSMiguel Ojeda #[link_section = \"{initcall_section}\"] 225*1fbde52bSMiguel Ojeda #[used] 226*1fbde52bSMiguel Ojeda pub static __{name}_initcall: extern \"C\" fn() -> core::ffi::c_int = __{name}_init; 227*1fbde52bSMiguel Ojeda 228*1fbde52bSMiguel Ojeda #[cfg(not(MODULE))] 229*1fbde52bSMiguel Ojeda #[cfg(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS)] 230*1fbde52bSMiguel Ojeda core::arch::global_asm!( 231*1fbde52bSMiguel Ojeda r#\".section \"{initcall_section}\", \"a\" 232*1fbde52bSMiguel Ojeda __{name}_initcall: 233*1fbde52bSMiguel Ojeda .long __{name}_init - . 234*1fbde52bSMiguel Ojeda .previous 235*1fbde52bSMiguel Ojeda \"# 236*1fbde52bSMiguel Ojeda ); 237*1fbde52bSMiguel Ojeda 238*1fbde52bSMiguel Ojeda #[cfg(not(MODULE))] 239*1fbde52bSMiguel Ojeda #[doc(hidden)] 240*1fbde52bSMiguel Ojeda #[no_mangle] 241*1fbde52bSMiguel Ojeda pub extern \"C\" fn __{name}_init() -> core::ffi::c_int {{ 242*1fbde52bSMiguel Ojeda __init() 243*1fbde52bSMiguel Ojeda }} 244*1fbde52bSMiguel Ojeda 245*1fbde52bSMiguel Ojeda #[cfg(not(MODULE))] 246*1fbde52bSMiguel Ojeda #[doc(hidden)] 247*1fbde52bSMiguel Ojeda #[no_mangle] 248*1fbde52bSMiguel Ojeda pub extern \"C\" fn __{name}_exit() {{ 249*1fbde52bSMiguel Ojeda __exit() 250*1fbde52bSMiguel Ojeda }} 251*1fbde52bSMiguel Ojeda 252*1fbde52bSMiguel Ojeda fn __init() -> core::ffi::c_int {{ 253*1fbde52bSMiguel Ojeda match <{type_} as kernel::Module>::init(&THIS_MODULE) {{ 254*1fbde52bSMiguel Ojeda Ok(m) => {{ 255*1fbde52bSMiguel Ojeda unsafe {{ 256*1fbde52bSMiguel Ojeda __MOD = Some(m); 257*1fbde52bSMiguel Ojeda }} 258*1fbde52bSMiguel Ojeda return 0; 259*1fbde52bSMiguel Ojeda }} 260*1fbde52bSMiguel Ojeda Err(e) => {{ 261*1fbde52bSMiguel Ojeda return e.to_kernel_errno(); 262*1fbde52bSMiguel Ojeda }} 263*1fbde52bSMiguel Ojeda }} 264*1fbde52bSMiguel Ojeda }} 265*1fbde52bSMiguel Ojeda 266*1fbde52bSMiguel Ojeda fn __exit() {{ 267*1fbde52bSMiguel Ojeda unsafe {{ 268*1fbde52bSMiguel Ojeda // Invokes `drop()` on `__MOD`, which should be used for cleanup. 269*1fbde52bSMiguel Ojeda __MOD = None; 270*1fbde52bSMiguel Ojeda }} 271*1fbde52bSMiguel Ojeda }} 272*1fbde52bSMiguel Ojeda 273*1fbde52bSMiguel Ojeda {modinfo} 274*1fbde52bSMiguel Ojeda ", 275*1fbde52bSMiguel Ojeda type_ = info.type_, 276*1fbde52bSMiguel Ojeda name = info.name, 277*1fbde52bSMiguel Ojeda modinfo = modinfo.buffer, 278*1fbde52bSMiguel Ojeda initcall_section = ".initcall6.init" 279*1fbde52bSMiguel Ojeda ) 280*1fbde52bSMiguel Ojeda .parse() 281*1fbde52bSMiguel Ojeda .expect("Error parsing formatted string into token stream.") 282*1fbde52bSMiguel Ojeda } 283