Load dynamic programs using FAT32

This commit is contained in:
2026-02-20 22:10:09 +01:00
parent 00d9ce656c
commit 235f17e7cf
26 changed files with 112 additions and 68 deletions

1
.gitignore vendored
View File

@@ -5,3 +5,4 @@
disk.img disk.img
**/*.mem **/*.mem
mnt

View File

@@ -1,14 +1,15 @@
cargo-features = ["profile-rustflags"]
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["kernel", "user/*"] members = ["user/*"]
default-members = ["kernel"]
[profile.dev] [package]
panic = "abort" name = "kernel-rust"
opt-level = 0 version = "0.1.0"
edition = "2024"
[profile.release] [dependencies]
panic = "abort" embedded-alloc = "0.7"
debug = true kernel-macros = { path = "crates/kernel-macros" }
log = "0.4"
critical-section = { version = "1", features = ["restore-state-bool"] }
bffs = { path = "../../../code/bffs", features = ["alloc"] }

View File

@@ -1,6 +0,0 @@
[package]
name = "bffs"
version = "0.1.0"
edition = "2024"
[dependencies]

View File

@@ -1,3 +0,0 @@
#![no_std]
// const MAGIC_NUMBER: usize = 0xBFF5;

View File

@@ -16,5 +16,5 @@ run: build
map_dir dir recipe: map_dir dir recipe:
@for file in `ls {{ dir }}`; do \ @for file in `ls {{ dir }}`; do \
just cargo_flags={{ cargo_flags }} {{ recipe }} $file ; \ just cargo_flags="{{ cargo_flags }}" {{ recipe }} $file ; \
done done

View File

@@ -1,11 +0,0 @@
[package]
name = "kernel-rust"
version = "0.1.0"
edition = "2024"
[dependencies]
embedded-alloc = "0.7"
kernel-macros = { path = "../crates/kernel-macros" }
log = "0.4"
critical-section = { version = "1", features = ["restore-state-bool"] }
bffs = { path = "../crates/bffs" }

View File

@@ -1,24 +0,0 @@
use core::time::Duration;
use crate::syscall::{sleep, write_int_temp, write_string_temp};
#[repr(align(32))]
struct Alignement([u8; 136]);
static PROG: Alignement = Alignement(*include_bytes!("../../user/test_pic/test_pic.mem"));
pub fn test() {
write_int_temp(PROG.0.as_ptr() as u64);
unsafe { core::mem::transmute::<*const u8, extern "C" fn()>(PROG.0.as_ptr())() }
loop {
write_string_temp("test");
sleep(Duration::new(2, 0));
}
}
pub fn proc2() {
loop {
write_string_temp("proc2");
sleep(Duration::new(3, 0));
}
}

42
src/fs.rs Normal file
View File

@@ -0,0 +1,42 @@
use bffs::io::{IoBase, Read, Seek};
const DISK_ADDR: *const u8 = 0x9000_0000 as *const _;
#[derive(Debug)]
pub struct Disk {
pos: u64,
size: u64,
}
impl Disk {
pub fn new(size: u64) -> Self {
Self { pos: 0, size }
}
}
impl IoBase for Disk {
type Error = ();
}
impl Seek for Disk {
fn seek(&mut self, pos: bffs::io::SeekFrom) -> Result<u64, bffs::error::Error<Self::Error>> {
match pos {
bffs::io::SeekFrom::Start(pos) => self.pos = pos,
bffs::io::SeekFrom::End(_) => unimplemented!(),
bffs::io::SeekFrom::Current(pos) => self.pos = (self.pos as i64 + pos) as u64,
}
Ok(self.pos)
}
}
impl Read for Disk {
fn read(&mut self, buf: &mut [u8]) -> Result<usize, bffs::error::Error<Self::Error>> {
if self.pos >= self.size {
return Ok(0);
}
let size = usize::min(buf.len(), (self.size - self.pos) as usize);
(0..size).for_each(|i| buf[i] = unsafe { *DISK_ADDR.byte_add(i + self.pos as usize) });
self.pos += size as u64;
Ok(size)
}
}

View File

