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
**/*.mem
mnt

View File

@@ -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"] }

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:
@for file in `ls {{ dir }}`; do \
just cargo_flags={{ cargo_flags }} {{ recipe }} $file ; \
just cargo_flags="{{ cargo_flags }}" {{ recipe }} $file ; \
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
)]
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<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();
idle();

View File

@@ -35,7 +35,7 @@ pub struct Process {
pub pid: i64,
pub name: String,
pub state: ProcessState,
pub entry: Option<fn()>,
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<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;
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].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<T: Into<String>>(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();
}

View File

@@ -51,7 +51,7 @@ pub fn scheduler_init() {
}
}
create_process(idle, "idle");
create_process(&idle, "idle");
unsafe {
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)]
pub extern "C" fn entry() {
let test = "Hello from user mode";
let test = "Hello from PIC program loaded dynamically";
unsafe {
core::arch::asm!(
"ecall",