1 // SPDX-License-Identifier: GPL-2.0 2 3 // Copyright (C) 2025 Google LLC. 4 5 //! Sample DebugFS exporting platform driver 6 //! 7 //! To successfully probe this driver with ACPI, use an ssdt that looks like 8 //! 9 //! ```dsl 10 //! DefinitionBlock ("", "SSDT", 2, "TEST", "VIRTACPI", 0x00000001) 11 //! { 12 //! Scope (\_SB) 13 //! { 14 //! Device (T432) 15 //! { 16 //! Name (_HID, "LNUXBEEF") // ACPI hardware ID to match 17 //! Name (_UID, 1) 18 //! Name (_STA, 0x0F) // Device present, enabled 19 //! Name (_DSD, Package () { // Sample attribute 20 //! ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"), 21 //! Package() { 22 //! Package(2) {"compatible", "sample-debugfs"} 23 //! } 24 //! }) 25 //! Name (_CRS, ResourceTemplate () 26 //! { 27 //! Memory32Fixed (ReadWrite, 0xFED00000, 0x1000) 28 //! }) 29 //! } 30 //! } 31 //! } 32 //! ``` 33 34 use core::str::FromStr; 35 use core::sync::atomic::AtomicUsize; 36 use core::sync::atomic::Ordering; 37 use kernel::c_str; 38 use kernel::debugfs::{Dir, File}; 39 use kernel::new_mutex; 40 use kernel::prelude::*; 41 use kernel::sizes::*; 42 use kernel::sync::Mutex; 43 44 use kernel::{acpi, device::Core, of, platform, str::CString, types::ARef}; 45 46 kernel::module_platform_driver! { 47 type: RustDebugFs, 48 name: "rust_debugfs", 49 authors: ["Matthew Maurer"], 50 description: "Rust DebugFS usage sample", 51 license: "GPL", 52 } 53 54 #[pin_data] 55 struct RustDebugFs { 56 pdev: ARef<platform::Device>, 57 // As we only hold these for drop effect (to remove the directory/files) we have a leading 58 // underscore to indicate to the compiler that we don't expect to use this field directly. 59 _debugfs: Dir, 60 #[pin] 61 _compatible: File<CString>, 62 #[pin] 63 counter: File<AtomicUsize>, 64 #[pin] 65 inner: File<Mutex<Inner>>, 66 #[pin] 67 array_blob: File<Mutex<[u8; 4]>>, 68 #[pin] 69 vector_blob: File<Mutex<KVec<u8>>>, 70 } 71 72 #[derive(Debug)] 73 struct Inner { 74 x: u32, 75 y: u32, 76 } 77 78 impl FromStr for Inner { 79 type Err = Error; 80 fn from_str(s: &str) -> Result<Self> { 81 let mut parts = s.split_whitespace(); 82 let x = parts 83 .next() 84 .ok_or(EINVAL)? 85 .parse::<u32>() 86 .map_err(|_| EINVAL)?; 87 let y = parts 88 .next() 89 .ok_or(EINVAL)? 90 .parse::<u32>() 91 .map_err(|_| EINVAL)?; 92 if parts.next().is_some() { 93 return Err(EINVAL); 94 } 95 Ok(Inner { x, y }) 96 } 97 } 98 99 kernel::acpi_device_table!( 100 ACPI_TABLE, 101 MODULE_ACPI_TABLE, 102 <RustDebugFs as platform::Driver>::IdInfo, 103 [(acpi::DeviceId::new(c_str!("LNUXBEEF")), ())] 104 ); 105 106 impl platform::Driver for RustDebugFs { 107 type IdInfo = (); 108 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None; 109 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); 110 111 fn probe( 112 pdev: &platform::Device<Core>, 113 _info: Option<&Self::IdInfo>, 114 ) -> impl PinInit<Self, Error> { 115 RustDebugFs::new(pdev).pin_chain(|this| { 116 this.counter.store(91, Ordering::Relaxed); 117 { 118 let mut guard = this.inner.lock(); 119 guard.x = guard.y; 120 guard.y = 42; 121 } 122 123 Ok(()) 124 }) 125 } 126 } 127 128 impl RustDebugFs { 129 fn build_counter(dir: &Dir) -> impl PinInit<File<AtomicUsize>> + '_ { 130 dir.read_write_file(c_str!("counter"), AtomicUsize::new(0)) 131 } 132 133 fn build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + '_ { 134 dir.read_write_file(c_str!("pair"), new_mutex!(Inner { x: 3, y: 10 })) 135 } 136 137 fn new(pdev: &platform::Device<Core>) -> impl PinInit<Self, Error> + '_ { 138 let debugfs = Dir::new(c_str!("sample_debugfs")); 139 let dev = pdev.as_ref(); 140 141 try_pin_init! { 142 Self { 143 _compatible <- debugfs.read_only_file( 144 c_str!("compatible"), 145 dev.fwnode() 146 .ok_or(ENOENT)? 147 .property_read::<CString>(c_str!("compatible")) 148 .required_by(dev)?, 149 ), 150 counter <- Self::build_counter(&debugfs), 151 inner <- Self::build_inner(&debugfs), 152 array_blob <- debugfs.read_write_binary_file( 153 c_str!("array_blob"), 154 new_mutex!([0x62, 0x6c, 0x6f, 0x62]), 155 ), 156 vector_blob <- debugfs.read_write_binary_file( 157 c_str!("vector_blob"), 158 new_mutex!(kernel::kvec!(0x42; SZ_4K)?), 159 ), 160 _debugfs: debugfs, 161 pdev: pdev.into(), 162 } 163 } 164 } 165 } 166