From 7785a8310f9c30a0c5df41cc439ab56a0a829398 Mon Sep 17 00:00:00 2001 From: Mark Poliakov Date: Thu, 16 Nov 2023 16:14:04 +0200 Subject: [PATCH] Better argument passing from kernel --- src/io/mod.rs | 7 ++++ src/lib.rs | 4 +-- src/pass.rs | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ src/process.rs | 18 +++++++++- src/serde.rs | 97 -------------------------------------------------- 5 files changed, 122 insertions(+), 100 deletions(-) create mode 100644 src/pass.rs delete mode 100644 src/serde.rs diff --git a/src/io/mod.rs b/src/io/mod.rs index 30988a6d..baec0baf 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -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::None` pub const NONE: Self = Self(u32::MAX); } + +impl From for RawFd { + fn from(value: u32) -> Self { + Self(value) + } +} diff --git a/src/lib.rs b/src/lib.rs index d5e0f297..8fd49b5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/pass.rs b/src/pass.rs new file mode 100644 index 00000000..80d6e282 --- /dev/null +++ b/src/pass.rs @@ -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(&mut self, r: &T) -> Result<*const T::Output, Error>; + fn place_slice(&mut self, r: &[T]) -> Result<*const [T::Output], Error>; +} + +pub trait Place { + type Output: 'static; + + fn place(&self, placer: &mut P) -> Result; + + fn place_ref(&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(&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(&self, placer: &mut P) -> Result { + 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 Place for [T] { + type Output = &'static [T::Output]; + + fn place(&self, placer: &mut P) -> Result { + 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(&self, placer: &mut P) + -> Result { + $( + let $field_name = self.$field_name.place(placer)?; + )* + + Ok($struct_name { + $($field_name),* + }) + } + } + }; +} diff --git a/src/process.rs b/src/process.rs index cb6eebf3..a0e47234 100644 --- a/src/process.rs +++ b/src/process.rs @@ -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); diff --git a/src/serde.rs b/src/serde.rs deleted file mode 100644 index 08ad0ca5..00000000 --- a/src/serde.rs +++ /dev/null @@ -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(&self, target: &mut B) -> Result<(), Error>; -} - -pub trait Deserialize: Sized { - unsafe fn deserialize(source: &mut B) -> Result; -} - -pub struct SliceSerializeBuffer> { - data: T, -} - -impl> SliceSerializeBuffer { - pub fn new(data: T) -> Self { - Self { data } - } -} - -impl> SerializeBuffer for SliceSerializeBuffer { - 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(&self, target: &mut B) -> Result<(), Error> { - target.write_bytes(&self.to_ne_bytes()) - } - } - - impl Deserialize for $ty { - unsafe fn deserialize(source: &mut B) -> Result { - let mut bytes = [0; core::mem::size_of::()]; - 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(&self, target: &mut B) -> Result<(), Error> { - target.write_bytes(&[*self]) - } -} - -impl Deserialize for u8 { - unsafe fn deserialize(source: &mut B) -> Result { - let mut buffer = [0; 1]; - source.read_bytes(&mut buffer)?; - Ok(buffer[0]) - } -} - -unsafe impl Serialize for [T] { - fn serialize(&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(&self, target: &mut B) -> Result<(), Error> { - self.as_bytes().serialize(target) - } -} - -unsafe impl Serialize for &T { - fn serialize(&self, target: &mut B) -> Result<(), Error> { - (*self).serialize(target) - } -}