Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/test-build-renesas-rx.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Wolfboot Reusable Build Workflow (Renesas RX)

# Builds a Renesas RX example config with the GNU RX (GNURX) toolchain.
# GNURX is login-gated (no public URL), so it is provided via a prebuilt
# container image, as done for PowerPC. To enable: publish
# ghcr.io/wolfssl/wolfboot-ci-rx (GNURX rx-elf-* on PATH) and set repo
# variable ENABLE_RENESAS_RX_CI=true (see test-configs.yml).

on:

workflow_call:
inputs:
arch:
required: true
type: string
config-file:
required: true
type: string
make-args:
required: false
type: string

jobs:

build:
runs-on: ubuntu-latest
container:
image: ghcr.io/wolfssl/wolfboot-ci-rx:v1
timeout-minutes: 30

steps:
- uses: actions/checkout@v4
with:
submodules: true

- name: Trust workspace
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"

- name: make clean
run: |
make distclean

- name: Select config
run: |
cp ${{inputs.config-file}} .config

- name: Build tools
run: |
make -C tools/keytools && make -C tools/bin-assemble

- name: Build wolfboot
run: |
make USE_GCC=0 CROSS_COMPILE=rx-elf- ${{inputs.make-args}}
24 changes: 24 additions & 0 deletions .github/workflows/test-configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -862,3 +862,27 @@ jobs:
arch: arm
config-file: ./config/examples/rp2350.config
target: rp2350

# Renesas RX builds (GNURX). Gated on ENABLE_RENESAS_RX_CI until the
# wolfboot-ci-rx image is published (GNURX is login-gated).
renesas_rx65n_test:
if: ${{ vars.ENABLE_RENESAS_RX_CI == 'true' }}
uses: ./.github/workflows/test-build-renesas-rx.yml
with:
arch: rx
config-file: ./config/examples/renesas-rx65n.config

renesas_rx65n_bigendian_test:
if: ${{ vars.ENABLE_RENESAS_RX_CI == 'true' }}
uses: ./.github/workflows/test-build-renesas-rx.yml
with:
arch: rx
config-file: ./config/examples/renesas-rx65n.config
make-args: BIG_ENDIAN=1 DEBUG_SYMBOLS=1

renesas_rx72n_test:
if: ${{ vars.ENABLE_RENESAS_RX_CI == 'true' }}
uses: ./.github/workflows/test-build-renesas-rx.yml
with:
arch: rx
config-file: ./config/examples/renesas-rx72n.config
13 changes: 11 additions & 2 deletions arch.mk
Original file line number Diff line number Diff line change
Expand Up @@ -721,8 +721,7 @@ ifeq ($(ARCH),RENESAS_RX)
CFLAGS+=-ffunction-sections -fdata-sections
CFLAGS+=-B$(dir $(CROSS_COMPILE))
LDFLAGS+=-gc-sections -Map=wolfboot.map
LDFLAGS+=-T $(LSCRIPT) -L$(dir $(CROSS_COMPILE))../lib
LIBS+=-lgcc
LDFLAGS+=-T $(LSCRIPT)
endif

# Renesas specific files
Expand Down Expand Up @@ -751,10 +750,20 @@ ifeq ($(ARCH),RENESAS_RX)
endif
endif

