From: Gary Guo <gary@garyguo.net>
To: Gladyshev Ilya <foxido@foxido.dev>
Cc: "foxido @ foxido . dev-cc= Rafael J. Wysocki" <rafael@kernel.org>,
Len Brown <lenb@kernel.org>, Miguel Ojeda <ojeda@kernel.org>,
Boqun Feng <boqun.feng@gmail.com>,
Benno Lossin <lossin@kernel.org>,
Andreas Hindborg <a.hindborg@kernel.org>,
Alice Ryhl <aliceryhl@google.com>,
Trevor Gross <tmgross@umich.edu>,
Danilo Krummrich <dakr@kernel.org>,
Tamir Duberstein <tamird@gmail.com>, Armin Wolf <W_Armin@gmx.de>,
<platform-driver-x86@vger.kernel.org>,
<linux-kernel@vger.kernel.org>, <rust-for-linux@vger.kernel.org>,
<linux-acpi@vger.kernel.org>
Subject: Re: [PATCH 2/3] rust: implement wrapper for acpi_object
Date: Thu, 8 Jan 2026 13:21:41 +0000 [thread overview]
Message-ID: <20260108132141.6cce4827.gary@garyguo.net> (raw)
In-Reply-To: <05261e88ac8503e2af59d703389d94cc15f4450d.1767818037.git.foxido@foxido.dev>
On Wed, 7 Jan 2026 23:35:32 +0300
Gladyshev Ilya <foxido@foxido.dev> wrote:
> ACPI Object is represented via union on C-side. On Rust side, this union
> is transparently wrapped for each ACPI Type, with individual methods and
> Defer implementation to represented type (integer, string, buffer, etc).
>
> Signed-off-by: Gladyshev Ilya <foxido@foxido.dev>
Hi Gladyshev,
I've checked the `acpi_object` implementation on the C side and it appears
that the buffer is not owned by the object (however managed externally,
could either be resting in ACPI tables directly or be allocated).
Therefore, you might want to carry a lifetime to represent the lifetime of
underlying buffers?
> ---
> rust/kernel/acpi.rs | 91 +++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 91 insertions(+)
>
> diff --git a/rust/kernel/acpi.rs b/rust/kernel/acpi.rs
> index 9b8efa623130..ac1a9f305f6c 100644
> --- a/rust/kernel/acpi.rs
> +++ b/rust/kernel/acpi.rs
> @@ -2,6 +2,8 @@
>
> //! Advanced Configuration and Power Interface abstractions.
>
> +use core::ops::Deref;
> +
> use crate::{
> bindings,
> device_id::{RawDeviceId, RawDeviceIdIndex},
> @@ -63,3 +65,92 @@ macro_rules! acpi_device_table {
> $crate::module_device_table!("acpi", $module_table_name, $table_name);
> };
> }
> +
> +/// An ACPI object.
> +///
> +/// This structure represents the Rust abstraction for a C [`struct acpi_object`].
> +/// You probably want to convert it into actual object type (e.g [`AcpiBuffer`]).
> +///
> +/// # Example
> +/// ```
> +/// # use kernel::prelude::*;
> +/// use kernel::acpi::{AcpiObject, AcpiBuffer};
> +///
> +/// fn read_first_acpi_byte(obj: &AcpiObject) -> Result<u8> {
> +/// let buf: &AcpiBuffer = obj.try_into()?;
> +///
> +/// Ok(buf[0])
> +/// }
> +/// ```
> +///
> +/// [`struct acpi_object`]: srctree/include/acpi/actypes.h
> +#[repr(transparent)]
> +pub struct AcpiObject(bindings::acpi_object);
> +
> +impl AcpiObject {
> + /// Returns object type id (see [`actypes.h`](srctree/include/acpi/actypes.h)).
> + pub fn type_id(&self) -> u32 {
> + // SAFETY: `type` field is valid in all union variants.
> + unsafe { self.0.type_ }
> + }
This should probably be an enum instead of just integer.
> +}
> +
> +/// Generate wrapper type for AcpiObject subtype.
> +///
> +/// For given subtype implements
> +/// - `#[repr(transparent)]` type wrapper,
> +/// - `TryFrom<&AcpiObject> for &SubType` trait,
> +/// - unsafe from_unchecked() for 'trusted' conversion.
> +macro_rules! acpi_object_subtype {
> + ($subtype_name:ident <- ($acpi_type:ident, $field_name:ident, $union_type:ty)) => {
> + /// Wraps `acpi_object` subtype.
> + #[repr(transparent)]
> + pub struct $subtype_name($union_type);
Instead of wrapping the bindgen-generated subtypes, I would rather this to
be a transparent wrapper of `acpi_object`, with an invariant that the
specific union field is active.
This way you do not have to name the bindgen-generated names.
> +
> + impl<'a> TryFrom<&'a AcpiObject> for &'a $subtype_name {
> + type Error = Error;
> +
> + fn try_from(value: &'a AcpiObject) -> core::result::Result<Self, Self::Error> {
> + if (value.type_id() != $subtype_name::ACPI_TYPE) {
> + return Err(EINVAL);
> + }
> +
> + // SAFETY: Requested cast is valid because we validated type_id
> + Ok(unsafe { $subtype_name::from_unchecked(&value) })
> + }
> + }
It feels like this can be better implemented by having a sealed trait for
all possible ACPI object types?
> +
> + impl $subtype_name {
> + /// Int value, representing this ACPI type (see [`acpitypes.h`]).
> + ///
> + /// [`acpitypes.h`]: srctree/include/linux/acpitypes.h
> + pub const ACPI_TYPE: u32 = bindings::$acpi_type;
> +
> + /// Converts opaque AcpiObject reference into exact ACPI type reference.
> + ///
> + /// # Safety
> + ///
> + /// - Requested cast should be valid (value.type_id() is `Self::ACPI_TYPE`).
> + pub unsafe fn from_unchecked(value: &AcpiObject) -> &Self {
> + // SAFETY:
> + // - $field_name is currently active union's field due to external safety contract,
> + // - Transmuting to `repr(transparent)` wrapper is safe.
> + unsafe {
> + ::core::mem::transmute::<&$union_type, &$subtype_name>(&value.0.$field_name)
> + }
> + }
> + }
> + };
> +}
> +
> +acpi_object_subtype!(AcpiBuffer
> + <- (ACPI_TYPE_BUFFER, buffer, bindings::acpi_object__bindgen_ty_3));
> +
> +impl Deref for AcpiBuffer {
> + type Target = [u8];
> +
> + fn deref(&self) -> &Self::Target {
> + // SAFETY: (pointer, length) indeed represents byte slice.
> + unsafe { ::core::slice::from_raw_parts(self.0.pointer, self.0.length as usize) }
> + }
> +}
next prev parent reply other threads:[~2026-01-08 13:21 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-07 20:35 [PATCH 0/3] rust: WMI abstractions Gladyshev Ilya
2026-01-07 20:35 ` [PATCH 1/3] rust: enable const_intrinsic_copy feature Gladyshev Ilya
2026-01-07 20:35 ` [PATCH 2/3] rust: implement wrapper for acpi_object Gladyshev Ilya
2026-01-08 13:21 ` Gary Guo [this message]
2026-01-08 17:11 ` Gladyshev Ilya
2026-01-08 18:46 ` Miguel Ojeda
2026-01-09 10:57 ` Gladyshev Ilya
2026-01-11 17:57 ` Miguel Ojeda
2026-01-08 20:06 ` Gary Guo
2026-01-09 10:30 ` Gladyshev Ilya
2026-01-07 20:35 ` [PATCH 3/3] rust: add WMI abstractions Gladyshev Ilya
2026-01-08 19:48 ` Kari Argillander
2026-01-09 11:12 ` Gladyshev Ilya
2026-01-09 11:17 ` Kari Argillander
2026-01-08 20:48 ` Kari Argillander
2026-01-09 11:01 ` Gladyshev Ilya
2026-01-09 11:15 ` Kari Argillander
2026-01-09 11:31 ` Gladyshev Ilya
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=20260108132141.6cce4827.gary@garyguo.net \
--to=gary@garyguo.net \
--cc=W_Armin@gmx.de \
--cc=a.hindborg@kernel.org \
--cc=aliceryhl@google.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=foxido@foxido.dev \
--cc=lenb@kernel.org \
--cc=linux-acpi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=platform-driver-x86@vger.kernel.org \
--cc=rafael@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tamird@gmail.com \
--cc=tmgross@umich.edu \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox