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