diff --git a/Cargo.toml b/Cargo.toml index 434ef5f..3f4bd62 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,11 @@ edition = "2018" [[example]] name = "hwa" -path = "example/hwa.rs" +path = "examples/hwa.rs" + +[[example]] +name = "con" +path = "examples/con.rs" [profile.release] opt-level = "z" diff --git a/Makefile.toml b/Makefile.toml index 7804c41..92ccf42 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -15,7 +15,7 @@ args = ["clean"] command = "cargo" args = ["build", "@@remove-empty(RELEASE_FLAG)"] -[tasks.hwa] +[tasks.example] command = "cargo" -args = ["objcopy", "@@remove-empty(RELEASE_FLAG)", "--example", "hwa", "--", "-O", "binary", "--strip-all", "rust.kex"] +args = ["objcopy", "@@remove-empty(RELEASE_FLAG)", "--example", "${@}", "--", "-O", "binary", "--strip-all", "${@}.kex"] #install_crate = { crate_name = "cargo-binutils", binary = "rust-objcopy", test_arg = ["--help"] } diff --git a/examples/con.rs b/examples/con.rs new file mode 100644 index 0000000..9018e05 --- /dev/null +++ b/examples/con.rs @@ -0,0 +1,20 @@ +#![no_std] +#![no_main] + +use cstr_core::cstr; +use kos::{dll::Console, threads::exit}; + +extern crate alloc; + +#[no_mangle] +pub fn kol_main() { + let header = cstr!("Rust!"); + let string = "Hi from Rust!"; + + let con_lib = Console::import(None).unwrap(); + con_lib.init(u32::MAX, u32::MAX, u32::MAX, u32::MAX, header); + con_lib.write_string(string); + con_lib.exit(false); + + exit(); +} diff --git a/example/hwa.rs b/examples/hwa.rs similarity index 100% rename from example/hwa.rs rename to examples/hwa.rs diff --git a/link.x b/link.x index feef1c9..1a3cac8 100644 --- a/link.x +++ b/link.x @@ -1,6 +1,6 @@ PATH_SIZE = 1024; PARAMS_SIZE = 256; -STACK_SIZE = 1024*4; +STACK_SIZE = 1024*64; SECTIONS { hdr : { diff --git a/src/dll.rs b/src/dll.rs new file mode 100644 index 0000000..b449d97 --- /dev/null +++ b/src/dll.rs @@ -0,0 +1,46 @@ +use crate::sys; +use cstr_core::CStr; + +mod console; +pub use console::Console; + +pub struct DLL { + table: *const ImportTableEl, +} + +impl DLL { + pub fn load_dll(name: &CStr) -> Result { + unsafe { + let table = sys::load_dll(name.as_ptr() as *const u8); + if table as usize == 0 { + return Err("Library load error"); + } + + return Ok(DLL { + table: table as *const ImportTableEl, + }); + } + } + + pub fn get_func(&self, name: &CStr) -> Result<*const (), &str> { + unsafe { + let mut i = 0; + loop { + let el = self.table.add(i); + if el as usize == 0 { + return Err("Function not found"); + } + let cur_name = CStr::from_ptr((*el).func_name as *const i8); + if cur_name == name { + return Ok((*el).func_addr as *const ()); + } + i += 1; + } + } + } +} +#[repr(C)] // Avoid random field order +struct ImportTableEl { + pub func_name: *const u8, + pub func_addr: fn(), +} diff --git a/src/dll/console.rs b/src/dll/console.rs new file mode 100644 index 0000000..7719af6 --- /dev/null +++ b/src/dll/console.rs @@ -0,0 +1,40 @@ +use crate::dll::DLL; +use core::mem::transmute; +use cstr_core::cstr; +use cstr_core::CStr; + +pub struct Console { + con_init: extern "stdcall" fn(u32, u32, u32, u32, *const u8), + con_write_string: extern "stdcall" fn(*const u8, u32), + con_exit: extern "stdcall" fn(bool), +} + +impl Console { + pub fn import(path: Option<&CStr>) -> Result { + let lib = DLL::load_dll(path.unwrap_or(cstr!("/sys/lib/console.obj"))); + match lib { + Err(e) => return Err(e), + Ok(dll) => unsafe { + Ok(Console { + con_init: transmute(dll.get_func(cstr!("con_init")).ok().unwrap()), + con_write_string: transmute( + dll.get_func(cstr!("con_write_string")).ok().unwrap(), + ), + con_exit: transmute(dll.get_func(cstr!("con_exit")).ok().unwrap()), + }) + }, + } + } + + pub fn init(&self, x: u32, y: u32, width: u32, height: u32, title: &CStr) { + (self.con_init)(x, y, width, height, title.as_ptr() as *const u8); + } + + pub fn write_string(&self, text: &str) { + (self.con_write_string)(text.as_ptr(), text.len() as u32); + } + + pub fn exit(self, close_window: bool) { + (self.con_exit)(close_window); + } +} diff --git a/src/func_constants.inc b/src/func_constants.inc index 636d5ab..771dcef 100644 --- a/src/func_constants.inc +++ b/src/func_constants.inc @@ -18,3 +18,4 @@ SF_SYS_MISC = 68 SSF_HEAP_INIT = 11 SSF_MEM_ALLOC = 12 SSF_MEM_FREE = 13 + SSF_LOAD_DLL = 19 diff --git a/src/lib.rs b/src/lib.rs index fac55f0..296cdf8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,11 @@ mod modules; mod nanolibc; -pub mod sys; pub mod allocation; +pub mod dll; +pub mod sys; + pub use modules::*; #[macro_use] @@ -26,6 +28,8 @@ macro_rules! throw_new { macro_rules! panic { ($text:expr) => { debug_write(cstr_core::cstr!("Panic!\n" + $text + "\n")); - sys::exit(); + unsafe { + sys::exit(); + } }; } diff --git a/src/sys.rs b/src/sys.rs index 12fe67d..2a71f2e 100644 --- a/src/sys.rs +++ b/src/sys.rs @@ -55,4 +55,8 @@ extern "C" { // 68.13 #[link_name = "_free"] pub fn free(block: *const u8) -> bool; + + // 68.19 + #[link_name = "_load_dll"] + pub fn load_dll(name: *const u8) -> *const u32; } diff --git a/src/syscalls.S b/src/syscalls.S index 0ac2a77..79d4369 100644 --- a/src/syscalls.S +++ b/src/syscalls.S @@ -17,6 +17,7 @@ section '.text' public _alloc public _free public _get_lang + public _load_dll _exit: mov eax, SF_TERMINATE_PROCESS @@ -118,3 +119,9 @@ _get_lang: int 0x40 ret +_load_dll: + mov eax, SF_SYS_MISC + mov ebx, SSF_LOAD_DLL + mov ecx, [esp + 4 * 1] + int 0x40 + ret