File Index
Files and directories
Sign in
FILE

rust_driver_platform.rs

File preview with syntax highlighting.

linux-6.19.14/samples/rust/rust_driver_platform.rs RUST
  1// SPDX-License-Identifier: GPL-2.0
  2
  3//! Rust Platform driver sample.
  4
  5//! ACPI match table test
  6//!
  7//! This demonstrates how to test an ACPI-based Rust platform driver using QEMU
  8//! with a custom SSDT.
  9//!
 10//! Steps:
 11//!
 12//! 1. **Create an SSDT source file** (`ssdt.dsl`) with the following content:
 13//!
 14//!     ```asl
 15//!     DefinitionBlock ("", "SSDT", 2, "TEST", "VIRTACPI", 0x00000001)
 16//!     {
 17//!         Scope (\_SB)
 18//!         {
 19//!             Device (T432)
 20//!             {
 21//!                 Name (_HID, "LNUXBEEF")  // ACPI hardware ID to match
 22//!                 Name (_UID, 1)
 23//!                 Name (_STA, 0x0F)        // Device present, enabled
 24//!                 Name (_CRS, ResourceTemplate ()
 25//!                 {
 26//!                     Memory32Fixed (ReadWrite, 0xFED00000, 0x1000)
 27//!                 })
 28//!             }
 29//!         }
 30//!     }
 31//!     ```
 32//!
 33//! 2. **Compile the table**:
 34//!
 35//!     ```sh
 36//!     iasl -tc ssdt.dsl
 37//!     ```
 38//!
 39//!     This generates `ssdt.aml`
 40//!
 41//! 3. **Run QEMU** with the compiled AML file:
 42//!
 43//!     ```sh
 44//!     qemu-system-x86_64 -m 512M \
 45//!         -enable-kvm \
 46//!         -kernel path/to/bzImage \
 47//!         -append "root=/dev/sda console=ttyS0" \
 48//!         -hda rootfs.img \
 49//!         -serial stdio \
 50//!         -acpitable file=ssdt.aml
 51//!     ```
 52//!
 53//!     Requirements:
 54//!     - The `rust_driver_platform` must be present either:
 55//!         - built directly into the kernel (`bzImage`), or
 56//!         - available as a `.ko` file and loadable from `rootfs.img`
 57//!
 58//! 4. **Verify it worked** by checking `dmesg`:
 59//!
 60//!     ```
 61//!     rust_driver_platform LNUXBEEF:00: Probed with info: '0'.
 62//!     ```
 63//!
 64
 65use kernel::{
 66    acpi, c_str,
 67    device::{
 68        self,
 69        property::{FwNodeReferenceArgs, NArgs},
 70        Core,
 71    },
 72    of, platform,
 73    prelude::*,
 74    str::CString,
 75    sync::aref::ARef,
 76};
 77
 78struct SampleDriver {
 79    pdev: ARef<platform::Device>,
 80}
 81
 82struct Info(u32);
 83
 84kernel::of_device_table!(
 85    OF_TABLE,
 86    MODULE_OF_TABLE,
 87    <SampleDriver as platform::Driver>::IdInfo,
 88    [(of::DeviceId::new(c_str!("test,rust-device")), Info(42))]
 89);
 90
 91kernel::acpi_device_table!(
 92    ACPI_TABLE,
 93    MODULE_ACPI_TABLE,
 94    <SampleDriver as platform::Driver>::IdInfo,
 95    [(acpi::DeviceId::new(c_str!("LNUXBEEF")), Info(0))]
 96);
 97
 98impl platform::Driver for SampleDriver {
 99    type IdInfo = Info;
100    const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = Some(&OF_TABLE);
101    const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE);
102
103    fn probe(
104        pdev: &platform::Device<Core>,
105        info: Option<&Self::IdInfo>,
106    ) -> impl PinInit<Self, Error> {
107        let dev = pdev.as_ref();
108
109        dev_dbg!(dev, "Probe Rust Platform driver sample.\n");
110
111        if let Some(info) = info {
112            dev_info!(dev, "Probed with info: '{}'.\n", info.0);
113        }
114
115        if dev.fwnode().is_some_and(|node| node.is_of_node()) {
116            Self::properties_parse(dev)?;
117        }
118
119        Ok(Self { pdev: pdev.into() })
120    }
121}
122
123impl SampleDriver {
124    fn properties_parse(dev: &device::Device) -> Result {
125        let fwnode = dev.fwnode().ok_or(ENOENT)?;
126
127        if let Ok(idx) =
128            fwnode.property_match_string(c_str!("compatible"), c_str!("test,rust-device"))
129        {
130            dev_info!(dev, "matched compatible string idx = {}\n", idx);
131        }
132
133        let name = c_str!("compatible");
134        let prop = fwnode.property_read::<CString>(name).required_by(dev)?;
135        dev_info!(dev, "'{name}'='{prop:?}'\n");
136
137        let name = c_str!("test,bool-prop");
138        let prop = fwnode.property_read_bool(c_str!("test,bool-prop"));
139        dev_info!(dev, "'{name}'='{prop}'\n");
140
141        if fwnode.property_present(c_str!("test,u32-prop")) {
142            dev_info!(dev, "'test,u32-prop' is present\n");
143        }
144
145        let name = c_str!("test,u32-optional-prop");
146        let prop = fwnode.property_read::<u32>(name).or(0x12);
147        dev_info!(dev, "'{name}'='{prop:#x}' (default = 0x12)\n");
148
149        // A missing required property will print an error. Discard the error to
150        // prevent properties_parse from failing in that case.
151        let name = c_str!("test,u32-required-prop");
152        let _ = fwnode.property_read::<u32>(name).required_by(dev);
153
154        let name = c_str!("test,u32-prop");
155        let prop: u32 = fwnode.property_read(name).required_by(dev)?;
156        dev_info!(dev, "'{name}'='{prop:#x}'\n");
157
158        let name = c_str!("test,i16-array");
159        let prop: [i16; 4] = fwnode.property_read(name).required_by(dev)?;
160        dev_info!(dev, "'{name}'='{prop:?}'\n");
161        let len = fwnode.property_count_elem::<u16>(name)?;
162        dev_info!(dev, "'{name}' length is {len}\n");
163
164        let name = c_str!("test,i16-array");
165        let prop: KVec<i16> = fwnode.property_read_array_vec(name, 4)?.required_by(dev)?;
166        dev_info!(dev, "'{name}'='{prop:?}' (KVec)\n");
167
168        for child in fwnode.children() {
169            let name = c_str!("test,ref-arg");
170            let nargs = NArgs::N(2);
171            let prop: FwNodeReferenceArgs = child.property_get_reference_args(name, nargs, 0)?;
172            dev_info!(dev, "'{name}'='{prop:?}'\n");
173        }
174
175        Ok(())
176    }
177}
178
179impl Drop for SampleDriver {
180    fn drop(&mut self) {
181        dev_dbg!(self.pdev.as_ref(), "Remove Rust Platform driver sample.\n");
182    }
183}
184
185kernel::module_platform_driver! {
186    type: SampleDriver,
187    name: "rust_driver_platform",
188    authors: ["Danilo Krummrich"],
189    description: "Rust Platform driver",
190    license: "GPL v2",
191}
~/ Read-only file preview.