diff --git a/extmod/foundation-rust/include/foundation.h b/extmod/foundation-rust/include/foundation.h index 008690258..94a570749 100644 --- a/extmod/foundation-rust/include/foundation.h +++ b/extmod/foundation-rust/include/foundation.h @@ -20,6 +20,10 @@ #define VERSION_LEN 8 +#define FIRMWARE_MAGIC_MONO 1346458451 + +#define FIRMWARE_MAGIC_COLOR 1397965136 + /** * Maximum size of an encoded Uniform Resource. * @@ -183,6 +187,7 @@ typedef enum { typedef struct { char version[VERSION_LEN]; + uint32_t magic; bool signed_by_user; } FirmwareResult_HeaderOk_Body; diff --git a/extmod/foundation-rust/src/firmware.rs b/extmod/foundation-rust/src/firmware.rs index b54c34954..040eda734 100644 --- a/extmod/foundation-rust/src/firmware.rs +++ b/extmod/foundation-rust/src/firmware.rs @@ -9,6 +9,15 @@ use secp256k1::PublicKey; pub const VERSION_LEN: usize = 8; +// These are defined here as cbindgen does not support generating C +// definitions for items outside of this crate. +// +// Note: keep in sync. with: +// +// - ports/stm32/boards/Passport/include/fwheader.h +pub const FIRMWARE_MAGIC_MONO: u32 = 0x50415353; +pub const FIRMWARE_MAGIC_COLOR: u32 = 0x53534150; + /// The result of the firmware update verification. /// cbindgen:rename-all=ScreamingSnakeCase /// cbindgen:prefix-with-name @@ -18,6 +27,7 @@ pub enum FirmwareResult { /// The firmware validation succeed. HeaderOk { version: [c_char; VERSION_LEN], + magic: u32, signed_by_user: bool, }, /// The header format is not valid. @@ -143,6 +153,7 @@ pub extern "C" fn verify_update_header( *result = FirmwareResult::HeaderOk { version, + magic: header.information.magic, signed_by_user: header.is_signed_by_user(), }; } @@ -208,5 +219,13 @@ mod tests { #[test] fn sanity_test() { assert_eq!(VERSION_LEN, foundation_firmware::VERSION_LEN); + assert_eq!( + FIRMWARE_MAGIC_MONO, + foundation_firmware::Information::MAGIC_MONO + ); + assert_eq!( + FIRMWARE_MAGIC_COLOR, + foundation_firmware::Information::MAGIC_COLOR + ); } } diff --git a/ports/stm32/boards/Passport/images/color/ICON_CASA.c b/ports/stm32/boards/Passport/images/color/ICON_CASA.c index c7c46dcd3..a29ffe783 100644 --- a/ports/stm32/boards/Passport/images/color/ICON_CASA.c +++ b/ports/stm32/boards/Passport/images/color/ICON_CASA.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-FileCopyrightText: © 2024 Foundation Devices, Inc. // SPDX-License-Identifier: GPL-3.0-or-later // @@ -14,32 +14,33 @@ #ifndef LV_ATTRIBUTE_IMG_ICON_CASA #define LV_ATTRIBUTE_IMG_ICON_CASA #endif + const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_ICON_CASA uint8_t ICON_CASA_map[] = { - 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xfe, 0xfe, 0xfe, 0x36, /*Color of index 1*/ - 0xfe, 0xfe, 0xfe, 0xbe, /*Color of index 2*/ - 0xfe, 0xfe, 0xfe, 0xfd, /*Color of index 3*/ + 0x00, 0x00, 0x00, 0x02, /*Color of index 0*/ + 0x00, 0x00, 0x00, 0x54, /*Color of index 1*/ + 0x00, 0x00, 0x00, 0xa0, /*Color of index 2*/ + 0x00, 0x00, 0x00, 0xf2, /*Color of index 3*/ - 0xbf, 0xff, 0xff, 0xff, 0xfe, - 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xeb, 0xff, - 0xff, 0xff, 0xf9, 0x41, 0x6f, - 0xff, 0xff, 0xd0, 0x00, 0x07, - 0xff, 0xff, 0x41, 0x69, 0x41, - 0xff, 0xfe, 0x06, 0xff, 0x90, - 0xff, 0xfd, 0x1b, 0xff, 0xe5, - 0xff, 0xf9, 0x1f, 0xff, 0xff, - 0xff, 0xfc, 0x1f, 0xff, 0xff, - 0xff, 0xf8, 0x1f, 0xff, 0xff, - 0xff, 0xfd, 0x1f, 0xff, 0xff, - 0xff, 0xfd, 0x1b, 0xff, 0xe5, - 0xff, 0xfe, 0x06, 0xff, 0x90, - 0xff, 0xff, 0x41, 0x69, 0x41, - 0xff, 0xff, 0xd0, 0x00, 0x07, - 0xff, 0xff, 0xf9, 0x41, 0x6f, - 0xff, 0xff, 0xff, 0xaa, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, - 0xbf, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x38, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x40, 0x00, + 0x00, 0x0f, 0xd7, 0xe0, 0x00, + 0x00, 0x7f, 0x00, 0xfd, 0x00, + 0x02, 0xf4, 0x00, 0x1f, 0x80, + 0x0b, 0xd0, 0xbe, 0x03, 0xe0, + 0x3f, 0x03, 0xff, 0xd0, 0xfc, + 0x2c, 0x0f, 0x41, 0xf8, 0x28, + 0x2d, 0x1e, 0x00, 0x3e, 0x04, + 0x1e, 0x1d, 0x00, 0x0b, 0xc0, + 0x0f, 0x1e, 0x00, 0x42, 0xf0, + 0x0b, 0x4f, 0x41, 0xe1, 0xe0, + 0x07, 0x83, 0xff, 0xd2, 0xd0, + 0x03, 0xc0, 0xae, 0x03, 0xc0, + 0x02, 0xd0, 0x00, 0x07, 0x80, + 0x01, 0xe9, 0x55, 0x5b, 0x40, + 0x00, 0xff, 0xff, 0xff, 0x00, + 0x00, 0x15, 0x55, 0x54, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, }; const lv_img_dsc_t ICON_CASA = { @@ -48,6 +49,6 @@ const lv_img_dsc_t ICON_CASA = { .header.reserved = 0, .header.w = 20, .header.h = 20, - .data_size = 117, + .data_size = 116, .data = ICON_CASA_map, }; diff --git a/ports/stm32/boards/Passport/images/color/ICON_CASA__CF_INDEXED_2_BIT.png b/ports/stm32/boards/Passport/images/color/ICON_CASA__CF_INDEXED_2_BIT.png index 824dd754b..f86b841ff 100644 Binary files a/ports/stm32/boards/Passport/images/color/ICON_CASA__CF_INDEXED_2_BIT.png and b/ports/stm32/boards/Passport/images/color/ICON_CASA__CF_INDEXED_2_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/color/ICON_HOURGLASS.c b/ports/stm32/boards/Passport/images/color/ICON_HOURGLASS.c index c5d1722b5..07165ee64 100644 --- a/ports/stm32/boards/Passport/images/color/ICON_HOURGLASS.c +++ b/ports/stm32/boards/Passport/images/color/ICON_HOURGLASS.c @@ -15,7 +15,6 @@ #ifndef LV_ATTRIBUTE_IMG_ICON_HOURGLASS #define LV_ATTRIBUTE_IMG_ICON_HOURGLASS #endif - const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST LV_ATTRIBUTE_IMG_ICON_HOURGLASS uint8_t ICON_HOURGLASS_map[] = { 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ 0xfe, 0xfe, 0xfe, 0xff, /*Color of index 1*/ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CASA.c b/ports/stm32/boards/Passport/images/mono/ICON_CASA.c index 0d9cf3cc3..8b37807b7 100644 --- a/ports/stm32/boards/Passport/images/mono/ICON_CASA.c +++ b/ports/stm32/boards/Passport/images/mono/ICON_CASA.c @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: © 2022 Foundation Devices, Inc. +// SPDX-FileCopyrightText: © 2024 Foundation Devices, Inc. // SPDX-License-Identifier: GPL-3.0-or-later // @@ -16,38 +16,36 @@ #endif const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_ICON_CASA uint8_t ICON_CASA_map[] = { 0x00, 0x00, 0x00, 0x00, /*Color of index 0*/ - 0xff, 0xff, 0xff, 0xff, /*Color of index 1*/ - 0x00, 0x00, 0x00, 0x00, /*Color of index 2*/ - 0x00, 0x00, 0x00, 0x00, /*Color of index 3*/ + 0x00, 0x00, 0x00, 0xdb, /*Color of index 1*/ - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x15, 0x55, 0x55, 0x55, 0x54, - 0x15, 0x55, 0x55, 0x55, 0x54, - 0x15, 0x55, 0x55, 0x55, 0x54, - 0x15, 0x55, 0x54, 0x00, 0x14, - 0x15, 0x55, 0x50, 0x00, 0x04, - 0x15, 0x55, 0x40, 0x55, 0x00, - 0x15, 0x55, 0x01, 0x55, 0x40, - 0x15, 0x55, 0x05, 0x55, 0x54, - 0x15, 0x55, 0x05, 0x55, 0x54, - 0x15, 0x55, 0x05, 0x55, 0x54, - 0x15, 0x55, 0x05, 0x55, 0x54, - 0x15, 0x55, 0x01, 0x55, 0x40, - 0x15, 0x55, 0x40, 0x55, 0x00, - 0x15, 0x55, 0x50, 0x00, 0x04, - 0x15, 0x55, 0x54, 0x00, 0x14, - 0x15, 0x55, 0x55, 0x55, 0x54, - 0x15, 0x55, 0x55, 0x55, 0x54, - 0x15, 0x55, 0x55, 0x55, 0x54, - 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, + 0x00, 0x60, 0x00, + 0x00, 0xf0, 0x00, + 0x03, 0xdc, 0x00, + 0x07, 0x0e, 0x00, + 0x0e, 0x07, 0x80, + 0x38, 0xf1, 0xc0, + 0x71, 0xfc, 0xe0, + 0x63, 0x8e, 0x60, + 0x63, 0x07, 0x00, + 0x36, 0x03, 0x80, + 0x33, 0x00, 0xc0, + 0x33, 0x1d, 0xc0, + 0x19, 0xf8, 0x80, + 0x18, 0xf1, 0x80, + 0x18, 0x01, 0x80, + 0x0e, 0xab, 0x00, + 0x0f, 0xff, 0x00, + 0x01, 0x54, 0x00, + 0x00, 0x00, 0x00, }; const lv_img_dsc_t ICON_CASA = { - .header.cf = LV_IMG_CF_INDEXED_2BIT, + .header.cf = LV_IMG_CF_INDEXED_1BIT, .header.always_zero = 0, .header.reserved = 0, .header.w = 20, .header.h = 20, - .data_size = 117, + .data_size = 68, .data = ICON_CASA_map, }; diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CASA__CF_INDEXED_1_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CASA__CF_INDEXED_1_BIT.png new file mode 100644 index 000000000..f86b841ff Binary files /dev/null and b/ports/stm32/boards/Passport/images/mono/ICON_CASA__CF_INDEXED_1_BIT.png differ diff --git a/ports/stm32/boards/Passport/images/mono/ICON_CASA__CF_INDEXED_2_BIT.png b/ports/stm32/boards/Passport/images/mono/ICON_CASA__CF_INDEXED_2_BIT.png deleted file mode 100644 index 1dc2d3247..000000000 Binary files a/ports/stm32/boards/Passport/images/mono/ICON_CASA__CF_INDEXED_2_BIT.png and /dev/null differ diff --git a/ports/stm32/boards/Passport/manifest.py b/ports/stm32/boards/Passport/manifest.py index d0f41a531..e43a1f6eb 100644 --- a/ports/stm32/boards/Passport/manifest.py +++ b/ports/stm32/boards/Passport/manifest.py @@ -346,6 +346,7 @@ 'wallets/bitcoin_core.py', 'wallets/bluewallet.py', 'wallets/btcpay.py', + 'wallets/bull.py', 'wallets/caravan.py', 'wallets/casa.py', 'wallets/coinbits.py', diff --git a/ports/stm32/boards/Passport/modpassport.c b/ports/stm32/boards/Passport/modpassport.c index 414f0e41f..0ee6ec126 100644 --- a/ports/stm32/boards/Passport/modpassport.c +++ b/ports/stm32/boards/Passport/modpassport.c @@ -19,6 +19,12 @@ #include "se-config.h" #include "se.h" +#if defined(SCREEN_MODE_MONO) +#define FIRMWARE_MAGIC FIRMWARE_MAGIC_MONO +#elif defined(SCREEN_MODE_COLOR) +#define FIRMWARE_MAGIC FIRMWARE_MAGIC_COLOR +#endif + /// package: passport STATIC MP_DEFINE_EXCEPTION(InvalidFirmwareUpdate, Exception); @@ -86,9 +92,13 @@ STATIC mp_obj_t mod_passport_verify_update_header(mp_obj_t header) { header_info.len, firmware_timestamp, &result); - switch (result.tag) { case FIRMWARE_RESULT_HEADER_OK: + if (result.HEADER_OK.magic != FIRMWARE_MAGIC) { + mp_raise_msg(&mp_type_InvalidFirmwareUpdate, + MP_ERROR_TEXT("The firmware is not for this device model.")); + } + tuple[0] = mp_obj_new_str_copy(&mp_type_str, (const uint8_t*)result.HEADER_OK.version, strlen((const char*)result.HEADER_OK.version)); @@ -96,14 +106,15 @@ STATIC mp_obj_t mod_passport_verify_update_header(mp_obj_t header) { return mp_obj_new_tuple(2, tuple); case FIRMWARE_RESULT_INVALID_HEADER: mp_raise_msg(&mp_type_InvalidFirmwareUpdate, - MP_ERROR_TEXT("Invalid firmware header")); + MP_ERROR_TEXT("Invalid firmware header.")); + break; case FIRMWARE_RESULT_UNKNOWN_MAGIC: mp_raise_msg(&mp_type_InvalidFirmwareUpdate, - MP_ERROR_TEXT("Unknown firmware magic bytes")); + MP_ERROR_TEXT("Unknown firmware magic bytes.")); break; case FIRMWARE_RESULT_INVALID_TIMESTAMP: mp_raise_msg(&mp_type_InvalidFirmwareUpdate, - MP_ERROR_TEXT("Invalid firmware timestamp")); + MP_ERROR_TEXT("Invalid firmware timestamp.")); break; case FIRMWARE_RESULT_TOO_SMALL: mp_raise_msg_varg(&mp_type_InvalidFirmwareUpdate, diff --git a/ports/stm32/boards/Passport/modules/views/card.py b/ports/stm32/boards/Passport/modules/views/card.py index 9960a84fd..d7824e688 100644 --- a/ports/stm32/boards/Passport/modules/views/card.py +++ b/ports/stm32/boards/Passport/modules/views/card.py @@ -206,6 +206,8 @@ def update(self): self.icon_view = Image(icon, color=self.header_fg_color) with Stylize(self.icon_view) as default: default.align(lv.ALIGN.LEFT_MID) + if self.icon == 'ICON_CASA' and passport.IS_COLOR: + default.pad(top=1) self.header.add_child(self.icon_view) header_title = Label(text=self.title, color=self.header_fg_color, long_mode=lv.label.LONG.SCROLL_CIRCULAR) @@ -220,6 +222,8 @@ def update(self): self.right_icon_view = Image(right_icon, color=self.header_fg_color) with Stylize(self.right_icon_view) as default: default.align(lv.ALIGN.RIGHT_MID) + if self.right_icon == 'ICON_CASA' and passport.IS_COLOR: + default.pad(top=1) self.header.add_child(self.right_icon_view) # Only draw right text if there is no right icon diff --git a/ports/stm32/boards/Passport/modules/views/icon.py b/ports/stm32/boards/Passport/modules/views/icon.py index fbee3bc5d..46f25a8d1 100644 --- a/ports/stm32/boards/Passport/modules/views/icon.py +++ b/ports/stm32/boards/Passport/modules/views/icon.py @@ -10,19 +10,22 @@ class Icon(View): - def __init__(self, icon, color=None, opa=None): + def __init__(self, icon, color=None, opa=None, bottom_pad=0, top_pad=0): from utils import derive_icon super().__init__() self.icon = derive_icon(icon) self.color = color self.opa = opa + self.bottom_pad = bottom_pad + self.top_pad = top_pad with Stylize(self) as default: if self.color is not None: default.img_recolor(self.color) if self.opa is not None: default.opa(self.opa) + default.pad(bottom=self.bottom_pad, top=self.top_pad) def set_icon(self, icon): from utils import derive_icon diff --git a/ports/stm32/boards/Passport/modules/views/menu_item.py b/ports/stm32/boards/Passport/modules/views/menu_item.py index 64e447585..c7a8c8952 100644 --- a/ports/stm32/boards/Passport/modules/views/menu_item.py +++ b/ports/stm32/boards/Passport/modules/views/menu_item.py @@ -11,6 +11,7 @@ from constants import MENU_ITEM_CORNER_RADIUS from views import View from utils import derive_icon +import passport class MenuItem(View): @@ -19,6 +20,7 @@ def __init__(self, icon='', label='', is_toggle=False, value=False, desc=None, c from views import Switch super().__init__(flex_flow=lv.FLEX_FLOW.ROW) + self.icon_name = icon self.icon = derive_icon(icon) self.label = label self.is_toggle = is_toggle @@ -50,7 +52,8 @@ def __init__(self, icon='', label='', is_toggle=False, value=False, desc=None, c focus.img_recolor(FOCUSED_LIST_ITEM_TEXT) # Icon - self.icon_view = Icon(icon=self.icon) + bottom_pad = 1 if self.icon_name == 'ICON_CASA' and passport.IS_COLOR else 0 + self.icon_view = Icon(icon=self.icon, bottom_pad=bottom_pad) self.icon_view.set_size(21, lv.SIZE.CONTENT) self.add_child(self.icon_view) diff --git a/ports/stm32/boards/Passport/modules/wallets/bull.py b/ports/stm32/boards/Passport/modules/wallets/bull.py new file mode 100644 index 000000000..4d19ee112 --- /dev/null +++ b/ports/stm32/boards/Passport/modules/wallets/bull.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: © 2021 Foundation Devices, Inc. +# SPDX-License-Identifier: GPL-3.0-or-later +# +# bull.py - Bull Bitcoin wallet support +# + +from .generic_json_wallet import create_generic_json_wallet +from .multisig_json import create_multisig_json_wallet +from .multisig_import import read_multisig_config_from_qr, read_multisig_config_from_microsd +from data_codecs.qr_type import QRType + +BullBitcoinWallet = { + 'label': 'Bull', + 'sig_types': [ + {'id': 'single-sig', 'label': 'Single-sig', 'addr_type': None, 'create_wallet': create_generic_json_wallet}, + ], + 'export_modes': [ + {'id': 'qr', 'label': 'QR Code', 'qr_type': QRType.UR2}, + ] +} diff --git a/ports/stm32/boards/Passport/modules/wallets/sw_wallets.py b/ports/stm32/boards/Passport/modules/wallets/sw_wallets.py index 943151057..bb6f9b069 100644 --- a/ports/stm32/boards/Passport/modules/wallets/sw_wallets.py +++ b/ports/stm32/boards/Passport/modules/wallets/sw_wallets.py @@ -8,6 +8,7 @@ from .keeper import KeeperWallet from .bluewallet import BlueWallet from .btcpay import BtcPayWallet +from .bull import BullBitcoinWallet from .casa import CasaWallet from .coinbits import CoinbitsWallet # from .caravan import CaravanWallet @@ -32,6 +33,7 @@ KeeperWallet, BlueWallet, BtcPayWallet, + BullBitcoinWallet, # CaravanWallet, CasaWallet, CoinbitsWallet,