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::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!(capsules_extra::virtual_kv::MuxKVPermissions<'static, $V>);
84
85        mux
86    };};
87}
88
89pub type KVPermissionsMuxComponentType<V> =
90    capsules_extra::kv_store_permissions::KVStorePermissions<'static, V>;
91
92pub struct KVPermissionsMuxComponent<V: hil::kv::KVPermissions<'static> + 'static> {
93    kv: &'static V,
94}
95
96impl<V: hil::kv::KVPermissions<'static>> KVPermissionsMuxComponent<V> {
97    pub fn new(kv: &'static V) -> KVPermissionsMuxComponent<V> {
98        Self { kv }
99    }
100}
101
102impl<V: hil::kv::KVPermissions<'static> + 'static> Component for KVPermissionsMuxComponent<V> {
103    type StaticInput = &'static mut MaybeUninit<MuxKVPermissions<'static, V>>;
104    type Output = &'static MuxKVPermissions<'static, V>;
105
106    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
107        let mux = static_buffer.write(MuxKVPermissions::new(self.kv));
108        self.kv.set_client(mux);
109        mux
110    }
111}
112
113/////////////////////
114// Virtual KV Object
115/////////////////////
116
117#[macro_export]
118macro_rules! virtual_kv_permissions_component_static {
119    ($V:ty $(,)?) => {{
120        let virtual_kv =
121            kernel::static_buf!(capsules_extra::virtual_kv::VirtualKVPermissions<'static, $V>);
122
123        virtual_kv
124    };};
125}
126
127pub type VirtualKVPermissionsComponentType<V> =
128    capsules_extra::virtual_kv::VirtualKVPermissions<'static, V>;
129
130pub struct VirtualKVPermissionsComponent<V: hil::kv::KVPermissions<'static> + 'static> {
131    mux_kv: &'static MuxKVPermissions<'static, V>,
132}
133
134impl<V: hil::kv::KVPermissions<'static>> VirtualKVPermissionsComponent<V> {
135    pub fn new(mux_kv: &'static MuxKVPermissions<'static, V>) -> VirtualKVPermissionsComponent<V> {
136        Self { mux_kv }
137    }
138}
139
140impl<V: hil::kv::KVPermissions<'static> + 'static> Component for VirtualKVPermissionsComponent<V> {
141    type StaticInput = &'static mut MaybeUninit<VirtualKVPermissions<'static, V>>;
142    type Output = &'static VirtualKVPermissions<'static, V>;
143
144    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
145        let virtual_kv = static_buffer.write(VirtualKVPermissions::new(self.mux_kv));
146        virtual_kv.setup();
147        virtual_kv
148    }
149}
150
151/////////////////////
152// KV Store Permissions
153/////////////////////
154
155#[macro_export]
156macro_rules! kv_store_permissions_component_static {
157    ($V:ty $(,)?) => {{
158        let buffer = kernel::static_buf!([u8; capsules_extra::kv_store_permissions::HEADER_LENGTH]);
159        let kv_store = kernel::static_buf!(
160            capsules_extra::kv_store_permissions::KVStorePermissions<'static, $V>
161        );
162
163        (kv_store, buffer)
164    };};
165}
166
167pub type KVStorePermissionsComponentType<V> =
168    capsules_extra::kv_store_permissions::KVStorePermissions<'static, V>;
169
170pub struct KVStorePermissionsComponent<V: hil::kv::KV<'static> + 'static> {
171    kv: &'static V,
172}
173
174impl<V: hil::kv::KV<'static> + 'static> KVStorePermissionsComponent<V> {
175    pub fn new(kv: &'static V) -> Self {
176        Self { kv }
177    }
178}
179
180impl<V: hil::kv::KV<'static> + 'static> Component for KVStorePermissionsComponent<V> {
181    type StaticInput = (
182        &'static mut MaybeUninit<KVStorePermissions<'static, V>>,
183        &'static mut MaybeUninit<[u8; capsules_extra::kv_store_permissions::HEADER_LENGTH]>,
184    );
185    type Output = &'static KVStorePermissions<'static, V>;
186
187    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
188        let buffer = static_buffer
189            .1
190            .write([0; capsules_extra::kv_store_permissions::HEADER_LENGTH]);
191
192        let kv_store_permissions = static_buffer
193            .0
194            .write(KVStorePermissions::new(self.kv, buffer));
195
196        self.kv.set_client(kv_store_permissions);
197
198        kv_store_permissions
199    }
200}
201
202/////////////////////
203// TicKV KV Store
204/////////////////////
205
206#[macro_export]
207macro_rules! tickv_kv_store_component_static {
208    ($K:ty, $T:ty $(,)?) => {{
209        let key = kernel::static_buf!($T);
210        let kv_store =
211            kernel::static_buf!(capsules_extra::tickv_kv_store::TicKVKVStore<'static, $K, $T>);
212
213        (kv_store, key)
214    };};
215}
216
217pub type TicKVKVStoreComponentType<K, T> =
218    capsules_extra::tickv_kv_store::TicKVKVStore<'static, K, T>;
219
220pub struct TicKVKVStoreComponent<K: 'static + KVSystem<'static, K = T>, T: 'static + KeyType> {
221    kv_system: &'static K,
222}
223
224impl<K: 'static + KVSystem<'static, K = T>, T: 'static + KeyType> TicKVKVStoreComponent<K, T> {
225    pub fn new(kv_system: &'static K) -> Self {
226        Self { kv_system }
227    }
228}
229
230impl<K: 'static + KVSystem<'static, K = T>, T: 'static + KeyType + Default> Component
231    for TicKVKVStoreComponent<K, T>
232{
233    type StaticInput = (
234        &'static mut MaybeUninit<TicKVKVStore<'static, K, T>>,
235        &'static mut MaybeUninit<T>,
236    );
237    type Output = &'static TicKVKVStore<'static, K, T>;
238
239    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
240        let key_buf = static_buffer.1.write(T::default());
241
242        let kv_store = static_buffer
243            .0
244            .write(TicKVKVStore::new(self.kv_system, key_buf));
245
246        self.kv_system.set_client(kv_store);
247
248        kv_store
249    }
250}