summaryrefslogtreecommitdiff
path: root/vendor/getrandom/src/backends/vxworks.rs
blob: 5f5e6773b3f7bb0584d0e57dab27e9df7e60a1fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//! Implementation for VxWorks
use crate::Error;
use core::{
    cmp::Ordering::{Equal, Greater, Less},
    mem::MaybeUninit,
    sync::atomic::{AtomicBool, Ordering::Relaxed},
};

#[path = "../util_libc.rs"]
mod util_libc;

pub use crate::util::{inner_u32, inner_u64};

static RNG_INIT: AtomicBool = AtomicBool::new(false);

#[cold]
fn init() -> Result<(), Error> {
    let ret = unsafe { libc::randSecure() };
    match ret.cmp(&0) {
        Greater => RNG_INIT.store(true, Relaxed),
        Equal => unsafe {
            libc::usleep(10);
        },
        Less => return Err(Error::VXWORKS_RAND_SECURE),
    }
    Ok(())
}

#[inline]
pub fn fill_inner(dest: &mut [MaybeUninit<u8>]) -> Result<(), Error> {
    while !RNG_INIT.load(Relaxed) {
        init()?;
    }

    // Prevent overflow of i32
    let chunk_size = usize::try_from(i32::MAX).expect("VxWorks does not support 16-bit targets");
    for chunk in dest.chunks_mut(chunk_size) {
        let chunk_len: libc::c_int = chunk
            .len()
            .try_into()
            .expect("chunk size is bounded by i32::MAX");
        let p: *mut libc::c_uchar = chunk.as_mut_ptr().cast();
        let ret = unsafe { libc::randABytes(p, chunk_len) };
        if ret != 0 {
            return Err(util_libc::last_os_error());
        }
    }
    Ok(())
}

impl Error {
    /// On VxWorks, call to `randSecure` failed (random number generator is not yet initialized).
    pub(crate) const VXWORKS_RAND_SECURE: Error = Self::new_internal(10);
}