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

On-silicon root-of-trust image verify (ECDSA-P256 via tf-psa-crypto). More...

#include <stdint.h>
#include <string.h>
#include "mbedtls/memory_buffer_alloc.h"
#include "ra8_board_ek_ra8d2.h"
#include "ra8_boot_entry.h"
#include "ra8_cgc.h"
#include "ra8_err.h"
#include "ra8_isr.h"
#include "ra8_psa_crypto.h"
#include "ra8_rot.h"
#include "ra8_time.h"
#include "rot_fixture.h"
Include dependency graph for main.c:

Go to the source code of this file.

Enumerations

enum  rot_const_t : uint32_t {
  k_rot_baud = 115200U ,
  k_rot_period_ms = 1000U ,
  k_rot_heap_bytes = 0x10000U
}
 Demo tunables. More...
enum  rot_bit_t : uint8_t { k_rot_tamper_bit = 0x01U }
 Byte flipped in the tamper copy (first body octet). More...

Functions

static void rot_write (const uint8_t *msg, size_t len)
static bool rot_genuine_ok (void)
 The genuine signed fixture must verify (k_ra8_ok).
static bool rot_tamper_rejected (void)
 A one-bit body corruption must be rejected (not k_ra8_ok).
static void rot_panic_halt (void)
static void rot_setup_or_halt (void)
void main (void)
 The application entry point Reset_Handler hands control to.

Variables

static const uint8_t k_rot_msg_pass [] = "rot verify: PASS\r\n"
static const uint8_t k_rot_msg_fail [] = "rot verify: FAIL\r\n"
static const uint8_t k_rot_diag_boot [] = "rot: boot (console up)\r\n"
static const uint8_t k_rot_diag_psa_fail [] = "rot: psa_init FAIL\r\n"
static const uint8_t k_rot_diag_psa_ok [] = "rot: psa_init ok\r\n"
static const uint8_t k_rot_diag_genuine [] = "rot: genuine image ACCEPTED\r\n"
static const uint8_t k_rot_diag_no_gen [] = "rot: genuine image REJECTED (bug)\r\n"
static const uint8_t k_rot_diag_tamper [] = "rot: tampered image REJECTED\r\n"
static const uint8_t k_rot_diag_no_tamp [] = "rot: tampered image ACCEPTED (bug)\r\n"
static uint8_t s_rot_heap [k_rot_heap_bytes]
 Static heap tf-psa's mbedtls_calloc draws from (no libc heap on target).
static uint8_t s_rot_tamper [sizeof(k_rot_fixture_image)]
 Mutable copy of the fixture used for the tamper case.

Detailed Description

On-silicon root-of-trust image verify (ECDSA-P256 via tf-psa-crypto).

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

Runs the REAL ra8_rot verify chain on the M85 against a signed image fixture (rot_fixture.h, produced by scripts/secrets/rot_sign.py with the project RoT key): SHA-256 of the body, the anti-rollback version-bind hash, and an ECDSA-P256 signature check via the tf-psa-crypto software backend (the RSIP crypto hardware is dead – see libs/ra8_hal/src/ra8_rsip.c). It proves a working root of trust can authenticate images on this hardware, and that a tampered body is rejected. This is a self-test: it does NOT touch the boot path, so there is no brick risk.

Reports "rot verify: PASS" (genuine accepted AND tamper rejected) or "rot verify: FAIL" over SCI8 (115200 8N1).

Since
0.1.0

Definition in file main.c.

Enumeration Type Documentation

◆ rot_bit_t

enum rot_bit_t : uint8_t

Byte flipped in the tamper copy (first body octet).

Enumerator
k_rot_tamper_bit 

Rot tamper bit.

Definition at line 48 of file main.c.

◆ rot_const_t

enum rot_const_t : uint32_t

Demo tunables.

Enumerator
k_rot_baud 

Rot baud.

k_rot_period_ms 

Rot period ms.

k_rot_heap_bytes 

64 KiB static heap for tf-psa mbedtls_calloc.

Definition at line 41 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

Definition at line 133 of file main.c.

