veridian_kernel/sysfs/
mod.rs1#![allow(dead_code)]
12
13extern crate alloc;
14
15use alloc::{string::String, vec::Vec};
16
17use spin::Mutex;
18
19use crate::error::{KernelError, KernelResult};
20
21pub mod power;
22
23const MAX_SYSFS_NODES: usize = 64;
29
30type SysfsReadFn = fn() -> String;
33
34type SysfsWriteFn = fn(&str) -> KernelResult<()>;
38
39#[derive(Clone)]
41pub struct SysfsNode {
42 pub path: &'static str,
44 pub description: &'static str,
46 pub read_fn: Option<SysfsReadFn>,
48 pub write_fn: Option<SysfsWriteFn>,
50}
51
52impl SysfsNode {
53 pub const fn read_only(
55 path: &'static str,
56 description: &'static str,
57 read_fn: SysfsReadFn,
58 ) -> Self {
59 Self {
60 path,
61 description,
62 read_fn: Some(read_fn),
63 write_fn: None,
64 }
65 }
66
67 pub const fn read_write(
69 path: &'static str,
70 description: &'static str,
71 read_fn: SysfsReadFn,
72 write_fn: SysfsWriteFn,
73 ) -> Self {
74 Self {
75 path,
76 description,
77 read_fn: Some(read_fn),
78 write_fn: Some(write_fn),
79 }
80 }
81
82 pub fn is_writable(&self) -> bool {
84 self.write_fn.is_some()
85 }
86
87 pub fn is_readable(&self) -> bool {
89 self.read_fn.is_some()
90 }
91}
92
93pub trait SysfsEntry {
95 fn path(&self) -> &str;
97
98 fn read(&self) -> KernelResult<String>;
100
101 fn write(&self, value: &str) -> KernelResult<()>;
103}
104
105struct SysfsRegistry {
110 nodes: Vec<SysfsNode>,
111}
112
113impl SysfsRegistry {
114 const fn new() -> Self {
115 Self { nodes: Vec::new() }
116 }
117}
118
119static SYSFS_REGISTRY: Mutex<SysfsRegistry> = Mutex::new(SysfsRegistry::new());
120
121pub fn register_node(node: SysfsNode) -> KernelResult<()> {
127 let mut registry = SYSFS_REGISTRY.lock();
128
129 if registry.nodes.len() >= MAX_SYSFS_NODES {
130 return Err(KernelError::ResourceExhausted {
131 resource: "sysfs nodes",
132 });
133 }
134
135 for existing in ®istry.nodes {
137 if existing.path == node.path {
138 return Err(KernelError::AlreadyExists {
139 resource: "sysfs node",
140 id: 0,
141 });
142 }
143 }
144
145 println!("[SYSFS] Registered: {}", node.path);
146 registry.nodes.push(node);
147 Ok(())
148}
149
150pub fn lookup(path: &str) -> Option<SysfsNode> {
152 let registry = SYSFS_REGISTRY.lock();
153 for node in ®istry.nodes {
154 if node.path == path {
155 return Some(node.clone());
156 }
157 }
158 None
159}
160
161pub fn sysfs_read(path: &str) -> KernelResult<String> {
163 let node = lookup(path).ok_or(KernelError::NotFound {
164 resource: "sysfs",
165 id: 0,
166 })?;
167
168 let read_fn = node.read_fn.ok_or(KernelError::PermissionDenied {
169 operation: "sysfs read (write-only node)",
170 })?;
171
172 Ok(read_fn())
173}
174
175pub fn sysfs_write(path: &str, value: &str) -> KernelResult<()> {
177 let node = lookup(path).ok_or(KernelError::NotFound {
178 resource: "sysfs",
179 id: 0,
180 })?;
181
182 let write_fn = node.write_fn.ok_or(KernelError::PermissionDenied {
183 operation: "sysfs write (read-only node)",
184 })?;
185
186 write_fn(value)
187}
188
189pub fn list_nodes() -> Vec<&'static str> {
191 let registry = SYSFS_REGISTRY.lock();
192 registry.nodes.iter().map(|n| n.path).collect()
193}
194
195pub fn sysfs_init() -> KernelResult<()> {
201 println!("[SYSFS] Initializing virtual filesystem...");
202
203 power::sysfs_power_init()?;
205
206 let count = {
207 let registry = SYSFS_REGISTRY.lock();
208 registry.nodes.len()
209 };
210
211 println!("[SYSFS] Initialized: {} nodes registered", count);
212 Ok(())
213}
214
215#[cfg(test)]
220mod tests {
221 use super::*;
222
223 fn test_read() -> String {
224 String::from("test_value")
225 }
226
227 fn test_write(value: &str) -> KernelResult<()> {
228 if value.is_empty() {
229 return Err(KernelError::InvalidArgument {
230 name: "value",
231 value: "empty",
232 });
233 }
234 Ok(())
235 }
236
237 #[test]
238 fn test_sysfs_node_read_only() {
239 let node = SysfsNode::read_only("/test/ro", "test read-only", test_read);
240 assert!(node.is_readable());
241 assert!(!node.is_writable());
242 assert_eq!(node.path, "/test/ro");
243 }
244
245 #[test]
246 fn test_sysfs_node_read_write() {
247 let node = SysfsNode::read_write("/test/rw", "test read-write", test_read, test_write);
248 assert!(node.is_readable());
249 assert!(node.is_writable());
250 }
251
252 #[test]
253 fn test_sysfs_node_read_fn() {
254 let node = SysfsNode::read_only("/test/read", "test", test_read);
255 let val = (node.read_fn.unwrap())();
256 assert_eq!(val, "test_value");
257 }
258
259 #[test]
260 fn test_sysfs_node_write_fn() {
261 let node = SysfsNode::read_write("/test/write", "test", test_read, test_write);
262 let result = (node.write_fn.unwrap())("hello");
263 assert!(result.is_ok());
264 }
265
266 #[test]
267 fn test_sysfs_node_write_empty_error() {
268 let node = SysfsNode::read_write("/test/write_err", "test", test_read, test_write);
269 let result = (node.write_fn.unwrap())("");
270 assert!(result.is_err());
271 }
272}