kernel/fs/drivers/
initramfs.rs

1//! Initramfs mounting functionality
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;
11
12use crate::device::fdt::FdtManager;
13use crate::fs::VfsManager;
14use crate::early_println;
15use crate::fs::FileSystemError;
16use crate::vm::vmem::MemoryArea;
17
18static mut INITRAMFS_AREA: Option<MemoryArea> = None;
19
20/// Relocate initramfs to heap memory
21///
22/// This function copies the initramfs from the location provided by the bootloader
23/// to a new location in kernel heap memory, so that it can be accessed after
24/// virtual memory is enabled.
25///
26/// # Returns
27/// Option<MemoryArea>: The memory area of the relocated initramfs if successful,
28/// None otherwise.
29pub fn relocate_initramfs(usable_area: &mut MemoryArea) -> Result<(), &'static str> {
30    early_println!("[InitRamFS] Relocating initramfs to {:#x}", usable_area.start as usize);
31    
32    // Get the FDT manager
33    let fdt_manager = FdtManager::get_manager();
34    
35    // Get the initramfs memory area from the device tree
36    let original_area = fdt_manager.get_initramfs()
37        .ok_or("Failed to get initramfs from device tree")?;
38    
39    let size = original_area.size();
40    early_println!("[InitRamFS] Original initramfs at {:#x}, size: {} bytes", 
41        original_area.start, size);
42    
43    let new_ptr = usable_area.start as *mut u8;
44    usable_area.start = new_ptr as usize + size;
45
46    // Copy the initramfs data
47    unsafe {
48        ptr::copy_nonoverlapping(
49            original_area.start as *const u8,
50            new_ptr,
51            size
52        );
53    }
54    
55    // Create a new memory area for the relocated initramfs
56    let new_area = MemoryArea::new(new_ptr as usize, (new_ptr as usize) + size - 1);
57    early_println!("[InitRamFS] Relocated initramfs to {:#x}", new_area.start);
58    
59    unsafe { INITRAMFS_AREA = Some(new_area) };
60
61    Ok(())
62}
63
64/// Mount the initramfs as the root filesystem
65///
66/// This function creates a CPIO filesystem from the initramfs memory area
67/// and mounts it at the root ("/") mount point.
68///
69/// # Arguments
70/// * `manager` - A mutable reference to the VFS manager. 
71/// * `initramfs` - The memory area of the initramfs.
72///
73/// # Returns
74/// Result<(), FileSystemError>: Ok if mounting was successful, Err otherwise.
75fn mount_initramfs(manager: &mut VfsManager, initramfs: MemoryArea) -> Result<(), FileSystemError> {
76    early_println!("[InitRamFS] Initializing initramfs");
77    
78    early_println!("[InitRamFS] Using initramfs at address: {:#x}, size: {} bytes", 
79        initramfs.start, initramfs.size());
80    
81    // Create and register a CPIO filesystem from the initramfs memory area
82    let fs_id = manager.create_and_register_memory_fs("cpiofs", &initramfs)?;
83    
84    // Mount the filesystem at the root directory
85    match manager.mount(fs_id, "/") {
86        Ok(_) => {
87            early_println!("[InitRamFS] Successfully mounted initramfs at root directory");
88            Ok(())
89        },
90        Err(e) => {
91            early_println!("[InitRamFS] Failed to mount initramfs: {:?}", e);
92            Err(e)
93        }
94    }
95}
96
97#[allow(static_mut_refs)]
98pub fn init_initramfs(manager: &mut VfsManager) {
99    let initramfs_ptr = unsafe { INITRAMFS_AREA.as_ref().map(|area| area.start as *const u8).unwrap_or(core::ptr::null()) };
100    if !initramfs_ptr.is_null() {
101        let initramfs = unsafe { *INITRAMFS_AREA.as_ref().unwrap() };
102        
103        // Mount the initramfs
104        if let Err(e) = mount_initramfs(manager, initramfs.clone()) {
105            early_println!("[InitRamFS] Warning: Could not mount initramfs: {:?}", e);
106            return;
107        }
108    } else {
109        early_println!("[InitRamFS] Warning: Initramfs relocation failed, cannot mount");
110    }
111}