diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index d2b3346c0..52c8eb7b9 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -82,7 +82,8 @@ typedef enum { CONTINUE = 0, RETURN = 1, SHUTDOWN = 2, -} usb_result_t; + NO_RESULT = -1, +} comm_result_t; static void usb_init_all(secbool usb21_landing) { usb_dev_info_t dev_info = { @@ -124,15 +125,6 @@ static void usb_init_all(secbool usb21_landing) { usb_start(); } -void start_comm(secbool usb21_landing) { - // if both are NULL, we don't have a firmware installed - // let's show a webusb landing page in this case - usb_init_all(usb21_landing); -#ifdef USE_BLE - start_advertising(); -#endif -} - void stop_comm(void) { hal_delay(100); usb_stop(); @@ -142,64 +134,138 @@ void stop_comm(void) { #endif } -static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, +static comm_result_t process_common_messages(uint8_t iface, uint8_t *buf, + const vendor_header *const vhdr, + const image_header *const hdr) { + uint16_t msg_id; + uint32_t msg_size; + uint32_t response; + int32_t upload_response; + if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) { + // invalid header -> discard + return NO_RESULT; + } + switch (msg_id) { + case 0: // Initialize + process_msg_Initialize(iface, msg_size, buf, vhdr, hdr); + break; + case 1: // Ping + process_msg_Ping(iface, msg_size, buf); + break; + case 5: // WipeDevice + response = ui_screen_wipe_confirm(); + if (INPUT_CANCEL == response) { + send_user_abort(iface, "Wipe cancelled"); + stop_comm(); + return RETURN; + } + ui_screen_wipe(); + upload_response = process_msg_WipeDevice(iface, msg_size, buf); + if (upload_response < 0) { // error + screen_wipe_fail(); + stop_comm(); + return SHUTDOWN; + } else { // success + screen_wipe_success(); + stop_comm(); + return SHUTDOWN; + } + break; + case 6: // FirmwareErase + process_msg_FirmwareErase(iface, msg_size, buf); + break; + case 7: // FirmwareUpload + upload_response = process_msg_FirmwareUpload(iface, msg_size, buf); + if (upload_response < 0 && + upload_response != + UPLOAD_ERR_USER_ABORT) { // error, but not user abort + ui_screen_fail(); + stop_comm(); + return SHUTDOWN; + } else if (upload_response == UPLOAD_ERR_USER_ABORT) { + stop_comm(); + return RETURN; + } else if (upload_response == 0) { // last chunk received + ui_screen_install_progress_upload(1000); + ui_screen_done(4, sectrue); + ui_screen_done(3, secfalse); + hal_delay(1000); + ui_screen_done(2, secfalse); + hal_delay(1000); + ui_screen_done(1, secfalse); + hal_delay(1000); + stop_comm(); + ui_screen_boot_empty(true); + return CONTINUE; + } + break; + case 55: // GetFeatures + process_msg_GetFeatures(iface, msg_size, buf, vhdr, hdr); + break; + default: + process_msg_unknown(iface, msg_size, buf); + break; + } + + return NO_RESULT; +} + +static comm_result_t bootloader_usb_loop(const vendor_header *const vhdr, const image_header *const hdr) { - start_comm((vhdr == NULL && hdr == NULL) ? sectrue : secfalse); + uint8_t buf[USB_PACKET_SIZE]; - uint8_t buf_usb[USB_PACKET_SIZE]; -#ifdef USE_BLE - uint8_t ble_buf[BLE_PACKET_SIZE]; + for (;;) { +#ifdef TREZOR_EMULATOR + emulator_poll_events(); #endif - uint8_t *buf = NULL; + int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE, + USB_TIMEOUT); + if (r != USB_PACKET_SIZE) { + continue; + } + + comm_result_t res = process_common_messages(USB_IFACE_NUM, buf, vhdr, hdr); + + if (res != NO_RESULT) { + return res; + } + } +} + +#ifdef USE_BLE +static comm_result_t bootloader_ble_loop(const vendor_header *const vhdr, + const image_header *const hdr) { + start_advertising(); + + uint8_t buf[BLE_PACKET_SIZE]; uint8_t active_iface = 0; int r = 0; for (;;) { for (;;) { -#ifdef TREZOR_EMULATOR - emulator_poll_events(); -#endif - r = usb_webusb_read_blocking(USB_IFACE_NUM, buf_usb, USB_PACKET_SIZE, 20); - if (r == USB_PACKET_SIZE) { - active_iface = USB_IFACE_NUM; - buf = buf_usb; - break; - } -#ifdef USE_BLE - r = ble_ext_comm_receive(ble_buf, sizeof(ble_buf)); + r = ble_ext_comm_receive(buf, sizeof(buf)); if (r == BLE_PACKET_SIZE) { active_iface = BLE_EXT_IFACE_NUM; - buf = ble_buf; break; } - r = ble_int_comm_receive(ble_buf, sizeof(ble_buf)); + r = ble_int_comm_receive(buf, sizeof(buf)); if (r != 0) { active_iface = BLE_INT_IFACE_NUM; - buf = ble_buf; break; } - - ble_event_poll(); -#endif } -#ifdef USE_BLE if (active_iface == BLE_INT_IFACE_NUM) { for (;;) { bool next = false; if (r == 0) { - if (active_iface == BLE_INT_IFACE_NUM) { - r = ble_int_comm_receive(ble_buf, sizeof(ble_buf)); + r = ble_int_comm_receive(buf, sizeof(buf)); - if (r == 0) { - continue; - } - } else { - // unknown interface - return CONTINUE; + if (r == 0) { + continue; } } @@ -214,7 +280,7 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, } switch (msg_id) { case MessageType_MessageType_PairingRequest: // pairing request - response = process_msg_Pairing(active_iface, msg_size, ble_buf); + response = process_msg_Pairing(active_iface, msg_size, buf); if (response != INPUT_CONFIRM) { stop_comm(); return RETURN; @@ -224,7 +290,7 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, break; case MessageType_MessageType_RepairRequest: // repairing request - response = process_msg_Repair(active_iface, msg_size, ble_buf); + response = process_msg_Repair(active_iface, msg_size, buf); if (response != INPUT_CONFIRM) { stop_comm(); return RETURN; @@ -233,7 +299,7 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, // todo - screen connect or timeout? break; default: - process_msg_unknown(active_iface, msg_size, ble_buf); + process_msg_unknown(active_iface, msg_size, buf); break; } if (next) { @@ -241,113 +307,58 @@ static usb_result_t bootloader_comm_loop(const vendor_header *const vhdr, } } } -#endif - if (active_iface == USB_IFACE_NUM || active_iface == BLE_EXT_IFACE_NUM) { + if (active_iface == BLE_EXT_IFACE_NUM) { for (;;) { -#ifdef TREZOR_EMULATOR - emulator_poll_events(); -#endif if (r == 0) { - if (active_iface == USB_IFACE_NUM) { - r = usb_webusb_read_blocking(active_iface, buf_usb, USB_PACKET_SIZE, - USB_TIMEOUT); - if (r != USB_PACKET_SIZE) { - continue; - } - } -#ifdef USE_BLE - else if (active_iface == BLE_EXT_IFACE_NUM) { - r = ble_ext_comm_receive(ble_buf, sizeof(ble_buf)); + r = ble_ext_comm_receive(buf, sizeof(buf)); - if (r != BLE_PACKET_SIZE) { - continue; - } - } -#endif - else { - // unknown interface - return CONTINUE; + if (r != BLE_PACKET_SIZE) { + continue; } } - r = 0; - uint16_t msg_id; - uint32_t msg_size; - uint32_t response; - int32_t upload_response; - if (sectrue != msg_parse_header(buf, &msg_id, &msg_size)) { - // invalid header -> discard - continue; - } - switch (msg_id) { - case 0: // Initialize - process_msg_Initialize(active_iface, msg_size, buf, vhdr, hdr); - break; - case 1: // Ping - process_msg_Ping(active_iface, msg_size, buf); - break; - case 5: // WipeDevice - response = ui_screen_wipe_confirm(); - if (INPUT_CANCEL == response) { - send_user_abort(active_iface, "Wipe cancelled"); - stop_comm(); - return RETURN; - } - ui_screen_wipe(); - upload_response = - process_msg_WipeDevice(active_iface, msg_size, buf); - if (upload_response < 0) { // error - screen_wipe_fail(); - stop_comm(); - return SHUTDOWN; - } else { // success - screen_wipe_success(); - stop_comm(); - return SHUTDOWN; - } - break; - case 6: // FirmwareErase - process_msg_FirmwareErase(active_iface, msg_size, buf); - break; - case 7: // FirmwareUpload - upload_response = - process_msg_FirmwareUpload(active_iface, msg_size, buf); - if (upload_response < 0 && - upload_response != - UPLOAD_ERR_USER_ABORT) { // error, but not user abort - ui_screen_fail(); - stop_comm(); - return SHUTDOWN; - } else if (upload_response == UPLOAD_ERR_USER_ABORT) { - stop_comm(); - return RETURN; - } else if (upload_response == 0) { // last chunk received - ui_screen_install_progress_upload(1000); - ui_screen_done(4, sectrue); - ui_screen_done(3, secfalse); - hal_delay(1000); - ui_screen_done(2, secfalse); - hal_delay(1000); - ui_screen_done(1, secfalse); - hal_delay(1000); - stop_comm(); - ui_screen_boot_empty(true); - return CONTINUE; - } - break; - case 55: // GetFeatures - process_msg_GetFeatures(active_iface, msg_size, buf, vhdr, hdr); - break; - default: - process_msg_unknown(active_iface, msg_size, buf); - break; + comm_result_t res = + process_common_messages(active_iface, buf, vhdr, hdr); + + if (res != NO_RESULT) { + return res; } } } } } +#endif + +static comm_result_t bootloader_comm_select(const vendor_header *const vhdr, + const image_header *const hdr) { + // if both are NULL, we don't have a firmware installed + // let's show a webusb landing page in this case + usb_init_all((vhdr == NULL && hdr == NULL) ? sectrue : secfalse); + +#ifdef USE_BLE + bool usb = false; + + for (int i = 0; i < 2000; i++) { + hal_delay(1); + if (usb_configured_now() == sectrue) { + usb = true; + break; + } + } + + if (usb) { + return bootloader_usb_loop(vhdr, hdr); + } else { + usb_stop(); + usb_deinit(); + return bootloader_ble_loop(vhdr, hdr); + } +#else + return bootloader_usb_loop(vhdr, hdr); +#endif +} secbool check_vendor_header_keys(const vendor_header *const vhdr) { return check_vendor_header_sig(vhdr, BOOTLOADER_KEY_M, BOOTLOADER_KEY_N, @@ -539,7 +550,7 @@ int bootloader_main(void) { NULL); // and start the usb loop - if (bootloader_comm_loop(NULL, NULL) != CONTINUE) { + if (bootloader_comm_select(NULL, NULL) != CONTINUE) { return 1; } } @@ -598,7 +609,7 @@ int bootloader_main(void) { break; case SCREEN_WAIT_FOR_HOST: screen_connect(); - switch (bootloader_comm_loop(&vhdr, hdr)) { + switch (bootloader_comm_select(&vhdr, hdr)) { case CONTINUE: continue_to_firmware = true; break; diff --git a/core/embed/trezorhal/usb.c b/core/embed/trezorhal/usb.c index 0feaac1c1..14457ae40 100644 --- a/core/embed/trezorhal/usb.c +++ b/core/embed/trezorhal/usb.c @@ -187,6 +187,15 @@ secbool usb_configured(void) { return secfalse; } +secbool usb_configured_now(void) { + const USBD_HandleTypeDef *pdev = &usb_dev_handle; + if (pdev->dev_state == USBD_STATE_SUSPENDED && + pdev->dev_old_state == USBD_STATE_CONFIGURED) { + return sectrue; + } + return secfalse; +} + /* * Utility functions for USB interfaces */ diff --git a/core/embed/trezorhal/usb.h b/core/embed/trezorhal/usb.h index b9b27a4de..90a197a48 100644 --- a/core/embed/trezorhal/usb.h +++ b/core/embed/trezorhal/usb.h @@ -144,5 +144,6 @@ void usb_deinit(void); void usb_start(void); void usb_stop(void); secbool usb_configured(void); +secbool usb_configured_now(void); #endif