Skip to content

Commit 441d871

Browse files
committed
Add wolfBoot HAL port for RealTek RTL8735B (AmebaPro2)
1 parent 4308b36 commit 441d871

11 files changed

Lines changed: 1323 additions & 0 deletions

File tree

arch.mk

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,66 @@ ifeq ($(ARCH),ARM)
336336
CFLAGS+=-I$(PICO_SDK_PATH)/src/common/pico_stdlib_headers/include
337337
endif
338338

339+
ifeq ($(TARGET),rtl8735b)
340+
# RealTek RTL8735B SoC (Cortex-M33), e.g. the AmebaPro2 EVB. wolfBoot is
341+
# staged into SRAM by the RealTek bootloader and copies the verified app
342+
# from external SPI NOR into DDR before jumping (src/update_ram.c RAMBOOT).
343+
CORTEX_M33=1
344+
CFLAGS+=-Ihal
345+
# ASDK 10.3.0 toolchain (system arm-none-eabi-gcc clashes on newlib/lwip).
346+
CROSS_COMPILE:=$(ASDK_PATH)/arm-none-eabi-
347+
# Match the RealTek SDK FPU/ABI (-mfpu=fpv5-sp-d16 -mfloat-abi=softfp) so
348+
# linking the SDK libraries is consistent; wolfBoot enables the FPU at
349+
# hal_init before any SDK code runs.
350+
CFLAGS+=-mfpu=fpv5-sp-d16 -mfloat-abi=softfp
351+
LDFLAGS+=-mfpu=fpv5-sp-d16 -mfloat-abi=softfp
352+
UPDATE_OBJS:=src/update_ram.o
353+
CFLAGS+=-DWOLFBOOT_DUALBOOT
354+
CFLAGS+=-ffunction-sections -fdata-sections
355+
LDFLAGS+=-Wl,--gc-sections
356+
# Flash/UART/cache backend: "sdk" (default, RealTek SDK drivers) or "bare"
357+
# (smaller, no SDK dependency -- not yet implemented). See hal/rtl8735b.c.
358+
HAL_BACKEND?=sdk
359+
ifeq ($(HAL_BACKEND),sdk)
360+
CFLAGS+=-DHAL_BACKEND_SDK
361+
# The SDK backend folds the RealTek SDK driver chain into hal/rtl8735b.o.
362+
# Its objects.h pulls the SDK's "hal.h" (defines flash_t,
363+
# hal_audio_adapter_t, ...); wolfBoot also ships "hal.h". hal/rtl8735b.c
364+
# does not include wolfBoot's hal.h, and the SDK dirs are passed with
365+
# -iquote (searched before the global -I for quoted includes) so the SDK
366+
# objects.h "hal.h" resolves to the SDK one for THIS object only. sdk-shim
367+
# supplies a stub cmsis_os.h so the chain does not pull CMSIS-OS/FreeRTOS
368+
# (wolfBoot never calls it). The CONFIG_* defines mirror the bare-metal
369+
# bootloader build; -mcmse satisfies the SDK cache header (SCB_NS). The
370+
# rest of wolfBoot stays plain M33.
371+
HAL_SDK_IQUOTE=-iquote $(WOLFBOOT_ROOT)/hal/rtl8735b/sdk-shim \
372+
-iquote $(AMEBA_SDK)/component/mbed/hal_ext \
373+
-iquote $(AMEBA_SDK)/component/mbed/hal \
374+
-iquote $(AMEBA_SDK)/component/mbed/api \
375+
-iquote $(AMEBA_SDK)/component/mbed/targets/hal/rtl8735b \
376+
-iquote $(AMEBA_SDK)/component/soc/8735b/fwlib/rtl8735b/include \
377+
-iquote $(AMEBA_SDK)/component/soc/8735b/fwlib/rtl8735b/lib/include \
378+
-iquote $(AMEBA_SDK)/component/soc/8735b/cmsis/rtl8735b/include \
379+
-iquote $(AMEBA_SDK)/component/soc/8735b/cmsis/rtl8735b/lib/include \
380+
-iquote $(AMEBA_SDK)/component/soc/8735b/cmsis/cmsis-core/include \
381+
-iquote $(AMEBA_SDK)/component/soc/8735b/app/rtl_printf/include \
382+
-iquote $(AMEBA_SDK)/component/soc/8735b/app/stdio_port \
383+
-iquote $(AMEBA_SDK)/component/soc/8735b/misc/utilities/include \
384+
-iquote $(AMEBA_SDK)/component/os/os_dep/include
385+
# The same dirs as plain -I too, so angle-bracket includes (e.g. some
386+
# CMSIS-Core headers) resolve; -iquote only covers quoted includes.
387+
HAL_SDK_INC=$(patsubst -iquote,-I,$(HAL_SDK_IQUOTE))
388+
HAL_SDK_DEFS=-DCONFIG_PLATFORM_8735B -DCONFIG_RTL8735B_PLATFORM=1 \
389+
-DCONFIG_BUILD_RAM=1
390+
hal/rtl8735b.o: CFLAGS += $(HAL_SDK_IQUOTE) $(HAL_SDK_INC) $(HAL_SDK_DEFS) -mcmse
391+
# Final link also needs the SDK fwlib + ROM symbol table; point at the
392+
# prebuilt SDK lib/objects and ROM symbol linker file during bring-up:
393+
# make TARGET=rtl8735b LIBS+=... LDFLAGS_EXTRA="-T<rom_symbol.ld>"
394+
else
395+
CFLAGS+=-DHAL_BACKEND_BARE
396+
endif
397+
endif
398+
339399
ifeq ($(TARGET),sama5d3)
340400
CORTEX_A5=1
341401
UPDATE_OBJS:=src/update_ram.o

