feat(core): introduce bootloader emulator

pull/2879/head
matejcik 1 year ago
parent af6c6d43ed
commit ae9960ca61

@ -7,7 +7,8 @@ SCONS = scons -Q -j $(JOBS)
BUILD_DIR = build
BOARDLOADER_BUILD_DIR = $(BUILD_DIR)/boardloader
BOOTLOADER_BUILD_DIR = $(BUILD_DIR)/bootloader
BOOTLOADER_CI_BUILD_DIR = $(BUILD_DIR)/bootloader_ci
BOOTLOADER_CI_BUILD_DIR = $(BUILD_DIR)/bootloader_ci
BOOTLOADER_EMU_BUILD_DIR = $(BUILD_DIR)/bootloader_emu
PRODTEST_BUILD_DIR = $(BUILD_DIR)/prodtest
REFLASH_BUILD_DIR = $(BUILD_DIR)/reflash
FIRMWARE_BUILD_DIR = $(BUILD_DIR)/firmware
@ -170,6 +171,9 @@ build_bootloader: ## build bootloader
build_bootloader_ci: ## build CI device testing bootloader
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" $(BOOTLOADER_CI_BUILD_DIR)/bootloader.bin
build_bootloader_emu: ## build the unix bootloader emulator
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" $(BOOTLOADER_EMU_BUILD_DIR)/bootloader.elf
build_prodtest: ## build production test firmware
$(SCONS) CFLAGS="$(CFLAGS)" PRODUCTION="$(PRODUCTION)" TREZOR_MODEL="$(TREZOR_MODEL)" CMAKELISTS="$(CMAKELISTS)" $(PRODTEST_BUILD_DIR)/prodtest.bin

