From 235f17e7cf027af3179d7939f97ae74efab7c498 Mon Sep 17 00:00:00 2001 From: Julien THILLARD Date: Fri, 20 Feb 2026 22:10:09 +0100 Subject: [PATCH] Load dynamic programs using FAT32 --- .gitignore | 1 + Cargo.toml | 21 +++++++------ kernel/build.rs => build.rs | 0 crates/bffs/Cargo.toml | 6 ---- crates/bffs/src/lib.rs | 3 -- justfile | 2 +- kernel/Cargo.toml | 11 ------- kernel/src/user.rs | 24 -------------- {kernel/src => src}/boot.rs | 0 {kernel/src => src}/boot/sbi.rs | 0 {kernel/src => src}/critical_section.rs | 0 src/fs.rs | 42 +++++++++++++++++++++++++ {kernel/src => src}/interrupt.rs | 0 {kernel/src => src}/io.rs | 0 {kernel/src => src}/main.rs | 21 ++++++++++--- {kernel/src => src}/panic_handler.rs | 0 {kernel/src => src}/process.rs | 15 ++++----- {kernel/src => src}/riscv.rs | 0 {kernel/src => src}/scheduler.rs | 2 +- {kernel/src => src}/syscall.rs | 0 {kernel/src => src}/tests_fat.rs | 0 {kernel/src => src}/time.rs | 0 {kernel/src => src}/uart.rs | 0 src/user.rs | 30 ++++++++++++++++++ {kernel/src => src}/vga.rs | 0 user/test_pic/src/main.rs | 2 +- 26 files changed, 112 insertions(+), 68 deletions(-) rename kernel/build.rs => build.rs (100%) delete mode 100644 crates/bffs/Cargo.toml delete mode 100644 crates/bffs/src/lib.rs delete mode 100644 kernel/Cargo.toml delete mode 100644 kernel/src/user.rs rename {kernel/src => src}/boot.rs (100%) rename {kernel/src => src}/boot/sbi.rs (100%) rename {kernel/src => src}/critical_section.rs (100%) create mode 100644 src/fs.rs rename {kernel/src => src}/interrupt.rs (100%) rename {kernel/src => src}/io.rs (100%) rename {kernel/src => src}/main.rs (66%) rename {kernel/src => src}/panic_handler.rs (100%) rename {kernel/src => src}/process.rs (90%) rename {kernel/src => src}/riscv.rs (100%) rename {kernel/src => src}/scheduler.rs (98%) rename {kernel/src => src}/syscall.rs (100%) rename {kernel/src => src}/tests_fat.rs (100%) rename {kernel/src => src}/time.rs (100%) rename {kernel/src => src}/uart.rs (100%) create mode 100644 src/user.rs rename {kernel/src => src}/vga.rs (100%) diff --git a/.gitignore b/.gitignore index 17c4a3b..e470ada 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ disk.img **/*.mem +mnt diff --git a/Cargo.toml b/Cargo.toml index e0f18c4..5492cc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,14 +1,15 @@ -cargo-features = ["profile-rustflags"] - [workspace] resolver = "3" -members = ["kernel", "user/*"] -default-members = ["kernel"] +members = ["user/*"] -[profile.dev] -panic = "abort" -opt-level = 0 +[package] +name = "kernel-rust" +version = "0.1.0" +edition = "2024" -[profile.release] -panic = "abort" -debug = true +[dependencies] +embedded-alloc = "0.7" +kernel-macros = { path = "crates/kernel-macros" } +log = "0.4" +critical-section = { version = "1", features = ["restore-state-bool"] } +bffs = { path = "../../../code/bffs", features = ["alloc"] } diff --git a/kernel/build.rs b/build.rs similarity index 100% rename from kernel/build.rs rename to build.rs diff --git a/crates/bffs/Cargo.toml b/crates/bffs/Cargo.toml deleted file mode 100644 index 7687ecf..0000000 --- a/crates/bffs/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "bffs" -version = "0.1.0" -edition = "2024" - -[dependencies] diff --git a/crates/bffs/src/lib.rs b/crates/bffs/src/lib.rs deleted file mode 100644 index c859c38..0000000 --- a/crates/bffs/src/lib.rs +++ /dev/null @@ -1,3 +0,0 @@ -#![no_std] - -// const MAGIC_NUMBER: usize = 0xBFF5; diff --git a/justfile b/justfile index a1981e6..a9f816d 100644 --- a/justfile +++ b/justfile @@ -16,5 +16,5 @@ run: build map_dir dir recipe: @for file in `ls {{ dir }}`; do \ - just cargo_flags={{ cargo_flags }} {{ recipe }} $file ; \ + just cargo_flags="{{ cargo_flags }}" {{ recipe }} $file ; \ done diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml deleted file mode 100644 index 43ed44c..0000000 --- a/kernel/Cargo.toml +++ /dev/null @@ -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" } diff --git a/kernel/src/user.rs b/kernel/src/user.rs deleted file mode 100644 index 53f08c4..0000000 --- a/kernel/src/user.rs +++ /dev/null @@ -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)); - } -} diff --git a/kernel/src/boot.rs b/src/boot.rs similarity index 100% rename from kernel/src/boot.rs rename to src/boot.rs diff --git a/kernel/src/boot/sbi.rs b/src/boot/sbi.rs similarity index 100% rename from kernel/src/boot/sbi.rs rename to src/boot/sbi.rs diff --git a/kernel/src/critical_section.rs b/src/critical_section.rs similarity index 100% rename from kernel/src/critical_section.rs rename to src/critical_section.rs diff --git a/src/fs.rs b/src/fs.rs new file mode 100644 index 0000000..4ffc623 --- /dev/null +++ b/src/fs.rs @@ -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> { + 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> { + 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) + } +} diff --git a/kernel/src/interrupt.rs b/src/interrupt.rs similarity index 100% rename from kernel/src/interrupt.rs rename to src/interrupt.rs diff --git a/kernel/src/io.rs b/src/io.rs similarity index 100% rename from kernel/src/io.rs rename to src/io.rs diff --git a/kernel/src/main.rs b/src/main.rs similarity index 66% rename from kernel/src/main.rs rename to src/main.rs index d9480d6..e8ad588 100644 --- a/kernel/src/main.rs +++ b/src/main.rs @@ -10,10 +10,13 @@ macro_metavar_expr_concat )] +use alloc::{boxed::Box, vec::Vec}; +use bffs::{io::Read, Fat32FileSystem}; use embedded_alloc::LlffHeap as Heap; use log::info; use crate::{ + fs::Disk, io::init_log, process::create_process, riscv::enable_supervisor_interrupt, @@ -26,6 +29,7 @@ use crate::{ extern crate alloc; mod boot; mod critical_section; +mod fs; mod interrupt; mod io; mod panic_handler; @@ -39,7 +43,7 @@ mod uart; mod user; mod vga; -pub const HEAP_SIZE: usize = 4096; +pub const HEAP_SIZE: usize = 40960; #[global_allocator] static HEAP: Heap = Heap::empty(); @@ -58,10 +62,19 @@ pub extern "C" fn supervisor_mode_entry() { info!("Hello World !"); unsafe { Vga::draw_string(10, 10, "Hello World !", Color::WHITE, Color::BLACK) }; - create_process(test, "proc1"); - create_process(proc2, "proc2"); + create_process(&test, "proc1"); + 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 = 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(); idle(); diff --git a/kernel/src/panic_handler.rs b/src/panic_handler.rs similarity index 100% rename from kernel/src/panic_handler.rs rename to src/panic_handler.rs diff --git a/kernel/src/process.rs b/src/process.rs similarity index 90% rename from kernel/src/process.rs rename to src/process.rs index 5d6d0e8..b4bf3ab 100644 --- a/kernel/src/process.rs +++ b/src/process.rs @@ -35,7 +35,7 @@ pub struct Process { pub pid: i64, pub name: String, pub state: ProcessState, - pub entry: Option, + pub entry: Option<&'static dyn Fn()>, pub wake_time: Duration, pub ctx: ExecutionContext, pub stack: [u64; STACK_SIZE], @@ -54,7 +54,7 @@ impl core::fmt::Debug for Process { } } -pub fn create_process>(code: fn(), name: T) -> i64 { +pub fn create_process, F: Fn()>(code: &'static F, name: T) -> i64 { let mut next_pid = 0; while next_pid < PROCESS_COUNT && unsafe { PROCESS_TABLE[next_pid].state != ProcessState::Dead } { @@ -71,7 +71,7 @@ pub fn create_process>(code: fn(), name: T) -> i64 { PROCESS_TABLE[next_pid].state = ProcessState::Activable; PROCESS_TABLE[next_pid].entry = Some(code); 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.mstatus = 1 << 1 | 1 << 5; PROCESS_TABLE[next_pid].ctx.sp = &raw const PROCESS_TABLE[next_pid].stack[STACK_SIZE - 1]; @@ -80,7 +80,7 @@ pub fn create_process>(code: fn(), name: T) -> i64 { next_pid as i64 } -extern "C" fn process_launcher(code: *const fn()) { +extern "C" fn process_launcher(code: *const &dyn Fn()) { unsafe { (*code)() }; terminate_process(); } @@ -89,9 +89,10 @@ fn terminate_process() { unsafe { PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Dead; } - unsafe { - wfi(); - } + loop {} + // unsafe { + // wfi(); + // } // scheduler(); } diff --git a/kernel/src/riscv.rs b/src/riscv.rs similarity index 100% rename from kernel/src/riscv.rs rename to src/riscv.rs diff --git a/kernel/src/scheduler.rs b/src/scheduler.rs similarity index 98% rename from kernel/src/scheduler.rs rename to src/scheduler.rs index 66d8725..b53101a 100644 --- a/kernel/src/scheduler.rs +++ b/src/scheduler.rs @@ -51,7 +51,7 @@ pub fn scheduler_init() { } } - create_process(idle, "idle"); + create_process(&idle, "idle"); unsafe { PROCESS_TABLE[0].state = ProcessState::Active; } diff --git a/kernel/src/syscall.rs b/src/syscall.rs similarity index 100% rename from kernel/src/syscall.rs rename to src/syscall.rs diff --git a/kernel/src/tests_fat.rs b/src/tests_fat.rs similarity index 100% rename from kernel/src/tests_fat.rs rename to src/tests_fat.rs diff --git a/kernel/src/time.rs b/src/time.rs similarity index 100% rename from kernel/src/time.rs rename to src/time.rs diff --git a/kernel/src/uart.rs b/src/uart.rs similarity index 100% rename from kernel/src/uart.rs rename to src/uart.rs diff --git a/src/user.rs b/src/user.rs new file mode 100644 index 0000000..fbfd07f --- /dev/null +++ b/src/user.rs @@ -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)); + } +} diff --git a/kernel/src/vga.rs b/src/vga.rs similarity index 100% rename from kernel/src/vga.rs rename to src/vga.rs diff --git a/user/test_pic/src/main.rs b/user/test_pic/src/main.rs index dc361d9..2ab008b 100644 --- a/user/test_pic/src/main.rs +++ b/user/test_pic/src/main.rs @@ -8,7 +8,7 @@ fn panic(_panic_info: &core::panic::PanicInfo) -> ! { #[unsafe(no_mangle)] pub extern "C" fn entry() { - let test = "Hello from user mode"; + let test = "Hello from PIC program loaded dynamically"; unsafe { core::arch::asm!( "ecall",