References k_ra8_board_led1, k_ra8_board_led2, k_rot_diag_genuine, k_rot_diag_no_gen, k_rot_diag_no_tamp, k_rot_diag_tamper, k_rot_msg_fail, k_rot_msg_pass, k_rot_period_ms, ra8_board_led_toggle(), ra8_delay_ms(), ra8_isr_globals_enable(), rot_genuine_ok(), rot_panic_halt(), rot_setup_or_halt(), rot_tamper_rejected(), and rot_write().

◆ rot_genuine_ok()

bool rot_genuine_ok ( void )
static

The genuine signed fixture must verify (k_ra8_ok).

Definition at line 74 of file main.c.

References k_ra8_ok, k_rot_fixture_body_len, k_rot_fixture_image, ra8_rot_trailer_after(), and ra8_rot_verify_image().

Referenced by main().

◆ rot_panic_halt()

void rot_panic_halt ( void )
static

Definition at line 96 of file main.c.

Referenced by main(), and rot_setup_or_halt().

◆ rot_setup_or_halt()

◆ rot_tamper_rejected()

bool rot_tamper_rejected ( void )
static

A one-bit body corruption must be rejected (not k_ra8_ok).

Definition at line 85 of file main.c.

References k_ra8_ok, k_rot_fixture_body_len, k_rot_fixture_image, k_rot_tamper_bit, memcpy(), ra8_rot_trailer_after(), ra8_rot_verify_image(), and s_rot_tamper.

Referenced by main().

◆ rot_write()

void rot_write ( const uint8_t * msg,
size_t len )
static

Definition at line 68 of file main.c.

References ra8_board_uart_console_write().

Referenced by main(), and rot_setup_or_halt().

Variable Documentation

◆ k_rot_diag_boot

const uint8_t k_rot_diag_boot[] = "rot: boot (console up)\r\n"
static

Definition at line 54 of file main.c.

Referenced by rot_setup_or_halt().

◆ k_rot_diag_genuine

const uint8_t k_rot_diag_genuine[] = "rot: genuine image ACCEPTED\r\n"
static

Definition at line 57 of file main.c.

Referenced by main().

◆ k_rot_diag_no_gen

const uint8_t k_rot_diag_no_gen[] = "rot: genuine image REJECTED (bug)\r\n"
static

Definition at line 58 of file main.c.

Referenced by main().

◆ k_rot_diag_no_tamp

const uint8_t k_rot_diag_no_tamp[] = "rot: tampered image ACCEPTED (bug)\r\n"
static

Definition at line 60 of file main.c.

Referenced by main().

◆ k_rot_diag_psa_fail

const uint8_t k_rot_diag_psa_fail[] = "rot: psa_init FAIL\r\n"
static

Definition at line 55 of file main.c.

Referenced by rot_setup_or_halt().

◆ k_rot_diag_psa_ok

const uint8_t k_rot_diag_psa_ok[] = "rot: psa_init ok\r\n"
static

Definition at line 56 of file main.c.

Referenced by rot_setup_or_halt().

◆ k_rot_diag_tamper

const uint8_t k_rot_diag_tamper[] = "rot: tampered image REJECTED\r\n"
static

Definition at line 59 of file main.c.

Referenced by main().

◆ k_rot_msg_fail

const uint8_t k_rot_msg_fail[] = "rot verify: FAIL\r\n"
static

Definition at line 53 of file main.c.

Referenced by main().

◆ k_rot_msg_pass

const uint8_t k_rot_msg_pass[] = "rot verify: PASS\r\n"
static

Definition at line 52 of file main.c.

Referenced by main().

◆ s_rot_heap

uint8_t s_rot_heap[k_rot_heap_bytes]
static

Static heap tf-psa's mbedtls_calloc draws from (no libc heap on target).

Definition at line 63 of file main.c.

Referenced by rot_setup_or_halt().

◆ s_rot_tamper

uint8_t s_rot_tamper[sizeof(k_rot_fixture_image)]
static

Mutable copy of the fixture used for the tamper case.

Definition at line 66 of file main.c.

Referenced by rot_tamper_rejected().