|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Secure side: authenticate the NS image, then BLXNS – the TrustZone RoT proof (#172). More...
#include <stddef.h>#include <stdint.h>#include "mbedtls/memory_buffer_alloc.h"#include "ra8_board_ek_ra8d2.h"#include "ra8_boot_entry.h"#include "ra8_err.h"#include "ra8_mstp.h"#include "ra8_psa_crypto.h"#include "ra8_tz_secure_boot.h"#include "trustzone_init.h"Go to the source code of this file.
Enumerations | |
| enum | sbns_const_t : uint32_t { k_sbns_heap_bytes = 0x10000U } |
| Static-heap sizing for tf-psa-crypto's mbedtls_calloc (no libc heap). More... | |
| enum | sbns_uart_t : uint32_t { k_sbns_uart_baud = 115200U } |
| Secure-side J-Link OB VCOM (SCI8) console parameters. More... | |
| enum | sbns_hex_t : uint8_t { k_sbns_hex_nibbles = 8U , k_sbns_hex_bits = 4U , k_sbns_hex_dec_max = 9U , k_sbns_hex_alpha_base = 10U } |
| Nibble-decode constants for the denial-code hexadecimal print. More... | |
| enum | sbns_hex_mask_t : uint32_t { k_sbns_hex_nibble_mask = 0xFU } |
| Bit mask isolating one hexadecimal nibble from a shifted word. More... | |
| enum | sbns_step_t : uint32_t { k_sbns_step_idle = 0U , k_sbns_step_crypto = 1U , k_sbns_step_armed = 2U , k_sbns_step_denied = 3U , k_sbns_step_psa_fail = 9U } |
| Boot-progress breadcrumbs latched into g_sbns_step. More... | |
Functions | |
| static void | sbns_park (void) |
| Park the Secure core in WFI forever. | |
| static void | sbns_console_bringup (void) |
| Bring up the Secure J-Link OB VCOM console (best-effort). | |
| static void | sbns_console_say (const uint8_t *msg, uint32_t len) |
| Emit a byte run on the Secure console (no-op until it is up). | |
| static void | sbns_console_print_hex32 (uint32_t value) |
| Print a uint32 as hexadecimal on the console, no leading zeros. | |
| static void | sbns_console_say_reject (ra8_err_t err) |
| Print the sbns: NS REJECTED err=0x... verdict line for a denial. | |
| void | main (void) |
| The application entry point Reset_Handler hands control to. | |
Variables | |
| volatile uint32_t | g_sbns_step = k_sbns_step_idle |
| Secure boot progress breadcrumb (sbns_step_t). | |
| volatile uint32_t | g_sbns_denied |
| Set to 1 when the root-of-trust gate DENIED the NS image (tampered). | |
| volatile uint32_t | g_sbns_jump_err |
| The ra8_err_t ra8_tz_secure_boot_jump_ns returned on a denial. | |
| static uint8_t | s_sbns_heap [k_sbns_heap_bytes] |
| Static heap tf-psa-crypto's mbedtls_calloc draws from. | |
| static bool | s_sbns_console_up = false |
| True once the Secure J-Link OB VCOM console is initialised. | |
| static const uint8_t | k_sbns_msg_crypto_ready [] = "sbns: crypto ready\r\n" |
| UART breadcrumb: crypto/PSA facade is up (printed pre-verify). | |
| static const uint8_t | k_sbns_msg_verify_enter [] = "sbns: verify+enter NS\r\n" |
| UART breadcrumb: about to verify + BLXNS into the NS image. | |
| static const uint8_t | k_sbns_msg_reject [] = "sbns: NS REJECTED err=0x" |
| UART verdict prefix: RoT denied the NS image (followed by the hex code). | |
| static const uint8_t | k_sbns_msg_crlf [] = "\r\n" |
| UART line terminator appended after the denial error code. | |
Secure side: authenticate the NS image, then BLXNS – the TrustZone RoT proof (#172).
The end-to-end proof that the root of trust ENFORCES the TrustZone Secure->NS boundary on this hardware. SystemInit -> ra8_trustzone_init has already carved the SRAM2 NS aperture, programmed the SAU, and copied the (separately flashed) NS image into the SRAM run base 0x3210_0000. This main() then:
Two flashable artifacts drive the two outcomes (identical Secure half):
The Secure side owns the security-critical verify decision, so it prints the verdict over the J-Link OB VCOM console (SCI8) for uart_scrape, since a J-Link memprobe is unreliable on this TrustZone app (a debugger connect forces VC_CORERESET, which re-runs and faults the secure boot). The Secure world has full peripheral access, so the console needs no NS/PSAR plumbing. Boot-order breadcrumbs:
All diagnostics are ALSO latched into Secure .bss globals a J-Link halt can read when the debug connection does not disturb the boot.
Definition in file main.c.
| enum sbns_const_t : uint32_t |
| enum sbns_hex_mask_t : uint32_t |
| enum sbns_hex_t : uint8_t |
Nibble-decode constants for the denial-code hexadecimal print.
Used only by sbns_console_print_hex32 to render g_sbns_jump_err as 0x... on the console. No hardware meaning.
| enum sbns_step_t : uint32_t |
Boot-progress breadcrumbs latched into g_sbns_step.
Read via J-Link to localise where the Secure boot wedged if the NS world never comes alive.
| enum sbns_uart_t : uint32_t |
| void main | ( | void | ) |
The application entry point Reset_Handler hands control to.
Returns void, not int. This is a freestanding image: there is no hosted C environment, no process and nothing to report an exit status to. ISO C fixes main at int only for a hosted implementation; for a freestanding one (C23 5.1.2.1) the startup function's name and type are implementation-defined, and this is that definition. Reset_Handler discards no value because there is none to discard, and if main ever does return, startup halts the CPU rather than resuming anything.
The firmware lane is compiled -ffreestanding (see cmake/ra8_add_app.cmake) and the flag and this signature travel together: without it both GCC and clang reject a non-int main (-Wmain / -Wmain-return-type). Do not remove one without the other.
That coupling is why the declaration sits behind __STDC_HOSTED__ == 0, which -ffreestanding sets and a hosted build does not. The guard is not defensive dressing: this header is reachable from host builds (the unit tests compile ra8_core natively), and an unguarded void main(void); makes every hosted translation unit that includes it fail with conflicting types for 'main' against its own ISO int main. The declaration therefore exists exactly where its contract does.
Hosted first-party code – everything under tests/ and tools/ – uses the ISO int main(...) contract instead, because it genuinely does run under an OS that reads the exit status. scripts/checks/check_entry_points.py holds each domain to its own contract (#707).
Declared here, once, for the same reason SystemInit is: every vector_table.c used to restate it as a local extern int32_t main(void);, sixteen copies that no compiler ever compared against the definition – and roughly thirty of them had silently drifted out of agreement with the main they called.
The application entry point Reset_Handler hands control to.
Brings up CGC + BSP audio then plays blocks.
The application entry point Reset_Handler hands control to.
Brings up CGC + GPT triple, runs sweep.
The application entry point Reset_Handler hands control to.
Brings up clocks + UART + RMII pins, then ThreadX.
The application entry point Reset_Handler hands control to.
Brings up clocks + UART, then enters ThreadX.
The application entry point Reset_Handler hands control to.
Brings up LED, console, SDHI pins, then ThreadX.
The application entry point Reset_Handler hands control to.
Brings up CGC + USB-FS + UAC1, then enters the iso-IN feed loop forever.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
See file header.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Profiles power modes once a second.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Brings up the clocks, console, SPI, and SD card, then runs the shared ra8_io VFS round-trip over the SD-over-SPI block device. On success it prints the exact PASS banner the HIL runner and ra8_emulator smoke gate scrape for; on any failure it prints FAIL and parks the core.
The application entry point Reset_Handler hands control to.
Initialises logging and the console, brings up the OSPI NOR volume, runs the erase-before-write round-trip, and prints a single PASS/FAIL verdict line over SCI8 before parking in an infinite loop.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Both USB controllers' clocks and pins come up before the kernel so the workers only deal with stack bring-up.
The application entry point Reset_Handler hands control to.
Brings up logging and the clock tree, releases the Cortex-M33 (which then blinks LED1 via ra8_pcntr_set_output()), and idles. See the file header.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Brings up logging, the clock tree, and the VCOM console, runs the cacheable-SRAM round-trip with the D-cache that SystemInit() enabled through ra8_cache_dcache_enable(), emits the matching PASS / FAIL banner over the console and ra8_log, then parks in WFI. Every byte the self-test touches runs with the L1 caches + MPU enabled by the shared boot (RA8_BOOT_ENABLE_CACHE_MPU + RA8_BOOT_CACHE_VIA_HAL).
The application entry point Reset_Handler hands control to.
Publishes the mailbox, releases the Cortex-M33 into the emitter, yields until it signals done, validates the blob the M33 built, then logs the PASS/FAIL verdict and the chapter count read back from the blob. See the file header for the offload narrative.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Publishes the mailbox, arms the IPC0 wake and configures the LPM block, releases the Cortex-M33 into the reader, waits for the first held page, logs the page-0 verdict, then runs the #150 mode-switch cycle – parking in low-power WFI and waking on the M33's page-turn pokes – before logging the handoff verdict and parking for good. See the file header for the narrative.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Brings up the timebase then measures forever.
The application entry point Reset_Handler hands control to.
Arms the RIIC1 target and polls the dispatcher.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Brings up the LIN commander then drives frames.
The application entry point Reset_Handler hands control to.
Brings up logging, "renders" page 0 into the shared mailbox, releases the Cortex-M33 into its hold loop, and parks the M85 in low-power WFI sleep. See the file header for the power-saving narrative.
The application entry point Reset_Handler hands control to.
The USB clock, pins, console, and the SD card all come up before the kernel so the worker only deals with USB stack bring-up.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Brings up logging, the clock tree, and the VCOM console, runs the three-step self-test (MPU enabled, canonical boot map, Device MMIO), emits the matching PASS / FAIL banner over the console and ra8_log, then parks in WFI.
The application entry point Reset_Handler hands control to.
The application entry point Reset_Handler hands control to.
Initialises logging + console, brings up the MRAM volume, runs the wear-levelling + power-cycle-survival flow, and prints a single PASS/FAIL verdict.
The application entry point Reset_Handler hands control to.
Initialises logging + console, brings up the MRAM volume, runs the program/erase round-trip, and prints a single PASS/FAIL verdict.
The application entry point Reset_Handler hands control to.
Brings up the clocks, console, and SDHI bus pins, runs the native SD card identification, fills the payload, then runs the full ra8_io VFS round-trip over the native-SDHI block device. On success it prints the exact PASS banner the HIL runner and ra8_emulator smoke gate scrape for; on any failure it prints FAIL and parks the core.
The application entry point Reset_Handler hands control to.
Brings up the console and both stdio sinks, retargets the engine's stdio to the in-RAM capture sink, runs the two-backend swap, replays the RAM capture out of the UART, and prints a single PASS/FAIL verdict per abstraction before parking in an infinite loop.
The application entry point Reset_Handler hands control to.
Brings up the clocks, console, and SDHI bus pins, runs the native SD card identification, fills the payload, then writes + reads + compares one raw 512-byte block straight against ra8_sdcard. On success it prints the exact PASS banner; on any failure it prints FAIL and parks the core.
Definition at line 333 of file main.c.
References g_sbns_denied, g_sbns_jump_err, g_sbns_step, k_ra8_err_exists, k_ra8_ok, k_sbns_msg_crypto_ready, k_sbns_msg_verify_enter, k_sbns_ns_run_base, k_sbns_step_armed, k_sbns_step_crypto, k_sbns_step_denied, k_sbns_step_psa_fail, ra8_psa_crypto_init(), ra8_tz_secure_boot_jump_ns(), s_sbns_heap, sbns_console_bringup(), sbns_console_say(), sbns_console_say_reject(), and sbns_park().
|
static |
Bring up the Secure J-Link OB VCOM console (best-effort).
Clears the module-stop refcounts (ra8_mstp_init) and initialises SCI8 on PD02/PD03 (ra8_board_uart_console_init) at k_sbns_uart_baud. ra8_cgc_init already ran in SystemInit, so PCLKA is post-PLL and the BRR divisor is valid. This is BEST-EFFORT: on any failure s_sbns_console_up stays false and the sbns_console_say helpers silently no-op, so a dead console never blocks the security-critical verify. No hardware crypto uses the modules gated here, so running it after ra8_psa_crypto_init leaves the verify unaffected.
Definition at line 230 of file main.c.
References k_ra8_ok, k_sbns_uart_baud, ra8_board_uart_console_init(), ra8_mstp_init(), and s_sbns_console_up.
Referenced by main().
|
static |
Print a uint32 as hexadecimal on the console, no leading zeros.
Renders value MSB-first into an 8-nibble scratch buffer, then emits from the first non-zero nibble (keeping at least one digit, so 0 prints "0"). Used to append g_sbns_jump_err after the err=0x prefix.
| [in] | value | 32-bit value to render (a denial ra8_err_t code here). |
Definition at line 287 of file main.c.
References k_sbns_hex_alpha_base, k_sbns_hex_bits, k_sbns_hex_dec_max, k_sbns_hex_nibble_mask, k_sbns_hex_nibbles, ra8_board_uart_console_write(), and s_sbns_console_up.
Referenced by sbns_console_say_reject().
|
static |
Emit a byte run on the Secure console (no-op until it is up).
Thin best-effort wrapper: guards on s_sbns_console_up and a NULL buffer, then forwards to the polled console write, discarding its status (console loss is acceptable for a breadcrumb; the HIL gate re-checks the output on the wire).
| [in] | msg | Bytes to transmit (not NUL-inspected); ignored when NULL. |
| [in] | len | Number of bytes in msg. |
Definition at line 259 of file main.c.
References ra8_board_uart_console_write(), and s_sbns_console_up.
Referenced by main(), and sbns_console_say_reject().
|
static |
Print the sbns: NS REJECTED err=0x... verdict line for a denial.
Composes the fixed prefix, the err code in hexadecimal, and a CRLF. Called only on the default-deny path (jump_ns returned).
| [in] | err | The ra8_err_t denial code from ra8_tz_secure_boot_jump_ns. |
Definition at line 326 of file main.c.
References k_sbns_msg_crlf, k_sbns_msg_reject, sbns_console_print_hex32(), and sbns_console_say().
Referenced by main().
|
static |
Park the Secure core in WFI forever.
Terminal halt used on every non-BLXNS exit so a J-Link halt leaves the diagnostic globals frozen.
Definition at line 203 of file main.c.
Referenced by main().
| volatile uint32_t g_sbns_denied |
Set to 1 when the root-of-trust gate DENIED the NS image (tampered).
Stays 0 on a genuine boot (BLXNS never returns to set it). A J-Link read of 1 confirms default-deny fired and the NS world never ran.
Definition at line 141 of file main.c.
Referenced by main().
| volatile uint32_t g_sbns_jump_err |
The ra8_err_t ra8_tz_secure_boot_jump_ns returned on a denial.
Captured only on the tampered path (a genuine boot BLXNS-es and never returns). Expected value: k_ra8_err_checksum_mismatch for a flipped body byte (the digest pre-check fails).
Definition at line 153 of file main.c.
Referenced by main().
| volatile uint32_t g_sbns_step = k_sbns_step_idle |
Secure boot progress breadcrumb (sbns_step_t).
Advanced at each Secure-side milestone. On a genuine boot it freezes at k_sbns_step_armed (BLXNS never returns); on a tampered boot it reaches k_sbns_step_denied.
Definition at line 130 of file main.c.
Referenced by main().
|
static |
UART line terminator appended after the denial error code.
Definition at line 189 of file main.c.
Referenced by sbns_console_say_reject().
|
static |
|
static |
UART verdict prefix: RoT denied the NS image (followed by the hex code).
Definition at line 186 of file main.c.
Referenced by sbns_console_say_reject().
|
static |
|
static |
True once the Secure J-Link OB VCOM console is initialised.
Set by sbns_console_bringup on success; the sbns_console_say helpers no-op while it is false so a dead console can never gate the security-critical verify.
Definition at line 177 of file main.c.
Referenced by sbns_console_bringup(), sbns_console_print_hex32(), and sbns_console_say().
|
static |
Static heap tf-psa-crypto's mbedtls_calloc draws from.
Secure-side .bss (below the SRAM2 NS boundary, so it stays Secure). Handed to mbedtls_memory_buffer_alloc_init before the first PSA call.
Definition at line 165 of file main.c.
Referenced by main().