Skip to content

Commit

Permalink
feat: UpdateAfter is busted, add reset parameter for triggering update
Browse files Browse the repository at this point in the history
  • Loading branch information
mrnerdhair committed Apr 20, 2022
1 parent a670f74 commit 18da57f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 34 deletions.
6 changes: 5 additions & 1 deletion include/keepkey/board/keepkey_board.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
#define VERSION_NUM(x) #x
#define VERSION_STR(x) VERSION_NUM(x)

#define RESET_PARAM_NONE 0
// This is the ASCII string "UPDT" interpreted as an integer in little-endian form.
#define RESET_PARAM_REQUEST_UPDATE 0x54445055

/* Flash metadata structure which will contains unique identifier
information that spans device resets. */
typedef struct _Metadata {
Expand All @@ -79,7 +83,7 @@ typedef struct _Cache {

extern uintptr_t __stack_chk_guard;

void board_reset(void);
void board_reset(uint32_t reset_param);
void board_init(void);
void kk_board_init(void);

Expand Down
5 changes: 4 additions & 1 deletion lib/board/keepkey_board.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,11 @@ void nmi_handler(void) {
* OUTPUT
* none
*/
void board_reset(void) {
void board_reset(uint32_t reset_param) {
#ifndef EMULATOR
_param_1 = reset_param;
_param_2 = ~reset_param;
_param_3 = reset_param;
scb_reset_system();
#endif
}
Expand Down
35 changes: 4 additions & 31 deletions tools/blupdater/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,17 @@ static bool write_bootloader(void) {
flash_unlock();

// erase the bootloader sectors, do not use flash_erase_word()
layoutProgress("Updating bootloader. DO NOT UNPLUG", 0);
layoutProgress("Updating Bootloader. DO NOT UNPLUG", 0);
flash_erase_sector(5, FLASH_CR_PROGRAM_X32);
flash_wait_for_last_operation();
layoutProgress("Updating bootloader. DO NOT UNPLUG", 100);
layoutProgress("Updating Bootloader. DO NOT UNPLUG", 100);
flash_erase_sector(6, FLASH_CR_PROGRAM_X32);
flash_wait_for_last_operation();

// Write into the sector.
for (int chunkstart = 0; chunkstart < _binary_payload_bin_size;
chunkstart += CHUNK_SIZE) {
layoutProgress("Updating bootloader. DO NOT UNPLUG",
layoutProgress("Updating Bootloader. DO NOT UNPLUG",
200 + chunkstart * 800 / _binary_payload_bin_size);

size_t chunksize;
Expand Down Expand Up @@ -162,39 +162,12 @@ static bool unknown_bootloader(void) {
/// \brief Success: everything went smoothly as expected, and the device has a
/// new bootloader installed.
static void success(void) {
for (int i = 0; i < NUM_RETRIES; ++i) {
// Enable writing to the read-only sectors
memory_unlock();
flash_unlock();

flash_program_word(FLASH_META_FLAGS, META_FLAGS | 1);
flash_wait_for_last_operation();

if ((META_FLAGS & 1) == 1) {
break;
}
}

// Disallow writing to flash.
flash_lock();

// Ignore any reported errors, we only care about the end result.
flash_clear_status_flags();

if ((META_FLAGS & 1) != 1) {
layout_standard_notification("Bootloader Update Complete",
"Please unplug your device.",
NOTIFICATION_CONFIRMED);
display_refresh();
shutdown();
}

layout_standard_notification("Bootloader Update Complete",
"Your device will now restart",
NOTIFICATION_CONFIRMED);
display_refresh();
delay_ms(3000);
board_reset();
board_reset(RESET_PARAM_REQUEST_UPDATE);
}

/// \brief Hard Failure: something went wrong during the write, and it's
Expand Down
26 changes: 25 additions & 1 deletion tools/bootloader/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,26 @@ static inline void __attribute__((noreturn)) jump_to_firmware(int trust) {
;
}

uint32_t reset_param = 0;

void capture_reset_param(void) {
// Capture the reset parameter value. Because SRAM starts up from a cold boot
// in an undefined state, a simple redundancy-based check is used to validate
// that a parameter was in fact passed: _param_1 and _param_3 must match, and
// _param_2 must be their bitwise inverse.
//
// Currently, this is only used by the blupdater to request that the firmware
// enter update mode, by passing RESET_PARAM_REQUEST_UPDATE.
if (_param_1 == ~_param_2 && _param_1 == _param_3) {
reset_param = _param_1;
}

// Clear the shared memory section used for communicating the reset parameter.
_param_1 = 0;
_param_2 = 0;
_param_3 = 0;
}

/// Bootloader Board Initialization
static void bootloader_init(void) {
cm_enable_interrupts();
Expand All @@ -156,6 +176,7 @@ static void bootloader_init(void) {
storage_sectorInit();
display_hw_init();
layout_init(display_canvas_init());
capture_reset_param();
}

/// Enable the timer interrupts
Expand All @@ -175,6 +196,9 @@ static void clock_init(void) {

/// \returns true iff the device should enter firmware update mode.
static bool isFirmwareUpdateMode(void) {
// Firmware asked for an update.
if (reset_param == RESET_PARAM_REQUEST_UPDATE) return true;

// User asked for an update.
if (keepkey_button_down()) return true;

Expand Down Expand Up @@ -280,7 +304,7 @@ static void update_fw(void) {
NOTIFICATION_CONFIRMED);
display_refresh();
delay_ms(3000);
board_reset();
board_reset(RESET_PARAM_NONE);
} else {
layout_standard_notification(
"Firmware Update Failure",
Expand Down
16 changes: 16 additions & 0 deletions tools/bootloader/startup.s
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,28 @@ reset_handler:
ldr r0, [r0]
msr msp, r0

// Save any reset parameters from the SRAM wipe
ldr r0, =_param_1
ldr r3, [r0]
ldr r0, =_param_2
ldr r4, [r0]
ldr r0, =_param_3
ldr r5, [r0]

ldr r0, =_ram_start // r0 - point to beginning of SRAM
// ldr r1, =_ram_end // r1 - point to byte after the end of SRAM
ldr r1, =_comram_end
ldr r2, =0 // r2 - the byte-sized value to be written
bl memset_reg

// Restore any reset parameters
ldr r0, =_param_1
str r3, [r0]
ldr r0, =_param_2
str r4, [r0]
ldr r0, =_param_3
str r5, [r0]

// copy .data section from flash to SRAM
ldr r0, =_data // dst addr
ldr r1, =_data_loadaddr // src addr
Expand Down

0 comments on commit 18da57f

Please sign in to comment.