From 5405af8c15fde0a512051eadf66bf67ca6ec2b26 Mon Sep 17 00:00:00 2001 From: Wouter Geraedts Date: Tue, 7 Oct 2025 15:50:51 +0200 Subject: [PATCH] Updated README's --- README.md | 83 +++++++++++++++++++++++++++------------ bootloader-tool/README.md | 25 ++++++------ 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 4d6311d..78ac862 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,71 @@ -# ec-slimloader **OUTDATED** +# ec-slimloader -A light-weight stage-two bootloader written in Rust for loading an app image as configured by ec-slimloader-descriptors. Also contains a tool for signing images, flashing them to the device, setting fuses (or shadow registers) containing crypto keys, and an example application to showcase the bootloaders A/B state functionality. +A light-weight bootloader written in Rust with a fail-safe NOR-flash backed state journal. +This framework can run on any platform if support for the platform is implemented. +It is only opinionated with regards to how the state is stored. -Currently this bootloader can only be used on the IMXRT600 series of chipsets from NXP. +Currently only supports the NXP IMXRT685S and IMXRT633S where it acts as a stage-two bootloader and copies the program to application RAM. +Also contains a tool for signing images, flashing them to the device, setting fuses (or shadow registers) containing crypto keys, +and an example application to showcase the bootloaders A/B state functionality for this family of chipsets. ## Organisation -This repository is split up into four parts: -* ec-slimloader: the binary project which forms the second stage bootloader -* ec-slimloader-descriptors: the library crate containing a descriptor of where each image slot exists, as well as a persistent fail-safe state journal for recording the A/B bootloading state. -* bootloader-tool: a command-line utility using the NXP SPSDK tooling to generate keys, sign images, and flash them to the target device. Also integrates probe-rs and allows for attaching to the RTT buffer for displaying `defmt` output. -* example: an example application image that uses the state-journal to select alternative images to execute. +This repository is split up into three parts: +* libs: library crates that implement the core functionality. +* examples/rt685s: example binary applications that be run on the RT685S evaluation kit. +* bootloader-tool: a command-line utility only used to perform operations related to the NXP RT685S platform. + It uses the NXP SPSDK tooling to generate keys, sign images, and flash them to the target device. Also integrates probe-rs and allows for attaching to the RTT buffer for displaying `defmt` output. + This tool is not relevant if you want to use `ec-slimloader` with any other platform. -## Memory layout -This repository has default configuration files detailing the used memory layout. This layout will probably will need to be adapted for your specific usecase. +The libraries are split out as follows: +* ec-slimloader: general library crate providing a basic structure to build your bootloader binary application. +* ec-slimloader-state: library crate with all code relating to managing the state journal. Used by both the bootloader and the application to change which image slot should be booted. +* ec-slimloader-imxrt: library crate implementing support for the NXP IMXRT685S and IMXRT633S. +* imxrt-rom: library crate implementing Rust support for the NXP ROM API which provides access to fuses and allows calling into a verification routine for images. + +## How it works +Assuming your platform is already supported, you can define: +* a region of NOR-flash memory containing at least 2 pages for the bootloader state. +* at least two regions of any memory that will fit an application image. + +Using the library crate for your platform (like `ec-slimloader-imxrt`) you can then implement your own bootloader binary by calling the `start` function in the `ec-slimloader` library crate. + +The `ec-slimloader` crate will handle for you: +* it will read from the state journal what image slot will be booted. +* on subsequent reboots, it will fall back to your defined backup slot if you do not mark your current application image as `confirmed`. + +However, some aspects are handled by the platform support crate (and can differ from project-to-project): +* how application images are loaded. For `ec-slimloader-imxrt` images are copied to RAM in a quite chip-specific way. Typically for other platforms you might want to swap images between on-chip NOR flash and external NOR flash. The latter method is not implemented in this repository (yet). +* how application images are verified. By default the images themselves are not checked at all. `ec-slimloader-imxrt` leverages the native NXP authentication routines to check image integrity. +* how application images are bootloaded, or in other words are jumped to. This differs for cortex-m or RISCV processors. + +Even when using `ec-slimloader-imxrt`, you will still have to implement a few details: +* from what memory is the `ec-slimloader` started, and what memory range is used for the bootloader data? +* which memory regions are mapped to be state journal and mapped to be a image slot 0, 1, etc.? +* what is a valid memory range for the application? + +Finally, your application needs to also work with the state journal to: +* after writing a new application image to a slot, marking that image slot as to be booted in the state journal. +* after rebooting, mark the current image slot from which the application is running as `confirmed`. + If the application does not do this, the bootloader will load the old 'backup' image and mark the current boot as `failed`. + +For a full tour on how to use this framework, please refer to the `examples/rt685s` folder. ## Quick guide This guide details how to use this repository on the NXP MIMXRT685S-EVK. First step is compiling the bootloader and application: ```bash -pushd ec-slimloader +pushd examples/rt685s cargo build --release --features defmt popd -pushd examples/rt685s-application -cargo build --release -popd ``` In general, the bootloader-tool is a `clap` supported CLI application with for each subcommand a full `--help`: ``` +popd bootloader-tool cargo run -- --help - Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s + Compiling bootloader-tool v0.1.0 (ec-slimloader/bootloader-tool) + Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.22s Running `target/debug/bootloader-tool --help` Usage: bootloader-tool [OPTIONS] [COMMAND] @@ -38,7 +73,7 @@ Commands: generate Generate keys and certificates sign Sign binaries for flashing or OTA download Download binaries to the device - run Run binaries, setting the shadow registers, by going through the bootloader chain for testing purposes + run Run binaries by going through the bootloader chain for testing purposes fuse Burn fuse registers with key material and settings help Print this message or the help of the given subcommand(s) @@ -50,41 +85,39 @@ Options: For now we need to prepare our testing setup by generating the key material: ```bash -cd bootloader-tool cargo run -- generate certificates cargo run -- generate otp ``` This key material is only used for testing right now, and everything is put in the `./artifacts` directory. This can be configured in the `./config.toml` file. -We are working on a setup to also support external HSM integration. Now we have everything ready to start flashing. We can use run `run` command to immediately flash and `attach` in the same way you are familiar with from `probe-rs`. However, we need the bootloader to start up the application, and we need the FCB (we call everything in 0x0 to 0x1000 the 'prelude') to start the bootloader. We can extract the FCB from the `ec-slimloader` as it is built with the appropriate feature flags to include a FCB in the ELF file. Extraction happens as a side-product of signing: ```bash -cargo run -- sign bootloader -i ../target/thumbv8m.main-none-eabihf/release/ec-slimloader +cargo run -- sign bootloader -i ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-bootloader ``` We can now flash the FCB: ```bash -cargo run -- download prelude --prelude-path ../target/thumbv8m.main-none-eabihf/release/ec-slimloader.prelude.elf +cargo run -- download prelude --prelude-path ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-bootloader/ec-slimloader.prelude.elf ``` And we can flash the application into *both slots*: ```bash -cargo run -- download application -i ../examples/rt685s-application/target/thumbv8m.main-none-eabihf/release/example-application --slot 0 -cargo run -- download application -i ../examples/rt685s-application/target/thumbv8m.main-none-eabihf/release/example-application --slot 1 +cargo run -- download application -i ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-application --slot 0 --certificate 0 +cargo run -- download application -i ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-application --slot 1 --certificate 0 ``` To flash & attach to the bootloader now run, whilst setting the OTP shadow registers: ```bash -cargo run -- download bootloader -i ../target/thumbv8m.main-none-eabihf/release/ec-slimloader +cargo run -- download bootloader -i ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-bootloader ``` -To flash & attach to the application (TODO it now is not resetting the state journal so take care), assuming you have a and FCB bootloader already flashed: +To flash & attach to the application, assuming you have a bootloader and FCB already flashed: ```bash -cargo run -- run application -i ../examples/rt685s-application/target/thumbv8m.main-none-eabihf/release/example-application +cargo run -- run application -i ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-application ``` You can use the `USER_1` button to change the state journal to either `confirmed` or try the other slot in state `initial` if the current image is already `confirmed`. diff --git a/bootloader-tool/README.md b/bootloader-tool/README.md index 7c5b0d1..ee7be36 100644 --- a/bootloader-tool/README.md +++ b/bootloader-tool/README.md @@ -2,7 +2,7 @@ This binary provides support for signing, downloading and running bootloaders via the secure pathway on the NXP RT6xx family of chips. It automates the signing process, as well as setting up the chip temporarily for running signed binaries. Note: It does not blow any fuses, unless using the `fuse` command, and any boot configuration changes made are erased on a power cycle. -**Note**: the RT6xx chipset enters a FAULT condition when image verification fails. You might need to periodically powercycle your board until the complete chain runs successfully. (TODO why?) +**Note**: the RT6xx chipset enters a FAULT condition when image verification fails in the ROM bootloader. You might need to periodically powercycle your board until the complete chain runs successfully. ## Installation @@ -35,13 +35,13 @@ cargo run -- generate otp Then, assuming you have a bootloader and application ready (see the example folder to quickly build something that runs on the RT685S EVK), you can use the following to flash an application to slot 0: -``` -cargo run -- run application --input-path ./example/application/target/thumbv8m.main-none-eabihf/release/example-application +```bash +cargo run -- run application --input-path ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-application ``` And then flash the bootloader to test that it works: -``` -cargo run -- run bootloader --input-path ./example/bootloader/target/thumbv8m.main-none-eabihf/release/example-bootloader +```bash +cargo run -- run bootloader --input-path ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-bootloader ``` **Note**: initially flashing the application causes the target to lock up, and you might need to powercycle before @@ -52,7 +52,7 @@ running the bootloader. ```bash # Copy in your image mkdir sign_me -cp example/bootloader/target/thumbv8m.main-none-eabihf/release/example-bootloader sign_me/ +cp ../examples/rt685s/target/thumbv8m.main-none-eabihf/release/example-bootloader sign_me/ # Prepare image for signing cargo run -- sign bootloader --input-path sign_me/example-bootloader --dont-sign @@ -75,12 +75,13 @@ This tool takes an input ELF image and: 1. extracts all relevant sections from the given ELF 2. performs checks, such as that the sections are consecutive, not too large, and that the vector table exists on the expected memory address 3. converts the ELF sections into a consecutive binary image -4. calls the SPSDK tooling to package the image as a Master Boot Image in signed and encrypted mode, set to be loaded into RAM -5. checks the integrity of this image -6. (optionally) loads the relevant shadow registers for RTKH (certificate hashes) and OTP (decryption) -7. (optionally) uploads the signed binary to external NOR flash on the address that the 1st stage ROM bootloader -8. (optionally TODO) loads the other sections required like the FCB into external NOR flash -9. (optionally) resets the target device, causing the 2nd stage bootloader to be executed +4. calls the SPSDK tooling to generate a certificate block +5. packages the image as a Master Boot Image in signed and encrypted mode, set to be loaded into RAM (XIP mode but in RAM range) +6. checks the integrity of this image +7. (optionally) loads the relevant shadow registers for RTKH (certificate hashes) and OTP (decryption) +8. (optionally) uploads the signed binary to external NOR flash on the address that the 1st stage ROM bootloader +9. (optionally TODO) loads the other sections required like the FCB into external NOR flash +10. (optionally) resets the target device, causing the 2nd stage bootloader to be executed ### Other sections The following sections need to also be set (TODO support) before the bootloader can be run: