feat(core/bootloader_emu): add option to preload firmware image
What changed, and why it matters
This commit adds a new command-line option to the Trezor bootloader emulator that lets developers pre-load a firmware image into the emulated flash memory before running tests. It is a development/testing convenience feature and does not change the real hardware bootloader or wallet behavior.
No immediate security action required. If reviewing for defensive purposes, verify that the emulator is not shipped to end users and that `FIRMWARE_MAXSIZE` bounds the read appropriately. Consider adding an explicit size check and error message if `read` exceeds the buffer.
Security signals we found
New file-loading path added to bootloader emulator
Firmware image written directly to emulated flash area
No input size validation beyond fixed FIRMWARE_MAXSIZE buffer
No changelog entry (marked [no changelog])
Evidence from the diff
The change introduces a -i IMAGE_FILE flag in core/embed/projects/bootloader/emulator.c. When used, it reads a firmware file into a static buffer, erases the emulated FIRMWARE_AREA, and writes the buffer into flash via flash_area_write_data_padded. The function returns success/failure and exits the emulator on failure. It is only used in the emulator build, not on physical devices.
Changed components
core/embed/projects/bootloader/emulator.cTrezor bootloader emulator (development tool only)Inspect captured patch +24 / −1
diff --git a/core/embed/projects/bootloader/emulator.c b/core/embed/projects/bootloader/emulator.c
index a55bdc00..a4b5f7b4 100644
--- a/core/embed/projects/bootloader/emulator.c
+++ b/core/embed/projects/bootloader/emulator.c
@@ -43,6 +43,7 @@ void usage(void) {
printf(" -e MESSAGE [TITLE [FOOTER]] display error screen and stop\n");
printf(" -c COLOR_VARIANT set color variant\n");
printf(" -b BITCOIN_ONLY set bitcoin only flag\n");
+ printf(" -i IMAGE_FILE path to firmware image file to be used\n");
printf(
" -f FIRMWARE run interaction-less update for the specified image\n");
#ifdef LOCKABLE_BOOTLOADER
@@ -88,6 +89,23 @@ bool load_firmware(const char *filename, uint8_t *hash) {
return true;
}
+bool preload_firmware_image(const char *filename) {
+ static uint8_t fw_buffer[FIRMWARE_MAXSIZE];
+
+ FILE *file = fopen(filename, "rb");
+ if (!file) {
+ printf("Failed to open file '%s'\n", filename);
+ return false;
+ }
+ size_t read = fread(fw_buffer, 1, sizeof(fw_buffer), file);
+ fclose(file);
+
+ flash_area_erase(&FIRMWARE_AREA, NULL);
+
+ return sectrue == flash_area_write_data_padded(&FIRMWARE_AREA, 0, fw_buffer,
+ read, 0x0, FIRMWARE_MAXSIZE);
+}
+
static int sdl_event_filter(void *userdata, SDL_Event *event) {
switch (event->type) {
case SDL_QUIT:
@@ -130,7 +148,7 @@ int main(int argc, char **argv) {
uint8_t set_variant = 0xff;
uint8_t color_variant = 0;
uint8_t bitcoin_only = 0;
- while ((opt = getopt(argc, argv, "hslec:b:f:")) != -1) {
+ while ((opt = getopt(argc, argv, "hslec:b:f:i:")) != -1) {
switch (opt) {
case 's':
bootargs_set(BOOT_COMMAND_STOP_AND_WAIT, NULL, 0);
@@ -146,6 +164,11 @@ int main(int argc, char **argv) {
set_variant = 1;
bitcoin_only = atoi(optarg);
break;
+ case 'i': {
+ if (!preload_firmware_image(optarg)) {
+ exit(1);
+ }
+ } break;
case 'f': {
uint8_t hash[BLAKE2S_DIGEST_LENGTH];
if (!load_firmware(optarg, hash)) {
Why this scored 21/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.