diff --git a/.gitignore b/.gitignore index f2c4331..a9af418 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .cache +.vscode build* .venv initrd/image.cpio diff --git a/CMakeLists.txt b/CMakeLists.txt index aa5503b..fd48f54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,7 @@ set(SYSTEM_SERVICES init debug termosh + rtest ) set(VOLUME_ROOT "${CMAKE_BINARY_DIR}/StartupVolume") @@ -70,7 +71,7 @@ endif() if(QEMU_EXE) add_custom_target(run COMMAND ${QEMU_EXE} - -enable-kvm + #-enable-kvm -bios ${OVMF_PATH} -drive file=${IMG_FILE},format=raw -vga std diff --git a/Runtime/CMakeLists.txt b/Runtime/CMakeLists.txt index 1408b96..7c85af2 100644 --- a/Runtime/CMakeLists.txt +++ b/Runtime/CMakeLists.txt @@ -9,5 +9,6 @@ message(STATUS "Building termOS's userspace") add_subdirectory(libterm) add_subdirectory(init) +add_subdirectory(rust) add_subdirectory(debug) add_subdirectory(termosh) \ No newline at end of file diff --git a/Runtime/debug/src/main.c b/Runtime/debug/src/main.c index 0f51246..0dff34e 100644 --- a/Runtime/debug/src/main.c +++ b/Runtime/debug/src/main.c @@ -1,12 +1,5 @@ #include int main() { - for (int i = 0; i < 100; i++) { - UInt64 pid = ProcessSpawn("/System/CoreServices/debug"); - if (pid < 0) { - ConsolePrint("[PIDSPAMMER] Error %d\n", pid); - } else { - ConsolePrint("[PIDSPAMMER] %d spawned\n", pid); - } - } + ConsolePrint("Test test test \n Meow meow meow \n"); } \ No newline at end of file diff --git a/Runtime/libterm/inc/Console.h b/Runtime/libterm/inc/Console.h index e104735..09afb72 100644 --- a/Runtime/libterm/inc/Console.h +++ b/Runtime/libterm/inc/Console.h @@ -5,10 +5,13 @@ #include enum { + kConsoleInput = 0, + kConsoleOutput = 1, kConsoleEOF = -1, kConsoleDefaultBufferSize = 1024 }; +Int32 ConsolePrintString(const char* string); Int32 ConsolePrint(const char* format, ...); Int32 StringFormat(char* destination, UInt64 size, const char* format, ...); Int32 ConsoleGetCharacter(); diff --git a/Runtime/libterm/src/Console.c b/Runtime/libterm/src/Console.c index a7054e4..2ace96e 100644 --- a/Runtime/libterm/src/Console.c +++ b/Runtime/libterm/src/Console.c @@ -9,7 +9,7 @@ extern UInt64 OSServiceIORead(UInt64 fileDescriptor, void* buffer, UInt64 length extern UInt64 OSServiceIOWrite(UInt64 fileDescriptor, const void* buffer, UInt64 length); static void sConsoleWriteCharacter(char character) { - OSServiceIOWrite(1, &character, 1); + OSServiceIOWrite(kConsoleOutput, &character, 1); } static inline void sConsoleBufferAdd(char* string, UInt64 size, UInt64* written, char character) { @@ -105,6 +105,10 @@ Int32 StringFormat(char* destination, usize size, const char* format, ...) { return returnValue; } +Int32 ConsolePrintString(const char* string) { + return OSServiceIOWrite(kConsoleOutput, string, StringGetLength(string)); +} + Int32 ConsolePrint(const char *format, ...) { char buffer[kConsoleDefaultBufferSize]; va_list args; @@ -114,14 +118,14 @@ Int32 ConsolePrint(const char *format, ...) { va_end(args); UInt64 writeLength = ((UInt64)length < sizeof(buffer)) ? length : (sizeof(buffer) - 1); - OSServiceIOWrite(1, buffer, writeLength); + OSServiceIOWrite(kConsoleOutput, buffer, writeLength); return (int)writeLength; } Int32 ConsoleGetCharacter() { char character; - UInt64 serviceCallResult = OSServiceIORead(0, &character, 1); + UInt64 serviceCallResult = OSServiceIORead(kConsoleInput, &character, 1); if (serviceCallResult <= 0) return kConsoleEOF; return (int)(unsigned char)character; } diff --git a/Runtime/rust/.cargo/config.toml b/Runtime/rust/.cargo/config.toml new file mode 100644 index 0000000..a4c35ca --- /dev/null +++ b/Runtime/rust/.cargo/config.toml @@ -0,0 +1,9 @@ +[build] +target = "x86_64-unknown-none" + +[target.x86_64-unknown-none] +rustflags = [ + "-C", "code-model=small", + "-C", "relocation-model=static", + "-C", "no-redzone=y", +] \ No newline at end of file diff --git a/Runtime/rust/CMakeLists.txt b/Runtime/rust/CMakeLists.txt new file mode 100644 index 0000000..c19fe16 --- /dev/null +++ b/Runtime/rust/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.16) +project(rustApps LANGUAGES C ASM_NASM) + +function(add_rust_app NAME) + set(RUST_LIB_FILE "${CMAKE_CURRENT_SOURCE_DIR}/target/x86_64-unknown-none/release/lib${NAME}.a") + + add_custom_target(cargo_build_${NAME} ALL + COMMAND cargo build --package ${NAME} --release + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + BYPRODUCTS ${RUST_LIB_FILE} + COMMENT "Cargo: Building bare-metal Rust app '${NAME}'..." + ) + + add_library(rust_lib_${NAME} STATIC IMPORTED) + set_target_properties(rust_lib_${NAME} PROPERTIES IMPORTED_LOCATION ${RUST_LIB_FILE}) + add_dependencies(rust_lib_${NAME} cargo_build_${NAME}) + add_executable(${NAME} $) + set_target_properties(${NAME} PROPERTIES LINKER_LANGUAGE C) + target_link_libraries(${NAME} PRIVATE rust_lib_${NAME} term) + + target_link_options(${NAME} PRIVATE + -T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld + -nostdlib + -static + -mno-red-zone + ) + + set(ELF2HOT_DIR "${CMAKE_SOURCE_DIR}/tools/elf2hot") + set(STARTUP_VOLUME_DIR "${CMAKE_BINARY_DIR}/StartupVolume/System/CoreServices") + file(MAKE_DIRECTORY "${STARTUP_VOLUME_DIR}") + + set(FINAL_HOT_PATH "${STARTUP_VOLUME_DIR}/${NAME}") + + add_custom_command(TARGET ${NAME} POST_BUILD + COMMAND cargo run --release --quiet -- $ ${FINAL_HOT_PATH} + WORKING_DIRECTORY ${ELF2HOT_DIR} + COMMENT "elf2hot: Converting ${NAME} to HOT! format..." + VERBATIM + ) +endfunction() + +add_rust_app(rtest) \ No newline at end of file diff --git a/Runtime/rust/Cargo.lock b/Runtime/rust/Cargo.lock new file mode 100644 index 0000000..5d0533a --- /dev/null +++ b/Runtime/rust/Cargo.lock @@ -0,0 +1,14 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "rterm" +version = "0.1.0" + +[[package]] +name = "rtest" +version = "0.1.0" +dependencies = [ + "rterm", +] diff --git a/Runtime/rust/Cargo.toml b/Runtime/rust/Cargo.toml new file mode 100644 index 0000000..0dda78d --- /dev/null +++ b/Runtime/rust/Cargo.toml @@ -0,0 +1,4 @@ +[workspace] +members = ["rterm", "apps/rtest"] + +resolver = "2" diff --git a/Runtime/rust/apps/rtest/Cargo.toml b/Runtime/rust/apps/rtest/Cargo.toml new file mode 100644 index 0000000..dbd8979 --- /dev/null +++ b/Runtime/rust/apps/rtest/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "rtest" +version = "0.1.0" +edition = "2024" + +[lib] +crate-type = ["staticlib"] + +[dependencies] +rterm = { path = "../../rterm" } \ No newline at end of file diff --git a/Runtime/rust/apps/rtest/src/lib.rs b/Runtime/rust/apps/rtest/src/lib.rs new file mode 100644 index 0000000..b89f75a --- /dev/null +++ b/Runtime/rust/apps/rtest/src/lib.rs @@ -0,0 +1,19 @@ +#![no_std] + +extern crate alloc; +use alloc::string::String; +use alloc::vec::Vec; + +extern crate rterm; + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn main() -> i32 { + let mut my_vec = Vec::new(); + my_vec.push(1); + my_vec.push(2); + + let text = String::from("Hello from zalupa!"); + rterm::print_str(&text); + + 0 +} diff --git a/Runtime/rust/linker.ld b/Runtime/rust/linker.ld new file mode 100644 index 0000000..718aab9 --- /dev/null +++ b/Runtime/rust/linker.ld @@ -0,0 +1,35 @@ +ENTRY(_start) + +SECTIONS +{ + . = 0x400000; + + .text : { + *(.text) + } + + .rodata : { + *(.rodata) + } + + .data : { + *(.data) + } + + .bss : { + *(.bss) + *(COMMON) + } + + /DISCARD/ : { + *(.note.gnu.build-id) + *(.note.GNU-stack) + *(.note.gnu.property) + *(.comment) + *(.interp) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.gnu.hash) + } +} \ No newline at end of file diff --git a/Runtime/rust/rterm/Cargo.toml b/Runtime/rust/rterm/Cargo.toml new file mode 100644 index 0000000..d654d5c --- /dev/null +++ b/Runtime/rust/rterm/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rterm" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/Runtime/rust/rterm/src/lib.rs b/Runtime/rust/rterm/src/lib.rs new file mode 100644 index 0000000..d32179a --- /dev/null +++ b/Runtime/rust/rterm/src/lib.rs @@ -0,0 +1,36 @@ +#![no_std] + +extern crate alloc; + +use core::panic::PanicInfo; +use core::alloc::{GlobalAlloc, Layout}; + +unsafe extern "C" { + fn MemoryAllocate(size: usize) -> *mut u8; + fn MemoryFree(ptr: *mut u8); + fn ConsolePrintString(s: *const u8); +} + +struct TermosAllocator; + +unsafe impl GlobalAlloc for TermosAllocator { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + MemoryAllocate(layout.size()) + } + + unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { + MemoryFree(ptr); + } +} + +#[global_allocator] +static ALLOCATOR: TermosAllocator = TermosAllocator; + +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} + +pub unsafe fn print_str(s: &str) { + ConsolePrintString(s.as_ptr()); +} \ No newline at end of file