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.
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.
11 pub use fortanix_sgx_abi::*;
13 use io::{Error as IoError, Result as IoResult};
19 pub(crate) fn copy_user_buffer(buf: &alloc::UserRef<ByteBuffer>) -> Vec<u8> {
21 let buf = buf.to_enclave();
22 alloc::User::from_raw_parts(buf.data as _, buf.len).to_enclave()
26 pub fn read(fd: Fd, buf: &mut [u8]) -> IoResult<usize> {
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]);
35 pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
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))
43 pub fn write(fd: Fd, buf: &[u8]) -> IoResult<usize> {
45 let userbuf = alloc::User::new_from_enclave(buf);
46 raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
50 pub fn flush(fd: Fd) -> IoResult<()> {
51 unsafe { raw::flush(fd).from_sgx_result() }
54 pub fn close(fd: Fd) {
55 unsafe { raw::close(fd) }
58 pub fn launch_thread() -> IoResult<()> {
59 unsafe { raw::launch_thread().from_sgx_result() }
62 pub fn exit(panic: bool) -> ! {
63 unsafe { raw::exit(panic) }
66 pub fn wait(event_mask: u64, timeout: u64) -> IoResult<u64> {
67 unsafe { raw::wait(event_mask, timeout).from_sgx_result() }
70 pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {
71 unsafe { raw::send(event_set, tcs).from_sgx_result() }
74 pub fn alloc(size: usize, alignment: usize) -> IoResult<*mut u8> {
75 unsafe { raw::alloc(size, alignment).from_sgx_result() }
78 pub use self::raw::free;
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)
104 panic!("Usercall: returned invalid error value {}", err)
108 trait FromSgxResult {
111 fn from_sgx_result(self) -> IoResult<Self::Return>;
114 impl<T> FromSgxResult for (Result, T) {
117 fn from_sgx_result(self) -> IoResult<Self::Return> {
118 if self.0 == RESULT_SUCCESS {
121 Err(IoError::from_raw_os_error(check_os_error(self.0)))
126 impl FromSgxResult for Result {
129 fn from_sgx_result(self) -> IoResult<Self::Return> {
130 if self == RESULT_SUCCESS {
133 Err(IoError::from_raw_os_error(check_os_error(self)))