components/
rng.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Component for random number generator using `Entropy32ToRandom`.
6//!
7//! This provides one Component, RngComponent, which implements a userspace
8//! syscall interface to the RNG peripheral (TRNG).
9//!
10//! Usage
11//! -----
12//! ```rust
13//! let rng = components::rng::RngComponent::new(board_kernel, &sam4l::trng::TRNG)
14//!     .finalize(rng_component_static!());
15//! ```
16
17// Author: Hudson Ayers <hayers@cs.stanford.edu>
18// Last modified: 07/12/2019
19
20use capsules_core::rng;
21use core::mem::MaybeUninit;
22use kernel::capabilities;
23use kernel::component::Component;
24use kernel::create_capability;
25use kernel::hil::entropy::Entropy32;
26use kernel::hil::rng::Rng;
27
28#[macro_export]
29macro_rules! rng_component_static {
30    ($E: ty $(,)?) => {{
31        let etr = kernel::static_buf!(capsules_core::rng::Entropy32ToRandom<'static, $E>);
32        let rng = kernel::static_buf!(
33            capsules_core::rng::RngDriver<
34                'static,
35                capsules_core::rng::Entropy32ToRandom<'static, $E>,
36            >
37        );
38
39        (etr, rng)
40    };};
41}
42
43pub type RngComponentType<E> =
44    rng::RngDriver<'static, capsules_core::rng::Entropy32ToRandom<'static, E>>;
45
46pub struct RngComponent<E: Entropy32<'static> + 'static> {
47    board_kernel: &'static kernel::Kernel,
48    driver_num: usize,
49    trng: &'static E,
50}
51
52impl<E: Entropy32<'static>> RngComponent<E> {
53    pub fn new(board_kernel: &'static kernel::Kernel, driver_num: usize, trng: &'static E) -> Self {
54        Self {
55            board_kernel,
56            driver_num,
57            trng,
58        }
59    }
60}
61
62impl<E: Entropy32<'static>> Component for RngComponent<E> {
63    type StaticInput = (
64        &'static mut MaybeUninit<capsules_core::rng::Entropy32ToRandom<'static, E>>,
65        &'static mut MaybeUninit<
66            capsules_core::rng::RngDriver<
67                'static,
68                capsules_core::rng::Entropy32ToRandom<'static, E>,
69            >,
70        >,
71    );
72    type Output =
73        &'static rng::RngDriver<'static, capsules_core::rng::Entropy32ToRandom<'static, E>>;
74
75    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
76        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
77
78        let entropy_to_random = static_buffer
79            .0
80            .write(rng::Entropy32ToRandom::new(self.trng));
81        let rng = static_buffer.1.write(rng::RngDriver::new(
82            entropy_to_random,
83            self.board_kernel.create_grant(self.driver_num, &grant_cap),
84        ));
85        self.trng.set_client(entropy_to_random);
86        entropy_to_random.set_client(rng);
87
88        rng
89    }
90}