config/examples/rtl8735b.config

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
ARCH?=ARM
2+
TARGET?=rtl8735b
3+
SIGN?=ECC256
4+
HASH?=SHA256
5+
6+
# ECC256 + SHA256 header fits in 256 bytes
7+
IMAGE_HEADER_SIZE?=256
8+
9+
# Cortex-M33 (single, non-TrustZone secure world for Model A)
10+
CORTEX_M33?=1
11+
TZEN?=0
12+
VTOR?=1
13+
NO_MPU?=1
14+
15+
# wolfBoot is staged into SRAM by the RealTek bootloader (not XIP). It reads the
16+
# BOOT/UPDATE/SWAP partitions from external SPI NOR and copies the verified
17+
# application into DDR before jumping (src/update_ram.c RAMBOOT path).
18+
NO_XIP?=1
19+
EXT_FLASH?=1
20+
SPI_FLASH?=0
21+
WOLFBOOT_DUALBOOT?=1
22+
23+
# wolfBoot runs entirely from SRAM, so RAM_CODE relocation is unnecessary.
24+
RAM_CODE?=0
25+
26+
DEBUG?=0
27+
DEBUG_UART?=1
28+
V?=0
29+
SPMATH?=1
30+
ALLOW_DOWNGRADE?=0
31+
NVM_FLASH_WRITEONCE?=0
32+
33+
WOLFBOOT_VERSION?=1
34+
35+
# 4 KB SPI NOR sector (flash_erase_sector granularity)
36+
WOLFBOOT_SECTOR_SIZE?=0x1000
37+
38+
# DDR address the verified application is copied to and launched from. Must
39+
# match the application's vector-table link address. The DDR memory window is
40+
# 0x70000000 (128 MB); load 1 MB in so the header (placed at LOAD-0x100 by the
41+
# RAMBOOT path) stays inside DDR. 0x70100000 matches the address proven by the
42+
# prior RealTek DDR bring-up on this board.
43+
WOLFBOOT_LOAD_ADDRESS?=0x70100000
44+
45+
# External SPI NOR partition layout. These are raw NOR byte offsets addressed
46+
# only by ext_flash_*. wolfBoot itself lives in the RealTek PT_FW1 region
47+
# (0x60000, 4 MB). The BOOT/UPDATE/SWAP partitions reuse the PT_FW2 region
48+
# (0x520000-0x920000, 4 MB) -- unused when wolfBoot is the only firmware -- so
49+
# they stay inside the 16 MB flash and do not overlap PARTBL/boot/PT_FW1/ISP/NN.
50+
WOLFBOOT_PARTITION_SIZE?=0x180000
51+
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x520000
52+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x6A0000
53+
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x820000
54+
55+
# Flash/UART/cache backend: "sdk" (default, RealTek SDK drivers) or "bare"
56+
# (smaller, no SDK dependency -- not yet implemented).
57+
HAL_BACKEND?=sdk
58+
59+
# RealTek SDK + ASDK toolchain locations (override on the command line).
60+
AMEBA_SDK?=$(HOME)/GitHub/ameba-rtos-pro2
61+
ASDK_PATH?=$(HOME)/ameba-pro2-workspace/asdk/asdk-10.3.0/linux/newlib/bin

