diff --git a/core/Makefile b/core/Makefile index 4aebf6db6..6db288ea1 100644 --- a/core/Makefile +++ b/core/Makefile @@ -83,7 +83,7 @@ test: ## run unit tests cd tests ; ./run_tests.sh $(TESTOPTS) test_rust: ## run rs unit tests - cd embed/rust ; cargo test --no-default-features --features model_t$(shell echo $(TREZOR_MODEL) | tr "T" "t"),test,ui,ui_debug -- --test-threads=1 + cd embed/rust ; cargo test --no-default-features --features model_t$(shell echo $(TREZOR_MODEL) | tr "TR" "tr"),test -- --test-threads=1 test_emu: ## run selected device tests from python-trezor $(EMU_TEST) $(PYTEST) $(TESTPATH)/device_tests $(TESTOPTS) diff --git a/core/SConscript.firmware b/core/SConscript.firmware index 34cdd72d5..b0bbcbb31 100644 --- a/core/SConscript.firmware +++ b/core/SConscript.firmware @@ -704,18 +704,14 @@ def cargo_build(): profile = '--release' else: profile = '' - if TREZOR_MODEL in ("1",): - features = ["model_t1"] - elif TREZOR_MODEL in ("R",): - features = ["model_tr"] - else: - features = ["model_tt"] - if BITCOIN_ONLY == "1": - features.append("bitcoin_only") + + features = ['micropython', 'protobuf', f'model_t{TREZOR_MODEL.lower()}'] + if BITCOIN_ONLY == '1': + features.append('bitcoin_only') if UI2: - features.append("ui") - if PYOPT == "0": - features.append("ui_debug") + features.append('ui') + if PYOPT == '0': + features.append('ui_debug') return f'cd embed/rust; cargo build {profile} --target={RUST_TARGET} --target-dir=../../build/firmware/rust --no-default-features --features "{" ".join(features)}"' diff --git a/core/SConscript.unix b/core/SConscript.unix index 2784656b8..c25358d8c 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -665,18 +665,13 @@ RUST_LIB = 'trezor_lib' RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a' def cargo_build(): - if TREZOR_MODEL in ('1',): - features = ["model_t1"] - elif TREZOR_MODEL in ('R',): - features = ["model_tr"] - else: - features = ["model_tt"] - if BITCOIN_ONLY == "1": - features.append("bitcoin_only") + features = ['micropython', 'protobuf', f'model_t{TREZOR_MODEL.lower()}'] + if BITCOIN_ONLY == '1': + features.append('bitcoin_only') if UI2: - features.append("ui") - if PYOPT == "0" or not FROZEN: - features.append("ui_debug") + features.append('ui') + if PYOPT == '0': + features.append('ui_debug') return f'cd embed/rust; cargo build --profile {RUST_PROFILE} --target-dir=../../build/unix/rust --no-default-features --features "{" ".join(features)}"' diff --git a/core/embed/rust/Cargo.toml b/core/embed/rust/Cargo.toml index 3adfdaf2c..fe0295ad3 100644 --- a/core/embed/rust/Cargo.toml +++ b/core/embed/rust/Cargo.toml @@ -11,12 +11,14 @@ bitcoin_only = [] model_tt = ["touch"] model_t1 = ["buttons"] model_tr = ["buttons"] +micropython = [] +protobuf = ["micropython"] ui = [] ui_debug = [] buttons = [] touch = [] clippy = [] -test = ["cc", "glob"] +test = ["cc", "glob", "micropython", "protobuf", "ui", "ui_debug"] [lib] crate-type = ["staticlib"] diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index 6e13ff9c2..7d5d59eef 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -3,7 +3,9 @@ use std::ffi::OsStr; use std::{env, path::PathBuf, process::Command}; fn main() { + #[cfg(feature = "micropython")] generate_qstr_bindings(); + #[cfg(feature = "micropython")] generate_micropython_bindings(); generate_trezorhal_bindings(); #[cfg(feature = "test")] @@ -18,6 +20,7 @@ fn model() -> String { } /// Generates Rust module that exports QSTR constants used in firmware. +#[cfg(feature = "micropython")] fn generate_qstr_bindings() { let out_path = env::var("OUT_DIR").unwrap(); @@ -117,6 +120,7 @@ fn prepare_bindings() -> bindgen::Builder { .parse_callbacks(Box::new(bindgen::CargoCallbacks)) } +#[cfg(feature = "micropython")] fn generate_micropython_bindings() { let out_path = env::var("OUT_DIR").unwrap(); @@ -269,7 +273,10 @@ fn generate_trezorhal_bindings() { .allowlist_function("slip39_word_completion_mask") .allowlist_function("button_sequence_to_word") // random - .allowlist_function("random_uniform"); + .allowlist_function("random_uniform") + // time + .allowlist_function("hal_delay") + .allowlist_function("hal_ticks_ms"); // Write the bindings to a file in the OUR_DIR. bindings diff --git a/core/embed/rust/src/error.rs b/core/embed/rust/src/error.rs index fcc0ac137..13e278603 100644 --- a/core/embed/rust/src/error.rs +++ b/core/embed/rust/src/error.rs @@ -1,7 +1,11 @@ -use core::convert::{Infallible, TryInto}; +use core::{ + convert::{Infallible, TryInto}, + num::TryFromIntError, +}; use cstr_core::CStr; +#[cfg(feature = "micropython")] use crate::micropython::{ffi, obj::Obj, qstr::Qstr}; #[allow(clippy::enum_variant_names)] // We mimic the Python exception classnames here. @@ -11,13 +15,19 @@ pub enum Error { OutOfRange, MissingKwargs, AllocationFailed, + #[cfg(feature = "micropython")] CaughtException(Obj), + #[cfg(feature = "micropython")] KeyError(Obj), + #[cfg(feature = "micropython")] AttributeError(Qstr), + #[cfg(feature = "micropython")] ValueError(&'static CStr), + #[cfg(feature = "micropython")] ValueErrorParam(&'static CStr, Obj), } +#[cfg(feature = "micropython")] impl Error { /// Create an exception instance matching the error code. The result of this /// call should only be used to immediately raise the exception, because the @@ -67,3 +77,9 @@ impl From for Error { unreachable!() } } + +impl From for Error { + fn from(_: TryFromIntError) -> Self { + Self::OutOfRange + } +} diff --git a/core/embed/rust/src/lib.rs b/core/embed/rust/src/lib.rs index 2fc1779b0..a79fdab42 100644 --- a/core/embed/rust/src/lib.rs +++ b/core/embed/rust/src/lib.rs @@ -5,8 +5,10 @@ #![allow(dead_code)] mod error; +#[cfg(feature = "micropython")] #[macro_use] mod micropython; +#[cfg(feature = "protobuf")] mod protobuf; mod time; #[cfg(feature = "ui_debug")] @@ -16,7 +18,6 @@ mod trezorhal; #[cfg(feature = "ui")] #[macro_use] pub mod ui; -mod util; #[cfg(not(test))] #[cfg(any(not(feature = "test"), feature = "clippy"))] diff --git a/core/embed/rust/src/micropython/mod.rs b/core/embed/rust/src/micropython/mod.rs index 4849d57f5..68659e800 100644 --- a/core/embed/rust/src/micropython/mod.rs +++ b/core/embed/rust/src/micropython/mod.rs @@ -16,6 +16,7 @@ pub mod qstr; pub mod runtime; pub mod time; pub mod typ; +pub mod util; #[cfg(test)] pub mod testutil; diff --git a/core/embed/rust/src/micropython/obj.rs b/core/embed/rust/src/micropython/obj.rs index 9cd027cd0..616ce81f6 100644 --- a/core/embed/rust/src/micropython/obj.rs +++ b/core/embed/rust/src/micropython/obj.rs @@ -1,7 +1,4 @@ -use core::{ - convert::{TryFrom, TryInto}, - num::TryFromIntError, -}; +use core::convert::{TryFrom, TryInto}; use cstr_core::CStr; @@ -413,9 +410,3 @@ impl Obj { } } } - -impl From for Error { - fn from(_: TryFromIntError) -> Self { - Self::OutOfRange - } -} diff --git a/core/embed/rust/src/util.rs b/core/embed/rust/src/micropython/util.rs similarity index 89% rename from core/embed/rust/src/util.rs rename to core/embed/rust/src/micropython/util.rs index 885b72220..caa2ae2d3 100644 --- a/core/embed/rust/src/util.rs +++ b/core/embed/rust/src/micropython/util.rs @@ -81,16 +81,3 @@ pub unsafe fn try_with_args_and_kwargs_inline( }; unsafe { try_or_raise(block) } } - -pub trait ResultExt { - fn assert_if_debugging_ui(self, message: &str); -} - -impl ResultExt for Result { - fn assert_if_debugging_ui(self, #[allow(unused)] message: &str) { - #[cfg(feature = "ui_debug")] - if self.is_err() { - panic!("{}", message); - } - } -} diff --git a/core/embed/rust/src/protobuf/decode.rs b/core/embed/rust/src/protobuf/decode.rs index c2d78c5e7..8566a78d4 100644 --- a/core/embed/rust/src/protobuf/decode.rs +++ b/core/embed/rust/src/protobuf/decode.rs @@ -5,8 +5,7 @@ use core::{ use crate::{ error::Error, - micropython::{buffer::Buffer, gc::Gc, list::List, map::Map, obj::Obj, qstr::Qstr}, - util, + micropython::{buffer::Buffer, gc::Gc, list::List, map::Map, obj::Obj, qstr::Qstr, util}, }; use super::{ diff --git a/core/embed/rust/src/protobuf/encode.rs b/core/embed/rust/src/protobuf/encode.rs index a1330802e..90690ec3b 100644 --- a/core/embed/rust/src/protobuf/encode.rs +++ b/core/embed/rust/src/protobuf/encode.rs @@ -9,8 +9,8 @@ use crate::{ list::List, obj::Obj, qstr::Qstr, + util, }, - util, }; use super::{ diff --git a/core/embed/rust/src/protobuf/obj.rs b/core/embed/rust/src/protobuf/obj.rs index d3451011b..815c6be0e 100644 --- a/core/embed/rust/src/protobuf/obj.rs +++ b/core/embed/rust/src/protobuf/obj.rs @@ -10,8 +10,8 @@ use crate::{ obj::{Obj, ObjBase}, qstr::Qstr, typ::Type, + util, }, - util, }; use super::{ diff --git a/core/embed/rust/src/time.rs b/core/embed/rust/src/time.rs index 25f5e880a..726d7a7e1 100644 --- a/core/embed/rust/src/time.rs +++ b/core/embed/rust/src/time.rs @@ -3,7 +3,7 @@ use core::{ ops::{Div, Mul}, }; -use crate::micropython::time; +use crate::trezorhal::time; const MILLIS_PER_SEC: u32 = 1000; @@ -83,7 +83,6 @@ pub struct Instant { impl Instant { pub fn now() -> Self { - // TODO: We should move this to `micropython::time`. Self { millis: time::ticks_ms(), } diff --git a/core/embed/rust/src/trezorhal/mod.rs b/core/embed/rust/src/trezorhal/mod.rs index 72c20fa29..b5571e8c4 100644 --- a/core/embed/rust/src/trezorhal/mod.rs +++ b/core/embed/rust/src/trezorhal/mod.rs @@ -5,3 +5,8 @@ pub mod display; mod ffi; pub mod random; pub mod slip39; + +#[cfg(not(feature = "micropython"))] +pub mod time; +#[cfg(feature = "micropython")] +pub use crate::micropython::time; diff --git a/core/embed/rust/src/trezorhal/time.rs b/core/embed/rust/src/trezorhal/time.rs new file mode 100644 index 000000000..30c9454cb --- /dev/null +++ b/core/embed/rust/src/trezorhal/time.rs @@ -0,0 +1,13 @@ +use crate::time::Duration; + +use super::ffi; + +pub fn ticks_ms() -> u32 { + unsafe { ffi::hal_ticks_ms() as _ } +} + +pub fn sleep(delay: Duration) { + unsafe { + ffi::hal_delay(delay.to_millis() as _); + } +} diff --git a/core/embed/rust/src/ui/display.rs b/core/embed/rust/src/ui/display.rs index 9a12c3999..966c58f87 100644 --- a/core/embed/rust/src/ui/display.rs +++ b/core/embed/rust/src/ui/display.rs @@ -1,5 +1,8 @@ use super::constant; -use crate::{micropython::time, time::Duration, trezorhal::display}; +use crate::{ + time::Duration, + trezorhal::{display, time}, +}; use super::geometry::{Offset, Point, Rect}; diff --git a/core/embed/rust/src/ui/layout/obj.rs b/core/embed/rust/src/ui/layout/obj.rs index 63619cae1..8054c073a 100644 --- a/core/embed/rust/src/ui/layout/obj.rs +++ b/core/embed/rust/src/ui/layout/obj.rs @@ -11,6 +11,7 @@ use crate::{ obj::{Obj, ObjBase}, qstr::Qstr, typ::Type, + util, }, time::Duration, ui::{ @@ -18,7 +19,6 @@ use crate::{ constant, geometry::Rect, }, - util, }; #[cfg(feature = "buttons")] diff --git a/core/embed/rust/src/ui/mod.rs b/core/embed/rust/src/ui/mod.rs index 1ca837741..12489ee51 100644 --- a/core/embed/rust/src/ui/mod.rs +++ b/core/embed/rust/src/ui/mod.rs @@ -7,6 +7,9 @@ pub mod constant; pub mod display; pub mod event; pub mod geometry; +mod util; + +#[cfg(feature = "micropython")] pub mod layout; #[cfg(feature = "model_t1")] diff --git a/core/embed/rust/src/ui/model_t1/layout.rs b/core/embed/rust/src/ui/model_t1/layout.rs index e4758bb08..8fc468343 100644 --- a/core/embed/rust/src/ui/model_t1/layout.rs +++ b/core/embed/rust/src/ui/model_t1/layout.rs @@ -2,7 +2,7 @@ use core::convert::TryInto; use crate::{ error::Error, - micropython::{buffer::StrBuffer, map::Map, module::Module, obj::Obj, qstr::Qstr}, + micropython::{buffer::StrBuffer, map::Map, module::Module, obj::Obj, qstr::Qstr, util}, ui::{ component::{ base::Component, @@ -15,7 +15,6 @@ use crate::{ result::{CANCELLED, CONFIRMED}, }, }, - util, }; use super::{ diff --git a/core/embed/rust/src/ui/model_t1/mod.rs b/core/embed/rust/src/ui/model_t1/mod.rs index c4e099002..c6eb39480 100644 --- a/core/embed/rust/src/ui/model_t1/mod.rs +++ b/core/embed/rust/src/ui/model_t1/mod.rs @@ -1,4 +1,6 @@ pub mod component; pub mod constant; -pub mod layout; pub mod theme; + +#[cfg(feature = "micropython")] +pub mod layout; diff --git a/core/embed/rust/src/ui/model_tr/layout.rs b/core/embed/rust/src/ui/model_tr/layout.rs index 757d34d00..483046ded 100644 --- a/core/embed/rust/src/ui/model_tr/layout.rs +++ b/core/embed/rust/src/ui/model_tr/layout.rs @@ -2,7 +2,7 @@ use core::convert::TryInto; use crate::{ error::Error, - micropython::{buffer::StrBuffer, map::Map, module::Module, obj::Obj, qstr::Qstr}, + micropython::{buffer::StrBuffer, map::Map, module::Module, obj::Obj, qstr::Qstr, util}, ui::{ component::{ base::Component, @@ -15,7 +15,6 @@ use crate::{ result::{CANCELLED, CONFIRMED}, }, }, - util, }; use super::{ diff --git a/core/embed/rust/src/ui/model_tr/mod.rs b/core/embed/rust/src/ui/model_tr/mod.rs index c4e099002..c6eb39480 100644 --- a/core/embed/rust/src/ui/model_tr/mod.rs +++ b/core/embed/rust/src/ui/model_tr/mod.rs @@ -1,4 +1,6 @@ pub mod component; pub mod constant; -pub mod layout; pub mod theme; + +#[cfg(feature = "micropython")] +pub mod layout; diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs index f23eeb333..616b1c0d5 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/common.rs @@ -6,8 +6,8 @@ use crate::{ component::{Event, EventCtx, TimerToken}, display::{self, Color, Font}, geometry::{Offset, Point, Rect}, + util::ResultExt, }, - util::ResultExt, }; pub const HEADER_HEIGHT: i32 = 25; diff --git a/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs b/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs index 548d4d0a4..71531ee8e 100644 --- a/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs +++ b/core/embed/rust/src/ui/model_tt/component/keyboard/slip39.rs @@ -18,8 +18,8 @@ use crate::{ }, theme, }, + util::ResultExt, }, - util::ResultExt, }; const MAX_LENGTH: usize = 8; diff --git a/core/embed/rust/src/ui/model_tt/layout.rs b/core/embed/rust/src/ui/model_tt/layout.rs index d8759e739..3cbf99046 100644 --- a/core/embed/rust/src/ui/model_tt/layout.rs +++ b/core/embed/rust/src/ui/model_tt/layout.rs @@ -2,7 +2,7 @@ use core::{convert::TryInto, ops::Deref}; use crate::{ error::Error, - micropython::{buffer::StrBuffer, map::Map, module::Module, obj::Obj, qstr::Qstr}, + micropython::{buffer::StrBuffer, map::Map, module::Module, obj::Obj, qstr::Qstr, util}, ui::{ component::{ base::ComponentExt, @@ -15,7 +15,6 @@ use crate::{ result::{CANCELLED, CONFIRMED, INFO}, }, }, - util, }; use super::{ diff --git a/core/embed/rust/src/ui/model_tt/mod.rs b/core/embed/rust/src/ui/model_tt/mod.rs index 43d96a0f7..8d508e39c 100644 --- a/core/embed/rust/src/ui/model_tt/mod.rs +++ b/core/embed/rust/src/ui/model_tt/mod.rs @@ -1,5 +1,7 @@ pub mod component; pub mod constant; pub mod event; -pub mod layout; pub mod theme; + +#[cfg(feature = "micropython")] +pub mod layout; diff --git a/core/embed/rust/src/ui/util.rs b/core/embed/rust/src/ui/util.rs new file mode 100644 index 000000000..f07b22881 --- /dev/null +++ b/core/embed/rust/src/ui/util.rs @@ -0,0 +1,12 @@ +pub trait ResultExt { + fn assert_if_debugging_ui(self, message: &str); +} + +impl ResultExt for Result { + fn assert_if_debugging_ui(self, #[allow(unused)] message: &str) { + #[cfg(feature = "ui_debug")] + if self.is_err() { + panic!("{}", message); + } + } +} diff --git a/core/embed/rust/trezorhal.h b/core/embed/rust/trezorhal.h index 18cc77fba..a9983404f 100644 --- a/core/embed/rust/trezorhal.h +++ b/core/embed/rust/trezorhal.h @@ -1,3 +1,4 @@ +#include "common.h" #include "display.h" #include "secbool.h" #include "storage.h" diff --git a/core/embed/trezorhal/common.c b/core/embed/trezorhal/common.c index 9b4a797de..f0396a7be 100644 --- a/core/embed/trezorhal/common.c +++ b/core/embed/trezorhal/common.c @@ -134,6 +134,7 @@ void __assert_func(const char *file, int line, const char *func, #endif void hal_delay(uint32_t ms) { HAL_Delay(ms); } +uint32_t hal_ticks_ms() { return HAL_GetTick(); } // reference RM0090 section 35.12.1 Figure 413 #define USB_OTG_HS_DATA_FIFO_RAM (USB_OTG_HS_PERIPH_BASE + 0x20000U) diff --git a/core/embed/trezorhal/common.h b/core/embed/trezorhal/common.h index 57ab303c6..1bee151f9 100644 --- a/core/embed/trezorhal/common.h +++ b/core/embed/trezorhal/common.h @@ -66,6 +66,7 @@ error_shutdown(const char *line1, const char *line2, const char *line3, : __fatal_error(#expr, msg, __FILE__, __LINE__, __func__)) void hal_delay(uint32_t ms); +uint32_t hal_ticks_ms(); void clear_otg_hs_memory(void); diff --git a/core/embed/unix/common.c b/core/embed/unix/common.c index 8549b4bab..57d9e4944 100644 --- a/core/embed/unix/common.c +++ b/core/embed/unix/common.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "common.h" @@ -116,6 +117,12 @@ error_shutdown(const char *line1, const char *line2, const char *line3, void hal_delay(uint32_t ms) { usleep(1000 * ms); } +uint32_t hal_ticks_ms() { + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + static int SDLCALL emulator_event_filter(void *userdata, SDL_Event *event) { switch (event->type) { case SDL_QUIT: