2 use crate::io::{Error as IoError, Result as IoResult, IoSlice, IoSliceMut};
3 use crate::time::Duration;
11 /// Usercall `read`. See the ABI documentation for more information.
13 /// This will do a single `read` usercall and scatter the read data among
14 /// `bufs`. To read to a single buffer, just pass a slice of length one.
15 #[unstable(feature = "sgx_platform", issue = "56975")]
16 pub fn read(fd: Fd, bufs: &mut [IoSliceMut<'_>]) -> IoResult<usize> {
18 let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
19 let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
20 let ret_len = raw::read(fd, userbuf.as_mut_ptr(), userbuf.len()).from_sgx_result()?;
21 let userbuf = &userbuf[..ret_len];
24 let end = cmp::min(index + buf.len(), userbuf.len());
25 if let Some(buflen) = end.checked_sub(index) {
26 userbuf[index..end].copy_to_enclave(&mut buf[..buflen]);
36 /// Usercall `read_alloc`. See the ABI documentation for more information.
37 #[unstable(feature = "sgx_platform", issue = "56975")]
38 pub fn read_alloc(fd: Fd) -> IoResult<Vec<u8>> {
40 let userbuf = ByteBuffer { data: crate::ptr::null_mut(), len: 0 };
41 let mut userbuf = alloc::User::new_from_enclave(&userbuf);
42 raw::read_alloc(fd, userbuf.as_raw_mut_ptr()).from_sgx_result()?;
43 Ok(userbuf.copy_user_buffer())
47 /// Usercall `write`. See the ABI documentation for more information.
49 /// This will do a single `write` usercall and gather the written data from
50 /// `bufs`. To write from a single buffer, just pass a slice of length one.
51 #[unstable(feature = "sgx_platform", issue = "56975")]
52 pub fn write(fd: Fd, bufs: &[IoSlice<'_>]) -> IoResult<usize> {
54 let total_len = bufs.iter().fold(0usize, |sum, buf| sum.saturating_add(buf.len()));
55 let mut userbuf = alloc::User::<[u8]>::uninitialized(total_len);
58 let end = cmp::min(index + buf.len(), userbuf.len());
59 if let Some(buflen) = end.checked_sub(index) {
60 userbuf[index..end].copy_from_enclave(&buf[..buflen]);
66 raw::write(fd, userbuf.as_ptr(), userbuf.len()).from_sgx_result()
70 /// Usercall `flush`. See the ABI documentation for more information.
71 #[unstable(feature = "sgx_platform", issue = "56975")]
72 pub fn flush(fd: Fd) -> IoResult<()> {
73 unsafe { raw::flush(fd).from_sgx_result() }
76 /// Usercall `close`. See the ABI documentation for more information.
77 #[unstable(feature = "sgx_platform", issue = "56975")]
78 pub fn close(fd: Fd) {
79 unsafe { raw::close(fd) }
82 fn string_from_bytebuffer(buf: &alloc::UserRef<ByteBuffer>, usercall: &str, arg: &str) -> String {
83 String::from_utf8(buf.copy_user_buffer())
84 .unwrap_or_else(|_| rtabort!("Usercall {}: expected {} to be valid UTF-8", usercall, arg))
87 /// Usercall `bind_stream`. See the ABI documentation for more information.
88 #[unstable(feature = "sgx_platform", issue = "56975")]
89 pub fn bind_stream(addr: &str) -> IoResult<(Fd, String)> {
91 let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
92 let mut local = alloc::User::<ByteBuffer>::uninitialized();
93 let fd = raw::bind_stream(
96 local.as_raw_mut_ptr()
98 let local = string_from_bytebuffer(&local, "bind_stream", "local_addr");
103 /// Usercall `accept_stream`. See the ABI documentation for more information.
104 #[unstable(feature = "sgx_platform", issue = "56975")]
105 pub fn accept_stream(fd: Fd) -> IoResult<(Fd, String, String)> {
107 let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
108 let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
109 // without forcing coercion?
110 let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
111 let fd = raw::accept_stream(
113 local.as_raw_mut_ptr(),
114 peer.as_raw_mut_ptr()
115 ).from_sgx_result()?;
116 let local = string_from_bytebuffer(&local, "accept_stream", "local_addr");
117 let peer = string_from_bytebuffer(&peer, "accept_stream", "peer_addr");
118 Ok((fd, local, peer))
122 /// Usercall `connect_stream`. See the ABI documentation for more information.
123 #[unstable(feature = "sgx_platform", issue = "56975")]
124 pub fn connect_stream(addr: &str) -> IoResult<(Fd, String, String)> {
126 let addr_user = alloc::User::new_from_enclave(addr.as_bytes());
127 let mut bufs = alloc::User::<[ByteBuffer; 2]>::uninitialized();
128 let mut buf_it = alloc::UserRef::iter_mut(&mut *bufs); // FIXME: can this be done
129 // without forcing coercion?
130 let (local, peer) = (buf_it.next().unwrap(), buf_it.next().unwrap());
131 let fd = raw::connect_stream(
134 local.as_raw_mut_ptr(),
135 peer.as_raw_mut_ptr()
136 ).from_sgx_result()?;
137 let local = string_from_bytebuffer(&local, "connect_stream", "local_addr");
138 let peer = string_from_bytebuffer(&peer, "connect_stream", "peer_addr");
139 Ok((fd, local, peer))
143 /// Usercall `launch_thread`. See the ABI documentation for more information.
144 #[unstable(feature = "sgx_platform", issue = "56975")]
145 pub unsafe fn launch_thread() -> IoResult<()> {
146 raw::launch_thread().from_sgx_result()
149 /// Usercall `exit`. See the ABI documentation for more information.
150 #[unstable(feature = "sgx_platform", issue = "56975")]
151 pub fn exit(panic: bool) -> ! {
152 unsafe { raw::exit(panic) }
155 /// Usercall `wait`. See the ABI documentation for more information.
156 #[unstable(feature = "sgx_platform", issue = "56975")]
157 pub fn wait(event_mask: u64, timeout: u64) -> IoResult<u64> {
158 unsafe { raw::wait(event_mask, timeout).from_sgx_result() }
161 /// Usercall `send`. See the ABI documentation for more information.
162 #[unstable(feature = "sgx_platform", issue = "56975")]
163 pub fn send(event_set: u64, tcs: Option<Tcs>) -> IoResult<()> {
164 unsafe { raw::send(event_set, tcs).from_sgx_result() }
167 /// Usercall `insecure_time`. See the ABI documentation for more information.
168 #[unstable(feature = "sgx_platform", issue = "56975")]
169 pub fn insecure_time() -> Duration {
170 let t = unsafe { raw::insecure_time() };
171 Duration::new(t / 1_000_000_000, (t % 1_000_000_000) as _)
174 /// Usercall `alloc`. See the ABI documentation for more information.
175 #[unstable(feature = "sgx_platform", issue = "56975")]
176 pub fn alloc(size: usize, alignment: usize) -> IoResult<*mut u8> {
177 unsafe { raw::alloc(size, alignment).from_sgx_result() }
180 #[unstable(feature = "sgx_platform", issue = "56975")]
182 pub use self::raw::free;
184 fn check_os_error(err: Result) -> i32 {
185 // FIXME: not sure how to make sure all variants of Error are covered
186 if err == Error::NotFound as _ ||
187 err == Error::PermissionDenied as _ ||
188 err == Error::ConnectionRefused as _ ||
189 err == Error::ConnectionReset as _ ||
190 err == Error::ConnectionAborted as _ ||
191 err == Error::NotConnected as _ ||
192 err == Error::AddrInUse as _ ||
193 err == Error::AddrNotAvailable as _ ||
194 err == Error::BrokenPipe as _ ||
195 err == Error::AlreadyExists as _ ||
196 err == Error::WouldBlock as _ ||
197 err == Error::InvalidInput as _ ||
198 err == Error::InvalidData as _ ||
199 err == Error::TimedOut as _ ||
200 err == Error::WriteZero as _ ||
201 err == Error::Interrupted as _ ||
202 err == Error::Other as _ ||
203 err == Error::UnexpectedEof as _ ||
204 ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&err)
208 rtabort!("Usercall: returned invalid error value {}", err)
212 trait FromSgxResult {
215 fn from_sgx_result(self) -> IoResult<Self::Return>;
218 impl<T> FromSgxResult for (Result, T) {
221 fn from_sgx_result(self) -> IoResult<Self::Return> {
222 if self.0 == RESULT_SUCCESS {
225 Err(IoError::from_raw_os_error(check_os_error(self.0)))
230 impl FromSgxResult for Result {
233 fn from_sgx_result(self) -> IoResult<Self::Return> {
234 if self == RESULT_SUCCESS {
237 Err(IoError::from_raw_os_error(check_os_error(self)))