ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
main.c File Reference

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"
Include dependency graph for main.c:

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.

Detailed Description

Secure side: authenticate the NS image, then BLXNS – the TrustZone RoT proof (#172).

Tag
[Ring 6 / APP] {World: S}

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:

  1. Brings up the tf-psa-crypto static heap + the PSA facade.
  2. Calls ra8_tz_secure_boot_jump_ns, whose RA8_ENABLE_ROOT_OF_TRUST gate reads the NS image's ra8_ns_rot_header_t (at ns_base + 0x40) to learn the signed-body length, locates the ra8_rot_trailer_t at ns_base + body_len, re-computes SHA-256 + verifies the ECDSA-P256 signature, and only then arms VTOR_NS + BLXNS.

Two flashable artifacts drive the two outcomes (identical Secure half):

  • Genuine signed NS image -> verify passes -> BLXNS -> the NS reset handler advances g_sbns_ns_alive forever (a J-Link memprobe sees it climb). main() never returns (BLXNS left Secure state).
  • Tampered NS image (one flipped body byte) -> digest mismatch -> default-deny -> jump_ns RETURNS an error -> main() latches g_sbns_denied = 1 + g_sbns_jump_err and parks. g_sbns_ns_alive stays 0 (the NS world never ran).

Observability (bench)

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:

  • sbns: crypto ready – PSA/crypto facade is up (pre-verify).
  • sbns: verify+enter NS – about to verify + BLXNS into the NS image.
  • sbns: NS REJECTED err=0x... – the deny path (jump_ns returned; the hex is g_sbns_jump_err, e.g. 0x502 = k_ra8_err_checksum_mismatch). A GENUINE image prints the first two lines and never returns (BLXNS); a TAMPERED image adds the REJECTED line. NS-side liveness is NOT UART-observable (the minimal NS image owns no console peripheral and delegating SCI8 to NS would need invasive PSAR/SAU changes); the g_sbns_ns_alive memprobe symbol remains as the belt-and-suspenders NS-liveness probe.

All diagnostics are ALSO latched into Secure .bss globals a J-Link halt can read when the debug connection does not disturb the boot.

Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ sbns_const_t

enum sbns_const_t : uint32_t

Static-heap sizing for tf-psa-crypto's mbedtls_calloc (no libc heap).

Enumerator
k_sbns_heap_bytes 

64 KiB static heap for the ECDSA verify.

Definition at line 69 of file main.c.

◆ sbns_hex_mask_t

enum sbns_hex_mask_t : uint32_t

Bit mask isolating one hexadecimal nibble from a shifted word.

Separate uint32_t enum because a mask is not an index/count.

Enumerator
k_sbns_hex_nibble_mask 

Low-nibble mask for a uint32 shift result.

Definition at line 102 of file main.c.

◆ sbns_hex_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.

Enumerator
k_sbns_hex_nibbles 

Hex nibbles in a uint32 (32 / 4).

k_sbns_hex_bits 

Bits per hex nibble.

k_sbns_hex_dec_max 

Highest nibble emitted as an ASCII '0'-'9'.

k_sbns_hex_alpha_base 

First nibble emitted as ASCII 'a'.

Definition at line 90 of file main.c.

◆ sbns_step_t

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.

Enumerator
k_sbns_step_idle 

Pre-main sentinel.

k_sbns_step_crypto 

Heap + PSA facade initialised.

k_sbns_step_armed 

About to call jump_ns (verify+BLXNS).

k_sbns_step_denied 

jump_ns returned -> NS image denied.

k_sbns_step_psa_fail 

PSA init failed (crypto unavailable).

Definition at line 112 of file main.c.

◆ sbns_uart_t

enum sbns_uart_t : uint32_t

Secure-side J-Link OB VCOM (SCI8) console parameters.

The verdict breadcrumbs are emitted on the stock EK-RA8D2 debug console so uart_scrape can read them; 115200 8N1 matches the sibling HIL apps (e.g. fault_div0_hil).

Enumerator
k_sbns_uart_baud 

SCI8 J-Link OB VCOM console line rate (bps).

Definition at line 80 of file main.c.

Function Documentation

◆ main()

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.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has configured the clock tree and VTOR.
Postcondition
Control does not return; the image runs until reset or halt.
Any value the application wanted to report has been logged, not returned.
Note
Not thread-safe; single-threaded startup context only.
Warning
Only valid while the translation unit is compiled -ffreestanding. A hosted build rejects this signature.
See also
SystemInit()
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + BSP audio then plays blocks.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the playback loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + GPT triple, runs sweep.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the sweep loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up clocks + UART + RMII pins, then ThreadX.

Precondition
Reset_Handler has copied .data and zeroed .bss.
Postcondition
On clean entry the kernel runs the worker thread once.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up clocks + UART, then enters ThreadX.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the kernel runs the worker thread forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up LED, console, SDHI pins, then ThreadX.

Precondition
Reset_Handler has copied .data + zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
CPUCLK0 is raised to the PLL1 target before the kernel starts.
On clean entry the SD card thread runs forever.
On any HAL init failure the function halts in __WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up CGC + USB-FS + UAC1, then enters the iso-IN feed loop forever.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the iso-IN feed loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
SystemInit set VTOR / FPU / priority grouping.

The application entry point Reset_Handler hands control to.

See file header.

Precondition
Boot init has completed.
The secure-boot library's BLXNS into NS image either failed or was skipped (the call site in ra8_trustzone_init is a no-op on host builds).
Postcondition
Diagnostic counter latched, CPU parked in a halt loop.
Function never returns.
Note
Single-threaded entry.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success g_eoh_chapters / g_eoh_crc hold the parsed results, the banner is emitted, and g_eoh_heartbeat advances once per frame.
On any failure g_eoh_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The chapters/ch0-CRC banner is emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success the g_etoc_* result globals hold the parsed TOC values, the banner is emitted, and g_etoc_heartbeat advances once per frame.
On any failure g_etoc_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss; SystemInit set VTOR/FPU.
Postcondition
The shelf scans on the panel; taps open books, browse, and read.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The slab/arena/tile/vmem banner is emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success the cache globals are latched and g_pc_heartbeat advances.
On any failure g_pc_err is non-zero and the CPU parks (no heartbeat).
Since
0.1.0

The application entry point Reset_Handler hands control to.

Profiles power modes once a second.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the profile + blink loop.
On any HAL hard error LED2 latches ON.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
The shared board boot files installed the vector table.
Postcondition
The demo has run once and its verdict banner is streaming steadily.
The CPU idles re-emitting the banner (or halts after a fatal init error).
Since
0.1.0

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.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On a clean run the CPU loops forever after the PASS banner.
On any failure the function prints FAIL and halts in WFI.
Note
Not thread-safe; this is the single-threaded app entry.
Since
0.1.0

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.

Precondition
SystemInit configured VTOR / FPU / priority grouping.
The OSPI NOR array is present (modelled in ra8_emulator, real on silicon).
Postcondition
Exactly one PASS or FAIL verdict line has been queued on SCI8.
Control parks in an infinite loop; the function never returns.
Note
Single-threaded; runs to the park loop on the main stack.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The page-count + render-hash banner is emitted; the CPU loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The cal=OK / cal=SKIP result and the finger-free touchcal: ready sentinel are emitted; the CPU then loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The open=OK touch banner is emitted; the CPU then loops in WFI.
Since
0.1.0

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.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR, FPU, priority grouping.
Postcondition
On clean entry the CPU stays in tx_kernel_enter forever.
On any HAL init failure the function halts in WFI.
Note
Single entry point; not re-entrant.
Since
0.1.0

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.

Precondition
SystemInit has completed core bring-up.
The M33 is held in reset by hardware until released here.
Postcondition
The M33 has been released and is blinking LED1.
This function never returns to its caller.
Note
Single-threaded; no RTOS on the M85 in this template.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
The application links ra8_c6link and ESP-hosted generated codecs.
No hardware validation is inferred from this function.
Postcondition
No c6link operation is attempted.
No network or storage state is modified.
Note
Single-threaded compile fixture.
Since
0.1.0

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).

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit enabled the MPU + I-cache + D-cache via the ra8_cache HAL.
Postcondition
Exactly one banner (PASS or FAIL) has been emitted.
The core is parked in WFI.
Note
Single-threaded; no RTOS and no IRQ sources in this template.
Since
0.1.0

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.

