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

SYSC register-write-protection (PRCR) model. More...

#include <stdint.h>
#include <stdio.h>
#include "board_periph_block.h"
#include "board_periph_prcr_internal.h"
#include "emu_host_io_internal.h"
#include "ra8_attributes.h"
Include dependency graph for board_periph_prcr.c:

Go to the source code of this file.

Data Structures

struct  prcr_state_t
 Live PRCR group-unlock mask, and the counters behind the report. More...

Enumerations

enum  prcr_geom_t : uint64_t {
  k_prcr_base = 0x4001E3FAUL ,
  k_prcr_span = 0x2UL
}
 PRCR window geometry (HUM Ch 13.2.1 p 522). More...
enum  prcr_mask_t : uint16_t {
  k_prcr_key_mask = 0xFF00U ,
  k_prcr_key_value = 0xA500U ,
  k_prcr_group_mask = 0x003BU
}
 PRCR field masks (HUM Ch 13.2.1 p 522). More...
enum  prcr_order_t : uint32_t { k_prcr_block_order = 170U }
 Per-tick order slot for the PRCR block (relative order). More...

Functions

static void internal_prcr_reset (void)
 Return PRCR to its power-on state: every group locked.
bool priv_board_prcr_group_unlocked (uint16_t group_mask)
 Report whether every bit in group_mask is currently unlocked.
static uint64_t internal_prcr_read (uc_engine *uc, uint64_t addr, unsigned size)
 MMIO read stub – never called for an observe-only block.
