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 core::ptr;
11use alloc::string::ToString;
12use alloc::sync::Arc;
13use crate::device::fdt::FdtManager;
14use crate::fs::VfsManager;
15use crate::early_println;
16use crate::fs::FileSystemError;
17use crate::vm::vmem::MemoryArea;
18
19static mut INITRAMFS_AREA: Option<MemoryArea> = None;
20
21/// Relocate initramfs to heap memory
22pub fn relocate_initramfs(usable_area: &mut MemoryArea) -> Result<(), &'static str> {
23    early_println!("[InitRamFS] Relocating initramfs to {:#x}", usable_area.start as usize);
24    let fdt_manager = FdtManager::get_manager();
25    let original_area = fdt_manager.get_initramfs()
26        .ok_or("Failed to get initramfs from device tree")?;
27    let size = original_area.size();
28    early_println!("[InitRamFS] Original initramfs at {:#x}, size: {} bytes", original_area.start, size);
29    
30    // Validate parameters before proceeding
31    if size == 0 || size > 0x10000000 {
32        return Err("Invalid initramfs size");
33    }
34    if original_area.start == 0 {
35        return Err("Invalid initramfs source address");
36    }
37    
38    // Ensure proper 8-byte alignment for destination
39    let raw_ptr = usable_area.start as *mut u8;
40    let aligned_ptr = ((raw_ptr as usize + 7) & !7) as *mut u8;
41    let aligned_addr = aligned_ptr as usize;
42    
43    early_println!("[InitRamFS] Copying from {:#x} to {:#x} (aligned), size: {} bytes", 
44                   original_area.start, aligned_addr, size);
45    
46    // Validate destination memory bounds
47    if aligned_addr + size > usable_area.end {
48        return Err("Insufficient memory for initramfs");
49    }
50    
51    // Create the new memory area BEFORE the copy operation
52    let new_area = MemoryArea::new(aligned_addr, aligned_addr + size - 1);
53    
54    // Perform the copy with explicit memory barriers
55    core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
56    
57    // Use a safer approach: copy in smaller chunks to avoid stack issues
58    let chunk_size = 4096; // 4KB chunks
59    let mut src_addr = original_area.start as *const u8;
60    let mut dst_addr = aligned_ptr;
61    let mut remaining = size;
62    
63    unsafe {
64        while remaining > 0 {
65            let copy_size = if remaining > chunk_size { chunk_size } else { remaining };
66            ptr::copy_nonoverlapping(src_addr, dst_addr, copy_size);
67            
68            src_addr = src_addr.add(copy_size);
69            dst_addr = dst_addr.add(copy_size);
70            remaining -= copy_size;
71            
72            // Add memory barrier between chunks
73            core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
74        }
75    }
76    
77    // Update usable_area start AFTER copying, with alignment
78    usable_area.start = (aligned_addr + size + 7) & !7;
79    early_println!("[InitRamFS] Relocated initramfs to {:#x}, next usable: {:#x}", 
80                   new_area.start, usable_area.start);
81    unsafe { INITRAMFS_AREA = Some(new_area) };
82    Ok(())
83}
84
85fn mount_initramfs(manager: &Arc<VfsManager>, initramfs: MemoryArea) -> Result<(), FileSystemError> {
86    early_println!("[InitRamFS] Initializing initramfs");
87    early_println!("[InitRamFS] Using initramfs at address: {:#x}, size: {} bytes", initramfs.start, initramfs.size());
88    // Generate file system from CPIO image
89    let cpio_data = unsafe {
90        core::slice::from_raw_parts(initramfs.start as *const u8, initramfs.size())
91    };
92    let fs = crate::fs::vfs_v2::drivers::cpiofs::CpioFS::new("initramfs".to_string(), cpio_data)?;
93    manager.mount(fs, "/", 0)?;
94    early_println!("[InitRamFS] Successfully mounted initramfs at root directory");
95    Ok(())
96}
97
98#[allow(static_mut_refs)]
99pub fn init_initramfs(manager: &Arc<VfsManager>) {
100    let initramfs_ptr = unsafe { INITRAMFS_AREA.as_ref().map(|area| area.start as *const u8).unwrap_or(core::ptr::null()) };
101    if !initramfs_ptr.is_null() {
102        let initramfs = unsafe { *INITRAMFS_AREA.as_ref().unwrap() };
103        if let Err(e) = mount_initramfs(manager, initramfs.clone()) {
104            early_println!("[InitRamFS] Warning: Could not mount initramfs: {:?}", e);
105            return;
106        }
107    } else {
108        early_println!("[InitRamFS] Warning: Initramfs relocation failed, cannot mount");
109    }
110}