Implement stubs for directory/fs system calls
This commit is contained in:
parent
84de8cc141
commit
a3456a5b99
20
src/alloc.rs
20
src/alloc.rs
@ -1,7 +1,7 @@
|
||||
//! Application heap management functions
|
||||
use core::alloc::Layout;
|
||||
|
||||
use crate::sys;
|
||||
use crate::{debug_trace, sys};
|
||||
|
||||
/// Allocates memory for `layout`.
|
||||
///
|
||||
@ -10,10 +10,11 @@ use crate::sys;
|
||||
/// Unsafe.
|
||||
pub unsafe fn malloc(layout: Layout) -> *mut u8 {
|
||||
if layout.size() > 0x1000 || layout.align() > 0x1000 {
|
||||
sys::debug_trace("rt::malloc() invalid align/size");
|
||||
debug_trace!("rt::malloc() invalid align/size");
|
||||
loop {}
|
||||
}
|
||||
let page = sys::map_memory(None, 0x1000).unwrap();
|
||||
// debug_trace!("malloc({:?}) -> {:#x}", layout, page);
|
||||
|
||||
page as *mut u8
|
||||
}
|
||||
@ -34,11 +35,11 @@ pub unsafe fn malloc_zeroed(_layout: Layout) -> *mut u8 {
|
||||
///
|
||||
/// Unsafe.
|
||||
pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
|
||||
// debug_trace!("dealloc({:p}, {:?})", ptr, layout);
|
||||
if layout.size() > 0x1000 || layout.align() > 0x1000 {
|
||||
sys::debug_trace("rt::dealloc() invalid align/size");
|
||||
debug_trace!("rt::dealloc() invalid align/size");
|
||||
loop {}
|
||||
}
|
||||
sys::debug_trace("rt::dealloc()");
|
||||
|
||||
sys::unmap_memory(ptr as usize, (layout.size() + 0xFFF) & !0xFFF).ok();
|
||||
}
|
||||
@ -49,11 +50,18 @@ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
|
||||
///
|
||||
/// Unsafe.
|
||||
pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||
sys::debug_trace("rt::realloc()");
|
||||
// debug_trace!("realloc({:p}, {:?}, {}) -> {:p}", ptr, layout, new_size, ptr);
|
||||
if layout.align() > 0x1000 || new_size > 0x1000 || layout.size() > 0x1000 {
|
||||
sys::debug_trace("rt::realloc() invalid align/size/new_size");
|
||||
loop {}
|
||||
}
|
||||
|
||||
ptr
|
||||
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
|
||||
let new_ptr = malloc(new_layout);
|
||||
|
||||
crate::memcpy(new_ptr as *mut _, ptr as *const _, layout.size());
|
||||
|
||||
dealloc(ptr, layout);
|
||||
|
||||
new_ptr
|
||||
}
|
||||
|
41
src/debug.rs
Normal file
41
src/debug.rs
Normal file
@ -0,0 +1,41 @@
|
||||
//! Debug tracing module
|
||||
|
||||
use core::fmt;
|
||||
|
||||
///
|
||||
#[macro_export]
|
||||
macro_rules! debug_trace {
|
||||
($($args:tt)+) => {
|
||||
$crate::debug::_debug_trace(format_args!($($args)+))
|
||||
};
|
||||
}
|
||||
|
||||
struct TracePrinter {
|
||||
buf: [u8; 512],
|
||||
len: usize,
|
||||
}
|
||||
|
||||
impl fmt::Write for TracePrinter {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
for &c in s.as_bytes() {
|
||||
self.buf[self.len] = c;
|
||||
self.len += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn _debug_trace(a: core::fmt::Arguments<'_>) {
|
||||
use fmt::Write;
|
||||
|
||||
let mut printer = TracePrinter { buf: [0; 512], len: 0 };
|
||||
printer.write_fmt(a).ok();
|
||||
|
||||
if printer.len != 0 {
|
||||
unsafe {
|
||||
let s = core::str::from_utf8_unchecked(&printer.buf[..printer.len]);
|
||||
crate::sys::debug_trace(s);
|
||||
}
|
||||
}
|
||||
}
|
38
src/lib.rs
38
src/lib.rs
@ -10,6 +10,7 @@ extern crate yggdrasil_abi as abi;
|
||||
pub use abi::error::Error;
|
||||
pub use abi::path;
|
||||
pub mod alloc;
|
||||
pub mod debug;
|
||||
pub mod netc;
|
||||
pub mod sys;
|
||||
pub mod time;
|
||||
@ -17,21 +18,46 @@ pub mod time;
|
||||
pub mod io {
|
||||
//! I/O data structures
|
||||
|
||||
pub use abi::io::{FileMode, MountOptions, OpenOptions, RawFd, UnmountOptions};
|
||||
pub use abi::io::{
|
||||
DirectoryEntry, FileAttr, FileMode, FileType, MountOptions, OpenOptions, RawFd, SeekFrom,
|
||||
UnmountOptions,
|
||||
};
|
||||
}
|
||||
|
||||
/// Type alias for a raw file descriptor
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn memcmp(_p0: *const c_void, _p1: *const c_void, _len: usize) -> i32 {
|
||||
todo!()
|
||||
unsafe extern "C" fn memcmp(p0: *const c_void, p1: *const c_void, len: usize) -> i32 {
|
||||
let mut offset = 0;
|
||||
|
||||
while offset < len {
|
||||
let c0 = (p0 as *const u8).add(offset).read_volatile();
|
||||
let c1 = (p1 as *const u8).add(offset).read_volatile();
|
||||
|
||||
if c0 > c1 {
|
||||
return (c0 - c1) as i32;
|
||||
} else if c0 < c1 {
|
||||
return -((c1 - c0) as i32);
|
||||
}
|
||||
|
||||
offset += 1;
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn memcpy(p0: *mut c_void, p1: *const c_void, len: usize) -> *mut c_void {
|
||||
if p0 == p1 as _ {
|
||||
sys::debug_trace("memcpy: pointers alias");
|
||||
loop {}
|
||||
}
|
||||
|
||||
let mut offset = 0;
|
||||
while offset < len {
|
||||
(p0 as *mut u8).add(offset).write((p1 as *mut u8).add(offset).read());
|
||||
let c = (p1 as *const u8).add(offset).read_volatile();
|
||||
(p0 as *mut u8).add(offset).write_volatile(c);
|
||||
|
||||
offset += 1;
|
||||
}
|
||||
p0
|
||||
@ -39,14 +65,14 @@ unsafe extern "C" fn memcpy(p0: *mut c_void, p1: *const c_void, len: usize) -> *
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn memmove(_dst: *mut c_void, _src: *const c_void, _len: usize) -> *mut c_void {
|
||||
todo!()
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn memset(dst: *mut c_void, val: i32, len: usize) -> *mut c_void {
|
||||
let mut offset = 0;
|
||||
while offset < len {
|
||||
(dst as *mut u8).add(offset).write(val as u8);
|
||||
(dst as *mut u8).add(offset).write_volatile(val as u8);
|
||||
offset += 1;
|
||||
}
|
||||
dst
|
||||
|
136
src/sys.rs
136
src/sys.rs
@ -1,51 +1,54 @@
|
||||
//! System call implementations
|
||||
use core::time::Duration;
|
||||
use core::{mem::MaybeUninit, time::Duration};
|
||||
|
||||
use abi::{
|
||||
error::{Error, SyscallResult},
|
||||
io::{FileMode, MountOptions, OpenOptions, RawFd, UnmountOptions},
|
||||
io::{
|
||||
DirectoryEntry, FileAttr, FileMode, MountOptions, OpenOptions, RawFd, SeekFrom,
|
||||
UnmountOptions,
|
||||
},
|
||||
syscall::SyscallFunction,
|
||||
};
|
||||
|
||||
macro_rules! syscall {
|
||||
($num:expr) => {{
|
||||
let mut res: usize;
|
||||
core::arch::asm!("svc #0", out("x0") res, in("x8") $num.repr(), options(nostack));
|
||||
core::arch::asm!("svc #0", lateout("x0") res, in("x8") $num.repr());
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr) => {{
|
||||
let mut res: usize = $a0;
|
||||
core::arch::asm!("svc #0",
|
||||
inout("x0") res,
|
||||
in("x8") usize::from($num), options(nostack));
|
||||
inlateout("x0") res,
|
||||
in("x8") usize::from($num));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr) => {{
|
||||
let mut res: usize = $a0;
|
||||
core::arch::asm!("svc #0",
|
||||
inout("x0") res, in("x1") $a1,
|
||||
in("x8") usize::from($num), options(nostack));
|
||||
inlateout("x0") res, in("x1") $a1,
|
||||
in("x8") usize::from($num));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr, $a2:expr) => {{
|
||||
let mut res: usize = $a0;
|
||||
core::arch::asm!("svc #0",
|
||||
inout("x0") res, in("x1") $a1, in("x2") $a2,
|
||||
in("x8") usize::from($num), options(nostack));
|
||||
inlateout("x0") res, in("x1") $a1, in("x2") $a2,
|
||||
in("x8") usize::from($num));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{
|
||||
let mut res: usize = $a0;
|
||||
core::arch::asm!("svc #0",
|
||||
inout("x0") res, in("x1") $a1, in("x2") $a2,
|
||||
in("x3") $a3, in("x8") usize::from($num), options(nostack));
|
||||
inlateout("x0") res, in("x1") $a1, in("x2") $a2,
|
||||
in("x3") $a3, in("x8") usize::from($num));
|
||||
res
|
||||
}};
|
||||
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {{
|
||||
let mut res: usize = $a0;
|
||||
core::arch::asm!("svc #0",
|
||||
inout("x0") res, in("x1") $a1, in("x2") $a2,
|
||||
in("x3") $a3, in("x4") $a4, in("x8") usize::from($num), options(nostack));
|
||||
inlateout("x0") res, in("x1") $a1, in("x2") $a2,
|
||||
in("x3") $a3, in("x4") $a4, in("x8") usize::from($num));
|
||||
res
|
||||
}};
|
||||
}
|
||||
@ -166,9 +169,16 @@ pub unsafe fn read(fd: RawFd, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: direct system call.
|
||||
pub unsafe fn open(path: &str, opts: OpenOptions, mode: FileMode) -> Result<RawFd, Error> {
|
||||
pub unsafe fn open(
|
||||
at: Option<RawFd>,
|
||||
path: &str,
|
||||
opts: OpenOptions,
|
||||
mode: FileMode,
|
||||
) -> Result<RawFd, Error> {
|
||||
let at = at.unwrap_or(RawFd::NONE).0;
|
||||
RawFd::from_syscall_result(syscall!(
|
||||
SyscallFunction::Open,
|
||||
argn!(at),
|
||||
argp!(path.as_ptr()),
|
||||
argn!(path.len()),
|
||||
argn!(opts.bits()),
|
||||
@ -208,3 +218,101 @@ pub unsafe fn mount(options: &MountOptions) -> Result<(), Error> {
|
||||
pub unsafe fn unmount(options: &UnmountOptions) -> Result<(), Error> {
|
||||
<()>::from_syscall_result(syscall!(SyscallFunction::Unmount, argp!(options as *const _)))
|
||||
}
|
||||
|
||||
/// System call: open a directory for reading.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: direct system call.
|
||||
pub unsafe fn open_directory(at: Option<RawFd>, path: &str) -> Result<RawFd, Error> {
|
||||
let at = at.unwrap_or(RawFd::NONE).0;
|
||||
RawFd::from_syscall_result(syscall!(
|
||||
SyscallFunction::OpenDirectory,
|
||||
argn!(at),
|
||||
argp!(path.as_ptr()),
|
||||
argn!(path.len())
|
||||
))
|
||||
}
|
||||
|
||||
/// System call: read information about directory entries into a slice.
|
||||
///
|
||||
/// * fd: directory file descriptor.
|
||||
/// * buffer: buffer to store the entries in.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: direct system call.
|
||||
pub unsafe fn read_directory_entries(
|
||||
fd: RawFd,
|
||||
buffer: &mut [MaybeUninit<DirectoryEntry>],
|
||||
) -> Result<usize, Error> {
|
||||
usize::from_syscall_result(syscall!(
|
||||
SyscallFunction::ReadDirectory,
|
||||
argn!(fd.0),
|
||||
argp!(buffer.as_mut_ptr()),
|
||||
argn!(buffer.len())
|
||||
))
|
||||
}
|
||||
|
||||
/// System call: create a directory.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: direct system call.
|
||||
pub unsafe fn create_directory(at: Option<RawFd>, path: &str, mode: FileMode) -> Result<(), Error> {
|
||||
let at = at.unwrap_or(RawFd::NONE).0;
|
||||
<()>::from_syscall_result(syscall!(
|
||||
SyscallFunction::CreateDirectory,
|
||||
argn!(at),
|
||||
argp!(path.as_ptr()),
|
||||
argn!(path.len()),
|
||||
argn!(mode.bits())
|
||||
))
|
||||
}
|
||||
|
||||
/// System call: remove a filesystem entry.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: direct system call.
|
||||
pub unsafe fn remove(at: Option<RawFd>, path: &str, recurse: bool) -> Result<(), Error> {
|
||||
let at = at.unwrap_or(RawFd::NONE).0;
|
||||
<()>::from_syscall_result(syscall!(
|
||||
SyscallFunction::Remove,
|
||||
argn!(at),
|
||||
argp!(path.as_ptr()),
|
||||
argn!(path.len()),
|
||||
argn!(recurse)
|
||||
))
|
||||
}
|
||||
|
||||
/// System call: retrieve metadata about a filesystem entry.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: direct system call.
|
||||
pub unsafe fn get_metadata(
|
||||
at: Option<RawFd>,
|
||||
path: &str,
|
||||
metadata: &mut MaybeUninit<FileAttr>,
|
||||
follow: bool,
|
||||
) -> Result<(), Error> {
|
||||
let at = at.unwrap_or(RawFd::NONE).0;
|
||||
<()>::from_syscall_result(syscall!(
|
||||
SyscallFunction::GetMetadata,
|
||||
argn!(at),
|
||||
argp!(path.as_ptr()),
|
||||
argn!(path.len()),
|
||||
argp!(metadata.as_ptr()),
|
||||
argn!(follow)
|
||||
))
|
||||
}
|
||||
|
||||
/// System call: seek a file descriptor to given position.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Unsafe: direct system call.
|
||||
pub unsafe fn seek(fd: RawFd, pos: SeekFrom) -> Result<u64, Error> {
|
||||
u64::from_syscall_result(syscall!(SyscallFunction::Seek, argn!(fd.0), argn!(u64::from(pos))))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user