kernel/fs/vfs_v2/drivers/
initramfs.rs

1//! Initramfs mounting functionality (VFS v2)
2//!
3//! This module provides functionality to mount the initial ramdisk (initramfs)
4//! as the root filesystem during early kernel boot. The initramfs is loaded by
5//! the bootloader and its location is passed to the kernel via the device tree.
6//!
7//! The module uses the existing CPIO filesystem driver to mount the initramfs
8//! at the root ("/") mount point.
9
10use crate::device::fdt::FdtManager;
11use crate::early_println;
12use crate::fs::FileSystemError;
13use crate::fs::VfsManager;
14use crate::vm::vmem::MemoryArea;
15use alloc::format;
16use alloc::string::{String, ToString};
17use alloc::sync::Arc;
18use core::ptr;
19
20/// Relocate initramfs to heap memory
21pub fn relocate_initramfs(usable_area: &mut MemoryArea) -> Result<MemoryArea, &'static str> {
22    let fdt_manager = FdtManager::get_manager();
23    let original_area = fdt_manager
24        .get_initramfs()
25        .ok_or("Failed to get initramfs from device tree")?;
26    let size = original_area.size();
27
28    // Validate parameters before proceeding
29    if size == 0 || size > 0x10000000 {
30        return Err("Invalid initramfs size");
31    }
32    if original_area.start == 0 {
33        return Err("Invalid initramfs source address");
34    }
35
36    // Ensure proper 8-byte alignment for destination
37    let raw_ptr = usable_area.start as *mut u8;
38    let aligned_ptr = ((raw_ptr as usize + 7) & !7) as *mut u8;
39    let aligned_addr = aligned_ptr as usize;
40
41    // Validate destination memory bounds
42    if aligned_addr + size > usable_area.end {
43        return Err("Insufficient memory for initramfs");
44    }
45
46    // Create the new memory area BEFORE the copy operation
47    let new_area = MemoryArea::new(aligned_addr, aligned_addr + size - 1);
48
49    // Perform the copy with explicit memory barriers
50    core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
51
52    // Use a safer approach: copy in smaller chunks to avoid stack issues
53    let chunk_size = 4096; // 4KB chunks
54    let mut src_addr = original_area.start as *const u8;
55    let mut dst_addr = aligned_ptr;
56    let mut remaining = size;
57
58    unsafe {
59        while remaining > 0 {
60            let copy_size = if remaining > chunk_size {
61                chunk_size
62            } else {
63                remaining
64            };
65            ptr::copy_nonoverlapping(src_addr, dst_addr, copy_size);
66
67            src_addr = src_addr.add(copy_size);
68            dst_addr = dst_addr.add(copy_size);
69            remaining -= copy_size;
70
71            // Add memory barrier between chunks
72            core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
73        }
74    }
75
76    // Update usable_area start AFTER copying, with alignment
77    usable_area.start = (aligned_addr + size + 7) & !7;
78
79    Ok(new_area)
80}
81
82fn mount_initramfs(
83    manager: &Arc<VfsManager>,
84    initramfs: MemoryArea,
85) -> Result<(), FileSystemError> {
86    early_println!("[InitRamFS] Initializing initramfs");
87    early_println!(
88        "[InitRamFS] Using initramfs at address: {:#x}, size: {} bytes",
89        initramfs.start,
90        initramfs.size()
91    );
92    // Generate file system from CPIO image
93    let cpio_data =
94        unsafe { core::slice::from_raw_parts(initramfs.start as *const u8, initramfs.size()) };
95    let fs = crate::fs::vfs_v2::drivers::cpiofs::CpioFS::new("initramfs".to_string(), cpio_data)?;
96    manager.mount(fs, "/", 0)?;
97    early_println!("[InitRamFS] Successfully mounted initramfs at root directory");
98    Ok(())
99}
100
101#[allow(static_mut_refs)]
102pub fn init_initramfs(manager: &Arc<VfsManager>, initramfs: MemoryArea) -> Result<(), String> {
103    match mount_initramfs(manager, initramfs) {
104        Ok(_) => Ok(()),
105        Err(e) => Err(format!("Failed to mount initramfs: {:?}", e)),
106    }
107}