1pub mod ext4;
78pub mod proc;
79pub mod simple_fs;
80pub mod smfs;
81pub mod sysfs;
82pub mod tmpfs;
83
84use alloc::string::String;
85use alloc::sync::Arc;
86
87use crate::device::BLK_DRIVERS;
88use crate::device::RamDisk;
89use crate::fs::ext4::Ext4FileSystem;
90use crate::fs::simple_fs::SimpleFs;
91use crate::fs::tmpfs::TmpFs;
92use crate::pr_info;
94use crate::vfs::dev::makedev;
95use crate::vfs::devno::{blkdev_major, chrdev_major};
96use crate::vfs::{FileMode, FsError, MOUNT_TABLE, MountFlags, vfs_lookup};
97
98static SIMPLE_FS_IMAGE: &[u8] = include_bytes!(env!("SIMPLE_FS_IMAGE"));
112
113pub fn init_simple_fs() -> Result<(), crate::vfs::FsError> {
115 pr_info!(
117 "[SimpleFS] Creating RamDisk ({} bytes)",
118 SIMPLE_FS_IMAGE.len()
119 );
120 let ramdisk = RamDisk::from_bytes(SIMPLE_FS_IMAGE.to_vec(), 512, 0);
121
122 pr_info!("[SimpleFS] Mounting SimpleFS on RamDisk");
124 let simplefs = SimpleFs::from_ramdisk(ramdisk)?;
125
126 MOUNT_TABLE.mount(
128 Arc::new(simplefs),
129 "/",
130 MountFlags::empty(),
131 Some(String::from("ramdisk0")),
132 )?;
133
134 pr_info!("[SimpleFS] Root filesystem mounted at /");
135
136 if let Ok(root_dentry) = crate::vfs::get_root_dentry() {
138 pr_info!("[SimpleFS] Root directory contents:");
139 let inode = root_dentry.inode.clone();
140 if let Ok(entries) = inode.readdir() {
141 for entry in entries {
142 pr_info!(" - {} (type: {:?})", entry.name, entry.inode_type);
143 }
144 }
145 }
146
147 Ok(())
148}
149
150pub fn init_ext4_from_block_device() -> Result<(), crate::vfs::FsError> {
154 use crate::config::{EXT4_BLOCK_SIZE, FS_IMAGE_SIZE, VIRTIO_BLK_SECTOR_SIZE};
155 use crate::vfs::FsError;
156
157 pr_info!("[Ext4] Initializing Ext4 filesystem from block device");
158
159 let blk_drivers = BLK_DRIVERS.read();
161 if blk_drivers.is_empty() {
162 pr_info!("[Ext4] No block device found");
163 return Err(FsError::NoDevice);
164 }
165
166 let block_driver = blk_drivers[0].clone();
167 drop(blk_drivers); pr_info!("[Ext4] Using block device: {}", block_driver.get_id());
170
171 let ext4_block_size = EXT4_BLOCK_SIZE;
174 let total_blocks = FS_IMAGE_SIZE / ext4_block_size;
177
178 pr_info!(
179 "[Ext4] Ext4 block size: {}, Total blocks: {}, Image size: {} MB",
180 ext4_block_size,
181 total_blocks,
182 FS_IMAGE_SIZE / 1024 / 1024
183 );
184
185 let ext4_fs = Ext4FileSystem::open(block_driver, ext4_block_size, total_blocks, 0)?;
188
189 pr_info!("[Ext4] Mounting Ext4 as root filesystem");
191 MOUNT_TABLE.mount(
192 ext4_fs,
193 "/",
194 MountFlags::empty(),
195 Some(String::from("virtio-blk0")),
196 )?;
197
198 pr_info!("[Ext4] Root filesystem mounted at /");
199
200 if let Ok(root_dentry) = crate::vfs::get_root_dentry() {
202 pr_info!("[Ext4] Root directory contents:");
203 let inode = root_dentry.inode.clone();
204 if let Ok(entries) = inode.readdir() {
205 for entry in entries {
206 pr_info!(" - {} (type: {:?})", entry.name, entry.inode_type);
207 }
208 } else {
209 pr_info!("[Ext4] Failed to read root directory");
210 }
211 }
212
213 Ok(())
214}
215
216pub fn mount_tmpfs(mount_point: &str, max_size_mb: usize) -> Result<(), crate::vfs::FsError> {
223 use crate::vfs::FsError;
224 use alloc::string::ToString;
225
226 pr_info!(
227 "[Tmpfs] Creating tmpfs filesystem (max_size: {} MB)",
228 if max_size_mb == 0 {
229 "unlimited".to_string()
230 } else {
231 max_size_mb.to_string()
232 }
233 );
234
235 let tmpfs = TmpFs::new(max_size_mb);
237
238 MOUNT_TABLE.mount(
240 tmpfs,
241 mount_point,
242 MountFlags::empty(),
243 Some(String::from("tmpfs")),
244 )?;
245
246 pr_info!("[Tmpfs] Tmpfs mounted at {}", mount_point);
247
248 Ok(())
249}
250
251pub fn init_dev() -> Result<(), FsError> {
252 if let Err(e) = vfs_lookup("/dev") {
253 return Err(e);
254 }
255
256 create_devices()?;
257
258 Ok(())
259}
260
261fn create_devices() -> Result<(), FsError> {
262 let dev_dentry = vfs_lookup("/dev")?;
264
265 let dev_inode = &dev_dentry.inode;
266
267 let char_mode = FileMode::S_IFCHR | FileMode::from_bits_truncate(0o666);
269
270 dev_inode.mknod("null", char_mode, makedev(chrdev_major::MEM, 3))?;
272
273 dev_inode.mknod("zero", char_mode, makedev(chrdev_major::MEM, 5))?;
275
276 dev_inode.mknod("random", char_mode, makedev(chrdev_major::MEM, 8))?;
278
279 dev_inode.mknod("urandom", char_mode, makedev(chrdev_major::MEM, 9))?;
281
282 let console_mode = FileMode::S_IFCHR | FileMode::from_bits_truncate(0o600);
284 dev_inode.mknod("console", console_mode, makedev(chrdev_major::CONSOLE, 1))?;
285
286 dev_inode.mknod("ttyS0", char_mode, makedev(chrdev_major::TTY, 64))?;
288
289 let dir_mode = FileMode::S_IFDIR | FileMode::from_bits_truncate(0o755);
291 dev_inode.mkdir("misc", dir_mode)?;
292
293 let misc_dentry = vfs_lookup("/dev/misc")?;
295 misc_dentry
296 .inode
297 .mknod("rtc", char_mode, makedev(chrdev_major::MISC, 135))?;
298
299 let block_mode = FileMode::S_IFBLK | FileMode::from_bits_truncate(0o660);
301
302 dev_inode.mknod("vda", block_mode, makedev(blkdev_major::VIRTIO_BLK, 0))?;
304
305 Ok(())
306}
307
308pub fn init_procfs() -> Result<(), crate::vfs::FsError> {
310 use crate::fs::proc::ProcFS;
311 use crate::vfs::MountFlags;
312 use alloc::string::ToString;
313
314 pr_info!("[ProcFS] Initializing procfs");
315
316 let procfs = ProcFS::new();
318
319 procfs.init_tree()?;
321
322 MOUNT_TABLE.mount(
324 procfs,
325 "/proc",
326 MountFlags::empty(),
327 Some(String::from("proc")),
328 )?;
329
330 pr_info!("[ProcFS] Procfs mounted at /proc");
331
332 Ok(())
333}
334
335pub fn init_sysfs() -> Result<(), crate::vfs::FsError> {
337 use crate::fs::sysfs::SysFS;
338 use crate::vfs::MountFlags;
339 use alloc::string::ToString;
340
341 pr_info!("[SysFS] Initializing sysfs");
342
343 let sysfs = SysFS::new();
345
346 sysfs.init_tree()?;
348
349 MOUNT_TABLE.mount(
351 sysfs,
352 "/sys",
353 MountFlags::empty(),
354 Some(String::from("sysfs")),
355 )?;
356
357 pr_info!("[SysFS] Sysfs mounted at /sys");
358
359 Ok(())
360}
361
362#[cfg(test)]
363mod tests;