diff --git a/core/SConscript.bootloader_emu b/core/SConscript.bootloader_emu index a35c95bc9..b479a256a 100644 --- a/core/SConscript.bootloader_emu +++ b/core/SConscript.bootloader_emu @@ -127,6 +127,7 @@ SOURCE_BOOTLOADER = [ ] SOURCE_TREZORHAL = [ + 'embed/trezorhal/unix/boot_args.c', 'embed/trezorhal/unix/display-unix.c', 'embed/trezorhal/unix/flash.c', 'embed/trezorhal/unix/common.c', diff --git a/core/SConscript.unix b/core/SConscript.unix index 2e7cf38cf..b596b5831 100644 --- a/core/SConscript.unix +++ b/core/SConscript.unix @@ -378,6 +378,7 @@ SOURCE_MICROPYTHON = [ ] SOURCE_UNIX = [ + 'embed/trezorhal/unix/boot_args.c', 'embed/trezorhal/unix/translations.c', 'embed/trezorhal/unix/common.c', 'embed/trezorhal/unix/display-unix.c', diff --git a/core/embed/boardloader/main.c b/core/embed/boardloader/main.c index fd147f4e1..1708dcf98 100644 --- a/core/embed/boardloader/main.c +++ b/core/embed/boardloader/main.c @@ -297,7 +297,7 @@ int main(void) { mpu_config_off(); - // g_boot_flag is preserved on STM32U5 + // g_boot_command is preserved on STM32U5 jump_to(BOOTLOADER_START + IMAGE_HEADER_SIZE); return 0; diff --git a/core/embed/boardloader/memory_stm32u5a.ld b/core/embed/boardloader/memory_stm32u5a.ld index 40aea090c..f5947dca9 100644 --- a/core/embed/boardloader/memory_stm32u5a.ld +++ b/core/embed/boardloader/memory_stm32u5a.ld @@ -4,8 +4,8 @@ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x0C004000, LENGTH = 48K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4) - BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4) + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K @@ -44,8 +44,6 @@ sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -g_boot_args = (boot_args_start + 4); -g_boot_flag = boot_args_start; SECTIONS { .vector_table : ALIGN(512) { @@ -104,6 +102,14 @@ SECTIONS { . = ALIGN(4); } >SRAM5 + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS + + /* Hard-coded address for capabilities structure */ .capabilities 0x0C00FF00 : {KEEP(*(.capabilities_section))} } diff --git a/core/embed/bootloader/boot_internal.h b/core/embed/bootloader/boot_internal.h deleted file mode 100644 index b5890382b..000000000 --- a/core/embed/bootloader/boot_internal.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef BOOT_INTERNAL_H -#define BOOT_INTERNAL_H - -#include -#include - -// The 'g_boot_command' variable stores the 'command' passed to the -// function 'svc_reboot_to_bootloader()'. It may be one of the -// 'BOOT_COMMAND_xxx' values defined in the enumeration, or it could -// be any other value that should be treated as a non-special action, -// in which case the bootloader should behave as if the device was -// just powered up. The variable is set before the main() is called. -extern boot_command_t g_boot_command; - -// The 'g_boot_args' array stores extra arguments passed -// function 'svc_reboot_to_bootloader()' -extern uint8_t g_boot_args[BOOT_ARGS_SIZE]; - -#endif // BOOT_INTERNAL_H diff --git a/core/embed/bootloader/emulator.c b/core/embed/bootloader/emulator.c index 36d885a9f..6b089ee39 100644 --- a/core/embed/bootloader/emulator.c +++ b/core/embed/bootloader/emulator.c @@ -2,7 +2,7 @@ #include #include TREZOR_BOARD -#include "boot_internal.h" +#include "boot_args.h" #include "bootui.h" #include "common.h" #include "display.h" @@ -19,11 +19,6 @@ uint8_t *FIRMWARE_START = 0; -// Simulation of a boot command normally grabbed during reset processing -boot_command_t g_boot_command = BOOT_COMMAND_NONE; -// Simulation of a boot args normally sitting at the BOOT_ARGS region -uint8_t g_boot_args[BOOT_ARGS_SIZE]; - void set_core_clock(int) {} int bootloader_main(void); @@ -55,7 +50,7 @@ void usage(void) { printf(" -h show this help\n"); } -bool load_firmware(const char *filename) { +bool load_firmware(const char *filename, uint8_t *hash) { // read the first 6 kB of firmware file into a buffer FILE *file = fopen(filename, "rb"); if (!file) { @@ -87,7 +82,8 @@ bool load_firmware(const char *filename) { BLAKE2S_CTX ctx; blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); blake2s_Update(&ctx, buffer, vhdr.hdrlen + hdr->hdrlen); - blake2s_Final(&ctx, g_boot_args, BLAKE2S_DIGEST_LENGTH); + blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); + return true; } @@ -131,7 +127,7 @@ __attribute__((noreturn)) int main(int argc, char **argv) { while ((opt = getopt(argc, argv, "hslec:b:f:")) != -1) { switch (opt) { case 's': - g_boot_command = BOOT_COMMAND_STOP_AND_WAIT; + bootargs_set(BOOT_COMMAND_STOP_AND_WAIT, NULL, 0); break; case 'e': display_error = true; @@ -145,10 +141,11 @@ __attribute__((noreturn)) int main(int argc, char **argv) { bitcoin_only = atoi(optarg); break; case 'f': - g_boot_command = BOOT_COMMAND_INSTALL_UPGRADE; - if (!load_firmware(optarg)) { + uint8_t hash[BLAKE2S_DIGEST_LENGTH]; + if (!load_firmware(optarg, hash)) { exit(1); } + bootargs_set(BOOT_COMMAND_INSTALL_UPGRADE, hash, sizeof(hash)); break; #ifdef USE_OPTIGA case 'l': diff --git a/core/embed/bootloader/main.c b/core/embed/bootloader/main.c index 677e87bc4..e03e2f6a0 100644 --- a/core/embed/bootloader/main.c +++ b/core/embed/bootloader/main.c @@ -20,7 +20,7 @@ #include #include -#include "boot_internal.h" +#include "boot_args.h" #include "common.h" #include "display.h" #include "display_utils.h" @@ -513,7 +513,7 @@ int bootloader_main(void) { check_bootloader_version(); #endif - switch (g_boot_command) { + switch (bootargs_get_command()) { case BOOT_COMMAND_STOP_AND_WAIT: // firmare requested to stay in bootloader stay_in_bootloader = sectrue; diff --git a/core/embed/bootloader/memory_stm32f4.ld b/core/embed/bootloader/memory_stm32f4.ld index d20e58cec..366280814 100644 --- a/core/embed/bootloader/memory_stm32f4.ld +++ b/core/embed/bootloader/memory_stm32f4.ld @@ -29,7 +29,6 @@ sram_end = ORIGIN(SRAM) + LENGTH(SRAM); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -g_boot_args = boot_args_start; _codelen = SIZEOF(.flash) + SIZEOF(.data); @@ -70,4 +69,9 @@ SECTIONS { . = ALIGN(4); } >SRAM + .boot_args : ALIGN(8) { + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS + } diff --git a/core/embed/bootloader/memory_stm32u5a.ld b/core/embed/bootloader/memory_stm32u5a.ld index 9a0df820d..5a8302696 100644 --- a/core/embed/bootloader/memory_stm32u5a.ld +++ b/core/embed/bootloader/memory_stm32u5a.ld @@ -4,8 +4,8 @@ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x0C010000, LENGTH = 128K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4) - BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4) + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K @@ -44,8 +44,6 @@ sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -g_boot_args = (boot_args_start + 4); -g_boot_flag = boot_args_start; _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive); @@ -104,4 +102,11 @@ SECTIONS { __fb_end = .; . = ALIGN(4); } >SRAM5 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/bootloader/messages.c b/core/embed/bootloader/messages.c index b1e5980cc..dcae07403 100644 --- a/core/embed/bootloader/messages.c +++ b/core/embed/bootloader/messages.c @@ -24,7 +24,7 @@ #include #include "messages.pb.h" -#include "boot_internal.h" +#include "boot_args.h" #include "common.h" #include "flash.h" #include "image.h" @@ -598,7 +598,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, secbool is_ilu = secfalse; // interaction-less update - if (g_boot_command == BOOT_COMMAND_INSTALL_UPGRADE) { + if (bootargs_get_command() == BOOT_COMMAND_INSTALL_UPGRADE) { BLAKE2S_CTX ctx; uint8_t hash[BLAKE2S_DIGEST_LENGTH]; blake2s_Init(&ctx, BLAKE2S_DIGEST_LENGTH); @@ -607,7 +607,7 @@ int process_msg_FirmwareUpload(uint8_t iface_num, uint32_t msg_size, blake2s_Final(&ctx, hash, BLAKE2S_DIGEST_LENGTH); // the firmware must be the same as confirmed by the user - if (memcmp(&g_boot_args[0], hash, sizeof(hash)) != 0) { + if (memcmp(bootargs_get_args()->hash, hash, sizeof(hash)) != 0) { MSG_SEND_INIT(Failure); MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError); MSG_SEND_ASSIGN_STRING(message, "Firmware mismatch"); diff --git a/core/embed/bootloader/startup_stm32f4.s b/core/embed/bootloader/startup_stm32f4.s index bb2d3ef6c..a1fb0c7e5 100644 --- a/core/embed/bootloader/startup_stm32f4.s +++ b/core/embed/bootloader/startup_stm32f4.s @@ -33,9 +33,9 @@ reset_handler: // subsequent operations, it is not necessary to insert a memory barrier instruction." cpsie f - // r11 contains argument passed to reboot_to_bootloader() + // r11 contains the command passed to bootargs_set() // function called when the firmware rebooted to the bootloader - ldr r0, =g_boot_command + ldr r0, =g_boot_command_shadow str r11, [r0] // enter the application code @@ -43,12 +43,5 @@ reset_handler: b shutdown_privileged - .bss - - .global g_boot_command -g_boot_command: - .word 0 - - .end diff --git a/core/embed/bootloader/startup_stm32u5.s b/core/embed/bootloader/startup_stm32u5.s index 858f2694f..f31dabc52 100644 --- a/core/embed/bootloader/startup_stm32u5.s +++ b/core/embed/bootloader/startup_stm32u5.s @@ -49,12 +49,12 @@ reset_handler: ldr r1, = __stack_chk_guard str r0, [r1] - // - ldr r0, =g_boot_flag - ldr r1, [r0] + // copy & clear g_boot_command ldr r0, =g_boot_command + ldr r1, [r0] + ldr r0, =g_boot_command_shadow str r1, [r0] - ldr r0, =g_boot_flag + ldr r0, =g_boot_command mov r1, #0 str r1, [r0] @@ -69,10 +69,4 @@ reset_handler: b shutdown_privileged - .bss - - .global g_boot_command -g_boot_command: - .word 0 - .end diff --git a/core/embed/bootloader_ci/memory_stm32f4.ld b/core/embed/bootloader_ci/memory_stm32f4.ld index 081bb0511..d66d8bfc3 100644 --- a/core/embed/bootloader_ci/memory_stm32f4.ld +++ b/core/embed/bootloader_ci/memory_stm32f4.ld @@ -69,4 +69,8 @@ SECTIONS { . = ALIGN(4); } >SRAM + .boot_args : ALIGN(8) { + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/bootloader_ci/memory_stm32u5a.ld b/core/embed/bootloader_ci/memory_stm32u5a.ld index 9a0df820d..5a8302696 100644 --- a/core/embed/bootloader_ci/memory_stm32u5a.ld +++ b/core/embed/bootloader_ci/memory_stm32u5a.ld @@ -4,8 +4,8 @@ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x0C010000, LENGTH = 128K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4) - BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4) + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K @@ -44,8 +44,6 @@ sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -g_boot_args = (boot_args_start + 4); -g_boot_flag = boot_args_start; _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive); @@ -104,4 +102,11 @@ SECTIONS { __fb_end = .; . = ALIGN(4); } >SRAM5 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/bootloader_ci/startup_stm32u5.s b/core/embed/bootloader_ci/startup_stm32u5.s index 858f2694f..ef0bb95a5 100644 --- a/core/embed/bootloader_ci/startup_stm32u5.s +++ b/core/embed/bootloader_ci/startup_stm32u5.s @@ -49,15 +49,6 @@ reset_handler: ldr r1, = __stack_chk_guard str r0, [r1] - // - ldr r0, =g_boot_flag - ldr r1, [r0] - ldr r0, =g_boot_command - str r1, [r0] - ldr r0, =g_boot_flag - mov r1, #0 - str r1, [r0] - // re-enable exceptions // according to "ARM Cortex-M Programming Guide to Memory Barrier Instructions" Application Note 321, section 4.7: // "If it is not necessary to ensure that a pended interrupt is recognized immediately before @@ -69,10 +60,4 @@ reset_handler: b shutdown_privileged - .bss - - .global g_boot_command -g_boot_command: - .word 0 - .end diff --git a/core/embed/extmod/modtrezorutils/modtrezorutils.c b/core/embed/extmod/modtrezorutils/modtrezorutils.c index 00110718e..b0ce35e48 100644 --- a/core/embed/extmod/modtrezorutils/modtrezorutils.c +++ b/core/embed/extmod/modtrezorutils/modtrezorutils.c @@ -286,7 +286,8 @@ STATIC mp_obj_t mod_trezorutils_reboot_to_bootloader(size_t n_args, mp_get_buffer_raise(args[1], &boot_args, MP_BUFFER_READ); } - svc_reboot_to_bootloader(boot_command, boot_args.buf, boot_args.len); + bootargs_set(boot_command, boot_args.buf, boot_args.len); + svc_reboot_to_bootloader(); #endif return mp_const_none; } diff --git a/core/embed/firmware/memory_DISC2.ld b/core/embed/firmware/memory_DISC2.ld index d5f81ce6d..e28dd7941 100644 --- a/core/embed/firmware/memory_DISC2.ld +++ b/core/embed/firmware/memory_DISC2.ld @@ -4,8 +4,8 @@ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4) - BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4) + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K @@ -44,8 +44,6 @@ sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -g_boot_args = (boot_args_start + 4); -g_boot_flag = boot_args_start; _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive); _flash_start = ORIGIN(FLASH); @@ -120,4 +118,11 @@ SECTIONS { __fb_end = .; . = ALIGN(4); } >SRAM5 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/firmware/memory_T.ld b/core/embed/firmware/memory_T.ld index d0a489b4c..8f65dd6c1 100644 --- a/core/embed/firmware/memory_T.ld +++ b/core/embed/firmware/memory_T.ld @@ -26,7 +26,6 @@ ccmram_end = ORIGIN(CCMRAM) + LENGTH(CCMRAM); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -g_boot_args = boot_args_start; /* used by the startup code to wipe memory */ sram_start = ORIGIN(SRAM); @@ -97,4 +96,9 @@ SECTIONS { *(.no_dma_buffers*); . = ALIGN(4); } >CCMRAM + + .boot_args : ALIGN(8) { + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/prodtest/memory_stm32f4.ld b/core/embed/prodtest/memory_stm32f4.ld index 0bc567ca2..61f7112ba 100644 --- a/core/embed/prodtest/memory_stm32f4.ld +++ b/core/embed/prodtest/memory_stm32f4.ld @@ -74,4 +74,9 @@ SECTIONS { .stack : ALIGN(8) { . = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */ } >SRAM + + .boot_args : ALIGN(8) { + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/prodtest/memory_stm32u5a.ld b/core/embed/prodtest/memory_stm32u5a.ld index 82e177b7a..0b487d350 100644 --- a/core/embed/prodtest/memory_stm32u5a.ld +++ b/core/embed/prodtest/memory_stm32u5a.ld @@ -4,8 +4,8 @@ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4) - BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4) + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K @@ -44,9 +44,6 @@ sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -g_boot_args = (boot_args_start + 4); -g_boot_flag= boot_args_start; - _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive); _flash_start = ORIGIN(FLASH); _flash_end = ORIGIN(FLASH) + LENGTH(FLASH); @@ -120,4 +117,11 @@ SECTIONS { __fb_end = .; . = ALIGN(4); } >SRAM5 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/reflash/memory_stm32f4.ld b/core/embed/reflash/memory_stm32f4.ld index 89b38a8ba..718b00938 100644 --- a/core/embed/reflash/memory_stm32f4.ld +++ b/core/embed/reflash/memory_stm32f4.ld @@ -73,4 +73,9 @@ SECTIONS { .stack : ALIGN(8) { . = 4K; /* this acts as a build time assertion that at least this much memory is available for stack use */ } >SRAM + + .boot_args : ALIGN(8) { + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/reflash/memory_stm32u5a.ld b/core/embed/reflash/memory_stm32u5a.ld index a57655ac3..55bda2ff3 100644 --- a/core/embed/reflash/memory_stm32u5a.ld +++ b/core/embed/reflash/memory_stm32u5a.ld @@ -4,8 +4,8 @@ ENTRY(reset_handler) MEMORY { FLASH (rx) : ORIGIN = 0x0C050000, LENGTH = 3648K - SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - (0x100 + 4) - BOOT_ARGS (wal) : ORIGIN = 0x300BFEFC, LENGTH = (0x100 + 4) + SRAM1 (wal) : ORIGIN = 0x30000000, LENGTH = 768K - 0x100 + BOOT_ARGS (wal) : ORIGIN = 0x300BFF00, LENGTH = 0x100 SRAM2 (wal) : ORIGIN = 0x300C0000, LENGTH = 64K SRAM3 (wal) : ORIGIN = 0x300D0000, LENGTH = 832K SRAM5 (wal) : ORIGIN = 0x301A0000, LENGTH = 832K @@ -44,8 +44,6 @@ sram6_end = ORIGIN(SRAM6) + LENGTH(SRAM6); /* reserve 256 bytes for bootloader arguments */ boot_args_start = ORIGIN(BOOT_ARGS); boot_args_end = ORIGIN(BOOT_ARGS) + LENGTH(BOOT_ARGS); -g_boot_args = (boot_args_start + 4); -g_boot_flag = boot_args_start; _codelen = SIZEOF(.flash) + SIZEOF(.data) + SIZEOF(.sensitive); _flash_start = ORIGIN(FLASH); @@ -120,4 +118,11 @@ SECTIONS { __fb_end = .; . = ALIGN(4); } >SRAM5 + + .boot_args : ALIGN(8) { + *(.boot_command*); + . = ALIGN(8); + *(.boot_args*); + . = ALIGN(8); + } >BOOT_ARGS } diff --git a/core/embed/trezorhal/boot_args.h b/core/embed/trezorhal/boot_args.h index d9ccd09e3..4236a42ae 100644 --- a/core/embed/trezorhal/boot_args.h +++ b/core/embed/trezorhal/boot_args.h @@ -1,6 +1,9 @@ #ifndef TREZORHAL_BOOT_ARGS_H #define TREZORHAL_BOOT_ARGS_H +#include +#include + // Defines boot command for 'svc_reboot_to_bootloader()' function typedef enum { // Normal boot sequence @@ -11,8 +14,26 @@ typedef enum { BOOT_COMMAND_INSTALL_UPGRADE = 0xFA4A5C8D, } boot_command_t; -// Maximum size of extra arguments passed to -// 'svc_reboot_to_bootloader()' function -#define BOOT_ARGS_SIZE 256 +// Maximum size boot_args array +#define BOOT_ARGS_MAX_SIZE (256 - 8) + +typedef union { + uint8_t raw[BOOT_ARGS_MAX_SIZE]; + + // firmware header hash, BOOT_COMMAND_INSTALL_UPGRADE + uint8_t hash[32]; + +} boot_args_t; + +// Sets boot command and arguments for the next reboot +// arguments have too respect boot_args_t structure layout +// (function can be called multiple times before reboting) +void bootargs_set(boot_command_t command, const void* args, size_t args_size); + +// Returns the last boot command set by bootargs_set_command() +boot_command_t bootargs_get_command(); + +// Returns the pointer to boot arguments +const boot_args_t* bootargs_get_args(); #endif // TREZORHAL_BOOT_ARGS_H diff --git a/core/embed/trezorhal/stm32f4/boot_args.c b/core/embed/trezorhal/stm32f4/boot_args.c new file mode 100644 index 000000000..70caf21fc --- /dev/null +++ b/core/embed/trezorhal/stm32f4/boot_args.c @@ -0,0 +1,44 @@ + +#include "../boot_args.h" +#include +#include + +// The 'g_boot_command_shadow' shadows a real boot command passed +// to the bootloader. +// 1. In the bootloader, its value is set in the startup code. +// 2. In the firmware it holds command for the next boot and it is used +// when svc_reboot_to_bootloader() is called +boot_command_t g_boot_command_shadow; + +#ifdef STM32U5 +// The 'g_boot_command' is persistent variable that holds the 'command' +// for the next reboot/jump to the bootloader. Its value is set to +// g_boot_command_shadow when 'svc_reboot_to_bootloader()' is called. +boot_command_t __attribute__((section(".boot_command"))) g_boot_command; +#endif + +// The 'g_boot_args' is persistent array that stores extra arguments passed +// to the function bootargs_set. +static boot_args_t __attribute__((section(".boot_args"))) g_boot_args; + +void bootargs_set(boot_command_t command, const void* args, size_t args_size) { + // save boot command + g_boot_command_shadow = command; + + size_t copy_size = 0; + // copy arguments up to BOOT_ARGS_MAX_SIZE + if (args != NULL && args_size > 0) { + copy_size = MIN(args_size, BOOT_ARGS_MAX_SIZE); + memcpy(&g_boot_args.raw[0], args, copy_size); + } + + // clear rest of boot_args array + size_t clear_size = BOOT_ARGS_MAX_SIZE - copy_size; + if (clear_size > 0) { + memset(&g_boot_args.raw[copy_size], 0, clear_size); + } +} + +boot_command_t bootargs_get_command() { return g_boot_command_shadow; } + +const boot_args_t* bootargs_get_args() { return &g_boot_args; } diff --git a/core/embed/trezorhal/stm32f4/supervise.c b/core/embed/trezorhal/stm32f4/supervise.c index bb23f302d..c1ea8f75a 100644 --- a/core/embed/trezorhal/stm32f4/supervise.c +++ b/core/embed/trezorhal/stm32f4/supervise.c @@ -8,31 +8,11 @@ #ifdef ARM_USER_MODE -// Saves extra parameters for the bootloader -static void _copy_boot_args(const void *args, size_t args_size) { - // symbols imported from the linker script - extern uint8_t g_boot_args; - extern uint8_t boot_args_end; - - uint8_t *p = &g_boot_args; - - if (args != NULL && args_size > 0) { - size_t max_size = &boot_args_end - &g_boot_args; - size_t copy_size = MIN(args_size, max_size); - memcpy(p, args, copy_size); - p += args_size; - } - - if (p < &boot_args_end) { - memset(p, 0, &boot_args_end - p); - } -} - #ifdef STM32U5 -extern uint32_t g_boot_flag; +extern uint32_t g_boot_command; __attribute__((noreturn)) static void _reboot_to_bootloader( boot_command_t boot_command) { - g_boot_flag = boot_command; + g_boot_command = boot_command; __disable_irq(); delete_secrets(); NVIC_SystemReset(); @@ -47,9 +27,8 @@ __attribute__((noreturn)) static void _reboot_to_bootloader( } #endif -void svc_reboot_to_bootloader(boot_command_t boot_command, const void *args, - size_t args_size) { - _copy_boot_args(args, args_size); +void svc_reboot_to_bootloader(void) { + boot_command_t boot_command = bootargs_get_command(); if (is_mode_unprivileged() && !is_mode_handler()) { register uint32_t r0 __asm__("r0") = boot_command; __asm__ __volatile__("svc %0" ::"i"(SVC_REBOOT_TO_BOOTLOADER), "r"(r0) diff --git a/core/embed/trezorhal/stm32f4/supervise.h b/core/embed/trezorhal/stm32f4/supervise.h index 95965ccf0..c4a70650e 100644 --- a/core/embed/trezorhal/stm32f4/supervise.h +++ b/core/embed/trezorhal/stm32f4/supervise.h @@ -68,8 +68,7 @@ static inline void svc_shutdown(void) { } } -void svc_reboot_to_bootloader(boot_command_t boot_command, const void* args, - size_t args_size); +void svc_reboot_to_bootloader(void); static inline uint32_t svc_get_systick_val(void) { if (is_mode_unprivileged() && !is_mode_handler()) { diff --git a/core/embed/trezorhal/stm32u5/boot_args.c b/core/embed/trezorhal/stm32u5/boot_args.c new file mode 120000 index 000000000..ea7e8b6c2 --- /dev/null +++ b/core/embed/trezorhal/stm32u5/boot_args.c @@ -0,0 +1 @@ +../stm32f4/boot_args.c \ No newline at end of file diff --git a/core/embed/trezorhal/unix/boot_args.c b/core/embed/trezorhal/unix/boot_args.c new file mode 100644 index 000000000..b9765d43e --- /dev/null +++ b/core/embed/trezorhal/unix/boot_args.c @@ -0,0 +1,44 @@ + +#include "../boot_args.h" +#include +#include + +// The 'g_boot_command_shadow' variable stores the 'command' for the next +// reboot/jumping to the bootloadeer. It may be one of the +// 'BOOT_COMMAND_xxx' values defined in the enumeration, or it could +// be any other value that should be treated as a non-special action, +// in which case the bootloader should behave as if the device was +// just powered up. + +static boot_command_t g_boot_command_shadow; + +// The 'g_boot_args' array stores extra arguments passed +// function boot_args. It sits at section that persists jump to the bootloader. +static boot_args_t g_boot_args; + +void bootargs_set(boot_command_t command, const void* args, size_t args_size) { + // save boot command + g_boot_command_shadow = command; + + size_t copy_size = 0; + // copy arguments up to BOOT_ARGS_MAX_SIZE + if (args != NULL && args_size > 0) { + copy_size = MIN(args_size, BOOT_ARGS_MAX_SIZE); + memcpy(&g_boot_args.raw[0], args, copy_size); + } + + // clear rest of boot_args array + size_t clear_size = BOOT_ARGS_MAX_SIZE - copy_size; + if (clear_size > 0) { + memset(&g_boot_args.raw[copy_size], 0, clear_size); + } +} + +void bootargs_clear() { + g_boot_command_shadow = BOOT_COMMAND_NONE; + memset(&g_boot_args, 0, sizeof(g_boot_args)); +} + +boot_command_t bootargs_get_command() { return g_boot_command_shadow; } + +const boot_args_t* bootargs_get_args() { return &g_boot_args; } diff --git a/core/site_scons/boards/stm32f4_common.py b/core/site_scons/boards/stm32f4_common.py index 7d881d398..26f489890 100644 --- a/core/site_scons/boards/stm32f4_common.py +++ b/core/site_scons/boards/stm32f4_common.py @@ -40,6 +40,7 @@ def stm32f4_common_files(env, defines, sources, paths): sources += [ "embed/trezorhal/stm32f4/board_capabilities.c", + "embed/trezorhal/stm32f4/boot_args.c", "embed/trezorhal/stm32f4/common.c", "embed/trezorhal/stm32f4/fault_handlers.c", "embed/trezorhal/stm32f4/flash.c", diff --git a/core/site_scons/boards/stm32u5_common.py b/core/site_scons/boards/stm32u5_common.py index c5e74f414..5d3127e6b 100644 --- a/core/site_scons/boards/stm32u5_common.py +++ b/core/site_scons/boards/stm32u5_common.py @@ -49,6 +49,7 @@ def stm32u5_common_files(env, defines, sources, paths): sources += [ "embed/trezorhal/stm32u5/board_capabilities.c", + "embed/trezorhal/stm32u5/boot_args.c", "embed/trezorhal/stm32u5/common.c", "embed/trezorhal/stm32u5/fault_handlers.c", "embed/trezorhal/stm32u5/flash.c",