diff --git a/patches/tock/01-persistent-storage.patch b/patches/tock/01-persistent-storage.patch index fd293069b3822cc035278021db9a8a14254dfa58..73f8ef35ecd394d5aa74483bd603850c6f64d00a 100644 --- a/patches/tock/01-persistent-storage.patch +++ b/patches/tock/01-persistent-storage.patch @@ -42,7 +42,7 @@ index fe493727..105f7120 100644 platform.pconsole.start(); diff --git a/chips/nrf52/src/nvmc.rs b/chips/nrf52/src/nvmc.rs -index 5abd2d84..5a726fdb 100644 +index 60fc2da8..77e7423d 100644 --- a/chips/nrf52/src/nvmc.rs +++ b/chips/nrf52/src/nvmc.rs @@ -3,6 +3,7 @@ @@ -62,7 +62,7 @@ index 5abd2d84..5a726fdb 100644 use crate::deferred_call_tasks::DeferredCallTask; -@@ -141,7 +142,13 @@ register_bitfields! [u32, +@@ -141,7 +142,33 @@ register_bitfields! [u32, static DEFERRED_CALL: DeferredCall<DeferredCallTask> = unsafe { DeferredCall::new(DeferredCallTask::Nvmc) }; @@ -73,10 +73,30 @@ index 5abd2d84..5a726fdb 100644 +const MAX_PAGE_ERASES: usize = 10000; +const WORD_MASK: usize = WORD_SIZE - 1; +const PAGE_MASK: usize = PAGE_SIZE - 1; ++ ++// The storage is currently static and readable by all processes. This will be fixed once Tock ++// supports persistent storage outside the application flash (i.e. not the current writeable flash ++// regions support). ++const STORAGE_PTR: usize = 0xc0000; ++const STORAGE_LEN: usize = 0x40000; ++ ++fn in_storage(ptr: usize, len: usize) -> bool { ++ // We want to check the 2 following inequalities: ++ // (1) `STORAGE_PTR <= ptr` ++ // (2) `ptr + len <= STORAGE_PTR + STORAGE_LEN` ++ // However, the second one may overflow written as is. We introduce a third ++ // inequality to solve this issue: ++ // (3) `len <= STORAGE_LEN` ++ // Using this third inequality, we can rewrite the second one as: ++ // (4) `ptr - STORAGE_PTR <= STORAGE_LEN - len` ++ // This fourth inequality is equivalent to the second one but doesn't overflow when ++ // the first and third inequalities hold. ++ STORAGE_PTR <= ptr && len <= STORAGE_LEN && ptr - STORAGE_PTR <= STORAGE_LEN - len ++} /// This is a wrapper around a u8 array that is sized to a single page for the /// nrf. Users of this module must pass an object of this type to use the -@@ -215,6 +222,11 @@ impl Nvmc { +@@ -215,6 +242,11 @@ impl Nvmc { } } @@ -88,7 +108,7 @@ index 5abd2d84..5a726fdb 100644 /// Configure the NVMC to allow writes to flash. pub fn configure_writeable(&self) { let regs = &*self.registers; -@@ -230,7 +242,7 @@ impl Nvmc { +@@ -230,7 +262,7 @@ impl Nvmc { let regs = &*self.registers; regs.config.write(Configuration::WEN::Een); while !self.is_ready() {} @@ -97,7 +117,7 @@ index 5abd2d84..5a726fdb 100644 while !self.is_ready() {} } -@@ -314,7 +326,7 @@ impl Nvmc { +@@ -322,7 +354,7 @@ impl Nvmc { // Put the NVMC in write mode. regs.config.write(Configuration::WEN::Wen); @@ -106,7 +126,7 @@ index 5abd2d84..5a726fdb 100644 let word: u32 = (data[i + 0] as u32) << 0 | (data[i + 1] as u32) << 8 | (data[i + 2] as u32) << 16 -@@ -374,3 +386,170 @@ impl hil::flash::Flash for Nvmc { +@@ -390,3 +422,178 @@ impl hil::flash::Flash for Nvmc { self.erase_page(page_number) } } @@ -189,7 +209,11 @@ index 5abd2d84..5a726fdb 100644 + /// Fails with `EINVAL` if any of the following conditions does not hold: + /// - `ptr` must be word-aligned. + /// - `slice.len()` must be word-aligned. ++ /// - The slice starting at `ptr` of length `slice.len()` must fit in the storage. + fn write_slice(&self, ptr: usize, slice: &[u8]) -> ReturnCode { ++ if !in_storage(ptr, slice.len()) { ++ return ReturnCode::EINVAL; ++ } + if ptr & WORD_MASK != 0 || slice.len() & WORD_MASK != 0 { + return ReturnCode::EINVAL; + } @@ -213,7 +237,11 @@ index 5abd2d84..5a726fdb 100644 + /// + /// Fails with `EINVAL` if any of the following conditions does not hold: + /// - `ptr` must be page-aligned. ++ /// - The slice starting at `ptr` of length `PAGE_SIZE` must fit in the storage. + fn erase_page(&self, ptr: usize) -> ReturnCode { ++ if !in_storage(ptr, PAGE_SIZE) { ++ return ReturnCode::EINVAL; ++ } + if ptr & PAGE_MASK != 0 { + return ReturnCode::EINVAL; + } @@ -278,14 +306,16 @@ index 5abd2d84..5a726fdb 100644 + } +} diff --git a/kernel/src/process.rs b/kernel/src/process.rs -index eb00f274..35c19d15 100644 +index eb00f274..663c2422 100644 --- a/kernel/src/process.rs +++ b/kernel/src/process.rs -@@ -1604,6 +1604,31 @@ impl<C: 'static + Chip> Process<'a, C> { +@@ -1604,6 +1604,33 @@ impl<C: 'static + Chip> Process<'a, C> { return Ok((None, 0)); } -+ // Allocate MPU region for storage. ++ // Allocate MPU region for storage. The storage is currently static and readable by all ++ // processes. This will be fixed once Tock supports persistent storage outside the ++ // application flash (i.e. not the current writeable flash regions support). + const STORAGE_PTR: usize = 0xc0000; + const STORAGE_LEN: usize = 0x40000; + if chip diff --git a/src/ctap/storage.rs b/src/ctap/storage.rs index 879c1e730cfb3a39b4b7121f58b50a21b073ebbf..2a6e52ebc8fa780dfa62d1593ee177baf3ec7c42 100644 --- a/src/ctap/storage.rs +++ b/src/ctap/storage.rs @@ -145,7 +145,6 @@ const PAGE_SIZE: usize = 0x1000; // 0xc0000-0xfffff: Store #[cfg(not(any(test, feature = "ram_storage")))] const STORE_ADDR: usize = 0xC0000; -const STORE_SIZE_LIMIT: usize = 0x40000; const STORE_SIZE: usize = NUM_PAGES * PAGE_SIZE; impl PersistentStore { @@ -155,8 +154,6 @@ impl PersistentStore { /// /// This should be at most one instance of persistent store per program lifetime. pub fn new(rng: &mut impl Rng256) -> PersistentStore { - // This should ideally be a compile-time assert, but Rust doesn't have native support. - assert!(STORE_SIZE <= STORE_SIZE_LIMIT); #[cfg(not(any(test, feature = "ram_storage")))] let storage = PersistentStore::new_prod_storage(); #[cfg(any(test, feature = "ram_storage"))]