# ld is invoked directly, so add libgcc for the selected multilib (GNU RX
# stores it per-endianness/-nofpu under lib/gcc/..., not in ../lib).
ifeq ($(USE_GCC),0)
LIBS+=$(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
endif

ifeq ($(PKA),1)
CFLAGS+=-DWOLFBOOT_RENESAS_TSIP
CFLAGS+=-DWOLFBOOT_DEVID_PUBKEY=7890
CFLAGS+=-DWOLFBOOT_DEVID_CRYPT=7891
# GCC RX 14.2 -Werror=enum-conversion trips on the wolfSSL TSIP port; add
# the relaxation only if the compiler knows the warning (RX 8.3 does not).
CFLAGS+=$(shell echo '' | $(CC) -xc -fsyntax-only \
-Wno-error=enum-conversion - >/dev/null 2>&1 && echo -Wno-error=enum-conversion)
RX_DRIVER_PATH?=./lib

OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cryptocb.o \
Expand Down
4 changes: 4 additions & 0 deletions config/examples/renesas-rx65n.config
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ PKA?=0

# Location of reset entry point from start of flash
#CFLAGS_EXTRA+=-DBOOT_ENTRY_OFFSET=0x2C

# External watchdog (e.g. MAX6316-MAX6322): toggle WDI from wolfBoot's long
# loops. WATCHDOG_WDI_PORT = RX port, WATCHDOG_WDI_PIN = bit (see renesas-rx.c).
#CFLAGS_EXTRA+=-DWATCHDOG -DWATCHDOG_WDI_PORT=0 -DWATCHDOG_WDI_PIN=5
4 changes: 4 additions & 0 deletions config/examples/renesas-rx72n.config
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ PKA?=0

# Location of reset entry point from start of flash
#CFLAGS_EXTRA+=-DBOOT_ENTRY_OFFSET=0x2C

# External watchdog (e.g. MAX6316-MAX6322): toggle WDI from wolfBoot's long
# loops. WATCHDOG_WDI_PORT = RX port, WATCHDOG_WDI_PIN = bit (see renesas-rx.c).
#CFLAGS_EXTRA+=-DWATCHDOG -DWATCHDOG_WDI_PORT=0 -DWATCHDOG_WDI_PIN=5
11 changes: 11 additions & 0 deletions docs/Renesas.md
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,17 @@ The key needed for the firmware signing tool is the 32 byte AES Key + 16 byte IV
| RX65N | 120MHz | ECDSA Verify P256 | 2.95 ms | 1208 ms | 602 ms | 517 ms |


## RX External Watchdog (MAX6316-MAX6322)

An external windowed watchdog resets the MCU unless its `WDI` input sees an edge each timeout period, which image verification or a swap can exceed. Build with `WATCHDOG` and point it at the GPIO wired to `WDI`:

```
CFLAGS_EXTRA+=-DWATCHDOG -DWATCHDOG_WDI_PORT=0 -DWATCHDOG_WDI_PIN=5
```

`WATCHDOG_WDI_PORT` is the RX port number and `WATCHDOG_WDI_PIN` the bit (0-7). wolfBoot calls `wolfBoot_watchdog_feed()` from its hash and flash copy/erase loops; the RX HAL toggles `WDI` to restart the timer. The application must keep servicing `WDI` after boot. `wolfBoot_watchdog_feed()` is a weak no-op by default (`include/hal.h`), so any port can override it for a different watchdog.


## RX Production Protection (recommendations)

1) Lockdown external serial programmer `SPCC.SPE = 0`
Expand Down
2 changes: 1 addition & 1 deletion docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -6915,7 +6915,7 @@ The following build options are available for the S32K1xx HAL:
| `RAM_CODE` | **Required for S32K1xx.** Run flash operations from RAM (no read-while-write on same block). |
| `WOLFBOOT_RESTORE_CLOCK` | Restore clock to SIRC (8 MHz) before booting application. Recommended for applications that configure their own clocks. |
| `WOLFBOOT_DISABLE_WATCHDOG_ON_BOOT` | Keep watchdog disabled when jumping to application. By default, the watchdog is re-enabled before boot since it is enabled out of reset. |
| `WATCHDOG` | Enable watchdog during wolfBoot operation. Recommended for production. |
| `WATCHDOG` | Enable the watchdog during wolfBoot operation. wolfBoot calls `wolfBoot_watchdog_feed()` from its hash and copy/erase loops -- a weak no-op a port overrides to service its watchdog (e.g. external MAX6316-MAX6322, see `hal/renesas-rx.c`). |
| `WATCHDOG_TIMEOUT_MS` | Watchdog timeout in milliseconds when `WATCHDOG` is enabled (default: 1000ms). |
| `S32K1XX_CLOCK_HSRUN` | Enable HSRUN mode (112 MHz). Requires external crystal and SPLL (not fully implemented). |
| `DEBUG_UART` | Enable LPUART1 debug output. |
Expand Down
29 changes: 29 additions & 0 deletions hal/renesas-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -464,6 +464,31 @@ int hal_renesas_init(void)
#endif /* TSIP */


#ifdef WATCHDOG
/* External watchdog (e.g. MAX6316-MAX6322): toggle the WDI GPIO so a signal
* edge restarts its timer. Pin set by WATCHDOG_WDI_PORT/WATCHDOG_WDI_PIN. */
#ifndef WATCHDOG_WDI_PORT
#define WATCHDOG_WDI_PORT 0 /* PORT0 */
#endif
#ifndef WATCHDOG_WDI_PIN
#define WATCHDOG_WDI_PIN 0
#endif

static void hal_watchdog_init(void)
{
/* Drive WDI as a general-purpose CMOS output */
PORT_PMR(WATCHDOG_WDI_PORT) &= (uint8_t)~(1U << WATCHDOG_WDI_PIN);
PORT_PDR(WATCHDOG_WDI_PORT) |= (uint8_t) (1U << WATCHDOG_WDI_PIN);
}

