Skip to content

Commit 7304cf4

Browse files
committed
std: xous: add support for args and env
Process arguments and environment variables are both passed by way of Application Parameters. These are a TLV format that gets passed in as the second process argument. This patch combines both as they are very similar in their decode. Signed-off-by: Sean Cross <sean@osdyne.com>
1 parent dcdb192 commit 7304cf4

5 files changed

Lines changed: 504 additions & 32 deletions

File tree

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
usecrate::ffi::OsString;
2+
usecrate::sys::pal::xous::os::get_application_parameters;
3+
usecrate::sys::pal::xous::os::params::ArgumentList;
4+
usecrate::{fmt, vec};
5+
6+
pubstructArgs{
7+
parsed_args_list: vec::IntoIter<OsString>,
8+
}
9+
10+
pubfnargs() -> Args{
11+
letSome(params) = get_application_parameters()else{
12+
returnArgs{parsed_args_list:vec![].into_iter()};
13+
};
14+
15+
for param in params {
16+
ifletOk(args) = ArgumentList::try_from(&param){
17+
letmut parsed_args = vec![];
18+
for arg in args {
19+
parsed_args.push(arg.into());
20+
}
21+
returnArgs{parsed_args_list: parsed_args.into_iter()};
22+
}
23+
}
24+
Args{parsed_args_list:vec![].into_iter()}
25+
}
26+
27+
impl fmt::DebugforArgs{
28+
fnfmt(&self,f:&mut fmt::Formatter<'_>) -> fmt::Result{
29+
self.parsed_args_list.as_slice().fmt(f)
30+
}
31+
}
32+
33+
implIteratorforArgs{
34+
typeItem = OsString;
35+
fnnext(&mutself) -> Option<OsString>{
36+
self.parsed_args_list.next()
37+
}
38+
fnsize_hint(&self) -> (usize,Option<usize>){
39+
self.parsed_args_list.size_hint()
40+
}
41+
}
42+
43+
implDoubleEndedIteratorforArgs{
44+
fnnext_back(&mutself) -> Option<OsString>{
45+
self.parsed_args_list.next_back()
46+
}
47+
}
48+
49+
implExactSizeIteratorforArgs{
50+
fnlen(&self) -> usize{
51+
self.parsed_args_list.len()
52+
}
53+
}

‎library/std/src/sys/pal/xous/mod.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#![forbid(unsafe_op_in_unsafe_fn)]
22

3-
#[path = "../unsupported/args.rs"]
43
pubmod args;
54
#[path = "../unsupported/env.rs"]
65
pubmod env;

‎library/std/src/sys/pal/xous/os.rs‎

Lines changed: 105 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,35 @@
11
usesuper::unsupported;
2+
usecrate::collections::HashMap;
23
usecrate::error::ErrorasStdError;
34
usecrate::ffi::{OsStr,OsString};
45
usecrate::marker::PhantomData;
56
usecrate::os::xous::ffi::ErrorasXousError;
67
usecrate::path::{self,PathBuf};
7-
usecrate::{fmt, io};
8+
usecrate::sync::atomic::{AtomicPtr,AtomicUsize,Ordering};
9+
usecrate::sync::{Mutex,Once};
10+
usecrate::{fmt, io, vec};
11+
12+
pub(crate)mod params;
13+
14+
staticPARAMS_ADDRESS:AtomicPtr<u8> = AtomicPtr::new(core::ptr::null_mut());
815

916
#[cfg(not(test))]
1017
#[cfg(feature = "panic_unwind")]
1118
mod eh_unwinding {
12-
pub(crate)structEhFrameFinder(usize/* eh_frame */);
13-
pub(crate)staticmutEH_FRAME_SETTINGS:EhFrameFinder = EhFrameFinder(0);
14-
implEhFrameFinder{
15-
pub(crate)unsafefninit(&mutself,eh_frame:usize){
16-
unsafe{
17-
EH_FRAME_SETTINGS.0 = eh_frame;
18-
}
19-
}
20-
}
19+
pub(crate)structEhFrameFinder;
20+
pub(crate)staticmutEH_FRAME_ADDRESS:usize = 0;
21+
pub(crate)staticEH_FRAME_SETTINGS:EhFrameFinder = EhFrameFinder;
22+
2123
unsafeimpl unwind::EhFrameFinderforEhFrameFinder{
2224
fnfind(&self,_pc:usize) -> Option<unwind::FrameInfo>{
23-
Some(unwind::FrameInfo{
24-
text_base:None,
25-
kind: unwind::FrameInfoKind::EhFrame(self.0),
26-
})
25+
ifunsafe{EH_FRAME_ADDRESS == 0}{
26+
None
27+
}else{
28+
Some(unwind::FrameInfo{
29+
text_base:None,
30+
kind: unwind::FrameInfoKind::EhFrame(unsafe{EH_FRAME_ADDRESS}),
31+
})
32+
}
2733
}
2834
}
2935
}
@@ -41,12 +47,21 @@ mod c_compat {
4147
}
4248

