rename syscall table from abi

This commit is contained in:
2025-11-18 13:37:50 -07:00
parent 9035ebc757
commit 49c11978d5
6 changed files with 69 additions and 67 deletions

View File

@@ -1,7 +1,7 @@
# PicoCalc OS (Rust) # PicoCalc OS (Rust)
A simple kernel and applications for the **Clockwork PicoCalc**, written in Rust. A simple kernel and applications for the **Clockwork PicoCalc**, written in Rust.
This project provides a minimal kernel, ABI, and user-space applications to experiment with OS development on constrained hardware. This project provides a minimal kernel, syscall table, and user-space applications to experiment with kernel development on constrained hardware.
## Status ## Status

View File

@@ -1,10 +1,12 @@
target := "thumbv8m.main-none-eabihf"
kernel-dev board: kernel-dev board:
cargo run --bin kernel --features {{board}} --features fps cargo run --bin kernel --features {{board}} --features fps
kernel-release-probe board: kernel-release-probe board:
cargo run --bin kernel --profile release --features {{board}} --features fps cargo run --bin kernel --profile release --features {{board}} --features fps
kernel-release board: kernel-release board:
cargo build --bin kernel --release --no-default-features --features {{board}} cargo build --bin kernel --release --no-default-features --features {{board}}
elf2uf2-rs -d target/thumbv8m.main-none-eabihf/release/kernel elf2uf2-rs -d target/{{target}}/release/kernel
binary-args := "RUSTFLAGS=\"-C link-arg=-pie -C relocation-model=pic\"" binary-args := "RUSTFLAGS=\"-C link-arg=-pie -C relocation-model=pic\""
@@ -42,7 +44,7 @@ userapps: cbindgen
just userapp wav_player just userapp wav_player
copy-userapp app: copy-userapp app:
cp ./target/thumbv8m.main-none-eabihf/release-binary/{{app}} /run/media/$(whoami)/PICOCALC/{{app}}.bin cp ./target/{{target}}/release-binary/{{app}} /run/media/$(whoami)/PICOCALC/{{app}}.bin
copy-userapps: copy-userapps:
#!/bin/bash #!/bin/bash

View File

