Skip to content
Snippets Groups Projects
Commit ecf02eb6 authored by Julien Cretin's avatar Julien Cretin
Browse files

Only store the storage location in the Kernel

parent 3edb3876
No related branches found
No related tags found
No related merge requests found
...@@ -42,7 +42,7 @@ index fe493727..105f7120 100644 ...@@ -42,7 +42,7 @@ index fe493727..105f7120 100644
platform.pconsole.start(); platform.pconsole.start();
diff --git a/chips/nrf52/src/nvmc.rs b/chips/nrf52/src/nvmc.rs diff --git a/chips/nrf52/src/nvmc.rs b/chips/nrf52/src/nvmc.rs
index 60fc2da8..77e7423d 100644 index 60fc2da8..45c75f89 100644
--- a/chips/nrf52/src/nvmc.rs --- a/chips/nrf52/src/nvmc.rs
+++ b/chips/nrf52/src/nvmc.rs +++ b/chips/nrf52/src/nvmc.rs
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
...@@ -126,7 +126,7 @@ index 60fc2da8..77e7423d 100644 ...@@ -126,7 +126,7 @@ index 60fc2da8..77e7423d 100644
let word: u32 = (data[i + 0] as u32) << 0 let word: u32 = (data[i + 0] as u32) << 0
| (data[i + 1] as u32) << 8 | (data[i + 1] as u32) << 8
| (data[i + 2] as u32) << 16 | (data[i + 2] as u32) << 16
@@ -390,3 +422,178 @@ impl hil::flash::Flash for Nvmc { @@ -390,3 +422,186 @@ impl hil::flash::Flash for Nvmc {
self.erase_page(page_number) self.erase_page(page_number)
} }
} }
...@@ -158,6 +158,8 @@ index 60fc2da8..77e7423d 100644 ...@@ -158,6 +158,8 @@ index 60fc2da8..77e7423d 100644
+/// - COMMAND(1, 2): Get the maximum number of word writes between page erasures (always 2). +/// - COMMAND(1, 2): Get the maximum number of word writes between page erasures (always 2).
+/// - COMMAND(1, 3): Get the maximum number page erasures in the lifetime of the flash (always +/// - COMMAND(1, 3): Get the maximum number page erasures in the lifetime of the flash (always
+/// 10000). +/// 10000).
+/// - COMMAND(1, 4): Get the storage address (page-aligned).
+/// - COMMAND(1, 5): Get the storage length (page-aligned).
+/// - COMMAND(2, ptr): Write the allow slice to the flash region starting at `ptr`. +/// - COMMAND(2, ptr): Write the allow slice to the flash region starting at `ptr`.
+/// - `ptr` must be word-aligned. +/// - `ptr` must be word-aligned.
+/// - The allow slice length must be word aligned. +/// - The allow slice length must be word aligned.
...@@ -268,6 +270,12 @@ index 60fc2da8..77e7423d 100644 ...@@ -268,6 +270,12 @@ index 60fc2da8..77e7423d 100644
+ (1, 3) => ReturnCode::SuccessWithValue { + (1, 3) => ReturnCode::SuccessWithValue {
+ value: MAX_PAGE_ERASES, + value: MAX_PAGE_ERASES,
+ }, + },
+ (1, 4) => ReturnCode::SuccessWithValue {
+ value: STORAGE_PTR,
+ },
+ (1, 5) => ReturnCode::SuccessWithValue {
+ value: STORAGE_LEN,
+ },
+ (1, _) => ReturnCode::EINVAL, + (1, _) => ReturnCode::EINVAL,
+ +
+ (2, ptr) => self + (2, ptr) => self
......
...@@ -133,20 +133,6 @@ pub struct PersistentStore { ...@@ -133,20 +133,6 @@ pub struct PersistentStore {
store: embedded_flash::Store<Storage, Config>, store: embedded_flash::Store<Storage, Config>,
} }
#[cfg(feature = "ram_storage")]
const PAGE_SIZE: usize = 0x100;
#[cfg(not(feature = "ram_storage"))]
const PAGE_SIZE: usize = 0x1000;
// We have the following layout:
// 0x00000-0x2ffff: Tock
// 0x30000-0x3ffff: Padding
// 0x40000-0xbffff: App
// 0xc0000-0xfffff: Store
#[cfg(not(any(test, feature = "ram_storage")))]
const STORE_ADDR: usize = 0xC0000;
const STORE_SIZE: usize = NUM_PAGES * PAGE_SIZE;
impl PersistentStore { impl PersistentStore {
/// Gives access to the persistent store. /// Gives access to the persistent store.
/// ///
...@@ -167,19 +153,16 @@ impl PersistentStore { ...@@ -167,19 +153,16 @@ impl PersistentStore {
#[cfg(not(any(test, feature = "ram_storage")))] #[cfg(not(any(test, feature = "ram_storage")))]
fn new_prod_storage() -> Storage { fn new_prod_storage() -> Storage {
let store = unsafe { Storage::new(NUM_PAGES).unwrap()
// Safety: The store cannot alias because this function is called only once.
core::slice::from_raw_parts_mut(STORE_ADDR as *mut u8, STORE_SIZE)
};
unsafe {
// Safety: The store is in a writeable flash region.
Storage::new(store).unwrap()
}
} }
#[cfg(any(test, feature = "ram_storage"))] #[cfg(any(test, feature = "ram_storage"))]
fn new_test_storage() -> Storage { fn new_test_storage() -> Storage {
let store = vec![0xff; STORE_SIZE].into_boxed_slice(); #[cfg(not(test))]
const PAGE_SIZE: usize = 0x100;
#[cfg(test)]
const PAGE_SIZE: usize = 0x1000;
let store = vec![0xff; NUM_PAGES * PAGE_SIZE].into_boxed_slice();
let options = embedded_flash::BufferOptions { let options = embedded_flash::BufferOptions {
word_size: 4, word_size: 4,
page_size: PAGE_SIZE, page_size: PAGE_SIZE,
......
...@@ -24,6 +24,8 @@ mod command_nr { ...@@ -24,6 +24,8 @@ mod command_nr {
pub const PAGE_SIZE: usize = 1; pub const PAGE_SIZE: usize = 1;
pub const MAX_WORD_WRITES: usize = 2; pub const MAX_WORD_WRITES: usize = 2;
pub const MAX_PAGE_ERASES: usize = 3; pub const MAX_PAGE_ERASES: usize = 3;
pub const STORAGE_PTR: usize = 4;
pub const STORAGE_LEN: usize = 5;
} }
pub const WRITE_SLICE: usize = 2; pub const WRITE_SLICE: usize = 2;
pub const ERASE_PAGE: usize = 3; pub const ERASE_PAGE: usize = 3;
...@@ -53,46 +55,31 @@ pub struct SyscallStorage { ...@@ -53,46 +55,31 @@ pub struct SyscallStorage {
impl SyscallStorage { impl SyscallStorage {
/// Provides access to the embedded flash if available. /// Provides access to the embedded flash if available.
/// ///
/// # Safety
///
/// The `storage` must be readable.
///
/// # Errors /// # Errors
/// ///
/// Returns `BadFlash` if any of the following conditions do not hold: /// Returns `BadFlash` if any of the following conditions do not hold:
/// - The word size is not a power of two. /// - The word size is a power of two.
/// - The page size is not a power of two. /// - The page size is a power of two.
/// - The page size is not a multiple of the word size. /// - The page size is a multiple of the word size.
/// /// - The storage is page-aligned.
/// Returns `NotAligned` if any of the following conditions do not hold:
/// - `storage` is page-aligned.
/// - `storage.len()` is a multiple of the page size.
/// ///
/// # Examples /// Returns `OutOfBounds` the number of pages does not fit in the storage.
/// pub fn new(num_pages: usize) -> StorageResult<SyscallStorage> {
/// ```rust
/// # extern crate ctap2;
/// # use ctap2::embedded_flash::SyscallStorage;
/// # use ctap2::embedded_flash::StorageResult;
/// # const STORAGE_ADDR: usize = 0x1000;
/// # const STORAGE_SIZE: usize = 0x1000;
/// # fn foo() -> StorageResult<SyscallStorage> {
/// // This is safe because we create and use `storage` only once in the whole program.
/// let storage = unsafe {
/// core::slice::from_raw_parts_mut(STORAGE_ADDR as *mut u8, STORAGE_SIZE)
/// };
/// // This is safe because `storage` is readable.
/// unsafe { SyscallStorage::new(storage) }
/// # }
/// ```
pub unsafe fn new(storage: &'static mut [u8]) -> StorageResult<SyscallStorage> {
let word_size = get_info(command_nr::get_info_nr::WORD_SIZE)?; let word_size = get_info(command_nr::get_info_nr::WORD_SIZE)?;
let page_size = get_info(command_nr::get_info_nr::PAGE_SIZE)?; let page_size = get_info(command_nr::get_info_nr::PAGE_SIZE)?;
let max_word_writes = get_info(command_nr::get_info_nr::MAX_WORD_WRITES)?; let max_word_writes = get_info(command_nr::get_info_nr::MAX_WORD_WRITES)?;
let max_page_erases = get_info(command_nr::get_info_nr::MAX_PAGE_ERASES)?; let max_page_erases = get_info(command_nr::get_info_nr::MAX_PAGE_ERASES)?;
let storage_ptr = get_info(command_nr::get_info_nr::STORAGE_PTR)?;
let max_storage_len = get_info(command_nr::get_info_nr::STORAGE_LEN)?;
if !word_size.is_power_of_two() || !page_size.is_power_of_two() { if !word_size.is_power_of_two() || !page_size.is_power_of_two() {
return Err(StorageError::BadFlash); return Err(StorageError::BadFlash);
} }
let storage_len = num_pages * page_size;
if storage_len > max_storage_len {
return Err(StorageError::OutOfBounds);
}
let storage =
unsafe { core::slice::from_raw_parts_mut(storage_ptr as *mut u8, storage_len) };
let syscall = SyscallStorage { let syscall = SyscallStorage {
word_size, word_size,
page_size, page_size,
...@@ -100,16 +87,10 @@ impl SyscallStorage { ...@@ -100,16 +87,10 @@ impl SyscallStorage {
max_page_erases, max_page_erases,
storage, storage,
}; };
if !syscall.is_word_aligned(page_size) { if !syscall.is_word_aligned(page_size) || !syscall.is_page_aligned(storage_ptr) {
return Err(StorageError::BadFlash); return Err(StorageError::BadFlash);
} }
if syscall.is_page_aligned(syscall.storage.as_ptr() as usize) Ok(syscall)
&& syscall.is_page_aligned(syscall.storage.len())
{
Ok(syscall)
} else {
Err(StorageError::NotAligned)
}
} }
fn is_word_aligned(&self, x: usize) -> bool { fn is_word_aligned(&self, x: usize) -> bool {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment