mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-04-25 11:49:03 +02:00
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.
This commit is contained in:
@@ -26,12 +26,8 @@ pub fn enter_usermode(user_rip: u64, user_rsp: u64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub fn run_elf(
|
pub fn run_elf(entry_point: *const u8, frame_allocator: &mut XunilFrameAllocator) {
|
||||||
entry_point: *const u8,
|
run_elf_x86_64(entry_point, frame_allocator);
|
||||||
frame_allocator: &mut XunilFrameAllocator,
|
|
||||||
mapper: &mut OffsetPageTable,
|
|
||||||
) {
|
|
||||||
run_elf_x86_64(entry_point, frame_allocator, mapper);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_allocator<'a>() -> &'static impl GlobalAlloc {
|
pub fn get_allocator<'a>() -> &'static impl GlobalAlloc {
|
||||||
|
|||||||
@@ -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 stack_base: u64 = 0x0000_7fff_0000_0000;
|
||||||
let page_count = 3;
|
let page_count = 3;
|
||||||
let page_size = 0x1000u64;
|
let page_size = 0x1000u64;
|
||||||
@@ -26,17 +33,21 @@ pub fn run_elf_x86_64(
|
|||||||
let page = Page::<Size4KiB>::containing_address(virt_addr);
|
let page = Page::<Size4KiB>::containing_address(virt_addr);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
mapper
|
SCHEDULER.with_process(process_pid, |process| {
|
||||||
.map_to(
|
process
|
||||||
page,
|
.address_space
|
||||||
frame,
|
.mapper
|
||||||
PageTableFlags::PRESENT
|
.map_to(
|
||||||
| PageTableFlags::WRITABLE
|
page,
|
||||||
| PageTableFlags::USER_ACCESSIBLE,
|
frame,
|
||||||
frame_allocator,
|
PageTableFlags::PRESENT
|
||||||
)
|
| PageTableFlags::WRITABLE
|
||||||
.unwrap()
|
| PageTableFlags::USER_ACCESSIBLE,
|
||||||
.flush();
|
frame_allocator,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.flush();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::arch::x86_64::paging::XunilFrameAllocator;
|
use crate::arch::x86_64::paging::XunilFrameAllocator;
|
||||||
use crate::util::{LinkedNode, Locked};
|
use crate::util::Locked;
|
||||||
use core::{
|
use core::{
|
||||||
alloc::{GlobalAlloc, Layout},
|
alloc::{GlobalAlloc, Layout},
|
||||||
ptr::null_mut,
|
ptr::null_mut,
|
||||||
@@ -22,6 +22,25 @@ pub static ALLOCATOR: Locked<LinkedListAllocator> = Locked::new(LinkedListAlloca
|
|||||||
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
||||||
pub const HEAP_SIZE: usize = 256 * 1024 * 1024; // 256 MiB
|
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 {
|
pub struct LinkedListAllocator {
|
||||||
head: LinkedNode,
|
head: LinkedNode,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ pub fn memory_management_init<'a>(
|
|||||||
) -> (OffsetPageTable<'static>, XunilFrameAllocator<'a>) {
|
) -> (OffsetPageTable<'static>, XunilFrameAllocator<'a>) {
|
||||||
let physical_offset = VirtAddr::new(hhdm_response.offset());
|
let physical_offset = VirtAddr::new(hhdm_response.offset());
|
||||||
let mapper = unsafe { initialize_paging(physical_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)
|
(mapper, frame_allocator)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,19 +24,21 @@ pub unsafe fn initialize_paging(physical_memory_offset: VirtAddr) -> OffsetPageT
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct XunilFrameAllocator<'a> {
|
pub struct XunilFrameAllocator<'a> {
|
||||||
|
pub hhdm_offset: u64,
|
||||||
memory_map: &'a [&'a Entry],
|
memory_map: &'a [&'a Entry],
|
||||||
region_index: usize,
|
region_index: usize,
|
||||||
region_offset: usize,
|
region_offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> XunilFrameAllocator<'a> {
|
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
|
let region_index = memory_map
|
||||||
.iter()
|
.iter()
|
||||||
.position(|region| region.entry_type == EntryType::USABLE)
|
.position(|region| region.entry_type == EntryType::USABLE)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
hhdm_offset,
|
||||||
memory_map,
|
memory_map,
|
||||||
region_index,
|
region_index,
|
||||||
region_offset: 0,
|
region_offset: 0,
|
||||||
|
|||||||
@@ -3,7 +3,11 @@ use core::{
|
|||||||
ptr::null_mut,
|
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_EXIT: usize = 1;
|
||||||
const SYS_WRITE: usize = 60;
|
const SYS_WRITE: usize = 60;
|
||||||
@@ -63,7 +67,7 @@ pub unsafe extern "C" fn syscall_dispatch(
|
|||||||
SYS_EXIT => {
|
SYS_EXIT => {
|
||||||
println!("Program exit.");
|
println!("Program exit.");
|
||||||
with_framebuffer(|fb| fb.swap());
|
with_framebuffer(|fb| fb.swap());
|
||||||
0
|
infinite_idle();
|
||||||
}
|
}
|
||||||
_ => -38, // syscall not found
|
_ => -38, // syscall not found
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ use limine::request::{
|
|||||||
};
|
};
|
||||||
pub mod arch;
|
pub mod arch;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
|
pub mod mm;
|
||||||
|
pub mod task;
|
||||||
pub mod userspace_stub;
|
pub mod userspace_stub;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
||||||
|
|||||||
66
kernel/src/mm/address_space.rs
Normal file
66
kernel/src/mm/address_space.rs
Normal file
@@ -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<Size4KiB>,
|
||||||
|
user_stack_top: VirtAddr,
|
||||||
|
pub mapper: OffsetPageTable<'static>,
|
||||||
|
heap_base: VirtAddr,
|
||||||
|
heap_end: VirtAddr,
|
||||||
|
}
|
||||||
|
impl AddressSpace {
|
||||||
|
pub fn new(frame_allocator: &mut XunilFrameAllocator) -> Option<AddressSpace> {
|
||||||
|
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
|
||||||
|
}
|
||||||
1
kernel/src/mm/mod.rs
Normal file
1
kernel/src/mm/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod address_space;
|
||||||
0
kernel/src/task/context.rs
Normal file
0
kernel/src/task/context.rs
Normal file
3
kernel/src/task/mod.rs
Normal file
3
kernel/src/task/mod.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub mod context;
|
||||||
|
pub mod process;
|
||||||
|
pub mod scheduler;
|
||||||
32
kernel/src/task/process.rs
Normal file
32
kernel/src/task/process.rs
Normal file
@@ -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<Process> {
|
||||||
|
let address_space = AddressSpace::new(frame_allocator)?;
|
||||||
|
|
||||||
|
Some(Process {
|
||||||
|
pid,
|
||||||
|
state: ProcessState::Ready,
|
||||||
|
address_space,
|
||||||
|
user_entry,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
45
kernel/src/task/scheduler.rs
Normal file
45
kernel/src/task/scheduler.rs
Normal file
@@ -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<u64, Process>,
|
||||||
|
next_pid: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Scheduler {
|
||||||
|
pub const fn new() -> Scheduler {
|
||||||
|
Scheduler {
|
||||||
|
processes: BTreeMap::new(),
|
||||||
|
next_pid: 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Locked<Scheduler> {
|
||||||
|
pub fn spawn_process(
|
||||||
|
&self,
|
||||||
|
entry_point: u64,
|
||||||
|
frame_allocator: &mut XunilFrameAllocator,
|
||||||
|
) -> Option<u64> {
|
||||||
|
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<F, R>(&self, index: u64, f: F) -> Option<R>
|
||||||
|
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<Scheduler> = Locked::new(Scheduler::new());
|
||||||
@@ -91,7 +91,7 @@ pub fn userspace_init(
|
|||||||
|
|
||||||
with_framebuffer(|fb| fb.swap());
|
with_framebuffer(|fb| fb.swap());
|
||||||
|
|
||||||
run_elf(entry_point, frame_allocator, mapper);
|
run_elf(entry_point, frame_allocator);
|
||||||
|
|
||||||
loop {}
|
loop {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,6 @@
|
|||||||
use crate::{driver::timer::TIMER, println};
|
use crate::{driver::timer::TIMER, println};
|
||||||
use spin::{Mutex, MutexGuard};
|
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<A> {
|
pub struct Locked<A> {
|
||||||
inner: Mutex<A>,
|
inner: Mutex<A>,
|
||||||
}
|
}
|
||||||
|
|||||||
4
user/libxunil/.cargo/config.toml
Normal file
4
user/libxunil/.cargo/config.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[unstable]
|
||||||
|
json-target-spec = true
|
||||||
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
|
build-std = ["core", "compiler_builtins", "alloc"]
|
||||||
46
user/libxunil/Cargo.lock
generated
46
user/libxunil/Cargo.lock
generated
@@ -2,6 +2,52 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
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]]
|
[[package]]
|
||||||
name = "libxunil"
|
name = "libxunil"
|
||||||
version = "0.1.0"
|
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",
|
||||||
|
]
|
||||||
|
|||||||
@@ -10,3 +10,9 @@ crate-type = ["staticlib"]
|
|||||||
[profile.release]
|
[profile.release]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
opt-level = "s"
|
opt-level = "s"
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "x86_64")'.dependencies]
|
||||||
|
x86_64 = "0.15.4"
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
|||||||
8
user/libxunil/rust-toolchain.toml
Normal file
8
user/libxunil/rust-toolchain.toml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[toolchain]
|
||||||
|
channel = "nightly"
|
||||||
|
targets = [
|
||||||
|
"x86_64-unknown-none",
|
||||||
|
# "aarch64-unknown-none",
|
||||||
|
# "riscv64gc-unknown-none-elf",
|
||||||
|
# "loongarch64-unknown-none",
|
||||||
|
]
|
||||||
66
user/libxunil/src/file.rs
Normal file
66
user/libxunil/src/file.rs
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -2,7 +2,17 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
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 *stdin;
|
||||||
extern FILE *stdout;
|
extern FILE *stdout;
|
||||||
@@ -1,20 +1,24 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![feature(c_variadic)]
|
||||||
|
|
||||||
|
use core::ptr::null;
|
||||||
|
|
||||||
use crate::syscall::syscall3;
|
use crate::syscall::syscall3;
|
||||||
|
|
||||||
|
pub mod file;
|
||||||
|
pub mod mem;
|
||||||
pub mod syscall;
|
pub mod syscall;
|
||||||
|
|
||||||
const SYS_EXIT: usize = 1;
|
const SYS_EXIT: usize = 1;
|
||||||
const SYS_WRITE: usize = 60;
|
const SYS_WRITE: usize = 60;
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[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 { syscall3(SYS_WRITE, fd as usize, buf as usize, count) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn exit(code: i32) -> ! {
|
extern "C" fn exit(code: i64) -> ! {
|
||||||
unsafe { syscall3(SYS_EXIT, code as usize, 0, 0) };
|
unsafe { syscall3(SYS_EXIT, code as usize, 0, 0) };
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
@@ -36,14 +40,26 @@ extern "C" fn puts(s: *const u8) -> isize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[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()
|
n.abs()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn atoi(mut c: *const u8) -> i32 {
|
unsafe extern "C" fn printf(format: *const u8, args: ...) {
|
||||||
let mut value: i32 = 0;
|
unsafe { syscall3(SYS_WRITE, 1, format as usize, strlen(format)) };
|
||||||
let mut sign: i32 = 1;
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
extern "C" fn atoi(mut c: *const u8) -> i64 {
|
||||||
|
let mut value: i64 = 0;
|
||||||
|
let mut sign: i64 = 1;
|
||||||
unsafe {
|
unsafe {
|
||||||
if (*c) == b'+' || (*c) == b'-' {
|
if (*c) == b'+' || (*c) == b'-' {
|
||||||
if *c == b'-' {
|
if *c == b'-' {
|
||||||
@@ -53,7 +69,7 @@ extern "C" fn atoi(mut c: *const u8) -> i32 {
|
|||||||
}
|
}
|
||||||
while (*c).is_ascii_digit() {
|
while (*c).is_ascii_digit() {
|
||||||
value *= 10;
|
value *= 10;
|
||||||
value += ((*c) - b'0') as i32;
|
value += ((*c) - b'0') as i64;
|
||||||
c = c.add(1);
|
c = c.add(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,6 +77,115 @@ extern "C" fn atoi(mut c: *const u8) -> i32 {
|
|||||||
value * sign
|
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]
|
#[panic_handler]
|
||||||
fn panic(_: &core::panic::PanicInfo) -> ! {
|
fn panic(_: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
|
|||||||
27
user/libxunil/src/mem.rs
Normal file
27
user/libxunil/src/mem.rs
Normal file
@@ -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()
|
||||||
|
}
|
||||||
@@ -1,17 +1,36 @@
|
|||||||
abs
|
abs
|
||||||
|
atof
|
||||||
atoi
|
atoi
|
||||||
calloc
|
calloc
|
||||||
__ctype_toupper_loc
|
__ctype_toupper_loc
|
||||||
|
__errno_location
|
||||||
|
exit
|
||||||
|
fclose
|
||||||
|
fflush
|
||||||
|
fopen
|
||||||
fprintf
|
fprintf
|
||||||
|
fread
|
||||||
free
|
free
|
||||||
|
fseek
|
||||||
|
ftell
|
||||||
|
fwrite
|
||||||
|
__isoc23_sscanf
|
||||||
malloc
|
malloc
|
||||||
memcpy
|
memcpy
|
||||||
memset
|
memset
|
||||||
|
mkdir
|
||||||
printf
|
printf
|
||||||
|
putchar
|
||||||
|
puts
|
||||||
realloc
|
realloc
|
||||||
|
remove
|
||||||
|
rename
|
||||||
|
snprintf
|
||||||
__stack_chk_fail
|
__stack_chk_fail
|
||||||
stderr
|
stderr
|
||||||
|
stdout
|
||||||
strcasecmp
|
strcasecmp
|
||||||
|
strchr
|
||||||
strcmp
|
strcmp
|
||||||
strdup
|
strdup
|
||||||
strlen
|
strlen
|
||||||
@@ -19,4 +38,8 @@ strncasecmp
|
|||||||
strncmp
|
strncmp
|
||||||
strncpy
|
strncpy
|
||||||
strrchr
|
strrchr
|
||||||
|
strstr
|
||||||
|
system
|
||||||
toupper
|
toupper
|
||||||
|
vfprintf // this
|
||||||
|
vsnprintf // also this
|
||||||
|
|||||||
Reference in New Issue
Block a user