@@ -116,6 +116,95 @@ unsafe impl Send for Firmware {}
116
116
// be used from any thread.
117
117
unsafe impl Sync for Firmware { }
118
118
119
+ /// Create firmware .modinfo entries.
120
+ ///
121
+ /// This macro is the counterpart of the C macro `MODULE_FIRMWARE()`, but instead of taking a
122
+ /// simple string literals, which is already covered by the `firmware` field of
123
+ /// [`crate::prelude::module!`], it allows the caller to pass a builder type, based on the
124
+ /// [`ModInfoBuilder`], which can create the firmware modinfo strings in a more flexible way.
125
+ ///
126
+ /// Drivers should extend the [`ModInfoBuilder`] with their own driver specific builder type.
127
+ ///
128
+ /// The `builder` argument must be a type which implements the following function.
129
+ ///
130
+ /// `const fn create(module_name: &'static CStr) -> ModInfoBuilder`
131
+ ///
132
+ /// `create` should pass the `module_name` to the [`ModInfoBuilder`] and, with the help of
133
+ /// it construct the corresponding firmware modinfo.
134
+ ///
135
+ /// Typically, such contracts would be enforced by a trait, however traits do not (yet) support
136
+ /// const functions.
137
+ ///
138
+ /// # Example
139
+ ///
140
+ /// ```
141
+ /// # mod module_firmware_test {
142
+ /// # use kernel::firmware;
143
+ /// # use kernel::prelude::*;
144
+ /// #
145
+ /// # struct MyModule;
146
+ /// #
147
+ /// # impl kernel::Module for MyModule {
148
+ /// # fn init(_module: &'static ThisModule) -> Result<Self> {
149
+ /// # Ok(Self)
150
+ /// # }
151
+ /// # }
152
+ /// #
153
+ /// #
154
+ /// struct Builder<const N: usize>;
155
+ ///
156
+ /// impl<const N: usize> Builder<N> {
157
+ /// const DIR: &'static str = "vendor/chip/";
158
+ /// const FILES: [&'static str; 3] = [ "foo", "bar", "baz" ];
159
+ ///
160
+ /// const fn create(module_name: &'static kernel::str::CStr) -> firmware::ModInfoBuilder<N> {
161
+ /// let mut builder = firmware::ModInfoBuilder::new(module_name);
162
+ ///
163
+ /// let mut i = 0;
164
+ /// while i < Self::FILES.len() {
165
+ /// builder = builder.new_entry()
166
+ /// .push(Self::DIR)
167
+ /// .push(Self::FILES[i])
168
+ /// .push(".bin");
169
+ ///
170
+ /// i += 1;
171
+ /// }
172
+ ///
173
+ /// builder
174
+ /// }
175
+ /// }
176
+ ///
177
+ /// module! {
178
+ /// type: MyModule,
179
+ /// name: "module_firmware_test",
180
+ /// author: "Rust for Linux",
181
+ /// description: "module_firmware! test module",
182
+ /// license: "GPL",
183
+ /// }
184
+ ///
185
+ /// kernel::module_firmware!(Builder);
186
+ /// # }
187
+ /// ```
188
+ #[ macro_export]
189
+ macro_rules! module_firmware {
190
+ // The argument is the builder type without the const generic, since it's deferred from within
191
+ // this macro. Hence, we can neither use `expr` nor `ty`.
192
+ ( $( $builder: tt) * ) => {
193
+ const _: ( ) = {
194
+ const __MODULE_FIRMWARE_PREFIX: & ' static $crate:: str :: CStr = if cfg!( MODULE ) {
195
+ $crate:: c_str!( "" )
196
+ } else {
197
+ <LocalModule as $crate:: ModuleMetadata >:: NAME
198
+ } ;
199
+
200
+ #[ link_section = ".modinfo" ]
201
+ #[ used]
202
+ static __MODULE_FIRMWARE: [ u8 ; $( $builder) * :: create( __MODULE_FIRMWARE_PREFIX)
203
+ . build_length( ) ] = $( $builder) * :: create( __MODULE_FIRMWARE_PREFIX) . build( ) ;
204
+ } ;
205
+ } ;
206
+ }
207
+
119
208
/// Builder for firmware module info.
120
209
///
121
210
/// [`ModInfoBuilder`] is a helper component to flexibly compose firmware paths strings for the
@@ -125,7 +214,7 @@ unsafe impl Sync for Firmware {}
125
214
/// [`ModInfoBuilder::push`], where the latter is used to push path components and the former to
126
215
/// mark the beginning of a new path string.
127
216
///
128
- /// [`ModInfoBuilder`] is meant to be used in combination with `kernel::module_firmware!`.
217
+ /// [`ModInfoBuilder`] is meant to be used in combination with [ `kernel::module_firmware!`] .
129
218
///
130
219
/// The const generic `N` as well as the `module_name` parameter of [`ModInfoBuilder::new`] is an
131
220
/// internal implementation detail and supplied through the above macro.
0 commit comments