1use capsules_core::rng;
34use core::mem::MaybeUninit;
35use kernel::capabilities;
36use kernel::component::Component;
37use kernel::create_capability;
38use kernel::hil::entropy::Entropy32;
39use kernel::hil::rng::Rng;
40
41#[macro_export]
42macro_rules! rng_component_static {
43    ($E: ty $(,)?) => {{
44        let etr = kernel::static_buf!(capsules_core::rng::Entropy32ToRandom<'static, $E>);
45        let rng = kernel::static_buf!(
46            capsules_core::rng::RngDriver<
47                'static,
48                capsules_core::rng::Entropy32ToRandom<'static, $E>,
49            >
50        );
51
52        (etr, rng)
53    };};
54}
55
56pub type RngComponentType<E> =
57    rng::RngDriver<'static, capsules_core::rng::Entropy32ToRandom<'static, E>>;
58
59pub struct RngComponent<E: Entropy32<'static> + 'static> {
60    board_kernel: &'static kernel::Kernel,
61    driver_num: usize,
62    trng: &'static E,
63}
64
65impl<E: Entropy32<'static>> RngComponent<E> {
66    pub fn new(board_kernel: &'static kernel::Kernel, driver_num: usize, trng: &'static E) -> Self {
67        Self {
68            board_kernel,
69            driver_num,
70            trng,
71        }
72    }
73}
74
75impl<E: Entropy32<'static>> Component for RngComponent<E> {
76    type StaticInput = (
77        &'static mut MaybeUninit<capsules_core::rng::Entropy32ToRandom<'static, E>>,
78        &'static mut MaybeUninit<
79            capsules_core::rng::RngDriver<
80                'static,
81                capsules_core::rng::Entropy32ToRandom<'static, E>,
82            >,
83        >,
84    );
85    type Output =
86        &'static rng::RngDriver<'static, capsules_core::rng::Entropy32ToRandom<'static, E>>;
87
88    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
89        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
90
91        let entropy_to_random = static_buffer
92            .0
93            .write(rng::Entropy32ToRandom::new(self.trng));
94        let rng = static_buffer.1.write(rng::RngDriver::new(
95            entropy_to_random,
96            self.board_kernel.create_grant(self.driver_num, &grant_cap),
97        ));
98        self.trng.set_client(entropy_to_random);
99        entropy_to_random.set_client(rng);
100
101        rng
102    }
103}
104
105#[macro_export]
106macro_rules! rng_random_component_static {
107    ($R: ty $(,)?) => {{
108        let rng = kernel::static_buf!(capsules_core::rng::RngDriver<'static, $R>);
109
110        rng
111    };};
112}
113
114pub type RngRandomComponentType<R> = rng::RngDriver<'static, R>;
115
116pub struct RngRandomComponent<R: Rng<'static> + 'static> {
117    board_kernel: &'static kernel::Kernel,
118    driver_num: usize,
119    rng: &'static R,
120}
121
122impl<R: Rng<'static>> RngRandomComponent<R> {
123    pub fn new(board_kernel: &'static kernel::Kernel, driver_num: usize, rng: &'static R) -> Self {
124        Self {
125            board_kernel,
126            driver_num,
127            rng,
128        }
129    }
130}
131
132impl<R: Rng<'static>> Component for RngRandomComponent<R> {
133    type StaticInput = &'static mut MaybeUninit<capsules_core::rng::RngDriver<'static, R>>;
134    type Output = &'static rng::RngDriver<'static, R>;
135
136    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
137        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
138
139        let rng_driver = static_buffer.write(rng::RngDriver::new(
140            self.rng,
141            self.board_kernel.create_grant(self.driver_num, &grant_cap),
142        ));
143        self.rng.set_client(rng_driver);
144
145        rng_driver
146    }
147}