Skip to content

Commit

Permalink
Merge pull request betrusted-io#581 from betrusted-io/xobs/flatipc-0.1.2
Browse files Browse the repository at this point in the history
flatipc: release 0.1.2
  • Loading branch information
bunnie authored Sep 23, 2024
2 parents 222f86d + 8e27dce commit 21c494a
Show file tree
Hide file tree
Showing 4 changed files with 267 additions and 39 deletions.
6 changes: 3 additions & 3 deletions libs/flatipc-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
edition = "2021"
name = "flatipc-derive"
version = "0.1.0"
version = "0.1.2"
authors = ["Sean Cross <[email protected]>"]
description = "Custom derive for traits from the flatipc crate"
license = "BSD-2-Clause OR Apache-2.0 OR MIT"
Expand All @@ -11,8 +11,8 @@ repository = "https://github.com/betrusted/xous-flatipc"
proc-macro = true

[dependencies]
proc-macro2 = "*"
quote = "*"
proc-macro2 = "1"
quote = "1"
syn = { version = "2", features = ["parsing", "extra-traits"] }

[features]
Expand Down
103 changes: 71 additions & 32 deletions libs/flatipc-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,22 @@ use proc_macro::TokenStream;
use quote::{format_ident, quote};
use syn::{parse_macro_input, spanned::Spanned, DeriveInput};

fn ast_hash(ast: &syn::DeriveInput) -> u32 {
fn ast_hash(ast: &syn::DeriveInput) -> usize {
use std::hash::{Hash, Hasher};
let mut hasher = std::collections::hash_map::DefaultHasher::new();
ast.hash(&mut hasher);
let full_hash = hasher.finish();
((full_hash >> 32) as u32) ^ (full_hash as u32)

#[cfg(target_pointer_width = "64")]
{
full_hash as usize
}
#[cfg(target_pointer_width = "32")]
{
(((full_hash >> 32) as u32) ^ (full_hash as u32)) as usize
}
#[cfg(not(any(target_pointer_width = "32", target_pointer_width = "64")))]
compile_error!("Unsupported target_pointer_width");
}

#[proc_macro_derive(IpcSafe)]
Expand Down Expand Up @@ -52,11 +62,10 @@ fn derive_ipc_inner(ast: DeriveInput) -> Result<proc_macro2::TokenStream, proc_m
syn::Data::Union(r#union) => generate_transmittable_checks_union(&ast, r#union)?,
};

let padded_version = generate_padded_version(&ast)?;

let ipc_struct = generate_ipc_struct(&ast)?;
Ok(quote! {
#transmittable_checks
#padded_version
#ipc_struct
})
}

Expand Down Expand Up @@ -222,10 +231,10 @@ fn generate_transmittable_checks_union(
})
}

fn generate_padded_version(ast: &DeriveInput) -> Result<proc_macro2::TokenStream, proc_macro2::TokenStream> {
fn generate_ipc_struct(ast: &DeriveInput) -> Result<proc_macro2::TokenStream, proc_macro2::TokenStream> {
let visibility = ast.vis.clone();
let ident = ast.ident.clone();
let padded_ident = format_ident!("Ipc{}", ast.ident);
let ipc_ident = format_ident!("Ipc{}", ast.ident);
let ident_size = quote! { core::mem::size_of::< #ident >() };
let padded_size = quote! { (#ident_size + (4096 - 1)) & !(4096 - 1) };
let padding_size = quote! { #padded_size - #ident_size };
Expand Down Expand Up @@ -286,96 +295,124 @@ fn generate_padded_version(ast: &DeriveInput) -> Result<proc_macro2::TokenStream
}
};

let memory_messages = if cfg!(feature = "xous") {
quote! {
fn from_memory_message<'a>(msg: &'a xous::MemoryMessage) -> Option<&'a Self> {
if msg.buf.len() < core::mem::size_of::< #ipc_ident >() {
return None;
}
let signature = msg.offset.map(|offset| offset.get()).unwrap_or_default();
if signature != #hash {
return None;
}
unsafe { Some(&*(msg.buf.as_ptr() as *const #ipc_ident)) }
}

fn from_memory_message_mut<'a>(msg: &'a mut xous::MemoryMessage) -> Option<&'a mut Self> {
if msg.buf.len() < core::mem::size_of::< #ipc_ident >() {
return None;
}
let signature = msg.offset.map(|offset| offset.get()).unwrap_or_default();
if signature != #hash {
return None;
}
unsafe { Some(&mut *(msg.buf.as_mut_ptr() as *mut #ipc_ident)) }
}
}
} else {
quote! {}
};

Ok(quote! {
#[repr(C, align(4096))]
#visibility struct #padded_ident {
#visibility struct #ipc_ident {
original: #ident,
padding: [u8; #padding_size],
}

impl core::ops::Deref for #padded_ident {
impl core::ops::Deref for #ipc_ident {
type Target = #ident ;
fn deref(&self) -> &Self::Target {
&self.original
}
}

impl core::ops::DerefMut for #padded_ident {
impl core::ops::DerefMut for #ipc_ident {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.original
}
}

impl flatipc::IntoIpc for #ident {
type IpcType = #padded_ident;
type IpcType = #ipc_ident;
fn into_ipc(self) -> Self::IpcType {
#padded_ident {
#ipc_ident {
original: self,
padding: [0; #padding_size],
}
}
}

