Implement stubs for directory/fs system calls

This commit is contained in:
Mark Poliakov 2023-07-22 17:36:39 +03:00
parent 84de8cc141
commit a3456a5b99
4 changed files with 209 additions and 26 deletions

View File

@ -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
View 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);
}
}
}

View File

@ -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

View File

@ -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))))
}