1de658283SDanilo Krummrich // SPDX-License-Identifier: GPL-2.0 2de658283SDanilo Krummrich 3de658283SDanilo Krummrich //! Firmware abstraction 4de658283SDanilo Krummrich //! 5cd04d509SAndrew Ballance //! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.h) 6de658283SDanilo Krummrich 7*53bd9780SChristian Schrefl use crate::{bindings, device::Device, error::Error, error::Result, ffi, str::CStr}; 8de658283SDanilo Krummrich use core::ptr::NonNull; 9de658283SDanilo Krummrich 10a23b018cSDanilo Krummrich /// # Invariants 11a23b018cSDanilo Krummrich /// 12a23b018cSDanilo Krummrich /// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`, 13a23b018cSDanilo Krummrich /// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`. 14a23b018cSDanilo Krummrich struct FwFunc( 15*53bd9780SChristian Schrefl unsafe extern "C" fn( 16*53bd9780SChristian Schrefl *mut *const bindings::firmware, 17*53bd9780SChristian Schrefl *const ffi::c_char, 18*53bd9780SChristian Schrefl *mut bindings::device, 19*53bd9780SChristian Schrefl ) -> i32, 20a23b018cSDanilo Krummrich ); 21a23b018cSDanilo Krummrich 22a23b018cSDanilo Krummrich impl FwFunc { request() -> Self23a23b018cSDanilo Krummrich fn request() -> Self { 24a23b018cSDanilo Krummrich Self(bindings::request_firmware) 25a23b018cSDanilo Krummrich } 26a23b018cSDanilo Krummrich request_nowarn() -> Self27a23b018cSDanilo Krummrich fn request_nowarn() -> Self { 28a23b018cSDanilo Krummrich Self(bindings::firmware_request_nowarn) 29a23b018cSDanilo Krummrich } 30a23b018cSDanilo Krummrich } 31de658283SDanilo Krummrich 32de658283SDanilo Krummrich /// Abstraction around a C `struct firmware`. 33de658283SDanilo Krummrich /// 34de658283SDanilo Krummrich /// This is a simple abstraction around the C firmware API. Just like with the C API, firmware can 35de658283SDanilo Krummrich /// be requested. Once requested the abstraction provides direct access to the firmware buffer as 36de658283SDanilo Krummrich /// `&[u8]`. The firmware is released once [`Firmware`] is dropped. 37de658283SDanilo Krummrich /// 38de658283SDanilo Krummrich /// # Invariants 39de658283SDanilo Krummrich /// 40de658283SDanilo Krummrich /// The pointer is valid, and has ownership over the instance of `struct firmware`. 41de658283SDanilo Krummrich /// 42bbe98f4fSDanilo Krummrich /// The `Firmware`'s backing buffer is not modified. 43de658283SDanilo Krummrich /// 44de658283SDanilo Krummrich /// # Examples 45de658283SDanilo Krummrich /// 462c61b8c5SDanilo Krummrich /// ```no_run 47de658283SDanilo Krummrich /// # use kernel::{c_str, device::Device, firmware::Firmware}; 48de658283SDanilo Krummrich /// 492c61b8c5SDanilo Krummrich /// # fn no_run() -> Result<(), Error> { 50de658283SDanilo Krummrich /// # // SAFETY: *NOT* safe, just for the example to get an `ARef<Device>` instance 51cc4332afSGuilherme Giacomo Simoes /// # let dev = unsafe { Device::get_device(core::ptr::null_mut()) }; 52de658283SDanilo Krummrich /// 532c61b8c5SDanilo Krummrich /// let fw = Firmware::request(c_str!("path/to/firmware.bin"), &dev)?; 54de658283SDanilo Krummrich /// let blob = fw.data(); 552c61b8c5SDanilo Krummrich /// 562c61b8c5SDanilo Krummrich /// # Ok(()) 572c61b8c5SDanilo Krummrich /// # } 58de658283SDanilo Krummrich /// ``` 59de658283SDanilo Krummrich pub struct Firmware(NonNull<bindings::firmware>); 60de658283SDanilo Krummrich 61de658283SDanilo Krummrich impl Firmware { request_internal(name: &CStr, dev: &Device, func: FwFunc) -> Result<Self>62de658283SDanilo Krummrich fn request_internal(name: &CStr, dev: &Device, func: FwFunc) -> Result<Self> { 63de658283SDanilo Krummrich let mut fw: *mut bindings::firmware = core::ptr::null_mut(); 64de658283SDanilo Krummrich let pfw: *mut *mut bindings::firmware = &mut fw; 65de658283SDanilo Krummrich 66de658283SDanilo Krummrich // SAFETY: `pfw` is a valid pointer to a NULL initialized `bindings::firmware` pointer. 67de658283SDanilo Krummrich // `name` and `dev` are valid as by their type invariants. 68a23b018cSDanilo Krummrich let ret = unsafe { func.0(pfw as _, name.as_char_ptr(), dev.as_raw()) }; 69de658283SDanilo Krummrich if ret != 0 { 70de658283SDanilo Krummrich return Err(Error::from_errno(ret)); 71de658283SDanilo Krummrich } 72de658283SDanilo Krummrich 73de658283SDanilo Krummrich // SAFETY: `func` not bailing out with a non-zero error code, guarantees that `fw` is a 74de658283SDanilo Krummrich // valid pointer to `bindings::firmware`. 75de658283SDanilo Krummrich Ok(Firmware(unsafe { NonNull::new_unchecked(fw) })) 76de658283SDanilo Krummrich } 77de658283SDanilo Krummrich 78de658283SDanilo Krummrich /// Send a firmware request and wait for it. See also `bindings::request_firmware`. request(name: &CStr, dev: &Device) -> Result<Self>79de658283SDanilo Krummrich pub fn request(name: &CStr, dev: &Device) -> Result<Self> { 80a23b018cSDanilo Krummrich Self::request_internal(name, dev, FwFunc::request()) 81de658283SDanilo Krummrich } 82de658283SDanilo Krummrich 83de658283SDanilo Krummrich /// Send a request for an optional firmware module. See also 84de658283SDanilo Krummrich /// `bindings::firmware_request_nowarn`. request_nowarn(name: &CStr, dev: &Device) -> Result<Self>85de658283SDanilo Krummrich pub fn request_nowarn(name: &CStr, dev: &Device) -> Result<Self> { 86a23b018cSDanilo Krummrich Self::request_internal(name, dev, FwFunc::request_nowarn()) 87de658283SDanilo Krummrich } 88de658283SDanilo Krummrich as_raw(&self) -> *mut bindings::firmware89de658283SDanilo Krummrich fn as_raw(&self) -> *mut bindings::firmware { 90de658283SDanilo Krummrich self.0.as_ptr() 91de658283SDanilo Krummrich } 92de658283SDanilo Krummrich 93de658283SDanilo Krummrich /// Returns the size of the requested firmware in bytes. size(&self) -> usize94de658283SDanilo Krummrich pub fn size(&self) -> usize { 95bbe98f4fSDanilo Krummrich // SAFETY: `self.as_raw()` is valid by the type invariant. 96de658283SDanilo Krummrich unsafe { (*self.as_raw()).size } 97de658283SDanilo Krummrich } 98de658283SDanilo Krummrich 99de658283SDanilo Krummrich /// Returns the requested firmware as `&[u8]`. data(&self) -> &[u8]100de658283SDanilo Krummrich pub fn data(&self) -> &[u8] { 101bbe98f4fSDanilo Krummrich // SAFETY: `self.as_raw()` is valid by the type invariant. Additionally, 102bbe98f4fSDanilo Krummrich // `bindings::firmware` guarantees, if successfully requested, that 103bbe98f4fSDanilo Krummrich // `bindings::firmware::data` has a size of `bindings::firmware::size` bytes. 104de658283SDanilo Krummrich unsafe { core::slice::from_raw_parts((*self.as_raw()).data, self.size()) } 105de658283SDanilo Krummrich } 106de658283SDanilo Krummrich } 107de658283SDanilo Krummrich 108de658283SDanilo Krummrich impl Drop for Firmware { drop(&mut self)109de658283SDanilo Krummrich fn drop(&mut self) { 110bbe98f4fSDanilo Krummrich // SAFETY: `self.as_raw()` is valid by the type invariant. 111de658283SDanilo Krummrich unsafe { bindings::release_firmware(self.as_raw()) }; 112de658283SDanilo Krummrich } 113de658283SDanilo Krummrich } 114de658283SDanilo Krummrich 115de658283SDanilo Krummrich // SAFETY: `Firmware` only holds a pointer to a C `struct firmware`, which is safe to be used from 116de658283SDanilo Krummrich // any thread. 117de658283SDanilo Krummrich unsafe impl Send for Firmware {} 118de658283SDanilo Krummrich 119de658283SDanilo Krummrich // SAFETY: `Firmware` only holds a pointer to a C `struct firmware`, references to which are safe to 120de658283SDanilo Krummrich // be used from any thread. 121de658283SDanilo Krummrich unsafe impl Sync for Firmware {} 122ef476b0dSDanilo Krummrich 1231d121a33SDanilo Krummrich /// Create firmware .modinfo entries. 1241d121a33SDanilo Krummrich /// 1251d121a33SDanilo Krummrich /// This macro is the counterpart of the C macro `MODULE_FIRMWARE()`, but instead of taking a 1261d121a33SDanilo Krummrich /// simple string literals, which is already covered by the `firmware` field of 1271d121a33SDanilo Krummrich /// [`crate::prelude::module!`], it allows the caller to pass a builder type, based on the 1281d121a33SDanilo Krummrich /// [`ModInfoBuilder`], which can create the firmware modinfo strings in a more flexible way. 1291d121a33SDanilo Krummrich /// 1301d121a33SDanilo Krummrich /// Drivers should extend the [`ModInfoBuilder`] with their own driver specific builder type. 1311d121a33SDanilo Krummrich /// 1321d121a33SDanilo Krummrich /// The `builder` argument must be a type which implements the following function. 1331d121a33SDanilo Krummrich /// 1341d121a33SDanilo Krummrich /// `const fn create(module_name: &'static CStr) -> ModInfoBuilder` 1351d121a33SDanilo Krummrich /// 1361d121a33SDanilo Krummrich /// `create` should pass the `module_name` to the [`ModInfoBuilder`] and, with the help of 1371d121a33SDanilo Krummrich /// it construct the corresponding firmware modinfo. 1381d121a33SDanilo Krummrich /// 1391d121a33SDanilo Krummrich /// Typically, such contracts would be enforced by a trait, however traits do not (yet) support 1401d121a33SDanilo Krummrich /// const functions. 1411d121a33SDanilo Krummrich /// 1421d121a33SDanilo Krummrich /// # Example 1431d121a33SDanilo Krummrich /// 1441d121a33SDanilo Krummrich /// ``` 1451d121a33SDanilo Krummrich /// # mod module_firmware_test { 1461d121a33SDanilo Krummrich /// # use kernel::firmware; 1471d121a33SDanilo Krummrich /// # use kernel::prelude::*; 1481d121a33SDanilo Krummrich /// # 1491d121a33SDanilo Krummrich /// # struct MyModule; 1501d121a33SDanilo Krummrich /// # 1511d121a33SDanilo Krummrich /// # impl kernel::Module for MyModule { 1521d121a33SDanilo Krummrich /// # fn init(_module: &'static ThisModule) -> Result<Self> { 1531d121a33SDanilo Krummrich /// # Ok(Self) 1541d121a33SDanilo Krummrich /// # } 1551d121a33SDanilo Krummrich /// # } 1561d121a33SDanilo Krummrich /// # 1571d121a33SDanilo Krummrich /// # 1581d121a33SDanilo Krummrich /// struct Builder<const N: usize>; 1591d121a33SDanilo Krummrich /// 1601d121a33SDanilo Krummrich /// impl<const N: usize> Builder<N> { 1611d121a33SDanilo Krummrich /// const DIR: &'static str = "vendor/chip/"; 1621d121a33SDanilo Krummrich /// const FILES: [&'static str; 3] = [ "foo", "bar", "baz" ]; 1631d121a33SDanilo Krummrich /// 1641d121a33SDanilo Krummrich /// const fn create(module_name: &'static kernel::str::CStr) -> firmware::ModInfoBuilder<N> { 1651d121a33SDanilo Krummrich /// let mut builder = firmware::ModInfoBuilder::new(module_name); 1661d121a33SDanilo Krummrich /// 1671d121a33SDanilo Krummrich /// let mut i = 0; 1681d121a33SDanilo Krummrich /// while i < Self::FILES.len() { 1691d121a33SDanilo Krummrich /// builder = builder.new_entry() 1701d121a33SDanilo Krummrich /// .push(Self::DIR) 1711d121a33SDanilo Krummrich /// .push(Self::FILES[i]) 1721d121a33SDanilo Krummrich /// .push(".bin"); 1731d121a33SDanilo Krummrich /// 1741d121a33SDanilo Krummrich /// i += 1; 1751d121a33SDanilo Krummrich /// } 1761d121a33SDanilo Krummrich /// 1771d121a33SDanilo Krummrich /// builder 1781d121a33SDanilo Krummrich /// } 1791d121a33SDanilo Krummrich /// } 1801d121a33SDanilo Krummrich /// 1811d121a33SDanilo Krummrich /// module! { 1821d121a33SDanilo Krummrich /// type: MyModule, 1831d121a33SDanilo Krummrich /// name: "module_firmware_test", 1841d121a33SDanilo Krummrich /// author: "Rust for Linux", 1851d121a33SDanilo Krummrich /// description: "module_firmware! test module", 1861d121a33SDanilo Krummrich /// license: "GPL", 1871d121a33SDanilo Krummrich /// } 1881d121a33SDanilo Krummrich /// 1891d121a33SDanilo Krummrich /// kernel::module_firmware!(Builder); 1901d121a33SDanilo Krummrich /// # } 1911d121a33SDanilo Krummrich /// ``` 1921d121a33SDanilo Krummrich #[macro_export] 1931d121a33SDanilo Krummrich macro_rules! module_firmware { 1941d121a33SDanilo Krummrich // The argument is the builder type without the const generic, since it's deferred from within 1951d121a33SDanilo Krummrich // this macro. Hence, we can neither use `expr` nor `ty`. 1961d121a33SDanilo Krummrich ($($builder:tt)*) => { 1971d121a33SDanilo Krummrich const _: () = { 1981d121a33SDanilo Krummrich const __MODULE_FIRMWARE_PREFIX: &'static $crate::str::CStr = if cfg!(MODULE) { 1991d121a33SDanilo Krummrich $crate::c_str!("") 2001d121a33SDanilo Krummrich } else { 2011d121a33SDanilo Krummrich <LocalModule as $crate::ModuleMetadata>::NAME 2021d121a33SDanilo Krummrich }; 2031d121a33SDanilo Krummrich 2041d121a33SDanilo Krummrich #[link_section = ".modinfo"] 2051d121a33SDanilo Krummrich #[used] 2061d121a33SDanilo Krummrich static __MODULE_FIRMWARE: [u8; $($builder)*::create(__MODULE_FIRMWARE_PREFIX) 2071d121a33SDanilo Krummrich .build_length()] = $($builder)*::create(__MODULE_FIRMWARE_PREFIX).build(); 2081d121a33SDanilo Krummrich }; 2091d121a33SDanilo Krummrich }; 2101d121a33SDanilo Krummrich } 2111d121a33SDanilo Krummrich 212ef476b0dSDanilo Krummrich /// Builder for firmware module info. 213ef476b0dSDanilo Krummrich /// 214ef476b0dSDanilo Krummrich /// [`ModInfoBuilder`] is a helper component to flexibly compose firmware paths strings for the 215ef476b0dSDanilo Krummrich /// .modinfo section in const context. 216ef476b0dSDanilo Krummrich /// 217ef476b0dSDanilo Krummrich /// Therefore the [`ModInfoBuilder`] provides the methods [`ModInfoBuilder::new_entry`] and 218ef476b0dSDanilo Krummrich /// [`ModInfoBuilder::push`], where the latter is used to push path components and the former to 219ef476b0dSDanilo Krummrich /// mark the beginning of a new path string. 220ef476b0dSDanilo Krummrich /// 2211d121a33SDanilo Krummrich /// [`ModInfoBuilder`] is meant to be used in combination with [`kernel::module_firmware!`]. 222ef476b0dSDanilo Krummrich /// 223ef476b0dSDanilo Krummrich /// The const generic `N` as well as the `module_name` parameter of [`ModInfoBuilder::new`] is an 224ef476b0dSDanilo Krummrich /// internal implementation detail and supplied through the above macro. 225ef476b0dSDanilo Krummrich pub struct ModInfoBuilder<const N: usize> { 226ef476b0dSDanilo Krummrich buf: [u8; N], 227ef476b0dSDanilo Krummrich n: usize, 228ef476b0dSDanilo Krummrich module_name: &'static CStr, 229ef476b0dSDanilo Krummrich } 230ef476b0dSDanilo Krummrich 231ef476b0dSDanilo Krummrich impl<const N: usize> ModInfoBuilder<N> { 232ef476b0dSDanilo Krummrich /// Create an empty builder instance. new(module_name: &'static CStr) -> Self233ef476b0dSDanilo Krummrich pub const fn new(module_name: &'static CStr) -> Self { 234ef476b0dSDanilo Krummrich Self { 235ef476b0dSDanilo Krummrich buf: [0; N], 236ef476b0dSDanilo Krummrich n: 0, 237ef476b0dSDanilo Krummrich module_name, 238ef476b0dSDanilo Krummrich } 239ef476b0dSDanilo Krummrich } 240ef476b0dSDanilo Krummrich push_internal(mut self, bytes: &[u8]) -> Self241ef476b0dSDanilo Krummrich const fn push_internal(mut self, bytes: &[u8]) -> Self { 242ef476b0dSDanilo Krummrich let mut j = 0; 243ef476b0dSDanilo Krummrich 244ef476b0dSDanilo Krummrich if N == 0 { 245ef476b0dSDanilo Krummrich self.n += bytes.len(); 246ef476b0dSDanilo Krummrich return self; 247ef476b0dSDanilo Krummrich } 248ef476b0dSDanilo Krummrich 249ef476b0dSDanilo Krummrich while j < bytes.len() { 250ef476b0dSDanilo Krummrich if self.n < N { 251ef476b0dSDanilo Krummrich self.buf[self.n] = bytes[j]; 252ef476b0dSDanilo Krummrich } 253ef476b0dSDanilo Krummrich self.n += 1; 254ef476b0dSDanilo Krummrich j += 1; 255ef476b0dSDanilo Krummrich } 256ef476b0dSDanilo Krummrich self 257ef476b0dSDanilo Krummrich } 258ef476b0dSDanilo Krummrich 259ef476b0dSDanilo Krummrich /// Push an additional path component. 260ef476b0dSDanilo Krummrich /// 261ef476b0dSDanilo Krummrich /// Append path components to the [`ModInfoBuilder`] instance. Paths need to be separated 262ef476b0dSDanilo Krummrich /// with [`ModInfoBuilder::new_entry`]. 263ef476b0dSDanilo Krummrich /// 264ef476b0dSDanilo Krummrich /// # Example 265ef476b0dSDanilo Krummrich /// 266ef476b0dSDanilo Krummrich /// ``` 267ef476b0dSDanilo Krummrich /// use kernel::firmware::ModInfoBuilder; 268ef476b0dSDanilo Krummrich /// 269ef476b0dSDanilo Krummrich /// # const DIR: &str = "vendor/chip/"; 270ef476b0dSDanilo Krummrich /// # const fn no_run<const N: usize>(builder: ModInfoBuilder<N>) { 271ef476b0dSDanilo Krummrich /// let builder = builder.new_entry() 272ef476b0dSDanilo Krummrich /// .push(DIR) 273ef476b0dSDanilo Krummrich /// .push("foo.bin") 274ef476b0dSDanilo Krummrich /// .new_entry() 275ef476b0dSDanilo Krummrich /// .push(DIR) 276ef476b0dSDanilo Krummrich /// .push("bar.bin"); 277ef476b0dSDanilo Krummrich /// # } 278ef476b0dSDanilo Krummrich /// ``` push(self, s: &str) -> Self279ef476b0dSDanilo Krummrich pub const fn push(self, s: &str) -> Self { 280ef476b0dSDanilo Krummrich // Check whether there has been an initial call to `next_entry()`. 281ef476b0dSDanilo Krummrich if N != 0 && self.n == 0 { 282ef476b0dSDanilo Krummrich crate::build_error!("Must call next_entry() before push()."); 283ef476b0dSDanilo Krummrich } 284ef476b0dSDanilo Krummrich 285ef476b0dSDanilo Krummrich self.push_internal(s.as_bytes()) 286ef476b0dSDanilo Krummrich } 287ef476b0dSDanilo Krummrich push_module_name(self) -> Self288ef476b0dSDanilo Krummrich const fn push_module_name(self) -> Self { 289ef476b0dSDanilo Krummrich let mut this = self; 290ef476b0dSDanilo Krummrich let module_name = this.module_name; 291ef476b0dSDanilo Krummrich 292ef476b0dSDanilo Krummrich if !this.module_name.is_empty() { 293ef476b0dSDanilo Krummrich this = this.push_internal(module_name.as_bytes_with_nul()); 294ef476b0dSDanilo Krummrich 295ef476b0dSDanilo Krummrich if N != 0 { 296ef476b0dSDanilo Krummrich // Re-use the space taken by the NULL terminator and swap it with the '.' separator. 297ef476b0dSDanilo Krummrich this.buf[this.n - 1] = b'.'; 298ef476b0dSDanilo Krummrich } 299ef476b0dSDanilo Krummrich } 300ef476b0dSDanilo Krummrich 301ef476b0dSDanilo Krummrich this 302ef476b0dSDanilo Krummrich } 303ef476b0dSDanilo Krummrich 304ef476b0dSDanilo Krummrich /// Prepare the [`ModInfoBuilder`] for the next entry. 305ef476b0dSDanilo Krummrich /// 306ef476b0dSDanilo Krummrich /// This method acts as a separator between module firmware path entries. 307ef476b0dSDanilo Krummrich /// 308ef476b0dSDanilo Krummrich /// Must be called before constructing a new entry with subsequent calls to 309ef476b0dSDanilo Krummrich /// [`ModInfoBuilder::push`]. 310ef476b0dSDanilo Krummrich /// 311ef476b0dSDanilo Krummrich /// See [`ModInfoBuilder::push`] for an example. new_entry(self) -> Self312ef476b0dSDanilo Krummrich pub const fn new_entry(self) -> Self { 313ef476b0dSDanilo Krummrich self.push_internal(b"\0") 314ef476b0dSDanilo Krummrich .push_module_name() 315ef476b0dSDanilo Krummrich .push_internal(b"firmware=") 316ef476b0dSDanilo Krummrich } 317ef476b0dSDanilo Krummrich 318ef476b0dSDanilo Krummrich /// Build the byte array. build(self) -> [u8; N]319ef476b0dSDanilo Krummrich pub const fn build(self) -> [u8; N] { 320ef476b0dSDanilo Krummrich // Add the final NULL terminator. 321ef476b0dSDanilo Krummrich let this = self.push_internal(b"\0"); 322ef476b0dSDanilo Krummrich 323ef476b0dSDanilo Krummrich if this.n == N { 324ef476b0dSDanilo Krummrich this.buf 325ef476b0dSDanilo Krummrich } else { 326ef476b0dSDanilo Krummrich crate::build_error!("Length mismatch."); 327ef476b0dSDanilo Krummrich } 328ef476b0dSDanilo Krummrich } 329ef476b0dSDanilo Krummrich } 330ef476b0dSDanilo Krummrich 331ef476b0dSDanilo Krummrich impl ModInfoBuilder<0> { 332ef476b0dSDanilo Krummrich /// Return the length of the byte array to build. build_length(self) -> usize333ef476b0dSDanilo Krummrich pub const fn build_length(self) -> usize { 334ef476b0dSDanilo Krummrich // Compensate for the NULL terminator added by `build`. 335ef476b0dSDanilo Krummrich self.n + 1 336ef476b0dSDanilo Krummrich } 337ef476b0dSDanilo Krummrich } 338