@@ -1,8 +1,7 @@
use crate::{ use crate::{
abi,
storage::{File, SDCARD}, storage::{File, SDCARD},
syscalls,
}; };
use userlib_sys::{CallTable, EntryFn};
use alloc::{vec, vec::Vec}; use alloc::{vec, vec::Vec};
use bumpalo::Bump; use bumpalo::Bump;
use core::ptr; use core::ptr;
@@ -17,6 +16,7 @@ use goblin::{
elf32::{header, reloc::Rel, section_header::SectionHeader, sym::Sym}, elf32::{header, reloc::Rel, section_header::SectionHeader, sym::Sym},
}; };
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use userlib_sys::{EntryFn, SyscallTable};
const ELF32_HDR_SIZE: usize = 52; const ELF32_HDR_SIZE: usize = 52;
@@ -70,7 +70,7 @@ pub async unsafe fn load_binary(name: &ShortFileName) -> Option<(EntryFn, Bump)>
} }
} }
patch_abi(&elf_header, base.as_mut_ptr(), min_vaddr, &mut file).unwrap(); patch_syscalls(&elf_header, base.as_mut_ptr(), min_vaddr, &mut file).unwrap();
// entry pointer is base_ptr + (entry - min_vaddr) // entry pointer is base_ptr + (entry - min_vaddr)
let entry_ptr: EntryFn = unsafe { let entry_ptr: EntryFn = unsafe {
@@ -150,7 +150,7 @@ fn apply_relocations(
Ok(()) Ok(())
} }
fn patch_abi( fn patch_syscalls(
elf_header: &Header, elf_header: &Header,
base: *mut u8, base: *mut u8,
min_vaddr: u32, min_vaddr: u32,
@@ -188,27 +188,27 @@ fn patch_abi(
} }
let symbol_name = core::str::from_utf8(&name).unwrap(); let symbol_name = core::str::from_utf8(&name).unwrap();
if symbol_name == "CALL_ABI_TABLE" { if symbol_name == stringify!(SYS_CALL_TABLE) {
let table_base = let table_base =
unsafe { base.add((sym.st_value as usize) - min_vaddr as usize) } unsafe { base.add((sym.st_value as usize) - min_vaddr as usize) }
as *mut usize; as *mut usize;
for (idx, call) in CallTable::iter().enumerate() { for (idx, call) in SyscallTable::iter().enumerate() {
let ptr = match call { let ptr = match call {
CallTable::Alloc => abi::alloc as usize, SyscallTable::Alloc => syscalls::alloc as usize,
CallTable::Dealloc => abi::dealloc as usize, SyscallTable::Dealloc => syscalls::dealloc as usize,
CallTable::PrintString => abi::print as usize, SyscallTable::PrintString => syscalls::print as usize,
CallTable::SleepMs => abi::sleep as usize, SyscallTable::SleepMs => syscalls::sleep as usize,
CallTable::GetMs => abi::get_ms as usize, SyscallTable::GetMs => syscalls::get_ms as usize,
CallTable::DrawIter => abi::draw_iter as usize, SyscallTable::DrawIter => syscalls::draw_iter as usize,
CallTable::GetKey => abi::get_key as usize, SyscallTable::GetKey => syscalls::get_key as usize,
CallTable::GenRand => abi::gen_rand as usize, SyscallTable::GenRand => syscalls::gen_rand as usize,
CallTable::ListDir => abi::list_dir as usize, SyscallTable::ListDir => syscalls::list_dir as usize,
CallTable::ReadFile => abi::read_file as usize, SyscallTable::ReadFile => syscalls::read_file as usize,
CallTable::WriteFile => abi::write_file as usize, SyscallTable::WriteFile => syscalls::write_file as usize,
CallTable::FileLen => abi::file_len as usize, SyscallTable::FileLen => syscalls::file_len as usize,
CallTable::AudioBufferReady => abi::audio_buffer_ready as usize, SyscallTable::AudioBufferReady => syscalls::audio_buffer_ready as usize,
CallTable::SendAudioBuffer => abi::send_audio_buffer as usize, SyscallTable::SendAudioBuffer => syscalls::send_audio_buffer as usize,
}; };
unsafe { unsafe {
table_base.add(idx as usize).write(ptr); table_base.add(idx as usize).write(ptr);

View File

@@ -8,7 +8,6 @@
extern crate alloc; extern crate alloc;
mod abi;
mod audio; mod audio;
mod display; mod display;
mod elf; mod elf;
@@ -16,6 +15,7 @@ mod framebuffer;
mod peripherals; mod peripherals;
mod scsi; mod scsi;
mod storage; mod storage;
mod syscalls;
mod ui; mod ui;
mod usb; mod usb;
mod utils; mod utils;
@@ -31,12 +31,12 @@ mod psram;
use crate::{heap::HEAP, heap::init_qmi_psram_heap, psram::init_psram, psram::init_psram_qmi}; use crate::{heap::HEAP, heap::init_qmi_psram_heap, psram::init_psram, psram::init_psram_qmi};
use crate::{ use crate::{
abi::{KEY_CACHE, MS_SINCE_LAUNCH},
audio::audio_handler, audio::audio_handler,
display::{FRAMEBUFFER, display_handler, init_display}, display::{FRAMEBUFFER, display_handler, init_display},
peripherals::{conf_peripherals, keyboard::read_keyboard_fifo}, peripherals::{conf_peripherals, keyboard::read_keyboard_fifo},
scsi::MSC_SHUTDOWN, scsi::MSC_SHUTDOWN,
storage::{SDCARD, SdCard}, storage::{SDCARD, SdCard},
syscalls::{KEY_CACHE, MS_SINCE_LAUNCH},
ui::{SELECTIONS, clear_selection, ui_handler}, ui::{SELECTIONS, clear_selection, ui_handler},
}; };
use bumpalo::Bump; use bumpalo::Bump;

View File

@@ -1,14 +1,14 @@
use alloc::{string::ToString, vec::Vec}; use alloc::{string::ToString, vec::Vec};
use core::{ffi::c_char, ptr, sync::atomic::Ordering}; use core::{ffi::c_char, ptr, sync::atomic::Ordering};
use embassy_rp::clocks::{clk_sys_freq, RoscRng}; use embassy_rp::clocks::{RoscRng, clk_sys_freq};
use embassy_time::Instant; use embassy_time::Instant;
use embedded_graphics::draw_target::DrawTarget; use embedded_graphics::draw_target::DrawTarget;
use embedded_sdmmc::LfnBuffer; use embedded_sdmmc::LfnBuffer;
use heapless::spsc::Queue; use heapless::spsc::Queue;
use userlib_sys::{ use userlib_sys::{
keyboard::*, AllocAbi, AudioBufferReady, CLayout, CPixel, DeallocAbi, DrawIterAbi, FileLen, AUDIO_BUFFER_SAMPLES, Alloc, AudioBufferReady, CLayout, CPixel, Dealloc, DrawIter, FileLen,
GenRand, GetMsAbi, ListDir, PrintAbi, ReadFile, RngRequest, SendAudioBuffer, SleepMsAbi, GenRand, GetMs, ListDir, Print, ReadFile, RngRequest, SendAudioBuffer, SleepMs, WriteFile,
WriteFile, AUDIO_BUFFER_SAMPLES, keyboard::*,
}; };
#[cfg(feature = "psram")] #[cfg(feature = "psram")]
@@ -24,7 +24,7 @@ use crate::{
storage::{Dir, File, SDCARD}, storage::{Dir, File, SDCARD},
}; };
const _: AllocAbi = alloc; const _: Alloc = alloc;
pub extern "C" fn alloc(layout: CLayout) -> *mut u8 { pub extern "C" fn alloc(layout: CLayout) -> *mut u8 {
// SAFETY: caller guarantees layout is valid // SAFETY: caller guarantees layout is valid
unsafe { unsafe {
@@ -40,7 +40,7 @@ pub extern "C" fn alloc(layout: CLayout) -> *mut u8 {
} }
} }
const _: DeallocAbi = dealloc; const _: Dealloc = dealloc;
pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) { pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) {
// SAFETY: caller guarantees ptr and layout are valid // SAFETY: caller guarantees ptr and layout are valid
#[cfg(feature = "psram")] #[cfg(feature = "psram")]
@@ -54,7 +54,7 @@ pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) {
} }
} }
const _: PrintAbi = print; const _: Print = print;
pub extern "C" fn print(ptr: *const u8, len: usize) { pub extern "C" fn print(ptr: *const u8, len: usize) {
// SAFETY: caller guarantees `ptr` is valid for `len` bytes // SAFETY: caller guarantees `ptr` is valid for `len` bytes
let slice = unsafe { core::slice::from_raw_parts(ptr, len) }; let slice = unsafe { core::slice::from_raw_parts(ptr, len) };
@@ -68,7 +68,7 @@ pub extern "C" fn print(ptr: *const u8, len: usize) {
} }
} }
const _: SleepMsAbi = sleep; const _: SleepMs = sleep;
pub extern "C" fn sleep(ms: u64) { pub extern "C" fn sleep(ms: u64) {
let cycles_per_ms = clk_sys_freq() / 1000; let cycles_per_ms = clk_sys_freq() / 1000;
let total_cycles = ms * cycles_per_ms as u64; let total_cycles = ms * cycles_per_ms as u64;
@@ -80,14 +80,14 @@ pub extern "C" fn sleep(ms: u64) {
pub static mut MS_SINCE_LAUNCH: Option<Instant> = None; pub static mut MS_SINCE_LAUNCH: Option<Instant> = None;
const _: GetMsAbi = get_ms; const _: GetMs = get_ms;
pub extern "C" fn get_ms() -> u64 { pub extern "C" fn get_ms() -> u64 {
Instant::now() Instant::now()
.duration_since(unsafe { MS_SINCE_LAUNCH.unwrap() }) .duration_since(unsafe { MS_SINCE_LAUNCH.unwrap() })
.as_millis() .as_millis()
} }
const _: DrawIterAbi = draw_iter; const _: DrawIter = draw_iter;
pub extern "C" fn draw_iter(cpixels: *const CPixel, len: usize) { pub extern "C" fn draw_iter(cpixels: *const CPixel, len: usize) {
// SAFETY: caller guarantees `ptr` is valid for `len` bytes // SAFETY: caller guarantees `ptr` is valid for `len` bytes
let cpixels = unsafe { core::slice::from_raw_parts(cpixels, len) }; let cpixels = unsafe { core::slice::from_raw_parts(cpixels, len) };
@@ -101,7 +101,7 @@ pub extern "C" fn draw_iter(cpixels: *const CPixel, len: usize) {
pub static mut KEY_CACHE: Queue<KeyEvent, 32> = Queue::new(); pub static mut KEY_CACHE: Queue<KeyEvent, 32> = Queue::new();
const _: GetKeyAbi = get_key; const _: GetKey = get_key;
pub extern "C" fn get_key() -> KeyEventC { pub extern "C" fn get_key() -> KeyEventC {
if let Some(event) = unsafe { KEY_CACHE.dequeue() } { if let Some(event) = unsafe { KEY_CACHE.dequeue() } {
event.into() event.into()

View File

@@ -12,12 +12,12 @@ use strum::{EnumCount, EnumIter};
pub type EntryFn = fn(); pub type EntryFn = fn();
pub const ABI_CALL_TABLE_COUNT: usize = 14; pub const SYS_CALL_TABLE_COUNT: usize = 14;
const _: () = assert!(ABI_CALL_TABLE_COUNT == CallTable::COUNT); const _: () = assert!(SYS_CALL_TABLE_COUNT == SyscallTable::COUNT);
#[derive(Clone, Copy, EnumIter, EnumCount)] #[derive(Clone, Copy, EnumIter, EnumCount)]
#[repr(u8)] #[repr(u8)]
pub enum CallTable { pub enum SyscallTable {
Alloc = 0, Alloc = 0,
Dealloc = 1, Dealloc = 1,
PrintString = 2, PrintString = 2,
@@ -36,7 +36,7 @@ pub enum CallTable {
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
#[unsafe(link_section = ".syscall_table")] #[unsafe(link_section = ".syscall_table")]
pub static mut CALL_ABI_TABLE: [usize; ABI_CALL_TABLE_COUNT] = [0; ABI_CALL_TABLE_COUNT]; pub static mut SYS_CALL_TABLE: [usize; SYS_CALL_TABLE_COUNT] = [0; SYS_CALL_TABLE_COUNT];
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
#[repr(C)] #[repr(C)]
@@ -62,46 +62,46 @@ impl From<Layout> for CLayout {
} }
} }
pub type AllocAbi = extern "C" fn(layout: CLayout) -> *mut u8; pub type Alloc = extern "C" fn(layout: CLayout) -> *mut u8;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn alloc(layout: CLayout) -> *mut u8 { pub extern "C" fn alloc(layout: CLayout) -> *mut u8 {
let f: AllocAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::Alloc as usize]) }; let f: Alloc = unsafe { core::mem::transmute(SYS_CALL_TABLE[SyscallTable::Alloc as usize]) };
f(layout) f(layout)
} }
pub type DeallocAbi = extern "C" fn(ptr: *mut u8, layout: CLayout); pub type Dealloc = extern "C" fn(ptr: *mut u8, layout: CLayout);
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) { pub extern "C" fn dealloc(ptr: *mut u8, layout: CLayout) {
let f: DeallocAbi = let f: Dealloc =
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::Dealloc as usize]) }; unsafe { core::mem::transmute(SYS_CALL_TABLE[SyscallTable::Dealloc as usize]) };
f(ptr, layout) f(ptr, layout)
} }
pub type PrintAbi = extern "C" fn(ptr: *const u8, len: usize); pub type Print = extern "C" fn(ptr: *const u8, len: usize);
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn print(ptr: *const u8, len: usize) { pub extern "C" fn print(ptr: *const u8, len: usize) {
let f: PrintAbi = let f: Print =
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::PrintString as usize]) }; unsafe { core::mem::transmute(SYS_CALL_TABLE[SyscallTable::PrintString as usize]) };
f(ptr, len); f(ptr, len);
} }
pub type SleepMsAbi = extern "C" fn(ms: u64); pub type SleepMs = extern "C" fn(ms: u64);
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn sleep(ms: u64) { pub extern "C" fn sleep(ms: u64) {
let f: SleepMsAbi = let f: SleepMs =
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::SleepMs as usize]) }; unsafe { core::mem::transmute(SYS_CALL_TABLE[SyscallTable::SleepMs as usize]) };
f(ms); f(ms);
} }
pub type GetMsAbi = extern "C" fn() -> u64; pub type GetMs = extern "C" fn() -> u64;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn get_ms() -> u64 { pub extern "C" fn get_ms() -> u64 {
let f: GetMsAbi = unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::GetMs as usize]) }; let f: GetMs = unsafe { core::mem::transmute(SYS_CALL_TABLE[SyscallTable::GetMs as usize]) };
f() f()
} }
@@ -139,17 +139,17 @@ impl Into<Pixel<Rgb565>> for CPixel {
} }
} }
pub type DrawIterAbi = extern "C" fn(ptr: *const CPixel, len: usize); pub type DrawIter = extern "C" fn(ptr: *const CPixel, len: usize);
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn draw_iter(ptr: *const CPixel, len: usize) { pub extern "C" fn draw_iter(ptr: *const CPixel, len: usize) {
let f: DrawIterAbi = let f: DrawIter =
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::DrawIter as usize]) }; unsafe { core::mem::transmute(SYS_CALL_TABLE[SyscallTable::DrawIter as usize]) };
f(ptr, len); f(ptr, len);
} }
pub mod keyboard { pub mod keyboard {
use crate::{CALL_ABI_TABLE, CallTable}; use crate::{SYS_CALL_TABLE, SyscallTable};
bitflags::bitflags! { bitflags::bitflags! {
#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)] #[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
@@ -367,12 +367,12 @@ pub mod keyboard {
} }
} }
pub type GetKeyAbi = extern "C" fn() -> KeyEventC; pub type GetKey = extern "C" fn() -> KeyEventC;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn get_key() -> KeyEventC { pub extern "C" fn get_key() -> KeyEventC {
let f: GetKeyAbi = let f: GetKey =
unsafe { core::mem::transmute(CALL_ABI_TABLE[CallTable::GetKey as usize]) }; unsafe { core::mem::transmute(SYS_CALL_TABLE[SyscallTable::GetKey as usize]) };
f() f()
} }
} }
@@ -389,7 +389,7 @@ pub type GenRand = extern "C" fn(req: &mut RngRequest);
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn gen_rand(req: &mut RngRequest) { pub extern "C" fn gen_rand(req: &mut RngRequest) {
unsafe { unsafe {
let ptr = CALL_ABI_TABLE[CallTable::GenRand as usize]; let ptr = SYS_CALL_TABLE[SyscallTable::GenRand as usize];
let f: GenRand = core::mem::transmute(ptr); let f: GenRand = core::mem::transmute(ptr);
f(req) f(req)
} }
@@ -412,7 +412,7 @@ pub extern "C" fn list_dir(
max_entry_str_len: usize, max_entry_str_len: usize,
) -> usize { ) -> usize {
unsafe { unsafe {
let ptr = CALL_ABI_TABLE[CallTable::ListDir as usize]; let ptr = SYS_CALL_TABLE[SyscallTable::ListDir as usize];
let f: ListDir = core::mem::transmute(ptr); let f: ListDir = core::mem::transmute(ptr);
f(str, len, entries, entry_count, max_entry_str_len) f(str, len, entries, entry_count, max_entry_str_len)
} }
@@ -435,7 +435,7 @@ pub extern "C" fn read_file(
buf_len: usize, buf_len: usize,
) -> usize { ) -> usize {
unsafe { unsafe {
let ptr = CALL_ABI_TABLE[CallTable::ReadFile as usize]; let ptr = SYS_CALL_TABLE[SyscallTable::ReadFile as usize];
let f: ReadFile = core::mem::transmute(ptr); let f: ReadFile = core::mem::transmute(ptr);
f(str, len, read_from, buf, buf_len) f(str, len, read_from, buf, buf_len)
} }
@@ -453,7 +453,7 @@ pub extern "C" fn write_file(
buf_len: usize, buf_len: usize,
) { ) {
unsafe { unsafe {
let ptr = CALL_ABI_TABLE[CallTable::WriteFile as usize]; let ptr = SYS_CALL_TABLE[SyscallTable::WriteFile as usize];
let f: WriteFile = core::mem::transmute(ptr); let f: WriteFile = core::mem::transmute(ptr);
f(str, len, write_from, buf, buf_len) f(str, len, write_from, buf, buf_len)
} }
@@ -464,7 +464,7 @@ pub type FileLen = extern "C" fn(str: *const u8, len: usize) -> usize;
#[unsafe(no_mangle)] #[unsafe(no_mangle)]
pub extern "C" fn file_len(str: *const u8, len: usize) -> usize { pub extern "C" fn file_len(str: *const u8, len: usize) -> usize {
unsafe { unsafe {
let ptr = CALL_ABI_TABLE[CallTable::FileLen as usize]; let ptr = SYS_CALL_TABLE[SyscallTable::FileLen as usize];
let f: FileLen = core::mem::transmute(ptr); let f: FileLen = core::mem::transmute(ptr);
f(str, len) f(str, len)
} }
@@ -475,7 +475,7 @@ pub type AudioBufferReady = extern "C" fn() -> bool;
#[allow(unused)] #[allow(unused)]
pub fn audio_buffer_ready() -> bool { pub fn audio_buffer_ready() -> bool {
unsafe { unsafe {
let ptr = CALL_ABI_TABLE[CallTable::AudioBufferReady as usize]; let ptr = SYS_CALL_TABLE[SyscallTable::AudioBufferReady as usize];
let f: AudioBufferReady = core::mem::transmute(ptr); let f: AudioBufferReady = core::mem::transmute(ptr);
f() f()
} }
@@ -489,7 +489,7 @@ pub type SendAudioBuffer = extern "C" fn(ptr: *const u8, len: usize);
#[allow(unused)] #[allow(unused)]
pub fn send_audio_buffer(buf: *const u8, len: usize) { pub fn send_audio_buffer(buf: *const u8, len: usize) {
unsafe { unsafe {
let ptr = CALL_ABI_TABLE[CallTable::SendAudioBuffer as usize]; let ptr = SYS_CALL_TABLE[SyscallTable::SendAudioBuffer as usize];
let f: SendAudioBuffer = core::mem::transmute(ptr); let f: SendAudioBuffer = core::mem::transmute(ptr);
f(buf, len) f(buf, len)
} }