Only store the storage location in the Kernel
This commit is contained in:
@@ -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
|
|||||||
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
|
|||||||
+/// - 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
|
|||||||
+ (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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
#[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 {
|
|||||||
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 {
|
|||||||
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:
|
/// Returns `OutOfBounds` the number of pages does not fit in the storage.
|
||||||
/// - `storage` is page-aligned.
|
pub fn new(num_pages: usize) -> StorageResult<SyscallStorage> {
|
||||||
/// - `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> {
|
|
||||||
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 {
|
|||||||
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)
|
|
||||||
&& syscall.is_page_aligned(syscall.storage.len())
|
|
||||||
{
|
|
||||||
Ok(syscall)
|
Ok(syscall)
|
||||||
} else {
|
|
||||||
Err(StorageError::NotAligned)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_word_aligned(&self, x: usize) -> bool {
|
fn is_word_aligned(&self, x: usize) -> bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user