Precondition
SystemInit has completed core bring-up.
The M33 is held inactive by hardware until released here.
Postcondition
The M33 has built a RABOOK1 blob and the M85 has validated it.
This function never returns to its caller.
Note
Single-threaded; no RTOS on the M85 in this example.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
On success the CPU heartbeats after epaper: PASS.
On any HAL error the console prints epaper: FAIL and the red LED latches on.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The chapters/toc/cover banner is emitted; CPU loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The reader loop runs forever, redrawing on each tap.
A page-1 banner is emitted once after the first render.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The cover-size / framebuffer-CRC banner is emitted; CPU loops in WFI.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The panel shows the reader screen and the input loop runs forever.
Since
0.1.0

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.

Precondition
SystemInit has completed core bring-up.
The M33 is held inactive by hardware until released here.
Postcondition
The M33 has rendered + re-rendered the held page and the M85 is parked.
This function never returns to its caller.
Note
Single-threaded; no RTOS on the M85 in this example.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR / FPU / priority grouping.
Postcondition
The boot banner is emitted; the reader loop services taps forever.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up the timebase then measures forever.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the measure + blink loop forever.
On any HAL init failure the function halts in WFI.
Note
Never returns.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Arms the RIIC1 target and polls the dispatcher.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
The CPU stays in the dispatch poll loop forever.
On any fatal init error the CPU parks in riic_target_panic_halt.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On a clean run the PASS banner is printed and the CPU loops in WFI.
On any failure the function prints a FAIL line and halts.
Note
Not thread-safe; single-threaded app entry.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the read + print loop forever.
On any HAL hard error LED2 latches ON and the loop exits.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Brings up the LIN commander then drives frames.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On clean entry the CPU stays in the LIN-frame + blink loop forever.
On any HAL init failure the function halts in WFI.
Since
0.1.0

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.

