diff --git a/core/embed/rust/build.rs b/core/embed/rust/build.rs index 03bc3fa59..97dec1db9 100644 --- a/core/embed/rust/build.rs +++ b/core/embed/rust/build.rs @@ -61,6 +61,7 @@ fn prepare_bindings() -> bindgen::Builder { "-I../../../crypto", "-I../../../storage", "-I../../vendor/micropython", + "-I../../vendor/micropython/lib/uzlib", "-I../extmod/modtrezorui", // for display.h format!("-DTREZOR_MODEL_{}", model()).as_str(), ]); @@ -271,6 +272,9 @@ fn generate_trezorhal_bindings() { .allowlist_function("display_get_glyph") .allowlist_var("DISPLAY_CMD_ADDRESS") .allowlist_var("DISPLAY_DATA_ADDRESS") + // uzlib + .allowlist_function("uzlib_uncompress_init") + .allowlist_function("uzlib_uncompress") // bip39 .allowlist_function("mnemonic_word_completion_mask") .allowlist_var("BIP39_WORDLIST_ENGLISH") diff --git a/core/embed/rust/src/trezorhal/ffi.rs b/core/embed/rust/src/trezorhal/ffi.rs index bc2e925a5..67269896b 100644 --- a/core/embed/rust/src/trezorhal/ffi.rs +++ b/core/embed/rust/src/trezorhal/ffi.rs @@ -1,5 +1,6 @@ #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] +#![allow(non_snake_case)] #![allow(dead_code)] include!(concat!(env!("OUT_DIR"), "/trezorhal.rs")); diff --git a/core/embed/rust/src/trezorhal/mod.rs b/core/embed/rust/src/trezorhal/mod.rs index bfbdabbd5..60bc142f2 100644 --- a/core/embed/rust/src/trezorhal/mod.rs +++ b/core/embed/rust/src/trezorhal/mod.rs @@ -8,6 +8,7 @@ pub mod random; #[cfg(feature = "model_tr")] pub mod rgb_led; pub mod slip39; +pub mod uzlib; #[cfg(not(feature = "micropython"))] pub mod time; diff --git a/core/embed/rust/src/trezorhal/uzlib.rs b/core/embed/rust/src/trezorhal/uzlib.rs new file mode 100644 index 000000000..a10b33b5b --- /dev/null +++ b/core/embed/rust/src/trezorhal/uzlib.rs @@ -0,0 +1,58 @@ +use super::ffi; +use core::{marker::PhantomData, mem::MaybeUninit, ptr}; + +pub const UZLIB_WINDOW_SIZE: usize = 1 << 10; +pub use ffi::uzlib_uncomp; + +impl Default for ffi::uzlib_uncomp { + fn default() -> Self { + unsafe { MaybeUninit::::zeroed().assume_init() } + } +} + +pub struct UzlibContext<'a> { + uncomp: ffi::uzlib_uncomp, + src_data: PhantomData<&'a [u8]>, + window: Option<[u8; UZLIB_WINDOW_SIZE]>, +} + +impl<'a> UzlibContext<'a> { + pub fn new(src: &'a [u8], use_window: bool) -> Self { + let window = use_window.then_some([0_u8; UZLIB_WINDOW_SIZE]); + + let mut ctx = Self { + uncomp: uzlib_uncomp::default(), + src_data: Default::default(), + window, + }; + + unsafe { + ctx.uncomp.source = src.as_ptr(); + ctx.uncomp.source_limit = src.as_ptr().add(src.len()); + + if let Some(w) = ctx.window { + ffi::uzlib_uncompress_init(&mut ctx.uncomp, w.as_ptr() as _, w.len() as u32); + } else { + ffi::uzlib_uncompress_init(&mut ctx.uncomp, ptr::null_mut(), 0); + } + } + + ctx + } + + /// returns Ok(true) if DONE + pub fn uncompress(&mut self, dest_buf: &mut [u8]) -> Result { + unsafe { + self.uncomp.dest = dest_buf.as_mut_ptr(); + self.uncomp.dest_limit = self.uncomp.dest.add(dest_buf.len()); + + let res = ffi::uzlib_uncompress(&mut self.uncomp); + + match res { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(()), + } + } + } +} diff --git a/core/embed/rust/trezorhal.h b/core/embed/rust/trezorhal.h index 09dc838f0..949a44632 100644 --- a/core/embed/rust/trezorhal.h +++ b/core/embed/rust/trezorhal.h @@ -7,3 +7,5 @@ #include "bip39.h" #include "rand.h" #include "slip39.h" + +#include "uzlib.h"