Skip to content

Commit 3adc0d5

Browse files
committed
Add charp and some primitive param types.
1 parent 745bd9d commit 3adc0d5

7 files changed

Lines changed: 166 additions & 30 deletions

File tree

.github/workflows/ci.yaml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,26 @@ jobs:
156156
# Run
157157
- run: ${{ env.BUILD_DIR }}usr/gen_init_cpio .github/workflows/qemu-initramfs.desc > qemu-initramfs.img
158158

159-
- run: qemu-system-${{ env.QEMU_ARCH }} -kernel ${{ env.BUILD_DIR }}${{ env.IMAGE_PATH }} -initrd qemu-initramfs.img -M ${{ env.QEMU_MACHINE }} -cpu ${{ env.QEMU_CPU }} -smp 2 -nographic -no-reboot -append '${{ env.QEMU_APPEND }} rust_example.my_i32=123321 rust_example_2.my_i32=234432' | tee qemu-stdout.log
159+
- run: qemu-system-${{ env.QEMU_ARCH }} -kernel ${{ env.BUILD_DIR }}${{ env.IMAGE_PATH }} -initrd qemu-initramfs.img -M ${{ env.QEMU_MACHINE }} -cpu ${{ env.QEMU_CPU }} -smp 2 -nographic -no-reboot -append '${{ env.QEMU_APPEND }} rust_example.my_i32=123321 rust_example.my_str=🦀mod rust_example.my_invbool=y rust_example_2.my_i32=234432' | tee qemu-stdout.log
160160

161161
# Check
162162
- run: grep -F '] Rust Example (init)' qemu-stdout.log
163163
- run: grep -F '] [2] Rust Example (init)' qemu-stdout.log
164164
- run: grep -F '] [3] Rust Example (init)' qemu-stdout.log
165165
- run: grep -F '] [4] Rust Example (init)' qemu-stdout.log
166166

167-
- run: "grep -F '] my_i32: 123321' qemu-stdout.log"
168-
- run: "grep -F '] [2] my_i32: 234432' qemu-stdout.log"
169-
- run: "grep -F '] [3] my_i32: 345543' qemu-stdout.log"
170-
- run: "grep -F '] [4] my_i32: 456654' qemu-stdout.log"
167+
- run: "grep -F '] my_i32: 123321' qemu-stdout.log"
168+
- run: "grep -F '] [2] my_i32: 234432' qemu-stdout.log"
169+
- run: "grep -F '] [3] my_i32: 345543' qemu-stdout.log"
170+
- run: "grep -F '] [4] my_i32: 456654' qemu-stdout.log"
171+
172+
- run: "grep -F '] my_invbool: false' qemu-stdout.log"
173+
- run: "grep -F '] [2] my_invbool: true' qemu-stdout.log"
174+
175+
- run: "grep '\\] my_str: 🦀mod\\s*$' qemu-stdout.log"
176+
- run: "grep '\\] \\[2\\] my_str: default str val\\s*$' qemu-stdout.log"
177+
- run: "grep '\\] \\[3\\] my_str: 🦀mod\\s*$' qemu-stdout.log"
178+
- run: "grep '\\] \\[4\\] my_str: default str val\\s*$' qemu-stdout.log"
171179

172180
- run: grep -F '] [3] Rust Example (exit)' qemu-stdout.log
173181
- run: grep -F '] [4] Rust Example (exit)' qemu-stdout.log

.github/workflows/qemu-init.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22

3-
busybox insmod rust_example_3.ko my_i32=345543
3+
busybox insmod rust_example_3.ko my_i32=345543 my_str=🦀mod
44
busybox insmod rust_example_4.ko my_i32=456654
55
busybox rmmod rust_example_3.ko
66
busybox rmmod rust_example_4.ko

drivers/char/rust_example.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ module! {
2525
permissions: 0o644,
2626
description: b"Example of i32",
2727
},
28+
my_str: str {
29+
default: b"default str val",
30+
permissions: 0o644,
31+
description: b"Example of a string param",
32+
},
33+
my_invbool: invbool {
34+
default: true,
35+
permissions: 0o644,
36+
description: b"Example of an inverted bool",
37+
},
2838
},
2939
}
3040

@@ -49,8 +59,13 @@ impl KernelModule for RustExample {
4959
println!("Rust Example (init)");
5060
println!("Am I built-in? {}", !cfg!(MODULE));
5161
println!("Parameters:");
52-
println!(" my_bool: {}", my_bool.read());
53-
println!(" my_i32: {}", my_i32.read());
62+
println!(" my_bool: {}", my_bool.read());
63+
println!(" my_i32: {}", my_i32.read());
64+
println!(
65+
" my_str: {}",
66+
my_str.read().expect("Expected valid UTF8 parameter")
67+
);
68+
println!(" my_invbool: {}", my_invbool.read());
5469

5570
Ok(RustExample {
5671
message: "on the heap!".to_owned(),

drivers/char/rust_example_2.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ module! {
2222
permissions: 0o644,
2323
description: b"Example of i32",
2424
},
25+
my_str: str {
26+
default: b"default str val",
27+
permissions: 0o644,
28+
description: b"Example of a string param",
29+
},
30+
my_invbool: invbool {
31+
default: true,
32+
permissions: 0o644,
33+
description: b"Example of an inverted bool",
34+
},
2535
},
2636
}
2737

@@ -34,8 +44,13 @@ impl KernelModule for RustExample2 {
3444
println!("[2] Rust Example (init)");
3545
println!("[2] Am I built-in? {}", !cfg!(MODULE));
3646
println!("[2] Parameters:");
37-
println!("[2] my_bool: {}", my_bool.read());
38-
println!("[2] my_i32: {}", my_i32.read());
47+
println!("[2] my_bool: {}", my_bool.read());
48+
println!("[2] my_i32: {}", my_i32.read());
49+
println!(
50+
"[2] my_str: {}",
51+
my_str.read().expect("Expected valid UTF8 parameter")
52+
);
53+
println!("[2] my_invbool: {}", my_invbool.read());
3954
Ok(RustExample2 {
4055
message: "on the heap!".to_owned(),
4156
})

drivers/char/rust_example_3.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ module! {
2222
permissions: 0o644,
2323
description: b"Example of i32",
2424
},
25+
my_str: str {
26+
default: b"default str val",
27+
permissions: 0o644,
28+
description: b"Example of a string param",
29+
},
30+
my_invbool: invbool {
31+
default: true,
32+
permissions: 0o644,
33+
description: b"Example of an inverted bool",
34+
},
2535
},
2636
}
2737