Precondition
SystemInit has completed core bring-up.
The M33 is held inactive by hardware until released here.
Postcondition
The M33 owns the held page and the M85 is parked.
This function never returns to its caller.
Note
Single-threaded; no RTOS on the M85 in this example.
Since
0.1.0

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.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit set VTOR, FPU, priority grouping.
Postcondition
On clean entry the CPU stays in tx_kernel_enter forever.
On any HAL init failure the function halts in WFI.
Note
Single entry point; not re-entrant.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler copied .data and zeroed .bss.
SystemInit configured VTOR / FPU.
Postcondition
On clean bring-up the CPU stays in the poll loop.
On any HAL init failure the function halts in WFI.
Note
Single entry point; not re-entrant.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler initialized static storage.
SystemInit configured VTOR, FPU, and priority grouping.
Postcondition
The startup banner is printed once.
Control enters ThreadX and never returns normally.
Note
The #707 freestanding contract is declared by ra8_boot_entry.h.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On a clean run the PASS banner is printed and the CPU heartbeats forever.
On any failure LED2 latches ON and the CPU parks.
Since
0.1.0

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.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit installed the boot map via ra8_mpu_apply_boot_map().
Postcondition
Exactly one banner (PASS or a step-specific FAIL) has been emitted.
The core is parked in WFI.
Note
Single-threaded; no RTOS and no IRQ sources in this template.
Since
0.1.0

The application entry point Reset_Handler hands control to.

Precondition
Reset_Handler initialised the C runtime; SystemInit ran.
The EK-RA8D2 J-Link OB VCOM console is attached for the banner.
Postcondition
The commit + rollback attempts have executed against extra-MRAM.
The verdict banner is emitted once per report cycle.
Note
Single entry point; not re-entrant.
Since
0.1.0

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.

Precondition
SystemInit configured VTOR / FPU / priority grouping.
The extra-MRAM region is present (modelled in ra8_emulator, real on silicon).
Postcondition
Exactly one PASS or FAIL verdict line has been queued on SCI8.
Control parks in an infinite loop; the function never returns.
Note
Single-threaded; runs to the park loop on the main stack.
Since
0.1.0

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.

Precondition
SystemInit configured VTOR / FPU / priority grouping.
The extra-MRAM region is present (modelled in ra8_emulator, real on silicon).
Postcondition
Exactly one PASS or FAIL verdict line has been queued on SCI8.
Control parks in an infinite loop; the function never returns.
Note
Single-threaded; runs to the park loop on the main stack.
Since
0.1.0

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.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On a clean run the CPU loops forever after the PASS banner.
On any failure the function prints FAIL and halts in WFI.
Note
Not thread-safe; this is the single-threaded app entry.
Since
0.1.0

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.

Precondition
SystemInit configured VTOR / FPU / priority grouping.
The OSPI NOR array is present (modelled in ra8_emulator, real on silicon).
Postcondition
A PASS or FAIL verdict line has been queued on SCI8 for each abstraction.
Control parks in an infinite loop; the function never returns.
Note
Single-threaded; runs to the park loop on the main stack.
Since
0.1.0

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.

Precondition
Reset_Handler has copied .data and zeroed .bss.
SystemInit has set VTOR, FPU, and priority grouping.
Postcondition
On a clean run the CPU loops forever after the PASS banner.
On any failure the function prints FAIL and halts in WFI.
Note
Not thread-safe; this is the single-threaded app entry.
Since
0.1.0

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().

