Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bootloader.ld
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ SECTIONS
{
. = ALIGN(4);
_srtt = .;
*(.auto_enter);
*(.segger_rtt);
*(.segger_rtt_buf);
_ertt = .;
Expand Down
1 change: 1 addition & 0 deletions firmware.ld
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ SECTIONS
{
. = ALIGN(4);
_srtt = .;
*(.auto_enter);
*(.segger_rtt);
*(.segger_rtt_buf);
_ertt = .;
Expand Down
13 changes: 6 additions & 7 deletions src/bootloader/bootloader.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@

#include <assert.h>

// Section is fixed in ram, so can be used to communicate between fw/bl
// Must stay synchronized with system.c, bootloader.ld, firmware.ld
volatile secbool_u32 auto_enter __attribute__((section(".auto_enter")));

#define BOOT_OP_LEN 2u // 1 byte op code and 1 byte parameter
#define BOOTLOADER_CMD (HID_VENDOR_FIRST + 0x03) // Hardware wallet command

Expand Down Expand Up @@ -845,12 +849,7 @@ static size_t _api_versions(uint8_t* output)

static void _api_reboot(void)
{
chunk_shared_t shared_data;
memory_read_shared_bootdata(&shared_data);
if (shared_data.fields.auto_enter == sectrue_u8) {
shared_data.fields.auto_enter = secfalse_u8;
_write_chunk(FLASH_SHARED_DATA_START, shared_data.bytes);
}
auto_enter = secfalse_u32;
_reset_mcu();
}

Expand Down Expand Up @@ -1076,7 +1075,7 @@ void bootloader_jump(void)

UG_FontSelect(&font_font_a_9X9);

if (shared_data.fields.auto_enter != sectrue_u8) {
if (auto_enter != sectrue_u32) {
#ifdef BOOTLOADER_DEVDEVICE
if (!_devdevice_enter(_firmware_verified_jump(&bootdata, secfalse_u32))) {
_binary_exec();
Expand Down
6 changes: 3 additions & 3 deletions src/common_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ void common_main(void)
mpu_bitbox02_init();
if (!memory_setup(&_memory_interface_functions)) {
// If memory setup failed, this also might fail, but can't hurt to try.
AbortAutoenter("memory_setup failed");
Abort("memory_setup failed");
}

/* Enable/configure SmartEEPROM. */
smarteeprom_bb02_config();

if (!securechip_init()) {
AbortAutoenter("Failed to detect securechip");
Abort("Failed to detect securechip");
}
// securechip_setup must come after memory_setup, so the io/auth keys to be
// used are already initialized.
Expand All @@ -75,6 +75,6 @@ void common_main(void)
sizeof(errmsg),
"Securechip setup failed.\nError code: %i\nPlease contact support.",
securechip_result);
AbortAutoenter(errmsg);
Abort(errmsg);
}
}
16 changes: 3 additions & 13 deletions src/factorysetup.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "rust/rust.h"
#include "screen.h"
#include "securechip/securechip.h"
#include "system.h"
#include "uart.h"
#include "usb/usb.h"
#include "usb/usb_packet.h"
Expand Down Expand Up @@ -581,19 +582,8 @@ int main(void)
screen_splash();
common_main();

{
// Set to re-enter bootloader again, otherwise we are stuck with this
// firmware forever.
auto_enter_t auto_enter = {
.value = sectrue_u8,
};
upside_down_t upside_down = {
.value = false,
};
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
// Not much we can do here.
}
}
// After reset we prefer to stay in bootloader
auto_enter = sectrue_u32;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The factory-setup could also just erase the first 8 bytes of itself when it is done, making it unbootable (and thus the bootloader would not try to boot it).


if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
_ble_result = _setup_ble();
Expand Down
33 changes: 12 additions & 21 deletions src/hardfault.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

#include "hardfault.h"
#include "system.h"
#include "util.h"
#include "utils_assert.h"
#include <driver_init.h>
Expand All @@ -27,6 +28,7 @@
#endif

#ifndef TESTING
#define ABORT_COUNTDOWN 30
void HardFault_Handler(void)
{
Abort("Unexpected error.\nPlease contact support.");
Expand All @@ -46,29 +48,18 @@ void Abort(const char* msg)
#else
util_log("%s", msg);
screen_print_debug(msg, 0);
usb_stop();
#if defined(BOOTLOADER)
bootloader_close_interfaces();
#else
system_close_interfaces();
#endif
// Break the program if we are debugging
ASSERT(false);
while (1) {
char buf[30] = {0};
for (int i = 0; i < ABORT_COUNTDOWN; i++) {
snprintf(buf, sizeof(buf), "Enter bootloader in %02d", ABORT_COUNTDOWN - i);
UG_PutStringCentered(0, 56, 128, 8, buf, false);
UG_SendBuffer();
delay_ms(1000);
}
// Restart into bootloader
auto_enter = sectrue_u32;
_reset_mcu();
while (1);
#endif
}

void AbortAutoenter(const char* msg)
{
auto_enter_t auto_enter = {
.value = sectrue_u8,
};
upside_down_t upside_down = {
.value = screen_is_upside_down(),
};
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
// If this failed, we might not be able to reboot into the bootloader.
}
Abort(msg);
}
7 changes: 0 additions & 7 deletions src/hardfault.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,4 @@ void HardFault_Handler(void) __attribute__((weak));
// debugging.
__attribute__((noreturn)) void Abort(const char* msg);

// Abort is for manual calls to stop execution, providing a message for debugging. It also sets
// autoenter to true, making sure that the device boots into the bootloader after reconnecting it.
// This should be called for any Abort during firmware startup, so a firmware update can be
// applied. Otherwise, if there is an Abort() during startup, there would no way to reboot into the
// bootloader and the device would be bricked.
__attribute__((noreturn)) void AbortAutoenter(const char* msg);

#endif
2 changes: 1 addition & 1 deletion src/memory/bitbox02_smarteeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ void bitbox02_smarteeprom_init(void)
*/
char msg[200] = {0};
snprintf(msg, sizeof(msg), "Unrecognized SmartEEPROM version.\nGot %d", current_version);
AbortAutoenter(msg);
Abort(msg);
}
}

