@@ -160,7 +160,7 @@ fn build_modinfo_string_param(module: &str, field: &str, param: &str, content: &
160
160
/// The `type` argument should be a type which implements the [`KernelModule`] trait.
161
161
/// Also accepts various forms of kernel metadata.
162
162
///
163
- /// Example:
163
+ /// ## Example
164
164
/// ```rust,no_run
165
165
/// use kernel::prelude::*;
166
166
///
@@ -170,17 +170,38 @@ fn build_modinfo_string_param(module: &str, field: &str, param: &str, content: &
170
170
/// author: b"Rust for Linux Contributors",
171
171
/// description: b"My very own kernel module!",
172
172
/// license: b"GPL v2",
173
- /// params: {},
173
+ /// params: {
174
+ /// my_i32: i32 {
175
+ /// default: 42,
176
+ /// permissions: 0o644,
177
+ /// description: b"Example of i32",
178
+ /// },
179
+ /// },
174
180
/// }
175
181
///
176
182
/// struct MyKernelModule;
177
183
///
178
184
/// impl KernelModule for MyKernelModule {
179
185
/// fn init() -> KernelResult<Self> {
186
+ /// println!("i32 param is: {}", my_i32.read());
180
187
/// Ok(MyKernelModule)
181
188
/// }
182
189
/// }
183
190
/// ```
191
+ ///
192
+ /// ## Suported Parameter Types
193
+ ///
194
+ /// - `bool` - Corresponds to C `bool` param type.
195
+ /// - `u8` - Corresponds to C `char` param type.
196
+ /// - `i16` - Corresponds to C `short` param type.
197
+ /// - `u16` - Corresponds to C `ushort` param type.
198
+ /// - `i32` - Corresponds to C `int` param type.
199
+ /// - `u32` - Corresponds to C `uint` param type.
200
+ /// - `u64` - Corresponds to C `ullong` param type.
201
+ /// - `invbool` - Corresponds to C `invbool` param type
202
+ /// Value is inverse of user input.
203
+ /// - `str` - Corresponds to C `charp` param type.
204
+ /// `read` returns a &[u8].
184
205
#[ proc_macro]
185
206
pub fn module ( ts : TokenStream ) -> TokenStream {
186
207
let mut it = ts. into_iter ( ) ;
@@ -215,10 +236,10 @@ pub fn module(ts: TokenStream) -> TokenStream {
215
236
assert_eq ! ( group. delimiter( ) , Delimiter :: Brace ) ;
216
237
217
238
let mut param_it = group. stream ( ) . into_iter ( ) ;
218
- let param_default = if param_type == "bool" {
219
- get_ident ( & mut param_it, "default" )
220
- } else {
221
- get_literal ( & mut param_it, "default" )
239
+ let param_default = match param_type. as_ref ( ) {
240
+ "bool" | "invbool" => get_ident ( & mut param_it, "default" ) ,
241
+ "str" => get_byte_string ( & mut param_it , "default" ) ,
242
+ _ => get_literal ( & mut param_it, "default" ) ,
222
243
} ;
223
244
let param_permissions = get_literal ( & mut param_it, "permissions" ) ;
224
245
let param_description = get_byte_string ( & mut param_it, "description" ) ;
@@ -228,7 +249,14 @@ pub fn module(ts: TokenStream) -> TokenStream {
228
249
// TODO: other kinds: arrays, unsafes, etc.
229
250
let param_kernel_type = match param_type. as_ref ( ) {
230
251
"bool" => "bool" ,
252
+ "u8" => "char" ,
253
+ "i16" => "short" ,
254
+ "u16" => "ushort" ,
231
255
"i32" => "int" ,
256
+ "u32" => "uint" ,
257
+ "u64" => "ullong" ,
258
+ "invbool" => "invbool" ,
259
+ "str" => "charp" ,
232
260
t => panic ! ( "Unrecognized type {}" , t) ,
233
261
} ;
234
262
@@ -244,18 +272,57 @@ pub fn module(ts: TokenStream) -> TokenStream {
244
272
& param_name,
245
273
& param_description,
246
274
) ) ;
275
+ let param_type_internal = match param_type. as_ref ( ) {
276
+ "str" => "*mut kernel::c_types::c_char" ,
277
+ "invbool" => "bool" ,
278
+ _ => & param_type,
279
+ } ;
280
+ let param_default = match param_type. as_ref ( ) {
281
+ "str" => format ! ( "b\" {}\0 \" as *const _ as *mut kernel::c_types::c_char" , param_default) ,
282
+ _ => param_default,
283
+ } ;
284
+ let read_func = match param_type. as_ref ( ) {
285
+ "str" => format ! (
286
+ "
287
+ fn read(&self) -> &[u8] {{
288
+ // SAFETY: The pointer is provided either in `param_default` when building the module,
289
+ // or by the kernel through `set_param_charp`. Both will be valid C strings.
290
+ unsafe {{
291
+ kernel::c_types::c_string_bytes(__{name}_{param_name}_value)
292
+ }}
293
+ }}
294
+ " ,
295
+ name = name,
296
+ param_name = param_name,
297
+ ) ,
298
+ _ => format ! (
299
+ "
300
+ fn read(&self) -> {param_type_internal} {{
301
+ unsafe {{ __{name}_{param_name}_value }}
302
+ }}
303
+ " ,
304
+ name = name,
305
+ param_name = param_name,
306
+ param_type_internal = param_type_internal,
307
+ ) ,
308
+ } ;
309
+ let kparam = format ! (
310
+ "
311
+ kernel::bindings::kernel_param__bindgen_ty_1 {{
312
+ arg: unsafe {{ &__{name}_{param_name}_value }} as *const _ as *mut kernel::c_types::c_void,
313
+ }},
314
+ " ,
315
+ name = name,
316
+ param_name = param_name,
317
+ ) ;
247
318
params_modinfo. push_str (
248
319
& format ! (
249
320
"
250
- static mut __{name}_{param_name}_value: {param_type } = {param_default};
321
+ static mut __{name}_{param_name}_value: {param_type_internal } = {param_default};
251
322
252
323
struct __{name}_{param_name};
253
324
254
- impl __{name}_{param_name} {{
255
- fn read(&self) -> {param_type} {{
256
- unsafe {{ __{name}_{param_name}_value }}
257
- }}
258
- }}
325
+ impl __{name}_{param_name} {{ {read_func} }}
259
326
260
327
const {param_name}: __{name}_{param_name} = __{name}_{param_name};
261
328
@@ -288,17 +355,17 @@ pub fn module(ts: TokenStream) -> TokenStream {
288
355
perm: {permissions},
289
356
level: -1,
290
357
flags: 0,
291
- __bindgen_anon_1: kernel::bindings::kernel_param__bindgen_ty_1 {{
292
- arg: unsafe {{ &__{name}_{param_name}_value }} as *const _ as *mut kernel::c_types::c_void,
293
- }},
358
+ __bindgen_anon_1: {kparam}
294
359
}});
295
360
" ,
296
361
name = name,
297
- param_type = param_type,
362
+ param_type_internal = param_type_internal,
363
+ read_func = read_func,
298
364
param_kernel_type = param_kernel_type,
299
365
param_default = param_default,
300
366
param_name = param_name,
301
367
permissions = param_permissions,
368
+ kparam = kparam,
302
369
)
303
370
) ;
304
371
}
0 commit comments