1 //! Implementation for Hermit
2 use crate::Error;
3 use core::{mem::MaybeUninit, num::NonZeroU32};
4
5 /// Minimum return value which we should get from syscalls in practice,
6 /// because Hermit uses positive `i32`s for error codes:
7 /// https://github.com/hermitcore/libhermit-rs/blob/main/src/errno.rs
8 const MIN_RET_CODE: isize = -(i32::MAX as isize);
9
10 extern "C" {
sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize11 fn sys_read_entropy(buffer: *mut u8, length: usize, flags: u32) -> isize;
12 }
13
getrandom_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error>14 pub fn getrandom_inner(mut dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
15 while !dest.is_empty() {
16 let res = unsafe { sys_read_entropy(dest.as_mut_ptr() as *mut u8, dest.len(), 0) };
17 // Positive `isize`s can be safely casted to `usize`
18 if res > 0 && (res as usize) <= dest.len() {
19 dest = &mut dest[res as usize..];
20 } else {
21 let err = match res {
22 MIN_RET_CODE..=-1 => NonZeroU32::new(-res as u32).unwrap().into(),
23 _ => Error::UNEXPECTED,
24 };
25 return Err(err);
26 }
27 }
28 Ok(())
29 }
30