Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use common error for update API #347

Merged
merged 1 commit into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/board/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Major

- Update `platform::update::Api` to return `Error` instead of `usize`
- Replace `Error` type with `wasefire-error`
- Add `Api::Gpio` for low-level GPIOs
- Add `platform::Api::version()`
Expand Down
30 changes: 15 additions & 15 deletions crates/board/src/platform/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,46 +16,46 @@

use alloc::boxed::Box;

use crate::{Support, Unsupported};
use wasefire_error::Code;

use crate::{Error, Support, Unsupported};

/// Platform update interface.
///
/// Errors must fit on 23 bits (they will be negated for the applet API).
pub trait Api: Support<bool> + Send {
/// Returns the metadata of the platform.
///
/// This typically contains the version and side (A or B) of the running platform.
fn metadata() -> Result<Box<[u8]>, usize>;
fn metadata() -> Result<Box<[u8]>, Error>;

/// Starts a platform update process.
///
/// During a dry-run, any mutable operation is skipped and only checks are performed.
fn initialize(dry_run: bool) -> Result<(), usize>;
fn initialize(dry_run: bool) -> Result<(), Error>;

/// Processes the next chunk of a platform update.
fn process(chunk: &[u8]) -> Result<(), usize>;
fn process(chunk: &[u8]) -> Result<(), Error>;

/// Finalizes a platform update process.
///
/// This function will reboot when the update is successful and thus only returns in case of
/// errors or in dry-run mode.
fn finalize() -> Result<(), usize>;
fn finalize() -> Result<(), Error>;
}

impl Api for Unsupported {
fn metadata() -> Result<Box<[u8]>, usize> {
unreachable!()
fn metadata() -> Result<Box<[u8]>, Error> {
Err(Error::user(Code::NotImplemented))
}

fn initialize(_: bool) -> Result<(), usize> {
unreachable!()
fn initialize(_: bool) -> Result<(), Error> {
Err(Error::user(Code::NotImplemented))
}

fn process(_: &[u8]) -> Result<(), usize> {
unreachable!()
fn process(_: &[u8]) -> Result<(), Error> {
Err(Error::user(Code::NotImplemented))
}

fn finalize() -> Result<(), usize> {
unreachable!()
fn finalize() -> Result<(), Error> {
Err(Error::user(Code::NotImplemented))
}
}
44 changes: 9 additions & 35 deletions crates/runner-nordic/src/board/platform/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use alloc::vec::Vec;
use header::{Header, Side};
use wasefire_board_api::platform::update::Api;
use wasefire_board_api::Supported;
use wasefire_store::{Storage as _, StorageError, StorageIndex};
use wasefire_error::{Code, Error};
use wasefire_store::{Storage as _, StorageIndex};
use wasefire_sync::TakeCell;

use crate::storage::Storage;
Expand All @@ -28,22 +29,22 @@ pub enum Impl {}
impl Supported for Impl {}

impl Api for Impl {
fn metadata() -> Result<Box<[u8]>, usize> {
fn metadata() -> Result<Box<[u8]>, Error> {
let mut metadata = Vec::new();
let side = Side::current().ok_or(Error::NoSide)?;
let side = Side::current().ok_or(Error::world(Code::BadState))?;
push_header(&mut metadata, Header::new(side));
push_header(&mut metadata, Header::new(!side));
Ok(metadata.into_boxed_slice())
}

fn initialize(dry_run: bool) -> Result<(), usize> {
fn initialize(dry_run: bool) -> Result<(), Error> {
STATE.with(|state| {
state.reset(dry_run);
Ok(())
})
}

fn process(mut chunk: &[u8]) -> Result<(), usize> {
fn process(mut chunk: &[u8]) -> Result<(), Error> {
STATE.with(|state| {
while !chunk.is_empty() {
state.write(&mut chunk)?;
Expand All @@ -52,7 +53,7 @@ impl Api for Impl {
})
}

fn finalize() -> Result<(), usize> {
fn finalize() -> Result<(), Error> {
STATE.with(|state| {
state.flush()?;
match state.dry_run {
Expand Down Expand Up @@ -111,9 +112,9 @@ impl Update {
}
if !self.dry_run {
if byte == 0 {
self.storage.erase_page(page)?;
self.storage.erase_page(page).map_err(|_| Error::world(0))?;
}
self.storage.write_slice(index, value)?;
self.storage.write_slice(index, value).map_err(|_| Error::world(0))?;
}
*chunk = rest;
self.offset += value.len();
Expand All @@ -135,33 +136,6 @@ impl Update {
}
}

#[repr(usize)]
enum Error {
_Unknown = 0x00,
// Internal errors (0x01 ..= 0x7f).
NoSide = 0x01,
Storage = 0x02,
// User errors (0x81 ..= 0xff).
OutOfBounds = 0x81,
NotAligned = 0x82,
}

impl From<StorageError> for Error {
fn from(value: StorageError) -> Self {
match value {
StorageError::NotAligned => Error::NotAligned,
StorageError::OutOfBounds => Error::OutOfBounds,
StorageError::CustomError => Error::Storage,
}
}
}

impl From<Error> for usize {
fn from(value: Error) -> Self {
value as usize
}
}

fn push_header(metadata: &mut Vec<u8>, header: Header) {
match header.side() {
Side::A => metadata.push(0xa),
Expand Down
1 change: 1 addition & 0 deletions crates/scheduler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

### Minor

- Migrate to `platform::update` returning `Error`
- Migrate to `wasefire-error`
- Support `gpio` module
- Support `platform::version()`
Expand Down
21 changes: 4 additions & 17 deletions crates/scheduler/src/call/platform/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ fn metadata<B: Board>(mut call: SchedulerCall<B, api::metadata::Sig>) {
memory.get_mut(*len_ptr, 4)?.copy_from_slice(&len.to_le_bytes());
0.into()
}
Err(error) => convert(error).into(),
Err(error) => error.into(),
};
api::metadata::Results { res }
};
Expand All @@ -67,10 +67,7 @@ fn initialize<B: Board>(call: SchedulerCall<B, api::initialize::Sig>) {
1 => true,
_ => Err(Trap)?,
};
let res = match board::platform::Update::<B>::initialize(dry_run) {
Ok(()) => 0.into(),
Err(error) => convert(error).into(),
};
let res = board::platform::Update::<B>::initialize(dry_run).into();
api::initialize::Results { res }
};
call.reply(results);
Expand All @@ -82,10 +79,7 @@ fn process_<B: Board>(mut call: SchedulerCall<B, api::process::Sig>) {
let memory = scheduler.applet.memory();
let results = try {
let chunk = memory.get(*ptr, *len)?;
let res = match board::platform::Update::<B>::process(chunk) {
Ok(()) => 0.into(),
Err(error) => convert(error).into(),
};
let res = board::platform::Update::<B>::process(chunk).into();
api::process::Results { res }
};
call.reply(results);
Expand All @@ -94,15 +88,8 @@ fn process_<B: Board>(mut call: SchedulerCall<B, api::process::Sig>) {
fn finalize<B: Board>(call: SchedulerCall<B, api::finalize::Sig>) {
let api::finalize::Params {} = call.read();
let results = try {
let res = match board::platform::Update::<B>::finalize() {
Ok(()) => 0.into(),
Err(error) => convert(error).into(),
};
let res = board::platform::Update::<B>::finalize().into();
api::finalize::Results { res }
};
call.reply(results);
}

fn convert(error: usize) -> u32 {
!(error as u32)
}