|
CycloneBOOT 2.6.6
Secure Bootloader for ARM Cortex-M MCU
|
The quickest way to use CycloneBOOT is to run a demo on a board, then copy its structure into your project. Every demo folder builds on its own and carries a README.md with the steps to build, flash and send an update.
Every release is available from https://www.oryx-embedded.com/download/CycloneBOOT.html in two versions, each with the full source code, the demos and ImageBuilder:
A build stops with an error until the licence terms are accepted: define GPL_LICENSE_TERMS_ACCEPTED (Open) or EVAL_LICENSE_TERMS_ACCEPTED (Eval), for example in the os_port_config.h of each project.
arm-none-eabi-gcc), CMake 3.25 or newer, Ninjatools/ImageBuilder/bin/ (Linux and Windows); the demo builds call itPick the update mode (see Secure Bootloader and Firmware Update), then a demo folder demo/<vendor>/<board>/<mode>/. The NUCLEO-G474RE has a demo for each of the three modes over UART/Y-Modem, through the ST-LINK virtual COM port, with no extra hardware.
Each project builds from its own folder:
Flash addresses, UART pins and programming commands are in the comment block at the top of each project's src/main.c. The update senders for Y-Modem, TFTP and HTTP are in demo/common/update_protocols/.
ImageBuilder turns the application binary into a CycloneBOOT image: a 64-byte header, the firmware and a check value. It also generates signing keys:
--key-type rsa --key-size 2048|3072|4096 generates an RSA key, --curve p256|p384|p521 selects the ECDSA curve.
The hybrid and standalone demos build two images of the same firmware:
--vtor-align places the firmware 1024 bytes after the start of the slot, so the application is linked at the slot address plus 0x400. It is required with a runtime signature or a runtime hash.--runtime-sign-* embeds the signature the bootloader checks before every start. The bootloader holds the matching public key.--sign-* signs the update image. The application (hybrid) or the bootloader (standalone) holds the matching public key. --integrity-algo or --auth-algo replace it with a hash or an HMAC; one method per image.--vtor-align nor --runtime-sign-*: the application is linked at the bank base.image_builder_linux --help lists every option.
Copy the source list, include paths and compile definitions from the cmake/CMakeLists.txt of the demo closest to your MCU and mode. Each project has a boot_config.h that enables the features, and a crypto_config.h for CycloneCRYPTO.
The application receives the update, writes it to the other bank and resets; the MCU starts from the new bank. Program the option bytes for dual-bank operation first (see the demo src/main.c).
boot_config.h: UPDATE_DUAL_BANK_SUPPORT, plus the verification and decryption switches the update images need (VERIFY_SIGNATURE_SUPPORT with VERIFY_RSA_SUPPORT or VERIFY_ECDSA_SUPPORT, CIPHER_SUPPORT, IMAGE_INPUT_ENCRYPTED).
The application receives the update and stores it in an update slot. On the next reset the bootloader verifies it, decrypts it, installs it over the application, and checks the application before every start.
Bootloader, linked at the flash base:
boot_config.h of the bootloader: BOOT_RUNTIME_SIGNATURE_CHECK_SUPPORT with BOOT_RUNTIME_SIGNATURE_RSA or BOOT_RUNTIME_SIGNATURE_ECDSA for verified boot (or BOOT_RUNTIME_INTEGRITY_CHECK_SUPPORT for a hash only), BOOT_FALLBACK_SUPPORT to return to the previous firmware, BOOT_COUNTER_SUPPORT to fall back after repeated failed starts.
Application, linked at the application slot plus 0x400: the same update calls as in dual-bank mode, with UPDATE_SINGLE_BANK_SUPPORT and the same slot table as the bootloader (slot 0 SLOT_CONTENT_APP). Once the new firmware runs correctly, it confirms itself so that no fallback occurs:
An optional first-stage bootloader, in hybrid_app_bl/1st_stage_bl on the STM32H573I-DK and the NUCLEO-L476RG, sits in front of the bootloader so that the bootloader itself can be updated.
The bootloader receives the update itself. The application only asks for an update:
Bootloader, linked at the flash base:
boot_config.h: at least one update trigger (BOOT_TRIGGER_GPIO, BOOT_TRIGGER_MAILBOX, BOOT_TRIGGER_WINDOW, BOOT_TRIGGER_NO_APP, BOOT_TRIGGER_RESET_CAUSE), and optionally BOOT_RECOVERY_SUPPORT with BOOT_FACTORY_SLOT_SUPPORT to restore a factory image. A new protocol is an UpdateTransport (update/update_transport.h): four callbacks, init, poll, read and close.
For execute-in-place, slot 0 points to the memory-mapped address of the external flash (for example 0x90000000) and its flash driver implements flashActivateXiPMode. See demo/st/stm32h750b_discovery/standalone_bl.
VERIFY_ECDSA_SUPPORT in the boot_config.h of the project that verifies them. Without it, updateInit() fails.IMAGE_OUTPUT_ENCRYPTED) needs a unique initialization vector per image: implement cipherGenerateIv(), for example with the true random number generator of the MCU.CBOOT_TRACE_LEVEL and CBOOT_DRIVER_TRACE_LEVEL in boot_config.h, for example TRACE_LEVEL_INFO.