refactor: rename syscall to libsys

This commit is contained in:
2021-11-11 20:45:54 +02:00
parent cd560e79ef
commit 41ffd0ddb7
71 changed files with 76 additions and 76 deletions
+13
View File
@@ -0,0 +1,13 @@
pub const SYS_EX_DEBUG_TRACE: usize = 128;
pub const SYS_EX_NANOSLEEP: usize = 129;
pub const SYS_EXIT: usize = 1;
pub const SYS_READ: usize = 2;
pub const SYS_WRITE: usize = 3;
pub const SYS_OPENAT: usize = 4;
pub const SYS_FSTATAT: usize = 5;
pub const SYS_CLOSE: usize = 6;
pub const SYS_FORK: usize = 7;
pub const SYS_EXECVE: usize = 8;
pub const SYS_WAITPID: usize = 9;
pub const SYS_IOCTL: usize = 10;
+200
View File
@@ -0,0 +1,200 @@
use crate::abi;
use crate::{
ioctl::IoctlCmd,
stat::{FileMode, OpenFlags, Stat},
};
use core::mem::size_of;
// TODO document the syscall ABI
macro_rules! syscall {
($num:expr) => {{
let mut res: usize;
asm!("svc #0", out("x0") res, in("x8") $num, options(nostack));
res
}};
($num:expr, $a0:expr) => {{
let mut res: usize = $a0;
asm!("svc #0",
inout("x0") res,
in("x8") $num, options(nostack));
res
}};
($num:expr, $a0:expr, $a1:expr) => {{
let mut res: usize = $a0;
asm!("svc #0",
inout("x0") res, in("x1") $a1,
in("x8") $num, options(nostack));
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr) => {{
let mut res: usize = $a0;
asm!("svc #0",
inout("x0") res, in("x1") $a1, in("x2") $a2,
in("x8") $num, options(nostack));
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr) => {{
let mut res: usize = $a0;
asm!("svc #0",
inout("x0") res, in("x1") $a1, in("x2") $a2,
in("x3") $a3, in("x8") $num, options(nostack));
res
}};
($num:expr, $a0:expr, $a1:expr, $a2:expr, $a3:expr, $a4:expr) => {{
let mut res: usize = $a0;
asm!("svc #0",
inout("x0") res, in("x1") $a1, in("x2") $a2,
in("x3") $a3, in("x4") $a4, in("x8") $num, options(nostack));
res
}};
}
/// Integer/size argument
macro_rules! argn {
($a:expr) => {
$a as usize
};
}
/// Pointer/base argument
macro_rules! argp {
($a:expr) => {
$a as usize
};
}
// /// Immutable pointer/base argument
// macro_rules! argpi {
// ($a:expr) => ($a as *const core::ffi::c_void as usize)
// }
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_exit(status: i32) -> ! {
syscall!(abi::SYS_EXIT, argn!(status));
unreachable!();
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_close(fd: i32) -> i32 {
syscall!(abi::SYS_CLOSE, argn!(fd)) as i32
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_ex_nanosleep(ns: u64, rem: &mut [u64; 2]) -> i32 {
syscall!(abi::SYS_EX_NANOSLEEP, argn!(ns), argp!(rem.as_mut_ptr())) as i32
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_ex_debug_trace(msg: &[u8]) -> usize {
syscall!(
abi::SYS_EX_DEBUG_TRACE,
argp!(msg.as_ptr()),
argn!(msg.len())
)
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_openat(at: i32, pathname: &str, mode: FileMode, flags: OpenFlags) -> i32 {
syscall!(
abi::SYS_OPENAT,
argn!(at),
argp!(pathname.as_ptr()),
argn!(pathname.len()),
argn!(mode.bits()),
argn!(flags.bits())
) as i32
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_read(fd: i32, data: &mut [u8]) -> isize {
syscall!(
abi::SYS_READ,
argn!(fd),
argp!(data.as_mut_ptr()),
argn!(data.len())
) as isize
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_write(fd: i32, data: &[u8]) -> isize {
syscall!(
abi::SYS_WRITE,
argn!(fd),
argp!(data.as_ptr()),
argn!(data.len())
) as isize
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_fstatat(at: i32, pathname: &str, statbuf: &mut Stat, flags: u32) -> i32 {
syscall!(
abi::SYS_FSTATAT,
argn!(at),
argp!(pathname.as_ptr()),
argn!(pathname.len()),
argp!(statbuf as *mut Stat),
argn!(flags)
) as i32
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_fork() -> i32 {
syscall!(abi::SYS_FORK) as i32
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_execve(pathname: &str) -> i32 {
syscall!(
abi::SYS_EXECVE,
argp!(pathname.as_ptr()),
argn!(pathname.len())
) as i32
}
/// # Safety
///
/// System call
#[inline(always)]
pub unsafe fn sys_waitpid(pid: u32, status: &mut i32) -> i32 {
syscall!(abi::SYS_WAITPID, argn!(pid), argp!(status as *mut i32)) as i32
}
#[inline(always)]
pub unsafe fn sys_ioctl(fd: u32, cmd: IoctlCmd, ptr: usize, len: usize) -> isize {
syscall!(
abi::SYS_IOCTL,
argn!(fd),
argn!(cmd),
argn!(ptr),
argn!(len)
) as isize
}
+21
View File
@@ -0,0 +1,21 @@
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum Errno {
AlreadyExists,
BadExecutable,
Busy,
DeviceError,
DoesNotExist,
EndOfFile,
Interrupt,
InvalidArgument,
InvalidFile,
InvalidOperation,
IsADirectory,
NotADirectory,
NotImplemented,
OutOfMemory,
ReadOnly,
TimedOut,
TooManyDescriptors,
WouldBlock,
}
+22
View File
@@ -0,0 +1,22 @@
use core::convert::TryFrom;
use crate::error::Errno;
#[derive(Clone, Copy, Debug)]
#[repr(u32)]
pub enum IoctlCmd {
TtySetAttributes = 1,
TtyGetAttributes = 2,
}
impl TryFrom<u32> for IoctlCmd {
type Error = Errno;
#[inline]
fn try_from(u: u32) -> Result<IoctlCmd, Errno> {
match u {
1 => Ok(Self::TtySetAttributes),
2 => Ok(Self::TtyGetAttributes),
_ => Err(Errno::InvalidArgument)
}
}
}
+19
View File
@@ -0,0 +1,19 @@
#![feature(asm)]
#![no_std]
#[macro_use]
extern crate bitflags;
pub mod abi;
pub mod stat;
pub mod ioctl;
pub mod termios;
pub mod error;
pub mod path;
pub mod mem;
pub mod traits;
#[cfg(feature = "user")]
pub mod calls;
#[cfg(feature = "user")]
pub use calls::*;
+77
View File
@@ -0,0 +1,77 @@
pub fn read_le32(src: &[u8]) -> u32 {
(src[0] as u32) | ((src[1] as u32) << 8) | ((src[2] as u32) << 16) | ((src[3] as u32) << 24)
}
pub fn read_le16(src: &[u8]) -> u16 {
(src[0] as u16) | ((src[1] as u16) << 8)
}
/// See memcpy(3p).
///
/// # Safety
///
/// Unsafe: writes to arbitrary memory locations, performs no pointer
/// validation.
#[no_mangle]
pub unsafe extern "C" fn memcpy(dst: *mut u8, src: *mut u8, mut len: usize) -> *mut u8 {
while len != 0 {
len -= 1;
*dst.add(len) = *src.add(len);
}
dst
}
/// See memcmp(3p).
///
/// # Safety
///
/// Unsafe: performs reads from arbitrary memory locations, performs no
/// pointer validation.
#[no_mangle]
pub unsafe extern "C" fn memcmp(a: *mut u8, b: *mut u8, mut len: usize) -> isize {
while len != 0 {
len -= 1;
if *a.add(len) < *b.add(len) {
return -1;
}
if *a.add(len) > *b.add(len) {
return 1;
}
}
0
}
/// See memmove(3p)
///
/// # Safety
///
/// Unsafe: writes to arbitrary memory locations, performs no pointer
/// validation.
#[no_mangle]
pub unsafe extern "C" fn memmove(dst: *mut u8, src: *mut u8, len: usize) -> *mut u8 {
if dst < src {
for i in 0..len {
*dst.add(i) = *src.add(i);
}
} else {
for i in 0..len {
*dst.add(len - (i + 1)) = *src.add(len - (i + 1));
}
}
dst
}
/// See memset(3p)
///
/// # Safety
///
/// Unsafe: writes to arbitrary memory locations, performs no pointer
/// validation.
#[no_mangle]
pub unsafe extern "C" fn memset(buf: *mut u8, val: u8, mut len: usize) -> *mut u8 {
while len != 0 {
len -= 1;
*buf.add(len) = val;
}
buf
}
+15
View File
@@ -0,0 +1,15 @@
pub fn path_component_left(path: &str) -> (&str, &str) {
if let Some((left, right)) = path.split_once('/') {
(left, right.trim_start_matches('/'))
} else {
(path, "")
}
}
pub fn path_component_right(path: &str) -> (&str, &str) {
if let Some((left, right)) = path.trim_end_matches('/').rsplit_once('/') {
(left.trim_end_matches('/'), right)
} else {
("", path)
}
}
+53
View File
@@ -0,0 +1,53 @@
pub const AT_FDCWD: i32 = -2;
pub const AT_EMPTY_PATH: u32 = 1 << 16;
pub const STDIN_FILENO: i32 = 0;
pub const STDOUT_FILENO: i32 = 1;
pub const STDERR_FILENO: i32 = 2;
bitflags! {
pub struct OpenFlags: u32 {
const O_RDONLY = 1;
const O_WRONLY = 2;
const O_RDWR = 3;
const O_ACCESS = 0x7;
const O_CREAT = 1 << 4;
const O_EXEC = 1 << 5;
const O_CLOEXEC = 1 << 6;
}
}
bitflags! {
pub struct FileMode: u32 {
const USER_READ = 1 << 8;
const USER_WRITE = 1 << 7;
const USER_EXEC = 1 << 6;
const GROUP_READ = 1 << 5;
const GROUP_WRITE = 1 << 4;
const GROUP_EXEC = 1 << 3;
const OTHER_READ = 1 << 2;
const OTHER_WRITE = 1 << 1;
const OTHER_EXEC = 1 << 0;
}
}
#[derive(Clone, Copy, Debug, Default)]
#[repr(C)]
pub struct Stat {
pub mode: u32,
pub size: u64,
pub blksize: u32,
}
impl FileMode {
/// Returns default permission set for directories
pub const fn default_dir() -> Self {
unsafe { Self::from_bits_unchecked(0o755) }
}
/// Returns default permission set for regular files
pub const fn default_reg() -> Self {
unsafe { Self::from_bits_unchecked(0o644) }
}
}
+80
View File
@@ -0,0 +1,80 @@
bitflags! {
pub struct TermiosIflag: u32 {
/// Translate NL to CR on input
const INLCR = 1 << 0;
/// Translate CR to NL on input
const ICRNL = 1 << 1;
}
pub struct TermiosOflag: u32 {
/// Translate NL to CR-NL on output
const ONLCR = 1 << 0;
}
pub struct TermiosLflag: u32 {
/// Signal processing (INTR, QUIT, SUSP)
const ISIG = 1 << 0;
/// Canonical mode
const ICANON = 1 << 1;
/// Echo input characters
const ECHO = 1 << 2;
/// If ICANON also set, ERASE erases chars, WERASE erases words
const ECHOE = 1 << 3;
/// If ICANON also set, KILL erases line
const ECHOK = 1 << 4;
/// If ICANON also set, echo NL even if ECHO is not set
const ECHONL = 1 << 5;
}
}
#[derive(Debug, Clone)]
pub struct TermiosChars {
pub eof: u8,
pub erase: u8,
pub intr: u8,
pub kill: u8,
pub vlnext: u8,
pub werase: u8,
}
#[derive(Debug, Clone)]
#[repr(C)]
pub struct Termios {
pub iflag: TermiosIflag,
pub oflag: TermiosOflag,
pub lflag: TermiosLflag,
pub chars: TermiosChars
}
impl TermiosChars {
pub const fn new() -> Self {
Self {
eof: 0x04,
erase: 0x7F,
intr: 0x03,
kill: 0x15,
vlnext: 0x16,
werase: 0x17,
}
}
}
impl Termios {
pub const fn new() -> Self {
Self {
iflag: TermiosIflag::ICRNL,
oflag: TermiosOflag::ONLCR,
// TODO prettify this
lflag: unsafe {
TermiosLflag::from_bits_unchecked(
(1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5),
)
},
chars: TermiosChars::new()
}
}
pub const fn is_canon(&self) -> bool {
self.lflag.contains(TermiosLflag::ICANON)
}
}
+28
View File
@@ -0,0 +1,28 @@
use crate::error::Errno;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum SeekDir {
Set,
End,
Current,
}
pub trait Read {
fn read(&mut self, data: &mut [u8]) -> Result<usize, Errno>;
}
pub trait Seek {
fn seek(&mut self, off: isize, whence: SeekDir) -> Result<usize, Errno>;
}
pub trait Write {
fn write(&mut self, data: &[u8]) -> Result<usize, Errno>;
}
pub trait RandomRead {
fn pread(&mut self, pos: usize, data: &mut [u8]) -> Result<usize, Errno>;
}
pub trait RandomWrite {
fn pwrite(&mut self, pos: usize, data: &[u8]) -> Result<usize, Errno>;
}