]> git.lizzy.rs Git - rust.git/blob - src/libstd/sys/sgx/abi/usercalls/mod.rs
SGX target: implement streams
[rust.git] / src / libstd / sys / sgx / abi / usercalls / mod.rs
1 // Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 pub use fortanix_sgx_abi::*;
12
13 use io::{Error as IoError, Result as IoResult};
14
15 pub mod alloc;
16 #[macro_use]
17 mod raw;
18
19 pub(crate) fn copy_user_buffer(buf: &alloc::UserRef<ByteBuffer>) -> Vec<u8> {
20     unsafe {
21         let buf = buf.to_enclave();
22         alloc::User::from_raw_parts(buf.data as _, buf.len).to_enclave()
23     }
24 }
25
26 pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
27     unsafe {
28         let mut userbuf = alloc::User::<[u8]>::uninitialized(buf.len());
29         let len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
30         userbuf[..len].copy_to_enclave(&mut buf[..len]);
31         Ok(len)
32     }
33 }
34
35 pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
36     unsafe {
37         let mut userbuf = alloc::User::<ByteBuffer>::uninitialized();
38         raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?;
39         Ok(copy_user_buffer(&userbuf))
40     }
41 }
42
43 pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
44     unsafe {
45         let userbuf = alloc::User::new_from_enclave(buf);
46         raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
47     }
48 }
49
50 pub fn flush(fd: Fd) -> IoResult<()> {
51     unsafe { raw::flush(fd).from_sgx_result() }
52 }
53
54 pub fn close(fd: Fd) {
55     unsafe { raw::close(fd) }
56 }
57
58 pub fn launch_thread() -> IoResult<()> {
59     unsafe { raw::launch_thread().from_sgx_result() }
60 }
61
62 pub fn exit(panic: bool) -> ! {
63     unsafe { raw::exit(panic) }
64 }
65
66 pub fn wait(event_mask: u64, timeout: u64) -> IoResult<u64> {
67     unsafe { raw::wait(event_mask, timeout).from_sgx_result() }
68 }
69
70 pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {
71     unsafe { raw::send(event_set, tcs).from_sgx_result() }
72 }
73
74 pub fn alloc(size: usize, alignment: usize) -> IoResult<*mut u8> {
75     unsafe { raw::alloc(size, alignment).from_sgx_result() }
76 }
77
78 pub use self::raw::free;
79
80 fn check_os_error(err: Result) -> i32 {
81     // FIXME: not sure how to make sure all variants of Error are covered
82     if err == Error::NotFound as _ ||
83        err == Error::PermissionDenied as _ ||
84        err == Error::ConnectionRefused as _ ||
85        err == Error::ConnectionReset as _ ||
86        err == Error::ConnectionAborted as _ ||
87        err == Error::NotConnected as _ ||
88        err == Error::AddrInUse as _ ||
89        err == Error::AddrNotAvailable as _ ||
90        err == Error::BrokenPipe as _ ||
91        err == Error::AlreadyExists as _ ||
92        err == Error::WouldBlock as _ ||
93        err == Error::InvalidInput as _ ||
94        err == Error::InvalidData as _ ||
95        err == Error::TimedOut as _ ||
96        err == Error::WriteZero as _ ||
97        err == Error::Interrupted as _ ||
98        err == Error::Other as _ ||
99        err == Error::UnexpectedEof as _ ||
100        ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&err)
101     {
102         err
103     } else {
104         panic!("Usercall: returned invalid error value {}", err)
105     }
106 }
107
108 trait FromSgxResult {
109     type Return;
110
111     fn from_sgx_result(self) -> IoResult<Self::Return>;
112 }
113
114 impl<T> FromSgxResult for (Result, T) {
115     type Return = T;
116
117     fn from_sgx_result(self) -> IoResult<Self::Return> {
118         if self.0 == RESULT_SUCCESS {
119             Ok(self.1)
120         } else {
121             Err(IoError::from_raw_os_error(check_os_error(self.0)))
122         }
123     }
124 }
125
126 impl FromSgxResult for Result {
127     type Return = ();
128
129     fn from_sgx_result(self) -> IoResult<Self::Return> {
130         if self == RESULT_SUCCESS {
131             Ok(())
132         } else {
133             Err(IoError::from_raw_os_error(check_os_error(self)))
134         }
135     }
136 }