components/
kv.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//! Components for KV stack capsules.
6
7use capsules_extra::kv_driver::KVStoreDriver;
8use capsules_extra::kv_store_permissions::KVStorePermissions;
9use capsules_extra::tickv::{KVSystem, KeyType};
10use capsules_extra::tickv_kv_store::TicKVKVStore;
11use capsules_extra::virtualizers::virtual_kv::{MuxKVPermissions, VirtualKVPermissions};
12use core::mem::MaybeUninit;
13use kernel::capabilities;
14use kernel::component::Component;
15use kernel::create_capability;
16use kernel::hil;
17
18///////////////////////
19// KV Userspace Driver
20///////////////////////
21
22#[macro_export]
23macro_rules! kv_driver_component_static {
24    ($V:ty $(,)?) => {{
25        let kv = kernel::static_buf!(capsules_extra::kv_driver::KVStoreDriver<'static, $V>);
26        let key_buffer = kernel::static_buf!([u8; 64]);
27        let value_buffer = kernel::static_buf!([u8; 512]);
28
29        (kv, key_buffer, value_buffer)
30    };};
31}
32
33pub type KVDriverComponentType<V> = capsules_extra::kv_driver::KVStoreDriver<'static, V>;
34
35pub struct KVDriverComponent<V: hil::kv::KVPermissions<'static> + 'static> {
36    kv: &'static V,
37    board_kernel: &'static kernel::Kernel,
38    driver_num: usize,
39}
40
41impl<V: hil::kv::KVPermissions<'static>> KVDriverComponent<V> {
42    pub fn new(kv: &'static V, board_kernel: &'static kernel::Kernel, driver_num: usize) -> Self {
43        Self {
44            kv,
45            board_kernel,
46            driver_num,
47        }
48    }
49}
50
51impl<V: hil::kv::KVPermissions<'static>> Component for KVDriverComponent<V> {
52    type StaticInput = (
53        &'static mut MaybeUninit<KVStoreDriver<'static, V>>,
54        &'static mut MaybeUninit<[u8; 64]>,
55        &'static mut MaybeUninit<[u8; 512]>,
56    );
57    type Output = &'static KVStoreDriver<'static, V>;
58
59    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
60        let grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
61
62        let key_buffer = static_buffer.1.write([0; 64]);
63        let value_buffer = static_buffer.2.write([0; 512]);
64
65        let driver = static_buffer.0.write(KVStoreDriver::new(
66            self.kv,
67            key_buffer,
68            value_buffer,
69            self.board_kernel.create_grant(self.driver_num, &grant_cap),
70        ));
71        self.kv.set_client(driver);
72        driver
73    }
74}
75
76//////////////
77// KV Mux
78//////////////
79
80#[macro_export]
81macro_rules! kv_permissions_mux_component_static {
82    ($V:ty $(,)?) => {{
83        let mux = kernel::static_buf!(
84            capsules_extra::virtualizers::virtual_kv::MuxKVPermissions<'static, $V>
85        );
86
87        mux
88    };};
89}
90
91pub type KVPermissionsMuxComponentType<V> =
92    capsules_extra::kv_store_permissions::KVStorePermissions<'static, V>;
93
94pub struct KVPermissionsMuxComponent<V: hil::kv::KVPermissions<'static> + 'static> {
95    kv: &'static V,
96}
97
98impl<V: hil::kv::KVPermissions<'static>> KVPermissionsMuxComponent<V> {
99    pub fn new(kv: &'static V) -> KVPermissionsMuxComponent<V> {
100        Self { kv }
101    }
102}
103
104impl<V: hil::kv::KVPermissions<'static> + 'static> Component for KVPermissionsMuxComponent<V> {
105    type StaticInput = &'static mut MaybeUninit<MuxKVPermissions<'static, V>>;
106    type Output = &'static MuxKVPermissions<'static, V>;
107
108    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
109        let mux = static_buffer.write(MuxKVPermissions::new(self.kv));
110        self.kv.set_client(mux);
111        mux
112    }
113}
114
115/////////////////////
116// Virtual KV Object
117/////////////////////
118
119#[macro_export]
120macro_rules! virtual_kv_permissions_component_static {
121    ($V:ty $(,)?) => {{
122        let virtual_kv = kernel::static_buf!(
123            capsules_extra::virtualizers::virtual_kv::VirtualKVPermissions<'static, $V>
124        );
125
126        virtual_kv
127    };};
128}
129
130pub type VirtualKVPermissionsComponentType<V> =
131    capsules_extra::virtualizers::virtual_kv::VirtualKVPermissions<'static, V>;
132
133pub struct VirtualKVPermissionsComponent<V: hil::kv::KVPermissions<'static> + 'static> {
134    mux_kv: &'static MuxKVPermissions<'static, V>,
135}
136
137impl<V: hil::kv::KVPermissions<'static>> VirtualKVPermissionsComponent<V> {
138    pub fn new(mux_kv: &'static MuxKVPermissions<'static, V>) -> VirtualKVPermissionsComponent<V> {
139        Self { mux_kv }
140    }
141}
142
143impl<V: hil::kv::KVPermissions<'static> + 'static> Component for VirtualKVPermissionsComponent<V> {
144    type StaticInput = &'static mut MaybeUninit<VirtualKVPermissions<'static, V>>;
145    type Output = &'static VirtualKVPermissions<'static, V>;
146
147    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
148        let virtual_kv = static_buffer.write(VirtualKVPermissions::new(self.mux_kv));
149        virtual_kv.setup();
150        virtual_kv
151    }
152}
153
154/////////////////////
155// KV Store Permissions
156/////////////////////
157
158#[macro_export]
159macro_rules! kv_store_permissions_component_static {
160    ($V:ty $(,)?) => {{
161        let buffer = kernel::static_buf!([u8; capsules_extra::kv_store_permissions::HEADER_LENGTH]);
162        let kv_store = kernel::static_buf!(
163            capsules_extra::kv_store_permissions::KVStorePermissions<'static, $V>
164        );
165
166        (kv_store, buffer)
167    };};
168}
169
170pub type KVStorePermissionsComponentType<V> =
171    capsules_extra::kv_store_permissions::KVStorePermissions<'static, V>;
172
173pub struct KVStorePermissionsComponent<V: hil::kv::KV<'static> + 'static> {
174    kv: &'static V,
175}
176
177impl<V: hil::kv::KV<'static> + 'static> KVStorePermissionsComponent<V> {
178    pub fn new(kv: &'static V) -> Self {
179        Self { kv }
180    }
181}
182
183impl<V: hil::kv::KV<'static> + 'static> Component for KVStorePermissionsComponent<V> {
184    type StaticInput = (
185        &'static mut MaybeUninit<KVStorePermissions<'static, V>>,
186        &'static mut MaybeUninit<[u8; capsules_extra::kv_store_permissions::HEADER_LENGTH]>,
187    );
188    type Output = &'static KVStorePermissions<'static, V>;
189
190    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
191        let buffer = static_buffer
192            .1
193            .write([0; capsules_extra::kv_store_permissions::HEADER_LENGTH]);
194
195        let kv_store_permissions = static_buffer
196            .0
197            .write(KVStorePermissions::new(self.kv, buffer));
198
199        self.kv.set_client(kv_store_permissions);
200
201        kv_store_permissions
202    }
203}
204
205/////////////////////
206// TicKV KV Store
207/////////////////////
208
209#[macro_export]
210macro_rules! tickv_kv_store_component_static {
211    ($K:ty, $T:ty $(,)?) => {{
212        let key = kernel::static_buf!($T);
213        let kv_store =
214            kernel::static_buf!(capsules_extra::tickv_kv_store::TicKVKVStore<'static, $K, $T>);
215
216        (kv_store, key)
217    };};
218}
219
220pub type TicKVKVStoreComponentType<K, T> =
221    capsules_extra::tickv_kv_store::TicKVKVStore<'static, K, T>;
222
223pub struct TicKVKVStoreComponent<K: 'static + KVSystem<'static, K = T>, T: 'static + KeyType> {
224    kv_system: &'static K,
225}
226
227impl<K: 'static + KVSystem<'static, K = T>, T: 'static + KeyType> TicKVKVStoreComponent<K, T> {
228    pub fn new(kv_system: &'static K) -> Self {
229        Self { kv_system }
230    }
231}
232
233impl<K: 'static + KVSystem<'static, K = T>, T: 'static + KeyType + Default> Component
234    for TicKVKVStoreComponent<K, T>
235{
236    type StaticInput = (
237        &'static mut MaybeUninit<TicKVKVStore<'static, K, T>>,
238        &'static mut MaybeUninit<T>,
239    );
240    type Output = &'static TicKVKVStore<'static, K, T>;
241
242    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
243        let key_buf = static_buffer.1.write(T::default());
244
245        let kv_store = static_buffer
246            .0
247            .write(TicKVKVStore::new(self.kv_system, key_buf));
248
249        self.kv_system.set_client(kv_store);
250
251        kv_store
252    }
253}