1use alloc::format;
6use alloc::string::ToString;
7use alloc::sync::Arc;
8
9use crate::fs::sysfs::device_registry;
10use crate::fs::sysfs::inode::{SysfsAttr, SysfsInode};
11use crate::vfs::{FileMode, FsError, Inode};
12
13pub fn build_platform_devices(root: &Arc<SysfsInode>) -> Result<(), FsError> {
15 let devices_inode = root.lookup("devices")?;
17 let devices_dir = devices_inode
18 .downcast_ref::<SysfsInode>()
19 .ok_or(FsError::InvalidArgument)?;
20
21 let platform_dir = SysfsInode::new_directory(FileMode::from_bits_truncate(0o040000 | 0o555));
23 devices_dir.add_child("platform", platform_dir.clone())?;
24
25 build_platform_block_devices(&platform_dir)?;
27
28 build_platform_net_devices(&platform_dir)?;
30
31 build_platform_tty_devices(&platform_dir)?;
33
34 build_platform_input_devices(&platform_dir)?;
36
37 build_platform_rtc_devices(&platform_dir)?;
39
40 Ok(())
41}
42
43fn build_platform_block_devices(platform_dir: &Arc<SysfsInode>) -> Result<(), FsError> {
45 for dev_info in device_registry::list_block_devices() {
46 let dev_dir = SysfsInode::new_directory(FileMode::from_bits_truncate(0o040000 | 0o555));
48
49 let dev_attr = SysfsAttr {
51 name: "dev".to_string(),
52 mode: FileMode::from_bits_truncate(0o444),
53 show: {
54 let maj = dev_info.major;
55 let min = dev_info.minor;
56 Arc::new(move || Ok(format!("{}:{}\n", maj, min)))
57 },
58 store: None,
59 };
60 dev_dir.add_child("dev", SysfsInode::new_attribute(dev_attr))?;
61
62 let uevent_attr = SysfsAttr {
64 name: "uevent".to_string(),
65 mode: FileMode::from_bits_truncate(0o644),
66 show: {
67 let maj = dev_info.major;
68 let min = dev_info.minor;
69 let name = dev_info.name.clone();
70 Arc::new(move || {
71 Ok(format!(
72 "MAJOR={}\nMINOR={}\nDEVNAME={}\nDEVTYPE=disk\n",
73 maj, min, name
74 ))
75 })
76 },
77 store: None,
78 };
79 dev_dir.add_child("uevent", SysfsInode::new_attribute(uevent_attr))?;
80
81 let size_attr = SysfsAttr {
83 name: "size".to_string(),
84 mode: FileMode::from_bits_truncate(0o444),
85 show: {
86 let dev = dev_info.device.clone();
87 Arc::new(move || {
88 let block_size = dev.block_size();
89 let total_blocks = dev.total_blocks();
90 let total_bytes = block_size * total_blocks;
91 let sectors = total_bytes / 512;
92 Ok(format!("{}\n", sectors))
93 })
94 },
95 store: None,
96 };
97 dev_dir.add_child("size", SysfsInode::new_attribute(size_attr))?;
98
99 let ro_attr = SysfsAttr {
101 name: "ro".to_string(),
102 mode: FileMode::from_bits_truncate(0o444),
103 show: Arc::new(|| Ok("0\n".to_string())),
104 store: None,
105 };
106 dev_dir.add_child("ro", SysfsInode::new_attribute(ro_attr))?;
107
108 let removable_attr = SysfsAttr {
110 name: "removable".to_string(),
111 mode: FileMode::from_bits_truncate(0o444),
112 show: Arc::new(|| Ok("0\n".to_string())),
113 store: None,
114 };
115 dev_dir.add_child("removable", SysfsInode::new_attribute(removable_attr))?;
116
117 let stat_attr = SysfsAttr {
119 name: "stat".to_string(),
120 mode: FileMode::from_bits_truncate(0o444),
121 show: Arc::new(|| {
122 Ok(" 0 0 0 0 0 0 0 0 0 0 0\n".to_string())
125 }),
126 store: None,
127 };
128 dev_dir.add_child("stat", SysfsInode::new_attribute(stat_attr))?;
129
130 build_queue_directory(&dev_dir, &dev_info.device)?;
132
133 platform_dir.add_child(&dev_info.name, dev_dir)?;
135 }
136
137 Ok(())
138}
139
140fn build_queue_directory(
142 dev_dir: &Arc<SysfsInode>,
143 device: &Arc<dyn crate::device::block::BlockDriver>,
144) -> Result<(), FsError> {
145 let queue_dir = SysfsInode::new_directory(FileMode::from_bits_truncate(0o040000 | 0o555));
146
147 let logical_block_size_attr = SysfsAttr {
149 name: "logical_block_size".to_string(),
150 mode: FileMode::from_bits_truncate(0o444),
151 show: {
152 let dev = device.clone();
153 Arc::new(move || Ok(format!("{}\n", dev.block_size())))
154 },
155 store: None,
156 };
157 queue_dir.add_child(
158 "logical_block_size",
159 SysfsInode::new_attribute(logical_block_size_attr),
160 )?;
161
162 let physical_block_size_attr = SysfsAttr {
164 name: "physical_block_size".to_string(),
165 mode: FileMode::from_bits_truncate(0o444),
166 show: {
167 let dev = device.clone();
168 Arc::new(move || Ok(format!("{}\n", dev.block_size())))
169 },
170 store: None,
171 };
172 queue_dir.add_child(
173 "physical_block_size",
174 SysfsInode::new_attribute(physical_block_size_attr),
175 )?;
176
177 let hw_sector_size_attr = SysfsAttr {
179 name: "hw_sector_size".to_string(),
180 mode: FileMode::from_bits_truncate(0o444),
181 show: Arc::new(|| Ok("512\n".to_string())),
182 store: None,
183 };
184 queue_dir.add_child(
185 "hw_sector_size",
186 SysfsInode::new_attribute(hw_sector_size_attr),
187 )?;
188
189 let max_sectors_kb_attr = SysfsAttr {
191 name: "max_sectors_kb".to_string(),
192 mode: FileMode::from_bits_truncate(0o644),
193 show: Arc::new(|| Ok("1280\n".to_string())), store: None,
195 };
196 queue_dir.add_child(
197 "max_sectors_kb",
198 SysfsInode::new_attribute(max_sectors_kb_attr),
199 )?;
200
201 let rotational_attr = SysfsAttr {
203 name: "rotational".to_string(),
204 mode: FileMode::from_bits_truncate(0o644),
205 show: Arc::new(|| Ok("1\n".to_string())), store: None,
207 };
208 queue_dir.add_child("rotational", SysfsInode::new_attribute(rotational_attr))?;
209
210 dev_dir.add_child("queue", queue_dir)?;
211 Ok(())
212}
213
214fn build_platform_net_devices(platform_dir: &Arc<SysfsInode>) -> Result<(), FsError> {
216 for dev_info in device_registry::list_net_devices() {
217 let dev_dir = SysfsInode::new_directory(FileMode::from_bits_truncate(0o040000 | 0o555));
219
220 let uevent_attr = SysfsAttr {
222 name: "uevent".to_string(),
223 mode: FileMode::from_bits_truncate(0o644),
224 show: {
225 let name = dev_info.name.clone();
226 let ifindex = dev_info.ifindex;
227 Arc::new(move || Ok(format!("INTERFACE={}\nIFINDEX={}\n", name, ifindex)))
228 },
229 store: None,
230 };
231 dev_dir.add_child("uevent", SysfsInode::new_attribute(uevent_attr))?;
232
233 let address_attr = SysfsAttr {
235 name: "address".to_string(),
236 mode: FileMode::from_bits_truncate(0o444),
237 show: {
238 let dev = dev_info.device.clone();
239 Arc::new(move || {
240 let mac = dev.mac_address();
241 Ok(format!(
242 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}\n",
243 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]
244 ))
245 })
246 },
247 store: None,
248 };
249 dev_dir.add_child("address", SysfsInode::new_attribute(address_attr))?;
250
251 let mtu_attr = SysfsAttr {
253 name: "mtu".to_string(),
254 mode: FileMode::from_bits_truncate(0o644),
255 show: {
256 let dev = dev_info.device.clone();
257 Arc::new(move || Ok(format!("{}\n", dev.mtu())))
258 },
259 store: None,
260 };
261 dev_dir.add_child("mtu", SysfsInode::new_attribute(mtu_attr))?;
262
263 let operstate_attr = SysfsAttr {
265 name: "operstate".to_string(),
266 mode: FileMode::from_bits_truncate(0o444),
267 show: Arc::new(|| Ok("up\n".to_string())),
268 store: None,
269 };
270 dev_dir.add_child("operstate", SysfsInode::new_attribute(operstate_attr))?;
271
272 let carrier_attr = SysfsAttr {
274 name: "carrier".to_string(),
275 mode: FileMode::from_bits_truncate(0o444),
276 show: Arc::new(|| Ok("1\n".to_string())), store: None,
278 };
279 dev_dir.add_child("carrier", SysfsInode::new_attribute(carrier_attr))?;
280
281 let ifindex_attr = SysfsAttr {
283 name: "ifindex".to_string(),
284 mode: FileMode::from_bits_truncate(0o444),
285 show: {
286 let ifindex = dev_info.ifindex;
287 Arc::new(move || Ok(format!("{}\n", ifindex)))
288 },
289 store: None,
290 };
291 dev_dir.add_child("ifindex", SysfsInode::new_attribute(ifindex_attr))?;
292
293 let type_attr = SysfsAttr {
295 name: "type".to_string(),
296 mode: FileMode::from_bits_truncate(0o444),
297 show: Arc::new(|| Ok("1\n".to_string())), store: None,
299 };
300 dev_dir.add_child("type", SysfsInode::new_attribute(type_attr))?;
301
302 platform_dir.add_child(&dev_info.name, dev_dir)?;
304 }
305
306 Ok(())
307}
308
309fn build_platform_tty_devices(platform_dir: &Arc<SysfsInode>) -> Result<(), FsError> {
311 for dev_info in device_registry::list_tty_devices() {
312 let dev_dir = SysfsInode::new_directory(FileMode::from_bits_truncate(0o040000 | 0o555));
314
315 let dev_attr = SysfsAttr {
317 name: "dev".to_string(),
318 mode: FileMode::from_bits_truncate(0o444),
319 show: {
320 let maj = dev_info.major;
321 let min = dev_info.minor;
322 Arc::new(move || Ok(format!("{}:{}\n", maj, min)))
323 },
324 store: None,
325 };
326 dev_dir.add_child("dev", SysfsInode::new_attribute(dev_attr))?;
327
328 let uevent_attr = SysfsAttr {
330 name: "uevent".to_string(),
331 mode: FileMode::from_bits_truncate(0o644),
332 show: {
333 let maj = dev_info.major;
334 let min = dev_info.minor;
335 let name = dev_info.name.clone();
336 Arc::new(move || Ok(format!("MAJOR={}\nMINOR={}\nDEVNAME={}\n", maj, min, name)))
337 },
338 store: None,
339 };
340 dev_dir.add_child("uevent", SysfsInode::new_attribute(uevent_attr))?;
341
342 platform_dir.add_child(&dev_info.name, dev_dir)?;
344 }
345
346 Ok(())
347}
348
349fn build_platform_input_devices(platform_dir: &Arc<SysfsInode>) -> Result<(), FsError> {
351 for dev_info in device_registry::list_input_devices() {
352 let dev_dir = SysfsInode::new_directory(FileMode::from_bits_truncate(0o040000 | 0o555));
354
355 let uevent_attr = SysfsAttr {
357 name: "uevent".to_string(),
358 mode: FileMode::from_bits_truncate(0o644),
359 show: {
360 let name = dev_info.name.clone();
361 Arc::new(move || Ok(format!("NAME={}\n", name)))
362 },
363 store: None,
364 };
365 dev_dir.add_child("uevent", SysfsInode::new_attribute(uevent_attr))?;
366
367 let name_attr = SysfsAttr {
369 name: "name".to_string(),
370 mode: FileMode::from_bits_truncate(0o444),
371 show: {
372 let name = dev_info.name.clone();
373 Arc::new(move || Ok(format!("{}\n", name)))
374 },
375 store: None,
376 };
377 dev_dir.add_child("name", SysfsInode::new_attribute(name_attr))?;
378
379 platform_dir.add_child(&dev_info.name, dev_dir)?;
381 }
382
383 Ok(())
384}
385
386fn build_platform_rtc_devices(platform_dir: &Arc<SysfsInode>) -> Result<(), FsError> {
388 for dev_info in device_registry::list_rtc_devices() {
389 let dev_dir = SysfsInode::new_directory(FileMode::from_bits_truncate(0o040000 | 0o555));
391
392 let uevent_attr = SysfsAttr {
394 name: "uevent".to_string(),
395 mode: FileMode::from_bits_truncate(0o644),
396 show: {
397 let name = dev_info.name.clone();
398 Arc::new(move || Ok(format!("RTC_NAME={}\n", name)))
399 },
400 store: None,
401 };
402 dev_dir.add_child("uevent", SysfsInode::new_attribute(uevent_attr))?;
403
404 let name_attr = SysfsAttr {
406 name: "name".to_string(),
407 mode: FileMode::from_bits_truncate(0o444),
408 show: {
409 let name = dev_info.name.clone();
410 Arc::new(move || Ok(format!("{}\n", name)))
411 },
412 store: None,
413 };
414 dev_dir.add_child("name", SysfsInode::new_attribute(name_attr))?;
415
416 let date_attr = SysfsAttr {
418 name: "date".to_string(),
419 mode: FileMode::from_bits_truncate(0o444),
420 show: {
421 let rtc = dev_info.device.clone();
422 Arc::new(move || {
423 let dt = rtc.read_datetime();
424 Ok(format!("{:04}-{:02}-{:02}\n", dt.year, dt.month, dt.day))
425 })
426 },
427 store: None,
428 };
429 dev_dir.add_child("date", SysfsInode::new_attribute(date_attr))?;
430
431 let time_attr = SysfsAttr {
433 name: "time".to_string(),
434 mode: FileMode::from_bits_truncate(0o444),
435 show: {
436 let rtc = dev_info.device.clone();
437 Arc::new(move || {
438 let dt = rtc.read_datetime();
439 Ok(format!(
440 "{:02}:{:02}:{:02}\n",
441 dt.hour, dt.minute, dt.second
442 ))
443 })
444 },
445 store: None,
446 };
447 dev_dir.add_child("time", SysfsInode::new_attribute(time_attr))?;
448
449 platform_dir.add_child(&dev_info.name, dev_dir)?;
451 }
452
453 Ok(())
454}