Better argument passing from kernel
This commit is contained in:
parent
ab13d0fec7
commit
7785a8310f
@ -46,6 +46,7 @@ pub struct UnmountOptions {
|
||||
/// Describes device-specific requests
|
||||
#[derive(Clone, Debug)]
|
||||
#[repr(C)]
|
||||
#[non_exhaustive]
|
||||
pub enum DeviceRequest {
|
||||
/// Configure the terminal's options
|
||||
ConfigureTerminal(terminal::TerminalOptions),
|
||||
@ -64,3 +65,9 @@ impl RawFd {
|
||||
/// Temporary hack to represent `Option<RawFd>::None`
|
||||
pub const NONE: Self = Self(u32::MAX);
|
||||
}
|
||||
|
||||
impl From<u32> for RawFd {
|
||||
fn from(value: u32) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
//! Yggdrasil OS user-kernel communication ABI
|
||||
#![no_std]
|
||||
#![feature(trace_macros, const_trait_impl)]
|
||||
// #![deny(missing_docs)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
pub(crate) mod macros;
|
||||
pub mod pass;
|
||||
|
||||
pub mod arch;
|
||||
pub mod error;
|
||||
pub mod io;
|
||||
pub mod path;
|
||||
pub mod process;
|
||||
pub mod serde;
|
||||
pub mod syscall;
|
||||
|
96
src/pass.rs
Normal file
96
src/pass.rs
Normal file
@ -0,0 +1,96 @@
|
||||
//! Interfaces for passing stuff between the kernel and the userspace
|
||||
// TODO
|
||||
#![allow(missing_docs)]
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
// TODO use NonNull instead
|
||||
pub trait Placer {
|
||||
fn place_ref<T: Place>(&mut self, r: &T) -> Result<*const T::Output, Error>;
|
||||
fn place_slice<T: Place>(&mut self, r: &[T]) -> Result<*const [T::Output], Error>;
|
||||
}
|
||||
|
||||
pub trait Place {
|
||||
type Output: 'static;
|
||||
|
||||
fn place<P: Placer>(&self, placer: &mut P) -> Result<Self::Output, Error>;
|
||||
|
||||
fn place_ref<P: Placer>(&self, placer: &mut P) -> Result<&'static Self::Output, Error>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let ptr = placer.place_ref(self)?;
|
||||
unsafe { Ok(&*ptr) }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_primitive {
|
||||
($($ty:ty),+) => {
|
||||
$(
|
||||
impl $crate::pass::Place for $ty {
|
||||
type Output = $ty;
|
||||
|
||||
fn place<P: $crate::pass::Placer>(&self, _placer: &mut P) -> Result<$ty, Error> {
|
||||
Ok(*self)
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
impl_primitive!(u8, u16, u32, u64, i8, i16, i32, i64, bool, char);
|
||||
|
||||
impl<'s> Place for &'s str {
|
||||
type Output = &'static str;
|
||||
|
||||
fn place<P: Placer>(&self, placer: &mut P) -> Result<Self::Output, Error> {
|
||||
let data = placer.place_slice(self.as_bytes())?;
|
||||
// Safety: safe, object passed in was already a proper &str
|
||||
Ok(unsafe { core::str::from_utf8_unchecked(data.as_ref().unwrap()) })
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Place> Place for [T] {
|
||||
type Output = &'static [T::Output];
|
||||
|
||||
fn place<P: Placer>(&self, placer: &mut P) -> Result<Self::Output, Error> {
|
||||
let data = placer.place_slice(self)?;
|
||||
Ok(unsafe { data.as_ref().unwrap() })
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_place_lifetime {
|
||||
(
|
||||
$( #[ $struct_meta:meta ] )*
|
||||
$struct_vis:vis struct $struct_name:ident<$struct_lifetime:lifetime> {
|
||||
$(
|
||||
$( #[ $field_meta:meta ] )*
|
||||
$field_vis:vis $field_name:ident: $field_ty:ty,
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
$( #[$struct_meta] )*
|
||||
$struct_vis struct $struct_name<$struct_lifetime> {
|
||||
$(
|
||||
$( #[$field_meta] )*
|
||||
$field_vis $field_name: $field_ty
|
||||
),*
|
||||
}
|
||||
|
||||
impl<$struct_lifetime> $crate::pass::Place for $struct_name<$struct_lifetime> {
|
||||
type Output = $struct_name<'static>;
|
||||
|
||||
fn place<P: $crate::pass::Placer>(&self, placer: &mut P)
|
||||
-> Result<Self::Output, $crate::error::Error> {
|
||||
$(
|
||||
let $field_name = self.$field_name.place(placer)?;
|
||||
)*
|
||||
|
||||
Ok($struct_name {
|
||||
$($field_name),*
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
use core::num::NonZeroI32;
|
||||
|
||||
use crate::{arch::SavedFrame, io::RawFd, primitive_enum};
|
||||
use crate::{arch::SavedFrame, impl_place_lifetime, io::RawFd, primitive_enum};
|
||||
|
||||
/// Code signalled by a process when it finishes or is terminated by a signal
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@ -24,6 +24,10 @@ pub enum SpawnOption {
|
||||
/// What FD number should be used in the child
|
||||
child: RawFd,
|
||||
},
|
||||
/// The new process should be placed in the specified group
|
||||
SetProcessGroup(u32),
|
||||
/// Gain terminal control for the given FD
|
||||
GainTerminal(RawFd),
|
||||
}
|
||||
|
||||
primitive_enum! {
|
||||
@ -64,6 +68,18 @@ pub struct SpawnOptions<'a> {
|
||||
pub optional: &'a [SpawnOption],
|
||||
}
|
||||
|
||||
// TODO not sure if I really need #[repr(C)] ABI here
|
||||
impl_place_lifetime! {
|
||||
#[doc = "Argument struct passed from the kernel to a spawned process"]
|
||||
#[derive(Debug)]
|
||||
pub struct ProgramArgumentInner<'a> {
|
||||
#[doc = "Argument list"]
|
||||
pub args: &'a [&'a str],
|
||||
#[doc = "List of KEY=VALUE environment variable pairs"]
|
||||
pub env: &'a [&'a str],
|
||||
}
|
||||
}
|
||||
|
||||
impl ExitCode {
|
||||
/// Returned when a process has exited successfully
|
||||
pub const SUCCESS: Self = Self::Exited(0);
|
||||
|
97
src/serde.rs
97
src/serde.rs
@ -1,97 +0,0 @@
|
||||
use core::ops::DerefMut;
|
||||
|
||||
use crate::error::Error;
|
||||
|
||||
pub trait SerializeBuffer {
|
||||
fn write_bytes(&mut self, data: &[u8]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
pub trait DeserializeBuffer {
|
||||
fn read_bytes(&mut self, data: &mut [u8]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
pub unsafe trait Serialize {
|
||||
fn serialize<B: SerializeBuffer>(&self, target: &mut B) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
pub trait Deserialize: Sized {
|
||||
unsafe fn deserialize<B: DeserializeBuffer>(source: &mut B) -> Result<Self, Error>;
|
||||
}
|
||||
|
||||
pub struct SliceSerializeBuffer<T: DerefMut<Target = [u8]>> {
|
||||
data: T,
|
||||
}
|
||||
|
||||
impl<T: DerefMut<Target = [u8]>> SliceSerializeBuffer<T> {
|
||||
pub fn new(data: T) -> Self {
|
||||
Self { data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: DerefMut<Target = [u8]>> SerializeBuffer for SliceSerializeBuffer<T> {
|
||||
fn write_bytes(&mut self, data: &[u8]) -> Result<(), Error> {
|
||||
if data.len() > self.data.len() {
|
||||
return Err(Error::InvalidArgument);
|
||||
}
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! int_serde_impl {
|
||||
($ty:ty) => {
|
||||
unsafe impl Serialize for $ty {
|
||||
fn serialize<B: SerializeBuffer>(&self, target: &mut B) -> Result<(), Error> {
|
||||
target.write_bytes(&self.to_ne_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for $ty {
|
||||
unsafe fn deserialize<B: DeserializeBuffer>(source: &mut B) -> Result<Self, Error> {
|
||||
let mut bytes = [0; core::mem::size_of::<Self>()];
|
||||
source.read_bytes(&mut bytes)?;
|
||||
Ok(Self::from_ne_bytes(bytes))
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
int_serde_impl!(usize);
|
||||
int_serde_impl!(u64);
|
||||
int_serde_impl!(u32);
|
||||
int_serde_impl!(u16);
|
||||
|
||||
unsafe impl Serialize for u8 {
|
||||
fn serialize<B: SerializeBuffer>(&self, target: &mut B) -> Result<(), Error> {
|
||||
target.write_bytes(&[*self])
|
||||
}
|
||||
}
|
||||
|
||||
impl Deserialize for u8 {
|
||||
unsafe fn deserialize<B: DeserializeBuffer>(source: &mut B) -> Result<Self, Error> {
|
||||
let mut buffer = [0; 1];
|
||||
source.read_bytes(&mut buffer)?;
|
||||
Ok(buffer[0])
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Serialize> Serialize for [T] {
|
||||
fn serialize<B: SerializeBuffer>(&self, target: &mut B) -> Result<(), Error> {
|
||||
self.len().serialize(target)?;
|
||||
for item in self.iter() {
|
||||
item.serialize(target)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Serialize for str {
|
||||
fn serialize<B: SerializeBuffer>(&self, target: &mut B) -> Result<(), Error> {
|
||||
self.as_bytes().serialize(target)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T: Serialize + ?Sized> Serialize for &T {
|
||||
fn serialize<B: SerializeBuffer>(&self, target: &mut B) -> Result<(), Error> {
|
||||
(*self).serialize(target)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user