From 5bd95048266dcd33a4006540d498a8e07eadc56a Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Sun, 20 Nov 2022 13:32:51 +0100 Subject: [PATCH] fixup! feat(core/rust): homescreen background --- core/embed/rust/src/micropython/gc.rs | 35 +++++++++++++- core/embed/rust/src/storage/mod.rs | 28 ++++++----- .../ui/model_tt/component/homescreen/mod.rs | 47 ++++++++++++++----- 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/core/embed/rust/src/micropython/gc.rs b/core/embed/rust/src/micropython/gc.rs index 466edb3052..ab336f7fc9 100644 --- a/core/embed/rust/src/micropython/gc.rs +++ b/core/embed/rust/src/micropython/gc.rs @@ -1,6 +1,6 @@ use core::{ alloc::Layout, - ops::Deref, + ops::{Deref, DerefMut}, ptr::{self, NonNull}, }; @@ -38,6 +38,33 @@ impl Gc { } } +impl Gc<[T]> { + /// Allocate slice on the heap managed by the MicroPython garbage collector + /// and fill with default values. + pub fn new_slice(len: usize) -> Result { + let layout = Layout::array::(len).unwrap(); + // TODO: Assert that `layout.align()` is the same as the GC alignment. + // SAFETY: + // - Unfortunately we cannot respect `layout.align()` as MicroPython GC does + // not support custom alignment. + // - `ptr` is guaranteed to stay valid as long as it's reachable from the stack + // or the MicroPython heap. + // EXCEPTION: Returns null instead of raising. + unsafe { + let raw = ffi::gc_alloc(layout.size(), 0); + if raw.is_null() { + return Err(Error::AllocationFailed); + } + let typed: *mut T = raw.cast(); + for i in 0..len { + ptr::write(typed.add(i), T::default()); + } + let array_ptr = ptr::slice_from_raw_parts_mut(typed, len); + Ok(Self::from_raw(array_ptr as _)) + } + } +} + impl Gc { /// Construct a `Gc` from a raw pointer. /// @@ -82,3 +109,9 @@ impl Deref for Gc { unsafe { self.0.as_ref() } } } + +impl DerefMut for Gc { + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { self.0.as_mut() } + } +} diff --git a/core/embed/rust/src/storage/mod.rs b/core/embed/rust/src/storage/mod.rs index 1b37ab669d..29d4777ff6 100644 --- a/core/embed/rust/src/storage/mod.rs +++ b/core/embed/rust/src/storage/mod.rs @@ -1,8 +1,6 @@ -use crate::{ - micropython::ffi, - trezorhal::storage::{get, get_length}, -}; -use core::slice; +use crate::trezorhal::storage::{get, get_length}; + +pub const HOMESCREEN_MAX_SIZE: usize = 16384; const STORAGE_VERSION_01: u8 = 1; const STORAGE_VERSION_02: u8 = 2; @@ -36,20 +34,26 @@ const INITIALIZED: u16 = FLAG_PUBLIC | APP_DEVICE | 0x0013; const SAFETY_CHECK_LEVEL: u16 = APP_DEVICE | 0x0014; const EXPERIMENTAL_FEATURES: u16 = APP_DEVICE | 0x0015; -pub fn get_avatar() -> Result<&'static mut [u8], ()> { +pub fn get_avatar_len() -> Result { + let avatar_len_res = get_length(HOMESCREEN); + if let Ok(len) = avatar_len_res { + Ok(len) + } else { + Err(()) + } +} + +pub fn get_avatar(buffer: &mut [u8]) -> Result { let avatar_len_res = get_length(HOMESCREEN); - return if let Ok(len) = avatar_len_res { - let data_ptr_raw = unsafe { ffi::gc_alloc(len, 0) }; - let buffer = unsafe { slice::from_raw_parts_mut(data_ptr_raw as _, len) }; - + if let Ok(len) = avatar_len_res { if len <= buffer.len() { unwrap!(get(HOMESCREEN, buffer)); - Ok(&mut buffer[..len]) + Ok(len) } else { Err(()) } } else { Err(()) - }; + } } diff --git a/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs b/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs index 5cbff3d281..f8a457ac64 100644 --- a/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs +++ b/core/embed/rust/src/ui/model_tt/component/homescreen/mod.rs @@ -1,7 +1,8 @@ mod render; use crate::{ - storage::get_avatar, + micropython::gc::Gc, + storage::{get_avatar, get_avatar_len}, time::{Duration, Instant}, trezorhal::usb::usb_configured, ui::{ @@ -192,12 +193,22 @@ where let notification = self.get_notification(); - homescreen( - get_image(), - texts, - notification, - self.paint_notification_only, - ); + let res = get_image(); + if let Ok(data) = res { + homescreen( + data.as_ref(), + texts, + notification, + self.paint_notification_only, + ); + } else { + homescreen( + IMAGE_HOMESCREEN, + texts, + notification, + self.paint_notification_only, + ); + } } } @@ -277,16 +288,26 @@ where icon: None }, ],)); - homescreen_blurred(get_image(), texts); + + let res = get_image(); + if let Ok(data) = res { + homescreen_blurred(data.as_ref(), texts); + } else { + homescreen_blurred(IMAGE_HOMESCREEN, texts); + } } } -fn get_image() -> &'static [u8] { - if let Ok(data) = get_avatar() { - data - } else { - IMAGE_HOMESCREEN +fn get_image() -> Result, ()> { + if let Ok(len) = get_avatar_len() { + let result = Gc::<[u8]>::new_slice(len); + if let Ok(mut buffer) = result { + if get_avatar(buffer.as_mut()).is_ok() { + return Ok(buffer); + } + } } + Err(()) } #[cfg(feature = "ui_debug")]