From 1e899e2f97c0a45073d20306661c11a86263ecc8 Mon Sep 17 00:00:00 2001 From: csd4ni3l Date: Fri, 3 Apr 2026 11:28:31 +0200 Subject: [PATCH] Add a scheduler which just keeps of processes for now, and a with_process to interact with them. User space now has it's own address space and mapper which means we will be able to allocate memory for it. I added a bunch of functions as stubs into libxunil which are required for doomgeneric. --- kernel/src/arch/arch.rs | 8 +- kernel/src/arch/x86_64/elf.rs | 45 ++++--- kernel/src/arch/x86_64/heap.rs | 21 ++- kernel/src/arch/x86_64/init.rs | 3 +- kernel/src/arch/x86_64/paging.rs | 4 +- kernel/src/driver/syscall.rs | 8 +- kernel/src/main.rs | 2 + kernel/src/mm/address_space.rs | 66 ++++++++++ kernel/src/mm/mod.rs | 1 + kernel/src/task/context.rs | 0 kernel/src/task/mod.rs | 3 + kernel/src/task/process.rs | 32 +++++ kernel/src/task/scheduler.rs | 45 +++++++ kernel/src/userspace_stub.rs | 2 +- kernel/src/util.rs | 19 --- user/libxunil/.cargo/config.toml | 4 + user/libxunil/Cargo.lock | 46 +++++++ user/libxunil/Cargo.toml | 6 + user/libxunil/rust-toolchain.toml | 8 ++ user/libxunil/src/file.rs | 66 ++++++++++ user/libxunil/{ => src}/include/inttypes.h | 0 user/libxunil/{ => src}/include/stdio.h | 12 +- user/libxunil/{ => src}/include/stdlib.h | 0 user/libxunil/{ => src}/include/string.h | 0 user/libxunil/{ => src}/include/strings.h | 0 user/libxunil/src/lib.rs | 141 +++++++++++++++++++-- user/libxunil/src/mem.rs | 27 ++++ user/libxunil/to_implement.txt | 23 ++++ 28 files changed, 535 insertions(+), 57 deletions(-) create mode 100644 kernel/src/mm/address_space.rs create mode 100644 kernel/src/mm/mod.rs create mode 100644 kernel/src/task/context.rs create mode 100644 kernel/src/task/mod.rs create mode 100644 kernel/src/task/process.rs create mode 100644 kernel/src/task/scheduler.rs create mode 100644 user/libxunil/.cargo/config.toml create mode 100644 user/libxunil/rust-toolchain.toml create mode 100644 user/libxunil/src/file.rs rename user/libxunil/{ => src}/include/inttypes.h (100%) rename user/libxunil/{ => src}/include/stdio.h (85%) rename user/libxunil/{ => src}/include/stdlib.h (100%) rename user/libxunil/{ => src}/include/string.h (100%) rename user/libxunil/{ => src}/include/strings.h (100%) create mode 100644 user/libxunil/src/mem.rs diff --git a/kernel/src/arch/arch.rs b/kernel/src/arch/arch.rs index a1f1930..a117fd6 100644 --- a/kernel/src/arch/arch.rs +++ b/kernel/src/arch/arch.rs @@ -26,12 +26,8 @@ pub fn enter_usermode(user_rip: u64, user_rsp: u64) { } #[cfg(target_arch = "x86_64")] -pub fn run_elf( - entry_point: *const u8, - frame_allocator: &mut XunilFrameAllocator, - mapper: &mut OffsetPageTable, -) { - run_elf_x86_64(entry_point, frame_allocator, mapper); +pub fn run_elf(entry_point: *const u8, frame_allocator: &mut XunilFrameAllocator) { + run_elf_x86_64(entry_point, frame_allocator); } pub fn get_allocator<'a>() -> &'static impl GlobalAlloc { diff --git a/kernel/src/arch/x86_64/elf.rs b/kernel/src/arch/x86_64/elf.rs index b1a073f..e0230f4 100644 --- a/kernel/src/arch/x86_64/elf.rs +++ b/kernel/src/arch/x86_64/elf.rs @@ -6,13 +6,20 @@ use x86_64::{ }, }; -use crate::arch::x86_64::{paging::XunilFrameAllocator, usermode::enter_usermode_x86_64}; +use crate::{ + arch::x86_64::{paging::XunilFrameAllocator, usermode::enter_usermode_x86_64}, + task::{process::Process, scheduler::SCHEDULER}, +}; + +pub fn run_elf_x86_64(entry_point: *const u8, frame_allocator: &mut XunilFrameAllocator) { + let process_pid = SCHEDULER + .spawn_process(entry_point as u64, frame_allocator) + .unwrap(); + + SCHEDULER.with_process(process_pid, |process| { + process.address_space.use_address_space() + }); -pub fn run_elf_x86_64( - entry_point: *const u8, - frame_allocator: &mut XunilFrameAllocator, - mapper: &mut OffsetPageTable, -) { let stack_base: u64 = 0x0000_7fff_0000_0000; let page_count = 3; let page_size = 0x1000u64; @@ -26,17 +33,21 @@ pub fn run_elf_x86_64( let page = Page::::containing_address(virt_addr); unsafe { - mapper - .map_to( - page, - frame, - PageTableFlags::PRESENT - | PageTableFlags::WRITABLE - | PageTableFlags::USER_ACCESSIBLE, - frame_allocator, - ) - .unwrap() - .flush(); + SCHEDULER.with_process(process_pid, |process| { + process + .address_space + .mapper + .map_to( + page, + frame, + PageTableFlags::PRESENT + | PageTableFlags::WRITABLE + | PageTableFlags::USER_ACCESSIBLE, + frame_allocator, + ) + .unwrap() + .flush(); + }); } } diff --git a/kernel/src/arch/x86_64/heap.rs b/kernel/src/arch/x86_64/heap.rs index ade2197..67e9110 100644 --- a/kernel/src/arch/x86_64/heap.rs +++ b/kernel/src/arch/x86_64/heap.rs @@ -1,5 +1,5 @@ use crate::arch::x86_64::paging::XunilFrameAllocator; -use crate::util::{LinkedNode, Locked}; +use crate::util::Locked; use core::{ alloc::{GlobalAlloc, Layout}, ptr::null_mut, @@ -22,6 +22,25 @@ pub static ALLOCATOR: Locked = Locked::new(LinkedListAlloca pub const HEAP_START: usize = 0x_4444_4444_0000; pub const HEAP_SIZE: usize = 256 * 1024 * 1024; // 256 MiB +pub struct LinkedNode { + pub size: usize, + pub next: Option<&'static mut LinkedNode>, +} + +impl LinkedNode { + pub const fn new(size: usize) -> LinkedNode { + LinkedNode { size, next: None } + } + + pub fn start_addr(&self) -> usize { + self as *const Self as usize + } + + pub fn end_addr(&self) -> usize { + self.start_addr() + self.size + } +} + pub struct LinkedListAllocator { head: LinkedNode, } diff --git a/kernel/src/arch/x86_64/init.rs b/kernel/src/arch/x86_64/init.rs index 9298c1c..5c8dd90 100644 --- a/kernel/src/arch/x86_64/init.rs +++ b/kernel/src/arch/x86_64/init.rs @@ -28,7 +28,8 @@ pub fn memory_management_init<'a>( ) -> (OffsetPageTable<'static>, XunilFrameAllocator<'a>) { let physical_offset = VirtAddr::new(hhdm_response.offset()); let mapper = unsafe { initialize_paging(physical_offset) }; - let frame_allocator = XunilFrameAllocator::new(memory_map_response.entries()); + let frame_allocator = + XunilFrameAllocator::new(hhdm_response.offset(), memory_map_response.entries()); (mapper, frame_allocator) } diff --git a/kernel/src/arch/x86_64/paging.rs b/kernel/src/arch/x86_64/paging.rs index 02b2f1e..ea17fde 100644 --- a/kernel/src/arch/x86_64/paging.rs +++ b/kernel/src/arch/x86_64/paging.rs @@ -24,19 +24,21 @@ pub unsafe fn initialize_paging(physical_memory_offset: VirtAddr) -> OffsetPageT } pub struct XunilFrameAllocator<'a> { + pub hhdm_offset: u64, memory_map: &'a [&'a Entry], region_index: usize, region_offset: usize, } impl<'a> XunilFrameAllocator<'a> { - pub fn new(memory_map: &'a [&'a Entry]) -> Self { + pub fn new(hhdm_offset: u64, memory_map: &'a [&'a Entry]) -> Self { let region_index = memory_map .iter() .position(|region| region.entry_type == EntryType::USABLE) .unwrap(); Self { + hhdm_offset, memory_map, region_index, region_offset: 0, diff --git a/kernel/src/driver/syscall.rs b/kernel/src/driver/syscall.rs index 62fafc4..c784749 100644 --- a/kernel/src/driver/syscall.rs +++ b/kernel/src/driver/syscall.rs @@ -3,7 +3,11 @@ use core::{ ptr::null_mut, }; -use crate::{arch::arch::get_allocator, driver::graphics::framebuffer::with_framebuffer, println}; +use crate::{ + arch::arch::{get_allocator, infinite_idle}, + driver::graphics::framebuffer::with_framebuffer, + println, +}; const SYS_EXIT: usize = 1; const SYS_WRITE: usize = 60; @@ -63,7 +67,7 @@ pub unsafe extern "C" fn syscall_dispatch( SYS_EXIT => { println!("Program exit."); with_framebuffer(|fb| fb.swap()); - 0 + infinite_idle(); } _ => -38, // syscall not found } diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 98c395a..8e11d7a 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -13,6 +13,8 @@ use limine::request::{ }; pub mod arch; pub mod driver; +pub mod mm; +pub mod task; pub mod userspace_stub; pub mod util; diff --git a/kernel/src/mm/address_space.rs b/kernel/src/mm/address_space.rs new file mode 100644 index 0000000..c57cd92 --- /dev/null +++ b/kernel/src/mm/address_space.rs @@ -0,0 +1,66 @@ +use x86_64::{ + PhysAddr, VirtAddr, + registers::control::{Cr3, Cr3Flags}, + structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB}, +}; + +use crate::{arch::x86_64::paging::XunilFrameAllocator, driver::syscall::memset}; + +pub struct AddressSpace { + cr3_frame: PhysFrame, + user_stack_top: VirtAddr, + pub mapper: OffsetPageTable<'static>, + heap_base: VirtAddr, + heap_end: VirtAddr, +} +impl AddressSpace { + pub fn new(frame_allocator: &mut XunilFrameAllocator) -> Option { + let new_pml4 = frame_allocator.allocate_frame()?; + + unsafe { + let new_pml4_ptr = + (frame_allocator.hhdm_offset + new_pml4.start_address().as_u64()) as *mut u64; + core::ptr::write_bytes(new_pml4_ptr, 0, 512); + } + + let (cur_pml4, pml4_flags) = Cr3::read(); + + unsafe { + let cur_pml4_ptr = + physical_to_virt_pointer(cur_pml4.start_address(), frame_allocator.hhdm_offset); + let new_pml4_ptr = + physical_to_virt_pointer(new_pml4.start_address(), frame_allocator.hhdm_offset); + + for i in 0..512 { + let val = core::ptr::read(cur_pml4_ptr.add(i)); + core::ptr::write(new_pml4_ptr.add(i), val); + } + } + + let mut mapper = unsafe { + let addr = frame_allocator.hhdm_offset + new_pml4.start_address().as_u64(); + let virtual_addr = VirtAddr::new(addr); + let level_4_table: *mut PageTable = virtual_addr.as_mut_ptr(); + OffsetPageTable::new( + &mut *level_4_table, + VirtAddr::new(frame_allocator.hhdm_offset), + ) + }; + + Some(AddressSpace { + cr3_frame: new_pml4, + user_stack_top: VirtAddr::new(0x0000_7fff_0000_0000), + mapper: mapper, + heap_base: VirtAddr::new(0x0), + heap_end: VirtAddr::new(0x0), + }) + } + + pub fn use_address_space(&mut self) { + unsafe { Cr3::write(self.cr3_frame, Cr3Flags::empty()) }; + } +} + +unsafe fn physical_to_virt_pointer(phys_addr: PhysAddr, hhdm_offset: u64) -> *mut u64 { + (hhdm_offset + phys_addr.as_u64()) as *mut u64 +} diff --git a/kernel/src/mm/mod.rs b/kernel/src/mm/mod.rs new file mode 100644 index 0000000..f2763a0 --- /dev/null +++ b/kernel/src/mm/mod.rs @@ -0,0 +1 @@ +pub mod address_space; diff --git a/kernel/src/task/context.rs b/kernel/src/task/context.rs new file mode 100644 index 0000000..e69de29 diff --git a/kernel/src/task/mod.rs b/kernel/src/task/mod.rs new file mode 100644 index 0000000..e5988ab --- /dev/null +++ b/kernel/src/task/mod.rs @@ -0,0 +1,3 @@ +pub mod context; +pub mod process; +pub mod scheduler; diff --git a/kernel/src/task/process.rs b/kernel/src/task/process.rs new file mode 100644 index 0000000..82eee84 --- /dev/null +++ b/kernel/src/task/process.rs @@ -0,0 +1,32 @@ +use crate::{arch::x86_64::paging::XunilFrameAllocator, mm::address_space::AddressSpace}; + +enum ProcessState { + Ready, + Running, + Blocked, + Zombie, +} + +pub struct Process { + pub pid: u64, + pub state: ProcessState, + // cpu_ctx: &[u8], + pub address_space: AddressSpace, + pub user_entry: u64, +} +impl Process { + pub fn new( + pid: u64, + user_entry: u64, + frame_allocator: &mut XunilFrameAllocator, + ) -> Option { + let address_space = AddressSpace::new(frame_allocator)?; + + Some(Process { + pid, + state: ProcessState::Ready, + address_space, + user_entry, + }) + } +} diff --git a/kernel/src/task/scheduler.rs b/kernel/src/task/scheduler.rs new file mode 100644 index 0000000..208297c --- /dev/null +++ b/kernel/src/task/scheduler.rs @@ -0,0 +1,45 @@ +use alloc::collections::btree_map::BTreeMap; +use lazy_static::lazy_static; + +use crate::{arch::x86_64::paging::XunilFrameAllocator, task::process::Process, util::Locked}; + +pub struct Scheduler { + pub processes: BTreeMap, + next_pid: u64, +} + +impl Scheduler { + pub const fn new() -> Scheduler { + Scheduler { + processes: BTreeMap::new(), + next_pid: 1, + } + } +} + +impl Locked { + pub fn spawn_process( + &self, + entry_point: u64, + frame_allocator: &mut XunilFrameAllocator, + ) -> Option { + let mut guard = self.lock(); + let pid = guard.next_pid; + guard.next_pid += 1; + let process = Process::new(pid, entry_point, frame_allocator)?; + guard.processes.insert(pid, process); + + Some(pid) + } + + pub fn with_process(&self, index: u64, f: F) -> Option + where + F: FnOnce(&mut Process) -> R, + { + let mut guard = self.lock(); + let process = guard.processes.get_mut(&index)?; + Some(f(process)) + } +} + +pub static SCHEDULER: Locked = Locked::new(Scheduler::new()); diff --git a/kernel/src/userspace_stub.rs b/kernel/src/userspace_stub.rs index 99bf2f2..884ee3c 100644 --- a/kernel/src/userspace_stub.rs +++ b/kernel/src/userspace_stub.rs @@ -91,7 +91,7 @@ pub fn userspace_init( with_framebuffer(|fb| fb.swap()); - run_elf(entry_point, frame_allocator, mapper); + run_elf(entry_point, frame_allocator); loop {} diff --git a/kernel/src/util.rs b/kernel/src/util.rs index 2666413..8c9042d 100644 --- a/kernel/src/util.rs +++ b/kernel/src/util.rs @@ -1,25 +1,6 @@ use crate::{driver::timer::TIMER, println}; use spin::{Mutex, MutexGuard}; -pub struct LinkedNode { - pub size: usize, - pub next: Option<&'static mut LinkedNode>, -} - -impl LinkedNode { - pub const fn new(size: usize) -> LinkedNode { - LinkedNode { size, next: None } - } - - pub fn start_addr(&self) -> usize { - self as *const Self as usize - } - - pub fn end_addr(&self) -> usize { - self.start_addr() + self.size - } -} - pub struct Locked { inner: Mutex, } diff --git a/user/libxunil/.cargo/config.toml b/user/libxunil/.cargo/config.toml new file mode 100644 index 0000000..7dc1635 --- /dev/null +++ b/user/libxunil/.cargo/config.toml @@ -0,0 +1,4 @@ +[unstable] + json-target-spec = true + build-std-features = ["compiler-builtins-mem"] + build-std = ["core", "compiler_builtins", "alloc"] diff --git a/user/libxunil/Cargo.lock b/user/libxunil/Cargo.lock index 6ea7801..c50653a 100644 --- a/user/libxunil/Cargo.lock +++ b/user/libxunil/Cargo.lock @@ -2,6 +2,52 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "const_fn" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413d67b29ef1021b4d60f4aa1e925ca031751e213832b4b1d588fae623c05c60" + [[package]] name = "libxunil" version = "0.1.0" +dependencies = [ + "x86_64", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "volatile" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "442887c63f2c839b346c192d047a7c87e73d0689c9157b00b53dcc27dd5ea793" + +[[package]] +name = "x86_64" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7841fa0098ceb15c567d93d3fae292c49e10a7662b4936d5f6a9728594555ba" +dependencies = [ + "bit_field", + "bitflags", + "const_fn", + "rustversion", + "volatile", +] diff --git a/user/libxunil/Cargo.toml b/user/libxunil/Cargo.toml index fafc857..c9c48d1 100644 --- a/user/libxunil/Cargo.toml +++ b/user/libxunil/Cargo.toml @@ -10,3 +10,9 @@ crate-type = ["staticlib"] [profile.release] panic = "abort" opt-level = "s" + +[target.'cfg(target_arch = "x86_64")'.dependencies] +x86_64 = "0.15.4" + +[profile.dev] +panic = "abort" diff --git a/user/libxunil/rust-toolchain.toml b/user/libxunil/rust-toolchain.toml new file mode 100644 index 0000000..66a0077 --- /dev/null +++ b/user/libxunil/rust-toolchain.toml @@ -0,0 +1,8 @@ +[toolchain] +channel = "nightly" +targets = [ + "x86_64-unknown-none", + # "aarch64-unknown-none", + # "riscv64gc-unknown-none-elf", + # "loongarch64-unknown-none", +] diff --git a/user/libxunil/src/file.rs b/user/libxunil/src/file.rs new file mode 100644 index 0000000..8f25028 --- /dev/null +++ b/user/libxunil/src/file.rs @@ -0,0 +1,66 @@ +use core::ptr::null_mut; + +#[unsafe(no_mangle)] +extern "C" fn fopen(path: *const u8, mode: *const u8) -> *mut u8 { + null_mut() +} + +#[unsafe(no_mangle)] +extern "C" fn fclose(file_ptr: *mut u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn fprintf(file_ptr: *mut u8, s: *const u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn fread(ptr: *mut u8, size: i32, nmemb: *const u8, fp: *const u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn fwrite(ptr: *mut u8, size: i32, nmemb: *const u8, fp: *const u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn fseek(s: *const u8, size: i32, fp: *const u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn ftell(fp: *const u8) -> i64 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn fflush(file_ptr: *mut u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn mkdir(path: *const u8, mode: *const u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn remove(path: *const u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn rename(path: *const u8, new_path: *const u8) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn vfprintf(stream: *const u8, format: *const u8, args: ...) -> i32 { + 0 +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn vsnprintf(s: *mut u8, n: i32, format: *const u8, args: ...) -> i32 { + 0 +} diff --git a/user/libxunil/include/inttypes.h b/user/libxunil/src/include/inttypes.h similarity index 100% rename from user/libxunil/include/inttypes.h rename to user/libxunil/src/include/inttypes.h diff --git a/user/libxunil/include/stdio.h b/user/libxunil/src/include/stdio.h similarity index 85% rename from user/libxunil/include/stdio.h rename to user/libxunil/src/include/stdio.h index 1749750..13a6468 100644 --- a/user/libxunil/include/stdio.h +++ b/user/libxunil/src/include/stdio.h @@ -2,7 +2,17 @@ #include #include -typedef struct FILE FILE; +typedef struct _iobuf +{ + char* _ptr; + int _cnt; + char* _base; + int _flag; + int _file; + int _charbuf; + int _bufsiz; + char* _tmpfname; +} FILE; extern FILE *stdin; extern FILE *stdout; diff --git a/user/libxunil/include/stdlib.h b/user/libxunil/src/include/stdlib.h similarity index 100% rename from user/libxunil/include/stdlib.h rename to user/libxunil/src/include/stdlib.h diff --git a/user/libxunil/include/string.h b/user/libxunil/src/include/string.h similarity index 100% rename from user/libxunil/include/string.h rename to user/libxunil/src/include/string.h diff --git a/user/libxunil/include/strings.h b/user/libxunil/src/include/strings.h similarity index 100% rename from user/libxunil/include/strings.h rename to user/libxunil/src/include/strings.h diff --git a/user/libxunil/src/lib.rs b/user/libxunil/src/lib.rs index 94043a6..6e5e849 100644 --- a/user/libxunil/src/lib.rs +++ b/user/libxunil/src/lib.rs @@ -1,20 +1,24 @@ #![no_std] -#![no_main] +#![feature(c_variadic)] + +use core::ptr::null; use crate::syscall::syscall3; +pub mod file; +pub mod mem; pub mod syscall; const SYS_EXIT: usize = 1; const SYS_WRITE: usize = 60; #[unsafe(no_mangle)] -extern "C" fn write(fd: i32, buf: *const u8, count: usize) -> isize { +extern "C" fn write(fd: i64, buf: *const u8, count: usize) -> isize { unsafe { syscall3(SYS_WRITE, fd as usize, buf as usize, count) } } #[unsafe(no_mangle)] -extern "C" fn exit(code: i32) -> ! { +extern "C" fn exit(code: i64) -> ! { unsafe { syscall3(SYS_EXIT, code as usize, 0, 0) }; loop {} } @@ -36,14 +40,26 @@ extern "C" fn puts(s: *const u8) -> isize { } #[unsafe(no_mangle)] -extern "C" fn abs(n: i32) -> i32 { +extern "C" fn putchar(s: i32) -> isize { + write(1, (s as u8 + b'0') as *const u8, 1); + + 0 +} + +#[unsafe(no_mangle)] +extern "C" fn abs(n: i64) -> i64 { n.abs() } #[unsafe(no_mangle)] -extern "C" fn atoi(mut c: *const u8) -> i32 { - let mut value: i32 = 0; - let mut sign: i32 = 1; +unsafe extern "C" fn printf(format: *const u8, args: ...) { + unsafe { syscall3(SYS_WRITE, 1, format as usize, strlen(format)) }; +} + +#[unsafe(no_mangle)] +extern "C" fn atoi(mut c: *const u8) -> i64 { + let mut value: i64 = 0; + let mut sign: i64 = 1; unsafe { if (*c) == b'+' || (*c) == b'-' { if *c == b'-' { @@ -53,7 +69,7 @@ extern "C" fn atoi(mut c: *const u8) -> i32 { } while (*c).is_ascii_digit() { value *= 10; - value += ((*c) - b'0') as i32; + value += ((*c) - b'0') as i64; c = c.add(1); } } @@ -61,6 +77,115 @@ extern "C" fn atoi(mut c: *const u8) -> i32 { value * sign } +#[unsafe(no_mangle)] +extern "C" fn atof(mut c: *const u8) -> f64 { + 0.0 +} + +pub fn compare_str(str_1: *const u8, str_2: *const u8, case: bool, n: usize) -> i32 { + let mut len = 0; + + while len < n { + let mut c_1 = unsafe { *str_1.add(len) }; + let mut c_2 = unsafe { *str_2.add(len) }; + + if case { + c_1 = c_1.to_ascii_lowercase(); + c_2 = c_2.to_ascii_lowercase(); + } + + if c_1 != c_2 { + return (c_1 - c_2) as i32; + } + + if c_1 == 0 { + return 0; + } + + len += 1; + } + + 0 +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strcasecmp(str_1: *const u8, str_2: *const u8) -> i32 { + compare_str(str_1, str_2, true, 999999999999999) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strcmp(str_1: *const u8, str_2: *const u8) -> i32 { + compare_str(str_1, str_2, false, 999999999999999) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strncasecmp(str_1: *const u8, str_2: *const u8, n: i32) -> i32 { + compare_str(str_1, str_2, true, n as usize) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strncmp(str_1: *const u8, str_2: *const u8, n: i32) -> i32 { + compare_str(str_1, str_2, false, n as usize) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strncopy(s: *const u8, n: i32) -> *const u8 { + null() +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strdup(s: *const u8) -> *const u8 { + null() +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strstr(s: *const u8) -> *const u8 { + null() +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strchr(s: *const u8, ch: u8) -> *const u8 { + null() +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn strrchr(s: *const u8, ch: u8) -> *const u8 { + let mut n = 0; + let mut last: *const u8 = null(); + + if ch == 0 { + while unsafe { *s.add(n) } != 0 { + n += 1; + } + unsafe { s.add(n + 1) } + } else { + while unsafe { *s.add(n) } != 0 { + let cur_ch = unsafe { s.add(n) }; + if unsafe { *cur_ch == ch } { + last = cur_ch; + } + n += 1; + } + + last + } +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn toupper(char: u8) -> u8 { + char.to_ascii_uppercase() +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn tolower(char: u8) -> u8 { + char.to_ascii_lowercase() +} + +#[unsafe(no_mangle)] +extern "C" fn system(cmd: *const u8) -> i32 { + 0 +} + #[panic_handler] fn panic(_: &core::panic::PanicInfo) -> ! { loop {} diff --git a/user/libxunil/src/mem.rs b/user/libxunil/src/mem.rs new file mode 100644 index 0000000..bfcbc2e --- /dev/null +++ b/user/libxunil/src/mem.rs @@ -0,0 +1,27 @@ +use core::ptr::null_mut; + +#[unsafe(no_mangle)] +extern "C" fn calloc(nitems: u64, size: u64) -> *mut u8 { + null_mut() +} + +#[unsafe(no_mangle)] +extern "C" fn free(ptr: *mut u8) {} + +#[unsafe(no_mangle)] +extern "C" fn malloc(size: u64) -> *mut u8 { + null_mut() +} + +#[unsafe(no_mangle)] +extern "C" fn memcpy(dest_str: *mut u8, src_str: *const u8, n: u64) {} + +#[unsafe(no_mangle)] +extern "C" fn memset(str: *mut u8, c: i64, n: u64) -> *mut u8 { + null_mut() +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn realloc(ptr: *mut u8, size: u64) -> *mut u8 { + null_mut() +} diff --git a/user/libxunil/to_implement.txt b/user/libxunil/to_implement.txt index d335a2a..8e8d306 100644 --- a/user/libxunil/to_implement.txt +++ b/user/libxunil/to_implement.txt @@ -1,17 +1,36 @@ abs +atof atoi calloc __ctype_toupper_loc +__errno_location +exit +fclose +fflush +fopen fprintf +fread free +fseek +ftell +fwrite +__isoc23_sscanf malloc memcpy memset +mkdir printf +putchar +puts realloc +remove +rename +snprintf __stack_chk_fail stderr +stdout strcasecmp +strchr strcmp strdup strlen @@ -19,4 +38,8 @@ strncasecmp strncmp strncpy strrchr +strstr +system toupper +vfprintf // this +vsnprintf // also this