Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/kernel/firmware.rs
49180 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
//! Firmware abstraction
4
//!
5
//! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.h)
6
7
use crate::{
8
bindings,
9
device::Device,
10
error::Error,
11
error::Result,
12
ffi,
13
str::{CStr, CStrExt as _},
14
};
15
use core::ptr::NonNull;
16
17
/// # Invariants
18
///
19
/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`,
20
/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`.
21
struct FwFunc(
22
unsafe extern "C" fn(
23
*mut *const bindings::firmware,
24
*const ffi::c_char,
25
*mut bindings::device,
26
) -> i32,
27
);
28
29
impl FwFunc {
30
fn request() -> Self {
31
Self(bindings::request_firmware)
32
}
33
34
fn request_nowarn() -> Self {
35
Self(bindings::firmware_request_nowarn)
36
}
37
}
38
39
/// Abstraction around a C `struct firmware`.
40
///
41
/// This is a simple abstraction around the C firmware API. Just like with the C API, firmware can
42
/// be requested. Once requested the abstraction provides direct access to the firmware buffer as
43
/// `&[u8]`. The firmware is released once [`Firmware`] is dropped.
44
///
45
/// # Invariants
46
///
47
/// The pointer is valid, and has ownership over the instance of `struct firmware`.
48
///
49
/// The `Firmware`'s backing buffer is not modified.
50
///
51
/// # Examples
52
///
53
/// ```no_run
54
/// # use kernel::{device::Device, firmware::Firmware};
55
///
56
/// # fn no_run() -> Result<(), Error> {
57
/// # // SAFETY: *NOT* safe, just for the example to get an `ARef<Device>` instance
58
/// # let dev = unsafe { Device::get_device(core::ptr::null_mut()) };
59
///
60
/// let fw = Firmware::request(c"path/to/firmware.bin", &dev)?;
61
/// let blob = fw.data();
62
///
63
/// # Ok(())
64
/// # }
65
/// ```
66
pub struct Firmware(NonNull<bindings::firmware>);
67
68
impl Firmware {
69
fn request_internal(name: &CStr, dev: &Device, func: FwFunc) -> Result<Self> {
70
let mut fw: *mut bindings::firmware = core::ptr::null_mut();
71
let pfw: *mut *mut bindings::firmware = &mut fw;
72
let pfw: *mut *const bindings::firmware = pfw.cast();
73
74
// SAFETY: `pfw` is a valid pointer to a NULL initialized `bindings::firmware` pointer.
75
// `name` and `dev` are valid as by their type invariants.
76
let ret = unsafe { func.0(pfw, name.as_char_ptr(), dev.as_raw()) };
77
if ret != 0 {
78
return Err(Error::from_errno(ret));
79
}
80
81
// SAFETY: `func` not bailing out with a non-zero error code, guarantees that `fw` is a
82
// valid pointer to `bindings::firmware`.
83
Ok(Firmware(unsafe { NonNull::new_unchecked(fw) }))
84
}
85
86
/// Send a firmware request and wait for it. See also `bindings::request_firmware`.
87
pub fn request(name: &CStr, dev: &Device) -> Result<Self> {
88
Self::request_internal(name, dev, FwFunc::request())
89
}
90
91
/// Send a request for an optional firmware module. See also
92
/// `bindings::firmware_request_nowarn`.
93
pub fn request_nowarn(name: &CStr, dev: &Device) -> Result<Self> {
94
Self::request_internal(name, dev, FwFunc::request_nowarn())
95
}
96
97
fn as_raw(&self) -> *mut bindings::firmware {
98
self.0.as_ptr()
99
}
100
101
/// Returns the size of the requested firmware in bytes.
102
pub fn size(&self) -> usize {
103
// SAFETY: `self.as_raw()` is valid by the type invariant.
104
unsafe { (*self.as_raw()).size }
105
}
106
107
/// Returns the requested firmware as `&[u8]`.
108
pub fn data(&self) -> &[u8] {
109
// SAFETY: `self.as_raw()` is valid by the type invariant. Additionally,
110
// `bindings::firmware` guarantees, if successfully requested, that
111
// `bindings::firmware::data` has a size of `bindings::firmware::size` bytes.
112
unsafe { core::slice::from_raw_parts((*self.as_raw()).data, self.size()) }
113
}
114
}
115
116
impl Drop for Firmware {
117
fn drop(&mut self) {
118
// SAFETY: `self.as_raw()` is valid by the type invariant.
119
unsafe { bindings::release_firmware(self.as_raw()) };
120
}
121
}
122
123
// SAFETY: `Firmware` only holds a pointer to a C `struct firmware`, which is safe to be used from
124
// any thread.
125
unsafe impl Send for Firmware {}
126
127
// SAFETY: `Firmware` only holds a pointer to a C `struct firmware`, references to which are safe to
128
// be used from any thread.
129
unsafe impl Sync for Firmware {}
130
131
/// Create firmware .modinfo entries.
132
///
133
/// This macro is the counterpart of the C macro `MODULE_FIRMWARE()`, but instead of taking a
134
/// simple string literals, which is already covered by the `firmware` field of
135
/// [`crate::prelude::module!`], it allows the caller to pass a builder type, based on the
136
/// [`ModInfoBuilder`], which can create the firmware modinfo strings in a more flexible way.
137
///
138
/// Drivers should extend the [`ModInfoBuilder`] with their own driver specific builder type.
139
///
140
/// The `builder` argument must be a type which implements the following function.
141
///
142
/// `const fn create(module_name: &'static CStr) -> ModInfoBuilder`
143
///
144
/// `create` should pass the `module_name` to the [`ModInfoBuilder`] and, with the help of
145
/// it construct the corresponding firmware modinfo.
146
///
147
/// Typically, such contracts would be enforced by a trait, however traits do not (yet) support
148
/// const functions.
149
///
150
/// # Examples
151
///
152
/// ```
153
/// # mod module_firmware_test {
154
/// # use kernel::firmware;
155
/// # use kernel::prelude::*;
156
/// #
157
/// # struct MyModule;
158
/// #
159
/// # impl kernel::Module for MyModule {
160
/// # fn init(_module: &'static ThisModule) -> Result<Self> {
161
/// # Ok(Self)
162
/// # }
163
/// # }
164
/// #
165
/// #
166
/// struct Builder<const N: usize>;
167
///
168
/// impl<const N: usize> Builder<N> {
169
/// const DIR: &'static str = "vendor/chip/";
170
/// const FILES: [&'static str; 3] = [ "foo", "bar", "baz" ];
171
///
172
/// const fn create(module_name: &'static kernel::str::CStr) -> firmware::ModInfoBuilder<N> {
173
/// let mut builder = firmware::ModInfoBuilder::new(module_name);
174
///
175
/// let mut i = 0;
176
/// while i < Self::FILES.len() {
177
/// builder = builder.new_entry()
178
/// .push(Self::DIR)
179
/// .push(Self::FILES[i])
180
/// .push(".bin");
181
///
182
/// i += 1;
183
/// }
184
///
185
/// builder
186
/// }
187
/// }
188
///
189
/// module! {
190
/// type: MyModule,
191
/// name: "module_firmware_test",
192
/// authors: ["Rust for Linux"],
193
/// description: "module_firmware! test module",
194
/// license: "GPL",
195
/// }
196
///
197
/// kernel::module_firmware!(Builder);
198
/// # }
199
/// ```
200
#[macro_export]
201
macro_rules! module_firmware {
202
// The argument is the builder type without the const generic, since it's deferred from within
203
// this macro. Hence, we can neither use `expr` nor `ty`.
204
($($builder:tt)*) => {
205
const _: () = {
206
const __MODULE_FIRMWARE_PREFIX: &'static $crate::str::CStr = if cfg!(MODULE) {
207
c""
208
} else {
209
<LocalModule as $crate::ModuleMetadata>::NAME
210
};
211
212
#[link_section = ".modinfo"]
213
#[used(compiler)]
214
static __MODULE_FIRMWARE: [u8; $($builder)*::create(__MODULE_FIRMWARE_PREFIX)
215
.build_length()] = $($builder)*::create(__MODULE_FIRMWARE_PREFIX).build();
216
};
217
};
218
}
219
220
/// Builder for firmware module info.
221
///
222
/// [`ModInfoBuilder`] is a helper component to flexibly compose firmware paths strings for the
223
/// .modinfo section in const context.
224
///
225
/// Therefore the [`ModInfoBuilder`] provides the methods [`ModInfoBuilder::new_entry`] and
226
/// [`ModInfoBuilder::push`], where the latter is used to push path components and the former to
227
/// mark the beginning of a new path string.
228
///
229
/// [`ModInfoBuilder`] is meant to be used in combination with [`kernel::module_firmware!`].
230
///
231
/// The const generic `N` as well as the `module_name` parameter of [`ModInfoBuilder::new`] is an
232
/// internal implementation detail and supplied through the above macro.
233
pub struct ModInfoBuilder<const N: usize> {
234
buf: [u8; N],
235
n: usize,
236
module_name: &'static CStr,
237
}
238
239
impl<const N: usize> ModInfoBuilder<N> {
240
/// Create an empty builder instance.
241
pub const fn new(module_name: &'static CStr) -> Self {
242
Self {
243
buf: [0; N],
244
n: 0,
245
module_name,
246
}
247
}
248
249
const fn push_internal(mut self, bytes: &[u8]) -> Self {
250
let mut j = 0;
251
252
if N == 0 {
253
self.n += bytes.len();
254
return self;
255
}
256
257
while j < bytes.len() {
258
if self.n < N {
259
self.buf[self.n] = bytes[j];
260
}
261
self.n += 1;
262
j += 1;
263
}
264
self
265
}
266
267
/// Push an additional path component.
268
///
269
/// Append path components to the [`ModInfoBuilder`] instance. Paths need to be separated
270
/// with [`ModInfoBuilder::new_entry`].
271
///
272
/// # Examples
273
///
274
/// ```
275
/// use kernel::firmware::ModInfoBuilder;
276
///
277
/// # const DIR: &str = "vendor/chip/";
278
/// # const fn no_run<const N: usize>(builder: ModInfoBuilder<N>) {
279
/// let builder = builder.new_entry()
280
/// .push(DIR)
281
/// .push("foo.bin")
282
/// .new_entry()
283
/// .push(DIR)
284
/// .push("bar.bin");
285
/// # }
286
/// ```
287
pub const fn push(self, s: &str) -> Self {
288
// Check whether there has been an initial call to `next_entry()`.
289
if N != 0 && self.n == 0 {
290
crate::build_error!("Must call next_entry() before push().");
291
}
292
293
self.push_internal(s.as_bytes())
294
}
295
296
const fn push_module_name(self) -> Self {
297
let mut this = self;
298
let module_name = this.module_name;
299
300
if !this.module_name.is_empty() {
301
this = this.push_internal(module_name.to_bytes_with_nul());
302
303
if N != 0 {
304
// Re-use the space taken by the NULL terminator and swap it with the '.' separator.
305
this.buf[this.n - 1] = b'.';
306
}
307
}
308
309
this
310
}
311
312
/// Prepare the [`ModInfoBuilder`] for the next entry.
313
///
314
/// This method acts as a separator between module firmware path entries.
315
///
316
/// Must be called before constructing a new entry with subsequent calls to
317
/// [`ModInfoBuilder::push`].
318
///
319
/// See [`ModInfoBuilder::push`] for an example.
320
pub const fn new_entry(self) -> Self {
321
self.push_internal(b"\0")
322
.push_module_name()
323
.push_internal(b"firmware=")
324
}
325
326
/// Build the byte array.
327
pub const fn build(self) -> [u8; N] {
328
// Add the final NULL terminator.
329
let this = self.push_internal(b"\0");
330
331
if this.n == N {
332
this.buf
333
} else {
334
crate::build_error!("Length mismatch.");
335
}
336
}
337
}
338
339
impl ModInfoBuilder<0> {
340
/// Return the length of the byte array to build.
341
pub const fn build_length(self) -> usize {
342
// Compensate for the NULL terminator added by `build`.
343
self.n + 1
344
}
345
}
346
347