@ -0,0 +1,259 @@
# pylint: disable=E0602
import os
import tools
import boards
TREZOR_MODEL = ARGUMENTS.get('TREZOR_MODEL', 'T')
CMAKELISTS = int(ARGUMENTS.get('CMAKELISTS', 0))
DMA2D = False
if TREZOR_MODEL in ('1', ):
# skip bootloader build
env = Environment()
def build_bootloader(target,source,env):
print(f'Bootloader: nothing to build for Model {TREZOR_MODEL}')
program_bin = env.Command(
target='bootloader.bin',
source=None,
action=build_bootloader
)
Return()
FEATURES_WANTED = ["input", "rgb_led"]
CCFLAGS_MOD = ''
CPPPATH_MOD = []
CPPDEFINES_MOD = []
SOURCE_MOD = []
if TREZOR_MODEL in ('1', 'R'):
FONT_NORMAL='Font_PixelOperator_Regular_8'
FONT_DEMIBOLD=None
FONT_BOLD=None
FONT_MONO='Font_PixelOperatorMono_Regular_8'
if TREZOR_MODEL in ('T', ):
FONT_NORMAL='Font_TTHoves_Regular_21'
FONT_DEMIBOLD=None
FONT_BOLD='Font_TTHoves_Bold_17'
FONT_MONO=None
# modtrezorcrypto
CCFLAGS_MOD += '-Wno-sequence-point '
CPPPATH_MOD += [
'vendor/trezor-crypto',
]
CPPDEFINES_MOD += [
'AES_128',
'AES_192',
'USE_KECCAK',
'ED25519_NO_PRECOMP',
'TREZOR_UI2',
'USE_RUST_LOADER',
'FANCY_FATAL_ERROR'
]
SOURCE_MOD += [
'vendor/trezor-crypto/blake2s.c',
'vendor/trezor-crypto/chacha_drbg.c',
'vendor/trezor-crypto/chacha20poly1305/chacha_merged.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-32bit.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-helpers.c',
'vendor/trezor-crypto/ed25519-donna/curve25519-donna-scalarmult-base.c',
'vendor/trezor-crypto/ed25519-donna/ed25519.c',
'vendor/trezor-crypto/ed25519-donna/ed25519-donna-32bit-tables.c',
'vendor/trezor-crypto/ed25519-donna/ed25519-donna-basepoint-table.c',
'vendor/trezor-crypto/ed25519-donna/ed25519-donna-impl-base.c',
'vendor/trezor-crypto/ed25519-donna/modm-donna-32bit.c',
'vendor/trezor-crypto/memzero.c',
'vendor/trezor-crypto/rand.c',
'vendor/trezor-crypto/sha2.c',
]
# modtrezorui
CPPPATH_MOD += [
'vendor/micropython/lib/uzlib',
]
SOURCE_MOD += [
'embed/extmod/modtrezorui/buffers.c',
'embed/extmod/modtrezorui/colors.c',
'embed/extmod/modtrezorui/display.c',
'embed/extmod/modtrezorui/fonts/fonts.c',
'embed/extmod/modtrezorui/fonts/font_bitmap.c',
'embed/extmod/modtrezorcrypto/rand.c',
'vendor/micropython/lib/uzlib/adler32.c',
'vendor/micropython/lib/uzlib/crc32.c',
'vendor/micropython/lib/uzlib/tinflate.c',
]
SOURCE_NANOPB = [
'vendor/nanopb/pb_common.c',
'vendor/nanopb/pb_decode.c',
'vendor/nanopb/pb_encode.c',
]
SOURCE_BOOTLOADER = [
'embed/bootloader/bootui.c',
'embed/bootloader/main.c',
'embed/bootloader/messages.c',
'embed/bootloader/emulator.c',
'embed/bootloader/protob/messages.pb.c',
]
SOURCE_TREZORHAL = [
'embed/trezorhal/image.c',
]
SOURCE_UNIX = [
'embed/unix/common.c',
'embed/unix/display-unix.c',
'embed/unix/flash.c',
'embed/unix/profile.c',
'embed/unix/random_delays.c',
'embed/unix/rng.c',
'embed/unix/touch/touch.c',
'embed/unix/usb.c',
]
# fonts
tools.add_font('NORMAL', FONT_NORMAL, CPPDEFINES_MOD, SOURCE_MOD)
tools.add_font('BOLD', FONT_BOLD, CPPDEFINES_MOD, SOURCE_MOD)
tools.add_font('DEMIBOLD', FONT_DEMIBOLD, CPPDEFINES_MOD, SOURCE_MOD)
tools.add_font('MONO', FONT_MONO, CPPDEFINES_MOD, SOURCE_MOD)
env = Environment(ENV=os.environ, CFLAGS='%s -DPRODUCTION=%s' % (ARGUMENTS.get('CFLAGS', ''), ARGUMENTS.get('PRODUCTION', '0')))
env.Replace(
CP='cp',
AS='as',
AR='ar',
CC='gcc',
LINK='ld',
SIZE='size',
STRIP='strip',
OBJCOPY='objcopy',
PYTHON='python',
MAKECMAKELISTS='$PYTHON tools/make_cmakelists.py', )
env.Replace(
TREZOR_MODEL=TREZOR_MODEL, )
MODEL_IDENTIFIER = tools.get_model_identifier(TREZOR_MODEL)
MODEL_AS_NUMBER = str(boards.get_hw_model_as_number(MODEL_IDENTIFIER))
env.Replace(
COPT=env.get('ENV').get('OPTIMIZE', '-Os'),
CCFLAGS='$COPT '
'-g3 '
'-nostdlib '
'-std=gnu99 -Wall -Werror -Wpointer-arith -Wno-missing-braces -fno-common '
'-fsingle-precision-constant -fdata-sections -ffunction-sections '
'-ffreestanding '
'-fstack-protector-all '
+ CCFLAGS_MOD,
CPPPATH=[
'embed/rust',
'embed/bootloader',
'embed/bootloader/nanopb',
'embed/bootloader/protob',
'embed/unix',
'embed/extmod/modtrezorui',
'vendor/nanopb',
] + CPPPATH_MOD,
CPPDEFINES=[
'BOOTLOADER',
'TREZOR_EMULATOR',
'HW_MODEL=' + MODEL_AS_NUMBER,
'HW_REVISION=0',
'TREZOR_MODEL_'+TREZOR_MODEL,
'TREZOR_BOARD=\\"board-unix.h\\"',
'PB_FIELD_16BIT',
'PB_ENCODE_ARRAYS_UNPACKED',
'PB_VALIDATE_UTF8',
] + CPPDEFINES_MOD,
ASPPFLAGS='$CFLAGS $CCFLAGS', )
try:
env.ParseConfig('pkg-config --cflags --libs sdl2 SDL2_image')
except OSError:
print("SDL2 not installed, Emulator build is not possible")
env.Replace(
ALLSOURCES=SOURCE_MOD + SOURCE_BOOTLOADER + SOURCE_NANOPB + SOURCE_TREZORHAL + SOURCE_UNIX,
ALLDEFS=tools.get_defs_for_cmake(env['CPPDEFINES']))
cmake_gen = env.Command(
target='CMakeLists.txt',
source='',
action='$MAKECMAKELISTS --sources $ALLSOURCES --dirs $CPPPATH --defs $ALLDEFS',
)
#
# Rust library
#
RUST_TARGET = 'x86_64-unknown-linux-gnu'
RUST_PROFILE = 'release'
RUST_LIB = 'trezor_lib'
RUST_LIBDIR = f'build/bootloader_emu/rust/{RUST_TARGET}/{RUST_PROFILE}'
RUST_LIBPATH = f'{RUST_LIBDIR}/lib{RUST_LIB}.a'
def cargo_build():
# Determine the profile build flags.
if RUST_PROFILE == 'release':
profile = '--release'
else:
profile = ''
if TREZOR_MODEL in ("1",):
features = ["model_t1"]
elif TREZOR_MODEL in ("R",):
features = ["model_tr"]
else:
features = ["model_tt"]
features.append("bitcoin_only")
features.append("ui")
features.append("bootloader")
cargo_opts = [
f'--target={RUST_TARGET}',
f'--target-dir=../../build/bootloader_emu/rust',
'--no-default-features',
'--features ' + ','.join(features),
'-Z build-std=core',
'-Z build-std-features=panic_immediate_abort',
]
return f'cd embed/rust; cargo build {profile} ' + ' '.join(cargo_opts)
rust = env.Command(
target=RUST_LIBPATH,
source='',
action=cargo_build(), )
env.Append(LINKFLAGS=f' -L{RUST_LIBDIR}')
env.Append(LINKFLAGS=f' -l{RUST_LIB}')
env.Append(LINKFLAGS=f' -lm')
#
# Program objects
#
obj_program = []
obj_program += env.Object(source=SOURCE_MOD)
obj_program += env.Object(source=SOURCE_BOOTLOADER)
obj_program += env.Object(source=SOURCE_NANOPB)
obj_program += env.Object(source=SOURCE_TREZORHAL)
obj_program += env.Object(source=SOURCE_UNIX)
program_elf = env.Command(
target='bootloader.elf',
source=obj_program,
action=
'$CC -o $TARGET $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $LINKFLAGS', )
env.Depends(program_elf, rust)
if CMAKELISTS != 0:
env.Depends(program_elf, cmake_gen)

