From: Danilo Krummrich <dakr@redhat.com>
To: Zhi Wang <zhiw@nvidia.com>
Cc: maarten.lankhorst@linux.intel.com, mripard@kernel.org,
tzimmermann@suse.de, airlied@gmail.com, daniel@ffwll.ch,
ojeda@kernel.org, alex.gaynor@gmail.com, wedsonaf@gmail.com,
boqun.feng@gmail.com, gary@garyguo.net, bjorn3_gh@protonmail.com,
benno.lossin@proton.me, a.hindborg@samsung.com,
aliceryhl@google.com, fujita.tomonori@gmail.com,
lina@asahilina.net, pstanner@redhat.com, ajanulgu@redhat.com,
lyude@redhat.com, gregkh@linuxfoundation.org,
rust-for-linux@vger.kernel.org, dri-devel@lists.freedesktop.org,
nouveau@lists.freedesktop.org
Subject: Re: [RFC PATCH 7/8] rust: add firmware abstractions
Date: Mon, 27 May 2024 21:18:53 +0200 [thread overview]
Message-ID: <ZlTcnYNff2EDQJdj@pollux.localdomain> (raw)
In-Reply-To: <20240521083231.000074c2.zhiw@nvidia.com>
On Tue, May 21, 2024 at 08:32:31AM +0300, Zhi Wang wrote:
> On Mon, 20 May 2024 19:24:19 +0200
> Danilo Krummrich <dakr@redhat.com> wrote:
>
> > Add an abstraction around the kernels firmware API to request firmware
> > images. The abstraction provides functions to access the firmware
> > buffer and / or copy it to a new buffer allocated with a given
> > allocator backend.
> >
>
> Was playing with firmware extractions based on this patch.
> Unfortunately I ended up with a lot of pointer operations, unsafe
> statements.
>
> As we know many vendors have a C headers for the definitions of the
> firwmare content, the driver extract the data by applying a struct
> pointer on it.
>
> But in rust, I feel it would nice that we can also have a common
> firmware extractor for drivers, that can wrap the pointer operations,
> take a list of the firmware struct members that converted from C headers
> as the input, offer the driver some common ABI methods to query them.
> Maybe that would ease the pain a lot.
So, you mean some abstraction that takes a list of types, offsets in the
firmware and a reference to the firmware itself and provides references to the
corresponding objects?
I agree it might be helpful to have some common infrastructure for this, but the
operations on it would still be unsafe, since ultimately it involves
dereferencing pointers.
>
> Thanks,
> Zhi.
>
> > The firmware is released once the abstraction is dropped.
> >
> > Signed-off-by: Danilo Krummrich <dakr@redhat.com>
> > ---
> > rust/bindings/bindings_helper.h | 1 +
> > rust/kernel/firmware.rs | 74
> > +++++++++++++++++++++++++++++++++ rust/kernel/lib.rs |
> > 1 + 3 files changed, 76 insertions(+)
> > create mode 100644 rust/kernel/firmware.rs
> >
> > diff --git a/rust/bindings/bindings_helper.h
> > b/rust/bindings/bindings_helper.h index b245db8d5a87..e4ffc47da5ec
> > 100644 --- a/rust/bindings/bindings_helper.h
> > +++ b/rust/bindings/bindings_helper.h
> > @@ -14,6 +14,7 @@
> > #include <kunit/test.h>
> > #include <linux/errname.h>
> > #include <linux/ethtool.h>
> > +#include <linux/firmware.h>
> > #include <linux/jiffies.h>
> > #include <linux/mdio.h>
> > #include <linux/pci.h>
> > diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs
> > new file mode 100644
> > index 000000000000..700504fb3c9c
> > --- /dev/null
> > +++ b/rust/kernel/firmware.rs
> > @@ -0,0 +1,74 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +//! Firmware abstraction
> > +//!
> > +//! C header:
> > [`include/linux/firmware.h`](../../../../include/linux/firmware.h") +
> > +use crate::{bindings, device::Device, error::Error, error::Result,
> > str::CStr, types::Opaque}; +
> > +/// Abstraction around a C firmware struct.
> > +///
> > +/// 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]`. Alternatively, the firmware can be copied to a new buffer
> > using `Firmware::copy`. The +/// firmware is released once
> > [`Firmware`] is dropped. +/// +/// # Examples
> > +///
> > +/// ```
> > +/// let fw = Firmware::request("path/to/firmware.bin",
> > dev.as_ref())?; +/// driver_load_firmware(fw.data());
> > +/// ```
> > +pub struct Firmware(Opaque<*const bindings::firmware>);
> > +
> > +impl Firmware {
> > + /// Send a firmware request and wait for it. See also
> > `bindings::request_firmware`.
> > + pub fn request(name: &CStr, dev: &Device) -> Result<Self> {
> > + let fw = Opaque::uninit();
> > +
> > + let ret = unsafe { bindings::request_firmware(fw.get(),
> > name.as_char_ptr(), dev.as_raw()) };
> > + if ret != 0 {
> > + return Err(Error::from_errno(ret));
> > + }
> > +
> > + Ok(Firmware(fw))
> > + }
> > +
> > + /// Send a request for an optional fw module. See also
> > `bindings::request_firmware_nowarn`.
> > + pub fn request_nowarn(name: &CStr, dev: &Device) -> Result<Self>
> > {
> > + let fw = Opaque::uninit();
> > +
> > + let ret = unsafe {
> > + bindings::firmware_request_nowarn(fw.get(),
> > name.as_char_ptr(), dev.as_raw())
> > + };
> > + if ret != 0 {
> > + return Err(Error::from_errno(ret));
> > + }
> > +
> > + Ok(Firmware(fw))
> > + }
> > +
> > + /// Returns the size of the requested firmware in bytes.
> > + pub fn size(&self) -> usize {
> > + unsafe { (*(*self.0.get())).size }
> > + }
> > +
> > + /// Returns the requested firmware as `&[u8]`.
> > + pub fn data(&self) -> &[u8] {
> > + unsafe {
> > core::slice::from_raw_parts((*(*self.0.get())).data, self.size()) }
> > + }
> > +}
> > +
> > +impl Drop for Firmware {
> > + fn drop(&mut self) {
> > + unsafe { bindings::release_firmware(*self.0.get()) };
> > + }
> > +}
> > +
> > +// SAFETY: `Firmware` only holds a pointer to a C firmware struct,
> > which is safe to be used from any +// thread.
> > +unsafe impl Send for Firmware {}
> > +
> > +// SAFETY: `Firmware` only holds a pointer to a C firmware struct,
> > references to which are safe to +// be used from any thread.
> > +unsafe impl Sync for Firmware {}
> > diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> > index 6415968ee3b8..ed97d131661a 100644
> > --- a/rust/kernel/lib.rs
> > +++ b/rust/kernel/lib.rs
> > @@ -35,6 +35,7 @@
> > #[cfg(CONFIG_DRM = "y")]
> > pub mod drm;
> > pub mod error;
> > +pub mod firmware;
> > pub mod init;
> > pub mod ioctl;
> > #[cfg(CONFIG_KUNIT)]
>
next prev parent reply other threads:[~2024-05-27 19:19 UTC|newest]
Thread overview: 52+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-05-20 17:20 [RFC PATCH 0/8] [RFC] DRM Rust abstractions and Nova Danilo Krummrich
2024-05-20 17:20 ` [RFC PATCH 1/8] rust: drm: ioctl: Add DRM ioctl abstraction Danilo Krummrich
2024-05-20 17:20 ` [RFC PATCH 2/8] rust: Add a Sealed trait Danilo Krummrich
2024-05-20 17:20 ` [RFC PATCH 3/8] rust: drm: Add Device and Driver abstractions Danilo Krummrich
2024-05-21 21:23 ` Rob Herring
2024-05-27 19:26 ` Danilo Krummrich
2024-06-09 5:15 ` Asahi Lina
2024-06-09 14:18 ` Danilo Krummrich
2024-06-11 15:46 ` Rob Herring
2024-05-20 17:20 ` [RFC PATCH 4/8] rust: drm: implement `AsRef` for DRM device Danilo Krummrich
2024-05-20 17:24 ` Danilo Krummrich
2024-05-20 17:24 ` [RFC PATCH 5/8] rust: drm: file: Add File abstraction Danilo Krummrich
2024-05-20 17:24 ` [RFC PATCH 6/8] rust: drm: gem: Add GEM object abstraction Danilo Krummrich
2024-06-06 15:26 ` Daniel Almeida
2024-05-20 17:24 ` [RFC PATCH 7/8] rust: add firmware abstractions Danilo Krummrich
2024-05-21 5:32 ` Zhi Wang
2024-05-27 19:18 ` Danilo Krummrich [this message]
2024-05-28 8:40 ` Zhi Wang
2024-05-28 10:17 ` FUJITA Tomonori
2024-05-28 10:45 ` Zhi Wang
2024-05-28 14:18 ` Danilo Krummrich
2024-05-28 21:20 ` Zhi Wang
2024-05-21 23:53 ` FUJITA Tomonori
2024-05-22 7:37 ` Philipp Stanner
2024-05-22 23:15 ` FUJITA Tomonori
2024-05-23 2:48 ` Boqun Feng
2024-05-27 19:22 ` Danilo Krummrich
2024-05-28 11:01 ` FUJITA Tomonori
2024-05-28 12:19 ` Danilo Krummrich
2024-05-28 12:45 ` Greg KH
2024-05-28 13:17 ` Danilo Krummrich
2024-05-29 0:28 ` FUJITA Tomonori
2024-05-29 19:57 ` Greg KH
2024-05-29 23:28 ` FUJITA Tomonori
2024-05-30 2:01 ` Danilo Krummrich
2024-05-30 4:24 ` FUJITA Tomonori
2024-05-30 6:47 ` Danilo Krummrich
2024-05-31 7:50 ` FUJITA Tomonori
2024-05-31 9:59 ` Danilo Krummrich
2024-06-07 12:11 ` FUJITA Tomonori
2024-06-07 12:36 ` Greg KH
2024-06-07 13:05 ` Danilo Krummrich
2024-06-07 13:33 ` Danilo Krummrich
2024-06-07 15:41 ` Greg KH
2024-06-07 17:55 ` Danilo Krummrich
2024-06-07 23:28 ` FUJITA Tomonori
2024-06-10 13:13 ` Danilo Krummrich
2024-06-07 12:43 ` Danilo Krummrich
2024-05-29 0:38 ` FUJITA Tomonori
2024-05-28 12:06 ` Danilo Krummrich
2024-05-20 17:24 ` [RFC PATCH 8/8] nova: add initial driver stub Danilo Krummrich
2024-05-20 17:30 ` Device / Driver and PCI Rust abstractions Danilo Krummrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZlTcnYNff2EDQJdj@pollux.localdomain \
--to=dakr@redhat.com \
--cc=a.hindborg@samsung.com \
--cc=airlied@gmail.com \
--cc=ajanulgu@redhat.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=daniel@ffwll.ch \
--cc=dri-devel@lists.freedesktop.org \
--cc=fujita.tomonori@gmail.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=lina@asahilina.net \
--cc=lyude@redhat.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=ojeda@kernel.org \
--cc=pstanner@redhat.com \
--cc=rust-for-linux@vger.kernel.org \
--cc=tzimmermann@suse.de \
--cc=wedsonaf@gmail.com \
--cc=zhiw@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.