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:
parent
4d8db9543f
commit
d1caab8f8b
@ -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_fadein(void) { display_fade(0, BACKLIGHT_NORMAL, 1000); }
|
||||||
|
|
||||||
void ui_fadeout(void) { display_fade(BACKLIGHT_NORMAL, 0, 500); }
|
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
|
||||||
|
@ -95,3 +95,7 @@ void ui_screen_boot_stage_1(bool fading);
|
|||||||
#ifdef USE_OPTIGA
|
#ifdef USE_OPTIGA
|
||||||
uint32_t ui_screen_unlock_bootloader_confirm(void);
|
uint32_t ui_screen_unlock_bootloader_confirm(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_BLE
|
||||||
|
uint32_t ui_screen_confirm_pairing(const char* code);
|
||||||
|
#endif
|
||||||
|
@ -25,6 +25,12 @@
|
|||||||
#include <io/ble.h>
|
#include <io/ble.h>
|
||||||
#include <sys/systick.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) {
|
static bool ble_write_(uint8_t* data, size_t size) {
|
||||||
if (size != BLE_TX_PACKET_SIZE) {
|
if (size != BLE_TX_PACKET_SIZE) {
|
||||||
return false;
|
return false;
|
||||||
@ -36,6 +42,9 @@ static bool ble_write_(uint8_t* data, size_t size) {
|
|||||||
if (ticks_expired(deadline)) {
|
if (ticks_expired(deadline)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!is_connected()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (ble_can_write()) {
|
if (ble_can_write()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -55,6 +64,9 @@ static int ble_read_(uint8_t* buffer, size_t buffer_size) {
|
|||||||
if (ticks_expired(deadline)) {
|
if (ticks_expired(deadline)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!is_connected()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (ble_can_read()) {
|
if (ble_can_read()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -92,6 +104,11 @@ void ble_iface_init(wire_iface_t* iface) {
|
|||||||
if (state.peer_count > 0) {
|
if (state.peer_count > 0) {
|
||||||
ble_command_t cmd = {
|
ble_command_t cmd = {
|
||||||
.cmd_type = BLE_SWITCH_ON,
|
.cmd_type = BLE_SWITCH_ON,
|
||||||
|
.data = {.adv_start =
|
||||||
|
{
|
||||||
|
.name = "Trezor Bootloader",
|
||||||
|
.static_mac = false,
|
||||||
|
}},
|
||||||
};
|
};
|
||||||
ble_issue_command(&cmd);
|
ble_issue_command(&cmd);
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,11 +24,10 @@
|
|||||||
#include <io/ble.h>
|
#include <io/ble.h>
|
||||||
|
|
||||||
#include "bootui.h"
|
#include "bootui.h"
|
||||||
#include "rust_ui_bootloader.h"
|
|
||||||
#include "workflow.h"
|
#include "workflow.h"
|
||||||
|
|
||||||
workflow_result_t workflow_ble_pairing_request(const uint8_t *data) {
|
workflow_result_t workflow_ble_pairing_request(const char *code) {
|
||||||
ui_result_t result = screen_confirm_pairing(data);
|
ui_result_t result = ui_screen_confirm_pairing(code);
|
||||||
|
|
||||||
if (result == UI_RESULT_CONFIRM) {
|
if (result == UI_RESULT_CONFIRM) {
|
||||||
ble_command_t cmd = {
|
ble_command_t cmd = {
|
||||||
@ -42,7 +41,6 @@ workflow_result_t workflow_ble_pairing_request(const uint8_t *data) {
|
|||||||
ble_issue_command(&cmd);
|
ble_issue_command(&cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
screen_connect(false);
|
|
||||||
return WF_OK;
|
return WF_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,8 @@ workflow_result_t workflow_host_control(const vendor_header *const vhdr,
|
|||||||
if (i == IFACE_BLE_EVENT) {
|
if (i == IFACE_BLE_EVENT) {
|
||||||
switch (e.event.ble_event.type) {
|
switch (e.event.ble_event.type) {
|
||||||
case BLE_PAIRING_REQUEST:
|
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;
|
continue;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -22,11 +22,61 @@
|
|||||||
|
|
||||||
#include <util/flash_utils.h>
|
#include <util/flash_utils.h>
|
||||||
|
|
||||||
|
#ifdef USE_BLE
|
||||||
|
#include <io/ble.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <sys/systick.h>
|
||||||
|
|
||||||
#include "bootui.h"
|
#include "bootui.h"
|
||||||
#include "protob.h"
|
#include "protob.h"
|
||||||
#include "rust_ui.h"
|
#include "rust_ui.h"
|
||||||
#include "workflow.h"
|
#include "workflow.h"
|
||||||
|
|
||||||
|
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) {
|
workflow_result_t workflow_wipe_device(protob_io_t* iface) {
|
||||||
ui_result_t response = ui_screen_wipe_confirm();
|
ui_result_t response = ui_screen_wipe_confirm();
|
||||||
if (UI_RESULT_CONFIRM != response) {
|
if (UI_RESULT_CONFIRM != response) {
|
||||||
@ -38,11 +88,14 @@ workflow_result_t workflow_wipe_device(protob_io_t *iface) {
|
|||||||
ui_screen_wipe();
|
ui_screen_wipe();
|
||||||
secbool wipe_result = erase_device(ui_screen_wipe_progress);
|
secbool wipe_result = erase_device(ui_screen_wipe_progress);
|
||||||
|
|
||||||
if (sectrue != wipe_result) {
|
#ifdef USE_BLE
|
||||||
if (iface != NULL) {
|
if (!wipe_bonds(iface)) {
|
||||||
send_msg_failure(iface, FailureType_Failure_ProcessError,
|
return WF_ERROR;
|
||||||
"Could not erase flash");
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sectrue != wipe_result) {
|
||||||
|
send_error_conditionally(iface, "Could not erase flash");
|
||||||
screen_wipe_fail();
|
screen_wipe_fail();
|
||||||
return WF_ERROR;
|
return WF_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -68,5 +68,5 @@ workflow_result_t workflow_auto_update(const vendor_header *const vhdr,
|
|||||||
const image_header *const hdr);
|
const image_header *const hdr);
|
||||||
|
|
||||||
#ifdef USE_BLE
|
#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
|
#endif
|
||||||
|
@ -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,
|
uint32_t version, const void* vendor_img,
|
||||||
size_t vendor_img_len, int wait);
|
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);
|
||||||
|
@ -146,8 +146,8 @@ extern "C" fn screen_wipe_fail() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[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) });
|
let code = unwrap!(unsafe { from_c_array(code, 6) });
|
||||||
|
|
||||||
ModelUI::screen_confirm_pairing(code)
|
ModelUI::screen_confirm_pairing(code, initial_setup)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ use crate::ui::{
|
|||||||
|
|
||||||
use ufmt::uwrite;
|
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 intro::Intro;
|
||||||
use menu::Menu;
|
use menu::Menu;
|
||||||
@ -441,15 +441,25 @@ impl BootloaderUI for UIBolt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ble")]
|
#[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 title = Label::centered("Pair device".into(), TEXT_NORMAL);
|
||||||
|
|
||||||
let msg = Label::centered(code.into(), TEXT_NORMAL);
|
let msg = Label::centered(code.into(), TEXT_NORMAL);
|
||||||
|
|
||||||
let right = Button::with_text("CONFIRM".into()).styled(button_confirm());
|
let (right, left) = if initial_setup {
|
||||||
let left = Button::with_text("REJECT".into()).styled(button_bld());
|
(
|
||||||
|
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)
|
run(&mut frame)
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
|
use super::super::{
|
||||||
|
component::{ButtonStyle, ButtonStyleSheet, ResultStyle},
|
||||||
|
fonts,
|
||||||
|
theme::{BLACK, FG, GREY_DARK, GREY_LIGHT, WHITE},
|
||||||
|
};
|
||||||
use crate::ui::{
|
use crate::ui::{
|
||||||
component::{text::TextStyle, LineBreaking::BreakWordsNoHyphen},
|
component::{text::TextStyle, LineBreaking::BreakWordsNoHyphen},
|
||||||
constant::{HEIGHT, WIDTH},
|
constant::{HEIGHT, WIDTH},
|
||||||
display::Color,
|
display::Color,
|
||||||
geometry::{Offset, Point, Rect},
|
geometry::{Offset, Point, Rect},
|
||||||
|
layout_bolt::theme::GREY_MEDIUM,
|
||||||
util::include_res,
|
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_BG: Color = Color::rgb(0x00, 0x1E, 0xAD);
|
||||||
pub const BLD_FG: Color = WHITE;
|
pub const BLD_FG: Color = WHITE;
|
||||||
pub const BLD_WIPE_COLOR: Color = Color::rgb(0xE7, 0x0E, 0x0E);
|
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: Color = Color::rgb(0x2D, 0x42, 0xBF);
|
||||||
pub const BLD_BTN_COLOR_ACTIVE: Color = Color::rgb(0x04, 0x10, 0x58);
|
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 BLD_TITLE_COLOR: Color = WHITE;
|
||||||
|
|
||||||
pub const WELCOME_COLOR: Color = BLACK;
|
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 {
|
pub const fn text_title(bg: Color) -> TextStyle {
|
||||||
TextStyle::new(
|
TextStyle::new(
|
||||||
fonts::FONT_BOLD_UPPER,
|
fonts::FONT_BOLD_UPPER,
|
||||||
|
@ -50,5 +50,5 @@ pub trait BootloaderUI {
|
|||||||
);
|
);
|
||||||
|
|
||||||
#[cfg(feature = "ble")]
|
#[cfg(feature = "ble")]
|
||||||
fn screen_confirm_pairing(code: &str) -> u32;
|
fn screen_confirm_pairing(code: &str, initial_setup: bool) -> u32;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user