Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions library/std/src/sys/args/xous.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
pub use super::common::Args;
use crate::sys::pal::os::get_application_parameters;
use crate::sys::pal::os::params::ArgumentList;
use crate::sys::pal::params::{self, ArgumentList};

pub fn args() -> Args {
let Some(params) = get_application_parameters() else {
let Some(params) = params::get() else {
return Args::new(vec![]);
};

Expand Down
4 changes: 2 additions & 2 deletions library/std/src/sys/env/xous.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::ffi::{OsStr, OsString};
use crate::io;
use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
use crate::sync::{Mutex, Once};
use crate::sys::pal::os::{get_application_parameters, params};
use crate::sys::pal::params;

static ENV: Atomic<usize> = AtomicUsize::new(0);
static ENV_INIT: Once = Once::new();
Expand All @@ -13,7 +13,7 @@ type EnvStore = Mutex<HashMap<OsString, OsString>>;
fn get_env_store() -> &'static EnvStore {
ENV_INIT.call_once(|| {
let env_store = EnvStore::default();
if let Some(params) = get_application_parameters() {
if let Some(params) = params::get() {
for param in params {
if let Ok(envs) = params::EnvironmentBlock::try_from(&param) {
let mut env_store = env_store.lock().unwrap();
Expand Down
48 changes: 48 additions & 0 deletions library/std/src/sys/pal/xous/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,55 @@
#![forbid(unsafe_op_in_unsafe_fn)]

pub mod os;
pub mod params;

#[path = "../unsupported/common.rs"]
mod common;
pub use common::*;

#[cfg(not(test))]
#[cfg(feature = "panic-unwind")]
mod eh_unwinding {
pub(crate) struct EhFrameFinder;
pub(crate) static mut EH_FRAME_ADDRESS: usize = 0;
pub(crate) static EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder;

unsafe impl unwind::EhFrameFinder for EhFrameFinder {
fn find(&self, _pc: usize) -> Option<unwind::FrameInfo> {
if unsafe { EH_FRAME_ADDRESS == 0 } {
None
} else {
Some(unwind::FrameInfo {
text_base: None,
kind: unwind::FrameInfoKind::EhFrame(unsafe { EH_FRAME_ADDRESS }),
})
}
}
}
}

#[cfg(not(test))]
mod c_compat {
use crate::os::xous::ffi::exit;

unsafe extern "C" {
fn main() -> u32;
}

#[unsafe(no_mangle)]
pub extern "C" fn abort() {
exit(1);
}

#[unsafe(no_mangle)]
pub extern "C" fn _start(eh_frame: usize, params: *mut u8) {
#[cfg(feature = "panic-unwind")]
{
unsafe { super::eh_unwinding::EH_FRAME_ADDRESS = eh_frame };
unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok();
}

unsafe { super::params::set(params) };
exit(unsafe { main() });
}
}
63 changes: 0 additions & 63 deletions library/std/src/sys/pal/xous/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,66 +2,8 @@ use super::unsupported;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
use crate::sync::atomic::{Atomic, AtomicPtr, Ordering};
use crate::{fmt, io};

pub(crate) mod params;

static PARAMS_ADDRESS: Atomic<*mut u8> = AtomicPtr::new(core::ptr::null_mut());

#[cfg(not(test))]
#[cfg(feature = "panic-unwind")]
mod eh_unwinding {
pub(crate) struct EhFrameFinder;
pub(crate) static mut EH_FRAME_ADDRESS: usize = 0;
pub(crate) static EH_FRAME_SETTINGS: EhFrameFinder = EhFrameFinder;

unsafe impl unwind::EhFrameFinder for EhFrameFinder {
fn find(&self, _pc: usize) -> Option<unwind::FrameInfo> {
if unsafe { EH_FRAME_ADDRESS == 0 } {
None
} else {
Some(unwind::FrameInfo {
text_base: None,
kind: unwind::FrameInfoKind::EhFrame(unsafe { EH_FRAME_ADDRESS }),
})
}
}
}
}

#[cfg(not(test))]
mod c_compat {
use crate::os::xous::ffi::exit;
unsafe extern "C" {
fn main() -> u32;
}

#[unsafe(no_mangle)]
pub extern "C" fn abort() {
exit(1);
}

#[unsafe(no_mangle)]
pub extern "C" fn _start(eh_frame: usize, params_address: usize) {
#[cfg(feature = "panic-unwind")]
{
unsafe { super::eh_unwinding::EH_FRAME_ADDRESS = eh_frame };
unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok();
}

if params_address != 0 {
let params_address = crate::ptr::with_exposed_provenance_mut::<u8>(params_address);
if unsafe {
super::params::ApplicationParameters::new_from_ptr(params_address).is_some()
} {
super::PARAMS_ADDRESS.store(params_address, core::sync::atomic::Ordering::Relaxed);
}
}
exit(unsafe { main() });
}
}

pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}
Expand Down Expand Up @@ -106,11 +48,6 @@ pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
}

pub(crate) fn get_application_parameters() -> Option<params::ApplicationParameters> {
let params_address = PARAMS_ADDRESS.load(Ordering::Relaxed);
unsafe { params::ApplicationParameters::new_from_ptr(params_address) }
}

pub fn temp_dir() -> PathBuf {
panic!("no filesystem on this platform")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,75 +1,100 @@
/// Xous passes a pointer to the parameter block as the second argument.
/// This is used for passing flags such as environment variables. The
/// format of the argument block is:
///
/// #[repr(C)]
/// struct BlockHeader {
/// /// Magic number that identifies this block. Must be printable ASCII.
/// magic: [u8; 4],
///
/// /// The size of the data block. Does not include this header. May be 0.
/// size: u32,
///
/// /// The contents of this block. Varies depending on the block type.
/// data: [u8; 0],
/// }
///
/// There is a BlockHeader at the start that has magic `AppP`, and the data
/// that follows is the number of blocks present:
///
/// #[repr(C)]
/// struct ApplicationParameters {
/// magic: b"AppP",
/// size: 4u32,
///
/// /// The size of the entire application slice, in bytes, including all headers
/// length: u32,
///
/// /// Number of application parameters present. Must be at least 1 (this block)
/// entries: (parameter_count as u32).to_bytes_le(),
/// }
///
/// #[repr(C)]
/// struct EnvironmentBlock {
/// magic: b"EnvB",
///
/// /// Total number of bytes, excluding this header
/// size: 2+data.len(),
///
/// /// The number of environment variables
/// count: u16,
///
/// /// Environment variable iteration
/// data: [u8; 0],
/// }
///
/// Environment variables are present in an `EnvB` block. The `data` section is
/// a sequence of bytes of the form:
///
/// (u16 /* key_len */; [0u8; key_len as usize] /* key */,
/// u16 /* val_len */ [0u8; val_len as usize])
///
/// #[repr(C)]
/// struct ArgumentList {
/// magic: b"ArgL",
///
/// /// Total number of bytes, excluding this header
/// size: 2+data.len(),
///
/// /// The number of arguments variables
/// count: u16,
///
/// /// Argument variable iteration
/// data: [u8; 0],
/// }
///
/// Args are just an array of strings that represent command line arguments.
/// They are a sequence of the form:
///
/// (u16 /* val_len */ [0u8; val_len as usize])
use core::slice;
//! Xous passes a pointer to the parameter block as the second argument.
//! This is used for passing flags such as environment variables. The
//! format of the argument block is:
//!
//! #[repr(C)]
//! struct BlockHeader {
//! /// Magic number that identifies this block. Must be printable ASCII.
//! magic: [u8; 4],
//!
//! /// The size of the data block. Does not include this header. May be 0.
//! size: u32,
//!
//! /// The contents of this block. Varies depending on the block type.
//! data: [u8; 0],
//! }
//!
//! There is a BlockHeader at the start that has magic `AppP`, and the data
//! that follows is the number of blocks present:
//!
//! #[repr(C)]
//! struct ApplicationParameters {
//! magic: b"AppP",
//! size: 4u32,
//!
//! /// The size of the entire application slice, in bytes, including all headers
//! length: u32,
//!
//! /// Number of application parameters present. Must be at least 1 (this block)
//! entries: (parameter_count as u32).to_bytes_le(),
//! }
//!
//! #[repr(C)]
//! struct EnvironmentBlock {
//! magic: b"EnvB",
//!
//! /// Total number of bytes, excluding this header
//! size: 2+data.len(),
//!
//! /// The number of environment variables
//! count: u16,
//!
//! /// Environment variable iteration
//! data: [u8; 0],
//! }
//!
//! Environment variables are present in an `EnvB` block. The `data` section is
//! a sequence of bytes of the form:
//!
//! (u16 /* key_len */; [0u8; key_len as usize] /* key */,
//! u16 /* val_len */ [0u8; val_len as usize])
//!
//! #[repr(C)]
//! struct ArgumentList {
//! magic: b"ArgL",
//!
//! /// Total number of bytes, excluding this header
//! size: 2+data.len(),
//!
//! /// The number of arguments variables
//! count: u16,
//!
//! /// Argument variable iteration
//! data: [u8; 0],
//! }
//!
//! Args are just an array of strings that represent command line arguments.
//! They are a sequence of the form:
//!
//! (u16 /* val_len */ [0u8; val_len as usize])

use crate::ffi::OsString;
use crate::slice;

#[cfg(test)]
mod tests;

static mut PARAMS: *mut u8 = crate::ptr::null_mut();

/// Remember the location of the parameter block.
///
/// # Safety
/// * This function may only be called before `main`.
/// * `data` must either be `null` or point to a valid parameter block.
pub(super) unsafe fn set(data: *mut u8) {
// SAFETY:
// Since this function is called before `main`, there cannot be any threads
// already running. Thus this write cannot race, and all threads will observe
// this write and the parameter block initialization since it happens-before
// their creation.
unsafe { PARAMS = data };
}

pub(crate) fn get() -> Option<ApplicationParameters> {
// SAFETY: See above.
let data = unsafe { PARAMS };
unsafe { ApplicationParameters::new_from_ptr(data) }
}

/// Magic number indicating we have an environment block
const ENV_MAGIC: [u8; 4] = *b"EnvB";
Expand All @@ -80,17 +105,14 @@ const ARGS_MAGIC: [u8; 4] = *b"ArgL";
/// Magic number indicating the loader has passed application parameters
const PARAMS_MAGIC: [u8; 4] = *b"AppP";

#[cfg(test)]
mod tests;

pub(crate) struct ApplicationParameters {
data: &'static [u8],
offset: usize,
_entries: usize,
}

impl ApplicationParameters {
pub(crate) unsafe fn new_from_ptr(data: *const u8) -> Option<ApplicationParameters> {
unsafe fn new_from_ptr(data: *const u8) -> Option<ApplicationParameters> {
if data.is_null() {
return None;
}
Expand Down
Loading