Filter syscall at platform-level instead of driver-level

This commit is contained in:
Julien Cretin
2020-05-14 20:19:21 +02:00
parent cf31110922
commit ba5caf0691
3 changed files with 156 additions and 79 deletions

View File

@@ -27,7 +27,7 @@ index 44a6c1cc..2ebc2868 100644
components::gpio_component_helper!( components::gpio_component_helper!(
&nrf52840::gpio::PORT[Pin::P1_01], &nrf52840::gpio::PORT[Pin::P1_01],
diff --git a/boards/nordic/nrf52dk_base/src/lib.rs b/boards/nordic/nrf52dk_base/src/lib.rs diff --git a/boards/nordic/nrf52dk_base/src/lib.rs b/boards/nordic/nrf52dk_base/src/lib.rs
index 5dd4328e..b8867461 100644 index 5dd4328e..a117d35f 100644
--- a/boards/nordic/nrf52dk_base/src/lib.rs --- a/boards/nordic/nrf52dk_base/src/lib.rs
+++ b/boards/nordic/nrf52dk_base/src/lib.rs +++ b/boards/nordic/nrf52dk_base/src/lib.rs
@@ -104,6 +104,7 @@ pub struct Platform { @@ -104,6 +104,7 @@ pub struct Platform {
@@ -38,7 +38,7 @@ index 5dd4328e..b8867461 100644
} }
impl kernel::Platform for Platform { impl kernel::Platform for Platform {
@@ -128,6 +129,7 @@ impl kernel::Platform for Platform { @@ -128,10 +129,30 @@ impl kernel::Platform for Platform {
capsules::nonvolatile_storage_driver::DRIVER_NUM => { capsules::nonvolatile_storage_driver::DRIVER_NUM => {
f(self.nonvolatile_storage.map_or(None, |nv| Some(nv))) f(self.nonvolatile_storage.map_or(None, |nv| Some(nv)))
} }
@@ -46,7 +46,30 @@ index 5dd4328e..b8867461 100644
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
_ => f(None), _ => f(None),
} }
@@ -405,6 +407,15 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>( }
+
+ fn filter_syscall(
+ &self,
+ process: &dyn kernel::procs::ProcessType,
+ syscall: &kernel::syscall::Syscall,
+ ) -> Result<(), kernel::ReturnCode> {
+ use kernel::syscall::Syscall;
+ match *syscall {
+ Syscall::COMMAND {
+ driver_number: nrf52::nvmc::DRIVER_NUM,
+ subdriver_number: cmd,
+ arg0: ptr,
+ arg1: len,
+ } if (cmd == 2 || cmd == 3) && !process.fits_in_storage_location(ptr, len) => {
+ Err(kernel::ReturnCode::EINVAL)
+ }
+ _ => Ok(()),
+ }
+ }
}
/// Generic function for starting an nrf52dk board.
@@ -405,6 +426,14 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
); );
nrf52::acomp::ACOMP.set_client(analog_comparator); nrf52::acomp::ACOMP.set_client(analog_comparator);
@@ -55,14 +78,13 @@ index 5dd4328e..b8867461 100644
+ nrf52::nvmc::SyscallDriver::new( + nrf52::nvmc::SyscallDriver::new(
+ &nrf52::nvmc::NVMC, + &nrf52::nvmc::NVMC,
+ board_kernel.create_grant(&memory_allocation_capability), + board_kernel.create_grant(&memory_allocation_capability),
+ board_kernel.storage_locations(),
+ ) + )
+ ); + );
+ +
// Start all of the clocks. Low power operation will require a better // Start all of the clocks. Low power operation will require a better
// approach than this. // approach than this.
nrf52::clock::CLOCK.low_stop(); nrf52::clock::CLOCK.low_stop();
@@ -431,6 +442,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>( @@ -431,6 +460,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
analog_comparator: analog_comparator, analog_comparator: analog_comparator,
nonvolatile_storage: nonvolatile_storage, nonvolatile_storage: nonvolatile_storage,
ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability), ipc: kernel::ipc::IPC::new(board_kernel, &memory_allocation_capability),
@@ -71,7 +93,7 @@ index 5dd4328e..b8867461 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..6e59d197 100644 index 60fc2da8..ca41b899 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 @@
@@ -87,7 +109,7 @@ index 60fc2da8..6e59d197 100644
use kernel::common::StaticRef; use kernel::common::StaticRef;
use kernel::hil; use kernel::hil;
-use kernel::ReturnCode; -use kernel::ReturnCode;
+use kernel::{AppId, AppSlice, Callback, Driver, Grant, ReturnCode, Shared, StorageLocation}; +use kernel::{AppId, AppSlice, Callback, Driver, Grant, ReturnCode, Shared};
use crate::deferred_call_tasks::DeferredCallTask; use crate::deferred_call_tasks::DeferredCallTask;
@@ -135,7 +157,7 @@ index 60fc2da8..6e59d197 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 +402,217 @@ impl hil::flash::Flash for Nvmc { @@ -390,3 +402,180 @@ impl hil::flash::Flash for Nvmc {
self.erase_page(page_number) self.erase_page(page_number)
} }
} }
@@ -167,22 +189,18 @@ index 60fc2da8..6e59d197 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): The number of storage locations. +/// - COMMAND(2, ptr, len): Write the allow slice to the flash region starting at `ptr`.
+/// - COMMAND(1, 5, i): Get the address of the i-th storage location (page-aligned).
+/// - COMMAND(1, 6, i): Get the size of the i-th storage location (page-aligned).
+/// - 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.
+/// - The region starting at `ptr` of the same length as the allow slice must be in a writeable +/// - The region starting at `ptr` of the same length as the allow slice must be in a writeable
+/// flash region. +/// flash region.
+/// - COMMAND(3, ptr): Erase a page. +/// - COMMAND(3, ptr, len): Erase a page.
+/// - `ptr` must be page-aligned. +/// - `ptr` must be page-aligned.
+/// - The page starting at `ptr` must be in a writeable flash region. +/// - The page starting at `ptr` must be in a writeable flash region.
+/// - ALLOW(0): The allow slice for COMMAND(2). +/// - ALLOW(0): The allow slice for COMMAND(2).
+pub struct SyscallDriver { +pub struct SyscallDriver {
+ nvmc: &'static Nvmc, + nvmc: &'static Nvmc,
+ apps: Grant<App>, + apps: Grant<App>,
+ storage_locations: &'static [StorageLocation],
+} +}
+ +
+pub const DRIVER_NUM: usize = 0x50003; +pub const DRIVER_NUM: usize = 0x50003;
@@ -194,16 +212,8 @@ index 60fc2da8..6e59d197 100644
+} +}
+ +
+impl SyscallDriver { +impl SyscallDriver {
+ pub fn new( + pub fn new(nvmc: &'static Nvmc, apps: Grant<App>) -> SyscallDriver {
+ nvmc: &'static Nvmc, + SyscallDriver { nvmc, apps }
+ apps: Grant<App>,
+ storage_locations: &'static [StorageLocation],
+ ) -> SyscallDriver {
+ SyscallDriver {
+ nvmc,
+ apps,
+ storage_locations,
+ }
+ } + }
+} +}
+ +
@@ -213,24 +223,6 @@ index 60fc2da8..6e59d197 100644
+} +}
+ +
+impl SyscallDriver { +impl SyscallDriver {
+ fn in_storage_locations(&self, ptr: usize, len: usize) -> bool {
+ self.storage_locations.iter().any(|storage_location| {
+ let storage_ptr = storage_location.address;
+ let storage_len = storage_location.size;
+ // 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
+ })
+ }
+
+ /// Writes a word-aligned slice at a word-aligned address. + /// Writes a word-aligned slice at a word-aligned address.
+ /// + ///
+ /// Words are written only if necessary, i.e. if writing the new value would change the current + /// Words are written only if necessary, i.e. if writing the new value would change the current
@@ -250,9 +242,6 @@ index 60fc2da8..6e59d197 100644
+ /// - `slice.len()` must be word-aligned. + /// - `slice.len()` must be word-aligned.
+ /// - The slice starting at `ptr` of length `slice.len()` must fit in the storage. + /// - The slice starting at `ptr` of length `slice.len()` must fit in the storage.
+ fn write_slice(&self, ptr: usize, slice: &[u8]) -> ReturnCode { + fn write_slice(&self, ptr: usize, slice: &[u8]) -> ReturnCode {
+ if !self.in_storage_locations(ptr, slice.len()) {
+ return ReturnCode::EINVAL;
+ }
+ if ptr & WORD_MASK != 0 || slice.len() & WORD_MASK != 0 { + if ptr & WORD_MASK != 0 || slice.len() & WORD_MASK != 0 {
+ return ReturnCode::EINVAL; + return ReturnCode::EINVAL;
+ } + }
@@ -278,9 +267,6 @@ index 60fc2da8..6e59d197 100644
+ /// - `ptr` must be page-aligned. + /// - `ptr` must be page-aligned.
+ /// - The slice starting at `ptr` of length `PAGE_SIZE` must fit in the storage. + /// - The slice starting at `ptr` of length `PAGE_SIZE` must fit in the storage.
+ fn erase_page(&self, ptr: usize) -> ReturnCode { + fn erase_page(&self, ptr: usize) -> ReturnCode {
+ if !self.in_storage_locations(ptr, PAGE_SIZE) {
+ return ReturnCode::EINVAL;
+ }
+ if ptr & PAGE_MASK != 0 { + if ptr & PAGE_MASK != 0 {
+ return ReturnCode::EINVAL; + return ReturnCode::EINVAL;
+ } + }
@@ -296,40 +282,39 @@ index 60fc2da8..6e59d197 100644
+ } + }
+ +
+ fn command(&self, cmd: usize, arg0: usize, arg1: usize, appid: AppId) -> ReturnCode { + fn command(&self, cmd: usize, arg0: usize, arg1: usize, appid: AppId) -> ReturnCode {
+ match (cmd, arg0) { + match (cmd, arg0, arg1) {
+ (0, _) => ReturnCode::SUCCESS, + (0, _, _) => ReturnCode::SUCCESS,
+ +
+ (1, 0) => ReturnCode::SuccessWithValue { value: WORD_SIZE }, + (1, 0, _) => ReturnCode::SuccessWithValue { value: WORD_SIZE },
+ (1, 1) => ReturnCode::SuccessWithValue { value: PAGE_SIZE }, + (1, 1, _) => ReturnCode::SuccessWithValue { value: PAGE_SIZE },
+ (1, 2) => ReturnCode::SuccessWithValue { + (1, 2, _) => ReturnCode::SuccessWithValue {
+ value: MAX_WORD_WRITES, + value: MAX_WORD_WRITES,
+ }, + },
+ (1, 3) => ReturnCode::SuccessWithValue { + (1, 3, _) => ReturnCode::SuccessWithValue {
+ value: MAX_PAGE_ERASES, + value: MAX_PAGE_ERASES,
+ }, + },
+ (1, 4) => ReturnCode::SuccessWithValue { + (1, _, _) => ReturnCode::EINVAL,
+ value: self.storage_locations.len(),
+ },
+ (1, 5) if arg1 < self.storage_locations.len() => ReturnCode::SuccessWithValue {
+ value: self.storage_locations[arg1].address,
+ },
+ (1, 6) if arg1 < self.storage_locations.len() => ReturnCode::SuccessWithValue {
+ value: self.storage_locations[arg1].size,
+ },
+ (1, _) => ReturnCode::EINVAL,
+ +
+ (2, ptr) => self + (2, ptr, len) => self
+ .apps + .apps
+ .enter(appid, |app, _| { + .enter(appid, |app, _| {
+ let slice = match app.slice.take() { + let slice = match app.slice.take() {
+ None => return ReturnCode::EINVAL, + None => return ReturnCode::EINVAL,
+ Some(slice) => slice, + Some(slice) => slice,
+ }; + };
+ if len != slice.len() {
+ return ReturnCode::EINVAL;
+ }
+ self.write_slice(ptr, slice.as_ref()) + self.write_slice(ptr, slice.as_ref())
+ }) + })
+ .unwrap_or_else(|err| err.into()), + .unwrap_or_else(|err| err.into()),
+ +
+ (3, ptr) => self.erase_page(ptr), + (3, ptr, len) => {
+ if len != PAGE_SIZE {
+ return ReturnCode::EINVAL;
+ }
+ self.erase_page(ptr)
+ }
+ +
+ _ => ReturnCode::ENOSUPPORT, + _ => ReturnCode::ENOSUPPORT,
+ } + }
@@ -366,11 +351,90 @@ index ebe8052a..a6dcd278 100644
// Export only select items from the process module. To remove the name conflict // Export only select items from the process module. To remove the name conflict
// this cannot be called `process`, so we use a shortened version. These // this cannot be called `process`, so we use a shortened version. These
diff --git a/kernel/src/memop.rs b/kernel/src/memop.rs
index 7537d2b4..61870ccd 100644
--- a/kernel/src/memop.rs
+++ b/kernel/src/memop.rs
@@ -108,6 +108,25 @@ crate fn memop(process: &dyn ProcessType, op_type: usize, r1: usize) -> ReturnCo
ReturnCode::SUCCESS
}
+ // Op Type 12: Number of storage locations.
+ 12 => ReturnCode::SuccessWithValue { value: process.number_storage_locations() },
+
+ // Op Type 13: The start address of the storage location indexed by r1.
+ 13 => {
+ match process.get_storage_location(r1) {
+ None => ReturnCode::FAIL,
+ Some(x) => ReturnCode::SuccessWithValue { value: x.address }
+ }
+ }
+
+ // Op Type 14: The size of the storage location indexed by r1.
+ 14 => {
+ match process.get_storage_location(r1) {
+ None => ReturnCode::FAIL,
+ Some(x) => ReturnCode::SuccessWithValue { value: x.size }
+ }
+ }
+
_ => ReturnCode::ENOSUPPORT,
}
}
diff --git a/kernel/src/process.rs b/kernel/src/process.rs diff --git a/kernel/src/process.rs b/kernel/src/process.rs
index eb00f274..268a270d 100644 index eb00f274..41243c8e 100644
--- a/kernel/src/process.rs --- a/kernel/src/process.rs
+++ b/kernel/src/process.rs +++ b/kernel/src/process.rs
@@ -1604,6 +1604,33 @@ impl<C: 'static + Chip> Process<'a, C> { @@ -281,6 +281,15 @@ pub trait ProcessType {
/// writeable flash region.
fn get_writeable_flash_region(&self, region_index: usize) -> (u32, u32);
+ /// How many storage locations are defined for this process.
+ fn number_storage_locations(&self) -> usize;
+
+ /// Get the i-th storage location.
+ fn get_storage_location(&self, index: usize) -> Option<&crate::StorageLocation>;
+
+ /// Whether a slice fits in a storage location.
+ fn fits_in_storage_location(&self, ptr: usize, len: usize) -> bool;
+
/// Debug function to update the kernel on where the stack starts for this
/// process. Processes are not required to call this through the memop
/// system call, but it aids in debugging the process.
@@ -999,6 +1008,32 @@ impl<C: Chip> ProcessType for Process<'a, C> {
self.header.get_writeable_flash_region(region_index)
}
+ fn number_storage_locations(&self) -> usize {
+ self.kernel.storage_locations().len()
+ }
+
+ fn get_storage_location(&self, index: usize) -> Option<&crate::StorageLocation> {
+ self.kernel.storage_locations().get(index)
+ }
+
+ fn fits_in_storage_location(&self, ptr: usize, len: usize) -> bool {
+ self.kernel.storage_locations().iter().any(|storage_location| {
+ let storage_ptr = storage_location.address;
+ let storage_len = storage_location.size;
+ // 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
+ })
+ }
+
fn update_stack_start_pointer(&self, stack_pointer: *const u8) {
if stack_pointer >= self.mem_start() && stack_pointer < self.mem_end() {
self.debug.map(|debug| {
@@ -1604,6 +1639,33 @@ impl<C: 'static + Chip> Process<'a, C> {
return Ok((None, 0)); return Ok((None, 0));
} }

View File

@@ -62,7 +62,7 @@ index 105f7120..535e5cd8 100644
kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)), kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
_ => f(None), _ => f(None),
} }
@@ -157,6 +167,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>( @@ -176,6 +186,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
app_fault_response: kernel::procs::FaultResponse, app_fault_response: kernel::procs::FaultResponse,
reg_vout: Regulator0Output, reg_vout: Regulator0Output,
nfc_as_gpios: bool, nfc_as_gpios: bool,
@@ -70,7 +70,7 @@ index 105f7120..535e5cd8 100644
chip: &'static nrf52::chip::NRF52<I>, chip: &'static nrf52::chip::NRF52<I>,
) { ) {
// Make non-volatile memory writable and activate the reset button // Make non-volatile memory writable and activate the reset button
@@ -416,6 +427,44 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>( @@ -434,6 +445,44 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
) )
); );
@@ -115,7 +115,7 @@ index 105f7120..535e5cd8 100644
// Start all of the clocks. Low power operation will require a better // Start all of the clocks. Low power operation will require a better
// approach than this. // approach than this.
nrf52::clock::CLOCK.low_stop(); nrf52::clock::CLOCK.low_stop();
@@ -440,6 +489,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>( @@ -458,6 +507,7 @@ pub unsafe fn setup_board<I: nrf52::interrupt_service::InterruptService>(
temp: temp, temp: temp,
alarm: alarm, alarm: alarm,
analog_comparator: analog_comparator, analog_comparator: analog_comparator,

View File

@@ -25,9 +25,6 @@ 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_CNT: usize = 4;
pub const STORAGE_PTR: usize = 5;
pub const STORAGE_LEN: usize = 6;
} }
pub const WRITE_SLICE: usize = 2; pub const WRITE_SLICE: usize = 2;
pub const ERASE_PAGE: usize = 3; pub const ERASE_PAGE: usize = 3;
@@ -37,6 +34,12 @@ mod allow_nr {
pub const WRITE_SLICE: usize = 0; pub const WRITE_SLICE: usize = 0;
} }
mod memop_nr {
pub const STORAGE_CNT: u32 = 12;
pub const STORAGE_PTR: u32 = 13;
pub const STORAGE_LEN: u32 = 14;
}
fn get_info(nr: usize, arg: usize) -> StorageResult<usize> { fn get_info(nr: usize, arg: usize) -> StorageResult<usize> {
let code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::GET_INFO, nr, arg) }; let code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::GET_INFO, nr, arg) };
if code < 0 { if code < 0 {
@@ -46,6 +49,15 @@ fn get_info(nr: usize, arg: usize) -> StorageResult<usize> {
} }
} }
fn memop(nr: u32, arg: usize) -> StorageResult<usize> {
let code = unsafe { syscalls::memop(nr, arg) };
if code < 0 {
Err(StorageError::KernelError { code })
} else {
Ok(code as usize)
}
}
pub struct SyscallStorage { pub struct SyscallStorage {
word_size: usize, word_size: usize,
page_size: usize, page_size: usize,
@@ -82,9 +94,9 @@ impl SyscallStorage {
{ {
return Err(StorageError::BadFlash); return Err(StorageError::BadFlash);
} }
for i in 0..get_info(command_nr::get_info_nr::STORAGE_CNT, 0)? { for i in 0..memop(memop_nr::STORAGE_CNT, 0)? {
let storage_ptr = get_info(command_nr::get_info_nr::STORAGE_PTR, i)?; let storage_ptr = memop(memop_nr::STORAGE_PTR, i)?;
let max_storage_len = get_info(command_nr::get_info_nr::STORAGE_LEN, i)?; let max_storage_len = memop(memop_nr::STORAGE_LEN, i)?;
if !syscall.is_page_aligned(storage_ptr) || !syscall.is_page_aligned(max_storage_len) { if !syscall.is_page_aligned(storage_ptr) || !syscall.is_page_aligned(max_storage_len) {
return Err(StorageError::BadFlash); return Err(StorageError::BadFlash);
} }
@@ -154,7 +166,8 @@ impl Storage for SyscallStorage {
if code < 0 { if code < 0 {
return Err(StorageError::KernelError { code }); return Err(StorageError::KernelError { code });
} }
let code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::WRITE_SLICE, ptr, 0) }; let code =
unsafe { syscalls::command(DRIVER_NUMBER, command_nr::WRITE_SLICE, ptr, value.len()) };
if code < 0 { if code < 0 {
return Err(StorageError::KernelError { code }); return Err(StorageError::KernelError { code });
} }
@@ -165,7 +178,7 @@ impl Storage for SyscallStorage {
let index = Index { page, byte: 0 }; let index = Index { page, byte: 0 };
let length = self.page_size(); let length = self.page_size();
let ptr = self.read_slice(index, length)?.as_ptr() as usize; let ptr = self.read_slice(index, length)?.as_ptr() as usize;
let code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::ERASE_PAGE, ptr, 0) }; let code = unsafe { syscalls::command(DRIVER_NUMBER, command_nr::ERASE_PAGE, ptr, length) };
if code < 0 { if code < 0 {
return Err(StorageError::KernelError { code }); return Err(StorageError::KernelError { code });
} }