diff --git a/CHANGELOG.md b/CHANGELOG.md index b5e0aa9..bdac14e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,10 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -[Unreleased]: https://github.com/trussed-dev/admin-app/compare/0.4.0...HEAD +[Unreleased]: https://github.com/trussed-dev/admin-app/compare/0.5.0...HEAD - +## [0.5.0] 2026-09-16 + +[0.5.0]: https://github.com/trussed-dev/admin-app/compare/0.4.0...0.5.0 + +- Remove `ResetSignal`. It is now in `trussed-core`. + ## [0.4.0] 2026-09-16 [0.4.0]: https://github.com/trussed-dev/admin-app/compare/0.3.0...0.4.0 diff --git a/Cargo.toml b/Cargo.toml index 9e16cbe..418ff74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "admin-app" -version = "0.4.0" +version = "0.5.0" authors = ["Conor Patrick ", "Nicolas Stalder "] repository = "https://github.com/solokeys/admin-app" edition = "2021" @@ -18,9 +18,8 @@ iso7816 = "0.2" littlefs2 = { version = "0.8", optional = true } littlefs2-core = { version = "0.1", features = ["heapless-bytes05"] } serde = { version = "1.0.180", default-features = false } -strum_macros = "0.25.2" trussed = { version = "0.2", default-features = false } -trussed-core = { version = "0.2", features = ["crypto-client", "filesystem-client", "management-client", "ui-client"] } +trussed-core = { version = "0.2.3", features = ["crypto-client", "filesystem-client", "management-client", "ui-client"] } embedded-hal = { version = "0.2.7", optional = true } hex-literal = "0.4.1" diff --git a/src/config.rs b/src/config.rs index 2687267..dfae67b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,116 +1,20 @@ use core::{ fmt::{self, Display, Formatter, Write as _}, str::FromStr, - sync::atomic::{AtomicU8, Ordering}, }; use cbor_smol::{cbor_deserialize, cbor_serialize_to}; use heapless::{string::StringView, VecView}; use littlefs2_core::{path, Path}; use serde::{de::DeserializeOwned, Serialize}; -use strum_macros::FromRepr; use trussed::store::Filestore; use trussed_core::{ + reset_signal::ResetSignalAllocation, try_syscall, types::{Location, Message}, FilesystemClient, }; -#[derive(Debug)] -/// Structure meant to be stored in a `static` to signal applications that they have been factory-resetted by the admin app -/// -/// It is expected to have one such structure for each application supporting factory-reset by the admin-app -/// -/// ```rust,ignore -///# use admin_app::{ResetSignalAllocation, ConfigValueMut}; -///# use littlefs2::{path::Path, path}; -/// #[derive(Default, PartialEq, serde::Deserialize, serde::Serialize)] -/// struct Config { -/// use_new_backend: bool, -///}; -/// static OPCARD_RESET: ResetSignalAllocation = ResetSignalAllocation::new(); -/// impl admin_app::Config for Config { -/// fn field(&mut self, key: &str) -> Option> { -/// match key { -/// "opcard.use_new_backend" => Some(ConfigValueMut::Bool(&mut self.use_new_backend)), -/// _ => None, -/// } -/// } -/// /// Client ID to factory-reset if the associated configuration option is changed -/// fn reset_client_id(&self, key: &str) -> Option<(&'static Path, &'static ResetSignalAllocation)> { -/// match key { -/// "opcard" => Some((path!("opcard"), &OPCARD_RESET)), -/// "opcard.use_new_backend" =>Some((path!("opcard"), &OPCARD_RESET)), -/// _ => None, -/// } -/// } -/// } -/// ``` -pub struct ResetSignalAllocation(AtomicU8); - -impl Default for ResetSignalAllocation { - fn default() -> Self { - Self::new() - } -} - -impl ResetSignalAllocation { - pub const fn new() -> Self { - Self(AtomicU8::new(ResetSignal::None as u8)) - } - - pub fn load(&self) -> ResetSignal { - let v = self.0.load(Ordering::Relaxed); - ResetSignal::from_repr(v).expect("A reset signal value") - } - - pub fn set_factory_reset(&self) -> bool { - self.0 - .compare_exchange( - ResetSignal::None as u8, - ResetSignal::FactoryReset as u8, - Ordering::Relaxed, - Ordering::Relaxed, - ) - .is_ok() - } - - pub fn set_config_changed(&self) { - self.0 - .store(ResetSignal::ConfigChanged as u8, Ordering::Relaxed) - } - - /// Factory reset can be acknowledged so that the application can restart working - /// - /// A configuration change cannot be acknowledged as it requires a power cycle to be taken into account. - pub fn ack_factory_reset(&self) -> bool { - self.0 - .compare_exchange( - ResetSignal::FactoryReset as u8, - ResetSignal::None as u8, - Ordering::Relaxed, - Ordering::Relaxed, - ) - .is_ok() - } -} - -#[derive(Debug, FromRepr, Default)] -#[repr(u8)] -pub enum ResetSignal { - #[default] - /// The App can continue operating - None, - /// The app has had it state factory reseted by the admin app - /// - /// It should delete any runtime state it is currently holding, then [`acknowledge`](ResetSignalAllocation::ack_factory_reset) the reset and continue working. - FactoryReset, - /// A configuration relevant to the application has been changed. - /// - /// The application must reject all incoming request and store no persistent state until a power cycle. - ConfigChanged, -} - const LOCATION: Location = Location::Internal; const FILENAME: &Path = path!("config"); @@ -270,19 +174,49 @@ impl<'a> Display for ConfigValueMut<'a> { } } -#[derive(Debug, FromRepr)] -#[repr(u8)] -pub enum ConfigError { - ReadFailed = 1, - WriteFailed = 2, - DeserializationFailed = 3, - SerializationFailed = 4, - InvalidKey = 5, - InvalidValue = 6, - DataTooLong = 7, - NotConfirmed = 8, +macro_rules! enum_u8 { + ( + $(#[$outer:meta])* + $vis:vis enum $name:ident { + $($(#[$attr:meta])* $var:ident = $num:expr),+ + $(,)* + } + ) => { + $(#[$outer])* + #[repr(u8)] + $vis enum $name { + $( + $(#[$attr])* + $var = $num, + )* + } + + impl $name { + const fn from_repr(val: u8) -> Option<$name> { + match val { + $( + $num => Some($name::$var), + )* + _ => None, + } + } + } + } } +enum_u8!( + #[derive(Debug)] + pub enum ConfigError { + ReadFailed = 1, + WriteFailed = 2, + DeserializationFailed = 3, + SerializationFailed = 4, + InvalidKey = 5, + InvalidValue = 6, + DataTooLong = 7, + NotConfirmed = 8, + } +); const _: () = assert!( ConfigError::from_repr(0).is_none(), "ConfigError may not have a variant with discriminant zero as zero indicates success.", diff --git a/src/lib.rs b/src/lib.rs index 7e5ec23..78729b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,10 +17,7 @@ mod config; pub mod migrations; pub use admin::{App, Data, StatusBytes}; -pub use config::{ - Config, ConfigError, ConfigField, ConfigValueMut, FieldType, ResetConfigResult, ResetSignal, - ResetSignalAllocation, -}; +pub use config::{Config, ConfigError, ConfigField, ConfigValueMut, FieldType, ResetConfigResult}; use trussed_manage::ManageClient; #[cfg(feature = "se050")] use trussed_se050_manage::Se050ManageClient;