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