Better user programs with a special std. Sleep and exit are calling scheduler instead of wfi.

This commit is contained in:
2026-02-21 18:29:27 +01:00
parent 235f17e7cf
commit 8a8034bd11
25 changed files with 263 additions and 210 deletions

View File

@@ -6,4 +6,7 @@ build-std = ["core", "compiler_builtins", "alloc"]
build-std-features = ["compiler-builtins-mem"] build-std-features = ["compiler-builtins-mem"]
[target.riscv64] [target.riscv64]
rustflags = [
"-C", "link-arg=-Tilm.ld",
]
runner = "qemu-system-riscv64 -machine virt -device bochs-display -bios none -m 512M -device loader,file=/home/julien/ensimag/TPs/kernel/disk.img,addr=0x90000000 -kernel" runner = "qemu-system-riscv64 -machine virt -device bochs-display -bios none -m 512M -device loader,file=/home/julien/ensimag/TPs/kernel/disk.img,addr=0x90000000 -kernel"

View File

@@ -1,6 +1,6 @@
[workspace] [workspace]
resolver = "3" resolver = "3"
members = ["user/*"] members = ["crates/os-std", "crates/shared", "user/*"]
[package] [package]
name = "kernel-rust" name = "kernel-rust"
@@ -13,3 +13,4 @@ kernel-macros = { path = "crates/kernel-macros" }
log = "0.4" log = "0.4"
critical-section = { version = "1", features = ["restore-state-bool"] } critical-section = { version = "1", features = ["restore-state-bool"] }
bffs = { path = "../../../code/bffs", features = ["alloc"] } bffs = { path = "../../../code/bffs", features = ["alloc"] }
shared = { path = "crates/shared" }

View File

@@ -1,3 +0,0 @@
fn main() {
println!("cargo::rustc-link-arg=-Tilm.ld");
}

View File

@@ -0,0 +1,12 @@
[package]
name = "os-std-macros"
version = "0.1.0"
edition = "2024"
[lib]
proc-macro = true
[dependencies]
proc-macro2 = "1"
quote = "1"
syn = { version = "2", features = ["full"] }

View File

@@ -0,0 +1 @@

8
crates/os-std/Cargo.toml Normal file
View File

@@ -0,0 +1,8 @@
[package]
name = "os-std"
version = "0.1.0"
edition = "2024"
[dependencies]
os-std-macros = { path = "../os-std-macros" }
shared = { path = "../shared" }

21
crates/os-std/src/lib.rs Normal file
View File

@@ -0,0 +1,21 @@
#![no_std]
mod prelude;
pub use shared::syscall;
#[macro_export]
macro_rules! custom_std_setup {
() => {
#[panic_handler]
fn panic(_panic_info: &core::panic::PanicInfo) -> ! {
// TODO print
loop {}
}
#[unsafe(no_mangle)]
pub extern "C" fn _start() {
main()
}
};
}

View File

@@ -0,0 +1 @@

6
crates/shared/Cargo.toml Normal file
View File

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

3
crates/shared/src/lib.rs Normal file
View File

@@ -0,0 +1,3 @@
#![no_std]
pub mod syscall;

View File

