From 2aa427a6e344af286b9166ea005e240e6e41606c Mon Sep 17 00:00:00 2001 From: matejcik Date: Wed, 8 Jun 2022 10:31:23 +0200 Subject: [PATCH] feat(core/rust): make Rust buildable without Micropython Features `micropython` and `protobuf` are defined. Protobuf implies micropython because our protobuf impl is pretty much _for_ micropython. The respective subdirs are included only if the matching feature is defined. util.rs is moved to micropython because it mostly concerns micropython interop ResultExt, useful only for ui_debug, is moved to ui::util. A new module `trezorhal::time` is provided. It mirrors functionality of `micropython::time` via stmlib functions. The intended use is to always use functions from `trezorhal::time`. The right micropython variants are used when micropython is available, otherwise the pure stmlib versions are called. ui::*::layout is conditional for micropython feature, because it only concerns micropython layouts. If we want to reuse layouts defined there, we will need to export them to not depend on Objs and Qstrs etc. --- core/Makefile | 2 +- core/SConscript.firmware | 18 +++++++----------- core/SConscript.unix | 17 ++++++----------- core/embed/rust/Cargo.toml | 4 +++- core/embed/rust/build.rs | 9 ++++++++- core/embed/rust/src/error.rs | 18 +++++++++++++++++- core/embed/rust/src/lib.rs | 3 ++- core/embed/rust/src/micropython/mod.rs | 1 + core/embed/rust/src/micropython/obj.rs | 11 +---------- core/embed/rust/src/{ => micropython}/util.rs | 13 ------------- core/embed/rust/src/protobuf/decode.rs | 3 +-- core/embed/rust/src/protobuf/encode.rs | 2 +- core/embed/rust/src/protobuf/obj.rs | 2 +- core/embed/rust/src/time.rs | 3 +-- core/embed/rust/src/trezorhal/mod.rs | 5 +++++ core/embed/rust/src/trezorhal/time.rs | 13 +++++++++++++ core/embed/rust/src/ui/display.rs | 5 ++++- core/embed/rust/src/ui/layout/obj.rs | 2 +- core/embed/rust/src/ui/mod.rs | 3 +++ core/embed/rust/src/ui/model_t1/layout.rs | 3 +-- core/embed/rust/src/ui/model_t1/mod.rs | 4 +++- core/embed/rust/src/ui/model_tr/layout.rs | 3 +-- core/embed/rust/src/ui/model_tr/mod.rs | 4 +++- .../ui/model_tt/component/keyboard/common.rs | 2 +- .../ui/model_tt/component/keyboard/slip39.rs | 2 +- core/embed/rust/src/ui/model_tt/layout.rs | 3 +-- core/embed/rust/src/ui/model_tt/mod.rs | 4 +++- core/embed/rust/src/ui/util.rs | 12 ++++++++++++ core/embed/rust/trezorhal.h | 1 + core/embed/trezorhal/common.c | 1 + core/embed/trezorhal/common.h | 1 + core/embed/unix/common.c | 7 +++++++ 32 files changed, 112 insertions(+), 69 deletions(-) rename core/embed/rust/src/{ => micropython}/util.rs (89%) create mode 100644 core/embed/rust/src/trezorhal/time.rs create mode 100644 core/embed/rust/src/ui/util.rs 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: