Skip to main content

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}