/* RAMFUNCTION: callable from the RAM-resident flash paths. */
void RAMFUNCTION wolfBoot_watchdog_feed(void)
{
/* Toggle WDI: any transition restarts the external watchdog timer */
PORT_PODR(WATCHDOG_WDI_PORT) ^= (uint8_t)(1U << WATCHDOG_WDI_PIN);
}
#endif /* WATCHDOG */

void hal_init(void)
{
#if defined(WOLFBOOT_RENESAS_TSIP) && !defined(WOLFBOOT_RENESAS_APP)
Expand All @@ -486,6 +511,10 @@ void hal_init(void)

hal_flash_init();

#ifdef WATCHDOG
hal_watchdog_init();
#endif

#if defined(WOLFBOOT_RENESAS_TSIP) && !defined(WOLFBOOT_RENESAS_APP)
err = hal_renesas_init();
if (err != 0) {
Expand Down
4 changes: 3 additions & 1 deletion hal/rx65n.ld
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,9 @@ SECTIONS
_edata = .;
} > RAM

.bss :
/* Pin .bss LMA to its VMA; else it chains past ROM at the top of the
* address space and newer ld errors "LMA wraps around address space". */
.bss (NOLOAD) : AT (ADDR (.bss))
{
_bss = .;
*(.dynbss)
Expand Down
4 changes: 3 additions & 1 deletion hal/rx72n.ld
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ SECTIONS
_edata = .;
} > RAM

.bss :
/* Pin .bss LMA to its VMA; else it chains past ROM at the top of the
* address space and newer ld errors "LMA wraps around address space". */
.bss (NOLOAD) : AT (ADDR (.bss))
{
_bss = .;
*(.dynbss)
Expand Down
9 changes: 9 additions & 0 deletions include/hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ void hal_prepare_boot(void);
const char* hal_fit_config_name(void);
#endif

/* Optional watchdog kick. With -DWATCHDOG, wolfBoot calls this from its long
* hash and flash copy/erase loops; a port overrides the weak no-op default
* (see libwolfboot.c, hal/renesas-rx.c). Compiles out when WATCHDOG is unset. */
#ifdef WATCHDOG
void wolfBoot_watchdog_feed(void);
#else
#define wolfBoot_watchdog_feed() do {} while (0)
#endif

/* FPGA load mode constants + hal_fpga_load() prototype (kept in a standalone
* header so the per-target HAL .c files can include just this, not all of
* hal.h). Gated internally by WOLFBOOT_FPGA_BITSTREAM. */
Expand Down
6 changes: 3 additions & 3 deletions include/user_settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,9 @@ extern int tolower(int c);
# if !defined(WOLFBOOT_TPM)
# define NO_ECC_SIGN
# define NO_ECC_DHE
/* For Renesas RX do not enable the misc.c constant time code
* due to issue with 64-bit types */
# if defined(__RX__)
/* Old GNU RX 4.x miscompiled misc.c 64-bit constant-time ops;
* newer RX needs them (sp_int.c uses ctMaskLT). */
# if defined(__RX__) && defined(__GNUC__) && (__GNUC__ < 5)
# define WOLFSSL_NO_CT_OPS /* don't use constant time ops in misc.c */
# endif
# if !defined(WOLFBOOT_ENABLE_WOLFHSM_CLIENT) && \
Expand Down
3 changes: 2 additions & 1 deletion options.mk
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,8 @@ ifeq ($(DEBUG_SYMBOLS),1)
CFLAGS+=-ggdb3
else ifneq ($(ARCH),AURIX_TC3)
ifneq ($(USE_CLANG),1)
CFLAGS+=-gstabs
# -gstabs was removed in GCC 12; -gdwarf-4 works on old and new GCC
CFLAGS+=-gdwarf-4
endif
endif
endif
Expand Down
8 changes: 2 additions & 6 deletions src/boot_renesas_start.S
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,9 @@ __rx_fini:

.global _exit
.type _exit, @function
/* call to exit */
/* main never returns; halt. Don't call newlib __call_exitprocs -- wolfBoot
* does not link libc, so it fails to link on newer binutils. */
_exit:
mov #0, r2
#ifndef NO_LEADING_UNDERSCORE
mov #___call_exitprocs, r7
#endif
jsr r7
_loop_here:
bra _loop_here

Expand Down
3 changes: 3 additions & 0 deletions src/image.c
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,7 @@ static int image_sha256(struct wolfBoot_image *img, uint8_t *hash)
blksz = img->fw_size - position;
wc_Sha256Update(&sha256_ctx, p, blksz);
position += blksz;
wolfBoot_watchdog_feed();
} while (position < img->fw_size);
}
#endif
Expand Down Expand Up @@ -1205,6 +1206,7 @@ static int image_sha384(struct wolfBoot_image *img, uint8_t *hash)
blksz = img->fw_size - position;
wc_Sha384Update(&sha384_ctx, p, blksz);
position += blksz;
wolfBoot_watchdog_feed();
} while (position < img->fw_size);
}
#endif
Expand Down Expand Up @@ -1322,6 +1324,7 @@ static int image_sha3_384(struct wolfBoot_image *img, uint8_t *hash)
blksz = img->fw_size - position;
wc_Sha3_384_Update(&sha3_ctx, p, blksz);
position += blksz;
wolfBoot_watchdog_feed();
} while (position < img->fw_size);
}
#endif
Expand Down
9 changes: 9 additions & 0 deletions src/libwolfboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@
#include "image.h"
#include "printf.h"

