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