@@ -2,6 +2,7 @@ use core::time::Duration;
#[repr(u64)] #[repr(u64)]
pub enum SysCall { pub enum SysCall {
Exit = 60,
NanoSleep = 101, NanoSleep = 101,
WriteIntTemp = 998, WriteIntTemp = 998,
WriteTemp = 999, WriteTemp = 999,
@@ -11,6 +12,7 @@ pub enum SysCall {
impl From<u64> for SysCall { impl From<u64> for SysCall {
fn from(value: u64) -> Self { fn from(value: u64) -> Self {
match value { match value {
60 => SysCall::Exit,
101 => SysCall::NanoSleep, 101 => SysCall::NanoSleep,
998 => SysCall::WriteIntTemp, 998 => SysCall::WriteIntTemp,
999 => SysCall::WriteTemp, 999 => SysCall::WriteTemp,
@@ -75,6 +77,12 @@ macro_rules! syscall {
}; };
} }
pub fn exit() {
unsafe {
syscall!(SysCall::Exit);
}
}
pub fn sleep(duration: Duration) { pub fn sleep(duration: Duration) {
unsafe { unsafe {
let (duration_secs, duration_nanos) = (duration.as_secs(), duration.subsec_nanos() as u64); let (duration_secs, duration_nanos) = (duration.as_secs(), duration.subsec_nanos() as u64);

5
ilm.ld
View File

@@ -2,17 +2,16 @@
* ld directives the for barmetal RISCV * ld directives the for barmetal RISCV
*/ */
OUTPUT_ARCH(riscv) OUTPUT_ARCH(riscv)
ENTRY(entry) ENTRY(_start)
MEMORY { MEMORY {
RAM (wxa) : ORIGIN = 0x80000000, LENGTH = 128M RAM (wxa) : ORIGIN = 0x80000000, LENGTH = 128M
} }
SECTIONS { SECTIONS {
/* The kernel starts at 0x80000000 */
. = 0x80000000; . = 0x80000000;
.text : { .text : {
KEEP(*(.text.entry)) KEEP(*(.text._start))
*(.text .text.*) *(.text .text.*)
} > RAM } > RAM

View File

@@ -3,16 +3,23 @@ cargo_flags := if release != "" { "--release" } else { "" }
default: run default: run
build_user_prog prog: mount_filesystem:
cd {{ "user" / prog }} && \ # Add some permissions to be able to do next operations without sudo
RUSTFLAGS="-C relocation-model=pic" cargo b {{ cargo_flags }} @mountpoint -q mnt || sudo mount -o umask=0022,gid=$(id -g $USER),uid=$(id -u $USER) disk.img mnt
riscv64-elf-objcopy -O binary {{ "target/riscv64/debug" / prog }} {{ "user" / prog / prog + ".mem" }}
build: (map_dir "user" "build_user_prog") sync_filesystem:
sync
build_user_prog prog:
RUSTFLAGS="-C relocation-model=pic -C link-arg=-Tilm.ld" cargo b {{ cargo_flags }} --package {{ prog }}
riscv64-elf-objcopy -O binary {{ "target/riscv64/debug" / prog }} {{ "mnt/usr/bin" / prog }}
build: mount_filesystem (map_dir "user" "build_user_prog")
cargo b {{ cargo_flags }} cargo b {{ cargo_flags }}
just sync_filesystem
run: build run: build
cargo r {{ cargo_flags }} --bin kernel-rust cargo r {{ cargo_flags }}
map_dir dir recipe: map_dir dir recipe:
@for file in `ls {{ dir }}`; do \ @for file in `ls {{ dir }}`; do \

View File

@@ -10,7 +10,7 @@ pub mod sbi;
#[unsafe(naked)] #[unsafe(naked)]
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn entry() { pub extern "C" fn _start() {
naked_asm!( naked_asm!(
" "
la sp, _heap_end la sp, _heap_end

View File

@@ -1,7 +1,33 @@
use bffs::io::{IoBase, Read, Seek}; use core::{cell::UnsafeCell, ops::Deref};
use bffs::{
io::{IoBase, Read, Seek},
Fat32FileSystem,
};
const DISK_ADDR: *const u8 = 0x9000_0000 as *const _; const DISK_ADDR: *const u8 = 0x9000_0000 as *const _;
pub struct FSTemp(UnsafeCell<Option<Fat32FileSystem<Disk>>>);
unsafe impl Sync for FSTemp {}
impl FSTemp {
pub unsafe fn init(&self) {
unsafe {
*self.0.get() = Some(Fat32FileSystem::new(Disk::new(1024 * 1024 * 16)).unwrap());
}
}
}
impl Deref for FSTemp {
type Target = Fat32FileSystem<Disk>;
fn deref(&self) -> &Self::Target {
unsafe { (&*self.0.get()).as_ref().unwrap_unchecked() }
}
}
pub static FILE_SYSTEM: FSTemp = FSTemp(UnsafeCell::new(None));
#[derive(Debug)] #[derive(Debug)]
pub struct Disk { pub struct Disk {
pos: u64, pos: u64,

View File

@@ -1,15 +1,15 @@
use alloc::str; use alloc::str;
use log::info; use log::info;
use shared::syscall::SysCall;
use crate::{ use crate::{
boot::sbi::{EextensionID, TimerFunctionID}, boot::sbi::{EextensionID, TimerFunctionID},
clear_csr, generate_trap_handler, clear_csr,
process::{sleep, ExecutionContext}, process::{exit_process, sleep, ExecutionContext},
read_csr, read_csr,
riscv::disable_interrupt, riscv::disable_interrupt,
scheduler::scheduler, scheduler::scheduler_without_ret,
set_csr, set_csr,
syscall::SysCall,
time::{setup_next_timer_interrupt, IRQ_M_TIMER}, time::{setup_next_timer_interrupt, IRQ_M_TIMER},
write_csr, write_csr,
}; };
@@ -87,7 +87,7 @@ unsafe extern "C" fn machine_trap_handler(
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
unsafe extern "C" fn supervisor_trap_handler( unsafe extern "C" fn supervisor_trap_handler(
interrupt_state: *mut ExecutionContext, mut interrupt_state: *mut ExecutionContext,
scause: u64, scause: u64,
_sie: u64, _sie: u64,
_sip: u64, _sip: u64,
@@ -96,13 +96,19 @@ unsafe extern "C" fn supervisor_trap_handler(
#[allow(clippy::single_match)] #[allow(clippy::single_match)]
match scause & !(1 << 63) { match scause & !(1 << 63) {
8 => { 8 => {
// Advance sepc to exit the ecall
unsafe {
(*interrupt_state).mepc = (*interrupt_state).mepc.byte_add(4);
}
// Environment call from S-mode // Environment call from S-mode
let syscall_u64: u64 = unsafe { (*interrupt_state).a[0] }; let syscall_u64: u64 = unsafe { (*interrupt_state).a[0] };
let a1: u64 = unsafe { (*interrupt_state).a[1] }; let a1: u64 = unsafe { (*interrupt_state).a[1] };
let a2: u64 = unsafe { (*interrupt_state).a[2] }; let a2: u64 = unsafe { (*interrupt_state).a[2] };
let syscall: SysCall = syscall_u64.into(); let syscall: SysCall = syscall_u64.into();
match syscall { match syscall {
SysCall::NanoSleep => sleep(Duration::new(a1, a2 as u32)), SysCall::Exit => exit_process(&mut interrupt_state),
SysCall::NanoSleep => sleep(Duration::new(a1, a2 as u32), &mut interrupt_state),
SysCall::WriteTemp => { SysCall::WriteTemp => {
info!("Print from user space : {}", unsafe { info!("Print from user space : {}", unsafe {
str::from_raw_parts(a1 as *const u8, a2 as usize) str::from_raw_parts(a1 as *const u8, a2 as usize)
@@ -115,11 +121,6 @@ unsafe extern "C" fn supervisor_trap_handler(
unimplemented!("Syscall {syscall_u64} is not implemented") unimplemented!("Syscall {syscall_u64} is not implemented")
} }
} }
// Advance sepc to exit the ecall
unsafe {
(*interrupt_state).mepc = (*interrupt_state).mepc.byte_add(4);
}
} }
_ => {} _ => {}
} }
@@ -137,7 +138,7 @@ unsafe extern "C" fn supervisor_trap_handler(
); );
} }
timer_interrupt(); timer_interrupt();
return scheduler(unsafe { *interrupt_state }); scheduler_without_ret(&mut interrupt_state);
} }
_ => {} _ => {}
} }
@@ -207,116 +208,107 @@ unsafe extern "C" fn _machine_mode_trap() {
mret" mret"
) )
} }
generate_trap_handler! { #[unsafe(naked)]
_supervisor_mode_trap, supervisor_trap_handler, s #[unsafe(no_mangle)]
unsafe extern "C" fn _supervisor_mode_trap() {
naked_asm!(concat!(
"
// Store sp before it gets modified
sd sp, 8-264(sp)
addi sp, sp, -264
# Store the current frame
sd ra, 0(sp)
// sp
sd gp, 16(sp)
sd tp, 24(sp)
sd a0, 32(sp)
sd a1, 40(sp)
sd a2, 48(sp)
sd a3, 56(sp)
sd a4, 64(sp)
sd a5, 72(sp)
sd a6, 80(sp)
sd a7, 88(sp)
sd t0, 96(sp)
sd t1, 104(sp)
sd t2, 112(sp)
sd t3, 120(sp)
sd t4, 128(sp)
sd t5, 136(sp)
sd t6, 144(sp)
sd s0, 152(sp)
sd s1, 160(sp)
sd s2, 168(sp)
sd s3, 176(sp)
sd s4, 184(sp)
sd s5, 192(sp)
sd s6, 200(sp)
sd s7, 208(sp)
sd s8, 216(sp)
sd s9, 224(sp)
sd s10, 232(sp)
sd s11, 240(sp)
csrr t0, sepc
sd t0, 248(sp)
csrr t0, sstatus
sd t0, 256(sp)
mv a0, sp
csrr a1, scause
csrr a2, sie
csrr a3, sip
jal supervisor_trap_handler
# Restore registers and sret
jal restore_context"
))
} }
#[macro_export] #[unsafe(naked)]
macro_rules! generate_trap_handler { #[unsafe(no_mangle)]
($name:ident, $jump_to:ident, $mode:ident) => { pub unsafe extern "C" fn restore_context(context: *const ExecutionContext) -> ! {
#[unsafe(naked)] naked_asm!(concat!(
#[unsafe(no_mangle)] "
unsafe extern "C" fn $name() { ld t0, 248(a0)
naked_asm!(concat!( csrw sepc, t0
" ld t0, 256(a0)
mv t0, sp csrw sstatus, t0
addi sp, sp, -264 ld ra, 0(a0)
ld sp, 8(a0)
ld gp, 16(a0)
ld tp, 24(a0)
ld a1, 40(a0)
ld a2, 48(a0)
ld a3, 56(a0)
ld a4, 64(a0)
ld a5, 72(a0)
ld a6, 80(a0)
ld a7, 88(a0)
ld t0, 96(a0)
ld t1, 104(a0)
ld t2, 112(a0)
ld t3, 120(a0)
ld t4, 128(a0)
ld t5, 136(a0)
ld t6, 144(a0)
ld s0, 152(a0)
ld s1, 160(a0)
ld s2, 168(a0)
ld s3, 176(a0)
ld s4, 184(a0)
ld s5, 192(a0)
ld s6, 200(a0)
ld s7, 208(a0)
ld s8, 216(a0)
ld s9, 224(a0)
ld s10, 232(a0)
ld s11, 240(a0)
# Store the current frame ld a0, 32(a0)
sd ra, 0(sp)
sd t0, 8(sp) // sp
sd gp, 16(sp)
sd tp, 24(sp)
sd a0, 32(sp)
sd a1, 40(sp)
sd a2, 48(sp)
sd a3, 56(sp)
sd a4, 64(sp)
sd a5, 72(sp)
sd a6, 80(sp)
sd a7, 88(sp)
sd t0, 96(sp)
sd t1, 104(sp)
sd t2, 112(sp)
sd t3, 120(sp)
sd t4, 128(sp)
sd t5, 136(sp)
sd t6, 144(sp)
sd s0, 152(sp)
sd s1, 160(sp)
sd s2, 168(sp)
sd s3, 176(sp)
sd s4, 184(sp)
sd s5, 192(sp)
sd s6, 200(sp)
sd s7, 208(sp)
sd s8, 216(sp)
sd s9, 224(sp)
sd s10, 232(sp)
sd s11, 240(sp)
csrr t0, sepc
sd t0, 248(sp)
csrr t0, sstatus
sd t0, 256(sp)
mv a0, sp sret"
csrr a1, ", ))
stringify!($mode),
"cause
csrr a2, ",
stringify!($mode),
"ie
csrr a3, ",
stringify!($mode),
"ip
jal ",
stringify!($jump_to),
"
# Restore registers
ld t0, 248(a0)
csrw sepc, t0
ld t0, 256(a0)
csrw sstatus, t0
ld ra, 0(a0)
ld sp, 8(a0)
ld gp, 16(a0)
ld tp, 24(a0)
ld a1, 40(a0)
ld a2, 48(a0)
ld a3, 56(a0)
ld a4, 64(a0)
ld a5, 72(a0)
ld a6, 80(a0)
ld a7, 88(a0)
ld t0, 96(a0)
ld t1, 104(a0)
ld t2, 112(a0)
ld t3, 120(a0)
ld t4, 128(a0)
ld t5, 136(a0)
ld t6, 144(a0)
ld s0, 152(a0)
ld s1, 160(a0)
ld s2, 168(a0)
ld s3, 176(a0)
ld s4, 184(a0)
ld s5, 192(a0)
ld s6, 200(a0)
ld s7, 208(a0)
ld s8, 216(a0)
ld s9, 224(a0)
ld s10, 232(a0)
ld s11, 240(a0)
ld a0, 32(a0)
",
stringify!($mode),
"ret"
))
}
};
} }
#[repr(C)] #[repr(C)]

View File

@@ -7,7 +7,7 @@ use log::{LevelFilter, SetLoggerError};
use crate::uart::write_uart; use crate::uart::write_uart;
fn print(content: String) { pub(crate) fn print(content: String) {
write_uart(content); write_uart(content);
} }

View File

@@ -10,18 +10,15 @@
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, fs::FILE_SYSTEM,
io::init_log, io::init_log,
process::create_process, process::{create_process, create_process_from_file},
riscv::enable_supervisor_interrupt, riscv::enable_supervisor_interrupt,
scheduler::{idle, scheduler_init}, scheduler::{idle, scheduler_init},
tests_fat::MemoryDisk,
user::{proc2, test}, user::{proc2, test},
vga::{Color, Vga}, vga::{Color, Vga},
}; };
@@ -36,14 +33,12 @@ mod panic_handler;
mod process; mod process;
mod riscv; mod riscv;
mod scheduler; mod scheduler;
mod syscall;
mod tests_fat;
mod time; mod time;
mod uart; mod uart;
mod user; mod user;
mod vga; mod vga;
pub const HEAP_SIZE: usize = 40960; pub const HEAP_SIZE: usize = 1024 * 1024; // 1Mo RAM
#[global_allocator] #[global_allocator]
static HEAP: Heap = Heap::empty(); static HEAP: Heap = Heap::empty();
@@ -56,6 +51,7 @@ pub extern "C" fn supervisor_mode_entry() {
embedded_alloc::init!(HEAP, HEAP_SIZE); embedded_alloc::init!(HEAP, HEAP_SIZE);
init_log().unwrap(); init_log().unwrap();
Vga::init(); Vga::init();
FILE_SYSTEM.init();
scheduler_init(); scheduler_init();
} }
@@ -65,16 +61,7 @@ pub extern "C" fn supervisor_mode_entry() {
create_process(&test, "proc1"); create_process(&test, "proc1");
create_process(&proc2, "proc2"); create_process(&proc2, "proc2");
let fs = Fat32FileSystem::new(Disk::new(1024 * 1024 * 16)).unwrap(); create_process_from_file("/usr/bin/test_pic");
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

@@ -1,9 +1,12 @@
use core::{arch::riscv64::wfi, time::Duration}; use core::time::Duration;
use alloc::{format, string::String}; use alloc::{boxed::Box, format, string::String, vec::Vec};
use bffs::{io::Read, path::Path};
use shared::syscall::exit;
use crate::{ use crate::{
scheduler::{ACTIVE_PID, PROCESS_COUNT, PROCESS_TABLE}, fs::FILE_SYSTEM,
scheduler::{scheduler_without_ret, ACTIVE_PID, PROCESS_COUNT, PROCESS_TABLE},
time::elapsed_time_since_startup, time::elapsed_time_since_startup,
}; };
@@ -54,6 +57,21 @@ impl core::fmt::Debug for Process {
} }
} }
pub fn create_process_from_file<'a, T: Into<Path<'a>>>(path: T) -> i64 {
let path = path.into();
let name = path.as_str();
let mut bin = FILE_SYSTEM.open_file(path).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()>(Vec::leak(content).as_ptr()) };
let test = Box::leak(Box::new(move || {
test();
}));
create_process(test, name)
}
pub fn create_process<T: Into<String>, F: Fn()>(code: &'static F, 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 }
@@ -82,27 +100,21 @@ pub fn create_process<T: Into<String>, F: Fn()>(code: &'static F, name: T) -> i6
extern "C" fn process_launcher(code: *const &dyn Fn()) { extern "C" fn process_launcher(code: *const &dyn Fn()) {
unsafe { (*code)() }; unsafe { (*code)() };
terminate_process(); // User code didn't exit before the end of its execution, so we call the exit syscall ourselves
exit();
} }
fn terminate_process() { pub fn exit_process(interrupt_context: &mut *mut ExecutionContext) {
unsafe { unsafe {
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Dead; PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Dead;
} }
loop {} scheduler_without_ret(interrupt_context)
// unsafe {
// wfi();
// }
// scheduler();
} }
pub fn sleep(duration: Duration) { pub fn sleep(duration: Duration, interrupt_context: &mut *mut ExecutionContext) {
unsafe { unsafe {
PROCESS_TABLE[ACTIVE_PID].wake_time = elapsed_time_since_startup() + duration; PROCESS_TABLE[ACTIVE_PID].wake_time = elapsed_time_since_startup() + duration;
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Asleep; PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Asleep;
} }
unsafe { scheduler_without_ret(interrupt_context)
wfi();
}
// scheduler();
} }

View File

@@ -57,11 +57,11 @@ pub fn scheduler_init() {
} }
} }
pub fn scheduler(interrupt_state: ExecutionContext) -> *const ExecutionContext { pub fn scheduler_without_ret(interrupt_state: &mut *mut ExecutionContext) {
// info!("scheduler"); // info!("scheduler");
unsafe { unsafe {
let prev_pid = ACTIVE_PID; let prev_pid = ACTIVE_PID;
PROCESS_TABLE[prev_pid].ctx = interrupt_state; PROCESS_TABLE[prev_pid].ctx = **interrupt_state;
if PROCESS_TABLE[prev_pid].state == ProcessState::Active { if PROCESS_TABLE[prev_pid].state == ProcessState::Active {
PROCESS_TABLE[prev_pid].state = ProcessState::Activable; PROCESS_TABLE[prev_pid].state = ProcessState::Activable;
@@ -80,6 +80,6 @@ pub fn scheduler(interrupt_state: ExecutionContext) -> *const ExecutionContext {
} }
PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Active; PROCESS_TABLE[ACTIVE_PID].state = ProcessState::Active;
&raw const PROCESS_TABLE[ACTIVE_PID].ctx *interrupt_state = &raw mut PROCESS_TABLE[ACTIVE_PID].ctx
} }
} }

View File

@@ -1,13 +0,0 @@
use core::str;
use log::info;
const DISK_ADDR: usize = 0x9000_0000;
pub struct MemoryDisk {}
impl MemoryDisk {
pub fn test() {
let test = unsafe { str::from_raw_parts(DISK_ADDR as *const u8, 13) };
info!("{}", test);
}
}

View File

@@ -1,15 +1,9 @@
use core::time::Duration; use core::time::Duration;
use alloc::vec::Vec; use shared::syscall::{sleep, write_int_temp, write_string_temp};
use bffs::{io::Read, Fat32FileSystem};
use crate::{
fs::Disk,
syscall::{sleep, write_int_temp, write_string_temp},
};
#[repr(align(32))] #[repr(align(32))]
struct Alignement([u8; 157]); struct Alignement([u8; include_bytes!("../user/test_pic/test_pic.mem").len()]);
static PROG: Alignement = Alignement(*include_bytes!("../user/test_pic/test_pic.mem")); static PROG: Alignement = Alignement(*include_bytes!("../user/test_pic/test_pic.mem"));

View File

@@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2024" edition = "2024"
[dependencies] [dependencies]
os-std = { path = "../../crates/os-std" }

View File

@@ -1,3 +0,0 @@
fn main() {
println!("cargo::rustc-link-arg=-Tilm.ld");
}

View File

@@ -1,21 +1,11 @@
#![no_std] #![no_std]
#![no_main] #![no_main]
os_std::custom_std_setup! {}
#[panic_handler] use os_std::syscall::write_string_temp;
fn panic(_panic_info: &core::panic::PanicInfo) -> ! {
loop {}
}
#[unsafe(no_mangle)] fn main() {
pub extern "C" fn entry() { write_string_temp(
let test = "Hello from PIC program loaded dynamically"; "Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls !",
unsafe { );
core::arch::asm!(
"ecall",
in("a0") 999,
in("a1") test.as_ptr(),
in("a2") test.len(),
clobber_abi("system")
);
}
} }