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