docs/Targets.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ This README describes configuration of supported targets.
3434
* [NXP T2080 PPC](#nxp-qoriq-t2080-ppc)
3535
* [Qemu x86-64 UEFI](#qemu-x86-64-uefi)
3636
* [Raspberry Pi pico 2 (rp2350)](#raspberry-pi-pico-rp2350)
37+
* [RealTek RTL8735B (AmebaPro2)](#realtek-rtl8735b-amebapro2)
3738
* [Renesas RA6M4](#renesas-ra6m4)
3839
* [Renesas RX65N](#renesas-rx65n)
3940
* [Renesas RX72N](#renesas-rx72n)
@@ -8491,3 +8492,124 @@ Number of public keys: 1
84918492
11 0C FA F6 B5 F9 59 BA B9 A5 8E 34 4A CD C5 83
84928493
7E 43 EF 61 6E C4 15 88 3C FE D6 76 47 D9 82 A4
84938494
```
8495+
8496+
## RealTek RTL8735B (AmebaPro2)
8497+
8498+
Tested on the RealTek RTL8735B (AmebaPro2) EVB. The RTL8735B is an Arm Cortex-M33 AIoT SoC with a vendor secure-boot ROM, an external SPI NOR flash, and DDR/PSRAM.
8499+
8500+
wolfBoot does not replace the RealTek secure-boot ROM; it runs as a second-stage verified bootloader and A/B firmware-update engine. The RealTek ROM authenticates `boot.bin`, `boot.bin` stages wolfBoot into SRAM via a RealTek `RAM_FUNCTION_START_TABLE`, and wolfBoot then verifies the application in external SPI NOR, applies any pending update, copies the verified image into DDR, and jumps to it. This is the non-TrustZone "Model A" integration.
8501+
8502+
Because wolfBoot runs from SRAM and its partitions live in external SPI NOR, the target uses `EXT_FLASH=1` and `NO_XIP=1`; the application is loaded to `WOLFBOOT_LOAD_ADDRESS` in DDR by the `src/update_ram.c` RAMBOOT path.
8503+
8504+
### Flash/UART/cache backend
8505+
8506+
The HAL (`hal/rtl8735b.c`) has two backends, selected with `HAL_BACKEND`:
8507+
8508+
* `HAL_BACKEND=sdk` (default) - flash and cache use the RealTek SDK drivers (`flash_api`, `hal_cache`); the `DEBUG_UART` console uses a small self-contained UART1 driver in the HAL (it does not depend on the OS-bound SDK `hal_uart_init`). wolfBoot links against the SDK SoC libraries and the ROM symbol table.
8509+
* `HAL_BACKEND=bare` - scaffold for a smaller backend with no SDK dependency (direct register/ROM access). It links a standalone `wolfboot.elf`, but the `ext_flash_*` entry points are still stubs that return `-1`, so it is not yet functional. Work in progress.
8510+
8511+
### Console (DEBUG_UART)
8512+
8513+
`DEBUG_UART=1` routes wolfBoot's log to UART1 (the RealTek "LOGUART" at `0x40040400`, pins PORT_F pin 4 = TX / pin 3 = RX), which reaches the EVB USB serial console at 115200 8N1. wolfBoot brings UART1 up itself (pinmux + clock enable + 115200 8N1). The RealTek boot ROM and `boot.bin` also print on this same UART before wolfBoot, so the vendor boot messages appear first, followed immediately by the wolfBoot banner. A successful boot looks like:
8514+
8515+
```
8516+
wolfBoot HAL: RTL8735B (AmebaPro2) init
8517+
wolfBoot HAL: flash init done
8518+
Versions: Boot 1, Update 0
8519+
Trying Boot partition at 0x520000
8520+
Loading header 256 bytes from 0x520000 to 0x700FFF00
8521+
Loading image 132 bytes from 0x520100 to 0x70100000...done
8522+
Checking integrity...done
8523+
Verifying signature...done
8524+
Booting at 0x70100000
8525+
```
8526+
8527+
### Partition layout
8528+
8529+
wolfBoot itself is packaged into the RealTek `PT_FW1` region (`0x60000`). The BOOT/UPDATE partitions are raw SPI NOR offsets (addressed only by `ext_flash_*`) carved out of the unused `PT_FW2` region so they do not collide with the RealTek partition table:
8530+
8531+
| Partition | Address | Size | Description |
8532+
|-------------|------------|-----------|-------------|
8533+
| Boot | 0x520000 | 0x180000 | Running, verified application |
8534+
| Update | 0x6A0000 | 0x180000 | Staged incoming update |
8535+
| Swap | 0x820000 | 0x1000 | Reserved (see note) |
8536+
8537+
These addresses are board-specific; confirm them against the board's `amebapro2_partitiontable.json`. The Swap partition is reserved by the configuration but unused in this RAMBOOT model, which selects between BOOT and UPDATE by version rather than copy-swapping through a swap sector.
8538+
8539+
### Application load address
8540+
8541+
The verified application is copied into DDR at `WOLFBOOT_LOAD_ADDRESS` (`0x70100000`) and launched there. The application's vector table must be linked to this same address: `do_boot()` reads word[0] as the initial MSP and word[1] as the entry point, and sets `VTOR` to the base. The DDR memory window starts at `0x70000000` (128 MB); the load address is kept 1 MB inside it because the RAMBOOT path places the image header at `WOLFBOOT_LOAD_ADDRESS - IMAGE_HEADER_SIZE`, which must also land in DDR.
8542+
8543+
### Building RealTek RTL8735B
8544+
8545+
All build settings come from the `.config` file. Use `TARGET=rtl8735b` and the RealTek ASDK toolchain (the system `arm-none-eabi-gcc` fails on newlib/lwip clashes). Point `AMEBA_SDK` at the RealTek `ameba-rtos-pro2` checkout and `ASDK_PATH` at the ASDK toolchain.
8546+
8547+
```sh
8548+
cp config/examples/rtl8735b.config .config
8549+
# Compile wolfBoot and perform the SDK-resolved final link (see note below).
8550+
tools/scripts/rtl8735b_build.sh
8551+
# Wrap wolfBoot with the RealTek partition table/boot/certs into flash_ntz.bin.
8552+
tools/scripts/amebapro2_package.sh wolfboot.elf
8553+
```
8554+
8555+
For the default `sdk` backend, `make TARGET=rtl8735b` compiles every wolfBoot object (including the RealTek SDK driver chain folded into `hal/rtl8735b.o`), but the final `wolfboot.elf` link must resolve the SDK SoC libraries (`liboutsrc.a`, `libsoc_ntz.a`) and the ROM symbol table (`romsym_is.so`), which live in the SDK build tree. `tools/scripts/rtl8735b_build.sh` runs that compile-then-SDK-resolved-link (it honors `AMEBA_SDK` and `ASDK_PATH`), and `tools/scripts/amebapro2_package.sh` then packages wolfBoot (in `PT_FW1`) with the RealTek partition table, boot, and certs via `elf2bin` into `flash_ntz.bin` (it needs only `AMEBA_SDK`, plus optional `OUTDIR`; no toolchain). See `hal/rtl8735b/README`.
8556+
8557+
The `bare` backend links a standalone `wolfboot.elf` with no SDK dependency (flash stubbed, not yet functional):
8558+
8559+
```sh
8560+
make TARGET=rtl8735b HAL_BACKEND=bare
8561+
```
8562+
8563+
### Building and staging an application
8564+
8565+
A minimal bare-metal example application is provided in `hal/rtl8735b/test-app/` (a vector table plus a UART banner, linked at the DDR load address). Build it with the ASDK toolchain, sign it with the wolfBoot key, and write it to the BOOT partition offset:
8566+
8567+
```sh
8568+
export PATH="$ASDK_PATH:$PATH"
8569+
arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=softfp \
8570+
-Os -ffreestanding -nostdlib -nostartfiles \
8571+
-T hal/rtl8735b/test-app/test_app.ld hal/rtl8735b/test-app/test_app.c -o test_app.elf
8572+
arm-none-eabi-objcopy -O binary test_app.elf test_app.bin
8573+
8574+
# Sign with ECDSA P-256 + SHA-256 as version 1
8575+
tools/keytools/sign --ecc256 --sha256 test_app.bin wolfboot_signing_private_key.der 1
8576+
8577+
# Write the signed image to the BOOT partition offset (no whole-image rebuild).
8578+
# uartfwburn's -s flag writes at an arbitrary flash offset.
8579+
uartfwburn.linux -p /dev/ttyUSBx -f test_app_v1_signed.bin -s 0x520000 -b 3000000 -U
8580+
```
8581+
8582+
To stage an update, sign a newer build with a higher version number and write it to the UPDATE offset (`0x6A0000`) the same way.
8583+
8584+
### A/B update and rollback
8585+
8586+
wolfBoot uses version-based A/B selection in this RAMBOOT model (there is no swap copy): it boots whichever of BOOT/UPDATE holds the higher version with a valid signature.
8587+
8588+
* **Update:** stage a higher-version signed image in UPDATE; on the next boot wolfBoot reports `Versions: Boot x, Update y`, selects the higher version, and boots it.
8589+
* **Integrity / authenticity:** a tampered image fails the SHA-256 integrity or ECDSA signature check and is rejected (`Checking integrity...FAILED`).
8590+
* **Anti-downgrade (secure default, `ALLOW_DOWNGRADE=0`):** if the newer image is rejected and the only remaining candidate is an older version, wolfBoot does not downgrade -- it stops (`Rollback to lower version not allowed`, then panic) rather than run older firmware.
8591+
* **Fault tolerance:** if a valid image of the same (or newer) version exists in the other partition, wolfBoot falls back to it and boots it.
8592+
8593+
### Watchdog
8594+
8595+
The RealTek boot ROM arms the SoC's vendor watchdog before handing off to wolfBoot, and it resets the SoC if the watchdog is not serviced. Following the usual wolfBoot convention (the bootloader hands a running watchdog to the application), wolfBoot leaves it running, so the **application is responsible for servicing or reconfiguring it** -- an app that never services the watchdog reboots after the timeout.
8596+
8597+
The example app in `hal/rtl8735b/test-app/` shows the minimal "pet": a read-modify-write that sets bit 24 (`WDT_CLEAR`) of the secure vendor watchdog register at `0x50002C00`, which reloads the timer while preserving the ROM-configured enable/mode/divisor bits. A real application would service it from a periodic task or reconfigure the timeout to suit its needs.
8598+
8599+
With `DEBUG_UART=1`, wolfBoot prints the last reset cause at startup, decoded from the AON boot-reason register (`0x40009104`) -- handy for spotting an unfed watchdog:
8600+
8601+
```
8602+
Reset reason: 0x1 VNDR-WDT <- vendor watchdog reset (app did not service it)
8603+
Reset reason: 0x10 BOD <- brown-out / power-on reset
8604+
```
8605+
8606+
### Status and roadmap
8607+
8608+
Verified on the AmebaPro2 EVB today: signed boot (ECDSA P-256 / SHA-256), version-based A/B update, rollback/anti-downgrade, the `DEBUG_UART` console, the reset-reason readout, and the watchdog handoff. This is the non-TrustZone "Model A" integration with the `sdk` backend.
8609+
8610+
Outstanding work (TODO):
8611+
8612+
- **Device-bound encrypted updates (HUK):** a non-MMU encrypted-RAMBOOT enabler (`wolfBoot_ramboot_decrypt`) and an `rtl8735b-encrypt.config` exist on a separate development branch; they build but are not yet hardware-verified. Binding the partition key to the RTL8735B Hardware Unique Key uses the wolfCrypt RealTek HUK crypto-callback port (wolfSSL PR #10677) and is still to be wired and tested.
8613+
- **TrustZone-M ("Model B"):** secure wolfBoot + non-secure application. Feasibility on the AmebaPro2 (does the ROM hand off in Secure state with the SAU free?) needs a spike before a full design; the generic wolfBoot TZ infrastructure (`hal/armv8m_tz.h`, the `blxns` path in `src/boot_arm.c`, `-mcmse`/`--cmse-implib`) would be reused.
8614+
- **`bare` backend:** currently a scaffold (`ext_flash_*` return `-1`). A no-SDK flash path must reimplement `spic_init()` (controller training) on the ROM `hal_spic_stubs`, since the bootloader hands off no SPIC adaptor.
8615+
- **Measured boot / DICE:** software DICE (HUK-derived UDS + TRNG) is a later follow-on; there is no on-chip TPM.

0 commit comments

Comments
 (0)