@@ -10,10 +10,13 @@
macro_metavar_expr_concat macro_metavar_expr_concat
)] )]
use alloc::{boxed::Box, vec::Vec};
use bffs::{io::Read, Fat32FileSystem};
use embedded_alloc::LlffHeap as Heap; use embedded_alloc::LlffHeap as Heap;
use log::info; use log::info;
use crate::{ use crate::{
fs::Disk,
io::init_log, io::init_log,
process::create_process, process::create_process,
riscv::enable_supervisor_interrupt, riscv::enable_supervisor_interrupt,
@@ -26,6 +29,7 @@ use crate::{
extern crate alloc; extern crate alloc;
mod boot; mod boot;
mod critical_section; mod critical_section;
mod fs;
mod interrupt; mod interrupt;
mod io; mod io;
mod panic_handler; mod panic_handler;
@@ -39,7 +43,7 @@ mod uart;
mod user; mod user;
mod vga; mod vga;
pub const HEAP_SIZE: usize = 4096; pub const HEAP_SIZE: usize = 40960;
#[global_allocator] #[global_allocator]
static HEAP: Heap = Heap::empty(); static HEAP: Heap = Heap::empty();
@@ -58,10 +62,19 @@ pub extern "C" fn supervisor_mode_entry() {
info!("Hello World !"); info!("Hello World !");
unsafe { Vga::draw_string(10, 10, "Hello World !", Color::WHITE, Color::BLACK) }; unsafe { Vga::draw_string(10, 10, "Hello World !", Color::WHITE, Color::BLACK) };
create_process(test, "proc1"); create_process(&test, "proc1");
create_process(proc2, "proc2"); create_process(&proc2, "proc2");
MemoryDisk::test(); let fs = Fat32FileSystem::new(Disk::new(1024 * 1024 * 16)).unwrap();
let mut bin = fs.open_file("/usr/bin/test").unwrap();
let mut content: Vec<u8> = Vec::new();
bin.read_to_end(&mut content).unwrap();
let test = unsafe { core::mem::transmute::<*const u8, extern "C" fn()>(content.as_ptr()) };
let test = Box::leak(Box::new(move || {
test();
}));
create_process(test, "dyn_proc");
enable_supervisor_interrupt(); enable_supervisor_interrupt();
idle(); idle();

View File

@@ -35,7 +35,7 @@ pub struct Process {
pub pid: i64, pub pid: i64,
pub name: String, pub name: String,
pub state: ProcessState, pub state: ProcessState,
pub entry: Option<fn()>, pub entry: Option<&'static dyn Fn()>,
pub wake_time: Duration, pub wake_time: Duration,
pub ctx: ExecutionContext, pub ctx: ExecutionContext,
pub stack: [u64; STACK_SIZE], pub stack: [u64; STACK_SIZE],
@@ -54,7 +54,7 @@ impl core::fmt::Debug for Process {
} }
} }
pub fn create_process<T: Into<String>>(code: fn(), name: T) -> i64 { pub fn create_process<T: Into<String>, F: Fn()>(code: &'static F, name: T) -> i64 {
let mut next_pid = 0; let mut next_pid = 0;
while next_pid < PROCESS_COUNT && unsafe { PROCESS_TABLE[next_pid].state != ProcessState::Dead } while next_pid < PROCESS_COUNT && unsafe { PROCESS_TABLE[next_pid].state != ProcessState::Dead }
{ {
@@ -71,7 +71,7 @@ pub fn create_process<T: Into<String>>(code: fn(), name: T) -> i64 {
PROCESS_TABLE[next_pid].state = ProcessState::Activable; PROCESS_TABLE[next_pid].state = ProcessState::Activable;
PROCESS_TABLE[next_pid].entry = Some(code); PROCESS_TABLE[next_pid].entry = Some(code);
PROCESS_TABLE[next_pid].ctx.a[0] = PROCESS_TABLE[next_pid].ctx.a[0] =
PROCESS_TABLE[next_pid].entry.as_ref().unwrap_unchecked() as *const fn() as u64; PROCESS_TABLE[next_pid].entry.as_ref().unwrap_unchecked() as *const &dyn Fn() as u64;
PROCESS_TABLE[next_pid].ctx.mepc = process_launcher as *const _; PROCESS_TABLE[next_pid].ctx.mepc = process_launcher as *const _;
PROCESS_TABLE[next_pid].ctx.mstatus = 1 << 1 | 1 << 5; PROCESS_TABLE[next_pid].ctx.mstatus = 1 << 1 | 1 << 5;
PROCESS_TABLE[next_pid].ctx.sp = &raw const PROCESS_TABLE[next_pid].stack[STACK_SIZE - 1]; PROCESS_TABLE[next_pid].ctx.sp = &raw const PROCESS_TABLE[next_pid].stack[STACK_SIZE - 1];
@@ -80,7 +80,7 @@ pub fn create_process<T: Into<String>>(code: fn(), name: T) -> i64 {
next_pid as i64 next_pid as i64
} }
extern "C" fn process_launcher(code: *const fn()) { extern "C" fn process_launcher(code: *const &dyn Fn()) {
unsafe { (*code)() }; unsafe { (*code)() };
terminate_process(); terminate_process();
} }
@@ -89,9 +89,10 @@ fn terminate_process() {
unsafe { unsafe {
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Dead; PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Dead;
} }
unsafe { loop {}
wfi(); // unsafe {
} // wfi();
// }
// scheduler(); // scheduler();
} }

View File

@@ -51,7 +51,7 @@ pub fn scheduler_init() {
} }
} }
create_process(idle, "idle"); create_process(&idle, "idle");
unsafe { unsafe {
PROCESS_TABLE[0].state = ProcessState::Active; PROCESS_TABLE[0].state = ProcessState::Active;
} }

30
src/user.rs Normal file
View File

@@ -0,0 +1,30 @@
use core::time::Duration;
use alloc::vec::Vec;
use bffs::{io::Read, Fat32FileSystem};
use crate::{
fs::Disk,
syscall::{sleep, write_int_temp, write_string_temp},
};
#[repr(align(32))]
struct Alignement([u8; 157]);
static PROG: Alignement = Alignement(*include_bytes!("../user/test_pic/test_pic.mem"));
pub fn test() {
write_int_temp(PROG.0.as_ptr() as u64);
// unsafe { core::mem::transmute::<*const u8, extern "C" fn()>(PROG.0.as_ptr())() }
loop {
write_string_temp("test");
sleep(Duration::new(2, 0));
}
}
pub fn proc2() {
loop {
write_string_temp("proc2");
sleep(Duration::new(3, 0));
}
}

View File

@@ -8,7 +8,7 @@ fn panic(_panic_info: &core::panic::PanicInfo) -> ! {
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn entry() { pub extern "C" fn entry() {
let test = "Hello from user mode"; let test = "Hello from PIC program loaded dynamically";
unsafe { unsafe {
core::arch::asm!( core::arch::asm!(
"ecall", "ecall",