diff options
author | Danilo Krummrich <dakr@redhat.com> | 2024-05-17 22:10:53 +0200 |
---|---|---|
committer | Danilo Krummrich <dakr@kernel.org> | 2024-08-13 16:11:41 +0200 |
commit | 20c2b0351ede60391b8147a076edba3308d1fbf4 (patch) | |
tree | 56f0a23d378b516c2328eaf33ab94f5ac33ce646 | |
parent | 562ab2de513d3a1e5ee16ae4ec15c493a1264dd4 (diff) |
rust: firmware: implement `copy<A: Allocator>`
Implement `copy<A: Allocator>` to copy firmware to a buffer backed by the
given allocator.
Signed-off-by: Danilo Krummrich <dakr@redhat.com>
-rw-r--r-- | rust/kernel/firmware.rs | 38 |
1 files 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<Device>` 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::<Vmalloc>(GFP_KERNEL)?; +/// let blob = fw.as_slice(); +/// +/// # Ok(()) +/// # } +/// ``` pub struct Firmware(NonNull<bindings::firmware>); 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<u8, A>`, using the given allocator and flags + /// to allocate the vector's backing buffer. + pub fn copy<A: Allocator>(&self, flags: Flags) -> Result<Vec<u8, A>> { + let mut dst = Vec::<u8, A>::new(); + + dst.extend_from_slice(self.data(), flags)?; + + Ok(dst) + } } impl Drop for Firmware { |