@@ -34,8 +44,14 @@ impl KernelModule for RustExample3 {
3444
println!("[3] Rust Example (init)");
3545
println!("[3] Am I built-in? {}", !cfg!(MODULE));
3646
println!("[3] Parameters:");
37-
println!("[3] my_bool: {}", my_bool.read());
38-
println!("[3] my_i32: {}", my_i32.read());
47+
println!("[3] my_bool: {}", my_bool.read());
48+
println!("[3] my_i32: {}", my_i32.read());
49+
println!(
50+
"[3] my_str: {}",
51+
my_str.read().expect("Expected valid UTF8 parameter")
52+
);
53+
println!("[3] my_invbool: {}", my_invbool.read());
54+
3955
Ok(RustExample3 {
4056
message: "on the heap!".to_owned(),
4157
})

drivers/char/rust_example_4.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,16 @@ module! {
2222
permissions: 0o644,
2323
description: b"Example of i32",
2424
},
25+
my_str: str {
26+
default: b"default str val",
27+
permissions: 0o644,
28+
description: b"Example of a string param",
29+
},
30+
my_invbool: invbool {
31+
default: true,
32+
permissions: 0o644,
33+
description: b"Example of an inverted bool",
34+
},
2535
},
2636
}
2737

@@ -34,8 +44,13 @@ impl KernelModule for RustExample4 {
3444
println!("[4] Rust Example (init)");
3545
println!("[4] Am I built-in? {}", !cfg!(MODULE));
3646
println!("[4] Parameters:");
37-
println!("[4] my_bool: {}", my_bool.read());
38-
println!("[4] my_i32: {}", my_i32.read());
47+
println!("[4] my_bool: {}", my_bool.read());
48+
println!("[4] my_i32: {}", my_i32.read());
49+
println!(
50+
"[4] my_str: {}",
51+
my_str.read().expect("Expected valid UTF8 parameter")
52+
);
53+
println!("[4] my_invbool: {}", my_invbool.read());
3954
Ok(RustExample4 {
4055
message: "on the heap!".to_owned(),
4156
})

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,36 @@ 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. Value is inverse of user input.
202+
/// - `str` - Corresponds to C `charp` param type. `read` signature is `read(&self) -> Result<&str, core::str::Utf8Error>`.
184203
#[proc_macro]
185204
pub fn module(ts: TokenStream) -> TokenStream {
186205
let mut it = ts.into_iter();
@@ -215,10 +234,10 @@ pub fn module(ts: TokenStream) -> TokenStream {
215234
assert_eq!(group.delimiter(), Delimiter::Brace);
216235

217236
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")
237+
let param_default = match param_type.as_ref() {
238+
"bool" | "invbool" => get_ident(&mut param_it, "default"),
239+
"str" => get_byte_string(&mut param_it, "default"),
240+
_ => get_literal(&mut param_it, "default"),
222241
};
223242
let param_permissions = get_literal(&mut param_it, "permissions");
224243
let param_description = get_byte_string(&mut param_it, "description");
@@ -228,7 +247,14 @@ pub fn module(ts: TokenStream) -> TokenStream {
228247
// TODO: other kinds: arrays, unsafes, etc.
229248
let param_kernel_type = match param_type.as_ref() {
230249
"bool" => "bool",
250+
"u8" => "char",
251+
"i16" => "short",
252+
"u16" => "ushort",
231253
"i32" => "int",
254+
"u32" => "uint",
255+
"u64" => "ullong",
256+
"invbool" => "invbool",
257+
"str" => "charp",
232258
t => panic!("Unrecognized type {}", t),
233259
};
234260

@@ -244,18 +270,59 @@ pub fn module(ts: TokenStream) -> TokenStream {
244270
&param_name,
245271
&param_description,
246272
));
273+
let param_type_internal = match param_type.as_ref() {
274+
"str" => "*mut u8",
275+
"invbool" => "bool",
276+
_ => &param_type,
277+
};
278+
let param_default = match param_type.as_ref() {
279+
"str" => format!("b\"{}\0\" as *const u8 as *mut u8", param_default),
280+
_ => param_default,
281+
};
282+
let read_func = match param_type.as_ref() {
283+
"str" => format!(
284+
"
285+
fn read(&self) -> Result<&str, core::str::Utf8Error> {{
286+
unsafe {{
287+
let mut count = 0;
288+
while *__{name}_{param_name}_value.add(count) != b'\0' {{
289+
count += 1;
290+
}}
291+
core::str::from_utf8(&core::slice::from_raw_parts(__{name}_{param_name}_value, count))
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)