Skip to content

call bootloader update from coreapp #5227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from

Conversation

TychoVrahe
Copy link
Contributor

@TychoVrahe TychoVrahe commented Jun 18, 2025

This PR changes the way bootloader update is invoked.

Instead of embedding bootloader into secmon/kernel, its embedded in firmware(coreapp), and bootloader update is invoked via syscall + smcall. To keep the security same, additional checks are added to update smcall ( signature and hash check).

New command is added to prodtest, which allows updating the bootloader via VPC. A simple script is added to upload the bootloader data by chunks.

This PR also fixes an issue with double-embedded bootloader when both secmon + kernel is used.

Hash processor is now made secure-only, as it is used for hashing the firmware image header in secmon.

fixes #4168

@TychoVrahe TychoVrahe self-assigned this Jun 18, 2025
@github-project-automation github-project-automation bot moved this to 🔎 Needs review in Firmware Jun 18, 2025
Copy link

github-actions bot commented Jun 18, 2025

core UI changes device test click test persistence test
T2T1 Model T test(screens) main(screens) test(screens) main(screens) test(screens) main(screens)
T3B1 Safe 3 test(screens) main(screens) test(screens) main(screens) test(screens) main(screens)
T3T1 Safe 5 test(screens) main(screens) test(screens) main(screens) test(screens) main(screens)
T3W1 test(screens) main(screens) test(screens) main(screens) test(screens) main(screens)
All main(screens)

@TychoVrahe TychoVrahe force-pushed the tychovrahe/bootloader/update_fw branch 4 times, most recently from 936d0ff to a256faa Compare June 19, 2025 07:37
@TychoVrahe TychoVrahe force-pushed the tychovrahe/bootloader/update_fw branch from a256faa to 35c37af Compare June 19, 2025 18:31
@TychoVrahe TychoVrahe marked this pull request as ready for review June 20, 2025 08:14
@TychoVrahe TychoVrahe requested review from cepetr and Copilot and removed request for prusnak June 20, 2025 08:14
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors bootloader updates to be invoked from the coreapp via new syscalls/smcalls, adds signature and hash checks to maintain security, introduces a prodtest command and Python tool for chunked bootloader uploads, and removes duplicate bootloader embedding while restricting the hash processor to secure-only builds.

  • Added util/bl_check module for verifying and replacing bootloader images.
  • Exposed new syscalls/smcalls (BL_CHECK_CHECK and BL_CHECK_REPLACE) and integrated them into dispatch and stubs.
  • Created core/tools/bld_update.py for CLI-driven USB-VCP bootloader uploads and updated prodtest to drive it.

Reviewed Changes

Copilot reviewed 45 out of 45 changed files in this pull request and generated 2 comments.

File Description
core/tools/bld_update.py New Python CLI tool to compress and upload bootloader
core/embed/util/bl_check/inc/util/bl_check.h Declares bl_check_check/bl_check_replace APIs
core/embed/sys/syscall/stm32/syscall_verifiers.c Adds verification stub for bl_check_replace syscall
core/SConscript.firmware Embeds compressed bootloader in firmware linker rules
Comments suppressed due to low confidence (3)

core/embed/util/bl_check/inc/util/bl_check.h:33

  • [nitpick] The function name bl_check_check is redundant and unclear. Consider renaming it to something more descriptive, such as bl_update_needed or bootloader_needs_update.
bool bl_check_check(void);

core/embed/projects/prodtest/cmd/prodtest_bootloader.c:62

  • This new prodtest_bootloader_update command implements significant logic but lacks dedicated tests. Consider adding unit or integration tests to validate correct behavior across begin/chunk/end phases and error conditions.
static void prodtest_bootloader_update(cli_t *cli) {

core/SConscript.firmware:911

  • [nitpick] Embedding the bootloader binary is now duplicated in multiple SConscript files. Consider centralizing this logic or defining a helper to reduce duplication and ease future updates.
tools.embed_compressed_binary(

@@ -64,6 +64,19 @@ void sysevents_poll__verified(const sysevents_t *awaited,

// ---------------------------------------------------------------------

void bl_check_replace__verified(const uint8_t *data, size_t len) {
Copy link
Preview

Copilot AI Jun 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a bounds check on len (e.g., len <= BOOTLOADER_MAXSIZE) before calling into bl_check_replace to prevent oversized input from causing buffer overflows.

Suggested change
void bl_check_replace__verified(const uint8_t *data, size_t len) {
void bl_check_replace__verified(const uint8_t *data, size_t len) {
if (len > BOOTLOADER_MAXSIZE) {
goto access_violation;
}

Copilot uses AI. Check for mistakes.

Comment on lines +54 to +55
hexstr = chunk.hex()
send_cmd(ser, f"bootloader-update chunk {hexstr}")
Copy link
Preview

Copilot AI Jun 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Converting binary data to hex doubles the payload size and CPU cost. Consider using a more efficient binary-to-text encoding (e.g., Base64) or a raw binary transfer protocol if supported.

Suggested change
hexstr = chunk.hex()
send_cmd(ser, f"bootloader-update chunk {hexstr}")
base64str = base64.b64encode(chunk).decode()
send_cmd(ser, f"bootloader-update chunk {base64str}")

Copilot uses AI. Check for mistakes.

);
show(&mut frame, true);
}
fn screen_update() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

making these functions empty looks wrong at first glance
should we drop the whole function, if it is unused (as it seems, from the fact that Caesar / Delicia don't even have it)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All UIs have it and it is called (when bootloader is updating). We might want to implement it with some nice message, but since the update us fast i didnt want to waste my time with thay right now. On Bolt and Delizia this will cause quick fadeout-fadein when updating the bootloader, no effect on Ceasar. Cc also @Hannsek if this is acceptable.

Copy link
Contributor

@matejcik matejcik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

concept ACK
i would like to change the bl_check_check signature, as commented

separately, why do we have to make hash processor secure? that seems generally impractical. can't secmon use an insecure peripheral?


void check_and_replace_bootloader(void) {
#if PRODUCTION || BOOTLOADER_QA
bool bl_check_check(void) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the hash value(s) to check against should come from the caller
because it's the caller who has the replacement data

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed aa979aa

@TychoVrahe
Copy link
Contributor Author

@matejcik sharing the peripheral is tricky, as we'd need to synchronize usage between secure/non-secure world, as each has its own globals which are used for this purpose. While probably possible, the usage outside of secure world is now quite limited that i don't think its worth the effort. Alternatively we could use it through smcalls, but again, i don't think its worth the effort now.

@TychoVrahe
Copy link
Contributor Author

added two more commits

  • RSOD on attempted bootloader downgrade
  • rebooting device after bootloader update

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🔎 Needs review
Development

Successfully merging this pull request may close these issues.

Restart device after upgrading the bootloader
2 participants