mirror of
https://github.com/XunilGroup/XunilOS.git
synced 2026-06-02 11:44:24 +02:00
Add a proper vfs driver into the kernel which handles file operations,
fix munmap number, remove the draw calls, make address space an option, copy only the top 256 bytes of the HHDM and map the ELF code inside userspace, add safe copying from userspace
This commit is contained in:
@@ -22,12 +22,12 @@ pub fn init<'a>(
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub fn enter_usermode(user_rip: u64, user_rsp: u64) {
|
||||
return enter_usermode_x86_64(user_rip, user_rsp);
|
||||
enter_usermode_x86_64(user_rip, user_rsp);
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub fn run_elf(entry_point: *const u8, heap_base: u64) {
|
||||
run_elf_x86_64(entry_point, heap_base);
|
||||
pub fn run_elf(file_bytes: &[u8]) {
|
||||
run_elf_x86_64(file_bytes);
|
||||
}
|
||||
|
||||
pub fn get_allocator<'a>() -> &'static impl GlobalAlloc {
|
||||
|
||||
+75
-22
@@ -1,3 +1,5 @@
|
||||
#![allow(dead_code)]
|
||||
|
||||
use core::{
|
||||
alloc::{GlobalAlloc, Layout},
|
||||
ptr::null_mut,
|
||||
@@ -12,11 +14,12 @@ use x86_64::{
|
||||
use crate::{
|
||||
arch::arch::{FRAME_ALLOCATOR, get_allocator, infinite_idle, sleep},
|
||||
driver::{
|
||||
graphics::{framebuffer::with_framebuffer, primitives::rectangle_filled},
|
||||
fs::vfs::{vfs_close, vfs_lseek, vfs_open, vfs_read},
|
||||
graphics::framebuffer::with_framebuffer,
|
||||
keyboard::{KeyboardEvent, process_scancodes},
|
||||
timer::TIMER,
|
||||
},
|
||||
mm::usercopy::copy_to_user,
|
||||
mm::usercopy::{copy_cstr_from_user, copy_to_user},
|
||||
print, println,
|
||||
task::scheduler::{SCHEDULER, current_pid},
|
||||
util::align_up,
|
||||
@@ -29,7 +32,7 @@ const CLOSE: usize = 3;
|
||||
const STAT: usize = 4;
|
||||
const LSEEK: usize = 8;
|
||||
const MMAP: usize = 9;
|
||||
const MUNMAP: usize = 9;
|
||||
const MUNMAP: usize = 11;
|
||||
const BRK: usize = 12;
|
||||
const GETPID: usize = 39;
|
||||
const FORK: usize = 57;
|
||||
@@ -45,9 +48,8 @@ const CLOCK_GETTIME: usize = 228;
|
||||
const EXIT_GROUP: usize = 231;
|
||||
const KBD_READ: usize = 666;
|
||||
const SLEEP: usize = 909090; // zzz haha
|
||||
const DRAW_PIXEL: usize = 5555;
|
||||
const FRAMEBUFFER_SWAP: usize = 6666;
|
||||
const DRAW_BUFFER: usize = 7777;
|
||||
pub const MAP_FRAMEBUFFER: usize = 5555;
|
||||
pub const FRAMEBUFFER_SWAP: usize = 6666;
|
||||
|
||||
pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 {
|
||||
let align = if align < 1 {
|
||||
@@ -84,6 +86,64 @@ pub unsafe fn memset(ptr: *mut u8, val: u8, count: usize) {
|
||||
unsafe { core::ptr::write_bytes(ptr, val, count) };
|
||||
}
|
||||
|
||||
fn map_framebuffer() -> isize {
|
||||
0
|
||||
}
|
||||
|
||||
fn read(ptr: isize, size: isize, nmemb: isize, fd: isize) -> isize {
|
||||
let pid = current_pid().unwrap_or(0);
|
||||
if pid == 0 {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SCHEDULER
|
||||
.with_process(pid, |process| {
|
||||
let len = size * nmemb;
|
||||
let to_read = vfs_read(fd as i64, len as usize);
|
||||
|
||||
if let Some(read_ptr) = to_read {
|
||||
let address_space = process.address_space.as_mut().unwrap();
|
||||
if copy_to_user(
|
||||
&mut address_space.mapper,
|
||||
ptr as *mut u8,
|
||||
read_ptr.0,
|
||||
read_ptr.1,
|
||||
)
|
||||
.is_err()
|
||||
{
|
||||
return -1;
|
||||
};
|
||||
|
||||
return (read_ptr.1 as isize) / size;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
})
|
||||
.unwrap_or(-1)
|
||||
}
|
||||
|
||||
fn open(path: isize, mode: isize) -> isize {
|
||||
let pid = current_pid().unwrap_or(0);
|
||||
if pid == 0 {
|
||||
return -1;
|
||||
}
|
||||
|
||||
SCHEDULER
|
||||
.with_process(pid, |process| {
|
||||
let address_space = process.address_space.as_mut().unwrap();
|
||||
let path = copy_cstr_from_user(&mut address_space.mapper, path as *const u8, 256)?;
|
||||
let mode = copy_cstr_from_user(&mut address_space.mapper, mode as *const u8, 16)?;
|
||||
|
||||
Ok::<isize, isize>(vfs_open(&path, &mode) as isize)
|
||||
})
|
||||
.unwrap_or(Err(-1))
|
||||
.unwrap_or(-1)
|
||||
}
|
||||
|
||||
fn close(fd: isize) -> isize {
|
||||
vfs_close(fd as i64) as isize
|
||||
}
|
||||
|
||||
fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize {
|
||||
process_scancodes();
|
||||
if max_events <= 0 || user_ptr.is_null() {
|
||||
@@ -99,8 +159,9 @@ fn kbd_read(user_ptr: *mut KeyboardEvent, max_events: isize) -> isize {
|
||||
return SCHEDULER
|
||||
.with_process(pid as u64, |process| {
|
||||
let to_copy = (max_events as usize).min(process.kbd_buffer.len());
|
||||
let address_space = process.address_space.as_mut().unwrap();
|
||||
if let Ok(_) = copy_to_user(
|
||||
&mut process.address_space.mapper,
|
||||
&mut address_space.mapper,
|
||||
user_ptr as *mut u8,
|
||||
process.kbd_buffer.as_ptr() as *const u8,
|
||||
to_copy * size_of::<KeyboardEvent>(),
|
||||
@@ -153,9 +214,9 @@ pub unsafe fn sbrk(increment: isize) -> isize {
|
||||
// TODO: do not use x86_64 only
|
||||
let virt_addr = VirtAddr::new(addr);
|
||||
let page = Page::<Size4KiB>::containing_address(virt_addr);
|
||||
let address_space = process.address_space.as_mut().unwrap();
|
||||
unsafe {
|
||||
process
|
||||
.address_space
|
||||
address_space
|
||||
.mapper
|
||||
.map_to(
|
||||
page,
|
||||
@@ -198,6 +259,7 @@ pub unsafe extern "C" fn syscall_dispatch(
|
||||
interrupts::enable();
|
||||
match num {
|
||||
BRK => unsafe { sbrk(arg0) },
|
||||
READ => read(arg0, arg1, arg2, arg3) as isize,
|
||||
WRITE => {
|
||||
let buf_ptr = arg1 as *const u8;
|
||||
let len = arg2 as usize;
|
||||
@@ -216,6 +278,9 @@ pub unsafe extern "C" fn syscall_dispatch(
|
||||
with_framebuffer(|fb| fb.swap());
|
||||
0
|
||||
}
|
||||
OPEN => open(arg0, arg1),
|
||||
CLOSE => close(arg0),
|
||||
LSEEK => vfs_lseek(arg0 as i64, arg1 as i64, arg2 as i32) as isize,
|
||||
EXIT => {
|
||||
println!("Program exit: {}", arg0);
|
||||
with_framebuffer(|fb| fb.swap());
|
||||
@@ -226,19 +291,7 @@ pub unsafe extern "C" fn syscall_dispatch(
|
||||
0
|
||||
}
|
||||
CLOCK_GETTIME => TIMER.now().elapsed() as isize,
|
||||
DRAW_PIXEL => {
|
||||
with_framebuffer(|mut fb| {
|
||||
rectangle_filled(&mut fb, arg0 as usize, arg1 as usize, 4, 4, arg2 as u32);
|
||||
});
|
||||
0
|
||||
}
|
||||
DRAW_BUFFER => {
|
||||
with_framebuffer(|fb| {
|
||||
unsafe { fb.load_from_ptr(arg0 as *const u32, arg1 as usize, arg2 as usize) };
|
||||
fb.swap();
|
||||
});
|
||||
0
|
||||
}
|
||||
MAP_FRAMEBUFFER => map_framebuffer(),
|
||||
KBD_READ => kbd_read(arg0 as *mut KeyboardEvent, arg1),
|
||||
FRAMEBUFFER_SWAP => {
|
||||
with_framebuffer(|fb| {
|
||||
|
||||
@@ -4,36 +4,40 @@ use x86_64::{
|
||||
structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, PhysFrame, Size4KiB},
|
||||
};
|
||||
|
||||
use crate::{arch::arch::FRAME_ALLOCATOR, task::scheduler::SCHEDULER};
|
||||
use crate::{
|
||||
arch::arch::FRAME_ALLOCATOR, driver::elf::loader::load_file, mm::address_space::AddressSpace,
|
||||
println, task::scheduler::SCHEDULER,
|
||||
};
|
||||
|
||||
pub fn run_elf_x86_64(entry_point: *const u8, heap_base: u64) {
|
||||
pub fn run_elf_x86_64(file_bytes: &[u8]) {
|
||||
let stack_base: u64 = 0x0000_7fff_0000_0000;
|
||||
let page_count = 4096; // 16 mib
|
||||
let page_size = 0x1000u64;
|
||||
let stack_top = stack_base + (page_count as u64 * page_size);
|
||||
|
||||
let process_pid = SCHEDULER
|
||||
.spawn_process(entry_point as u64, stack_top, heap_base)
|
||||
.unwrap();
|
||||
if let Some(mut address_space) = AddressSpace::new() {
|
||||
address_space.use_address_space();
|
||||
|
||||
SCHEDULER.with_process(process_pid, |process| {
|
||||
process.address_space.use_address_space()
|
||||
});
|
||||
let (entry_point, heap_base) = load_file(&mut address_space.mapper, file_bytes);
|
||||
|
||||
let mut frames: Vec<PhysFrame<Size4KiB>> = Vec::new();
|
||||
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
||||
println!("Entry point: {:?}", entry_point);
|
||||
|
||||
for i in 0..page_count {
|
||||
let frame = frame_allocator.allocate_frame().unwrap();
|
||||
frames.push(frame);
|
||||
let process_pid = SCHEDULER
|
||||
.spawn_process(entry_point as u64, stack_top, heap_base)
|
||||
.unwrap();
|
||||
|
||||
let virt_addr = VirtAddr::new(stack_base + i as u64 * page_size);
|
||||
let page = Page::<Size4KiB>::containing_address(virt_addr);
|
||||
let mut frames: Vec<PhysFrame<Size4KiB>> = Vec::new();
|
||||
let mut frame_allocator = FRAME_ALLOCATOR.lock();
|
||||
|
||||
unsafe {
|
||||
SCHEDULER.with_process(process_pid, |process| {
|
||||
process
|
||||
.address_space
|
||||
for i in 0..page_count {
|
||||
let frame = frame_allocator.allocate_frame().unwrap();
|
||||
frames.push(frame);
|
||||
|
||||
let virt_addr = VirtAddr::new(stack_base + i as u64 * page_size);
|
||||
let page = Page::<Size4KiB>::containing_address(virt_addr);
|
||||
|
||||
unsafe {
|
||||
address_space
|
||||
.mapper
|
||||
.map_to(
|
||||
page,
|
||||
@@ -45,10 +49,16 @@ pub fn run_elf_x86_64(entry_point: *const u8, heap_base: u64) {
|
||||
)
|
||||
.unwrap()
|
||||
.flush();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
drop(frame_allocator);
|
||||
drop(frame_allocator);
|
||||
|
||||
SCHEDULER.run_process(process_pid, entry_point);
|
||||
SCHEDULER.with_process(process_pid, |process| {
|
||||
process.address_space = Some(address_space)
|
||||
});
|
||||
|
||||
SCHEDULER.run_process(process_pid, entry_point);
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ fn align_up(addr: usize, align: usize) -> usize {
|
||||
#[global_allocator]
|
||||
pub static ALLOCATOR: Locked<LinkedListAllocator> = Locked::new(LinkedListAllocator::new());
|
||||
|
||||
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
||||
pub const HEAP_START: usize = 0xffffffff90000000;
|
||||
pub const HEAP_SIZE: usize = 64 * 1024 * 1024; // 64 MiB
|
||||
|
||||
pub struct LinkedNode {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use core::arch::asm;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
use x86_64::instructions::tlb::{self, flush_all};
|
||||
use x86_64::instructions::tlb::flush_all;
|
||||
|
||||
use crate::arch::x86_64::gdt::{GDT, TSS};
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// this is not made by me, but AI, im not going to type these out...
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
// e_ident indices
|
||||
pub const EI_MAG0: usize = 0;
|
||||
pub const EI_MAG1: usize = 1;
|
||||
|
||||
@@ -30,7 +30,7 @@ pub fn load_file(mapper: &mut OffsetPageTable, elf_bytes: &[u8]) -> (*const u8,
|
||||
|
||||
let elf_header_ptr = elf_bytes.as_ptr() as *const Elf64Ehdr;
|
||||
|
||||
return match unsafe { elf_header.e_type } {
|
||||
return match elf_header.e_type {
|
||||
ET_EXEC => unsafe { load_program(mapper, elf_header_ptr, elf_bytes, false) },
|
||||
ET_DYN => unsafe { load_program(mapper, elf_header_ptr, elf_bytes, true) },
|
||||
ET_REL => return (null(), 0),
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
pub mod vfs;
|
||||
@@ -0,0 +1,208 @@
|
||||
use core::ptr::{null, null_mut};
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct FILE {
|
||||
pub data: *const u8, // pointer to the file's data
|
||||
pub size: usize, // total size
|
||||
pub cursor: usize, // current position
|
||||
pub writable: bool, // is this a write buffer?
|
||||
pub write_buf: *mut u8, // for writable fake files
|
||||
pub write_cap: usize,
|
||||
pub fd: i64,
|
||||
}
|
||||
|
||||
impl FILE {
|
||||
pub const fn zeroed() -> FILE {
|
||||
FILE {
|
||||
data: null(),
|
||||
size: 0,
|
||||
cursor: 0,
|
||||
writable: false,
|
||||
write_buf: null_mut(),
|
||||
write_cap: 0,
|
||||
fd: -1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FakeFileEntry {
|
||||
name: &'static str,
|
||||
data: &'static [u8],
|
||||
}
|
||||
|
||||
pub type Fd = i64;
|
||||
const MAX_FD: usize = 16;
|
||||
|
||||
fn fd_ok(fd: Fd) -> bool {
|
||||
fd >= 0 && (fd as usize) < MAX_FD
|
||||
}
|
||||
|
||||
static DOOM_WAD: &[u8] = include_bytes!("../../../../assets/doom1.wad");
|
||||
static DOOM_ELF: &[u8] = include_bytes!("../../../../assets/doomgeneric");
|
||||
static HELLOWORLD_ELF: &[u8] = include_bytes!("../../../../assets/helloworld.elf");
|
||||
|
||||
static FILES: &[FakeFileEntry] = &[
|
||||
FakeFileEntry {
|
||||
name: "testfile",
|
||||
data: b"Hello, World!",
|
||||
},
|
||||
FakeFileEntry {
|
||||
name: "helloworld.elf",
|
||||
data: HELLOWORLD_ELF,
|
||||
},
|
||||
FakeFileEntry {
|
||||
name: "doomgeneric",
|
||||
data: DOOM_ELF,
|
||||
},
|
||||
FakeFileEntry {
|
||||
name: "doom1.wad",
|
||||
data: DOOM_WAD,
|
||||
},
|
||||
FakeFileEntry {
|
||||
name: "default.cfg",
|
||||
data: b"",
|
||||
},
|
||||
FakeFileEntry {
|
||||
name: "doom.cfg",
|
||||
data: b"",
|
||||
},
|
||||
];
|
||||
|
||||
static mut FILE_POOL: [FILE; 16] = [FILE::zeroed(); 16];
|
||||
static mut FILE_POOL_USED: [bool; 16] = [false; 16];
|
||||
|
||||
pub unsafe fn get_file_pool_slot() -> (*mut FILE, i64) {
|
||||
unsafe {
|
||||
for i in 0..16 {
|
||||
if !FILE_POOL_USED[i] {
|
||||
FILE_POOL_USED[i] = true;
|
||||
return (&mut FILE_POOL[i], i as i64);
|
||||
}
|
||||
}
|
||||
|
||||
(null_mut(), -1)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe fn file_mut(fd: Fd) -> Option<&'static mut FILE> {
|
||||
if !fd_ok(fd) {
|
||||
return None;
|
||||
}
|
||||
let idx = fd as usize;
|
||||
|
||||
if unsafe { !FILE_POOL_USED[idx] } {
|
||||
return None;
|
||||
}
|
||||
|
||||
return unsafe { Some(&mut FILE_POOL[idx]) };
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn vfs_open(name: &str, _mode: &str) -> Fd {
|
||||
for entry in FILES {
|
||||
if entry.name.contains(name) {
|
||||
let (slot, fd) = unsafe { get_file_pool_slot() };
|
||||
if slot.is_null() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
(*slot).data = entry.data.as_ptr();
|
||||
(*slot).size = entry.data.len();
|
||||
(*slot).cursor = 0;
|
||||
(*slot).writable = false;
|
||||
(*slot).write_buf = null_mut();
|
||||
(*slot).write_cap = 0;
|
||||
(*slot).fd = fd;
|
||||
}
|
||||
return fd;
|
||||
}
|
||||
}
|
||||
-1
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn vfs_close(fd: Fd) -> i32 {
|
||||
if !fd_ok(fd) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsafe {
|
||||
let idx = fd as usize;
|
||||
if !FILE_POOL_USED[idx] {
|
||||
return -1;
|
||||
}
|
||||
FILE_POOL_USED[idx] = false;
|
||||
FILE_POOL[idx] = FILE::zeroed();
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn vfs_write(ptr: *mut u8, size: usize, count: usize, fp: *mut FILE) -> usize {
|
||||
if ptr.is_null() || fp.is_null() || unsafe { (*fp).fd < 0 || (*fp).fd >= 16 } {
|
||||
return 0;
|
||||
}
|
||||
count
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub fn vfs_read(fd: Fd, len: usize) -> Option<(*const u8, usize)> {
|
||||
unsafe {
|
||||
let f = file_mut(fd)?;
|
||||
if f.cursor > f.size {
|
||||
return Some((f.data, 0));
|
||||
}
|
||||
|
||||
let available = f.size - f.cursor;
|
||||
let to_read = len.min(available);
|
||||
|
||||
let src = f.data.add(f.cursor);
|
||||
f.cursor = f.cursor.saturating_add(to_read);
|
||||
|
||||
Some((src, to_read))
|
||||
}
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
pub extern "C" fn vfs_lseek(fd: Fd, offset: i64, whence: i32) -> i64 {
|
||||
let f = match unsafe { file_mut(fd) } {
|
||||
Some(f) => f,
|
||||
None => return -1,
|
||||
};
|
||||
|
||||
let new_pos = match whence {
|
||||
0 => {
|
||||
if offset < 0 {
|
||||
return -1;
|
||||
}
|
||||
offset as usize
|
||||
}
|
||||
1 => {
|
||||
let cur = f.cursor as i64;
|
||||
let pos = cur.saturating_add(offset);
|
||||
if pos < 0 {
|
||||
return -1;
|
||||
}
|
||||
pos as usize
|
||||
}
|
||||
2 => {
|
||||
let end = f.size as i64;
|
||||
let pos = end.saturating_add(offset);
|
||||
if pos < 0 {
|
||||
return -1;
|
||||
}
|
||||
pos as usize
|
||||
}
|
||||
_ => return -1,
|
||||
};
|
||||
|
||||
if new_pos > f.size {
|
||||
return -1;
|
||||
}
|
||||
|
||||
f.cursor = new_pos;
|
||||
f.cursor as i64
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod elf;
|
||||
pub mod fs;
|
||||
pub mod graphics;
|
||||
pub mod keyboard;
|
||||
pub mod mouse;
|
||||
|
||||
+2
-7
@@ -102,11 +102,9 @@ unsafe extern "C" fn kmain() -> ! {
|
||||
// removed by the linker.
|
||||
assert!(BASE_REVISION.is_supported());
|
||||
|
||||
let mut mapper;
|
||||
|
||||
if let Some(hhdm_response) = HHDM_REQUEST.get_response() {
|
||||
if let Some(memory_map_response) = MEMORY_MAP_REQUEST.get_response() {
|
||||
mapper = init(hhdm_response, memory_map_response);
|
||||
init(hhdm_response, memory_map_response);
|
||||
} else {
|
||||
kernel_crash(); // Could not get required info from Limine's memory map.
|
||||
}
|
||||
@@ -130,12 +128,9 @@ unsafe extern "C" fn kmain() -> ! {
|
||||
println!("Could not get date at boot. Will default to 0.")
|
||||
}
|
||||
|
||||
let (entry_point, heap_base) = load_file(&mut mapper, INIT_ELF_BYTES);
|
||||
println!("Entry point: {:?}", entry_point);
|
||||
|
||||
with_framebuffer(|fb| fb.swap());
|
||||
|
||||
run_elf(entry_point, heap_base);
|
||||
run_elf(INIT_ELF_BYTES);
|
||||
|
||||
loop {}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ impl AddressSpace {
|
||||
let new_pml4_ptr =
|
||||
physical_to_virt_pointer(new_pml4.start_address(), frame_allocator.hhdm_offset);
|
||||
|
||||
for i in 0..512 {
|
||||
for i in 256..512 {
|
||||
let val = core::ptr::read(cur_pml4_ptr.add(i));
|
||||
core::ptr::write(new_pml4_ptr.add(i), val);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
use alloc::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use x86_64::{
|
||||
VirtAddr,
|
||||
structures::paging::{OffsetPageTable, PageTableFlags, Translate, mapper::TranslateResult},
|
||||
@@ -37,3 +41,71 @@ pub fn copy_to_user(
|
||||
unsafe { core::ptr::copy_nonoverlapping(src, buf, len) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn copy_from_user(
|
||||
mapper: &mut OffsetPageTable,
|
||||
buf: *mut u8,
|
||||
src: *const u8,
|
||||
len: usize,
|
||||
) -> Result<(), isize> {
|
||||
if len == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
if buf.is_null() || src.is_null() {
|
||||
return Err(-14);
|
||||
}
|
||||
|
||||
let start = src as u64;
|
||||
let end = start
|
||||
.checked_add(len as u64)
|
||||
.ok_or(-1)
|
||||
.map_err(|err| err as isize)?;
|
||||
|
||||
let mut page_addr = start & !0xFFF;
|
||||
|
||||
while page_addr < end {
|
||||
let translate_result = mapper.translate(VirtAddr::new(page_addr));
|
||||
#[allow(non_shorthand_field_patterns)]
|
||||
if let TranslateResult::Mapped {
|
||||
frame: _,
|
||||
offset: _,
|
||||
flags: flags,
|
||||
} = translate_result
|
||||
{
|
||||
if !flags.contains(PageTableFlags::USER_ACCESSIBLE) {
|
||||
return Err(-13);
|
||||
}
|
||||
} else {
|
||||
return Err(-1);
|
||||
}
|
||||
page_addr += 0x1000;
|
||||
}
|
||||
|
||||
unsafe { core::ptr::copy_nonoverlapping(src, buf, len) };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn copy_cstr_from_user(
|
||||
mapper: &mut OffsetPageTable,
|
||||
user_ptr: *const u8,
|
||||
max_len: usize,
|
||||
) -> Result<String, isize> {
|
||||
if user_ptr.is_null() {
|
||||
return Err(-14);
|
||||
}
|
||||
|
||||
let mut buf: Vec<u8> = Vec::with_capacity(64);
|
||||
|
||||
for i in 0..max_len {
|
||||
let mut byte = 0u8;
|
||||
copy_from_user(mapper, &mut byte as *mut u8, unsafe { user_ptr.add(i) }, 1)?;
|
||||
if byte == 0 {
|
||||
return core::str::from_utf8(&buf)
|
||||
.map(|s| s.to_string())
|
||||
.map_err(|_| -84);
|
||||
}
|
||||
buf.push(byte);
|
||||
}
|
||||
|
||||
Err(-36)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ pub struct Process {
|
||||
pub heap_base: u64,
|
||||
pub heap_end: u64,
|
||||
pub kbd_buffer: Vec<KeyboardEvent>,
|
||||
pub address_space: AddressSpace,
|
||||
pub address_space: Option<AddressSpace>,
|
||||
pub user_entry: u64,
|
||||
}
|
||||
impl Process {
|
||||
@@ -26,18 +26,16 @@ impl Process {
|
||||
stack_top: u64,
|
||||
heap_base: u64,
|
||||
heap_end: u64,
|
||||
) -> Option<Process> {
|
||||
let address_space = AddressSpace::new()?;
|
||||
|
||||
Some(Process {
|
||||
) -> Process {
|
||||
Process {
|
||||
pid,
|
||||
stack_top,
|
||||
state: ProcessState::Ready,
|
||||
heap_base,
|
||||
heap_end,
|
||||
kbd_buffer: Vec::new(),
|
||||
address_space,
|
||||
address_space: None,
|
||||
user_entry,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ impl Locked<Scheduler> {
|
||||
let mut guard = without_interrupts(|| self.lock());
|
||||
let pid = guard.next_pid;
|
||||
guard.next_pid += 1;
|
||||
let process = Process::new(pid, entry_point, stack_top, heap_base, heap_base)?;
|
||||
let process = Process::new(pid, entry_point, stack_top, heap_base, heap_base);
|
||||
guard.processes.insert(pid, process);
|
||||
|
||||
Some(pid)
|
||||
@@ -52,7 +52,6 @@ impl Locked<Scheduler> {
|
||||
};
|
||||
|
||||
set_current_pid(Some(pid));
|
||||
|
||||
enter_usermode(entry_point as u64, (stack_top & !0xF) - 8);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
Submodule user/init updated: 80dde531ba...3fe910f33a
+1
-1
Submodule user/libxunil updated: c508fee99e...222374a639
Reference in New Issue
Block a user