1use crate::fs::sysfs::{build_cpu_class_directory, build_kernel_directory, build_power_directory};
6use crate::task::{CurrentTask, Kernel};
7use crate::vfs::pseudo::simple_directory::SimpleDirectoryMutator;
8use crate::vfs::pseudo::simple_file::BytesFile;
9use crate::vfs::pseudo::stub_empty_file::StubEmptyFile;
10use crate::vfs::{
11 CacheMode, FileSystem, FileSystemHandle, FileSystemOps, FileSystemOptions, FsStr,
12};
13use ebpf_api::BPF_PROG_TYPE_FUSE;
14use starnix_logging::bug_ref;
15use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked, Unlocked};
16use starnix_types::vfs::default_statfs;
17use starnix_uapi::errors::Errno;
18use starnix_uapi::file_mode::mode;
19use starnix_uapi::{SYSFS_MAGIC, statfs};
20
21struct SysFs;
22impl FileSystemOps for SysFs {
23 fn statfs(
24 &self,
25 _locked: &mut Locked<FileOpsCore>,
26 _fs: &FileSystem,
27 _current_task: &CurrentTask,
28 ) -> Result<statfs, Errno> {
29 Ok(default_statfs(SYSFS_MAGIC))
30 }
31 fn name(&self) -> &'static FsStr {
32 "sysfs".into()
33 }
34}
35
36impl SysFs {
37 fn new_fs<L>(
38 locked: &mut Locked<L>,
39 kernel: &Kernel,
40 options: FileSystemOptions,
41 ) -> FileSystemHandle
42 where
43 L: LockEqualOrBefore<FileOpsCore>,
44 {
45 let fs = FileSystem::new(
46 locked,
47 kernel,
48 CacheMode::Cached(kernel.fs_cache_config()),
49 SysFs,
50 options,
51 )
52 .expect("sysfs constructed with valid options");
53
54 fn empty_dir(_: &SimpleDirectoryMutator) {}
55
56 let registry = &kernel.device_registry;
57 let root = ®istry.objects.root;
58 fs.create_root(fs.allocate_ino(), root.clone());
59 let dir = SimpleDirectoryMutator::new(fs.clone(), root.clone());
60
61 let dir_mode = 0o755;
62 dir.subdir("fs", dir_mode, |dir| {
63 dir.subdir("selinux", dir_mode, empty_dir);
64 dir.subdir("bpf", dir_mode, empty_dir);
65 dir.subdir("cgroup", dir_mode, empty_dir);
66 dir.subdir("fuse", dir_mode, |dir| {
67 dir.subdir("connections", dir_mode, empty_dir);
68 dir.subdir("features", dir_mode, |dir| {
69 dir.entry(
70 "fuse_bpf",
71 BytesFile::new_node(b"supported\n".to_vec()),
72 mode!(IFREG, 0o444),
73 );
74 });
75 dir.entry(
76 "bpf_prog_type_fuse",
77 BytesFile::new_node(format!("{}\n", BPF_PROG_TYPE_FUSE).into_bytes()),
78 mode!(IFREG, 0o444),
79 );
80 });
81 dir.subdir("pstore", dir_mode, empty_dir);
82 });
83
84 dir.subdir("block", dir_mode, |dir| {
85 dir.subdir("zram0", dir_mode, |dir| {
86 dir.entry(
87 "backing_dev",
88 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
89 mode!(IFREG, 0o444),
90 );
91 dir.entry(
92 "recomp_algorithm",
93 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
94 mode!(IFREG, 0o444),
95 );
96 dir.entry(
97 "recompress",
98 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
99 mode!(IFREG, 0o444),
100 );
101 });
102 });
103
104 dir.subdir("bus", dir_mode, |dir| {
105 dir.subdir("mmc", dir_mode, |dir| {
106 dir.subdir("devices", dir_mode, |dir| {
107 dir.subdir("mmc0:0001", dir_mode, |dir| {
108 dir.subdir("block", dir_mode, |dir| {
109 dir.subdir("mmcblk0", dir_mode, |dir| {
110 dir.entry(
111 "size",
112 StubEmptyFile::new_node(bug_ref!(
113 "https://fxbug.dev/452096300"
114 )),
115 mode!(IFREG, 0o444),
116 );
117 });
118 });
119 });
120 });
121 });
122 dir.subdir("platform", dir_mode, |dir| {
123 dir.subdir("drivers", dir_mode, |dir| {
124 dir.entry(
125 "trusty",
126 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
127 mode!(IFREG, 0o444),
128 );
129 });
130 });
131 });
132
133 dir.subdir("class", dir_mode, |dir| {
134 dir.subdir("backlight", dir_mode, |dir| {
135 dir.subdir("panel0-backlight", dir_mode, |dir| {
136 dir.entry(
137 "brightness",
138 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
139 mode!(IFREG, 0o444),
140 );
141 });
142 });
143 dir.subdir("bdi", dir_mode, |dir| {
144 dir.subdir("0:80", dir_mode, |dir| {
145 dir.entry(
146 "max_ratio",
147 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
148 mode!(IFREG, 0o444),
149 );
150 dir.entry(
151 "read_ahead_kb",
152 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
153 mode!(IFREG, 0o444),
154 );
155 });
156 });
157 dir.subdir("mmc_host", dir_mode, |dir| {
158 dir.subdir("mmc0", dir_mode, |dir| {
159 dir.subdir("mmc0:0001", dir_mode, |dir| {
160 dir.entry(
161 "fwrev",
162 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
163 mode!(IFREG, 0o444),
164 );
165 dir.entry(
166 "hwrev",
167 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
168 mode!(IFREG, 0o444),
169 );
170 dir.entry(
171 "life_time",
172 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
173 mode!(IFREG, 0o444),
174 );
175 dir.entry(
176 "manfid",
177 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
178 mode!(IFREG, 0o444),
179 );
180 dir.entry(
181 "pre_eol_info",
182 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
183 mode!(IFREG, 0o444),
184 );
185 dir.entry(
186 "serial",
187 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
188 mode!(IFREG, 0o444),
189 );
190 });
191 });
192 });
193 dir.subdir("net", dir_mode, |dir| {
194 dir.subdir("eth0", dir_mode, |dir| {
195 dir.entry(
196 "address",
197 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
198 mode!(IFREG, 0o444),
199 );
200 });
201 dir.subdir("sit0", dir_mode, |dir| {
202 dir.entry(
203 "address",
204 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
205 mode!(IFREG, 0o444),
206 );
207 });
208 dir.subdir("wlan0", dir_mode, |dir| {
209 dir.entry(
210 "address",
211 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
212 mode!(IFREG, 0o444),
213 );
214 });
215 });
216 dir.subdir("powercap", dir_mode, |_dir| {});
217 dir.subdir("udc", dir_mode, |_dir| {});
218 dir.subdir("android_usb", dir_mode, empty_dir);
222 });
223 dir.subdir("dev", dir_mode, |dir| {
224 dir.subdir("char", dir_mode, empty_dir);
225 dir.subdir("block", dir_mode, empty_dir);
226 });
227 dir.subdir("firmware", dir_mode, |dir| {
228 dir.subdir("devicetree", dir_mode, |dir| {
229 dir.subdir("base", dir_mode, |dir| {
230 dir.subdir("chosen", dir_mode, |dir| {
231 dir.subdir("plat", dir_mode, |dir| {
232 if let Some(device_tree) = &kernel.device_tree {
233 if let Some(product_bytes) =
234 device_tree.root_node.find("plat").and_then(|n| {
235 n.get_property("product").map(|p| p.value.clone())
236 })
237 {
238 let product_bytes = if product_bytes.len() >= 4 {
239 product_bytes.to_vec()
240 } else {
241 let mut padded_bytes = vec![0; 4];
242 let start = 4 - product_bytes.len();
243 padded_bytes[start..].copy_from_slice(&product_bytes);
244 padded_bytes
245 };
246 dir.entry(
247 "product",
248 BytesFile::new_node(product_bytes),
249 mode!(IFREG, 0o444),
250 );
251 }
252 }
253 });
254 dir.subdir("config", dir_mode, |dir| {
255 dir.entry(
256 "pcbcfg",
257 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
258 mode!(IFREG, 0o444),
259 );
260 });
261 });
262 dir.subdir("firmware", dir_mode, |dir| {
263 dir.subdir("android", 0o755, |dir| {
264 dir.entry(
265 "compatible",
266 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
267 mode!(IFREG, 0o444),
268 );
269 dir.subdir("vbmeta", 0o755, |dir| {
270 dir.entry(
271 "parts",
272 StubEmptyFile::new_node(bug_ref!(
273 "https://fxbug.dev/452096300"
274 )),
275 mode!(IFREG, 0o444),
276 );
277 });
278 });
279 });
280 dir.subdir("mcu", dir_mode, |dir| {
281 dir.entry(
282 "board_type",
283 BytesFile::new_node(b"starnix".to_vec()),
284 mode!(IFREG, 0o444),
285 );
286 });
287 });
288 });
289 });
290
291 dir.subdir("kernel", dir_mode, |dir| {
292 build_kernel_directory(kernel, dir);
293 });
294
295 dir.subdir("power", 0o755, |dir| {
296 build_power_directory(kernel, dir);
297 });
298
299 dir.subdir("leds", dir_mode, |dir| {
300 dir.entry(
301 "leds",
302 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
303 mode!(IFREG, 0o444),
304 );
305 });
306
307 dir.subdir("module", dir_mode, |dir| {
308 dir.subdir("dm_bufio", dir_mode, |dir| {
309 dir.subdir("parameters", dir_mode, |dir| {
310 dir.entry(
311 "max_age_seconds",
312 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
313 mode!(IFREG, 0o644),
314 );
315 });
316 });
317 dir.subdir("dm_verity", dir_mode, |dir| {
318 dir.subdir("parameters", dir_mode, |dir| {
319 dir.entry(
320 "prefetch_cluster",
321 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/322893670")),
322 mode!(IFREG, 0o644),
323 );
324 });
325 });
326 });
327
328 dir.subdir("devices", dir_mode, |dir| {
330 dir.subdir("system", dir_mode, |dir| {
331 dir.subdir("cpu", dir_mode, build_cpu_class_directory);
332 });
333 dir.subdir("leds", dir_mode, |_dir| {});
334 dir.subdir("platform", dir_mode, |dir| {
335 dir.subdir("soc", dir_mode, |dir| {
336 dir.subdir("1c40000.qcom,spmi", dir_mode, |dir| {
337 dir.subdir("spmi-0", dir_mode, |dir| {
338 dir.subdir("0-00", dir_mode, |dir| {
339 dir.subdir(
340 "1c40000.qcom,spmi:qcom,pm5100@0:qpnp,qbg@4f00",
341 dir_mode,
342 |dir| {
343 dir.subdir("iio:device3", dir_mode, |dir| {
344 dir.entry(
345 "in_resistance_resistance_id_input",
346 StubEmptyFile::new_node(bug_ref!(
347 "https://fxbug.dev/452096300"
348 )),
349 mode!(IFREG, 0o444),
350 );
351 });
352 },
353 );
354 });
355 });
356 });
357 dir.subdir("5e00000.qcom,mdss_mdp", dir_mode, |dir| {
358 dir.subdir("drm", dir_mode, |dir| {
359 dir.subdir("card0", dir_mode, |dir| {
360 dir.subdir("sde-conn-0-DSI-1", dir_mode, |dir| {
361 dir.entry(
362 "display_power_state",
363 StubEmptyFile::new_node(bug_ref!(
364 "https://fxbug.dev/452096300"
365 )),
366 mode!(IFREG, 0o644),
367 );
368 dir.entry(
369 "panel_power_state",
370 StubEmptyFile::new_node(bug_ref!(
371 "https://fxbug.dev/452096300"
372 )),
373 mode!(IFREG, 0o644),
374 );
375 });
376 });
377 });
378 });
379 });
380 });
381 dir.subdir("soc0", dir_mode, |dir| {
382 dir.entry(
383 "revision",
384 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
385 mode!(IFREG, 0o444),
386 );
387 dir.entry(
388 "serial_number",
389 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
390 mode!(IFREG, 0o444),
391 );
392 });
393 dir.subdir("virtual", dir_mode, |dir| {
394 dir.subdir("leds", dir_mode, |_dir| {});
395 dir.subdir("power_supply", dir_mode, |dir| {
396 dir.subdir("bms", dir_mode, |dir| {
397 dir.entry(
398 "capacity",
399 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
400 mode!(IFREG, 0o444),
401 );
402 dir.entry(
403 "capacity_level",
404 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
405 mode!(IFREG, 0o444),
406 );
407 dir.entry(
408 "status",
409 StubEmptyFile::new_node(bug_ref!("https://fxbug.dev/452096300")),
410 mode!(IFREG, 0o444),
411 );
412 });
413 });
414 });
415 });
416
417 fs
418 }
419}
420
421struct SysFsHandle(FileSystemHandle);
422
423pub fn sys_fs(
424 locked: &mut Locked<Unlocked>,
425 current_task: &CurrentTask,
426 _options: FileSystemOptions,
427) -> Result<FileSystemHandle, Errno> {
428 Ok(get_sysfs(locked, current_task.kernel()))
429}
430
431pub fn get_sysfs<L>(locked: &mut Locked<L>, kernel: &Kernel) -> FileSystemHandle
432where
433 L: LockEqualOrBefore<FileOpsCore>,
434{
435 kernel
436 .expando
437 .get_or_init(|| SysFsHandle(SysFs::new_fs(locked, kernel, FileSystemOptions::default())))
438 .0
439 .clone()
440}