diff --git a/Cargo.lock b/Cargo.lock index 2a3c0f077..85ecfd2b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1941,11 +1941,10 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" [[package]] name = "littlefs2" version = "0.6.1" -source = "git+https://github.com/trussed-dev/littlefs2.git?rev=v0.6.1-nitrokey.1#b3a7371d849695fa05ab75910c4b14057db7ceb2" +source = "git+https://github.com/trussed-dev/littlefs2.git?rev=d0ebffac28f264990e8eedea98074005f318f0f4#d0ebffac28f264990e8eedea98074005f318f0f4" dependencies = [ "bitflags 2.9.1", "delog", - "generic-array", "heapless", "littlefs2-core", "littlefs2-sys", @@ -1954,7 +1953,7 @@ dependencies = [ [[package]] name = "littlefs2-core" version = "0.1.1" -source = "git+https://github.com/trussed-dev/littlefs2.git?rev=v0.6.1-nitrokey.1#b3a7371d849695fa05ab75910c4b14057db7ceb2" +source = "git+https://github.com/trussed-dev/littlefs2.git?rev=d0ebffac28f264990e8eedea98074005f318f0f4#d0ebffac28f264990e8eedea98074005f318f0f4" dependencies = [ "bitflags 2.9.1", "heapless-bytes", @@ -3476,7 +3475,7 @@ dependencies = [ [[package]] name = "trussed" version = "0.1.0" -source = "git+https://github.com/trussed-dev/trussed.git?rev=e107ed315a07dc6c992fac39d542e847cc3a1b6c#e107ed315a07dc6c992fac39d542e847cc3a1b6c" +source = "git+https://github.com/trussed-dev/trussed.git?rev=7c19c00a8959a88a498032fb096d4574d1a85007#7c19c00a8959a88a498032fb096d4574d1a85007" dependencies = [ "aes", "bitflags 2.9.1", diff --git a/Cargo.toml b/Cargo.toml index 0688e3bbf..2f1f3e1c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ memory-regions = { path = "components/memory-regions" } # unreleased libraries p256-cortex-m4 = { git = "https://github.com/ycrypto/p256-cortex-m4.git", rev = "cdb31e12594b4dc1f045b860a885fdc94d96aee2" } -trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "e107ed315a07dc6c992fac39d542e847cc3a1b6c" } +trussed = { git = "https://github.com/trussed-dev/trussed.git", rev = "7c19c00a8959a88a498032fb096d4574d1a85007" } trussed-usbip = { git = "https://github.com/trussed-dev/pc-usbip-runner.git", rev = "504674453c9573a30aa2f155101df49eb2af1ba7" } # applications @@ -37,8 +37,8 @@ trussed-rsa-alloc = { git = "https://github.com/trussed-dev/trussed-rsa-backend. trussed-se050-backend = { git = "https://github.com/Nitrokey/trussed-se050-backend.git", tag = "v0.5.0" } trussed-staging = { git = "https://github.com/trussed-dev/trussed-staging.git", tag = "v0.3.3" } littlefs2-sys = { git = "https://github.com/trussed-dev/littlefs2-sys.git", rev = "v0.3.1-nitrokey.1" } -littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "v0.6.1-nitrokey.1" } -littlefs2-core = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "v0.6.1-nitrokey.1" } +littlefs2 = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "d0ebffac28f264990e8eedea98074005f318f0f4"} +littlefs2-core = { git = "https://github.com/trussed-dev/littlefs2.git", rev = "d0ebffac28f264990e8eedea98074005f318f0f4"} [profile.release] codegen-units = 1 diff --git a/components/boards/Cargo.toml b/components/boards/Cargo.toml index bc10c98f3..6f1c45821 100644 --- a/components/boards/Cargo.toml +++ b/components/boards/Cargo.toml @@ -27,7 +27,7 @@ trussed = { version = "0.1", default-features = false } usb-device = "0.2" usbd-ccid = "0.3" usbd-ctaphid = "0.3" -utils = { path = "../utils" } +utils = { path = "../utils", features = ["storage"]} # soc-lpc55 lpc55-hal = { version = "0.4", optional = true } diff --git a/components/boards/src/flash.rs b/components/boards/src/flash.rs index bd26f9fd6..de46d30c1 100644 --- a/components/boards/src/flash.rs +++ b/components/boards/src/flash.rs @@ -32,13 +32,32 @@ where SPI: Transfer, CS: OutputPin, { - const BLOCK_SIZE: usize = 4096; - const READ_SIZE: usize = 4; - const WRITE_SIZE: usize = 256; - const BLOCK_COUNT: usize = - (FLASH_PROPERTIES.size / Self::BLOCK_SIZE) - (SPARE_LEN / Self::BLOCK_SIZE); - type CACHE_SIZE = generic_array::typenum::U256; - type LOOKAHEAD_SIZE = generic_array::typenum::U1; + fn read_size(&self) -> usize { + 4 + } + + fn write_size(&self) -> usize { + 256 + } + + fn block_size(&self) -> usize { + 4096 + } + + fn cache_size(&self) -> usize { + 256 + } + + fn lookahead_size(&self) -> usize { + 1 + } + + fn block_count(&self) -> usize { + (FLASH_PROPERTIES.size / self.block_size()) - (SPARE_LEN / self.block_size()) + } + + type CACHE_BUFFER = [u8; 256]; + type LOOKAHEAD_BUFFER = [u8; 8]; fn read(&mut self, off: usize, buf: &mut [u8]) -> Result { /*trace!("EFr {:x} {:x}", off, buf.len()); diff --git a/components/boards/src/init.rs b/components/boards/src/init.rs index c05f53aba..1e558bb7b 100644 --- a/components/boards/src/init.rs +++ b/components/boards/src/init.rs @@ -53,6 +53,12 @@ impl Resources { } } +impl Default for Resources { + fn default() -> Self { + Self::new() + } +} + pub struct UsbResources { usb_bus: Option::UsbBus>>, } @@ -63,6 +69,12 @@ impl UsbResources { } } +impl Default for UsbResources { + fn default() -> Self { + Self::new() + } +} + #[derive(Debug)] pub struct DelogFlusher {} diff --git a/components/boards/src/lib.rs b/components/boards/src/lib.rs index e0f5242e7..2ea43736e 100644 --- a/components/boards/src/lib.rs +++ b/components/boards/src/lib.rs @@ -30,6 +30,7 @@ use littlefs2::{ use nfc_device::traits::nfc::Device as NfcDevice; use rand_chacha::ChaCha8Rng; use trussed::{client::Syscall, Platform}; +use utils::MaybeStorage; use crate::{ soc::{Soc, Uuid}, @@ -51,7 +52,7 @@ pub trait Board { type Led: RgbLed; type InternalStorage: Storage + 'static; - type ExternalStorage: Storage + 'static; + type ExternalStorage: MaybeStorage; #[cfg(feature = "se050")] type Se050Timer: se05x::embedded_hal::Delay + 'static; diff --git a/components/boards/src/nk3am.rs b/components/boards/src/nk3am.rs index 4a35dc8c1..d6c98d912 100644 --- a/components/boards/src/nk3am.rs +++ b/components/boards/src/nk3am.rs @@ -76,7 +76,7 @@ impl Board for NK3AM { // regular mount failed, try mounting "old" (pre-journaling) IFS let pac = unsafe { nrf52840_pac::Peripherals::steal() }; let mut old_ifs_storage = OldFlashStorage::new(pac.NVMC); - let mut old_ifs_alloc: Allocation = Filesystem::allocate(); + let mut old_ifs_alloc: Allocation = Filesystem::allocate(&old_ifs_storage); let old_mountable = Filesystem::is_mountable(&mut old_ifs_storage); // we can mount the old ifs filesystem, thus we need to migrate diff --git a/components/boards/src/nk3am/migrations/ftl_journal/ifs_flash_old.rs b/components/boards/src/nk3am/migrations/ftl_journal/ifs_flash_old.rs index b57b3ec30..9fc0b136b 100644 --- a/components/boards/src/nk3am/migrations/ftl_journal/ifs_flash_old.rs +++ b/components/boards/src/nk3am/migrations/ftl_journal/ifs_flash_old.rs @@ -13,13 +13,32 @@ pub struct FlashStorage { } impl littlefs2::driver::Storage for FlashStorage { - const BLOCK_SIZE: usize = 256; - const READ_SIZE: usize = 4; - const WRITE_SIZE: usize = 4; - const BLOCK_COUNT: usize = FLASH_SIZE / Self::BLOCK_SIZE; + fn read_size(&self) -> usize { + 4 + } + + fn write_size(&self) -> usize { + 4 + } + + fn block_size(&self) -> usize { + 256 + } + + fn cache_size(&self) -> usize { + 256 + } + + fn lookahead_size(&self) -> usize { + 1 + } + + fn block_count(&self) -> usize { + FLASH_SIZE / self.block_size() + } - type CACHE_SIZE = generic_array::typenum::U256; - type LOOKAHEAD_SIZE = generic_array::typenum::U1; + type CACHE_BUFFER = [u8; 256]; + type LOOKAHEAD_BUFFER = [u8; 8]; fn read(&mut self, off: usize, buf: &mut [u8]) -> Result { // w/o this too much spam is generated, thus writes/deletes traces get lost diff --git a/components/boards/src/nk3xn/prince.rs b/components/boards/src/nk3xn/prince.rs index 8ebbad016..e8b2a3e66 100644 --- a/components/boards/src/nk3xn/prince.rs +++ b/components/boards/src/nk3xn/prince.rs @@ -4,7 +4,6 @@ // License: Apache-2.0 or MIT use littlefs2::{ - consts::{U512, U8}, driver::Storage, io::{Error, Result}, }; @@ -111,15 +110,32 @@ impl InternalFilesystem { } impl Storage for InternalFilesystem { - const READ_SIZE: usize = READ_SIZE; - const WRITE_SIZE: usize = WRITE_SIZE; - const BLOCK_SIZE: usize = BLOCK_SIZE; + fn read_size(&self) -> usize { + READ_SIZE + } + fn write_size(&self) -> usize { + WRITE_SIZE + } + fn block_size(&self) -> usize { + BLOCK_SIZE + } + fn cache_size(&self) -> usize { + 512 + } + fn lookahead_size(&self) -> usize { + 8 + } + + fn block_cycles(&self) -> isize { + -1 + } - const BLOCK_COUNT: usize = BLOCK_COUNT; - const BLOCK_CYCLES: isize = -1; + fn block_count(&self) -> usize { + BLOCK_COUNT + } - type CACHE_SIZE = U512; - type LOOKAHEAD_SIZE = U8; + type CACHE_BUFFER = [u8; 512]; + type LOOKAHEAD_BUFFER = [u8; 8 * 8]; fn read(&mut self, off: usize, buf: &mut [u8]) -> Result { with_enabled(&mut self.prince, || { diff --git a/components/boards/src/nkpk.rs b/components/boards/src/nkpk.rs index f9f87624b..334d22903 100644 --- a/components/boards/src/nkpk.rs +++ b/components/boards/src/nkpk.rs @@ -1,6 +1,6 @@ use littlefs2::{fs::Allocation, io::Result as LfsResult}; use memory_regions::MemoryRegions; -use utils::RamStorage; +use utils::PhantomStorage; use super::nk3am::{ self, @@ -55,4 +55,4 @@ impl Board for NKPK { pub type InternalFlashStorage = FlashStorage<{ MEMORY_REGIONS.filesystem.start }, { MEMORY_REGIONS.filesystem.end }>; // TODO: Do we want to mirror the NK3AM EFS? -pub type ExternalFlashStorage = RamStorage; +pub type ExternalFlashStorage = PhantomStorage; diff --git a/components/boards/src/soc/nrf52/flash.rs b/components/boards/src/soc/nrf52/flash.rs index 18b3b2bfd..ecb2494c8 100644 --- a/components/boards/src/soc/nrf52/flash.rs +++ b/components/boards/src/soc/nrf52/flash.rs @@ -200,14 +200,32 @@ impl FlashStorage { } impl littlefs2::driver::Storage for FlashStorage { - const BLOCK_SIZE: usize = FTL_BLOCK_SIZE; - const READ_SIZE: usize = 4; - const WRITE_SIZE: usize = FTL_BLOCK_SIZE; - const BLOCK_COUNT: usize = - ((END - START) / Self::BLOCK_SIZE) - (FTL_BLOCKS_IN_REAL * FTL_JOURNAL_BLOCKS); - - type CACHE_SIZE = generic_array::typenum::U256; - type LOOKAHEAD_SIZE = generic_array::typenum::U1; + fn read_size(&self) -> usize { + 4 + } + + fn write_size(&self) -> usize { + FTL_BLOCK_SIZE + } + + fn block_size(&self) -> usize { + FTL_BLOCK_SIZE + } + + fn cache_size(&self) -> usize { + 256 + } + + fn lookahead_size(&self) -> usize { + 1 + } + + fn block_count(&self) -> usize { + ((END - START) / self.block_size()) - (FTL_BLOCKS_IN_REAL * FTL_JOURNAL_BLOCKS) + } + + type CACHE_BUFFER = [u8; 256]; + type LOOKAHEAD_BUFFER = [u8; 8]; fn read(&mut self, off: usize, buf: &mut [u8]) -> Result { // skip journal blocks diff --git a/components/boards/src/store.rs b/components/boards/src/store.rs index 6b59062a1..3ce2cd0b9 100644 --- a/components/boards/src/store.rs +++ b/components/boards/src/store.rs @@ -10,6 +10,7 @@ use littlefs2::{ }; use trussed::store::Store; use trussed_manage::FACTORY_RESET_MARKER_FILE; +use utils::{EmptyFilesystem, MaybeStorage}; use crate::Board; @@ -19,19 +20,19 @@ const_ram_storage!( erase_value = 0xff, read_size = 16, write_size = 256, - cache_size_ty = littlefs2::consts::U256, + cache_size = 256, // We use 256 instead of the default 512 to avoid loosing too much space to nearly empty blocks containing only folder metadata. block_size = 256, block_count = 8192 / 256, - lookahead_size_ty = littlefs2::consts::U1, - filename_max_plus_one_ty = littlefs2::consts::U256, - path_max_plus_one_ty = littlefs2::consts::U256, + lookahead_size = 1, ); pub struct StoreResources { internal: StorageResources, external: StorageResources, volatile: StorageResources, + // Used in cases where EFS is "faked" + empty_efs: MaybeUninit, } impl StoreResources { @@ -40,17 +41,24 @@ impl StoreResources { internal: StorageResources::new(), external: StorageResources::new(), volatile: StorageResources::new(), + empty_efs: MaybeUninit::uninit(), } } } -pub struct StorageResources { - fs: MaybeUninit>, - alloc: MaybeUninit>, +impl Default for StoreResources { + fn default() -> Self { + Self::new() + } +} + +pub struct StorageResources { + fs: MaybeUninit>, + alloc: MaybeUninit>, storage: MaybeUninit, } -impl StorageResources { +impl StorageResources { pub const fn new() -> Self { Self { fs: MaybeUninit::uninit(), @@ -60,6 +68,12 @@ impl StorageResources { } } +impl Default for StorageResources { + fn default() -> Self { + Self::new() + } +} + struct StorePointers { ifs: MaybeUninit<&'static dyn DynFilesystem>, efs: MaybeUninit<&'static dyn DynFilesystem>, @@ -134,12 +148,13 @@ pub fn init_store( status: &mut InitStatus, ) -> RunnerStore { let ifs_storage = resources.internal.storage.write(int_flash); - let ifs_alloc = resources.internal.alloc.write(Filesystem::allocate()); let efs_storage = resources.external.storage.write(ext_flash); - let efs_alloc = resources.external.alloc.write(Filesystem::allocate()); let vfs_storage = resources.volatile.storage.write(VolatileStorage::new()); - let vfs_alloc = resources.volatile.alloc.write(Filesystem::allocate()); + let ifs_alloc = resources + .internal + .alloc + .write(Filesystem::allocate(ifs_storage)); let ifs = match init_ifs::(ifs_storage, ifs_alloc, efs_storage, status) { Ok(ifs) => resources.internal.fs.write(ifs), Err(_e) => { @@ -148,14 +163,27 @@ pub fn init_store( } }; - let efs = match init_efs::(efs_storage, efs_alloc, simulated_efs, status) { - Ok(efs) => resources.external.fs.write(efs), - Err(_e) => { - error!("EFS Mount Error {:?}", _e); - panic!("EFS"); + let efs: &mut dyn DynFilesystem = if let Some(efs_storage) = efs_storage.as_storage() { + let efs_alloc = resources + .external + .alloc + .write(Filesystem::allocate(efs_storage)); + + match init_efs::(efs_storage, efs_alloc, simulated_efs, status) { + Ok(efs) => resources.external.fs.write(efs), + Err(_e) => { + error!("EFS Mount Error {:?}", _e); + panic!("EFS"); + } } + } else { + resources.empty_efs.write(EmptyFilesystem) }; + let vfs_alloc = resources + .volatile + .alloc + .write(Filesystem::allocate(vfs_storage)); let vfs = match init_vfs(vfs_storage, vfs_alloc) { Ok(vfs) => resources.volatile.fs.write(vfs), Err(_e) => { @@ -197,11 +225,11 @@ fn init_ifs( #[inline(always)] fn init_efs<'a, B: Board>( - efs_storage: &'a mut B::ExternalStorage, - efs_alloc: &'a mut Allocation, + efs_storage: &'a mut ::Storage, + efs_alloc: &'a mut Allocation<::Storage>, simulated_efs: bool, status: &mut InitStatus, -) -> Result> { +) -> Result::Storage>> { use littlefs2::fs::{Config as LfsConfig, MountFlags}; if cfg!(feature = "format-filesystem") { Filesystem::format(efs_storage).ok(); @@ -220,14 +248,14 @@ fn init_efs<'a, B: Board>( let shrink_res = Filesystem::mount_and_then_with_config(storage, config.clone(), |fs| { mounted_with_wrong_block_count = true; - fs.shrink(B::ExternalStorage::BLOCK_COUNT) + fs.shrink(fs.total_blocks()) }); match shrink_res { Ok(_) => return Ok(()), // The error is just the block count and shrinking failed, we warn that reformat is required Err(_) if mounted_with_wrong_block_count => { status.insert(InitStatus::EXT_FLASH_NEED_REFORMAT); - *efs_alloc = Allocation::with_config(config); + *efs_alloc = Allocation::with_config(storage, config); return Ok(()); } // Failed to mount when ignoring block count check. Error is something else @@ -439,12 +467,10 @@ mod tests { erase_value = 0xFF, read_size = 4, write_size = 256, - cache_size_ty = littlefs2::consts::U256, + cache_size = 256, block_size = 4096, block_count = FULL_EXTERNAL_STORAGE_BLOCK_COUNT, - lookahead_size_ty = littlefs2::consts::U1, - filename_max_plus_one_ty = littlefs2::consts::U1, - path_max_plus_one_ty = littlefs2::consts::U2, + lookahead_size = 1, ); const_ram_storage!( @@ -452,12 +478,10 @@ mod tests { erase_value = 0xFF, read_size = 4, write_size = 256, - cache_size_ty = littlefs2::consts::U256, + cache_size = 256, block_size = 4096, block_count = CROPPED_EXTERNAL_STORAGE_BLOCK_COUNT, - lookahead_size_ty = littlefs2::consts::U1, - filename_max_plus_one_ty = littlefs2::consts::U1, - path_max_plus_one_ty = littlefs2::consts::U2, + lookahead_size = 1, ); const_ram_storage!( @@ -465,12 +489,10 @@ mod tests { erase_value = 0xFF, read_size = 4, write_size = 256, - cache_size_ty = littlefs2::consts::U256, + cache_size = 256, block_size = 4096, block_count = 0x20_0000 / 4096, - lookahead_size_ty = littlefs2::consts::U1, - filename_max_plus_one_ty = littlefs2::consts::U1, - path_max_plus_one_ty = littlefs2::consts::U2, + lookahead_size = 1, ); impl Board for TestBoard { @@ -514,8 +536,8 @@ mod tests { .unwrap(); let efs_storage_cropped: &mut ExternalStorageCropped = unsafe { &mut *(&raw mut *efs_storage_cropped as *mut ExternalStorageCropped) }; - let efs_alloc = &mut Allocation::new(); - let efs_alloc_cropped = &mut Allocation::new(); + let efs_alloc = &mut Allocation::new(efs_storage_full); + let efs_alloc_cropped = &mut Allocation::new(efs_storage_cropped); let storage = init_efs::>( efs_storage_full, efs_alloc, @@ -540,7 +562,7 @@ mod tests { // Check that factory reset correctly reformats the filesystem storage.write(FACTORY_RESET_MARKER_FILE, &[]).unwrap(); let (_, efs_storage_full) = storage.into_inner(); - let efs_alloc = &mut Allocation::new(); + let efs_alloc = &mut Allocation::new(efs_storage_full); let storage = init_efs::>( efs_storage_full, @@ -560,7 +582,7 @@ mod tests { assert_eq!(storage.total_blocks(), 0x20_0000 / 4096); let (_, efs_storage) = storage.into_inner(); - let efs_alloc = &mut Allocation::new(); + let efs_alloc = &mut Allocation::new(efs_storage); let storage = init_efs::>(efs_storage, efs_alloc, false, &mut status) .unwrap(); @@ -590,7 +612,7 @@ mod tests { } } let (_, efs_storage_full) = storage.into_inner(); - let efs_alloc = &mut Allocation::new(); + let efs_alloc = &mut Allocation::new(efs_storage_full); efs_storage_cropped .buf @@ -607,7 +629,7 @@ mod tests { .unwrap(); assert_eq!(status, InitStatus::EXT_FLASH_NEED_REFORMAT); let (_, efs_storage_cropped) = storage.into_inner(); - let efs_alloc_cropped = &mut Allocation::new(); + let efs_alloc_cropped = &mut Allocation::new(efs_storage_cropped); efs_storage_cropped.buf.fill(0); efs_storage_full.buf.fill(0); diff --git a/components/utils/src/lib.rs b/components/utils/src/lib.rs index 8f6284857..6ea10c08a 100644 --- a/components/utils/src/lib.rs +++ b/components/utils/src/lib.rs @@ -12,5 +12,5 @@ mod version; #[cfg(feature = "build")] pub use build::version_string; #[cfg(feature = "storage")] -pub use storage::{OptionalStorage, RamStorage}; +pub use storage::{EmptyFilesystem, MaybeStorage, OptionalStorage, PhantomStorage}; pub use version::Version; diff --git a/components/utils/src/storage.rs b/components/utils/src/storage.rs index 21b2ceabd..960e9b28e 100644 --- a/components/utils/src/storage.rs +++ b/components/utils/src/storage.rs @@ -1,128 +1,140 @@ use core::marker::PhantomData; -use littlefs2::{driver::Storage, io::Error}; - -// Chosen so that the littlefs2 header fits. Note that using this size will cause a `NoSpace` -// error during formatting. The filesystem will still be mountable though. -const DEFAULT_RAM_SIZE: usize = 256; -const ERASED: u8 = 0xff; +use littlefs2::{ + driver::Storage, + fs::{Attribute, FileOpenFlags, Metadata}, + io::{Error, OpenSeekFrom}, + object_safe::{DirEntriesCallback, DynFilesystem, FileCallback, Predicate}, + path::Path, +}; + +pub struct EmptyFilesystem; + +impl DynFilesystem for EmptyFilesystem { + fn total_blocks(&self) -> usize { + 0 + } -pub struct RamStorage { - buf: [u8; SIZE], - _marker: PhantomData, -} + fn total_space(&self) -> usize { + 0 + } + fn available_blocks(&self) -> Result { + Ok(0) + } + fn available_space(&self) -> Result { + Ok(0) + } -impl Storage for RamStorage { - const BLOCK_SIZE: usize = S::BLOCK_SIZE; - const READ_SIZE: usize = S::READ_SIZE; - const WRITE_SIZE: usize = S::WRITE_SIZE; - const BLOCK_COUNT: usize = S::BLOCK_COUNT; - - type CACHE_SIZE = S::CACHE_SIZE; - type LOOKAHEAD_SIZE = S::LOOKAHEAD_SIZE; - - fn read(&mut self, off: usize, buf: &mut [u8]) -> Result { - let read_size: usize = Self::READ_SIZE; - debug_assert!(off % read_size == 0); - debug_assert!(buf.len() % read_size == 0); - for (from, to) in self.buf.iter().skip(off).zip(buf.iter_mut()) { - *to = *from; - } - // Data outside of the RAM part is always erased - for to in buf.iter_mut().skip(self.buf.len().saturating_sub(off)) { - *to = ERASED; - } - info!("{}: {:?}", buf.len(), buf); - Ok(buf.len()) - } - - fn write(&mut self, off: usize, data: &[u8]) -> Result { - if off + data.len() > SIZE { - return Err(Error::NO_SPACE); - } - let write_size: usize = Self::WRITE_SIZE; - debug_assert!(off % write_size == 0); - debug_assert!(data.len() % write_size == 0); - for (from, to) in data.iter().zip(self.buf.iter_mut().skip(off)) { - *to = *from; - } - info!("{}: {:?}", data.len(), data); - Ok(data.len()) - } - - fn erase(&mut self, off: usize, len: usize) -> Result { - let block_size: usize = Self::BLOCK_SIZE; - debug_assert!(off % block_size == 0); - debug_assert!(len % block_size == 0); - for byte in self.buf.iter_mut().skip(off).take(len) { - *byte = ERASED; - } - Ok(len) + fn remove(&self, _: &Path) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn remove_dir(&self, _: &Path) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn remove_dir_all(&self, _: &Path) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn remove_dir_all_where(&self, _: &Path, _: Predicate) -> Result { + Err(Error::NO_SPACE) + } + fn rename(&self, _: &Path, _: &Path) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn exists(&self, _: &Path) -> bool { + false + } + fn metadata(&self, _: &Path) -> Result { + Err(Error::NO_SPACE) } -} -impl Default for RamStorage { - fn default() -> Self { - Self { - buf: [0xff; SIZE], - _marker: Default::default(), - } + fn create_file_and_then_unit(&self, _: &Path, _: FileCallback) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn open_file_and_then_unit(&self, _: &Path, _: FileCallback) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn open_file_with_flags_and_then_unit( + &self, + _: FileOpenFlags, + _: &Path, + _: FileCallback, + ) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn attribute<'a>( + &self, + _: &Path, + _: u8, + _: &'a mut [u8], + ) -> Result>, Error> { + Err(Error::NO_SPACE) + } + fn remove_attribute<'a>(&self, _: &Path, _: u8) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn set_attribute(&self, _: &Path, _: u8, _: &[u8]) -> Result<(), Error> { + Err(Error::NO_SPACE) } -} -pub enum OptionalStorage { - Storage(S), - Ram(RamStorage), -} + fn create_dir(&self, _: &Path) -> Result<(), Error> { + Err(Error::NO_SPACE) + } -impl OptionalStorage { - pub fn is_ram(&self) -> bool { - matches!(self, Self::Ram(_)) + fn create_dir_all(&self, _: &Path) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn write(&self, _: &Path, _: &[u8]) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn write_chunk(&self, _: &Path, _: &[u8], _: OpenSeekFrom) -> Result<(), Error> { + Err(Error::NO_SPACE) + } + fn read_dir_and_then_unit(&self, _: &Path, _: DirEntriesCallback<'_>) -> Result<(), Error> { + Err(Error::NO_SPACE) } } -impl Storage for OptionalStorage { - const BLOCK_SIZE: usize = S::BLOCK_SIZE; - const READ_SIZE: usize = S::READ_SIZE; - const WRITE_SIZE: usize = S::WRITE_SIZE; - const BLOCK_COUNT: usize = S::BLOCK_COUNT; +pub trait MaybeStorage: 'static { + type Storage: Storage + 'static; + + fn as_storage(&mut self) -> Option<&mut Self::Storage>; +} - type CACHE_SIZE = S::CACHE_SIZE; - type LOOKAHEAD_SIZE = S::LOOKAHEAD_SIZE; +/// Exists only to avoid conflicting impls +pub struct OptionalStorage(pub Option); - fn read(&mut self, off: usize, buf: &mut [u8]) -> Result { - info_now!("EFr {:x} {:x}", off, buf.len()); - match self { - Self::Storage(s) => s.read(off, buf), - Self::Ram(s) => s.read(off, buf), - } +impl From> for OptionalStorage { + fn from(value: Option) -> Self { + Self(value) } +} - fn write(&mut self, off: usize, data: &[u8]) -> Result { - info_now!("EFw {:x} {:x}", off, data.len()); - match self { - Self::Storage(s) => s.write(off, data), - Self::Ram(s) => s.write(off, data), - } +/// Exists only to avoid conflicting impls +pub struct PhantomStorage(pub PhantomData); + +impl Default for PhantomStorage { + fn default() -> Self { + Self(PhantomData) } +} - fn erase(&mut self, off: usize, len: usize) -> Result { - info_now!("EFe {:x} {:x}", off, len); - match self { - Self::Storage(s) => s.erase(off, len), - Self::Ram(s) => s.erase(off, len), - } +impl MaybeStorage for OptionalStorage { + type Storage = S; + fn as_storage(&mut self) -> Option<&mut S> { + self.0.as_mut() } } -impl Default for OptionalStorage { - fn default() -> Self { - Self::Ram(Default::default()) +impl MaybeStorage for S { + type Storage = S; + fn as_storage(&mut self) -> Option<&mut S> { + Some(self) } } -impl From for OptionalStorage { - fn from(storage: S) -> Self { - Self::Storage(storage) +impl MaybeStorage for PhantomStorage { + type Storage = S; + fn as_storage(&mut self) -> Option<&mut S> { + None } } diff --git a/runners/embedded/src/nk3xn/init.rs b/runners/embedded/src/nk3xn/init.rs index d611df766..0e772ccb6 100644 --- a/runners/embedded/src/nk3xn/init.rs +++ b/runners/embedded/src/nk3xn/init.rs @@ -582,11 +582,11 @@ impl Stage4 { nb::block!(self.basic.delay_timer.wait()).ok(); if let Some(storage) = ExtFlashStorage::try_new(spi, flash_cs) { - storage.into() + Some(storage).into() } else { self.status.insert(InitStatus::EXTERNAL_FLASH_ERROR); info!("failed to initialize external flash, using fallback"); - OptionalStorage::default() + None.into() } } @@ -599,7 +599,7 @@ impl Stage4 { self.setup_external_flash(spi) } else { info_now!("simulating external flash with RAM"); - OptionalStorage::default() + None.into() }; #[cfg(not(feature = "no-encrypted-storage"))] @@ -631,7 +631,7 @@ impl Stage4 { self.basic.perf_timer.elapsed().0 / 1000 ); // TODO: poll iso14443 - let simulated_efs = external.is_ram(); + let simulated_efs = external.0.is_none(); let store = store::init_store( resources, internal, diff --git a/runners/nkpk/Cargo.toml b/runners/nkpk/Cargo.toml index 6074defd6..cd032de15 100644 --- a/runners/nkpk/Cargo.toml +++ b/runners/nkpk/Cargo.toml @@ -33,6 +33,7 @@ log-warn = [] log-error = [] log-none = [] no-delog = ["boards/no-delog", "delog/knock-it-off"] +develop = [] log-rtt = ["boards/log-rtt"] diff --git a/runners/nkpk/src/main.rs b/runners/nkpk/src/main.rs index 7ce524234..bbfde6248 100644 --- a/runners/nkpk/src/main.rs +++ b/runners/nkpk/src/main.rs @@ -11,7 +11,7 @@ mod app { use apps::{Endpoints, Reboot}; use boards::{ init::{CtaphidDispatch, Resources, UsbClasses}, - nkpk::{self, ExternalFlashStorage, InternalFlashStorage, NKPK}, + nkpk::{self, InternalFlashStorage, NKPK}, runtime, soc::nrf52::{self, rtic_monotonic::RtcDuration, Nrf52}, store, Apps, Trussed, @@ -84,7 +84,7 @@ mod app { ); let internal_flash = InternalFlashStorage::new(ctx.device.NVMC); - let external_flash = ExternalFlashStorage::default(); + let external_flash = Default::default(); let store = store::init_store( &mut ctx.local.resources.store, internal_flash, diff --git a/runners/usbip/src/store.rs b/runners/usbip/src/store.rs index 24f661288..e05510dee 100644 --- a/runners/usbip/src/store.rs +++ b/runners/usbip/src/store.rs @@ -7,7 +7,6 @@ use std::{ use littlefs2::{ const_ram_storage, - consts::{U1, U512, U8}, driver::Storage, fs::{Allocation, Filesystem}, }; @@ -15,6 +14,7 @@ use littlefs2_core::{DynFilesystem, Error, Result}; use trussed_usbip::Store; const IFS_STORAGE_SIZE: usize = 512 * 128; +const FILESYSTEM_BLOCK_SIZE: usize = 512; const_ram_storage!(InternalRamStorage, IFS_STORAGE_SIZE); // Modelled after the actual external RAM, see src/flash.rs in the embedded runner @@ -23,12 +23,10 @@ const_ram_storage!( erase_value = 0xff, read_size = 4, write_size = 256, - cache_size_ty = U512, + cache_size = 512, block_size = 4096, block_count = 0x2_0000 / 4096, - lookahead_size_ty = U1, - filename_max_plus_one_ty = U256, - path_max_plus_one_ty = U256, + lookahead_size = 1, ); const_ram_storage!(VolatileStorage, IFS_STORAGE_SIZE); @@ -52,7 +50,7 @@ pub fn init(ifs: Option, efs: Option) -> Store { } fn mount_fs(path: PathBuf) -> Result<&'static dyn DynFilesystem> { - let len = u64::try_from(S::BLOCK_SIZE * S::BLOCK_COUNT).unwrap(); + let len = u64::try_from(IFS_STORAGE_SIZE).unwrap(); let format = if let Ok(file) = File::open(&path) { assert_eq!(file.metadata().unwrap().len(), len); false @@ -66,7 +64,7 @@ fn mount_fs(path: PathBuf) -> Result<&'static dyn DynFiles } fn mount(storage: S, format: bool) -> Result<&'static dyn DynFilesystem> { - let alloc = Box::leak(Box::new(Allocation::new())); + let alloc = Box::leak(Box::new(Allocation::new(&storage))); let storage = Box::leak(Box::new(storage)); if format { Filesystem::format(storage)?; @@ -90,15 +88,32 @@ impl FilesystemStorage { } impl Storage for FilesystemStorage { - const READ_SIZE: usize = S::READ_SIZE; - const WRITE_SIZE: usize = S::WRITE_SIZE; - const BLOCK_SIZE: usize = S::BLOCK_SIZE; + fn read_size(&self) -> usize { + 256 + } + + fn write_size(&self) -> usize { + 256 + } + + fn block_size(&self) -> usize { + FILESYSTEM_BLOCK_SIZE + } - const BLOCK_COUNT: usize = S::BLOCK_COUNT; - const BLOCK_CYCLES: isize = S::BLOCK_CYCLES; + fn cache_size(&self) -> usize { + 256 + } + + fn lookahead_size(&self) -> usize { + 1 + } + + fn block_count(&self) -> usize { + self.block_size() / IFS_STORAGE_SIZE + } - type CACHE_SIZE = U512; - type LOOKAHEAD_SIZE = U8; + type CACHE_BUFFER = S::CACHE_BUFFER; + type LOOKAHEAD_BUFFER = S::LOOKAHEAD_BUFFER; fn read(&mut self, offset: usize, buffer: &mut [u8]) -> Result { let mut file = File::open(&self.path).unwrap(); @@ -109,7 +124,7 @@ impl Storage for FilesystemStorage { } fn write(&mut self, offset: usize, data: &[u8]) -> Result { - if offset + data.len() > Self::BLOCK_COUNT * Self::BLOCK_SIZE { + if offset + data.len() > self.block_count() * FILESYSTEM_BLOCK_SIZE { return Err(Error::NO_SPACE); } let mut file = OpenOptions::new().write(true).open(&self.path).unwrap(); @@ -121,15 +136,15 @@ impl Storage for FilesystemStorage { } fn erase(&mut self, offset: usize, len: usize) -> Result { - if offset + len > Self::BLOCK_COUNT * Self::BLOCK_SIZE { + if offset + len > self.block_count() * FILESYSTEM_BLOCK_SIZE { return Err(Error::NO_SPACE); } let mut file = OpenOptions::new().write(true).open(&self.path).unwrap(); file.seek(SeekFrom::Start(offset as _)).unwrap(); - let zero_block = vec![0xFFu8; S::BLOCK_SIZE]; - for _ in 0..(len / Self::BLOCK_SIZE) { + let zero_block = vec![0xFFu8; FILESYSTEM_BLOCK_SIZE]; + for _ in 0..(len / FILESYSTEM_BLOCK_SIZE) { let bytes_written = file.write(&zero_block).unwrap(); - assert_eq!(bytes_written, Self::BLOCK_SIZE); + assert_eq!(bytes_written, FILESYSTEM_BLOCK_SIZE); } file.flush().unwrap(); Ok(len)