Expand Down
16 changes: 6 additions & 10 deletions src/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,16 @@
#include <memory/memory.h>
#include <memory/memory_shared.h>
#include <screen.h>
#include <stdint.h>
#ifndef TESTING
#include "uart.h"
#include <driver_init.h>
#endif

// Section is fixed in ram, so can be used to communicate between fw/bl
// Must stay synchronized with bootloader.c, bootloader.ld, firmware.ld
volatile secbool_u32 auto_enter __attribute__((section(".auto_enter")));

static void _ble_clear_product(void)
{
struct ringbuffer uart_queue;
Expand All @@ -43,16 +48,7 @@ void reboot_to_bootloader(void)
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
_ble_clear_product();
}
auto_enter_t auto_enter = {
.value = sectrue_u8,
};
upside_down_t upside_down = {
.value = screen_is_upside_down(),
};
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
// If this failed, we might not be able to reboot into the bootloader.
// We will try anyway, no point in aborting here.
}
auto_enter = sectrue_u32;
#ifndef TESTING
_reset_mcu();
#endif
Expand Down
6 changes: 6 additions & 0 deletions src/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@
#ifndef _SYSTEM_H_
#define _SYSTEM_H_

#include "util.h"

// Set this to `sectrue_u32` to stay in bootloader, or anything else to jump to firmware

extern volatile secbool_u32 auto_enter;

/**
* Reboots the device to bootloader
*/
Expand Down
4 changes: 2 additions & 2 deletions src/usb/usb_processing.c
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ void usb_processing_init(void)
void usb_processing_lock(struct usb_processing* ctx)
{
if (_usb_state.blocking_ctx) {
AbortAutoenter("Tried to lock the USB stack while locked.");
Abort("Tried to lock the USB stack while locked.");
}
_usb_state.blocking_ctx = ctx;
}
Expand All @@ -436,7 +436,7 @@ void usb_processing_timeout_reset(int16_t val)
void usb_processing_unlock(void)
{
if (!_usb_state.blocking_ctx) {
AbortAutoenter("Tried to unlock the USB stack while not locked.");
Abort("Tried to unlock the USB stack while not locked.");
}
_usb_state.blocking_ctx = NULL;
}
Expand Down