Skip to content

Commit a1ccae8

Browse files
committed
Add support for charp and some primitive parameter types
1 parent 745bd9d commit a1ccae8

File tree

2 files changed

+89
-16
lines changed

2 files changed

+89
-16
lines changed

rust/kernel/c_types.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,9 @@ mod c {
5151
}
5252

5353
pub use c::*;
54+
55+
/// Reads string until null byte is reached and returns slice excluding the terminating null.
56+
pub unsafe fn c_string_bytes(ptr: *const crate::c_types::c_char) -> &'static [u8] {
57+
let length = crate::bindings::strlen(ptr) as usize;
58+
&core::slice::from_raw_parts(ptr as *const u8, length)
59+
}

rust/module.rs

Lines changed: 83 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ fn build_modinfo_string_param(module: &str, field: &str, param: &str, content: &
160160
/// The `type` argument should be a type which implements the [`KernelModule`] trait.
161161
/// Also accepts various forms of kernel metadata.
162162
///
163-
/// Example:
163+
/// ## Example
164164
/// ```rust,no_run
165165
/// use kernel::prelude::*;
166166
///
@@ -170,17 +170,38 @@ fn build_modinfo_string_param(module: &str, field: &str, param: &str, content: &
170170
/// author: b"Rust for Linux Contributors",
171171
/// description: b"My very own kernel module!",
172172
/// 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+
/// },
174180
/// }
175181
///
176182
/// struct MyKernelModule;
177183
///
178184
/// impl KernelModule for MyKernelModule {
179185
/// fn init() -> KernelResult<Self> {
186+
/// println!("i32 param is: {}", my_i32.read());
180187
/// Ok(MyKernelModule)
181188
/// }
182189
/// }
183190
/// ```
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].
184205
#[proc_macro]
185206
pub fn module(ts: TokenStream) -> TokenStream {
186207
let mut it = ts.into_iter();
@@ -215,10 +236,10 @@ pub fn module(ts: TokenStream) -> TokenStream {
215236
assert_eq!(group.delimiter(), Delimiter::Brace);
216237

217238
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"),
222243
};
223244
let param_permissions = get_literal(&mut param_it, "permissions");
224245
let param_description = get_byte_string(&mut param_it, "description");
@@ -228,7 +249,14 @@ pub fn module(ts: TokenStream) -> TokenStream {
228249
// TODO: other kinds: arrays, unsafes, etc.
229250
let param_kernel_type = match param_type.as_ref() {
230251
"bool" => "bool",
252+
"u8" => "char",
253+
"i16" => "short",
254+
"u16" => "ushort",
231255
"i32" => "int",
256+
"u32" => "uint",
257+
"u64" => "ullong",
258+
"invbool" => "invbool",
259+
"str" => "charp",
232260
t => panic!("Unrecognized type {}", t),
233261
};
234262

@@ -244,18 +272,57 @@ pub fn module(ts: TokenStream) -> TokenStream {
244272
&param_name,
245273
&param_description,
246274
));
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+
);
247318
params_modinfo.push_str(
248319
&format!(
249320
"
250-
static mut __{name}_{param_name}_value: {param_type} = {param_default};
321+
static mut __{name}_{param_name}_value: {param_type_internal} = {param_default};
251322
252323
struct __{name}_{param_name};
253324
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} }}
259326
260327
const {param_name}: __{name}_{param_name} = __{name}_{param_name};
261328
@@ -288,17 +355,17 @@ pub fn module(ts: TokenStream) -> TokenStream {
288355
perm: {permissions},
289356
level: -1,
290357
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}
294359
}});
295360
",
296361
name = name,
297-
param_type = param_type,
362+
param_type_internal = param_type_internal,
363+
read_func = read_func,
298364
param_kernel_type = param_kernel_type,
299365
param_default = param_default,
300366
param_name = param_name,
301367
permissions = param_permissions,
368+
kparam = kparam,
302369
)
303370
);
304371
}

0 commit comments

Comments
 (0)