static void internal_prcr_write (uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
 Snoop a PRCR write and update the retained group mask.
static void internal_prcr_report (void)
 End-of-run PRCR section: unlock traffic and any key mistakes.
static void internal_prcr_block_register (void)
 Register the PRCR block before main (host constructor).

Variables

static prcr_state_t s_prcr
static const board_periph_block_t s_k_prcr_block
 PRCR block descriptor (observe-only: snoops, does not own).

Detailed Description

SYSC register-write-protection (PRCR) model.

Models the RA8D2 Protect Register (PRCR) at 0x4001_E3FA – HUM Ch 13 "Register Write Protection Function" p 520-523. PRCR gates writes to whole families of SYSC-adjacent registers; reads are never gated. A write to a protected register while its group bit is 0 is silently discarded by the hardware: no bus fault, no status flag, the register simply keeps its old value.

That silence is exactly what makes the protection worth modelling. Issue #131 was a driver (ra8_bkup.c) that wrote the entire VBATT backup register file with PRCR locked. On silicon every write vanished and bkup_survival_demo reported rw=BAD; in the emulator, which modelled no protection at all, the same firmware reported rw=ok. The emulator passed where the bench failed, which is the defect this block removes.

The block is observe-only: it snoops the PRCR window so the sparse fallback continues to serve reads and record writes exactly as before, while the protected blocks consult priv_board_prcr_group_unlocked to decide whether to accept a store. Bench-confirmed on an EK-RA8D2 by J-Link: writing VBTBKR0 with PRCR locked reads back 0x00000000; after PRCR = 0xA502 the identical write reads back intact.

Scope: the mask is maintained for every group, but only the blocks that have been silicon-verified against it consult it (currently the VBATT backup block, PRC1). Wiring the remaining protected windows – CGC under PRC0, the PVD registers under PRC3 – is deliberately left to the change that verifies each on hardware, so no gate is tightened on theory alone.

Since
0.1.0

Definition in file board_periph_prcr.c.

Enumeration Type Documentation

◆ prcr_geom_t

enum prcr_geom_t : uint64_t

PRCR window geometry (HUM Ch 13.2.1 p 522).

Enumerator
k_prcr_base 

PRCR_S: SYSC base 0x4001_E000 + 0x3FA.

k_prcr_span 

One 16-bit register.

Definition at line 47 of file board_periph_prcr.c.

◆ prcr_mask_t

enum prcr_mask_t : uint16_t

PRCR field masks (HUM Ch 13.2.1 p 522).

Enumerator
k_prcr_key_mask 

PRKEY[7:0] lives in bits 15:8.

k_prcr_key_value 

Mandatory 0xA5 write key.

k_prcr_group_mask 

PRC0/1/3/4/5; bit 2 + 7:6 reserved.

Definition at line 53 of file board_periph_prcr.c.

◆ prcr_order_t

enum prcr_order_t : uint32_t

Per-tick order slot for the PRCR block (relative order).

Enumerator
k_prcr_block_order 

Just before the VBATT-backup block.

Definition at line 60 of file board_periph_prcr.c.

Function Documentation

◆ internal_prcr_block_register()

void internal_prcr_block_register ( void )
static

Register the PRCR block before main (host constructor).

Definition at line 192 of file board_periph_prcr.c.

References board_periph_register_block(), RA8_INTERNAL, and s_k_prcr_block.

◆ internal_prcr_read()

uint64_t internal_prcr_read ( uc_engine * uc,
uint64_t addr,
unsigned size )
static

MMIO read stub – never called for an observe-only block.

The sparse fallback answers PRCR reads (the block snoops rather than owns its window), so this exists only to satisfy the descriptor's required read slot.

Parameters
[in,out]ucUnicorn engine whose emulated state is read or updated.
[in]addrGuest address involved in the operation.
[in]sizeSize of the requested region or access in bytes.
Returns
The prcr read result produced by the board periph prcr model.
Return values
valueThe operation-specific prcr read value.
Precondition
Arguments satisfy the ranges documented for prcr read.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph prcr model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 111 of file board_periph_prcr.c.

References RA8_INTERNAL.

◆ internal_prcr_report()

void internal_prcr_report ( void )
static

End-of-run PRCR section: unlock traffic and any key mistakes.

End-of-run prcr section: unlock traffic and any key mistakes; this step is contained within the board periph prcr model and uses bounded caller or module-owned storage.

Precondition
Arguments satisfy the ranges documented for prcr report.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph prcr model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 161 of file board_periph_prcr.c.

References priv_emu_io_errf(), RA8_INTERNAL, and s_prcr.

◆ internal_prcr_reset()

void internal_prcr_reset ( void )
static

Return PRCR to its power-on state: every group locked.

HUM Ch 13.2.1 p 522 gives PRCR a reset value of 0x0000, so no group is write-enabled until firmware presents the key.

Precondition
Arguments satisfy the ranges documented for prcr reset.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph prcr model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 85 of file board_periph_prcr.c.

References RA8_INTERNAL, and s_prcr.

◆ internal_prcr_write()

void internal_prcr_write ( uc_engine * uc,
uint64_t addr,
unsigned size,
uint64_t value )
static

Snoop a PRCR write and update the retained group mask.

HUM Ch 13.2.1 p 522: "PRKEY[7:0] ... Write 0xA5 to this bit field to permit the write to the PRCn bits." A write whose key byte is not 0xA5 is discarded and leaves the mask untouched – modelled here so firmware that forgets the key gets the silicon result (no unlock) rather than a free one.

Parameters
[in,out]ucUnicorn engine whose emulated state is read or updated.
[in]addrGuest address involved in the operation.
[in]sizeSize of the requested region or access in bytes.
[in]valueRegister or payload value involved in the operation.
Precondition
Arguments satisfy the ranges documented for prcr write.
The call executes on the emulator's single owning thread.
Postcondition
State changes remain confined to the board periph prcr model and documented output objects.
Ownership of caller-supplied storage is unchanged.
Note
The operation is synchronous and does not transfer heap ownership.
Since
0.1.0

Definition at line 137 of file board_periph_prcr.c.

References k_prcr_group_mask, k_prcr_key_mask, k_prcr_key_value, and s_prcr.

◆ priv_board_prcr_group_unlocked()

bool priv_board_prcr_group_unlocked ( uint16_t group_mask)

Report whether every bit in group_mask is currently unlocked.

Reflects the last PRCR write that carried the correct 0xA5 key. A write with a wrong key is ignored by the hardware and by this model, so the mask keeps its previous value.

Parameters
[in]group_maskOne or more k_board_prcr_grp* bits.
Returns
true when all requested groups are write-enabled.
Return values
trueEvery bit in group_mask is set in the live PRCR mask.
falseAt least one requested group is still locked.
Precondition
group_mask names only bits defined by board_prcr_group_t.
The PRCR block is registered (host constructor, before main).
Postcondition
No state is mutated.
Note
Not thread-safe; ra8_emulator drives all blocks from one thread.
Since
0.1.0
Postcondition
Ownership of caller-supplied storage is unchanged.

Definition at line 90 of file board_periph_prcr.c.

References RA8_PRIV, and s_prcr.

Referenced by internal_bkup_write(), and internal_pdctr_write().

Variable Documentation

◆ s_k_prcr_block

const board_periph_block_t s_k_prcr_block
static
Initial value:
= {
.base = (uint64_t)k_prcr_base,
.span = (uint64_t)k_prcr_span,
.order = (uint32_t)k_prcr_block_order,
.tick = nullptr,
.name = "SYSC-PRCR",
.observe = true,
}
static uint64_t internal_prcr_read(uc_engine *uc, uint64_t addr, unsigned size)
MMIO read stub – never called for an observe-only block.
@ k_prcr_block_order
Just before the VBATT-backup block.
static void internal_prcr_reset(void)
Return PRCR to its power-on state: every group locked.
static void internal_prcr_report(void)
End-of-run PRCR section: unlock traffic and any key mistakes.
@ k_prcr_span
One 16-bit register.
@ k_prcr_base
PRCR_S: SYSC base 0x4001_E000 + 0x3FA.
static void internal_prcr_write(uc_engine *uc, uint64_t addr, unsigned size, uint64_t value)
Snoop a PRCR write and update the retained group mask.
-proof

PRCR block descriptor (observe-only: snoops, does not own).

Definition at line 178 of file board_periph_prcr.c.

Referenced by internal_prcr_block_register().

◆ s_prcr