1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-03-12 22:26:08 +00:00

fixup! feat(core): add BLE to bootloader

This commit is contained in:
tychovrahe 2025-03-05 14:04:40 +01:00 committed by M1nd3r
parent 4d8db9543f
commit d1caab8f8b
12 changed files with 182 additions and 26 deletions

View File

@ -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

View File

@ -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

View File

@ -25,6 +25,12 @@
#include <io/ble.h>
#include <sys/systick.h>
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 {

View File

@ -24,11 +24,10 @@
#include <io/ble.h>
#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;
}

View File

@ -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;

View File

@ -22,12 +22,62 @@
#include <util/flash_utils.h>
#ifdef USE_BLE
#include <io/ble.h>
#endif
#include <sys/systick.h>
#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;
}

View File

@ -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

View File

@ -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);

View File

@ -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)
}

View File

@ -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)
}

View File

@ -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,

View File

@ -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;
}