@@ -15,6 +15,13 @@ use core::fmt::Write;
1515///
1616/// [`PAGE_SIZE`]: `crate::PAGE_SIZE`
1717pub trait ModuleParam : core:: fmt:: Display + core:: marker:: Sized {
18+ /// The `ModuleParam` will be used by the kernel module through this type.
19+ ///
20+ /// This may differ from `Self` if, for example, `Self` needs to track
21+ /// ownership without exposing it or allocate extra space for other possible
22+ /// parameter values. See [`StringParam`] or [`ArrayParam`] for examples.
23+ type Value : ?Sized ;
24+
1825 /// Whether the parameter is allowed to be set without an argument.
1926 ///
2027 /// Setting this to `true` allows the parameter to be passed without an
@@ -27,7 +34,13 @@ pub trait ModuleParam: core::fmt::Display + core::marker::Sized {
2734 /// `arg == None` indicates that the parameter was passed without an
2835 /// argument. If `NOARG_ALLOWED` is set to `false` then `arg` is guaranteed
2936 /// to always be `Some(_)`.
30- fn try_from_param_arg ( arg : Option < & [ u8 ] > ) -> Option < Self > ;
37+ fn try_from_param_arg ( arg : Option < & ' static [ u8 ] > ) -> Option < Self > ;
38+
39+ /// Get the current value of the parameter for use in the kernel module.
40+ ///
41+ /// This function should not be used directly. Instead use the wrapper
42+ /// `read` which will be generated by [`module::module`].
43+ fn value ( & self ) -> & Self :: Value ;
3144
3245 /// Set the module parameter from a string.
3346 ///
@@ -161,13 +174,18 @@ impl_parse_int!(usize);
161174macro_rules! impl_module_param {
162175 ( $ty: ident) => {
163176 impl ModuleParam for $ty {
177+ type Value = $ty;
164178 const NOARG_ALLOWED : bool = false ;
165179
166- fn try_from_param_arg( arg: Option <& [ u8 ] >) -> Option <Self > {
180+ fn try_from_param_arg( arg: Option <& ' static [ u8 ] >) -> Option <Self > {
167181 let bytes = arg?;
168182 let utf8 = core:: str :: from_utf8( bytes) . ok( ) ?;
169183 <$ty as crate :: module_param:: ParseInt >:: from_str( utf8)
170184 }
185+
186+ fn value( & self ) -> & Self :: Value {
187+ self
188+ }
171189 }
172190 } ;
173191}
@@ -184,27 +202,27 @@ macro_rules! impl_module_param {
184202/// );
185203/// ```
186204macro_rules! make_param_ops {
187- ( $ops: ident, $ty: ident ) => {
188- make_param_ops!(
205+ ( $ops: ident, $ty: ty ) => {
206+ $crate :: make_param_ops!(
189207 #[ doc="" ]
190208 $ops,
191209 $ty
192210 ) ;
193211 } ;
194- ( $( #[ $meta: meta] ) * $ops: ident, $ty: ident ) => {
212+ ( $( #[ $meta: meta] ) * $ops: ident, $ty: ty ) => {
195213 $( #[ $meta] ) *
196214 ///
197215 /// Static [`kernel_param_ops`](../../../include/linux/moduleparam.h)
198216 /// struct generated by [`make_param_ops`].
199- pub static $ops: crate :: bindings:: kernel_param_ops = crate :: bindings:: kernel_param_ops {
200- flags: if <$ty as crate :: module_param:: ModuleParam >:: NOARG_ALLOWED {
201- crate :: bindings:: KERNEL_PARAM_OPS_FL_NOARG
217+ pub static $ops: $ crate:: bindings:: kernel_param_ops = $ crate:: bindings:: kernel_param_ops {
218+ flags: if <$ty as $ crate:: module_param:: ModuleParam >:: NOARG_ALLOWED {
219+ $ crate:: bindings:: KERNEL_PARAM_OPS_FL_NOARG
202220 } else {
203221 0
204222 } ,
205- set: Some ( <$ty as crate :: module_param:: ModuleParam >:: set_param) ,
206- get: Some ( <$ty as crate :: module_param:: ModuleParam >:: get_param) ,
207- free: Some ( <$ty as crate :: module_param:: ModuleParam >:: free) ,
223+ set: Some ( <$ty as $ crate:: module_param:: ModuleParam >:: set_param) ,
224+ get: Some ( <$ty as $ crate:: module_param:: ModuleParam >:: get_param) ,
225+ free: Some ( <$ty as $ crate:: module_param:: ModuleParam >:: free) ,
208226 } ;
209227 } ;
210228}
@@ -282,16 +300,21 @@ make_param_ops!(
282300) ;
283301
284302impl ModuleParam for bool {
303+ type Value = bool ;
285304 const NOARG_ALLOWED : bool = true ;
286305
287- fn try_from_param_arg ( arg : Option < & [ u8 ] > ) -> Option < Self > {
306+ fn try_from_param_arg ( arg : Option < & ' static [ u8 ] > ) -> Option < Self > {
288307 match arg {
289308 None => Some ( true ) ,
290309 Some ( b"y" ) | Some ( b"Y" ) | Some ( b"1" ) | Some ( b"true" ) => Some ( true ) ,
291310 Some ( b"n" ) | Some ( b"N" ) | Some ( b"0" ) | Some ( b"false" ) => Some ( false ) ,
292311 _ => None ,
293312 }
294313 }
314+
315+ fn value ( & self ) -> & Self :: Value {
316+ self
317+ }
295318}
296319
297320make_param_ops ! (
@@ -300,3 +323,157 @@ make_param_ops!(
300323 PARAM_OPS_BOOL ,
301324 bool
302325) ;
326+
327+ /// An array of at __most__ `N` values.
328+ ///
329+ /// # Invariant
330+ ///
331+ /// The first `self.used` elements of `self.values` are initialized.
332+ pub struct ArrayParam < T , const N : usize > {
333+ values : [ core:: mem:: MaybeUninit < T > ; N ] ,
334+ used : usize ,
335+ }
336+
337+ impl < T , const N : usize > ArrayParam < T , { N } > {
338+ fn values ( & self ) -> & [ T ] {
339+ // SAFETY: The invariant maintained by `ArrayParam` allows us to cast
340+ // the first `self.used` elements to `T`.
341+ unsafe {
342+ & * ( & self . values [ 0 ..self . used ] as * const [ core:: mem:: MaybeUninit < T > ] as * const [ T ] )
343+ }
344+ }
345+ }
346+
347+ impl < T : Copy , const N : usize > ArrayParam < T , { N } > {
348+ const fn new ( ) -> Self {
349+ // INVARIANT: The first `self.used` elements of `self.values` are
350+ // initialized.
351+ ArrayParam {
352+ values : [ core:: mem:: MaybeUninit :: uninit ( ) ; N ] ,
353+ used : 0 ,
354+ }
355+ }
356+
357+ const fn push ( & mut self , val : T ) {
358+ if self . used < N {
359+ // INVARIANT: The first `self.used` elements of `self.values` are
360+ // initialized.
361+ self . values [ self . used ] = core:: mem:: MaybeUninit :: new ( val) ;
362+ self . used += 1 ;
363+ }
364+ }
365+
366+ /// Create an instance of `ArrayParam` initialized with `vals`.
367+ ///
368+ /// This function is only meant to be used in the [`module::module`] macro.
369+ #[ doc( hidden) ]
370+ pub const fn create ( vals : & [ T ] ) -> Self {
371+ let mut result = ArrayParam :: new ( ) ;
372+ let mut i = 0 ;
373+ while i < vals. len ( ) {
374+ result. push ( vals[ i] ) ;
375+ i += 1 ;
376+ }
377+ result
378+ }
379+ }
380+
381+ impl < T : core:: fmt:: Display , const N : usize > core:: fmt:: Display for ArrayParam < T , { N } > {
382+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
383+ for val in self . values ( ) {
384+ write ! ( f, "{}," , val) ?;
385+ }
386+ Ok ( ( ) )
387+ }
388+ }
389+
390+ impl < T : Copy + core:: fmt:: Display + ModuleParam , const N : usize > ModuleParam
391+ for ArrayParam < T , { N } >
392+ {
393+ type Value = [ T ] ;
394+ const NOARG_ALLOWED : bool = false ;
395+
396+ fn try_from_param_arg ( arg : Option < & ' static [ u8 ] > ) -> Option < Self > {
397+ arg. and_then ( |args| {
398+ let mut result = Self :: new ( ) ;
399+ for arg in args. split ( |b| * b == b',' ) {
400+ result. push ( T :: try_from_param_arg ( Some ( arg) ) ?) ;
401+ }
402+ Some ( result)
403+ } )
404+ }
405+
406+ fn value ( & self ) -> & Self :: Value {
407+ self . values ( )
408+ }
409+ }
410+
411+ /// A C-style string parameter.
412+ ///
413+ /// The Rust version of the [`charp`] parameter. This type is meant to be
414+ /// used by the [`module::module`] macro, not handled directly. Instead use the
415+ /// `read` method generated by that macro.
416+ ///
417+ /// [`charp`]: ../../../include/linux/moduleparam.h
418+ pub enum StringParam {
419+ /// A borrowed parameter value.
420+ ///
421+ /// Either the default value (which is static in the module) or borrowed
422+ /// from the original argument buffer used to set the value.
423+ Ref ( & ' static [ u8 ] ) ,
424+
425+ /// A value that was allocated when the parameter was set.
426+ ///
427+ /// The value needs to be freed when the parameter is reset or the module is
428+ /// unloaded.
429+ Owned ( alloc:: vec:: Vec < u8 > ) ,
430+ }
431+
432+ impl StringParam {
433+ fn bytes ( & self ) -> & [ u8 ] {
434+ match self {
435+ StringParam :: Ref ( bytes) => * bytes,
436+ StringParam :: Owned ( vec) => & vec[ ..] ,
437+ }
438+ }
439+ }
440+
441+ impl core:: fmt:: Display for StringParam {
442+ fn fmt ( & self , f : & mut core:: fmt:: Formatter < ' _ > ) -> core:: fmt:: Result {
443+ let bytes = self . bytes ( ) ;
444+ match core:: str:: from_utf8 ( bytes) {
445+ Ok ( utf8) => write ! ( f, "{}" , utf8) ,
446+ Err ( _) => write ! ( f, "{:?}" , bytes) ,
447+ }
448+ }
449+ }
450+
451+ impl ModuleParam for StringParam {
452+ type Value = [ u8 ] ;
453+ const NOARG_ALLOWED : bool = false ;
454+
455+ fn try_from_param_arg ( arg : Option < & ' static [ u8 ] > ) -> Option < Self > {
456+ // SAFETY: It is always safe to call [`slab_is_available`](../../../include/linux/slab.h).
457+ let slab_available = unsafe { crate :: bindings:: slab_is_available ( ) } ;
458+ arg. map ( |arg| {
459+ if slab_available {
460+ let mut vec = alloc:: vec:: Vec :: new ( ) ;
461+ vec. extend_from_slice ( arg) ;
462+ StringParam :: Owned ( vec)
463+ } else {
464+ StringParam :: Ref ( arg)
465+ }
466+ } )
467+ }
468+
469+ fn value ( & self ) -> & Self :: Value {
470+ self . bytes ( )
471+ }
472+ }
473+
474+ make_param_ops ! (
475+ /// Rust implementation of [`kernel_param_ops`](../../../include/linux/moduleparam.h)
476+ /// for [`StringParam`].
477+ PARAM_OPS_STR ,
478+ StringParam
479+ ) ;
0 commit comments