vck_common/store.rs
1// SPDX-FileCopyrightText: 2026 JC-Lab <joseph@jc-lab.net>
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use crate::{
6 types::{EncryptedOffset, VolumeState},
7 VckResult,
8};
9
10/// Abstraction over raw sector read/write of a single volume.
11///
12/// Implemented differently per environment:
13/// - UEFI loader: backed by `EFI_BLOCK_IO_PROTOCOL` (see `lib/common` uefi
14/// feature, or `lib/loader`).
15/// - Kernel driver: backed by the lower volume device (`lib/windrv`).
16///
17/// All offsets are absolute LBAs on the volume.
18///
19/// `Send + Sync` so a `JvckMetadataStore<S>` / `Arc<dyn SectorIo>` can be shared
20/// with the background sweep thread.
21pub trait SectorIo: Send + Sync {
22 fn sector_size(&self) -> u32;
23 /// Total raw sector count of the volume (partition capacity).
24 fn total_sectors(&self) -> u64;
25 fn read_sectors(&self, lba: u64, buf: &mut [u8]) -> VckResult<()>;
26 fn write_sectors(&self, lba: u64, buf: &[u8]) -> VckResult<()>;
27}
28
29/// Blanket impl so an `Arc<dyn SectorIo>` (or any `Arc<T: SectorIo>`) is itself a
30/// `SectorIo`. This lets a caller share one owning I/O handle: e.g. hand an
31/// `Arc<dyn SectorIo>` to `JvckMetadataStore::open` (which consumes an `S:
32/// SectorIo` by value) while keeping a clone for the background sweep.
33impl<T: SectorIo + ?Sized> SectorIo for alloc::sync::Arc<T> {
34 fn sector_size(&self) -> u32 {
35 (**self).sector_size()
36 }
37 fn total_sectors(&self) -> u64 {
38 (**self).total_sectors()
39 }
40 fn read_sectors(&self, lba: u64, buf: &mut [u8]) -> VckResult<()> {
41 (**self).read_sectors(lba, buf)
42 }
43 fn write_sectors(&self, lba: u64, buf: &[u8]) -> VckResult<()> {
44 (**self).write_sectors(lba, buf)
45 }
46}
47
48/// Persists the progressive-encryption offset durably so encryption can resume
49/// after a reboot or power loss.
50///
51/// The default JVCK implementation (`jvck::JvckMetadataStore`) writes the value
52/// to every configured header/footer replica.
53pub trait EncryptedOffsetStore: Send + Sync + 'static {
54 fn load(&self) -> VckResult<EncryptedOffset>;
55 fn store(&self, offset: &EncryptedOffset) -> VckResult<()>;
56 fn flush(&self) -> VckResult<()>;
57
58 /// Load the persisted sweep direction (encrypt vs decrypt). Defaults to
59 /// `Encrypt` for stores that do not track it.
60 fn load_state(&self) -> VckResult<VolumeState> {
61 Ok(VolumeState::Encrypt)
62 }
63
64 /// Persist the sweep direction durably (so a reboot resumes the right
65 /// direction). Default no-op for stores that do not track it.
66 fn store_state(&self, _state: VolumeState) -> VckResult<()> {
67 Ok(())
68 }
69}