Only store the storage location in the Kernel
This commit is contained in:
@@ -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 60fc2da8..77e7423d 100644
|
||||
index 60fc2da8..45c75f89 100644
|
||||
--- a/chips/nrf52/src/nvmc.rs
|
||||
+++ b/chips/nrf52/src/nvmc.rs
|
||||
@@ -3,6 +3,7 @@
|
||||
@@ -126,7 +126,7 @@ index 60fc2da8..77e7423d 100644
|
||||
let word: u32 = (data[i + 0] as u32) << 0
|
||||
| (data[i + 1] as u32) << 8
|
||||
| (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)
|
||||
}
|
||||
}
|
||||
@@ -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, 3): Get the maximum number page erasures in the lifetime of the flash (always
|
||||
+/// 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`.
|
||||
+/// - `ptr` must be word-aligned.
|
||||
+/// - The allow slice length must be word aligned.
|
||||
@@ -268,6 +270,12 @@ index 60fc2da8..77e7423d 100644
|
||||
+ (1, 3) => ReturnCode::SuccessWithValue {
|
||||
+ value: MAX_PAGE_ERASES,
|
||||
+ },
|
||||
+ (1, 4) => ReturnCode::SuccessWithValue {
|
||||
+ value: STORAGE_PTR,
|
||||
+ },
|
||||
+ (1, 5) => ReturnCode::SuccessWithValue {
|
||||
+ value: STORAGE_LEN,
|
||||
+ },
|
||||
+ (1, _) => ReturnCode::EINVAL,
|
||||
+
|
||||
+ (2, ptr) => self
|
||||
|
||||
@@ -133,20 +133,6 @@ pub struct PersistentStore {
|
||||
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 {
|
||||
/// Gives access to the persistent store.
|
||||
///
|
||||
@@ -167,19 +153,16 @@ impl PersistentStore {
|
||||
|
||||
#[cfg(not(any(test, feature = "ram_storage")))]
|
||||
fn new_prod_storage() -> Storage {
|
||||
let store = unsafe {
|
||||
// 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()
|
||||
}
|
||||
Storage::new(NUM_PAGES).unwrap()
|
||||
}
|
||||
|
||||
#[cfg(any(test, feature = "ram_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 {
|
||||
word_size: 4,
|
||||
page_size: PAGE_SIZE,
|
||||
|
||||
@@ -24,6 +24,8 @@ mod command_nr {
|
||||
pub const PAGE_SIZE: usize = 1;
|
||||
pub const MAX_WORD_WRITES: usize = 2;
|
||||
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 ERASE_PAGE: usize = 3;
|
||||
@@ -53,46 +55,31 @@ pub struct SyscallStorage {
|
||||
impl SyscallStorage {
|
||||
/// Provides access to the embedded flash if available.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The `storage` must be readable.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `BadFlash` if any of the following conditions do not hold:
|
||||
/// - The word size is not a power of two.
|
||||
/// - The page size is not a power of two.
|
||||
/// - The page size is not a multiple of the word size.
|
||||
/// - The word size is a power of two.
|
||||
/// - The page size is a power of two.
|
||||
/// - 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
|
||||
///
|
||||
/// ```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> {
|
||||
/// Returns `OutOfBounds` the number of pages does not fit in the storage.
|
||||
pub fn new(num_pages: usize) -> StorageResult<SyscallStorage> {
|
||||
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 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 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() {
|
||||
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 {
|
||||
word_size,
|
||||
page_size,
|
||||
@@ -100,16 +87,10 @@ impl SyscallStorage {
|
||||
max_page_erases,
|
||||
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);
|
||||
}
|
||||
if syscall.is_page_aligned(syscall.storage.as_ptr() as usize)
|
||||
&& syscall.is_page_aligned(syscall.storage.len())
|
||||
{
|
||||
Ok(syscall)
|
||||
} else {
|
||||
Err(StorageError::NotAligned)
|
||||
}
|
||||
Ok(syscall)
|
||||
}
|
||||
|
||||
fn is_word_aligned(&self, x: usize) -> bool {
|
||||
|
||||
Reference in New Issue
Block a user