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 kernel::{ 36 acpi, 37 c_str, 38 debugfs::{ 39 Dir, 40 File, // 41 }, 42 device::Core, 43 new_mutex, 44 of, 45 platform, 46 prelude::*, 47 sizes::*, 48 str::CString, 49 sync::{ 50 aref::ARef, 51 atomic::{ 52 Atomic, 53 Relaxed, // 54 }, 55 Mutex, 56 }, // 57 }; 58 59 kernel::module_platform_driver! { 60 type: RustDebugFs, 61 name: "rust_debugfs", 62 authors: ["Matthew Maurer"], 63 description: "Rust DebugFS usage sample", 64 license: "GPL", 65 } 66 67 #[pin_data] 68 struct RustDebugFs { 69 pdev: ARef<platform::Device>, 70 // As we only hold these for drop effect (to remove the directory/files) we have a leading 71 // underscore to indicate to the compiler that we don't expect to use this field directly. 72 _debugfs: Dir, 73 #[pin] 74 _compatible: File<CString>, 75 #[pin] 76 counter: File<Atomic<usize>>, 77 #[pin] 78 inner: File<Mutex<Inner>>, 79 #[pin] 80 array_blob: File<Mutex<[u8; 4]>>, 81 #[pin] 82 vector_blob: File<Mutex<KVec<u8>>>, 83 } 84 85 #[derive(Debug)] 86 struct Inner { 87 x: u32, 88 y: u32, 89 } 90 91 impl FromStr for Inner { 92 type Err = Error; 93 fn from_str(s: &str) -> Result<Self> { 94 let mut parts = s.split_whitespace(); 95 let x = parts 96 .next() 97 .ok_or(EINVAL)? 98 .parse::<u32>() 99 .map_err(|_| EINVAL)?; 100 let y = parts 101 .next() 102 .ok_or(EINVAL)? 103 .parse::<u32>() 104 .map_err(|_| EINVAL)?; 105 if parts.next().is_some() { 106 return Err(EINVAL); 107 } 108 Ok(Inner { x, y }) 109 } 110 } 111 112 kernel::acpi_device_table!( 113 ACPI_TABLE, 114 MODULE_ACPI_TABLE, 115 <RustDebugFs as platform::Driver>::IdInfo, 116 [(acpi::DeviceId::new(c_str!("LNUXBEEF")), ())] 117 ); 118 119 impl platform::Driver for RustDebugFs { 120 type IdInfo = (); 121 const OF_ID_TABLE: Option<of::IdTable<Self::IdInfo>> = None; 122 const ACPI_ID_TABLE: Option<acpi::IdTable<Self::IdInfo>> = Some(&ACPI_TABLE); 123 124 fn probe( 125 pdev: &platform::Device<Core>, 126 _info: Option<&Self::IdInfo>, 127 ) -> impl PinInit<Self, Error> { 128 RustDebugFs::new(pdev).pin_chain(|this| { 129 this.counter.store(91, Relaxed); 130 { 131 let mut guard = this.inner.lock(); 132 guard.x = guard.y; 133 guard.y = 42; 134 } 135 136 Ok(()) 137 }) 138 } 139 } 140 141 impl RustDebugFs { 142 fn build_counter(dir: &Dir) -> impl PinInit<File<Atomic<usize>>> + '_ { 143 dir.read_write_file(c_str!("counter"), Atomic::<usize>::new(0)) 144 } 145 146 fn build_inner(dir: &Dir) -> impl PinInit<File<Mutex<Inner>>> + '_ { 147 dir.read_write_file(c_str!("pair"), new_mutex!(Inner { x: 3, y: 10 })) 148 } 149 150 fn new(pdev: &platform::Device<Core>) -> impl PinInit<Self, Error> + '_ { 151 let debugfs = Dir::new(c_str!("sample_debugfs")); 152 let dev = pdev.as_ref(); 153 154 try_pin_init! { 155 Self { 156 _compatible <- debugfs.read_only_file( 157 c_str!("compatible"), 158 dev.fwnode() 159 .ok_or(ENOENT)? 160 .property_read::<CString>(c_str!("compatible")) 161 .required_by(dev)?, 162 ), 163 counter <- Self::build_counter(&debugfs), 164 inner <- Self::build_inner(&debugfs), 165 array_blob <- debugfs.read_write_binary_file( 166 c_str!("array_blob"), 167 new_mutex!([0x62, 0x6c, 0x6f, 0x62]), 168 ), 169 vector_blob <- debugfs.read_write_binary_file( 170 c_str!("vector_blob"), 171 new_mutex!(kernel::kvec!(0x42; SZ_4K)?), 172 ), 173 _debugfs: debugfs, 174 pdev: pdev.into(), 175 } 176 } 177 } 178 } 179