Skip to main content

starnix_core/fs/sysfs/
fs.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use 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 = &registry.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        // TODO(https://fxbug.dev/425942145): Correctly implement system filesystem in sysfs
307        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}