#ifdef WATCHDOG
/* Weak no-op default; a port HAL overrides this to service the watchdog.
* RAMFUNCTION so the fallback is safe when called from the RAM-resident flash
* paths (update_flash.c) on RAM_CODE targets. */
void RAMFUNCTION WEAKFUNCTION wolfBoot_watchdog_feed(void)
{
}
#endif

#ifdef UNIT_TEST
/**
* @def unit_dbg
Expand Down
4 changes: 4 additions & 0 deletions src/update_flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,9 @@ static int RAMFUNCTION wolfBoot_copy_sector(struct wolfBoot_image *src,
wolfBoot_printf("Copy sector %d (part %d->%d)\n",
sector, src->part, dst->part);

/* Kick the watchdog once per sector copy (no-op unless -DWATCHDOG) */
wolfBoot_watchdog_feed();

if (src->part == PART_SWAP)
src_sector_offset = 0;
if (dst->part == PART_SWAP)
Expand Down Expand Up @@ -1213,6 +1216,7 @@ static int RAMFUNCTION wolfBoot_update(int fallback_allowed)
) {
wb_flash_erase(&boot, sector * sector_size, sector_size);
wb_flash_erase(&update, sector * sector_size, sector_size);
wolfBoot_watchdog_feed();
sector++;
}
#endif /* WOLFBOOT_FLASH_MULTI_SECTOR_ERASE */
Expand Down
10 changes: 5 additions & 5 deletions tools/bin-assemble/bin-assemble.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ int binentry_address_compare(const void* a, const void* b)
}
}

#ifdef _WIN32
#ifdef _MSC_VER
/* 'strerror' has been explicitly marked deprecated */
static const char* win_strerror(int err, char* buf, size_t bufsz) {
if (strerror_s(buf, bufsz, err) != 0) {
Expand All @@ -83,7 +83,7 @@ static const char* win_strerror(int err, char* buf, size_t bufsz) {
#endif

int main(int argc, const char* argv[]) {
#ifdef _WIN32
#ifdef _MSC_VER
char errbuf[128] = { 0 };
errno_t fe;
#endif
Expand Down Expand Up @@ -127,7 +127,7 @@ int main(int argc, const char* argv[]) {
entries[i].fname = argv[2 * i + 3];

if (stat(entries[i].fname, &st)) {
#ifdef _WIN32
#ifdef _MSC_VER
fprintf(stderr, "unable to stat %s: %s\n",
entries[i].fname, win_strerror(errno, errbuf, sizeof errbuf));
#else
Expand Down Expand Up @@ -166,7 +166,7 @@ int main(int argc, const char* argv[]) {
}

// TODO: consider handling stdout "-"
#ifdef _WIN32
#ifdef _MSC_VER
fe = fopen_s(&fo, outname, "wb");
if (fo == NULL || fe != 0) {
fprintf(stderr, "opening %s failed %s\n",
Expand All @@ -184,7 +184,7 @@ int main(int argc, const char* argv[]) {
cur_add = entries[0].address;
for (i=0; i<num_entries; i++) {
size_t fillSz = entries[i].address - cur_add;
#ifdef _WIN32
#ifdef _MSC_VER
fe = fopen_s(&fi, entries[i].fname, "rb");
if (fi == NULL || fe != 0) {
fprintf(stderr, "opening %s failed %s\n",
Expand Down
Loading
Loading