Skip to content

Commit 40d3475

Browse files
committed
bootloader-fw-link: Use RAM to communicate
Instead of writing to non-volatile storage between mcu resets, write to a well-known RAM location. RAM is random after power cycling, but does not get cleared on MCU reset.
1 parent ddd9b65 commit 40d3475

File tree

11 files changed

+41
-64
lines changed

11 files changed

+41
-64
lines changed

bootloader.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ SECTIONS
116116
{
117117
. = ALIGN(4);
118118
_srtt = .;
119+
*(.auto_enter);
119120
*(.segger_rtt);
120121
*(.segger_rtt_buf);
121122
_ertt = .;

firmware.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ SECTIONS
115115
{
116116
. = ALIGN(4);
117117
_srtt = .;
118+
*(.auto_enter);
118119
*(.segger_rtt);
119120
*(.segger_rtt_buf);
120121
_ertt = .;

src/bootloader/bootloader.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@
5151

5252
#include <assert.h>
5353

54+
// Section is fixed in ram, so can be used to communicate between fw/bl
55+
// Must stay synchronized with system.c, bootloader.ld, firmware.ld
56+
volatile secbool_u32 auto_enter __attribute__((section(".auto_enter")));
57+
5458
#define BOOT_OP_LEN 2u // 1 byte op code and 1 byte parameter
5559
#define BOOTLOADER_CMD (HID_VENDOR_FIRST + 0x03) // Hardware wallet command
5660

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

846850
static void _api_reboot(void)
847851
{
848-
chunk_shared_t shared_data;
849-
memory_read_shared_bootdata(&shared_data);
850-
if (shared_data.fields.auto_enter == sectrue_u8) {
851-
shared_data.fields.auto_enter = secfalse_u8;
852-
_write_chunk(FLASH_SHARED_DATA_START, shared_data.bytes);
853-
}
852+
auto_enter = secfalse_u32;
854853
_reset_mcu();
855854
}
856855

@@ -1076,7 +1075,7 @@ void bootloader_jump(void)
10761075

10771076
UG_FontSelect(&font_font_a_9X9);
10781077

1079-
if (shared_data.fields.auto_enter != sectrue_u8) {
1078+
if (auto_enter != sectrue_u32) {
10801079
#ifdef BOOTLOADER_DEVDEVICE
10811080
if (!_devdevice_enter(_firmware_verified_jump(&bootdata, secfalse_u32))) {
10821081
_binary_exec();

src/common_main.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,14 @@ void common_main(void)
5656
mpu_bitbox02_init();
5757
if (!memory_setup(&_memory_interface_functions)) {
5858
// If memory setup failed, this also might fail, but can't hurt to try.
59-
AbortAutoenter("memory_setup failed");
59+
Abort("memory_setup failed");
6060
}
6161

6262
/* Enable/configure SmartEEPROM. */
6363
smarteeprom_bb02_config();
6464

6565
if (!securechip_init()) {
66-
AbortAutoenter("Failed to detect securechip");
66+
Abort("Failed to detect securechip");
6767
}
6868
// securechip_setup must come after memory_setup, so the io/auth keys to be
6969
// used are already initialized.
@@ -75,6 +75,6 @@ void common_main(void)
7575
sizeof(errmsg),
7676
"Securechip setup failed.\nError code: %i\nPlease contact support.",
7777
securechip_result);
78-
AbortAutoenter(errmsg);
78+
Abort(errmsg);
7979
}
8080
}

src/factorysetup.c

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "rust/rust.h"
2828
#include "screen.h"
2929
#include "securechip/securechip.h"
30+
#include "system.h"
3031
#include "uart.h"
3132
#include "usb/usb.h"
3233
#include "usb/usb_packet.h"
@@ -581,19 +582,8 @@ int main(void)
581582
screen_splash();
582583
common_main();
583584

584-
{
585-
// Set to re-enter bootloader again, otherwise we are stuck with this
586-
// firmware forever.
587-
auto_enter_t auto_enter = {
588-
.value = sectrue_u8,
589-
};
590-
upside_down_t upside_down = {
591-
.value = false,
592-
};
593-
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
594-
// Not much we can do here.
595-
}
596-
}
585+
// After reset we prefer to stay in bootloader
586+
auto_enter = sectrue_u32;
597587

598588
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
599589
_ble_result = _setup_ble();

src/hardfault.c

Lines changed: 12 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// limitations under the License.
1414

1515
#include "hardfault.h"
16+
#include "system.h"
1617
#include "util.h"
1718
#include "utils_assert.h"
1819
#include <driver_init.h>
@@ -27,6 +28,7 @@
2728
#endif
2829

2930
#ifndef TESTING
31+
#define ABORT_COUNTDOWN 30
3032
void HardFault_Handler(void)
3133
{
3234
Abort("Unexpected error.\nPlease contact support.");
@@ -46,29 +48,18 @@ void Abort(const char* msg)
4648
#else
4749
util_log("%s", msg);
4850
screen_print_debug(msg, 0);
49-
usb_stop();
50-
#if defined(BOOTLOADER)
51-
bootloader_close_interfaces();
52-
#else
53-
system_close_interfaces();
54-
#endif
5551
// Break the program if we are debugging
5652
ASSERT(false);
57-
while (1) {
53+
char buf[30] = {0};
54+
for (int i = 0; i < ABORT_COUNTDOWN; i++) {
55+
snprintf(buf, sizeof(buf), "Enter bootloader in %02d", ABORT_COUNTDOWN - i);
56+
UG_PutStringCentered(0, 56, 128, 8, buf, false);
57+
UG_SendBuffer();
58+
delay_ms(1000);
5859
}
60+
// Restart into bootloader
61+
auto_enter = sectrue_u32;
62+
_reset_mcu();
63+
while (1);
5964
#endif
6065
}
61-
62-
void AbortAutoenter(const char* msg)
63-
{
64-
auto_enter_t auto_enter = {
65-
.value = sectrue_u8,
66-
};
67-
upside_down_t upside_down = {
68-
.value = screen_is_upside_down(),
69-
};
70-
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
71-
// If this failed, we might not be able to reboot into the bootloader.
72-
}
73-
Abort(msg);
74-
}

src/hardfault.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,4 @@ void HardFault_Handler(void) __attribute__((weak));
2626
// debugging.
2727
__attribute__((noreturn)) void Abort(const char* msg);
2828

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

src/memory/bitbox02_smarteeprom.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ void bitbox02_smarteeprom_init(void)
110110
*/
111111
char msg[200] = {0};
112112
snprintf(msg, sizeof(msg), "Unrecognized SmartEEPROM version.\nGot %d", current_version);
113-
AbortAutoenter(msg);
113+
Abort(msg);
114114
}
115115
}
116116

