Initial commit

This commit is contained in:
Mark Poliakov 2023-07-18 17:57:20 +03:00
commit 7ed747351a
6 changed files with 272 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

15
Cargo.toml Normal file
View File

@ -0,0 +1,15 @@
[package]
name = "yggdrasil-abi"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
core = { version = "1.0.0", optional = true, package = "rustc-std-workspace-core" }
alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" }
compiler_builtins = { version = "0.1", optional = true }
[features]
default = []
rustc-dep-of-std = ["core", "alloc", "compiler_builtins/rustc-dep-of-std"]

130
src/error.rs Normal file
View File

@ -0,0 +1,130 @@
use crate::io::RawFd;
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Error {
OutOfMemory = 1,
InvalidMemoryOperation,
AlreadyExists,
TimedOut,
InvalidArgument,
DoesNotExist,
IsADirectory,
InvalidFile,
}
pub trait FromSyscallResult: Sized {
fn from_syscall_result(value: usize) -> Result<Self, Error>;
}
pub trait IntoSyscallResult {
fn into_syscall_result(self) -> usize;
}
pub trait SyscallError {
fn from_syscall_error(value: usize) -> Self;
fn into_syscall_error(self) -> usize;
}
impl TryFrom<u32> for Error {
type Error = ();
fn try_from(value: u32) -> Result<Self, ()> {
match value {
1 => Ok(Self::OutOfMemory),
2 => Ok(Self::InvalidMemoryOperation),
3 => Ok(Self::AlreadyExists),
4 => Ok(Self::TimedOut),
5 => Ok(Self::InvalidArgument),
6 => Ok(Self::DoesNotExist),
7 => Ok(Self::IsADirectory),
8 => Ok(Self::InvalidFile),
_ => Err(()),
}
}
}
impl From<Error> for u32 {
fn from(value: Error) -> Self {
match value {
Error::OutOfMemory => 1,
Error::InvalidMemoryOperation => 2,
Error::AlreadyExists => 3,
Error::TimedOut => 4,
Error::InvalidArgument => 5,
Error::DoesNotExist => 6,
Error::IsADirectory => 7,
Error::InvalidFile => 8,
}
}
}
impl SyscallError for Error {
fn from_syscall_error(value: usize) -> Self {
Error::try_from((-(value as isize)) as u32).unwrap_or(Error::InvalidArgument)
}
fn into_syscall_error(self) -> usize {
(-((self as u32) as isize)) as usize
}
}
impl<T: IntoSyscallResult> IntoSyscallResult for Result<T, Error> {
fn into_syscall_result(self) -> usize {
match self {
Ok(t) => t.into_syscall_result(),
Err(e) => e.into_syscall_error(),
}
}
}
impl FromSyscallResult for () {
fn from_syscall_result(value: usize) -> Result<Self, Error> {
if (value as isize) < 0 {
Err(Error::from_syscall_error(value))
} else {
// TODO assert value == 0
Ok(())
}
}
}
impl IntoSyscallResult for () {
fn into_syscall_result(self) -> usize {
0
}
}
impl FromSyscallResult for usize {
fn from_syscall_result(value: usize) -> Result<Self, Error> {
if (value as isize) < 0 {
Err(Error::from_syscall_error(value))
} else {
Ok(value)
}
}
}
impl IntoSyscallResult for usize {
fn into_syscall_result(self) -> usize {
assert!((self as isize) >= 0);
self
}
}
impl FromSyscallResult for RawFd {
fn from_syscall_result(value: usize) -> Result<Self, Error> {
if (value as isize) < 0 {
Err(Error::from_syscall_error(value))
} else {
// TODO assert value < u32::MAX
Ok(RawFd(value as u32))
}
}
}
impl IntoSyscallResult for RawFd {
fn into_syscall_result(self) -> usize {
self.0 as usize
}
}

48
src/io.rs Normal file
View File

@ -0,0 +1,48 @@
use core::fmt;
#[derive(Clone, Copy, PartialEq, Debug, PartialOrd, Ord, Eq)]
pub struct RawFd(pub u32);
#[derive(Clone, Copy, PartialEq, Eq)]
pub struct OpenFlags(pub u32);
const O_READ: u32 = 1 << 0;
const O_WRITE: u32 = 1 << 1;
impl RawFd {
pub const STDOUT: Self = Self(1);
pub const STDERR: Self = Self(2);
}
impl OpenFlags {
pub fn new() -> Self {
Self(0)
}
pub const fn read(mut self) -> Self {
self.0 |= O_READ;
self
}
pub const fn write(mut self) -> Self {
self.0 |= O_WRITE;
self
}
pub const fn is_read(self) -> bool {
self.0 & O_READ != 0
}
pub const fn is_write(self) -> bool {
self.0 & O_WRITE != 0
}
}
impl fmt::Debug for OpenFlags {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("OpenFlags")
.field("read", &(self.is_read()))
.field("write", &(self.is_write()))
.finish()
}
}

57
src/lib.rs Normal file
View File

@ -0,0 +1,57 @@
#![no_std]
pub mod error;
pub mod io;
pub mod path;
#[derive(Clone, Copy, Debug)]
pub enum SyscallFunction {
Exit = 1,
Nanosleep = 2,
MapMemory = 3,
UnmapMemory = 4,
Write = 5,
Read = 6,
Open = 7,
Close = 8,
DebugTrace = 128,
}
impl TryFrom<usize> for SyscallFunction {
type Error = ();
fn try_from(value: usize) -> Result<Self, Self::Error> {
match value {
1 => Ok(Self::Exit),
2 => Ok(Self::Nanosleep),
3 => Ok(Self::MapMemory),
4 => Ok(Self::UnmapMemory),
5 => Ok(Self::Write),
6 => Ok(Self::Read),
7 => Ok(Self::Open),
8 => Ok(Self::Close),
128 => Ok(Self::DebugTrace),
_ => Err(()),
}
}
}
impl From<SyscallFunction> for usize {
fn from(value: SyscallFunction) -> Self {
match value {
SyscallFunction::Exit => 1,
SyscallFunction::Nanosleep => 2,
SyscallFunction::MapMemory => 3,
SyscallFunction::UnmapMemory => 4,
SyscallFunction::Write => 5,
SyscallFunction::Read => 6,
SyscallFunction::Open => 7,
SyscallFunction::Close => 8,
SyscallFunction::DebugTrace => 128,
}
}
}

21
src/path.rs Normal file
View File

@ -0,0 +1,21 @@
pub const PARENT_NAME: &'static str = "..";
pub const SELF_NAME: &'static str = ".";
pub const SEPARATOR_STR: &'static str = "/";
pub const SEPARATOR: char = '/';
pub fn split_left(path: &str) -> (&str, &str) {
if let Some((left, right)) = path.split_once(SEPARATOR) {
(left, right.trim_start_matches(SEPARATOR))
} else {
(path, "")
}
}
pub fn split_right(path: &str) -> (&str, &str) {
if let Some((left, right)) = path.trim_end_matches(SEPARATOR).rsplit_once(SEPARATOR) {
(left.trim_end_matches(SEPARATOR), right)
} else {
("", path)
}
}