|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
FSP-style TrustZone secure-boot for the Cortex-M85 (CPU0). More...
Go to the source code of this file.
Data Structures | |
| struct | ra8_ns_rot_header_t |
| Self-describing RoT header the NS linker embeds in the NS image. More... | |
Functions | |
| uint32_t | ra8_tz_ns_signed_body_len (const uint32_t *ns_vector_table) |
| Read the NS image's self-describing signed-body length. | |
| ra8_err_t | ra8_tz_secure_boot_sau_init (void) |
| Programme the SAU regions documented in ra8_tz_sau_region_t. | |
| ra8_err_t | ra8_tz_secure_boot_security_init (uint32_t ipcsar_value, uint32_t ipcpar_value) |
| Unlock PRCR_S.PRC4 and write IPCSAR + IPCPAR. | |
| ra8_err_t | ra8_tz_secure_boot_jump_ns (const uint32_t *ns_vector_table) |
| Switch to NS state and jump to the NS image's reset vector. | |
| ra8_err_t | ra8_tz_secure_boot_run (uint32_t ipcsar_value, uint32_t ipcpar_value, const uint32_t *ns_vector_table) |
| Run the full secure-boot sequence and (on target) BLXNS. | |
| void | ra8_tz_secure_boot_host_reset (void) |
| Reset the host-side state for unit-test fixtures. | |
| ra8_tz_secure_boot_step_t | ra8_tz_secure_boot_get_step (void) |
| Read the boot progress counter (debug / test). | |
| uint32_t | ra8_tz_secure_boot_host_blxns_target (void) |
| Read the captured BLXNS target (host / test). | |
FSP-style TrustZone secure-boot for the Cortex-M85 (CPU0).
Mirrors the FSP R_BSP_SAUInit + R_BSP_SecurityInit + R_BSP_NonSecureEnter triplet without copying any FSP code. The entry point is ra8_tz_secure_boot_run, which is called from the per-app trustzone_init.c when RA8_TRUSTZONE_ENABLE is on.
The boot sequence is:
On a host (RA8_OFF_TARGET defined) the module exposes a pure-C implementation that writes to a mocked CPSCU window, so the unit tests under tests/ can drive the IPCSAR-unlock sequence without touching real hardware.
Definition in file ra8_tz_secure_boot.h.
| enum ra8_tz_ns_rot_header_magic_t : uint32_t |
Magic marker of the Non-Secure signed-image RoT header.
The 32-bit little-endian word the NS linker emits as the first field of the ra8_ns_rot_header_t. It is the ASCII string "NSR1" (bytes N,S,R,1), so a hex dump of the flashed NS image reads the marker in order. A mismatched magic means the NS image was not built with the RoT header (or is corrupt) and the secure boot default-denies the BLXNS.
| Enumerator | |
|---|---|
| k_ra8_tz_ns_rot_header_magic | ASCII "NSR1" (little-endian). |
Definition at line 122 of file ra8_tz_secure_boot.h.
| enum ra8_tz_ns_rot_header_offset_t : uint8_t |
Byte offset of the ra8_ns_rot_header_t from the NS image base.
The header sits immediately after the 16-slot ARMv8-M Non-Secure vector table (16 * 4 = 64 bytes), so 0x40 is the first free, deterministic offset from ns_vector_table. Both the NS linker script (which places .ns_rot_header here and ASSERTs the placement) and the Secure verifier agree on this constant; it is the whole cross-image contract, so the NS vector table MUST remain exactly 16 entries.
| Enumerator | |
|---|---|
| k_ra8_tz_ns_rot_header_offset | Offset after the 16-slot NS vectors. |
Definition at line 138 of file ra8_tz_secure_boot.h.
| enum ra8_tz_sau_region_t : uint8_t |
Canonical SAU region indices for the RA8D2 secure-boot layout.
The layout deliberately mirrors FSP's R_BSP_SAUInit – five regions are programmed and the SAU is enabled with ALLNS = 0. Region 3 (NSC veneer) points at the unused 0x10000000 IDAU alias rather than at the actual .gnu.sgstubs placement inside MRAM, because the latter has been bench-verified to brick the chip (see project memory project_sau_sgstubs_brick). With ALLNS = 0 and Region 3 pointing at an unused alias, callers must not emit any Non-Secure entries (cmse_nonsecure_entry) until a follow-up change moves the veneers into their own non-S-executable region.
Definition at line 82 of file ra8_tz_secure_boot.h.
| enum ra8_tz_secure_boot_step_t : uint8_t |
Progress markers stamped into g_ra8_tz_secure_boot_step.
Mirrors the diagnostic counters in the existing cpu1_pingpong app – each step is set in-order as the secure boot makes forward progress, so a J-Link memprobe can pinpoint exactly where bring-up wedged if the BLXNS never fires.
Definition at line 101 of file ra8_tz_secure_boot.h.
|
nodiscard |
Read the NS image's self-describing signed-body length.
Reads the ra8_ns_rot_header_t the NS linker embedded at k_ra8_tz_ns_rot_header_offset from ns_vector_table and returns its body_len field after confirming the header magic. This is the BLXNS boundary's analog of the DFU header's body-length word on the copy-to-run boundary: it tells the root-of-trust gate exactly how many bytes to hash and where the appended ra8_rot_trailer_t begins (ns_vector_table + body_len).
Reading body_len from the untrusted NS image is safe: a lie about it only changes which bytes are hashed, and no attacker can forge a valid ECDSA-P256 signature over any body without the held-out private key – so a wrong length simply default-denies at the signature check.
| [in] | ns_vector_table | Base of the NS image (its vector table). May be NULL (handled: returns 0). |
| 0 | ns_vector_table is NULL, or the header magic is wrong (no RoT header present) – the caller must NOT BLXNS. |
| non-zero | The body_len recorded in the NS RoT header. |
Definition at line 510 of file ra8_tz_secure_boot.c.
References ra8_ns_rot_header_t::body_len, k_ra8_tz_ns_rot_header_magic, k_ra8_tz_ns_rot_header_offset, ra8_log_error, and s_tag.
Referenced by internal_ns_verify_or_deny().
| ra8_tz_secure_boot_step_t ra8_tz_secure_boot_get_step | ( | void | ) |
Read the boot progress counter (debug / test).
Returns the most-recent ra8_tz_secure_boot_step_t value stored in the internal progress counter. Useful for J-Link memprobe scripts on the bench and for unit-test assertions on the host.
| k_ra8_tz_secure_boot_step_idle | Pre-run. |
| k_ra8_tz_secure_boot_step_sau_done | SAU init complete. |
| k_ra8_tz_secure_boot_step_ipcsar_written | IPCSAR landed. |
| k_ra8_tz_secure_boot_step_branched | BLXNS executed. |
Definition at line 691 of file ra8_tz_secure_boot.c.
References s_step.
Referenced by ra8_trustzone_init().
| uint32_t ra8_tz_secure_boot_host_blxns_target | ( | void | ) |
Read the captured BLXNS target (host / test).
Host-only accessor: returns the NS reset vector that ra8_tz_secure_boot_jump_ns was last asked to branch to. On target builds this returns 0 because BLXNS does not return.
| 0 | BLXNS not yet armed (or running on target). |
| non-zero | NS reset vector that was loaded for BLXNS. |
Definition at line 233 of file ra8_tz_secure_boot.c.
| void ra8_tz_secure_boot_host_reset | ( | void | ) |
Reset the host-side state for unit-test fixtures.
Host-only helper that clears the fake PRCR_S / IPCSAR / IPCPAR captures and the BLXNS target so each test starts from a known baseline. Cross-compiled (target) builds expose the symbol but the body is empty.
Definition at line 225 of file ra8_tz_secure_boot.c.
References s_tag.
|
nodiscard |
Switch to NS state and jump to the NS image's reset vector.
Reads the initial-SP slot of the NS vector table into MSP_NS, sets VTOR_NS to ns_vector_table, then performs a BLXNS to the reset-vector slot. The function is declared [[noreturn]] and does not return on hardware.
On target, a root-of-trust gate runs BEFORE VTOR_NS is armed and BEFORE the BLXNS: ra8_rot_verify_image must authenticate the Non-Secure image (SHA-256 + ECDSA-P256) against the provisioned root public key. This is default-deny – any failure (missing / malformed signature trailer, tampered body, or an invalid signature) returns the verify error and the function does NOT branch into the NS world. The signed body length is read from the NS image's own ra8_ns_rot_header_t (emitted by the NS linker at k_ra8_tz_ns_rot_header_offset, see ra8_tz_ns_signed_body_len), and the ra8_rot_trailer_t sits immediately after that body at ns_vector_table + body_len – the same self-describing [ body ] [ trailer ] layout the copy-to-run boundary uses.
On the host (RA8_OFF_TARGET defined) the function stamps the progress counter, sets s_ra8_tz_secure_boot_blxns_target to the supplied reset vector, and returns k_ra8_ok so unit tests can assert the documented transition state; the gate's decision logic is covered directly in tests/security/src/test_ra8_root_of_trust.c.
| [in] | ns_vector_table | Pointer to the NS image's vector table. |
| k_ra8_ok | On host: BLXNS state captured. |
| k_ra8_err_null_ptr | ns_vector_table is NULL. |
| k_ra8_err_invalid_arg | ns_vector_table is not 4-byte aligned, or the reset-vector slot holds an obviously bogus value (0 or 0xFFFFFFFF). |
| k_ra8_err_* | On target: the root-of-trust gate denied the NS image (e.g. k_ra8_err_crc_mismatch for a bad signature) – BLXNS is not performed. |
Definition at line 612 of file ra8_tz_secure_boot.c.
References internal_ns_verify_or_deny(), internal_write32(), k_ra8_err_invalid_arg, k_ra8_ok, k_ra8_tz_scb_vtor_ns_addr, k_ra8_tz_secure_boot_step_blxns_armed, k_ra8_tz_secure_boot_step_branched, RA8_CHECK_NULL_PTR, ra8_log_error, ra8_log_error_val, s_step, and s_tag.
Referenced by main(), ra8_trustzone_init(), and ra8_tz_secure_boot_run().
|
nodiscard |
Run the full secure-boot sequence and (on target) BLXNS.
Convenience wrapper: ra8_tz_secure_boot_sau_init -> ra8_tz_secure_boot_security_init -> ra8_tz_secure_boot_jump_ns, returning the first non-OK status.
| [in] | ipcsar_value | Forwarded to security_init. |
| [in] | ipcpar_value | Forwarded to security_init. |
| [in] | ns_vector_table | Forwarded to jump_ns. |
| k_ra8_ok | On host happy path (BLXNS captured). |
| k_ra8_err_null_ptr | ns_vector_table is NULL. |
| k_ra8_err_not_supported | SAU_TYPE.SREGION < 5. |
| k_ra8_err_invalid_arg | NS vector table mis-aligned / invalid. |
Definition at line 671 of file ra8_tz_secure_boot.c.
References k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_tz_secure_boot_jump_ns(), ra8_tz_secure_boot_sau_init(), ra8_tz_secure_boot_security_init(), and s_tag.
|
nodiscard |
Programme the SAU regions documented in ra8_tz_sau_region_t.
Equivalent to the FSP R_BSP_SAUInit function: writes each region's RBAR / RLAR, then enables the SAU with ALLNS = 0. Does NOT touch CPSCU or jump to the NS image – callers issue ra8_tz_secure_boot_security_init and ra8_tz_secure_boot_jump_ns separately so unit tests can exercise each phase in isolation.
| k_ra8_ok | SAU programmed and enabled. |
| k_ra8_err_not_supported | SAU_TYPE.SREGION < 5. |
Definition at line 441 of file ra8_tz_secure_boot.c.
References internal_dsb(), internal_isb(), internal_read32(), internal_sau_set_region(), internal_write32(), k_ra8_err_not_supported, k_ra8_ok, k_ra8_tz_part_code_nsc_base, k_ra8_tz_part_code_nsc_limit, k_ra8_tz_part_ns_mram_base, k_ra8_tz_part_ns_mram_limit, k_ra8_tz_part_ns_per_base, k_ra8_tz_part_ns_per_limit, k_ra8_tz_part_ns_sram_base, k_ra8_tz_part_ns_sram_limit, k_ra8_tz_part_sram_nsc_base, k_ra8_tz_part_sram_nsc_limit, k_ra8_tz_sau_ctrl_addr, k_ra8_tz_sau_ctrl_enable, k_ra8_tz_sau_region_code_nsc, k_ra8_tz_sau_region_count, k_ra8_tz_sau_region_ns_mram, k_ra8_tz_sau_region_ns_periph, k_ra8_tz_sau_region_ns_sram, k_ra8_tz_sau_region_sram_nsc, k_ra8_tz_sau_type_addr, k_ra8_tz_sau_type_mask, k_ra8_tz_secure_boot_step_sau_done, ra8_log_error, s_step, and s_tag.
Referenced by ra8_trustzone_init(), and ra8_tz_secure_boot_run().
|
nodiscard |
Unlock PRCR_S.PRC4 and write IPCSAR + IPCPAR.
Writes ipcsar_value to CPSCU.IPCSAR and ipcpar_value to CPSCU.IPCPAR after first opening the PRCR_S.PRC4 write-protect gate (HUM Ch 13.2.1 "PRCR_S" – key 0xA510 at address 0x4001E3FA). The gate is closed again before the function returns.
For the cpu1_pingpong_ipc app the canonical value is ipcsar_value = 0x00050000, which sets SAIPCIR0 (IPC0 channel 0, CPU1 -> CPU0) and SAIPCIR2 (IPC1 channel 0, CPU0 -> CPU1) – the two channels CPU1 (always-NS) must reach. ipcpar_value stays at 0 so the channels remain Privileged-only.
| [in] | ipcsar_value | Value to write into CPSCU.IPCSAR. |
| [in] | ipcpar_value | Value to write into CPSCU.IPCPAR. |
| k_ra8_ok | Always (the unlock + write + relock sequence cannot fail in software; bench bring-up may still observe read-back mismatches if the chip's CPSCU is in an unexpected state). |
Definition at line 481 of file ra8_tz_secure_boot.c.
References internal_dsb(), internal_write16(), internal_write32(), k_ra8_ok, k_ra8_tz_ipcpar_addr, k_ra8_tz_ipcsar_addr, k_ra8_tz_prcr_s_addr, k_ra8_tz_prcr_s_close, k_ra8_tz_prcr_s_open, k_ra8_tz_secure_boot_step_ipcsar_written, k_ra8_tz_secure_boot_step_prcr_relocked, k_ra8_tz_secure_boot_step_prcr_unlocked, and s_step.
Referenced by ra8_trustzone_init(), and ra8_tz_secure_boot_run().