src/system.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,16 @@
1818
#include <memory/memory.h>
1919
#include <memory/memory_shared.h>
2020
#include <screen.h>
21+
#include <stdint.h>
2122
#ifndef TESTING
2223
#include "uart.h"
2324
#include <driver_init.h>
2425
#endif
2526

27+
// Section is fixed in ram, so can be used to communicate between fw/bl
28+
// Must stay synchronized with bootloader.c, bootloader.ld, firmware.ld
29+
volatile secbool_u32 auto_enter __attribute__((section(".auto_enter")));
30+
2631
static void _ble_clear_product(void)
2732
{
2833
struct ringbuffer uart_queue;
@@ -43,16 +48,7 @@ void reboot_to_bootloader(void)
4348
if (memory_get_platform() == MEMORY_PLATFORM_BITBOX02_PLUS) {
4449
_ble_clear_product();
4550
}
46-
auto_enter_t auto_enter = {
47-
.value = sectrue_u8,
48-
};
49-
upside_down_t upside_down = {
50-
.value = screen_is_upside_down(),
51-
};
52-
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
53-
// If this failed, we might not be able to reboot into the bootloader.
54-
// We will try anyway, no point in aborting here.
55-
}
51+
auto_enter = sectrue_u32;
5652
#ifndef TESTING
5753
_reset_mcu();
5854
#endif

src/system.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@
1515
#ifndef _SYSTEM_H_
1616
#define _SYSTEM_H_
1717

18+
#include "util.h"
19+
20+
// Set this to `sectrue_u32` to stay in bootloader, or anything else to jump to firmware
21+
22+
extern volatile secbool_u32 auto_enter;
23+
1824
/**
1925
* Reboots the device to bootloader
2026
*/

0 commit comments

Comments
 (0)