mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-27 16:48:09 +00:00
legacy/intermediate_fw: Intermediate firmware for T1 (#1084)
* legacy/intermediate_fw: skeleton FW with RAM shim function * legacy/intermediate_fw: reboot from RAM * legacy/intermediate_fw: flash erase from RAM * legacy/intermediate_fw: port flash erase body from cm3 * legacy/intermediate_fw: erase works with flash unlock * legacy/intermediate_fw: wait for flash controller ready * legacy/intermediate_fw: cleanup and add comments * legacy/intermediate_fw: disable IRQ before reboot * legacy/intermediate_fw: also erase storage * legacy/intermediate_fw: style * legacy/intermediate_fw: dialogs for update bootloader/erase FW * legacy/intermediate_fw: style * legacy/intermediate_fw: add bootloader replacement code * legacy/intermediate_fw: add CI build script for intermediate FW * legacy/intermediate_fw: call bootloader update * legacy/intermediate_fw: add bootloader update dependency * legacy/intermediate_fw: change setup() at start of main * legacy/intermediate_fw: deduplicate code * docs: table for MEMORY_PROTECT combinations that work on T1 * legacy/intermediate_fw: deduplicate code * legacy/intermediate_fw: check if running in privileged mode * legacy/intermediate_fw: style * legacy/intermediate_fw: ChangeLog * legacy/intermediate_fw: make version match latest bootloader included * legacy/intermediate_fw: style
This commit is contained in:
parent
21b4c5b60e
commit
ff3b10a329
@ -105,3 +105,21 @@ Switch your device to bootloader mode, then execute:
|
||||
```sh
|
||||
trezorctl firmware-update -f build/legacy/firmware/trezor.bin
|
||||
```
|
||||
|
||||
## Combining bootloader and firmware with various `MEMORY_PROTECT` settings, signed/unsigned
|
||||
|
||||
Not all combinations of bootloader and firmware will work. This depends on
|
||||
3 variables: MEMORY_PROTECT of bootloader, MEMORY_PROTECT of firmware, whether firmware is signed
|
||||
|
||||
This table shows the result for bootloader 1.8.0+ and 1.9.1+:
|
||||
|
||||
| Bootloader MEMORY_PROTECT | Firmware MEMORY_PROTECT | Is firmware officially signed? | Result |
|
||||
| ------------------------- | ----------------------- | ------------------------------ | ------------------------------------------------------------------------------------------ |
|
||||
| 1 | 1 | yes | works, official configuration |
|
||||
| 1 | 1 | no | hardfault in header.S when setting VTOR and stack |
|
||||
| 0 | 1 | no | works, but don't forget to comment out `check_bootloader`, otherwise it'll get overwritten |
|
||||
| 0 | 0 | no | hard fault because header.S doesn't set VTOR and stack right |
|
||||
| 1 | 0 | no | works |
|
||||
|
||||
The other three possibilities with signed firmware and `MEMORY_PROTECT!=0` for bootloader/firmware don't exist.
|
||||
|
||||
|
@ -130,7 +130,13 @@ static int known_bootloader(int r, const uint8_t *hash) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void check_bootloader(void) {
|
||||
/**
|
||||
* If bootloader is older and known, replace with newer bootloader.
|
||||
* If bootloader is unknown, halt with error message.
|
||||
*
|
||||
* @param shutdown_on_success: if true, shuts down device instead of return
|
||||
*/
|
||||
void check_bootloader(bool shutdown_on_success) {
|
||||
#if MEMORY_PROTECT
|
||||
uint8_t hash[32] = {0};
|
||||
int r = memory_bootloader_hash(hash);
|
||||
@ -178,11 +184,13 @@ void check_bootloader(void) {
|
||||
// check whether the write was OK
|
||||
r = memory_bootloader_hash(hash);
|
||||
if (r == 32 && 0 == memcmp(hash, bl_hash, 32)) {
|
||||
// OK -> show info and halt
|
||||
layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Update finished"),
|
||||
_("successfully."), NULL, _("Please reconnect"),
|
||||
_("the device."), NULL);
|
||||
shutdown();
|
||||
if (shutdown_on_success) {
|
||||
// OK -> show info and halt
|
||||
layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Update finished"),
|
||||
_("successfully."), NULL, _("Please reconnect"),
|
||||
_("the device."), NULL);
|
||||
shutdown();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -192,4 +200,6 @@ void check_bootloader(void) {
|
||||
_("contact our support."), NULL);
|
||||
shutdown();
|
||||
#endif
|
||||
// prevent compiler warning when MEMORY_PROTECT==0
|
||||
(void)shutdown_on_success;
|
||||
}
|
||||
|
@ -20,6 +20,8 @@
|
||||
#ifndef __BL_CHECK_H__
|
||||
#define __BL_CHECK_H__
|
||||
|
||||
void check_bootloader(void);
|
||||
#include <stdbool.h>
|
||||
|
||||
void check_bootloader(bool shutdown_on_success);
|
||||
|
||||
#endif
|
||||
|
@ -123,7 +123,7 @@ int main(void) {
|
||||
// unpredictable stack protection checks
|
||||
oledInit();
|
||||
#else
|
||||
check_bootloader();
|
||||
check_bootloader(true);
|
||||
setupApp();
|
||||
__stack_chk_guard = random32(); // this supports compiler provided
|
||||
// unpredictable stack protection checks
|
||||
|
28
legacy/intermediate_fw/ChangeLog
Normal file
28
legacy/intermediate_fw/ChangeLog
Normal file
@ -0,0 +1,28 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
|
||||
### Security
|
||||
|
||||
------------
|
||||
|
||||
### Older changelog:
|
||||
|
||||
Version 1.8.0 [Jun 2020]
|
||||
* Initial version of intermediate firmware
|
||||
* Updates bootloader to 1.8.0
|
||||
* Deletes storage and the intermediate firmware code
|
||||
* Version of intermediate firmware matches bootloader version included
|
||||
|
60
legacy/intermediate_fw/Makefile
Normal file
60
legacy/intermediate_fw/Makefile
Normal file
@ -0,0 +1,60 @@
|
||||
APPVER = 1.8.0
|
||||
|
||||
NAME = trezor
|
||||
|
||||
OBJS += trezor.o
|
||||
OBJS += header.o
|
||||
OBJS += bl_check.o
|
||||
OBJS += ../vendor/trezor-crypto/memzero.o
|
||||
OBJS += ../vendor/trezor-crypto/sha2.o
|
||||
|
||||
OPTFLAGS ?= -Og
|
||||
|
||||
|
||||
../vendor/trezor-crypto/bip32.o: OPTFLAGS = -O3
|
||||
../vendor/trezor-crypto/bip39.o: OPTFLAGS = -O3
|
||||
../vendor/trezor-crypto/ecdsa.o: OPTFLAGS = -O3
|
||||
../vendor/trezor-crypto/sha2.o: OPTFLAGS = -O3
|
||||
../vendor/trezor-crypto/secp256k1.o: OPTFLAGS = -O3
|
||||
|
||||
include ../Makefile.include
|
||||
CFLAGS:=$(filter-out -fstack-protector-all,$(CFLAGS))
|
||||
|
||||
DEBUG_LINK ?= 0
|
||||
DEBUG_LOG ?= 0
|
||||
|
||||
CFLAGS += -Wno-sequence-point
|
||||
CFLAGS += -I../vendor/nanopb -Iprotob -DPB_FIELD_16BIT=1 -DPB_ENCODE_ARRAYS_UNPACKED=1 -DPB_VALIDATE_UTF8=1
|
||||
CFLAGS += -DDEBUG_LINK=$(DEBUG_LINK)
|
||||
CFLAGS += -DDEBUG_LOG=$(DEBUG_LOG)
|
||||
CFLAGS += -DSCM_REVISION='"$(shell git rev-parse HEAD | sed 's:\(..\):\\x\1:g')"'
|
||||
CFLAGS += -DUSE_MONERO=0
|
||||
ifneq ($(BITCOIN_ONLY),1)
|
||||
CFLAGS += -DUSE_ETHEREUM=1
|
||||
CFLAGS += -DUSE_NEM=1
|
||||
MAKO_RENDER_FLAG =
|
||||
else
|
||||
CFLAGS += -DUSE_ETHEREUM=0
|
||||
CFLAGS += -DUSE_NEM=0
|
||||
MAKO_RENDER_FLAG = --bitcoin-only
|
||||
endif
|
||||
|
||||
%:: %.mako defs
|
||||
@printf " MAKO $@\n"
|
||||
$(Q)$(PYTHON) ../vendor/trezor-common/tools/cointool.py render $(MAKO_RENDER_FLAG) $@.mako
|
||||
|
||||
bl_data.h: bl_data.py bootloader.dat
|
||||
@printf " PYTHON bl_data.py\n"
|
||||
$(Q)$(PYTHON) bl_data.py
|
||||
|
||||
clean::
|
||||
rm -f bl_data.h
|
||||
find -maxdepth 1 -name "*.mako" | sed 's/.mako$$//' | xargs rm -f
|
||||
|
||||
FIRMWARE_T1_START = 0x08010000
|
||||
flash_intermediate_fw: trezor.bin
|
||||
openocd -f interface/stlink-v2.cfg -c "transport select hla_swd" -f target/stm32f2x.cfg -c "init; reset halt; flash write_image erase $< $(FIRMWARE_T1_START); exit"
|
||||
|
||||
openocd_reset:
|
||||
$(OPENOCD) -c "init; reset; exit"
|
||||
|
1
legacy/intermediate_fw/bl_check.c
Symbolic link
1
legacy/intermediate_fw/bl_check.c
Symbolic link
@ -0,0 +1 @@
|
||||
../firmware/bl_check.c
|
1
legacy/intermediate_fw/bl_check.h
Symbolic link
1
legacy/intermediate_fw/bl_check.h
Symbolic link
@ -0,0 +1 @@
|
||||
../firmware/bl_check.h
|
1
legacy/intermediate_fw/bl_data.py
Symbolic link
1
legacy/intermediate_fw/bl_data.py
Symbolic link
@ -0,0 +1 @@
|
||||
../firmware/bl_data.py
|
1
legacy/intermediate_fw/bootloader.dat
Symbolic link
1
legacy/intermediate_fw/bootloader.dat
Symbolic link
@ -0,0 +1 @@
|
||||
../firmware/bootloader.dat
|
1
legacy/intermediate_fw/gettext.h
Symbolic link
1
legacy/intermediate_fw/gettext.h
Symbolic link
@ -0,0 +1 @@
|
||||
../firmware/gettext.h
|
1
legacy/intermediate_fw/header.S
Symbolic link
1
legacy/intermediate_fw/header.S
Symbolic link
@ -0,0 +1 @@
|
||||
../firmware/header.S
|
125
legacy/intermediate_fw/trezor.c
Normal file
125
legacy/intermediate_fw/trezor.c
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2014 Pavol Rusnak <stick@satoshilabs.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "trezor.h"
|
||||
#include <libopencm3/stm32/desig.h>
|
||||
#include <libopencm3/stm32/flash.h>
|
||||
#include <vendor/libopencm3/include/libopencmsis/core_cm3.h>
|
||||
#include "bitmaps.h"
|
||||
#include "bl_check.h"
|
||||
#include "layout.h"
|
||||
#include "memory.h"
|
||||
#include "memzero.h"
|
||||
#include "oled.h"
|
||||
#include "rng.h"
|
||||
#include "setup.h"
|
||||
#include "timer.h"
|
||||
#include "util.h"
|
||||
|
||||
/** Sector erase operation extracted from libopencm3 - flash_erase_sector
|
||||
* so it can run from RAM
|
||||
*/
|
||||
static void __attribute__((noinline, section(".data")))
|
||||
erase_sector(uint8_t sector, uint32_t psize) {
|
||||
// Wait for flash controller to be ready
|
||||
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
|
||||
;
|
||||
// Set program word width
|
||||
FLASH_CR &= ~(FLASH_CR_PROGRAM_MASK << FLASH_CR_PROGRAM_SHIFT);
|
||||
FLASH_CR |= psize << FLASH_CR_PROGRAM_SHIFT;
|
||||
|
||||
/* Sector numbering is not contiguous internally! */
|
||||
if (sector >= 12) {
|
||||
sector += 4;
|
||||
}
|
||||
|
||||
FLASH_CR &= ~(FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT);
|
||||
FLASH_CR |= (sector & FLASH_CR_SNB_MASK) << FLASH_CR_SNB_SHIFT;
|
||||
FLASH_CR |= FLASH_CR_SER;
|
||||
FLASH_CR |= FLASH_CR_STRT;
|
||||
|
||||
// Wait for flash controller to be ready
|
||||
while ((FLASH_SR & FLASH_SR_BSY) == FLASH_SR_BSY)
|
||||
;
|
||||
FLASH_CR &= ~FLASH_CR_SER;
|
||||
FLASH_CR &= ~(FLASH_CR_SNB_MASK << FLASH_CR_SNB_SHIFT);
|
||||
}
|
||||
|
||||
static void __attribute__((noinline, section(".data")))
|
||||
erase_firmware_and_storage(void) {
|
||||
// Flash unlock
|
||||
FLASH_KEYR = FLASH_KEYR_KEY1;
|
||||
FLASH_KEYR = FLASH_KEYR_KEY2;
|
||||
|
||||
// Erase storage sectors to prevent firmware downgrade to vulnerable version
|
||||
for (int i = FLASH_STORAGE_SECTOR_FIRST; i <= FLASH_STORAGE_SECTOR_LAST;
|
||||
i++) {
|
||||
erase_sector(i, FLASH_CR_PROGRAM_X32);
|
||||
}
|
||||
|
||||
// Erase firmware sectors
|
||||
for (int i = FLASH_CODE_SECTOR_FIRST; i <= FLASH_CODE_SECTOR_LAST; i++) {
|
||||
erase_sector(i, FLASH_CR_PROGRAM_X32);
|
||||
}
|
||||
|
||||
// Flash lock
|
||||
FLASH_CR |= FLASH_CR_LOCK;
|
||||
}
|
||||
|
||||
void __attribute__((noinline, noreturn, section(".data"))) reboot_device(void) {
|
||||
__disable_irq();
|
||||
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
/** Entry point of RAM shim that deletes old FW, storage and reboot */
|
||||
void __attribute__((noinline, noreturn, section(".data")))
|
||||
erase_fw_and_reboot(void) {
|
||||
erase_firmware_and_storage();
|
||||
reboot_device();
|
||||
|
||||
for (;;)
|
||||
; // never reached, but compiler would generate error
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
setupApp();
|
||||
__stack_chk_guard = random32(); // this supports compiler provided
|
||||
// unpredictable stack protection checks
|
||||
oledInit();
|
||||
if (is_mode_unprivileged()) {
|
||||
layoutDialog(&bmp_icon_warning, NULL, NULL, NULL, "Cannot update", NULL,
|
||||
NULL, "Unprivileged mode", "Unsigned firmware", NULL);
|
||||
shutdown();
|
||||
}
|
||||
|
||||
mpu_config_off(); // needed for flash writable, RAM RWX
|
||||
timer_init();
|
||||
check_bootloader(false);
|
||||
|
||||
layoutDialog(&bmp_icon_warning, NULL, NULL, NULL, "Erasing old data", NULL,
|
||||
NULL, "DO NOT UNPLUG", "YOUR TREZOR!", NULL);
|
||||
oledRefresh();
|
||||
|
||||
// from this point the execution is from RAM instead of flash
|
||||
erase_fw_and_reboot();
|
||||
|
||||
return 0;
|
||||
}
|
40
legacy/intermediate_fw/trezor.h
Normal file
40
legacy/intermediate_fw/trezor.h
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (C) 2014 Pavol Rusnak <stick@satoshilabs.com>
|
||||
*
|
||||
* This library is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __TREZOR_H__
|
||||
#define __TREZOR_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "version.h"
|
||||
|
||||
#define STR(X) #X
|
||||
#define VERSTR(X) STR(X)
|
||||
|
||||
#ifndef DEBUG_LINK
|
||||
#define DEBUG_LINK 0
|
||||
#endif
|
||||
|
||||
#ifndef DEBUG_LOG
|
||||
#define DEBUG_LOG 0
|
||||
#endif
|
||||
|
||||
/* Screen timeout */
|
||||
extern uint32_t system_millis_lock_start;
|
||||
|
||||
#endif
|
8
legacy/intermediate_fw/version.h
Normal file
8
legacy/intermediate_fw/version.h
Normal file
@ -0,0 +1,8 @@
|
||||
// Matches the bootloader version included in this firmware
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 8
|
||||
#define VERSION_PATCH 0
|
||||
|
||||
#define FIX_VERSION_MAJOR 1
|
||||
#define FIX_VERSION_MINOR 8
|
||||
#define FIX_VERSION_PATCH 0
|
15
legacy/script/cibuild_intermediate_fw
Executable file
15
legacy/script/cibuild_intermediate_fw
Executable file
@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# script/cibuild_intermediate_fw:
|
||||
# Setup environment for CI to build intermediate firmware.
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
make -C vendor/libopencm3 lib/stm32/f2
|
||||
|
||||
make libtrezor.a
|
||||
|
||||
make -C intermediate_fw all sign
|
||||
|
Loading…
Reference in New Issue
Block a user