Skip to content

Commit bf840c2

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 location. RAM is random after hardware reset, but does not get cleared on MCU reset.
1 parent 42bda93 commit bf840c2

10 files changed

+32
-59
lines changed

bootloader.ld

+1
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

+1
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

+5-7
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@
3939

4040
#include <assert.h>
4141

42+
// Section is fixed in ram, so can be used to communicate between fw/bl
43+
volatile secbool_u32 auto_enter __attribute__((section(".auto_enter")));
44+
4245
#define BOOT_OP_LEN 2u // 1 byte op code and 1 byte parameter
4346
#define BOOTLOADER_CMD (HID_VENDOR_FIRST + 0x03) // Hardware wallet command
4447

@@ -758,12 +761,7 @@ static size_t _api_versions(uint8_t* output)
758761

759762
static void _api_reboot(void)
760763
{
761-
chunk_shared_t shared_data;
762-
memory_read_shared_bootdata(&shared_data);
763-
if (shared_data.fields.auto_enter == sectrue_u8) {
764-
shared_data.fields.auto_enter = secfalse_u8;
765-
_write_chunk(FLASH_SHARED_DATA_START, shared_data.bytes);
766-
}
764+
auto_enter = secfalse_u32;
767765
_reset_mcu();
768766
}
769767

@@ -977,7 +975,7 @@ void bootloader_jump(void)
977975

978976
UG_FontSelect(&font_font_a_9X9);
979977

980-
if (shared_data.fields.auto_enter != sectrue_u8) {
978+
if (auto_enter != sectrue_u32) {
981979
#ifdef BOOTLOADER_DEVDEVICE
982980
if (!_devdevice_enter(_firmware_verified_jump(&bootdata, secfalse_u32))) {
983981
_binary_exec();

src/common_main.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,18 @@ void common_main(void)
7373
mpu_bitbox02_init();
7474
if (!memory_setup(&_memory_interface_functions)) {
7575
// If memory setup failed, this also might fail, but can't hurt to try.
76-
AbortAutoenter("memory_setup failed");
76+
Abort("memory_setup failed");
7777
}
7878

7979
if (!_setup_wally()) {
80-
AbortAutoenter("_setup_wally failed");
80+
Abort("_setup_wally failed");
8181
}
8282

8383
/* Enable/configure SmartEEPROM. */
8484
smarteeprom_bb02_config();
8585

8686
if (!securechip_init()) {
87-
AbortAutoenter("Failed to detect securechip");
87+
Abort("Failed to detect securechip");
8888
}
8989
// securechip_setup must come after memory_setup, so the io/auth keys to be
9090
// used are already initialized.
@@ -96,6 +96,6 @@ void common_main(void)
9696
sizeof(errmsg),
9797
"Securechip setup failed.\nError code: %i\nPlease contact support.",
9898
securechip_result);
99-
AbortAutoenter(errmsg);
99+
Abort(errmsg);
100100
}
101101
}

src/factorysetup.c

+3-13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "platform_init.h"
2121
#include "screen.h"
2222
#include "securechip/securechip.h"
23+
#include "system.h"
2324
#include "usb/usb.h"
2425
#include "usb/usb_packet.h"
2526
#include "usb/usb_processing.h"
@@ -312,19 +313,8 @@ int main(void)
312313
screen_splash();
313314
common_main();
314315

315-
{
316-
// Set to re-enter bootloader again, otherwise we are stuck with this
317-
// firmware forever.
318-
auto_enter_t auto_enter = {
319-
.value = sectrue_u8,
320-
};
321-
upside_down_t upside_down = {
322-
.value = false,
323-
};
324-
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
325-
// Not much we can do here.
326-
}
327-
}
316+
// After reset we prefer to stay in bootloader
317+
auto_enter = sectrue_u32;
328318

329319
SEGGER_RTT_Init();
330320

src/hardfault.c

+6-16
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 <memory/memory.h>
@@ -47,20 +48,9 @@ void Abort(const char* msg)
4748
#endif
4849
// Break the program if we are debugging
4950
ASSERT(false);
50-
while (1) {
51-
}
52-
}
53-
54-
void AbortAutoenter(const char* msg)
55-
{
56-
auto_enter_t auto_enter = {
57-
.value = sectrue_u8,
58-
};
59-
upside_down_t upside_down = {
60-
.value = screen_is_upside_down(),
61-
};
62-
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
63-
// If this failed, we might not be able to reboot into the bootloader.
64-
}
65-
Abort(msg);
51+
delay_ms(30000);
52+
// Restart into bootloader
53+
auto_enter = sectrue_u32;
54+
_reset_mcu();
55+
while (1);
6656
}

src/hardfault.h

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

+1-1
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

+4-10
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,16 @@
1515
#include "system.h"
1616
#include <memory/memory.h>
1717
#include <screen.h>
18+
#include <stdint.h>
1819
#ifndef TESTING
1920
#include <driver_init.h>
2021
#endif
2122

23+
volatile secbool_u32 auto_enter __attribute__((section(".auto_enter")));
24+
2225
void reboot(void)
2326
{
24-
auto_enter_t auto_enter = {
25-
.value = sectrue_u8,
26-
};
27-
upside_down_t upside_down = {
28-
.value = screen_is_upside_down(),
29-
};
30-
if (!memory_bootloader_set_flags(auto_enter, upside_down)) {
31-
// If this failed, we might not be able to reboot into the bootloader.
32-
// We will try anyway, no point in aborting here.
33-
}
27+
auto_enter = sectrue_u32;
3428
#ifndef TESTING
3529
_reset_mcu();
3630
#endif

src/system.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,14 @@
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
/**
19-
* Reboots the device.
25+
* Reboots the device into bootloader
2026
*/
2127
void reboot(void);
2228

0 commit comments

Comments
 (0)