From 20c2b0351ede60391b8147a076edba3308d1fbf4 Mon Sep 17 00:00:00 2001 From: Danilo Krummrich Date: Fri, 17 May 2024 22:10:53 +0200 Subject: rust: firmware: implement `copy` Implement `copy` to copy firmware to a buffer backed by the given allocator. Signed-off-by: Danilo Krummrich --- rust/kernel/firmware.rs | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs index 2ba03af9f036..66033aee5984 100644 --- a/rust/kernel/firmware.rs +++ b/rust/kernel/firmware.rs @@ -4,7 +4,14 @@ //! //! C header: [`include/linux/firmware.h`](srctree/include/linux/firmware.h") -use crate::{bindings, device::Device, error::Error, error::Result, str::CStr}; +use crate::{ + alloc::{Allocator, Flags, Vec}, + bindings, + device::Device, + error::Error, + error::Result, + str::CStr, +}; use core::ptr::NonNull; /// # Invariants @@ -29,7 +36,8 @@ impl FwFunc { /// /// This is a simple abstraction around the C firmware API. Just like with the C API, firmware can /// be requested. Once requested the abstraction provides direct access to the firmware buffer as -/// `&[u8]`. The firmware is released once [`Firmware`] is dropped. +/// `&[u8]`. Alternatively, the firmware can be copied to a new buffer using `Firmware::copy`. The +/// firmware is released once [`Firmware`] is dropped. /// /// # Invariants /// @@ -52,6 +60,22 @@ impl FwFunc { /// # Ok(()) /// # } /// ``` +/// +/// ```no_run +/// use kernel::alloc::allocator::Vmalloc; +/// # use kernel::{c_str, device::Device, firmware::Firmware}; +/// +/// # fn no_run() -> Result<(), Error> { +/// # // SAFETY: *NOT* safe, just for the example to get an `ARef` instance +/// # let dev = unsafe { Device::from_raw(core::ptr::null_mut()) }; +/// +/// let fw = Firmware::request(c_str!("path/to/firmware.bin"), &dev)?; +/// let fw = fw.copy::(GFP_KERNEL)?; +/// let blob = fw.as_slice(); +/// +/// # Ok(()) +/// # } +/// ``` pub struct Firmware(NonNull); impl Firmware { @@ -99,6 +123,16 @@ impl Firmware { // `bindings::firmware::data` has a size of `bindings::firmware::size` bytes. unsafe { core::slice::from_raw_parts((*self.as_raw()).data, self.size()) } } + + /// Copies the requested firmware into a new `Vec`, using the given allocator and flags + /// to allocate the vector's backing buffer. + pub fn copy(&self, flags: Flags) -> Result> { + let mut dst = Vec::::new(); + + dst.extend_from_slice(self.data(), flags)?; + + Ok(dst) + } } impl Drop for Firmware { -- cgit v1.2.3-58-ga151