diff --git a/core/embed/projects/bootloader/bootui.c b/core/embed/projects/bootloader/bootui.c index 51ac3da056..24c06318c7 100644 --- a/core/embed/projects/bootloader/bootui.c +++ b/core/embed/projects/bootloader/bootui.c @@ -182,3 +182,9 @@ void ui_screen_install_restricted(void) { screen_install_fail(); } void ui_fadein(void) { display_fade(0, BACKLIGHT_NORMAL, 1000); } void ui_fadeout(void) { display_fade(BACKLIGHT_NORMAL, 0, 500); } + +#ifdef USE_BLE +uint32_t ui_screen_confirm_pairing(const char *code) { + return screen_confirm_pairing(code, initial_setup); +} +#endif diff --git a/core/embed/projects/bootloader/bootui.h b/core/embed/projects/bootloader/bootui.h index 8dd4c556d8..ef438cc37e 100644 --- a/core/embed/projects/bootloader/bootui.h +++ b/core/embed/projects/bootloader/bootui.h @@ -95,3 +95,7 @@ void ui_screen_boot_stage_1(bool fading); #ifdef USE_OPTIGA uint32_t ui_screen_unlock_bootloader_confirm(void); #endif + +#ifdef USE_BLE +uint32_t ui_screen_confirm_pairing(const char* code); +#endif diff --git a/core/embed/projects/bootloader/wire/wire_iface_ble.c b/core/embed/projects/bootloader/wire/wire_iface_ble.c index 79a16bfd1f..3c6e66bd8b 100644 --- a/core/embed/projects/bootloader/wire/wire_iface_ble.c +++ b/core/embed/projects/bootloader/wire/wire_iface_ble.c @@ -25,6 +25,12 @@ #include #include +static bool is_connected(void) { + ble_state_t state = {0}; + ble_get_state(&state); + return state.connected; +} + static bool ble_write_(uint8_t* data, size_t size) { if (size != BLE_TX_PACKET_SIZE) { return false; @@ -36,6 +42,9 @@ static bool ble_write_(uint8_t* data, size_t size) { if (ticks_expired(deadline)) { return false; } + if (!is_connected()) { + return false; + } if (ble_can_write()) { break; } @@ -55,6 +64,9 @@ static int ble_read_(uint8_t* buffer, size_t buffer_size) { if (ticks_expired(deadline)) { return false; } + if (!is_connected()) { + return false; + } if (ble_can_read()) { break; } @@ -92,6 +104,11 @@ void ble_iface_init(wire_iface_t* iface) { if (state.peer_count > 0) { ble_command_t cmd = { .cmd_type = BLE_SWITCH_ON, + .data = {.adv_start = + { + .name = "Trezor Bootloader", + .static_mac = false, + }}, }; ble_issue_command(&cmd); } else { diff --git a/core/embed/projects/bootloader/workflow/wf_ble_pairing_request.c b/core/embed/projects/bootloader/workflow/wf_ble_pairing_request.c index b6d214c70b..c57c46b6e4 100644 --- a/core/embed/projects/bootloader/workflow/wf_ble_pairing_request.c +++ b/core/embed/projects/bootloader/workflow/wf_ble_pairing_request.c @@ -24,11 +24,10 @@ #include #include "bootui.h" -#include "rust_ui_bootloader.h" #include "workflow.h" -workflow_result_t workflow_ble_pairing_request(const uint8_t *data) { - ui_result_t result = screen_confirm_pairing(data); +workflow_result_t workflow_ble_pairing_request(const char *code) { + ui_result_t result = ui_screen_confirm_pairing(code); if (result == UI_RESULT_CONFIRM) { ble_command_t cmd = { @@ -42,7 +41,6 @@ workflow_result_t workflow_ble_pairing_request(const uint8_t *data) { ble_issue_command(&cmd); } - screen_connect(false); return WF_OK; } diff --git a/core/embed/projects/bootloader/workflow/wf_host_control.c b/core/embed/projects/bootloader/workflow/wf_host_control.c index 2356f1bbba..f815b7e14b 100644 --- a/core/embed/projects/bootloader/workflow/wf_host_control.c +++ b/core/embed/projects/bootloader/workflow/wf_host_control.c @@ -115,7 +115,8 @@ workflow_result_t workflow_host_control(const vendor_header *const vhdr, if (i == IFACE_BLE_EVENT) { switch (e.event.ble_event.type) { case BLE_PAIRING_REQUEST: - workflow_ble_pairing_request(e.event.ble_event.data); + workflow_ble_pairing_request((char *)e.event.ble_event.data); + redraw_wait_screen(); continue; default: break; diff --git a/core/embed/projects/bootloader/workflow/wf_wipe_device.c b/core/embed/projects/bootloader/workflow/wf_wipe_device.c index 51b483d06e..e1e13cd4b0 100644 --- a/core/embed/projects/bootloader/workflow/wf_wipe_device.c +++ b/core/embed/projects/bootloader/workflow/wf_wipe_device.c @@ -22,12 +22,62 @@ #include +#ifdef USE_BLE +#include +#endif + +#include + #include "bootui.h" #include "protob.h" #include "rust_ui.h" #include "workflow.h" -workflow_result_t workflow_wipe_device(protob_io_t *iface) { +static void send_error_conditionally(protob_io_t* iface, char* msg) { + if (iface != NULL) { + send_msg_failure(iface, FailureType_Failure_ProcessError, + "Could not read BLE status"); + } +} + +#ifdef USE_BLE +static bool wipe_bonds(protob_io_t* iface) { + ble_state_t state = {0}; + ble_get_state(&state); + + if (!state.state_known) { + send_error_conditionally(iface, "Could not read BLE status"); + screen_wipe_fail(); + return false; + } + + ble_command_t ble_command = {0}; + ble_command.cmd_type = BLE_ERASE_BONDS; + if (!ble_issue_command(&ble_command)) { + send_error_conditionally(iface, "Could not issue BLE command"); + screen_wipe_fail(); + return false; + } + + uint32_t deadline = ticks_timeout(100); + + while (true) { + ble_get_state(&state); + if (state.peer_count == 0) { + break; + } + if (ticks_expired(deadline)) { + send_error_conditionally(iface, "Could not erase bonds"); + screen_wipe_fail(); + return false; + } + } + + return true; +} +#endif + +workflow_result_t workflow_wipe_device(protob_io_t* iface) { ui_result_t response = ui_screen_wipe_confirm(); if (UI_RESULT_CONFIRM != response) { if (iface != NULL) { @@ -38,11 +88,14 @@ workflow_result_t workflow_wipe_device(protob_io_t *iface) { ui_screen_wipe(); secbool wipe_result = erase_device(ui_screen_wipe_progress); +#ifdef USE_BLE + if (!wipe_bonds(iface)) { + return WF_ERROR; + } +#endif + if (sectrue != wipe_result) { - if (iface != NULL) { - send_msg_failure(iface, FailureType_Failure_ProcessError, - "Could not erase flash"); - } + send_error_conditionally(iface, "Could not erase flash"); screen_wipe_fail(); return WF_ERROR; } diff --git a/core/embed/projects/bootloader/workflow/workflow.h b/core/embed/projects/bootloader/workflow/workflow.h index d2a130c5f7..36c678fca9 100644 --- a/core/embed/projects/bootloader/workflow/workflow.h +++ b/core/embed/projects/bootloader/workflow/workflow.h @@ -68,5 +68,5 @@ workflow_result_t workflow_auto_update(const vendor_header *const vhdr, const image_header *const hdr); #ifdef USE_BLE -workflow_result_t workflow_ble_pairing_request(const uint8_t *data); +workflow_result_t workflow_ble_pairing_request(const char *code); #endif diff --git a/core/embed/rust/rust_ui_bootloader.h b/core/embed/rust/rust_ui_bootloader.h index 6472e63742..17cbff1252 100644 --- a/core/embed/rust/rust_ui_bootloader.h +++ b/core/embed/rust/rust_ui_bootloader.h @@ -28,4 +28,4 @@ void screen_boot(bool warning, const char* vendor_str, size_t vendor_str_len, uint32_t version, const void* vendor_img, size_t vendor_img_len, int wait); -uint32_t screen_confirm_pairing(const uint8_t* code); +uint32_t screen_confirm_pairing(const char* code, bool initial_setup); diff --git a/core/embed/rust/src/ui/api/bootloader_c.rs b/core/embed/rust/src/ui/api/bootloader_c.rs index 2724c53f70..0dcf61a100 100644 --- a/core/embed/rust/src/ui/api/bootloader_c.rs +++ b/core/embed/rust/src/ui/api/bootloader_c.rs @@ -146,8 +146,8 @@ extern "C" fn screen_wipe_fail() { } #[no_mangle] -extern "C" fn screen_confirm_pairing(code: *const cty::c_char) -> u32 { +extern "C" fn screen_confirm_pairing(code: *const cty::c_char, initial_setup: bool) -> u32 { let code = unwrap!(unsafe { from_c_array(code, 6) }); - ModelUI::screen_confirm_pairing(code) + ModelUI::screen_confirm_pairing(code, initial_setup) } diff --git a/core/embed/rust/src/ui/layout_bolt/bootloader/mod.rs b/core/embed/rust/src/ui/layout_bolt/bootloader/mod.rs index 14abccaa7f..92324ab0af 100644 --- a/core/embed/rust/src/ui/layout_bolt/bootloader/mod.rs +++ b/core/embed/rust/src/ui/layout_bolt/bootloader/mod.rs @@ -41,7 +41,7 @@ use crate::ui::{ use ufmt::uwrite; -use super::theme::bootloader::BLD_WARN_COLOR; +use super::theme::bootloader::{button_confirm_initial, button_initial, BLD_WARN_COLOR}; use intro::Intro; use menu::Menu; @@ -441,15 +441,25 @@ impl BootloaderUI for UIBolt { } #[cfg(feature = "ble")] - fn screen_confirm_pairing(code: &str) -> u32 { + fn screen_confirm_pairing(code: &str, initial_setup: bool) -> u32 { + let bg = if initial_setup { WELCOME_COLOR } else { BLD_BG }; let title = Label::centered("Pair device".into(), TEXT_NORMAL); let msg = Label::centered(code.into(), TEXT_NORMAL); - let right = Button::with_text("CONFIRM".into()).styled(button_confirm()); - let left = Button::with_text("REJECT".into()).styled(button_bld()); + let (right, left) = if initial_setup { + ( + Button::with_text("CONFIRM".into()).styled(button_confirm_initial()), + Button::with_text("REJECT".into()).styled(button_initial()), + ) + } else { + ( + Button::with_text("CONFIRM".into()).styled(button_confirm()), + Button::with_text("REJECT".into()).styled(button_bld()), + ) + }; - let mut frame = Confirm::new(BLD_BG, left, right, ConfirmTitle::Text(title), msg); + let mut frame = Confirm::new(bg, left, right, ConfirmTitle::Text(title), msg); run(&mut frame) } diff --git a/core/embed/rust/src/ui/layout_bolt/theme/bootloader.rs b/core/embed/rust/src/ui/layout_bolt/theme/bootloader.rs index 56c948a132..231719a42e 100644 --- a/core/embed/rust/src/ui/layout_bolt/theme/bootloader.rs +++ b/core/embed/rust/src/ui/layout_bolt/theme/bootloader.rs @@ -1,17 +1,17 @@ +use super::super::{ + component::{ButtonStyle, ButtonStyleSheet, ResultStyle}, + fonts, + theme::{BLACK, FG, GREY_DARK, GREY_LIGHT, WHITE}, +}; use crate::ui::{ component::{text::TextStyle, LineBreaking::BreakWordsNoHyphen}, constant::{HEIGHT, WIDTH}, display::Color, geometry::{Offset, Point, Rect}, + layout_bolt::theme::GREY_MEDIUM, util::include_res, }; -use super::super::{ - component::{ButtonStyle, ButtonStyleSheet, ResultStyle}, - fonts, - theme::{BLACK, FG, GREY_DARK, GREY_LIGHT, WHITE}, -}; - pub const BLD_BG: Color = Color::rgb(0x00, 0x1E, 0xAD); pub const BLD_FG: Color = WHITE; pub const BLD_WIPE_COLOR: Color = Color::rgb(0xE7, 0x0E, 0x0E); @@ -30,6 +30,9 @@ pub const BLD_INSTALL_BTN_COLOR_ACTIVE: Color = Color::rgb(0xCD, 0xD2, 0xEF); pub const BLD_BTN_COLOR: Color = Color::rgb(0x2D, 0x42, 0xBF); pub const BLD_BTN_COLOR_ACTIVE: Color = Color::rgb(0x04, 0x10, 0x58); +pub const BLD_BTN_INITIAL_COLOR: Color = GREY_MEDIUM; +pub const BLD_BTN_INITIAL_ACTIVE: Color = GREY_DARK; + pub const BLD_TITLE_COLOR: Color = WHITE; pub const WELCOME_COLOR: Color = BLACK; @@ -234,6 +237,70 @@ pub fn button_bld() -> ButtonStyleSheet { } } +pub fn button_confirm_initial() -> ButtonStyleSheet { + ButtonStyleSheet { + normal: &ButtonStyle { + font: fonts::FONT_BOLD_UPPER, + text_color: WELCOME_COLOR, + button_color: WHITE, + background_color: WELCOME_COLOR, + border_color: WELCOME_COLOR, + border_radius: RADIUS, + border_width: 0, + }, + active: &ButtonStyle { + font: fonts::FONT_BOLD_UPPER, + text_color: WELCOME_COLOR, + button_color: GREY_LIGHT, + background_color: WELCOME_COLOR, + border_color: WELCOME_COLOR, + border_radius: RADIUS, + border_width: 0, + }, + disabled: &ButtonStyle { + font: fonts::FONT_BOLD_UPPER, + text_color: FG, + button_color: GREY_DARK, + background_color: FG, + border_color: FG, + border_radius: RADIUS, + border_width: 0, + }, + } +} + +pub fn button_initial() -> ButtonStyleSheet { + ButtonStyleSheet { + normal: &ButtonStyle { + font: fonts::FONT_BOLD_UPPER, + text_color: WHITE, + button_color: BLD_BTN_INITIAL_COLOR, + background_color: WELCOME_COLOR, + border_color: WELCOME_COLOR, + border_radius: 4, + border_width: 0, + }, + active: &ButtonStyle { + font: fonts::FONT_BOLD_UPPER, + text_color: WHITE, + button_color: BLD_BTN_INITIAL_ACTIVE, + background_color: WELCOME_COLOR, + border_color: WELCOME_COLOR, + border_radius: 4, + border_width: 0, + }, + disabled: &ButtonStyle { + font: fonts::FONT_BOLD_UPPER, + text_color: GREY_LIGHT, + button_color: BLD_BTN_COLOR, + background_color: WELCOME_COLOR, + border_color: WELCOME_COLOR, + border_radius: 4, + border_width: 0, + }, + } +} + pub const fn text_title(bg: Color) -> TextStyle { TextStyle::new( fonts::FONT_BOLD_UPPER, diff --git a/core/embed/rust/src/ui/ui_bootloader.rs b/core/embed/rust/src/ui/ui_bootloader.rs index 031348521c..a07dca89b6 100644 --- a/core/embed/rust/src/ui/ui_bootloader.rs +++ b/core/embed/rust/src/ui/ui_bootloader.rs @@ -50,5 +50,5 @@ pub trait BootloaderUI { ); #[cfg(feature = "ble")] - fn screen_confirm_pairing(code: &str) -> u32; + fn screen_confirm_pairing(code: &str, initial_setup: bool) -> u32; }