From eaa39be9e45639381bb8060bf0c8f0e9d69d24b7 Mon Sep 17 00:00:00 2001 From: David Garske Date: Fri, 24 Jul 2026 08:40:34 -0700 Subject: [PATCH] renesas-rx: fix build for GCC RX 8.3/14.2 --- arch.mk | 13 +++++++++++-- config/examples/renesas-rx65n.config | 2 +- hal/renesas-rx.c | 8 ++++++++ hal/rx65n.ld | 4 +++- hal/rx72n.ld | 4 +++- include/printf.h | 3 +++ include/user_settings.h | 6 +++--- options.mk | 3 ++- src/boot_renesas_start.S | 8 ++------ test-app/Makefile | 23 ++++++++++++++++++++--- test-app/app_renesas_rx.c | 18 ++++++++++++++++++ test-app/syscalls.c | 9 +++++++++ tools/bin-assemble/bin-assemble.c | 10 +++++----- tools/keytools/sign.c | 8 ++++---- 14 files changed, 92 insertions(+), 27 deletions(-) diff --git a/arch.mk b/arch.mk index 14072a90..53ede8b2 100644 --- a/arch.mk +++ b/arch.mk @@ -765,8 +765,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 @@ -795,10 +794,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 \ diff --git a/config/examples/renesas-rx65n.config b/config/examples/renesas-rx65n.config index 64eb33d1..391bfe07 100644 --- a/config/examples/renesas-rx65n.config +++ b/config/examples/renesas-rx65n.config @@ -3,7 +3,7 @@ TARGET?=rx65n SIGN?=ECC256 HASH?=SHA256 DEBUG?=0 -DEBUG_UART?=0 +DEBUG_UART?=1 VTOR?=1 NO_ASM?=0 NO_MPU=1 diff --git a/hal/renesas-rx.c b/hal/renesas-rx.c index 7902d0b7..1b4dc8be 100644 --- a/hal/renesas-rx.c +++ b/hal/renesas-rx.c @@ -214,6 +214,14 @@ void uart_write(const char* buf, unsigned int sz) SCI_TDR(DEBUG_UART_SCI) = c; } } +void uart_read(char* buf, unsigned int sz) +{ + uint32_t pos = 0; + while (sz-- > 0) { + while ((SCI_SSR(DEBUG_UART_SCI) & SCI_SSR_RDRF) == 0); + buf[pos++] = (char)SCI_RDR(DEBUG_UART_SCI); + } +} #endif /* DEBUG_UART */ /* LOCO clock is used out of reset */ diff --git a/hal/rx65n.ld b/hal/rx65n.ld index 74b6599e..99a8c1dc 100644 --- a/hal/rx65n.ld +++ b/hal/rx65n.ld @@ -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) diff --git a/hal/rx72n.ld b/hal/rx72n.ld index 6e632c01..65a009b0 100644 --- a/hal/rx72n.ld +++ b/hal/rx72n.ld @@ -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) diff --git a/include/printf.h b/include/printf.h index 758403f5..6a5661ed 100644 --- a/include/printf.h +++ b/include/printf.h @@ -39,6 +39,9 @@ void uart_init(void); #endif void uart_write(const char* buf, unsigned int sz); + #if defined(__RX__) + void uart_read(char* buf, unsigned int sz); + #endif /* turn on small printf support in string.c */ #if !defined(PRINTF_ENABLED) && !defined(NO_PRINTF_UART) diff --git a/include/user_settings.h b/include/user_settings.h index f6beb2a8..429bd424 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -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) && \ diff --git a/options.mk b/options.mk index ddf3bda4..6f9b9ae4 100644 --- a/options.mk +++ b/options.mk @@ -936,7 +936,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 diff --git a/src/boot_renesas_start.S b/src/boot_renesas_start.S index 1d278885..a499bd9e 100644 --- a/src/boot_renesas_start.S +++ b/src/boot_renesas_start.S @@ -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 diff --git a/test-app/Makefile b/test-app/Makefile index 7ccd9030..3230edb4 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -99,13 +99,19 @@ else 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 ifeq ($(ARCH),RENESAS_RX) APP_OBJS:=app_renesas_rx.o ../test-app/libwolfboot.o ../src/boot_renesas.o ../src/boot_renesas_start.o ../hal/renesas-rx.o - LDFLAGS+=-ffreestanding -nostartfiles + # -ffreestanding/-nostartfiles are gcc-driver flags. Only pass them when + # linking via gcc (USE_GCC=1); for USE_GCC=0 rx-elf-ld is invoked directly + # and rejects them (-ffreestanding is already in CFLAGS; ld adds no crt). + ifeq ($(USE_GCC),1) + LDFLAGS+=-ffreestanding -nostartfiles + endif CFLAGS+=-DWOLFBOOT_RENESAS_APP else ifeq ($(WOLFHAL),1) APP_OBJS:=app_wolfhal.o led.o system.o timer.o ../test-app/libwolfboot.o @@ -116,6 +122,13 @@ endif include ../arch.mk +# The Renesas RX app links with ld directly (USE_GCC=0), with no gcc driver to +# pull in newlib. syscalls.o provides a minimal stdio (printf/putchar/snprintf/ +# malloc) on top of uart_write, so the app links without libc. +ifeq ($(ARCH),RENESAS_RX) + APP_OBJS+=syscalls.o +endif + ifeq ($(USE_CLANG),1) APP_NEEDS_STRING:=1 endif @@ -136,8 +149,12 @@ ifeq ($(WOLFCRYPT_TZ_WOLFHSM),1) WOLFCRYPT_TZ_WOLFHSM=1 endif -# Setup default linker flags +# Setup default linker flags (gcc-driver form). Renesas RX links with ld +# directly (USE_GCC=0) and gets its -T/-gc-sections/oformat from arch.mk, so +# these gcc-driver flags (-Wl,/-nostartfiles and a duplicate -T) are skipped. +ifneq ($(ARCH),RENESAS_RX) LDFLAGS+=-T $(LSCRIPT) -Wl,-gc-sections -Wl,-Map=image.map -nostartfiles +endif # Setup default objcopy flags OBJCOPY_FLAGS+=--gap-fill $(FILL_BYTE) diff --git a/test-app/app_renesas_rx.c b/test-app/app_renesas_rx.c index d2173da7..ab8073bc 100644 --- a/test-app/app_renesas_rx.c +++ b/test-app/app_renesas_rx.c @@ -34,10 +34,26 @@ int write(int fileno, char *buf, int count) { (void)fileno; +#ifdef DEBUG_UART uart_write(buf, count); +#else + (void)buf; +#endif return count; } +/* wait for a single key from the UART (used to pause the demo) */ +int getchar(void) +{ +#ifdef DEBUG_UART + char c = 0; + uart_read(&c, 1); + return (int)(unsigned char)c; +#else + return -1; +#endif +} + static const char* state2str(uint8_t s) { switch (s) { @@ -90,7 +106,9 @@ int main(void) { uint8_t firmware_version = 0; +#ifdef DEBUG_UART uart_init(); +#endif #if !defined(WOLFBOOT_RENESAS_TSIP) printf("| ------------------------------------------------------------------- |\n"); diff --git a/test-app/syscalls.c b/test-app/syscalls.c index 77e0cbe5..0a1559d7 100644 --- a/test-app/syscalls.c +++ b/test-app/syscalls.c @@ -125,6 +125,15 @@ void _exit(int status) } } +#if defined(__RX__) +/* GCC emits calls to abort() for trap paths; the RX app links without libc, + * so provide it here (halt). */ +void abort(void) +{ + _exit(1); +} +#endif + int _kill(int pid, int sig) { errno = EINVAL; diff --git a/tools/bin-assemble/bin-assemble.c b/tools/bin-assemble/bin-assemble.c index c65585bb..02bfede9 100644 --- a/tools/bin-assemble/bin-assemble.c +++ b/tools/bin-assemble/bin-assemble.c @@ -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) { @@ -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 @@ -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 @@ -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", @@ -184,7 +184,7 @@ int main(int argc, const char* argv[]) { cur_add = entries[0].address; for (i=0; i (uintmax_t)MAX_TLV_LEN) { printf("Error: Certificate chain too large for TLV encoding " - "(%ju > %u)\n", (uintmax_t)chain_file_sz, MAX_TLV_LEN); + "(%" PRIuMAX " > %u)\n", (uintmax_t)chain_file_sz, MAX_TLV_LEN); goto failure; } else { @@ -1584,7 +1584,7 @@ static int make_header_ex(int is_diff, uint8_t *pubkey, uint32_t pubkey_sz, if ((file_stat.st_size < 0) || ((uintmax_t)file_stat.st_size > (uintmax_t)UINT32_MAX)) { - printf("Error: Invalid certificate chain file size (%jd)\n", + printf("Error: Invalid certificate chain file size (%" PRIdMAX ")\n", (intmax_t)file_stat.st_size); fclose(f); f = NULL; @@ -2563,7 +2563,7 @@ static int base_diff(const char *f_base, uint8_t *pubkey, uint32_t pubkey_sz, in (cc_stat.st_size >= 0)) { if ((uintmax_t)cc_stat.st_size > (uintmax_t)MAX_TLV_LEN) { printf("Error: Certificate chain too large for TLV encoding " - "(%ju > %u)\n", (uintmax_t)cc_stat.st_size, MAX_TLV_LEN); + "(%" PRIuMAX " > %u)\n", (uintmax_t)cc_stat.st_size, MAX_TLV_LEN); goto cleanup; } cert_chain_sz = (uint32_t)cc_stat.st_size;