// SPDX-License-Identifier: GPL-2.012//! Firmware abstraction3//!4//! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.h)56use crate::{bindings, device::Device, error::Error, error::Result, ffi, str::CStr};7use core::ptr::NonNull;89/// # Invariants10///11/// One of the following: `bindings::request_firmware`, `bindings::firmware_request_nowarn`,12/// `bindings::firmware_request_platform`, `bindings::request_firmware_direct`.13struct FwFunc(14unsafe extern "C" fn(15*mut *const bindings::firmware,16*const ffi::c_char,17*mut bindings::device,18) -> i32,19);2021impl FwFunc {22fn request() -> Self {23Self(bindings::request_firmware)24}2526fn request_nowarn() -> Self {27Self(bindings::firmware_request_nowarn)28}29}3031/// Abstraction around a C `struct firmware`.32///33/// This is a simple abstraction around the C firmware API. Just like with the C API, firmware can34/// be requested. Once requested the abstraction provides direct access to the firmware buffer as35/// `&[u8]`. The firmware is released once [`Firmware`] is dropped.36///37/// # Invariants38///39/// The pointer is valid, and has ownership over the instance of `struct firmware`.40///41/// The `Firmware`'s backing buffer is not modified.42///43/// # Examples44///45/// ```no_run46/// # use kernel::{c_str, device::Device, firmware::Firmware};47///48/// # fn no_run() -> Result<(), Error> {49/// # // SAFETY: *NOT* safe, just for the example to get an `ARef<Device>` instance50/// # let dev = unsafe { Device::get_device(core::ptr::null_mut()) };51///52/// let fw = Firmware::request(c_str!("path/to/firmware.bin"), &dev)?;53/// let blob = fw.data();54///55/// # Ok(())56/// # }57/// ```58pub struct Firmware(NonNull<bindings::firmware>);5960impl Firmware {61fn request_internal(name: &CStr, dev: &Device, func: FwFunc) -> Result<Self> {62let mut fw: *mut bindings::firmware = core::ptr::null_mut();63let pfw: *mut *mut bindings::firmware = &mut fw;64let pfw: *mut *const bindings::firmware = pfw.cast();6566// SAFETY: `pfw` is a valid pointer to a NULL initialized `bindings::firmware` pointer.67// `name` and `dev` are valid as by their type invariants.68let ret = unsafe { func.0(pfw, name.as_char_ptr(), dev.as_raw()) };69if ret != 0 {70return Err(Error::from_errno(ret));71}7273// SAFETY: `func` not bailing out with a non-zero error code, guarantees that `fw` is a74// valid pointer to `bindings::firmware`.75Ok(Firmware(unsafe { NonNull::new_unchecked(fw) }))76}7778/// Send a firmware request and wait for it. See also `bindings::request_firmware`.79pub fn request(name: &CStr, dev: &Device) -> Result<Self> {80Self::request_internal(name, dev, FwFunc::request())81}8283/// Send a request for an optional firmware module. See also84/// `bindings::firmware_request_nowarn`.85pub fn request_nowarn(name: &CStr, dev: &Device) -> Result<Self> {86Self::request_internal(name, dev, FwFunc::request_nowarn())87}8889fn as_raw(&self) -> *mut bindings::firmware {90self.0.as_ptr()91}9293/// Returns the size of the requested firmware in bytes.94pub fn size(&self) -> usize {95// SAFETY: `self.as_raw()` is valid by the type invariant.96unsafe { (*self.as_raw()).size }97}9899/// Returns the requested firmware as `&[u8]`.100pub fn data(&self) -> &[u8] {101// SAFETY: `self.as_raw()` is valid by the type invariant. Additionally,102// `bindings::firmware` guarantees, if successfully requested, that103// `bindings::firmware::data` has a size of `bindings::firmware::size` bytes.104unsafe { core::slice::from_raw_parts((*self.as_raw()).data, self.size()) }105}106}107108impl Drop for Firmware {109fn drop(&mut self) {110// SAFETY: `self.as_raw()` is valid by the type invariant.111unsafe { bindings::release_firmware(self.as_raw()) };112}113}114115// SAFETY: `Firmware` only holds a pointer to a C `struct firmware`, which is safe to be used from116// any thread.117unsafe impl Send for Firmware {}118119// SAFETY: `Firmware` only holds a pointer to a C `struct firmware`, references to which are safe to120// be used from any thread.121unsafe impl Sync for Firmware {}122123/// Create firmware .modinfo entries.124///125/// This macro is the counterpart of the C macro `MODULE_FIRMWARE()`, but instead of taking a126/// simple string literals, which is already covered by the `firmware` field of127/// [`crate::prelude::module!`], it allows the caller to pass a builder type, based on the128/// [`ModInfoBuilder`], which can create the firmware modinfo strings in a more flexible way.129///130/// Drivers should extend the [`ModInfoBuilder`] with their own driver specific builder type.131///132/// The `builder` argument must be a type which implements the following function.133///134/// `const fn create(module_name: &'static CStr) -> ModInfoBuilder`135///136/// `create` should pass the `module_name` to the [`ModInfoBuilder`] and, with the help of137/// it construct the corresponding firmware modinfo.138///139/// Typically, such contracts would be enforced by a trait, however traits do not (yet) support140/// const functions.141///142/// # Examples143///144/// ```145/// # mod module_firmware_test {146/// # use kernel::firmware;147/// # use kernel::prelude::*;148/// #149/// # struct MyModule;150/// #151/// # impl kernel::Module for MyModule {152/// # fn init(_module: &'static ThisModule) -> Result<Self> {153/// # Ok(Self)154/// # }155/// # }156/// #157/// #158/// struct Builder<const N: usize>;159///160/// impl<const N: usize> Builder<N> {161/// const DIR: &'static str = "vendor/chip/";162/// const FILES: [&'static str; 3] = [ "foo", "bar", "baz" ];163///164/// const fn create(module_name: &'static kernel::str::CStr) -> firmware::ModInfoBuilder<N> {165/// let mut builder = firmware::ModInfoBuilder::new(module_name);166///167/// let mut i = 0;168/// while i < Self::FILES.len() {169/// builder = builder.new_entry()170/// .push(Self::DIR)171/// .push(Self::FILES[i])172/// .push(".bin");173///174/// i += 1;175/// }176///177/// builder178/// }179/// }180///181/// module! {182/// type: MyModule,183/// name: "module_firmware_test",184/// authors: ["Rust for Linux"],185/// description: "module_firmware! test module",186/// license: "GPL",187/// }188///189/// kernel::module_firmware!(Builder);190/// # }191/// ```192#[macro_export]193macro_rules! module_firmware {194// The argument is the builder type without the const generic, since it's deferred from within195// this macro. Hence, we can neither use `expr` nor `ty`.196($($builder:tt)*) => {197const _: () = {198const __MODULE_FIRMWARE_PREFIX: &'static $crate::str::CStr = if cfg!(MODULE) {199$crate::c_str!("")200} else {201<LocalModule as $crate::ModuleMetadata>::NAME202};203204#[link_section = ".modinfo"]205#[used(compiler)]206static __MODULE_FIRMWARE: [u8; $($builder)*::create(__MODULE_FIRMWARE_PREFIX)207.build_length()] = $($builder)*::create(__MODULE_FIRMWARE_PREFIX).build();208};209};210}211212/// Builder for firmware module info.213///214/// [`ModInfoBuilder`] is a helper component to flexibly compose firmware paths strings for the215/// .modinfo section in const context.216///217/// Therefore the [`ModInfoBuilder`] provides the methods [`ModInfoBuilder::new_entry`] and218/// [`ModInfoBuilder::push`], where the latter is used to push path components and the former to219/// mark the beginning of a new path string.220///221/// [`ModInfoBuilder`] is meant to be used in combination with [`kernel::module_firmware!`].222///223/// The const generic `N` as well as the `module_name` parameter of [`ModInfoBuilder::new`] is an224/// internal implementation detail and supplied through the above macro.225pub struct ModInfoBuilder<const N: usize> {226buf: [u8; N],227n: usize,228module_name: &'static CStr,229}230231impl<const N: usize> ModInfoBuilder<N> {232/// Create an empty builder instance.233pub const fn new(module_name: &'static CStr) -> Self {234Self {235buf: [0; N],236n: 0,237module_name,238}239}240241const fn push_internal(mut self, bytes: &[u8]) -> Self {242let mut j = 0;243244if N == 0 {245self.n += bytes.len();246return self;247}248249while j < bytes.len() {250if self.n < N {251self.buf[self.n] = bytes[j];252}253self.n += 1;254j += 1;255}256self257}258259/// Push an additional path component.260///261/// Append path components to the [`ModInfoBuilder`] instance. Paths need to be separated262/// with [`ModInfoBuilder::new_entry`].263///264/// # Examples265///266/// ```267/// use kernel::firmware::ModInfoBuilder;268///269/// # const DIR: &str = "vendor/chip/";270/// # const fn no_run<const N: usize>(builder: ModInfoBuilder<N>) {271/// let builder = builder.new_entry()272/// .push(DIR)273/// .push("foo.bin")274/// .new_entry()275/// .push(DIR)276/// .push("bar.bin");277/// # }278/// ```279pub const fn push(self, s: &str) -> Self {280// Check whether there has been an initial call to `next_entry()`.281if N != 0 && self.n == 0 {282crate::build_error!("Must call next_entry() before push().");283}284285self.push_internal(s.as_bytes())286}287288const fn push_module_name(self) -> Self {289let mut this = self;290let module_name = this.module_name;291292if !this.module_name.is_empty() {293this = this.push_internal(module_name.to_bytes_with_nul());294295if N != 0 {296// Re-use the space taken by the NULL terminator and swap it with the '.' separator.297this.buf[this.n - 1] = b'.';298}299}300301this302}303304/// Prepare the [`ModInfoBuilder`] for the next entry.305///306/// This method acts as a separator between module firmware path entries.307///308/// Must be called before constructing a new entry with subsequent calls to309/// [`ModInfoBuilder::push`].310///311/// See [`ModInfoBuilder::push`] for an example.312pub const fn new_entry(self) -> Self {313self.push_internal(b"\0")314.push_module_name()315.push_internal(b"firmware=")316}317318/// Build the byte array.319pub const fn build(self) -> [u8; N] {320// Add the final NULL terminator.321let this = self.push_internal(b"\0");322323if this.n == N {324this.buf325} else {326crate::build_error!("Length mismatch.");327}328}329}330331impl ModInfoBuilder<0> {332/// Return the length of the byte array to build.333pub const fn build_length(self) -> usize {334// Compensate for the NULL terminator added by `build`.335self.n + 1336}337}338339340