4349
#[no_mangle]
44-
pubextern"C"fn_start(eh_frame:usize){
50+
pubextern"C"fn_start(eh_frame:usize,params_address:usize){
4551
#[cfg(feature = "panic_unwind")]
46-
unsafe{
47-
super::eh_unwinding::EH_FRAME_SETTINGS.init(eh_frame);
52+
{
53+
unsafe{super::eh_unwinding::EH_FRAME_ADDRESS = eh_frame};
4854
unwind::set_custom_eh_frame_finder(&super::eh_unwinding::EH_FRAME_SETTINGS).ok();
4955
}
56+
57+
if params_address != 0{
58+
let params_address = crate::ptr::with_exposed_provenance_mut::<u8>(params_address);
59+
ifunsafe{
60+
super::params::ApplicationParameters::new_from_ptr(params_address).is_some()
61+
}{
62+
super::PARAMS_ADDRESS.store(params_address, core::sync::atomic::Ordering::Relaxed);
63+
}
64+
}
5065
exit(unsafe{main()});
5166
}
5267

@@ -116,44 +131,103 @@ pub fn current_exe() -> io::Result<PathBuf> {
116131
unsupported()
117132
}
118133

119-
pubstructEnv(!);
134+
pub(crate)fnget_application_parameters() -> Option<params::ApplicationParameters>{
135+
let params_address = PARAMS_ADDRESS.load(Ordering::Relaxed);
136+
unsafe{ params::ApplicationParameters::new_from_ptr(params_address)}
137+
}
138+
139+
// ---------- Environment handling ---------- //
140+
staticENV:AtomicUsize = AtomicUsize::new(0);
141+
staticENV_INIT:Once = Once::new();
142+
typeEnvStore = Mutex<HashMap<OsString,OsString>>;
143+
144+
fnget_env_store() -> &'staticEnvStore{
145+
ENV_INIT.call_once(|| {
146+
let env_store = EnvStore::default();
147+
ifletSome(params) = get_application_parameters(){
148+
for param in params {
149+
ifletOk(envs) = params::EnvironmentBlock::try_from(&param){
150+
letmut env_store = env_store.lock().unwrap();
151+
for env in envs {
152+
env_store.insert(env.key.into(), env.value.into());
153+
}
154+
break;
155+
}
156+
}
157+
}
158+
ENV.store(Box::into_raw(Box::new(env_store))as_,Ordering::Relaxed)
159+
});
160+
unsafe{&*core::ptr::with_exposed_provenance::<EnvStore>(ENV.load(Ordering::Relaxed))}
161+
}
162+
163+
pubstructEnv{
164+
iter: vec::IntoIter<(OsString,OsString)>,
165+
}
166+
167+
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
168+
pubstructEnvStrDebug<'a>{
169+
slice:&'a[(OsString,OsString)],
170+
}
171+
172+
impl fmt::DebugforEnvStrDebug<'_>{
173+
fnfmt(&self,f:&mut fmt::Formatter<'_>) -> fmt::Result{
174+
letSelf{ slice } = self;
175+
f.debug_list()
176+
.entries(slice.iter().map(|(a, b)| (a.to_str().unwrap(), b.to_str().unwrap())))
177+
.finish()
178+
}
179+
}
120180

121181
implEnv{
122182
// FIXME(https://github.com/rust-lang/rust/issues/114583): Remove this when <OsStr as Debug>::fmt matches <str as Debug>::fmt.
123183
pubfnstr_debug(&self) -> impl fmt::Debug + '_{
124-
letSelf(inner) = self;
125-
match*inner {}
184+
letSelf{ iter } = self;
185+
EnvStrDebug{slice: iter.as_slice()}
126186
}
127187
}
128188

129189
impl fmt::DebugforEnv{
130-
fnfmt(&self,_:&mut fmt::Formatter<'_>) -> fmt::Result{
131-
letSelf(inner) = self;
132-
match*inner {}
190+
fnfmt(&self,f:&mut fmt::Formatter<'_>) -> fmt::Result{
191+
letSelf{ iter } = self;
192+
f.debug_list().entries(iter.as_slice()).finish()
133193
}
134194
}
135195

196+
impl !SendforEnv{}
197+
impl !SyncforEnv{}
198+
136199
implIteratorforEnv{
137200
typeItem = (OsString,OsString);
138201
fnnext(&mutself) -> Option<(OsString,OsString)>{
139-
self.0
202+
self.iter.next()
203+
}
204+
fnsize_hint(&self) -> (usize,Option<usize>){
205+
self.iter.size_hint()
140206
}
141207
}
142208

143209
pubfnenv() -> Env{
144-
panic!("not supported on this platform")
210+
let clone_to_vec = |map:&HashMap<OsString,OsString>| -> Vec<_>{
211+
map.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
212+
};
213+
214+
let iter = clone_to_vec(&*get_env_store().lock().unwrap()).into_iter();
215+
Env{ iter }
145216
}
146217

147-
pubfngetenv(_:&OsStr) -> Option<OsString>{
148-
None
218+
pubfngetenv(k:&OsStr) -> Option<OsString>{
219+
get_env_store().lock().unwrap().get(k).cloned()
149220
}
150221

151-
pubunsafefnsetenv(_:&OsStr, _:&OsStr) -> io::Result<()>{
152-
Err(io::const_io_error!(io::ErrorKind::Unsupported,"cannot set env vars on this platform"))
222+
pubunsafefnsetenv(k:&OsStr,v:&OsStr) -> io::Result<()>{
223+
let(k, v) = (k.to_owned(), v.to_owned());
224+
get_env_store().lock().unwrap().insert(k, v);
225+
Ok(())
153226
}
154227

155-
pubunsafefnunsetenv(_:&OsStr) -> io::Result<()>{
156-
Err(io::const_io_error!(io::ErrorKind::Unsupported,"cannot unset env vars on this platform"))
228+
pubunsafefnunsetenv(k:&OsStr) -> io::Result<()>{
229+
get_env_store().lock().unwrap().remove(k);
230+
Ok(())
157231
}
158232

159233
pubfntemp_dir() -> PathBuf{

0 commit comments

Comments
 (0)