@ -3,6 +3,7 @@
SConscript('SConscript.boardloader', variant_dir='build/boardloader', duplicate=False)
SConscript('SConscript.bootloader', variant_dir='build/bootloader', duplicate=False)
SConscript('SConscript.bootloader_ci', variant_dir='build/bootloader_ci', duplicate=False)
SConscript('SConscript.bootloader_emu', variant_dir='build/bootloader_emu', duplicate=False)
SConscript('SConscript.firmware', variant_dir='build/firmware', duplicate=False)
SConscript('SConscript.prodtest', variant_dir='build/prodtest', duplicate=False)
SConscript('SConscript.reflash', variant_dir='build/reflash', duplicate=False)

@ -0,0 +1 @@
Introduced bootloader emulator.

@ -21,7 +21,11 @@
#include "bootui.h"
#include "display.h"
#ifdef TREZOR_EMULATOR
#include "emulator.h"
#else
#include "mini_printf.h"
#endif
#include "rust_ui.h"
#include "version.h"
@ -187,7 +191,7 @@ void ui_screen_wipe_progress(int pos, int len) {
}
// done UI
void ui_screen_done(int restart_seconds, secbool full_redraw) {
void ui_screen_done(uint8_t restart_seconds, secbool full_redraw) {
const char *str;
char count_str[24];
if (restart_seconds >= 1) {

@ -58,7 +58,7 @@ uint32_t ui_screen_wipe_confirm(void);
void ui_screen_wipe(void);
void ui_screen_wipe_progress(int pos, int len);
void ui_screen_done(int restart_seconds, secbool full_redraw);
void ui_screen_done(uint8_t restart_seconds, secbool full_redraw);
void ui_screen_fail(void);

@ -0,0 +1,48 @@
#include <unistd.h>
#include "common.h"
#include "display.h"
#include "emulator.h"
#include "flash.h"
#include "rust_ui.h"
uint8_t *FIRMWARE_START = 0;
uint32_t stay_in_bootloader_flag;
void set_core_clock(int) {}
int bootloader_main(void);
int main(int argc, char **argv) {
flash_init();
FIRMWARE_START =
(uint8_t *)flash_get_address(FLASH_SECTOR_FIRMWARE_START, 0, 0);
if (argc > 1 && argv[1][0] == 's') {
// Run the firmware
stay_in_bootloader_flag = STAY_IN_BOOTLOADER_FLAG;
}
int retval = bootloader_main();
hal_delay(3000);
exit(retval);
}
void display_set_little_endian(void) {}
void display_reinit(void) {}
void mpu_config_bootloader(void) {}
void mpu_config_off(void) {}
void jump_to(void *addr) {
screen_fatal_error_rust("= bootloader =", "Jumped to firmware", "this is ok");
display_refresh();
hal_delay(3000);
exit(0);
}
void ensure_compatible_settings(void) {}
void main_clean_exit(int code) { exit(code); }

@ -0,0 +1,24 @@
#ifndef __EMULATOR_H__
#define __EMULATOR_H__
#define CLOCK_180_MHZ 0
#define STAY_IN_BOOTLOADER_FLAG 0x0FC35A96
#define mini_snprintf snprintf
#undef FIRMWARE_START
#include <stdint.h>
#include <stdio.h>
extern uint8_t *FIRMWARE_START;
extern uint32_t stay_in_bootloader_flag;
void emulator_poll_events(void);
void set_core_clock(int);
void mpu_config_bootloader(void);
void mpu_config_off(void);
void display_set_little_endian(void);
void jump_to(void *addr);
void ensure_compatible_settings(void);
#endif

@ -21,15 +21,19 @@
#include <sys/types.h>
#include "common.h"
#include "compiler_traits.h"
#include "display.h"
#include "flash.h"
#include "image.h"
#include "mini_printf.h"
#include "mpu.h"
#include "random_delays.h"
#include "secbool.h"
#ifdef TREZOR_EMULATOR
#include "emulator.h"
#else
#include "compiler_traits.h"
#include "mini_printf.h"
#include "mpu.h"
#include "stm32.h"
#endif
#ifdef USE_DMA2D
#include "dma2d.h"
#endif
@ -89,8 +93,12 @@ static void usb_init_all(secbool usb21_landing) {
static const usb_webusb_info_t webusb_info = {
.iface_num = USB_IFACE_NUM,
#ifdef TREZOR_EMULATOR
.emu_port = 21324,
#else
.ep_in = USB_EP_DIR_IN | 0x01,
.ep_out = USB_EP_DIR_OUT | 0x01,
#endif
.subclass = 0,
.protocol = 0,
.max_packet_len = sizeof(rx_buffer),
@ -114,6 +122,9 @@ static usb_result_t bootloader_usb_loop(const vendor_header *const vhdr,
uint8_t buf[USB_PACKET_SIZE];
for (;;) {
#ifdef TREZOR_EMULATOR
emulator_poll_events();
#endif
int r = usb_webusb_read_blocking(USB_IFACE_NUM, buf, USB_PACKET_SIZE,
USB_TIMEOUT);
if (r != USB_PACKET_SIZE) {
@ -248,10 +259,14 @@ static void check_bootloader_version(void) {
#endif
#ifndef TREZOR_EMULATOR
int main(void) {
// grab "stay in bootloader" flag as soon as possible
register uint32_t r11 __asm__("r11");
volatile uint32_t stay_in_bootloader_flag = r11;
#else
int bootloader_main(void) {
#endif
random_delays_init();
// display_init_seq();
@ -339,7 +354,11 @@ int main(void) {
if (touched) {
break;
}
#ifdef TREZOR_EMULATOR
hal_delay(25);
#else
hal_delay(1);
#endif
}
}
#elif defined USE_BUTTON

@ -37,6 +37,10 @@
#include "memzero.h"
#ifdef TREZOR_EMULATOR
#include "emulator.h"
#endif
#define MSG_HEADER1_LEN 9
#define MSG_HEADER2_LEN 1
@ -370,7 +374,7 @@ static bool _read_payload(pb_istream_t *stream, const pb_field_t *field,
void **arg) {
#define BUFSIZE 32768
uint32_t offset = (uint32_t)(*arg);
size_t offset = (size_t)(*arg);
if (stream->bytes_left > IMAGE_CHUNK_SIZE) {
chunk_size = 0;
@ -460,8 +464,8 @@ static void detect_installation(const vendor_header *current_vhdr,
}
static int firmware_upload_chunk_retry = FIRMWARE_UPLOAD_CHUNK_RETRY_COUNT;
static uint32_t headers_offset = 0;
static uint32_t read_offset = 0;
static size_t headers_offset = 0;
static size_t read_offset = 0;
int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size,
uint8_t *buf) {

@ -97,6 +97,7 @@ where
}
display::sync();
frame.paint();
display::refresh();
}
}
}
@ -501,6 +502,7 @@ extern "C" fn screen_install_success(
} else {
screen_install_success_bld(msg, complete_draw)
}
display::refresh();
}
#[no_mangle]

@ -3,4 +3,6 @@
#include "display-unix.h"
#define USE_TOUCH 1
#endif //_BOARD_UNIX_H

@ -0,0 +1 @@
../trezorhal/image.h

@ -23,12 +23,16 @@
#if defined TREZOR_MODEL_T
#include "common.h"
#include "touch.h"
extern int sdl_display_res_x, sdl_display_res_y;
extern int sdl_touch_offset_x, sdl_touch_offset_y;
static bool _touch_detected = false;
uint32_t touch_read(void) {
emulator_poll_events();
SDL_Event event;
SDL_PumpEvents();
if (SDL_PollEvent(&event) > 0) {
@ -56,6 +60,7 @@ uint32_t touch_read(void) {
}
switch (event.type) {
case SDL_MOUSEBUTTONDOWN:
_touch_detected = true;
return TOUCH_START | touch_pack_xy(x, y);
case SDL_MOUSEMOTION:
// remove other SDL_MOUSEMOTION events from queue
@ -65,6 +70,7 @@ uint32_t touch_read(void) {
}
break;
case SDL_MOUSEBUTTONUP:
_touch_detected = false;
return TOUCH_END | touch_pack_xy(x, y);
}
break;
@ -74,6 +80,11 @@ uint32_t touch_read(void) {
return 0;
}
void touch_init(void) {}
void touch_power_on(void) {}
uint32_t touch_is_detected(void) { return _touch_detected; }
#elif defined TREZOR_MODEL_1 || defined TREZOR_MODEL_R
#include "button.h"

Loading…
Cancel
Save