components/
tickv.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 TicKV KV System Driver.
6//!
7//! This provides one component, TicKVComponent, which provides
8//! a system call inteface to non-volatile storage.
9//!
10//! Usage
11//! -----
12//! ```rust
13//!    let flash_ctrl_read_buf = static_init!(
14//!        [u8; lowrisc::flash_ctrl::PAGE_SIZE],
15//!        [0; lowrisc::flash_ctrl::PAGE_SIZE]
16//!    );
17//!    let page_buffer = static_init!(
18//!        lowrisc::flash_ctrl::LowRiscPage,
19//!        lowrisc::flash_ctrl::LowRiscPage::default()
20//!    );
21//!
22//!    let mux_flash = components::tickv::FlashMuxComponent::new(&peripherals.flash_ctrl).finalize(
23//!        components::flash_user_component_static!(lowrisc::flash_ctrl::FlashCtrl),
24//!    );
25//!
26//!    // SipHash
27//!    let sip_hash = static_init!(
28//!        capsules_extra::sip_hash::SipHasher24,
29//!        capsules_extra::sip_hash::SipHasher24::new()
30//!    );
31//!    sip_hash.register();
32//!
33//!    let tickv = components::tickv::TicKVComponent::new(
34//!        sip_hash,
35//!        &mux_flash,
36//!        0x20040000 / lowrisc::flash_ctrl::PAGE_SIZE,
37//!        0x40000,
38//!        flash_ctrl_read_buf,
39//!        page_buffer,
40//!    )
41//!    .finalize(components::tickv_component_static!(
42//!        lowrisc::flash_ctrl::FlashCtrl,
43//!        capsules_extra::sip_hash::SipHasher24
44//!    ));
45//!    hil::flash::HasClient::set_client(&peripherals.flash_ctrl, mux_flash);
46//! ```
47
48use capsules_core::virtualizers::virtual_flash::FlashUser;
49use capsules_core::virtualizers::virtual_flash::MuxFlash;
50use capsules_extra::tickv::TicKVSystem;
51use core::mem::MaybeUninit;
52use kernel::capabilities;
53use kernel::component::Component;
54use kernel::create_capability;
55use kernel::hil;
56use kernel::hil::flash::HasClient;
57use kernel::hil::hasher::Hasher;
58
59// Setup static space for the objects.
60#[macro_export]
61macro_rules! tickv_component_static {
62    ($F:ty, $H:ty, $PAGE_SIZE:expr $(,)?) => {{
63        let flash =
64            kernel::static_buf!(capsules_core::virtualizers::virtual_flash::FlashUser<'static, $F>);
65        let tickv = kernel::static_buf!(
66            capsules_extra::tickv::TicKVSystem<
67                'static,
68                capsules_core::virtualizers::virtual_flash::FlashUser<'static, $F>,
69                $H,
70                $PAGE_SIZE,
71            >
72        );
73
74        (flash, tickv)
75    };};
76}
77
78#[macro_export]
79macro_rules! tickv_dedicated_flash_component_static {
80    ($F:ty, $H:ty, $PAGE_SIZE:expr $(,)?) => {{
81        let tickfs_read_buffer = kernel::static_buf!([u8; $PAGE_SIZE]);
82        let tickv =
83            kernel::static_buf!(capsules_extra::tickv::TicKVSystem<'static, $F, $H, $PAGE_SIZE>);
84
85        (tickv, tickfs_read_buffer)
86    };};
87}
88
89pub struct TicKVComponent<
90    F: 'static + hil::flash::Flash + hil::flash::HasClient<'static, MuxFlash<'static, F>>,
91    H: 'static + Hasher<'static, 8>,
92    const PAGE_SIZE: usize,
93> {
94    mux_flash: &'static MuxFlash<'static, F>,
95    hasher: &'static H,
96    region_offset: usize,
97    flash_size: usize,
98    tickfs_read_buf: &'static mut [u8; PAGE_SIZE],
99    flash_read_buffer: &'static mut F::Page,
100}
101
102impl<
103        F: 'static + hil::flash::Flash + hil::flash::HasClient<'static, MuxFlash<'static, F>>,
104        H: Hasher<'static, 8>,
105        const PAGE_SIZE: usize,
106    > TicKVComponent<F, H, PAGE_SIZE>
107{
108    pub fn new(
109        hasher: &'static H,
110        mux_flash: &'static MuxFlash<'static, F>,
111        region_offset: usize,
112        flash_size: usize,
113        tickfs_read_buf: &'static mut [u8; PAGE_SIZE],
114        flash_read_buffer: &'static mut F::Page,
115    ) -> Self {
116        Self {
117            mux_flash,
118            hasher,
119            region_offset,
120            flash_size,
121            tickfs_read_buf,
122            flash_read_buffer,
123        }
124    }
125}
126
127impl<
128        F: 'static + hil::flash::Flash + hil::flash::HasClient<'static, MuxFlash<'static, F>>,
129        H: 'static + Hasher<'static, 8>,
130        const PAGE_SIZE: usize,
131    > Component for TicKVComponent<F, H, PAGE_SIZE>
132{
133    type StaticInput = (
134        &'static mut MaybeUninit<FlashUser<'static, F>>,
135        &'static mut MaybeUninit<TicKVSystem<'static, FlashUser<'static, F>, H, PAGE_SIZE>>,
136    );
137    type Output = &'static TicKVSystem<'static, FlashUser<'static, F>, H, PAGE_SIZE>;
138
139    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
140        let _grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
141
142        let virtual_flash = static_buffer.0.write(FlashUser::new(self.mux_flash));
143
144        let driver = static_buffer.1.write(TicKVSystem::new(
145            virtual_flash,
146            self.hasher,
147            self.tickfs_read_buf,
148            self.flash_read_buffer,
149            self.region_offset,
150            self.flash_size,
151        ));
152        virtual_flash.set_client(driver);
153        driver.initialise();
154        driver
155    }
156}
157
158pub type TicKVDedicatedFlashComponentType<F, H, const PAGE: usize> =
159    capsules_extra::tickv::TicKVSystem<'static, F, H, PAGE>;
160
161pub struct TicKVDedicatedFlashComponent<
162    F: 'static
163        + hil::flash::Flash
164        + hil::flash::HasClient<'static, TicKVSystem<'static, F, H, PAGE_SIZE>>,
165    H: 'static + Hasher<'static, 8>,
166    const PAGE_SIZE: usize,
167> {
168    flash: &'static F,
169    hasher: &'static H,
170    region_offset: usize,
171    flash_size: usize,
172    flash_read_buffer: &'static mut F::Page,
173}
174
175impl<
176        F: 'static
177            + hil::flash::Flash
178            + hil::flash::HasClient<'static, TicKVSystem<'static, F, H, PAGE_SIZE>>,
179        H: Hasher<'static, 8>,
180        const PAGE_SIZE: usize,
181    > TicKVDedicatedFlashComponent<F, H, PAGE_SIZE>
182{
183    pub fn new(
184        hasher: &'static H,
185        flash: &'static F,
186        region_offset: usize,
187        flash_size: usize,
188        flash_read_buffer: &'static mut F::Page,
189    ) -> Self {
190        Self {
191            flash,
192            hasher,
193            region_offset,
194            flash_size,
195            flash_read_buffer,
196        }
197    }
198}
199
200impl<
201        F: 'static
202            + hil::flash::Flash
203            + hil::flash::HasClient<'static, TicKVSystem<'static, F, H, PAGE_SIZE>>,
204        H: 'static + Hasher<'static, 8>,
205        const PAGE_SIZE: usize,
206    > Component for TicKVDedicatedFlashComponent<F, H, PAGE_SIZE>
207{
208    type StaticInput = (
209        &'static mut MaybeUninit<TicKVSystem<'static, F, H, PAGE_SIZE>>,
210        &'static mut MaybeUninit<[u8; PAGE_SIZE]>,
211    );
212    type Output = &'static TicKVSystem<'static, F, H, PAGE_SIZE>;
213
214    fn finalize(self, static_buffer: Self::StaticInput) -> Self::Output {
215        let _grant_cap = create_capability!(capabilities::MemoryAllocationCapability);
216
217        let tickfs_read_buf = static_buffer.1.write([0; PAGE_SIZE]);
218
219        let tickv = static_buffer.0.write(TicKVSystem::new(
220            self.flash,
221            self.hasher,
222            tickfs_read_buf,
223            self.flash_read_buffer,
224            self.region_offset,
225            self.flash_size,
226        ));
227        self.flash.set_client(tickv);
228        self.hasher.set_client(tickv);
229        tickv.initialise();
230        tickv
231    }
232}