⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/process/
loader.rs

1//! User program loader
2//!
3//! This module handles loading user programs from ELF binaries into process
4//! memory.
5
6#![allow(clippy::get_first)]
7
8use alloc::{string::String, vec::Vec};
9
10use crate::{
11    elf::ElfLoader,
12    error::KernelError,
13    process::{Process, ProcessId},
14};
15
16/// Load a user program from ELF binary data
17pub fn load_user_program(process: &mut Process, elf_data: &[u8]) -> Result<u64, KernelError> {
18    // Get process VAS
19    let vas = process
20        .memory_space_mut()
21        .ok_or(KernelError::NotInitialized {
22            subsystem: "process memory space",
23        })?;
24
25    // Load ELF into process memory
26    let entry_point = ElfLoader::load(elf_data, vas)?;
27
28    Ok(entry_point)
29}
30
31/// Create a new process from an ELF binary
32pub fn create_process_from_elf(
33    name: String,
34    elf_data: &[u8],
35    _parent_pid: ProcessId,
36) -> Result<ProcessId, KernelError> {
37    use crate::process::lifecycle::create_process;
38
39    // Create the process (entry_point is temporary, will be replaced)
40    let pid = create_process(name, 0)?;
41
42    // Get the process
43    let process = crate::process::table::get_process_mut(pid)
44        .ok_or(KernelError::ProcessNotFound { pid: pid.0 })?;
45
46    // Load the program
47    let entry_point = load_user_program(process, elf_data)?;
48
49    // Set the entry point for the main thread
50    if let Some(thread) = process.get_main_thread_mut() {
51        thread.set_entry_point(entry_point as usize);
52    }
53
54    Ok(pid)
55}
56
57/// Execute a program by replacing current process image
58pub fn exec_program(
59    process: &mut Process,
60    elf_data: &[u8],
61    args: Vec<String>,
62) -> Result<(), KernelError> {
63    // Clear current memory space
64    if let Some(vas) = process.memory_space_mut() {
65        vas.clear_user_space()?;
66    }
67
68    // Load new program
69    let entry_point = load_user_program(process, elf_data)?;
70
71    // Update process state
72    process.set_name(
73        args.get(0)
74            .cloned()
75            .unwrap_or_else(|| String::from("unknown")),
76    );
77
78    // Reset main thread to new entry point
79    if let Some(thread) = process.get_main_thread_mut() {
80        thread.set_entry_point(entry_point as usize);
81        thread.reset_context();
82    }
83
84    Ok(())
85}