impl flatipc::Ipc for #padded_ident {
unsafe impl flatipc::Ipc for #ipc_ident {
type Original = #ident ;

fn from_slice<'a>(data: &'a [u8], signature: usize) -> Option<&'a Self> {
if data.len() < core::mem::size_of::< #padded_ident >() {
if data.len() < core::mem::size_of::< #ipc_ident >() {
return None;
}
if signature as u32 != #hash {
if signature != #hash {
return None;
}
unsafe { Some(&*(data.as_ptr() as *const u8 as *const #padded_ident)) }
unsafe { Some(&*(data.as_ptr() as *const u8 as *const #ipc_ident)) }
}

unsafe fn from_buffer_unchecked<'a>(data: &'a [u8]) -> &'a Self {
&*(data.as_ptr() as *const u8 as *const #padded_ident)
&*(data.as_ptr() as *const u8 as *const #ipc_ident)
}

fn from_slice_mut<'a>(data: &'a mut [u8], signature: usize) -> Option<&'a mut Self> {
if data.len() < core::mem::size_of::< #padded_ident >() {
if data.len() < core::mem::size_of::< #ipc_ident >() {
return None;
}
if signature as u32 != #hash {
if signature != #hash {
return None;
}
unsafe { Some(&mut *(data.as_mut_ptr() as *mut u8 as *mut #padded_ident)) }
unsafe { Some(&mut *(data.as_mut_ptr() as *mut u8 as *mut #ipc_ident)) }
}

unsafe fn from_buffer_mut_unchecked<'a>(data: &'a mut [u8]) -> &'a mut Self {
unsafe { &mut *(data.as_mut_ptr() as *mut u8 as *mut #padded_ident) }
unsafe { &mut *(data.as_mut_ptr() as *mut u8 as *mut #ipc_ident) }
}

fn lend(&self, connection: flatipc::CID, opcode: usize) -> Result<(), flatipc::Error> {
let signature = self.signature() as usize;
let signature = self.signature();
let data = unsafe {
core::slice::from_raw_parts(
self as *const #padded_ident as *const u8,
core::mem::size_of::< #padded_ident >(),
self as *const #ipc_ident as *const u8,
core::mem::size_of::< #ipc_ident >(),
)
};
#lend
Ok(())
}

fn try_lend(&self, connection: flatipc::CID, opcode: usize) -> Result<(), flatipc::Error> {
let signature = self.signature() as usize;
let signature = self.signature();
let data = unsafe {
core::slice::from_raw_parts(
self as *const #padded_ident as *const u8,
core::mem::size_of::< #padded_ident >(),
self as *const #ipc_ident as *const u8,
core::mem::size_of::< #ipc_ident >(),
)
};
#try_lend
Ok(())
}

fn lend_mut(&mut self, connection: flatipc::CID, opcode: usize) -> Result<(), flatipc::Error> {
let signature = self.signature() as usize;
let signature = self.signature();
let mut data = unsafe {
core::slice::from_raw_parts_mut(
self as *mut #padded_ident as *mut u8,
self as *mut #ipc_ident as *mut u8,
#padded_size,
)
};
Expand All @@ -384,10 +421,10 @@ fn generate_padded_version(ast: &DeriveInput) -> Result<proc_macro2::TokenStream
}

fn try_lend_mut(&mut self, connection: flatipc::CID, opcode: usize) -> Result<(), flatipc::Error> {
let signature = self.signature() as usize;
let signature = self.signature();
let mut data = unsafe {
core::slice::from_raw_parts_mut(
self as *mut #padded_ident as *mut u8,
self as *mut #ipc_ident as *mut u8,
#padded_size,
)
};
Expand All @@ -407,9 +444,11 @@ fn generate_padded_version(ast: &DeriveInput) -> Result<proc_macro2::TokenStream
self.original
}

fn signature(&self) -> u32 {
fn signature(&self) -> usize {
#hash
}

#memory_messages
}
})
}
Loading

0 comments on commit 21c494a

Please sign in to comment.