◆ sbns_console_bringup()

void sbns_console_bringup ( void )
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.

Precondition
ra8_cgc_init has run (PCLKA is post-PLL) – done in SystemInit.
Secure state, single-threaded boot context.
Postcondition
s_sbns_console_up is true iff both MSTP and console init returned ok.
No global state other than s_sbns_console_up + the SCI8/PFS registers is modified.
Note
Not thread-safe; call once during boot.
Since
0.1.0

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().

◆ sbns_console_print_hex32()

void sbns_console_print_hex32 ( uint32_t value)
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.

Parameters
[in]value32-bit value to render (a denial ra8_err_t code here).
Precondition
The console is up (else the call is a no-op).
value is any uint32 (full range supported).
Postcondition
The hexadecimal text was pushed to the console, or nothing when down.
No other state modified.
Note
Not thread-safe (single-threaded boot).
Since
0.1.0

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().

◆ sbns_console_say()

void sbns_console_say ( const uint8_t * msg,
uint32_t len )
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).

Parameters
[in]msgBytes to transmit (not NUL-inspected); ignored when NULL.
[in]lenNumber of bytes in msg.
Precondition
msg points at len readable bytes when non-NULL.
The console is up (else the call is a no-op).
Postcondition
len bytes were pushed to the console, or nothing on a guard miss.
No other state modified.
Note
Not thread-safe (single-threaded boot).
Since
0.1.0

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().

◆ sbns_console_say_reject()

void sbns_console_say_reject ( ra8_err_t err)
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).

Parameters
[in]errThe ra8_err_t denial code from ra8_tz_secure_boot_jump_ns.
Precondition
Reached from the deny path (the NS image was rejected).
The console is up (else the call is a no-op).
Postcondition
The full REJECTED line was pushed to the console, or nothing when down.
No other state modified.
Note
Not thread-safe (single-threaded terminal path).
Since
0.1.0

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().

◆ sbns_park()

void sbns_park ( void )
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.

Returns
Never returns.
Precondition
Reached from a terminal boot outcome.
The diagnostic globals reflect the reason.
Postcondition
The core spins in WFI.
No further work is done.
Note
Single-threaded.
Since
0.1.0

Definition at line 203 of file main.c.

Referenced by main().

Variable Documentation

◆ g_sbns_denied

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.

Note
Read externally by J-Link only.
Warning
Do not modify from outside main().
Since
0.1.0

Definition at line 141 of file main.c.

Referenced by main().

◆ g_sbns_jump_err

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).

Note
Read externally by J-Link only.
Warning
Do not modify from outside main().
Since
0.1.0

Definition at line 153 of file main.c.

Referenced by main().

◆ g_sbns_step

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.

Note
Read externally by J-Link only.
Warning
Do not modify from outside main().
Since
0.1.0

Definition at line 130 of file main.c.

Referenced by main().

◆ k_sbns_msg_crlf

const uint8_t k_sbns_msg_crlf[] = "\r\n"
static

UART line terminator appended after the denial error code.

Definition at line 189 of file main.c.

Referenced by sbns_console_say_reject().

◆ k_sbns_msg_crypto_ready

const uint8_t k_sbns_msg_crypto_ready[] = "sbns: crypto ready\r\n"
static

UART breadcrumb: crypto/PSA facade is up (printed pre-verify).

Definition at line 180 of file main.c.

Referenced by main().

◆ k_sbns_msg_reject

const uint8_t k_sbns_msg_reject[] = "sbns: NS REJECTED err=0x"
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().

◆ k_sbns_msg_verify_enter

const uint8_t k_sbns_msg_verify_enter[] = "sbns: verify+enter NS\r\n"
static

UART breadcrumb: about to verify + BLXNS into the NS image.

Definition at line 183 of file main.c.

Referenced by main().

◆ s_sbns_console_up

bool s_sbns_console_up = false
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.

Note
File-private; boot context only, single-threaded.
Warning
Do not set from outside sbns_console_bringup.
Since
0.1.0

Definition at line 177 of file main.c.

Referenced by sbns_console_bringup(), sbns_console_print_hex32(), and sbns_console_say().

◆ s_sbns_heap

uint8_t s_sbns_heap[k_sbns_heap_bytes]
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.

Note
File-private; the allocator owns it after init.
Warning
Do not access directly after mbedtls_memory_buffer_alloc_init.
Since
0.1.0

Definition at line 165 of file main.c.

Referenced by main().