diff --git a/IDE/Renesas/e2studio/RA6M4/Readme.md b/IDE/Renesas/e2studio/RA6M4/Readme.md index efe218fb19..c3f0311e24 100644 --- a/IDE/Renesas/e2studio/RA6M4/Readme.md +++ b/IDE/Renesas/e2studio/RA6M4/Readme.md @@ -17,24 +17,24 @@ Please see `Readme_wSCE.md` for Renesas SCE use case. |:--|:--|:--| |Board|Renesas EK-RA6M4|| |Device|R7FA6M4AF3CFB|| -|Toolchain|GCC ARM Embedded 10.3.1.20210824|Included in GCC for Renesas RA| -|FSP Version|3.6.0|Download from Renesas site| -|IDE|e2studio 2022-01|Download from Renesas site| +|Toolchain|GCC ARM Embedded 13.2 (arm-none-eabi)|Included in e2studio / GCC for Renesas RA| +|FSP Version|6.1.0|Bundled with e2studio or download from Renesas site| +|IDE|e2studio 2024-01 or later|Download from Renesas site| |Flash Writer|Renesas Flash Programmer v3|Download from Renesas site| -|Binary tool|aarch64-none-elf-objcopy 10.3-2021.07|Download from GNU site| -|Key tool|keygen and sign|Included in wolfBoot| +|Binary tool|arm-none-eabi-objcopy|Included in GCC ARM toolchain| +|Key tool|keygen and sign|Included in wolfBoot (`tools/keytools`)| +|RTT Viewer|J-Link RTT Viewer|Included in J-Link Software Pack (SEGGER)| |FIT Components|Version| |:--|:--| -|Board Support Package Common Files|v3.6.0| -|I/O Port|v3.6.0| -|Arm CMSIS Version 5 - Core (M)|v5.8.0+fsp.3.6.0| -|RA6M4-EK Board Support Files|v3.6.0| -|Board support package for R7FA6M4AF3CFB|v3.6.0| -|Board support package for RA6M4|v3.6.0| -|Board support package for RA6M4 - FSP Data|v3.6.0| -|Flash Memory High Performance|v3.6.0| +|Board Support Package Common Files|v6.1.0| +|I/O Port|v6.1.0| +|Arm CMSIS Version 6 - Core (M)|v6.x+fsp.6.1.0| +|RA6M4-EK Board Support Files|v6.1.0| +|Board support package for R7FA6M4AF3CFB|v6.1.0| +|Board support package for RA6M4|v6.1.0| +|Board support package for RA6M4 - FSP Data|v6.1.0| e2Studio Project:\ @@ -48,178 +48,364 @@ Flash Allocation: | B |H| |H| | | | o |e| Primary |e| Update |Swap | | o |a| Partition |a| Partition |Sect | -| t |d| |d| | | +| t |d| (448 KB) |d| (448 KB) |64KB | +---------------------------+------------------------+-----+ -0x00000000: wolfBoot -0x00010000: Primary partition (Header) +0x00000000: wolfBoot (64 KB) +0x00010000: Primary partition (Header, IMAGE_HEADER_SIZE = 0x200) 0x00010200: Primary partition (Application image) 0x00080000: Update partition (Header) 0x00080200: Update partition (Application image) -0x000F0000: Swap sector +0x000F0000: Swap sector (64 KB) ``` -## 2. How to build and use -This section describes about how to build wolfBoot and application and use them. +## 3. Key Architecture Notes -### 1) Key generation -It has key tools running under the host environment such as Linux, Windows or MacOS. -For compiling the tools, follow the instruction described in the user manual. +### FSP Usage Summary +Both the **wolfBoot** and **app_RA** projects use the Renesas FSP, but only for the following: + +| FSP Role | wolfBoot | app_RA | +|:--|:--|:--| +| `SystemInit` (clock init, cache, early BSP) | ✓ | ✓ | +| `SystemRuntimeInit` (.data copy, .bss zero) | **✗ Disabled** (`BSP_CFG_C_RUNTIME_INIT=0`) | ✓ | +| Clock configuration (PLL, PCLK, ICLK via `bsp_clocks.c`) | ✓ | ✓ | +| IOPORT pin configuration (`R_IOPORT_Open`) | — | ✓ | +| **Flash driver (`g_flash0 Flash(r_flash_hp)`)** | **✗ Not used** | **✗ Not used** | + +wolfBoot sets **C Runtime Initialization = Disabled** in the FSP Smart Configurator +(BSP tab → RA Common → C Runtime Initialization). +Instead, wolfBoot copies the `.ram_code_from_flash` / `.data` sections and zeros `.bss` +manually inside `hal_init()` → `copy_ram_sections()` (`hal/renesas-ra.c`). + +The FSP provides the indispensable clock and startup infrastructure (`SystemInit`), +but RAM section initialisation and flash erase/write are handled by wolfBoot itself. + +### Direct FACI HP Flash Access (No FSP Flash Driver) + +wolfBoot accesses the RA6M4 code flash directly via FACI HP registers (`hal/renesas-ra.c`, `hal/renesas-ra.h`). +**The FSP `g_flash0 Flash(r_flash_hp)` driver is NOT used** — do not add it to either project. + +Direct register access requires all flash erase/write functions to run from RAM (`RAMFUNCTION`). +The `RAMFUNCTION` macro is defined in `wolfBoot/user_settings.h`: + +```c +#define RAMFUNCTION \ + __attribute__((used, noinline, section(".ram_code_from_flash"), long_call)) +``` + +> **Important**: The `noinline` attribute is required. Without it, GCC `-O2` (`-finline-functions`) +> can inline RAMFUNCTION bodies into flash-resident callers, causing a HardFault when code flash +> is in P/E mode (instruction fetches from flash are prohibited during P/E). + +### wolfBoot Warm Start in app_RA + +When the application is launched by wolfBoot, wolfBoot's RAM functions occupy the lower part of RAM. +The application's own RAM functions (`__ram_from_flash$$` section) must be copied to RAM +**before** `SystemRuntimeInit()` calls `memcpy()` — otherwise `memcpy()` itself is not yet in place. + +This is handled by `wolfboot_pre_init()` in `app_RA/src/wolfboot_startup.c`, called from +`R_BSP_WarmStart(BSP_WARM_START_RESET)` in `app_RA/src/hal_warmstart.c`. + +## 4. How to Build and Use + +### 1) Key Generation + +Build and install the key tools on your host (Linux, Windows, or macOS). +See the wolfBoot user manual for toolchain prerequisites. ``` $ cd $ export PATH=$PATH:/tools/keytools -$ keygen --ecc256 -g ./pri-ecc256.der # ECC256 -$ keygen --rsa2048 -g ./pri-rsa2048.der # RSA2048 +$ keygen --rsa2048 -g ./pri-rsa2048.der +``` + +The `keygen` tool writes the public key into `src/keystore.c` for linking with wolfBoot. +Other supported algorithms: `--ed25519 --ed448 --ecc256 --ecc384 --ecc521 --rsa2048 --rsa3072 --rsa4096` + +### 2) Build wolfBoot + +Open the project `IDE/Renesas/e2studio/RA6M4/wolfBoot` in e2studio and build. + +> **Note**: `configuration.xml` (FSP Smart Configurator project file) is not stored in the +> repository. You must generate the FSP files (`ra_gen/`, `ra_cfg/`) using a `dummy_library` +> project as described below. + +#### 2-1) Create `dummy_library` to Generate FSP Files + ++ Click **File** → **New** → **RA C/C++ Project** ++ Select `EK-RA6M4` from the board drop-down list ++ Check **Static Library** ++ Select **No RTOS**. Click Next ++ Check **Bare Metal Minimal**. Click Finish ++ Open Smart Configurator by clicking `configuration.xml` in the project ++ Go to **BSP** tab → **RA Common** on the Properties page: + + Set **Main Stack Size (bytes)** to `0x2000` + + Set **Heap Size (bytes)** to `0x10000` + + Set **C Runtime Initialization** to `Disabled` ++ Save the `dummy_library` FSP configuration ++ Copy `configuration.xml` and `pincfg` from `dummy_library` into `wolfBoot` ++ Open Smart Configurator by clicking the copied `configuration.xml` ++ Click **Generate Project Content** ++ Build the `wolfBoot` project + +Key BSP settings configured above (`wolfBoot/ra_cfg/fsp_cfg/bsp/bsp_cfg.h`): + +|Setting|Value|Note| +|:--|:--|:--| +|`BSP_CFG_STACK_MAIN_BYTES`|`0x2000`|8 KB main stack| +|`BSP_CFG_HEAP_BYTES`|`0x10000`|64 KB heap (wolfCrypt)| +|`BSP_CFG_C_RUNTIME_INIT`|`0`|wolfBoot copies RAM sections manually in `hal_init()`| + +wolfBoot initialises the FACI HP directly; **no FSP flash stack (`g_flash0`) is required**. + +To enable debug output over UART (SCI7, P613=TXD7, J23 connector), edit `wolfBoot/user_settings.h`: +```c +#define DEBUG_UART +#define PRINTF_ENABLED ``` -The `keygen` tool generates a pair of private and public key with -g option. -The private key is stored in the specified file. -The public key is stored in a key store as a C source code in "src/keystore.c" so that it can be compiled and linked with wolfBoot. -If you have an existing key pair, you can use -i option to import the public key to the store. +#### 2-2) Modify wolfBoot hal_entry.c -You can specify various signature algorithms such as +`wolfBoot/src/hal_entry.c` is **not stored in the repository** (Renesas copyright, FSP-generated). +After FSP generates the file, replace the `/* TODO */` body with the `loader_main()` call: -```les ---ed25519 --ed448 --ecc256 --ecc384 --ecc521 --rsa2048 --rsa3072 --rsa4096 +```c +#include +#include "hal_data.h" + +void hal_entry(void) +{ + loader_main(); /* wolfBoot entry */ +#if BSP_TZ_SECURE_BUILD + R_BSP_NonSecureEnter(); +#endif +} ``` -### 2) Compile wolfBoot +> **Important**: FSP regeneration (clicking **Generate Project Content**) may overwrite +> `hal_entry.c`. If that happens, restore the `loader_main()` call manually. +> Without it, wolfBoot will halt in `hal_entry()` without ever verifying or booting the application. -Open project under IDE/Renesas/e2studio/RA6M4/wolfBoot with e2Studio, and build the project. Project properties are preset for the demo. +### 3) Build the Sample Application -`PRINTF_ENABLED` is for debug information about partitions. Eliminate them for operational use. +Open the project `IDE/Renesas/e2studio/RA6M4/app_RA` in e2studio and build. -#### 2-1) Create `dummy_library` Static Library -+ Click File->New->`RA C/C++ Project`. -+ Select `EK-RA6M4` from Drop-down list. -+ Check `Static Library`. -+ Select `No RTOS` from RTOS selection. Click Next. -+ Check `Bare Metal Minimal`. Click Finish. -+ Open Smart Configurator by clicking configuration.xml in the project -+ Go to `BSP` tab and increase Main Stack Size under `RA Common` on Properties page, e.g. 0x2000 -+ Go to `BSP` tab and increase Heap Size under `RA Common` on Properties page, e.g. 0x10000 -+ Go to `Stacks` tab -+ Add `SCE Protected Mode` stack from `New Stack` -> `Security` -+ Add `g_flash0 Flash(r_flash_hp)` stack from `New Stack` -> `Storage` +> **Note**: `configuration.xml` is not stored in the repository. +> You must generate the FSP files using a `dummy_application` project as described below. -Modify `g_flash0 Flash(r_flash_hp)` properties as follows: -|Property|Value| -|:--|:--| -|Data Flash Background Operation|Disabled| +#### 3-1) Create `dummy_application` to Generate FSP Files -+ Save `dummy_library` FSP configuration -+ Copy configuration.xml and pincfg under `dummy_library` to `wolfBoot` -+ Open Smart Configurator by clicking copied configuration.xml -+ Click `Generate Project Content` on Smart Configurator -+ Set `BSP_FEATURE_FLASH_SUPPORTS_ACCESS_WINDOW` to 1) -+ Build `wolfBoot` project ++ Click **File** → **New** → **RA C/C++ Project** ++ Select `EK-RA6M4` from the board drop-down list ++ Check **Executable** ++ Select **No RTOS**. Click Next ++ Check **Bare Metal Minimal**. Click Finish ++ Open Smart Configurator by clicking `configuration.xml` in the project ++ Go to **BSP** tab → **RA Common**: leave default settings (C Runtime Initialization = Enabled) ++ Save the `dummy_application` FSP configuration ++ Copy `configuration.xml` and `pincfg` from `dummy_application` into `app_RA` ++ Open Smart Configurator by clicking the copied `configuration.xml` ++ Click **Generate Project Content** ++ Build the `app_RA` project -### 3) Compile the sample application +#### 3-2) Application Linker Script -Open project under IDE/Renesas/e2studio/RA6M4/app_RA with e2Studio, and build the project. -Project properties are preset for the demo. +`app_RA/script/fsp.ld` contains wolfBoot-specific overrides (already in the project): - #### 3-1). Prepare SEGGER_RTT for logging - + Download J-Link software from [Segger](https://www.segger.com/downloads/jlink) - + Choose `J-Link Software and Documentation Pack` - + Copy sample program files below from `Installed SEGGER` folder, `e.g C:\Program Files\SEGGER\JLink\Samples\RTT`, to /path/to/wolfBoot/IDE/Reenesas/e2studio/RA6M4/app_RA/src/SEGGER_RTT\ +```ld +// FLASH_START = 0x00010200; /* wolfBoot 64 KB + image header 512 B */ +// FLASH_LENGTH = 0x000EFE00; +``` - SEGGER_RTT.c\ - SEGGER_RTT.h\ - SEGGER_RTT_Conf.h\ - SEGGER_RTT_printf.c - + Open `SEGGER_RTT_Conf.h` and Set `SEGGER_RTT_MEMCPY_USE_BYTELOOP` to `1` - + To connect RTT block, you can configure RTT viewer configuration based on where RTT block is in map file +Uncomment these two lines only if you need to run the app **standalone** (without wolfBoot). +Leave them commented out for the normal wolfBoot-booted build. - e.g.[app_RA.map] +#### 3-3) Required Source Files in app_RA - ``` - .bss._SEGGER_RTT - 0x2000094c 0xa8 ./src/SEGGER_RTT/SEGGER_RTT.o - 0x2000094c _SEGGER_RTT - ```` - - you can specify "RTT control block" to 0x2000094c by Address - OR - you can specify "RTT control block" to 0x20000000 0x1000 by Search Range - - #### 3-2). Create `dummy_application` -+ Click File->New->`RA C/C++ Project`. -+ Select `EK-RA6M4` from Drop-down list. -+ Check `Executable`. -+ Select `No RTOS` from RTOS selection. Click Next. -+ Check `Bare Metal Minimal`. Click Finish. -+ Go to `BSP` tab and Add `g_flash0 Flash(r_flash_hp)` stack from `New Stack` -> `Storage` - -Modify `g_flash0 Flash(r_flash_hp)` properties as follows: -|Property|Value| -|:--|:--| -|Data Flash Background Operation|Disabled| +**Copy from the wolfBoot repository** into `app_RA/src/`: + +|File|Source in repo|Purpose| +|:--|:--|:--| +|`wolfboot_startup.c`|`IDE/Renesas/e2studio/RA6M4/app_RA/src/wolfboot_startup.c`|Defines `wolfboot_pre_init()` — copies `__ram_from_flash$$` to RAM before `SystemRuntimeInit` runs| +|`app_RA.c`|`IDE/Renesas/e2studio/RA6M4/app_RA/src/app_RA.c`|Main application logic| + +**Modify the FSP-generated `hal_entry.c`** (Renesas copyright, not stored in repo): + +After FSP generates `hal_entry.c`, add the following: -+ Save `dummy_application` FSP configuration -+ Copy configuration.xml and pincfg under `dummy_application` to `app_RA` -+ Open Smart Configurator by clicking copied configuration.xml -+ Click `Generate Project Content` on Smart Configurator -+ Set `BSP_FEATURE_FLASH_SUPPORTS_ACCESS_WINDOW` to 1) -+ Build `app_RA` project +1. At the top of the file, after `#include "hal_data.h"`, add: -Code Origin and entry point is "0x00010200". app_RA.elf is generated under Debug. +```c +#include -### 4) Generate Signature for app V1 -You can derive the binary file (app_RA.bin) using objcopy command as follows: +/* Enable flash P/E (required for wolfBoot_success() when running standalone). */ +#define R_SYSTEM_FWEPROR (*(volatile uint8_t *)0x4001E416UL) +#define FWEPROR_FLWE_ENABLE (0x01U) +void app_RA(void); ``` -$ aarch64-none-elf-objcopy.exe -O binary -j .text -j .data app_RA.elf app_RA.bin + +2. Inside `hal_entry()`, replace the `/* TODO */` comment with: + +```c +void hal_entry(void) +{ + R_SYSTEM_FWEPROR = FWEPROR_FLWE_ENABLE; /* <-- add: enable code flash P/E */ + app_RA(); /* <-- add: call application */ +#if BSP_TZ_SECURE_BUILD + R_BSP_NonSecureEnter(); +#endif +} ``` -"sign" command under tools/keytools generates a signature for the binary with a specified version. -It generates a file contain a partition header and application image. -The partition header contain generated signature and other control fields. -Output file name is made up from the input file name and version like app_RenesasRx01_v1.0_signed.bin. +**Modify the FSP-generated `hal_warmstart.c`** (Renesas copyright, not stored in repo): + +After FSP generates `hal_warmstart.c`, add the following two lines manually: +1. After `FSP_CPP_FOOTER`, add the forward declaration: + +```c +/* wolfBoot-specific early startup — see wolfboot_startup.c */ +extern void wolfboot_pre_init(void); ``` -$ sign --ecc256 app_RA.bin ../../../../../pri-ecc256.der 1.0 -$ sign --rsa2048 app_RA.bin ../../../../../pri-rsa2048.der 1.0 -wolfBoot KeyTools (Compiled C version) -wolfBoot version 10E0000 -Update type: Firmware -Input image: app_RA.bin -Selected cipher: RSA2048 -Selected hash : SHA256 -Public key: ./pri-rsa2048.der -Output image: app_RA_v1.0_signed.bin -Target partition id : 1 -Calculating SHA256 digest... -Signing the digest... -Output image(s) successfully created. + +2. Inside the `BSP_WARM_START_RESET` block, call `wolfboot_pre_init()`: + +```c +void R_BSP_WarmStart (bsp_warm_start_event_t event) +{ + if (BSP_WARM_START_RESET == event) + { + /* Copy APP RAM functions before SystemRuntimeInit runs. + * Required when booted by wolfBoot — see wolfboot_startup.c for details. */ + wolfboot_pre_init(); /* <-- add this line */ + } + + if (BSP_WARM_START_POST_C == event) + { + R_IOPORT_Open(&IOPORT_CFG_CTRL, &IOPORT_CFG_NAME); + } +} ``` -### 5) Download the app V1 +**Why this is necessary**: wolfBoot's RAM functions occupy the lower RAM area when the app starts. +The app's own RAM functions (`__ram_from_flash$$` section) must be copied to their correct VMA +addresses *before* `SystemRuntimeInit()` calls `memcpy()` — because `memcpy()` itself is one +of those RAM functions. `wolfboot_pre_init()` performs this copy using a plain word loop that +requires no library functions. + +#### 3-4) SEGGER RTT for Logging + + + Download J-Link Software from [SEGGER](https://www.segger.com/downloads/jlink) and choose `J-Link Software and Documentation Pack` + + Copy the following files from `/Samples/RTT/` to `app_RA/src/SEGGER_RTT/`: + + ``` + SEGGER_RTT.c + SEGGER_RTT.h + SEGGER_RTT_Conf.h + SEGGER_RTT_printf.c + ``` + + + Open `SEGGER_RTT_Conf.h` and set `SEGGER_RTT_MEMCPY_USE_BYTELOOP` to `1` + + + To find the RTT Control Block address, search for `_SEGGER_RTT` in the build's `.map` file after each build: + + ``` + grep _SEGGER_RTT app_RA/Debug/app_RA.map + # Example output: + # 0x20000eb0 _SEGGER_RTT + ``` + + In J-Link RTT Viewer, set **RTT Control Block** to **Address** `0x20000eb0` + (the exact address changes per build and optimization level). + + Alternatively, use **Search Range** `0x20000000 0x10000` for automatic detection. + +> **Note on optimization**: The RTT Control Block address shifts with `-O2` vs `-O0`/-O1` +> because code size affects `.bss` layout. Always re-check the map file after changing +> the optimization level. + +#### 3-5) Optimization Level + +The default build uses `-O0` or `-O1`. If you set `-O2`: + +- Ensure `RAMFUNCTION` in `wolfBoot/user_settings.h` includes `noinline`: + ```c + #define RAMFUNCTION \ + __attribute__((used, noinline, section(".ram_code_from_flash"), long_call)) + ``` +- Re-check the RTT Control Block address in the `.map` file. + +### 4) Convert ELF to Binary -You can convert the binary file to hex format and download it to the board by Flash Programmer. The partition starts at "0x00010000". +#### 4-1) Using the provided script (recommended) +`IDE/Renesas/e2studio/RA6M4/elf2hex.sh` automates steps 4–5 for both v1 and v2. +Run it from WSL or an equivalent Bash environment: + +```bash +$ cd IDE/Renesas/e2studio/RA6M4 +$ ./elf2hex.sh 0 +# e.g.: +$ ./elf2hex.sh 0 /mnt/c/workspace/wolfBoot /mnt/c/toolchain/gcc-arm/bin +``` + +This produces `app_RA_v1.0_signed.hex` and `app_RA_v2.0_signed.hex` ready for Renesas Flash Programmer. + +#### 4-2) Manual Steps + +The FSP linker uses `$$`-delimited section names. Use `arm-none-eabi-objcopy` with the +following sections to produce a flat binary: + +```bash +$ arm-none-eabi-objcopy -O binary --gap-fill=0xff \ + -j '__flash_vectors$$' \ + -j '__flash_readonly$$' \ + -j '__flash_ctor$$' \ + -j '__flash_preinit_array$$' \ + -j '__flash_.got$$' \ + -j '__flash_init_array$$' \ + -j '__flash_fini_array$$' \ + -j '__flash_arm.extab$$' \ + -j '__flash_arm.exidx$$' \ + -j '__ram_from_flash$$' \ + app_RA.elf app_RA.bin ``` -$ aarch64-none-elf-objcopy.exe -I binary -O srec --change-addresses=0x00010000 app_RA_v1.0_signed.bin app_RA_v1.0_signed.hex + +> **Note**: Shell quoting of `$$` is required on Bash. Wrap each section name in +> single quotes when running interactively, or use the script above. + +### 5) Sign and Generate Hex + +```bash +$ cd +# Sign version 1 +$ sign --rsa2048 app_RA.bin ./pri-rsa2048.der 1.0 +# Output: app_RA_v1.0_signed.bin + +# Convert to SREC (Primary partition starts at 0x00010000) +$ arm-none-eabi-objcopy -I binary -O srec \ + --change-addresses=0x00010000 \ + app_RA_v1.0_signed.bin app_RA_v1.0_signed.hex ``` -### 6) Execute initial boot +### 6) Download app V1 and Execute Initial Boot + +Flash `app_RA_v1.0_signed.hex` to the board using Renesas Flash Programmer (partition base `0x00010000`). -Now, you can download and start wolfBoot program by e2Studio debugger. -After starting the program, you can see the partition information as follows. -If the boot program succeeds integrity and authenticity check, it initiate the application V1. To initially run `wolfBoot` project, -1.) Right-Click the Project name. -2.) Select `Debug As` -> `Renesas GDB Hardware Debugging` -3.) Select `J-Link ARM`. Click OK. -4.) Select `R7FA6M4AF`. Click OK. +Then start wolfBoot via e2studio debugger: +1. Right-click the **wolfBoot** project → **Debug As** → **Renesas GDB Hardware Debugging** +2. Select **J-Link ARM** → OK +3. Select **R7FA6M4AF** → OK + +Expected RTT output: ``` | ------------------------------------------------------------------- | | Renesas RA User Application in BOOT partition started by wolfBoot | | ------------------------------------------------------------------- | - -WOLFBOOT_PARTITION_SIZE: 0x00060000 +WOLFBOOT_PARTITION_SIZE: 0x00070000 WOLFBOOT_PARTITION_BOOT_ADDRESS: 0x00010000 WOLFBOOT_PARTITION_UPDATE_ADDRESS: 0x00080000 @@ -229,70 +415,60 @@ Application Entry Address: 0x00010200 Magic: WOLF Version: 01 Status: FF -Trailer Magic: +Trailer Mgc: === Update Partition[00080000] === Magic: Version: 00 Status: FF -Trailer Magic: +Trailer Mgc: Current Firmware Version : 1 Calling wolfBoot_success() - -``` - -The application is calling wolfBoot_success() to set boot partition state. - -``` Called wolfBoot_success() === Boot Partition[00010000] === Magic: WOLF Version: 01 Status: 00 -Trailer Magic: BOOT +Trailer Mgc: BOOT === Update Partition[00080000] === Magic: Version: 00 Status: FF -Trailer Magic: +Trailer Mgc: ``` -You can see the state is Success("00") and Trailer Magic number becomes "BOOT". -You can also see flashing each LED light in 1 second. Notable things about V1 application, -it will also call wolfBoot_update_trigger() so that it tells wolfBoot that new version exists. -We are going to generate and download V2 application into "Update partition". +State `00` = Success; Trailer Magic `BOOT` confirms the partition is marked good. +V1 also calls `wolfBoot_update_trigger()` so wolfBoot will look for a V2 image. +LEDs blink in sequence (reverse order for V1). -### 7) Generate Signed app V2 and download it +### 7) Sign and Download app V2 -Similar to V1, you can sign and generate a binary of V2. The update partition starts at "0x00080000". -You can download it by the flash programmer. +```bash +# Sign version 2 +$ sign --rsa2048 app_RA.bin ./pri-rsa2048.der 2.0 -Updtate partition: --change-addresses=0x00080000 - -``` -$ sign --ecc256 app_RA.bin ../../../../../pri-ecc256.der 2.0 -$ sign --rsa2048 app_RA.bin ../../../../../pri-rsa2048.der 2.0 -$ aarch64-none-elf-objcopy.exe -I binary -O srec --change-addresses=0x00080000 app_RA_v2.0_signed.bin app_RA_v2.0_signed.hex +# Convert to SREC (Update partition starts at 0x00080000) +$ arm-none-eabi-objcopy -I binary -O srec \ + --change-addresses=0x00080000 \ + app_RA_v2.0_signed.bin app_RA_v2.0_signed.hex ``` +Flash `app_RA_v2.0_signed.hex` to the board at base `0x00080000`. -### 8) Re-boot and secure update to V2 +### 8) Re-boot and Secure Update to V2 -The boot program checks integrity and authenticity of V2, swap the partition safely and initiates V2. -You will see following message after the partition -information. You can also see flashing each LED light in 5 second. +Reset the board (or re-run the debugger). wolfBoot verifies V2, swaps the partitions, and boots V2. -``` +Expected RTT output: +``` | ------------------------------------------------------------------- | | Renesas RA User Application in BOOT partition started by wolfBoot | | ------------------------------------------------------------------- | - -WOLFBOOT_PARTITION_SIZE: 0x00060000 +WOLFBOOT_PARTITION_SIZE: 0x00070000 WOLFBOOT_PARTITION_BOOT_ADDRESS: 0x00010000 WOLFBOOT_PARTITION_UPDATE_ADDRESS: 0x00080000 @@ -302,13 +478,13 @@ Application Entry Address: 0x00010200 Magic: WOLF Version: 02 Status: 00 -Trailer Magic: BOOT +Trailer Mgc: BOOT === Update Partition[00080000] === Magic: WOLF Version: 01 Status: FF -Trailer Magic: +Trailer Mgc: Current Firmware Version : 2 Calling wolfBoot_success() @@ -317,14 +493,14 @@ Called wolfBoot_success() Magic: WOLF Version: 02 Status: 00 -Trailer Magic: BOOT +Trailer Mgc: BOOT === Update Partition[00080000] === Magic: WOLF Version: 01 Status: FF -Trailer Magic: +Trailer Mgc: ``` -You can see "Current Firmware Version : 2". The state is Success("00") and Tailer Magic number becomes "BOOT". -You can also see flashing each LED light in 5 second at this new version. +`Current Firmware Version : 2` confirms the secure update succeeded. +LEDs blink in forward order for V2. diff --git a/IDE/Renesas/e2studio/RA6M4/app_RA/.cproject b/IDE/Renesas/e2studio/RA6M4/app_RA/.cproject index 734087d340..ab5c069a8f 100644 --- a/IDE/Renesas/e2studio/RA6M4/app_RA/.cproject +++ b/IDE/Renesas/e2studio/RA6M4/app_RA/.cproject @@ -67,10 +67,13 @@ + + @@ -312,6 +384,64 @@ + + + + diff --git a/IDE/Renesas/e2studio/RA6M4/app_RA/.project b/IDE/Renesas/e2studio/RA6M4/app_RA/.project index 4b60e48794..7d7f26c84f 100644 --- a/IDE/Renesas/e2studio/RA6M4/app_RA/.project +++ b/IDE/Renesas/e2studio/RA6M4/app_RA/.project @@ -32,6 +32,12 @@ + + com.renesas.cdt.managedbuild.jsoncdb.compilationdatabase.compilationDatabaseBuilder + full,incremental, + + + org.eclipse.cdt.core.cnature @@ -40,6 +46,7 @@ com.renesas.cdt.ddsc.contentgen.ddscNature com.renesas.cdt.ra.contentgen.raNature org.eclipse.xtext.ui.shared.xtextNature + com.renesas.cdt.managedbuild.jsoncdb.compilationdatabase.CompileCommandsNature @@ -52,5 +59,20 @@ 1 PARENT-5-PROJECT_LOC/hal/renesas-ra.c + + src/string.c + 1 + PARENT-5-PROJECT_LOC/src/string.c + + + src/target.h + 1 + PARENT-1-PROJECT_LOC/wolfBoot/target.h + + + src/user_settings.h + 1 + PARENT-1-PROJECT_LOC/wolfBoot/user_settings.h + diff --git a/IDE/Renesas/e2studio/RA6M4/app_RA/script/fsp.ld b/IDE/Renesas/e2studio/RA6M4/app_RA/script/fsp.ld new file mode 100644 index 0000000000..c62a8563c6 --- /dev/null +++ b/IDE/Renesas/e2studio/RA6M4/app_RA/script/fsp.ld @@ -0,0 +1,19 @@ +/* + Linker File for Renesas FSP +*/ + +INCLUDE memory_regions.ld + +/* wolfBoot override: app must start after wolfBoot bootloader + image header. + * WOLFBOOT_PARTITION_BOOT_ADDRESS = 0x00010000 (64KB wolfBoot) + * IMAGE_HEADER_SIZE = 0x00000200 (512B, RSA2048) + * -> App vector table start = 0x00010200 + * This must be placed AFTER INCLUDE memory_regions.ld and BEFORE fsp_gen.ld + * so that fsp_gen.ld's MEMORY block uses the overridden values. + * + * Please comment-out the following two lines when app runs stand-alone. + */ +FLASH_START = 0x00010200; +FLASH_LENGTH = 0x000EFE00; + +INCLUDE fsp_gen.ld diff --git a/IDE/Renesas/e2studio/RA6M4/app_RA/src/app_RA.c b/IDE/Renesas/e2studio/RA6M4/app_RA/src/app_RA.c index ee840c3bfb..e52dd570ce 100644 --- a/IDE/Renesas/e2studio/RA6M4/app_RA/src/app_RA.c +++ b/IDE/Renesas/e2studio/RA6M4/app_RA/src/app_RA.c @@ -2,7 +2,7 @@ * * Test bare-metal application. * - * Copyright (C) 2025 wolfSSL Inc. + * Copyright (C) 2026 wolfSSL Inc. * * This file is part of wolfBoot. * @@ -29,49 +29,83 @@ #include "hal.h" #include "hal_data.h" #include "wolfboot/wolfboot.h" +#include "image.h" extern bsp_leds_t g_bsp_leds; void R_BSP_WarmStart(bsp_warm_start_event_t event); int myprintf(const char * sFormat, ...); -static void blink(int interval) +static const char* state2str(uint8_t s) { + switch(s) { + case IMG_STATE_NEW: return "New"; + case IMG_STATE_UPDATING: return "Updating"; + case IMG_STATE_TESTING: return "Testing"; + case IMG_STATE_SUCCESS: return "Success"; + default: return "Unknown"; + } +} + +static const char* upFlag2str(uint8_t s) +{ + switch(s) { + case SECT_FLAG_NEW: return "New"; + case SECT_FLAG_SWAPPING: return "Swapping"; + case SECT_FLAG_BACKUP: return "Backup"; + case SECT_FLAG_UPDATED: return "Updated"; + default: return "Unknown"; + } +} + +static void blink(int order) +{ + + int start, end, step; + int i = 0; /* LED type structure */ bsp_leds_t leds = g_bsp_leds; #if BSP_TZ_SECURE_BUILD - /* Enter non-secure code */ R_BSP_NonSecureEnter(); #endif /* Define the units to be used with the software delay function */ - const bsp_delay_units_t bsp_delay_units = BSP_DELAY_UNITS_MILLISECONDS * interval; - /* Calculate the delay in terms of bsp_delay_units */ - const uint32_t delay = bsp_delay_units / 2; - + const bsp_delay_units_t bsp_delay_units = BSP_DELAY_UNITS_MILLISECONDS; + const uint32_t freq = 1; + /* Calculate the delay: 500ms * interval per LED write */ + const uint32_t delay = (uint32_t)(bsp_delay_units / (freq * 2)); + /* Holds level to set for pins */ bsp_io_level_t pin_level = BSP_IO_LEVEL_LOW; + start = 0; + end = leds.led_count; + step = (order == -1)? -1 : 1; + + if (order == -1) { + start = end - 1; + end = -1; + } while (1) { /* Enable access to the PFS registers */ R_BSP_PinAccessEnable(); - /* Update each LEDs*/ - for (uint32_t i = 0; i < leds.led_count; i++) + i = start; + for (;;) { + if (i == end) break; /* Get pin to toggle */ uint32_t pin = leds.p_leds[i]; - /* Write to this pin */ R_BSP_PinWrite((bsp_io_port_pin_t) pin, pin_level); - /* Delay */ R_BSP_SoftwareDelay(delay, bsp_delay_units); + i += step; } /* Protect PFS registers */ @@ -84,6 +118,8 @@ static void blink(int interval) else { pin_level = BSP_IO_LEVEL_LOW; } + /* Delay */ + R_BSP_SoftwareDelay(delay, bsp_delay_units); } } @@ -96,15 +132,20 @@ static void printPart(uint8_t *part) uint8_t *magic; uint8_t state; uint32_t ver; + uint8_t upflag; magic = part; myprintf("Magic: %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]); ver = wolfBoot_get_blob_version(part); myprintf("Version: %02x\n", ver); - state = *(part + WOLFBOOT_PARTITION_SIZE - sizeof(uint32_t) - 1); - myprintf("Status: %02x\n", state); + wolfBoot_get_partition_state(0, &state); + myprintf("Status: %02x(%s)\n", state, state2str(state)); magic = part + WOLFBOOT_PARTITION_SIZE - sizeof(uint32_t); - myprintf("Trailer Magic: %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]); + if (magic[0] != 0x42) + magic = part + WOLFBOOT_PARTITION_SIZE - WOLFBOOT_SECTOR_SIZE - sizeof(uint32_t); + myprintf("Trailer Mgc: %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]); + wolfBoot_get_update_sector_flag(0, &upflag); + myprintf("Update flag: %02x (%s)\n", upflag, upFlag2str(upflag)); #ifdef WOLFBOOT_DEBUG_PARTION v = (uint32_t *)part; @@ -130,6 +171,7 @@ void app_RA(void) uint8_t firmware_version = 0; R_BSP_WarmStart(BSP_WARM_START_POST_C); + SystemCoreClockUpdate(); hal_init(); @@ -175,13 +217,13 @@ void app_RA(void) if (firmware_version == 1) { wolfBoot_update_trigger(); - blink(1); + blink(-1); } else if (firmware_version == 2) { - blink(5); + blink(1); } /* busy wait */ busy_idle: /* flashing LEDs in busy */ - blink(1); + blink(-1); } diff --git a/IDE/Renesas/e2studio/RA6M4/app_RA/src/hal_entry.c b/IDE/Renesas/e2studio/RA6M4/app_RA/src/hal_entry.c deleted file mode 100644 index e0e3366911..0000000000 --- a/IDE/Renesas/e2studio/RA6M4/app_RA/src/hal_entry.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "hal_data.h" - -FSP_CPP_HEADER -void R_BSP_WarmStart(bsp_warm_start_event_t event); -FSP_CPP_FOOTER - - -/*******************************************************************************************************************//** - * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function - * is called by main() when no RTOS is used. - **********************************************************************************************************************/ -void app_RA(void); /* Example application main entry point */ - -void hal_entry(void) -{ - /* TODO: add your own code here */ - app_RA(); - -#if BSP_TZ_SECURE_BUILD - /* Enter non-secure code */ - R_BSP_NonSecureEnter(); -#endif -} - -/*******************************************************************************************************************//** - * This function is called at various points during the startup process. This implementation uses the event that is - * called right before main() to set up the pins. - * - * @param[in] event Where at in the start up process the code is currently at - **********************************************************************************************************************/ -void R_BSP_WarmStart(bsp_warm_start_event_t event) -{ - if (BSP_WARM_START_RESET == event) - { -#if BSP_FEATURE_FLASH_LP_VERSION != 0 - - /* Enable reading from data flash. */ - R_FACI_LP->DFLCTL = 1U; - - /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and - * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */ -#endif - } - - if (BSP_WARM_START_POST_C == event) - { - /* C runtime environment and system clocks are setup. */ - - /* Configure pins. */ - R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg); - } -} - -#if BSP_TZ_SECURE_BUILD - -BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable (); - -/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */ -BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable () -{ - -} -#endif diff --git a/IDE/Renesas/e2studio/RA6M4/app_RA/src/wolfboot_startup.c b/IDE/Renesas/e2studio/RA6M4/app_RA/src/wolfboot_startup.c new file mode 100644 index 0000000000..805fdb93a0 --- /dev/null +++ b/IDE/Renesas/e2studio/RA6M4/app_RA/src/wolfboot_startup.c @@ -0,0 +1,58 @@ +/* wolfboot_startup.c + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + /* + wolfBoot-specific early startup code for RA6M4 application. + * + * When this application is booted by wolfBoot, wolfBoot's own RAM functions + * occupy 0x20000000-0x20001188 with a DIFFERENT layout than this application + * expects. The C runtime startup (SystemRuntimeInit) tries to call memcpy() + * at the address this application was linked to, but that address contains + * wolfBoot's code, not the application's memcpy, causing an immediate crash. + * + * wolfboot_pre_init() must be called from R_BSP_WarmStart(BSP_WARM_START_RESET) + * BEFORE SystemRuntimeInit runs. It copies the __ram_from_flash$$ section + * using a plain word loop (no library memcpy) so that the application's RAM + * functions are placed at their correct VMA addresses. SystemRuntimeInit will + * then redundantly copy the same data, but by that point memcpy is valid. + */ +#include + +/** + * Copy __ram_from_flash$$ section to its VMA before SystemRuntimeInit runs. + * + * Call this from R_BSP_WarmStart(BSP_WARM_START_RESET), which fires inside + * SystemInit() BEFORE SystemRuntimeInit() is called. + */ +void wolfboot_pre_init(void) +{ + extern uint32_t __ram_from_flash$$Base; + extern uint32_t __ram_from_flash$$Limit; + extern uint32_t __ram_from_flash$$Load; + + volatile uint32_t *dst = &__ram_from_flash$$Base; + volatile const uint32_t *src = (const uint32_t *)(&__ram_from_flash$$Load); + volatile const uint32_t *end = &__ram_from_flash$$Limit; + + while (dst < end) + { + *dst++ = *src++; + } +} diff --git a/IDE/Renesas/e2studio/RA6M4/elf2hex.sh b/IDE/Renesas/e2studio/RA6M4/elf2hex.sh index 53a34d559a..6a5d03bf86 100755 --- a/IDE/Renesas/e2studio/RA6M4/elf2hex.sh +++ b/IDE/Renesas/e2studio/RA6M4/elf2hex.sh @@ -6,12 +6,12 @@ # This script is an example. You can update the script based on your environment. # # usage -# elf2hex.sh +# elf2hex.sh # if [ $# -ne 3 ];then - echo "Usage: $0 <0 or 1 for SCE use> WOLFBOOT_DIR AARCH64_BIN_DIR"; + echo "Usage: $0 <0 or 1 for SCE use> WOLFBOOT_DIR OBJCPY_BIN_DIR"; exit 1 fi @@ -22,10 +22,10 @@ RSA_SIGN="--rsa2048" SCEUSE=$1 WOLFBOOT_DIR=$2 -AARCH64_BIN_DIR=$3 +OBJCPY_BIN_DIR=$3 CURRENT=$(cd $(dirname $0);pwd) -APP_RA=${CURRENT}/app_RA -AARCH64_OBJCPY_BIN=${AARCH64_BIN_DIR}/aarch64-none-elf-objcopy.exe +APP_RA_ELF=${CURRENT}/app_RA/Debug/app_RA.elf +OBJCPY_BIN="${OBJCPY_BIN_DIR}/arm-none-eabi-objcopy.exe" PATH=$PATH:${WOLFBOOT_DIR}/tools/keytools @@ -39,21 +39,32 @@ echo "Version 1 app start address : " $VER1_ADDR echo "Version 2 app start address : " $VER2_ADDR echo "Signature method : " $RSA_SIGN +#echo cp ${APP_RA_ELF} ${OBJCPY_BIN_DIR} +#cp ${APP_RA_ELF} ${OBJCPY_BIN_DIR} +#exit +#pushd "${OBJCPY_BIN_DIR}" +pwd echo -echo COPY app_RA.elf to AARCH64_BIN_DIR to convert bin file -cp ${APP_RA}/Debug/app_RA.elf ${AARCH64_BIN_DIR} - -pushd ${AARCH64_BIN_DIR} - -echo -echo Run aarch64-none-elf-objcopy.exe to generate bin -${AARCH64_OBJCPY_BIN} -O binary -j .text -j .data app_RA.elf app_RA.bin +echo Run objcopy.exe to generate bin +echo "${OBJCPY_BIN}" -O binary --gap-fill=0xff -j '__flash_vectors$$' -j '__flash_readonly$$' -j '__flash_ctor$$' -j '__flash_preinit_array$$' -j '__flash_.got$$' -j '__flash_init_array$$' -j '__flash_fini_array$$' -j '__flash_arm.extab$$' -j '__flash_arm.exidx$$' -j '__ram_from_flash$$' "$(wslpath -w "${APP_RA_ELF}")" app_RA.bin +"${OBJCPY_BIN}" -O binary --gap-fill=0xff \ + -j '__flash_vectors$$' \ + -j '__flash_readonly$$' \ + -j '__flash_ctor$$' \ + -j '__flash_preinit_array$$' \ + -j '__flash_.got$$' \ + -j '__flash_init_array$$' \ + -j '__flash_fini_array$$' \ + -j '__flash_arm.extab$$' \ + -j '__flash_arm.exidx$$' \ + -j '__ram_from_flash$$' \ + "$(wslpath -w "${APP_RA_ELF}")" app_RA.bin echo echo copy app_RA.bin to wolfBoot folder to sign -cp app_RA.bin ${WOLFBOOT_DIR} +cp app_RA.bin "${WOLFBOOT_DIR}" -pushd ${WOLFBOOT_DIR} +pushd "${WOLFBOOT_DIR}" echo echo sign app_RA.bin for version 1 @@ -64,25 +75,27 @@ echo sign app_RA.bin for version 2 sign ${RSA_SIGN} app_RA.bin ./pri-rsa2048.der 2.0 echo -echo copy app_RA_v1.0/v2.0_signed.bin AARCH64_BIN_DIR -cp app_RA_v1.0_signed.bin ${AARCH64_BIN_DIR} -cp app_RA_v2.0_signed.bin ${AARCH64_BIN_DIR} +echo move app_RA_v1.0/v2.0_signed.bin OBJCPY_BIN DIR +mv app_RA_v1.0_signed.bin "${CURRENT}" +mv app_RA_v2.0_signed.bin "${CURRENT}" +APP_V1_BIN=${CURRENT}/app_RA_v1.0_signed.bin +APP_V2_BIN=${CURRENT}/app_RA_v2.0_signed.bin popd echo echo Run aarch64-none-elf-objcopy.exe to generate hex for version 1 -${AARCH64_OBJCPY_BIN} -I binary -O srec --change-addresses=${VER1_ADDR} app_RA_v1.0_signed.bin app_RA_v1.0_signed.hex +"${OBJCPY_BIN}" -I binary -O srec --change-addresses=${VER1_ADDR} "$(wslpath -w "${APP_V1_BIN}")" app_RA_v1.0_signed.hex echo echo Run aarch64-none-elf-objcopy.exe to generate hex for version 2 -${AARCH64_OBJCPY_BIN} -I binary -O srec --change-addresses=${VER2_ADDR} app_RA_v2.0_signed.bin app_RA_v2.0_signed.hex +"${OBJCPY_BIN}" -I binary -O srec --change-addresses=${VER2_ADDR} "$(wslpath -w "${APP_V2_BIN}")" app_RA_v2.0_signed.hex -echo -echo move *.hex to ${CURRENT} -mv app_RA_v1.0_signed.hex app_RA_v2.0_signed.hex ${CURRENT} +#echo +#echo move *.hex to ${CURRENT} +#mv app_RA_v1.0_signed.hex app_RA_v2.0_signed.hex ${CURRENT} -echo -echo Clean up all copied and generated files -rm -rf app_RA.elf app_RA.bin app_RA_v1.0_signed.bin app_RA_v2.0_signed.bin -popd +#echo +#echo Clean up all copied and generated files +#rm -rf app_RA.elf app_RA.bin app_RA_v1.0_signed.bin app_RA_v2.0_signed.bin +#popd diff --git a/IDE/Renesas/e2studio/RA6M4/wolfBoot/.cproject b/IDE/Renesas/e2studio/RA6M4/wolfBoot/.cproject index d9f1963a9e..6cc3a1ff77 100644 --- a/IDE/Renesas/e2studio/RA6M4/wolfBoot/.cproject +++ b/IDE/Renesas/e2studio/RA6M4/wolfBoot/.cproject @@ -21,7 +21,7 @@ @@ -124,6 +136,7 @@ + @@ -433,6 +460,64 @@ + + + + diff --git a/IDE/Renesas/e2studio/RA6M4/wolfBoot/.project b/IDE/Renesas/e2studio/RA6M4/wolfBoot/.project index fec93f32cc..f1fe3d37b5 100644 --- a/IDE/Renesas/e2studio/RA6M4/wolfBoot/.project +++ b/IDE/Renesas/e2studio/RA6M4/wolfBoot/.project @@ -32,6 +32,12 @@ + + com.renesas.cdt.managedbuild.jsoncdb.compilationdatabase.compilationDatabaseBuilder + full,incremental, + + + org.eclipse.cdt.core.cnature @@ -40,6 +46,7 @@ com.renesas.cdt.ddsc.contentgen.ddscNature com.renesas.cdt.ra.contentgen.raNature org.eclipse.xtext.ui.shared.xtextNature + com.renesas.cdt.managedbuild.jsoncdb.compilationdatabase.CompileCommandsNature @@ -78,9 +85,9 @@ PARENT-5-PROJECT_LOC/src/loader.c - src/wolfboot/spi_flash.c + src/wolfboot/string.c 1 - PARENT-5-PROJECT_LOC/src/spi_flash.c + PARENT-5-PROJECT_LOC/src/string.c src/wolfboot/uart_flash.c @@ -213,24 +220,24 @@ PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_common.c - src/wolfcrypt/port/renesas_sce_aes.c + src/wolfcrypt/port/renesas_fspsm_aes.c 1 - PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_sce_aes.c + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_fspsm_aes.c - src/wolfcrypt/port/renesas_sce_rsa.c + src/wolfcrypt/port/renesas_fspsm_rsa.c 1 - PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_sce_rsa.c + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_fspsm_rsa.c - src/wolfcrypt/port/renesas_sce_sha.c + src/wolfcrypt/port/renesas_fspsm_sha.c 1 - PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_sce_sha.c + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c - src/wolfcrypt/port/renesas_sce_util.c + src/wolfcrypt/port/renesas_fspsm_util.c 1 - PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_sce_util.c + PARENT-5-PROJECT_LOC/lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_fspsm_util.c diff --git a/IDE/Renesas/e2studio/RA6M4/wolfBoot/src/hal_entry.c b/IDE/Renesas/e2studio/RA6M4/wolfBoot/src/hal_entry.c deleted file mode 100644 index 321d1584db..0000000000 --- a/IDE/Renesas/e2studio/RA6M4/wolfBoot/src/hal_entry.c +++ /dev/null @@ -1,61 +0,0 @@ -#include "hal_data.h" - -FSP_CPP_HEADER -void R_BSP_WarmStart(bsp_warm_start_event_t event); -FSP_CPP_FOOTER - -/*******************************************************************************************************************//** - * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used. This function - * is called by main() when no RTOS is used. - **********************************************************************************************************************/ - -extern void loader_main(void); - -void hal_entry(void) -{ - loader_main(); /* wolfBoot entry */ - -#if BSP_TZ_SECURE_BUILD - /* Enter non-secure code */ - R_BSP_NonSecureEnter(); -#endif -} - -/*******************************************************************************************************************//** - * This function is called at various points during the startup process. This implementation uses the event that is - * called right before main() to set up the pins. - * - * @param[in] event Where at in the start up process the code is currently at - **********************************************************************************************************************/ -void R_BSP_WarmStart(bsp_warm_start_event_t event) -{ - if (BSP_WARM_START_RESET == event) - { -#if BSP_FEATURE_FLASH_LP_VERSION != 0 - - /* Enable reading from data flash. */ - R_FACI_LP->DFLCTL = 1U; - - /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and - * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */ -#endif - } - - if (BSP_WARM_START_POST_C == event) - { - /* C runtime environment and system clocks are setup. */ - - /* Configure pins. */ - R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg); - } -} - -#if BSP_TZ_SECURE_BUILD - -BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable (); - -/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */ -BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable () -{ -} -#endif diff --git a/IDE/Renesas/e2studio/RA6M4/wolfBoot/src/target.h b/IDE/Renesas/e2studio/RA6M4/wolfBoot/target.h similarity index 67% rename from IDE/Renesas/e2studio/RA6M4/wolfBoot/src/target.h rename to IDE/Renesas/e2studio/RA6M4/wolfBoot/target.h index 9b1226d04a..7ec2262e6f 100644 --- a/IDE/Renesas/e2studio/RA6M4/wolfBoot/src/target.h +++ b/IDE/Renesas/e2studio/RA6M4/wolfBoot/target.h @@ -33,19 +33,31 @@ #endif #define WOLFBOOT_FLASH_ADDR 0x0 -#define WOLFBOOT_FLASH_SIZE 0x100000 - -#define WOLFBOOT_SECTOR_SIZE 0x10000 -#define WOLFBOOT_PARTITION_SIZE 0x60000 +#define WOLFBOOT_FLASH_SIZE 0x100000 /* RA6M4: 1MB code flash */ #ifndef WOLFBOOT_RENESAS_SCEPROTECT -# define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x10000 -# define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x80000 -# define WOLFBOOT_PARTITION_SWAP_ADDRESS 0xf0000 + + #define WOLFBOOT_BOOT_SIZE 0x10000 + #define WOLFBOOT_SECTOR_SIZE 0x10000 + + #define WOLFBOOT_PARTITION_SIZE\ + ((WOLFBOOT_FLASH_SIZE - WOLFBOOT_BOOT_SIZE -\ + WOLFBOOT_SECTOR_SIZE) / 2) + + #define WOLFBOOT_PARTITION_BOOT_ADDRESS\ + (WOLFBOOT_FLASH_ADDR + WOLFBOOT_BOOT_SIZE) + + #define WOLFBOOT_PARTITION_UPDATE_ADDRESS\ + (WOLFBOOT_PARTITION_BOOT_ADDRESS + WOLFBOOT_PARTITION_SIZE) + + #define WOLFBOOT_PARTITION_SWAP_ADDRESS\ + (WOLFBOOT_PARTITION_UPDATE_ADDRESS + WOLFBOOT_PARTITION_SIZE) + #else # define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x20000 # define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x90000 # define WOLFBOOT_PARTITION_SWAP_ADDRESS 0xf0000 #endif + #endif /* !H_TARGETS_TARGET_ */ diff --git a/IDE/Renesas/e2studio/RA6M4/wolfBoot/src/user_settings.h b/IDE/Renesas/e2studio/RA6M4/wolfBoot/user_settings.h similarity index 87% rename from IDE/Renesas/e2studio/RA6M4/wolfBoot/src/user_settings.h rename to IDE/Renesas/e2studio/RA6M4/wolfBoot/user_settings.h index b0bec23a73..c8d8e8393e 100644 --- a/IDE/Renesas/e2studio/RA6M4/wolfBoot/src/user_settings.h +++ b/IDE/Renesas/e2studio/RA6M4/wolfBoot/user_settings.h @@ -4,7 +4,7 @@ * Enabled via WOLFSSL_USER_SETTINGS. * * - * Copyright (C) 2025 wolfSSL Inc. + * Copyright (C) 2026 wolfSSL Inc. * * This file is part of wolfBoot. * @@ -23,11 +23,23 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ -#ifndef H_USER_SETTINGS_ -#define H_USER_SETTINGS_ +#ifndef _WOLFBOOT_USER_SETTINGS_H_ +#define _WOLFBOOT_USER_SETTINGS_H_ + +/* RAMFUNCTION: use FSP-managed .ram_code_from_flash section. + * fsp_gen.ld places this in RAM (AT > FLASH) and the FSP BSP + * startup copies it automatically — no extra linker changes needed. + * This must be defined before wolfboot.h to override its default. */ +#define RAMFUNCTION \ + __attribute__((used, noinline,\ + section(".ram_code_from_flash"), long_call)) #define WOLFBOOT_LOADER_MAIN +/* Debug UART: define both to enable wolfBoot_printf via uart_write */ +/* #define DEBUG_UART */ +/* #define PRINTF_ENABLED */ + /* For SCE use, please enable the following line. */ /* #define WOLFBOOT_RENESAS_SCEPROTECT */ @@ -42,9 +54,6 @@ #define WOLFBOOT_FIXED_PARTITIONS -#define VECTOR_SP ((uint32_t *) (0x00000)) -#define VECTOR_Reset_Handler ((uint32_t *) (0x10204)) - #ifdef WOLFBOOT_RENESAS_SCEPROTECT # define WOLFSSL_RENESAS_SCEPROTECT_CRYPTONLY # define WOLFBOOT_SMALL_STACK @@ -53,6 +62,7 @@ # define SCE_ID 7890 # undef VECTOR_Reset_Handler # define VECTOR_Reset_Handler ((uint32_t *)(0x20204)) +... #endif #ifdef WOLFBOOT_DUALBOOT @@ -305,5 +315,7 @@ # define WOLFSSL_SMALL_STACK #endif - +#define NVM_FLASH_WRITEONCE +/*#define DEBUG_UART*/ +/*#define PRINTF_ENABLED*/ #endif /* !H_USER_SETTINGS_ */ diff --git a/hal/renesas-ra.c b/hal/renesas-ra.c index 087f9b6d2a..1050244c54 100644 --- a/hal/renesas-ra.c +++ b/hal/renesas-ra.c @@ -1,9 +1,9 @@ /* renesas-ra.c * - * Stubs for custom HAL implementation. Defines the - * functions used by wolfboot for a specific target. + * wolfBoot HAL for Renesas RA series (RA6M4). + * Direct FACI HP register access — no FSP driver dependency. * - * Copyright (C) 2025 wolfSSL Inc. + * Copyright (C) 2026 wolfSSL Inc. * * This file is part of wolfBoot. * @@ -19,31 +19,31 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1335, USA */ -#include #include #include #include "user_settings.h" - #include #include "hal.h" +#include "renesas-ra.h" -#include "r_flash_hp.h" +void uart_init(); +void uart_write(const char* buf, unsigned int sz); #if defined(WOLFSSL_RENESAS_SCEPROTECT_CRYPTONLY) && \ - !defined(WOLFBOOT_RENESAS_APP) - -# include "wolfssl/wolfcrypt/wc_port.h" -# include "wolfssl/wolfcrypt/port/Renesas/renesas-sce-crypt.h" -# include "wolfssl/wolfcrypt/port/Renesas/renesas_sync.h" - User_SCEPKCbInfo pkInfo; - sce_rsa2048_public_wrapped_key_t wrapped_rsapub2048; + !defined(WOLFBOOT_RENESAS_APP) +# include "wolfssl/wolfcrypt/wc_port.h" +# include "wolfssl/wolfcrypt/port/Renesas/renesas-sce-crypt.h" +# include "wolfssl/wolfcrypt/port/Renesas/renesas_sync.h" + User_SCEPKCbInfo pkInfo; + sce_rsa2048_public_wrapped_key_t wrapped_rsapub2048; #endif -/* #define DEBUG_FLASH_WRITE_VERIFY */ +#define FLASH_READY() while (!(FLASH_FSTATR & FLASH_FSTATR_FRDY)); static inline void hal_panic(void) { @@ -51,11 +51,31 @@ static inline void hal_panic(void) ; } -extern flash_ctrl_t g_flash0_ctrl; -extern flash_cfg_t g_flash0_cfg; +/* ------------------------------------------------------------------ */ +/* flash_check_error: read FSTATR and return first error found */ +/* ------------------------------------------------------------------ */ +static flash_err_t RAMFUNCTION flash_check_error(void) +{ + uint32_t st = FLASH_FSTATR; + + if (st & FLASH_FSTATR_ILGLERR)return FLASH_ERR_ILGL; + if (st & FLASH_FSTATR_PRGERR) return FLASH_ERR_PRG; + if (st & FLASH_FSTATR_ERSERR) return FLASH_ERR_ERS; + if (st & FLASH_FSTATR_FLWEERR)return FLASH_ERR_FLWE; + if (st & FLASH_FSTATR_FESETERR) return FLASH_ERR_FESET; + if (st & FLASH_FSTATR_SECERR) return FLASH_ERR_SEC; + if (st & FLASH_FSTATR_OTERR) return FLASH_ERR_OT; + + return FLASH_OK; +} -#if defined(WOLFBOOT_RENESAS_SCEPROTECT) && !defined(WOLFBOOT_RENESAS_APP) +/* ------------------------------------------------------------------ */ +/* SCE initialisation (WOLFBOOT_RENESAS_SCEPROTECT only) */ +/* ------------------------------------------------------------------ */ +#if defined(WOLFBOOT_RENESAS_SCEPROTECT) && \ + !defined(WOLFBOOT_RENESAS_APP) static int sipInitDone = 0; + int hal_renesas_init(void) { fsp_err_t err; @@ -64,224 +84,394 @@ int hal_renesas_init(void) if (sipInitDone) return 0; - /* retrieve installed pubkey from flash */ pubkey = keystore_get_buffer(0); err = wolfCrypt_Init(); if (err != 0) { - printf("ERROR: wolfCrypt_Init %d\n", err); - hal_panic(); + wolfBoot_printf("ERROR: wolfCrypt_Init %d\n", err); + hal_panic(); } XMEMSET(&pkInfo, 0, sizeof(pkInfo)); pkInfo.sce_wrapped_key_rsapub2048 = - (sce_rsa2048_public_wrapped_key_t*)&wrapped_rsapub2048; + (sce_rsa2048_public_wrapped_key_t*)&wrapped_rsapub2048; XMEMCPY(&wrapped_rsapub2048.value, (uint32_t*)pubkey, - sizeof(wrapped_rsapub2048.value)); + sizeof(wrapped_rsapub2048.value)); - wrapped_rsapub2048.type =SCE_KEY_INDEX_TYPE_RSA2048_PUBLIC; + wrapped_rsapub2048.type = SCE_KEY_INDEX_TYPE_RSA2048_PUBLIC; pkInfo.keyflgs_crypt.bits.rsapub2048_installedkey_set = 1; pkInfo.keyflgs_crypt.bits.message_type = 1; err = wc_CryptoCb_CryptInitRenesasCmn(NULL, &pkInfo); if (err < 0) { - printf("ERROR: wc_CryptoCb_CryptInitRenesasCmn %d\n", err); - return err; + wolfBoot_printf("ERROR: wc_CryptoCb_CryptInitRenesasCmn %d\n", + err); + return err; } sipInitDone = 1; return 0; } -#endif +#endif /* WOLFBOOT_RENESAS_SCEPROTECT */ -void hal_init(void) +/* ------------------------------------------------------------------ */ +/* Debug UART (SCI7, P613=TXD7, J23 pin2 on EK-RA6M4) */ +/* ------------------------------------------------------------------ */ +#ifdef DEBUG_UART +void uart_init(void) { - fsp_err_t err; + /* Release SCI7 from module stop */ + R_MSTP_MSTPCRB &= ~MSTPCRB_SCI7; - err = R_FLASH_HP_Close(&g_flash0_ctrl); - err = R_FLASH_HP_Open(&g_flash0_ctrl, &g_flash0_cfg); + /* Disable TX/RX for configuration */ + SCI_SCR = 0x00u; - if (err != FSP_ERR_ALREADY_OPEN && err != FSP_SUCCESS){ - wolfBoot_printf("ERROR: %d\n", err); - hal_panic(); - } + /* Async, 8N1, internal clock (CKS=00) */ + SCI_SMR = 0x00u; - /* Setup Default Block 0 as Startup Setup Block */ - err = R_FLASH_HP_StartUpAreaSelect(&g_flash0_ctrl, FLASH_STARTUP_AREA_BLOCK0, true); - if (err != FSP_SUCCESS){ - wolfBoot_printf("ERROR: %d\n", err); - hal_panic(); - } -#if defined(WOLFBOOT_RENESAS_SCEPROTECT) && !defined(WOLFBOOT_RENESAS_APP) - err = hal_renesas_init(); - if (err != 0) { - wolfBoot_printf("ERROR: hal_renesas_init %d\n", err); - hal_panic(); + /* CHR1=1: 8-bit character length */ + SCI_SCMR |= SCI_SCMR_CHR1; + + /* BGDM=1, ABCS=1: divide clock by 8 */ + SCI_SEMR = SCI_SEMR_BGDM | SCI_SEMR_ABCS; + + /* Baud rate register */ + SCI_BRR = (uint8_t)SCI_BRR_VAL; + + /* Enable PFS write */ + R_PMISC_PWPR = 0x00u; + R_PMISC_PWPR = PWPR_PFSWE; + + /* P613: TXD7 peripheral output, idle-high */ + R_PFS_P613 = PFS_PSEL_SCI7 | PFS_PMR | PFS_PDR | PFS_PODR; + + /* Disable PFS write */ + R_PMISC_PWPR = 0x00u; + R_PMISC_PWPR = PWPR_B0WI; + + /* Enable transmit */ + SCI_SCR = SCI_SCR_TE; +} + +void uart_write(const char* buf, unsigned int sz) +{ + unsigned int i; + for (i = 0; i < sz; i++) { + char c = buf[i]; + if (c == '\n') { + while (!(SCI_SSR & SCI_SSR_TEND)); + SCI_TDR = '\r'; + } + while (!(SCI_SSR & SCI_SSR_TEND)); + SCI_TDR = (uint8_t)c; } -#endif } +#endif /* DEBUG_UART */ -void hal_prepare_boot(void) +/* ------------------------------------------------------------------ */ +/* hal_flash_init: one-time flash controller setup */ +/* ------------------------------------------------------------------ */ +static int hal_flash_init(void) +{ + /* Notify FACI of PCLKA frequency so timing parameters are correct. + * FSP sets this in R_FLASH_HP_Open(); without it the FACI uses + * whatever power-on default is in FPCKAR, causing ILGLERR on any + * P/E operation. KEY=0x1E, PCKA = (PCLKA_MHz - 1). */ + FLASH_FPCKAR = (uint16_t)(FLASH_FPCKAR_KEY | (RA_PCLKA_MHZ - 1U)); + + /* Enter read mode and wait for ready */ + FLASH_FENTRYR = FLASH_FENTRYR_KEY; + FLASH_READY() + + /* Enable program/erase for the lifetime of wolfBoot */ + FLASH_FWEPROR = FLASH_FWEPROR_FLWE; + return 0; +} + +/* Linker-generated symbols — BSP_CFG_C_RUNTIME_INIT=0, so FSP does not + * initialize these sections automatically. + */ +/* .ram_code_from_flash + .data : copy from flash LMA to RAM VMA */ +extern uint32_t __ram_from_flash$$Base; +extern uint32_t __ram_from_flash$$Limit; +extern uint32_t __ram_from_flash$$Load; +/* .bss : must be zeroed (warm reset leaves RAM with stale values) */ +extern uint32_t __ram_zero$$Base; +extern uint32_t __ram_zero$$Limit; + +static void copy_ram_sections(void) { + uint32_t *src; + uint32_t *dst; + + /* 1. Copy RAMFUNCTION code + .data from flash to RAM. + * Do NOT call memcpy() here — wolfBoot's memcpy is itself in this + * region and has not been copied yet. */ + src = &__ram_from_flash$$Load; + dst = &__ram_from_flash$$Base; + while (dst < &__ram_from_flash$$Limit) + { + *dst++ = *src++; + } + /* 2. Zero .bss. + * A debugger warm-reset does not clear RAM, so without this step + * global variables expected to be 0 will contain stale values. */ + dst = &__ram_zero$$Base; + while (dst < &__ram_zero$$Limit) + { + *dst++ = 0u; + } } -#define MINIMUM_BLOCK (128) -#define ALIGN_FLASH(a) (((a) / MINIMUM_BLOCK) * MINIMUM_BLOCK) -static uint8_t save[MINIMUM_BLOCK*sizeof(uint32_t)]; -#ifdef DEBUG_FLASH_WRITE_VERIFY -static uint8_t readbuf[MINIMUM_BLOCK*sizeof(uint32_t)]; +/* ------------------------------------------------------------------ */ +/* hal_init */ +/* ------------------------------------------------------------------ */ +void hal_init(void) +{ +#ifndef WOLFBOOT_RENESAS_APP + /* wolfBoot only: BSP_CFG_C_RUNTIME_INIT=0, so FSP startup skips BSS + * zero-init and .data copy. Do them manually here. + * When building as app (WOLFBOOT_RENESAS_APP defined), the FSP startup + * already ran SystemRuntimeInit(0) which handles both — calling + * copy_ram_sections() again would re-zero .bss and clobber + * SystemCoreClock and other BSS variables. */ + copy_ram_sections(); #endif -/* */ -static int blockWrite(const uint8_t *data, uint32_t addr, uint32_t len) -{ - for(; len; len-=MINIMUM_BLOCK, data+=MINIMUM_BLOCK, addr+=MINIMUM_BLOCK) { - /* for the case "data" ls a flash address */ - memcpy(save, data, MINIMUM_BLOCK); + hal_flash_init(); - if(R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t)save, addr, MINIMUM_BLOCK) - != FSP_SUCCESS) - return -1; +#ifdef DEBUG_UART + uart_init(); + uart_write("wolfBoot HAL Init\n", 18); +#endif + +#if defined(WOLFBOOT_RENESAS_SCEPROTECT) && \ + !defined(WOLFBOOT_RENESAS_APP) + if (hal_renesas_init() != 0) { + wolfBoot_printf("ERROR: hal_renesas_init\n"); + hal_panic(); } - return 0; +#endif } -#define IS_FLASH_ADDR(addr) (addr) >= 0xffc00000 ? 1 : 0 +void hal_prepare_boot(void) +{ +} -int hal_flash_write(uint32_t addr, const uint8_t *data, int int_len) +/* ------------------------------------------------------------------ */ +/* hal_flash_unlock: enter code flash P/E mode */ +/* ------------------------------------------------------------------ */ +void RAMFUNCTION hal_flash_unlock(void) { - fsp_err_t err; - uint32_t len = (uint32_t)int_len; - uint32_t save_len = 0; - uint8_t address_tmp = (uint8_t)(addr - ALIGN_FLASH(addr)); + /* Ensure P/E is enabled (FWEPROR.FLWE=1). + * FWEPROR is NOT in the FACI register block, so FRESETR does not + * reset it. Set it first so it is ready when P/E mode is entered. + */ + FLASH_FWEPROR = FLASH_FWEPROR_FLWE; + + /* Reset the flash sequencer (FRESETR=1) to unconditionally clear any + * stale ILGLERR / PRGERR / ERSERR / OTERR flags left by a previous + * interrupted P/E operation. + */ + FLASH_FRESETR = 0x01U; + FLASH_READY() + FLASH_FRESETR = 0x00U; + FLASH_READY() + + /* FRESETR may reset FPCKAR to its power-on default (0x0000). + * Re-set it here (FRDY=1 guaranteed above) so the FACI uses the + * correct PCLKA frequency for all timing parameters. + * KEY=0x1E, PCKA = PCLKA_MHz - 1. */ + FLASH_FPCKAR = (uint16_t)(FLASH_FPCKAR_KEY | (RA_PCLKA_MHZ - 1U)); + + /* Clear P/E mode entry protection: FMEPROT.CEPROT=0.*/ + FLASH_FMEPROT = (uint16_t)(FLASH_FMEPROT_KEY | 0U); + + /* Enter code flash P/E mode.*/ + FLASH_FENTRYR = FLASH_FENTRYR_KEY | FLASH_FENTRYR_CODE_PR; + FLASH_READY() +} - if(addr != ALIGN_FLASH(addr)) { +/* ------------------------------------------------------------------ */ +/* hal_flash_lock: return to read mode */ +/* ------------------------------------------------------------------ */ +void RAMFUNCTION hal_flash_lock(void) +{ + FLASH_READY() + FLASH_FENTRYR = FLASH_FENTRYR_KEY; + FLASH_READY() +} - memset(save, 0, sizeof(save)); +/* ------------------------------------------------------------------ */ +/* hal_flash_erase: erase len bytes starting at address */ +/* address must be block-aligned */ +/* len must be a multiple of the block size */ +/* ------------------------------------------------------------------ */ +int RAMFUNCTION hal_flash_erase(uint32_t address, int int_len) +{ + uint32_t len = (uint32_t)int_len; - save_len = (addr - ALIGN_FLASH(addr)) < len ? - (addr - ALIGN_FLASH(addr)) : len; + while (len > 0) { + uint32_t block_size; - memcpy(save, (const void *)ALIGN_FLASH(addr), - MINIMUM_BLOCK * sizeof(uint32_t)); - memcpy(save + (address_tmp), data, save_len); - addr = ALIGN_FLASH(addr); +#ifdef WOLFBOOT_DUALBANK + block_size = + ((address <= 0x80000 && address >= 0x10000) || + address >= 0x210000) + ? (32 * 1024) : (8 * 1024); +#else + block_size = (address >= 0x10000) + ? (32 * 1024) : (8 * 1024); +#endif - if((err=R_FLASH_HP_Erase(&g_flash0_ctrl, addr, 1)) != FSP_SUCCESS) + if (len < block_size) return -1; - if((err=R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t)save, addr, - MINIMUM_BLOCK * sizeof(uint32_t))) != FSP_SUCCESS) - return -1; + FLASH_FSADDR = address; + FACI_CMD8 = FACI_CMD_BLOCK_ERASE; + FACI_CMD8 = FACI_CMD_EXECUTE; + FLASH_READY() -#ifdef DEBUG_FLASH_WRITE_VERIFY - memcpy(readbuf, (const void*)addr, MINIMUM_BLOCK * sizeof(uint32_t)); - if(memcmp(readbuf, save, MINIMUM_BLOCK * sizeof(uint32_t)) != 0) { + if (flash_check_error() != FLASH_OK) { + FACI_CMD8 = FACI_CMD_FORCED_STOP; + FLASH_READY() + FACI_CMD8 = FACI_CMD_STATUS_CLR; return -1; } -#endif - len -= save_len; - data += save_len; - addr += MINIMUM_BLOCK; + + address += block_size; + len -= block_size; } + return 0; +} - if(len > 0) { - if(blockWrite(data, addr, ALIGN_FLASH(len)) < 0) - goto error; - addr += ALIGN_FLASH(len); - data += ALIGN_FLASH(len); - len -= ALIGN_FLASH(len); +/* ------------------------------------------------------------------ */ +/* flash_write_128: write exactly FACI_PROG_UNIT (128) bytes */ +/* addr must be 128-byte aligned */ +/* data must point to a RAM buffer (not code flash) */ +/* ------------------------------------------------------------------ */ +static int RAMFUNCTION flash_write_128(uint32_t addr, + const uint8_t *data) +{ + int i; + const uint16_t *d16 = (const uint16_t *)data; + + FLASH_READY() /* ensure FCU idle */ + FLASH_FSADDR = addr; + FACI_CMD8 = FACI_CMD_PROGRAM; + FACI_CMD8 = FACI_CMD_PROGRAM_LEN; /* 0x40 = 64 words */ + for (i = 0; i < 64; i++) { + while (FLASH_FSTATR & FLASH_FSTATR_DBFULL); + FACI_CMD16 = d16[i]; } + FACI_CMD8 = FACI_CMD_EXECUTE; + FLASH_READY() - if(len > 0) { - memcpy(save, (const void *)addr, MINIMUM_BLOCK); - memcpy(save, data, len); - if(R_FLASH_HP_Erase(&g_flash0_ctrl, addr, 1) != FSP_SUCCESS) - return -1; - if(R_FLASH_HP_Write(&g_flash0_ctrl, - (uint32_t)save, addr, MINIMUM_BLOCK) != FSP_SUCCESS) - goto error; + if (flash_check_error() != FLASH_OK) { + FACI_CMD8 = FACI_CMD_FORCED_STOP; + FLASH_READY() + FACI_CMD8 = FACI_CMD_STATUS_CLR; + return -1; } return 0; +} + +/* Static buffer used by hal_flash_write (must be in RAM) */ +static uint8_t prog_buf[FACI_PROG_UNIT]; + +/* ------------------------------------------------------------------ */ +/* flash_read_sector: read FACI_PROG_UNIT bytes from code flash */ +/* Must be called in read mode (FENTRYR.FENTRY0 = 0). */ +/* Temporarily exits P/E mode, reads, then re-enters P/E mode. */ +/* ------------------------------------------------------------------ */ +static void RAMFUNCTION flash_read_sector(uint32_t addr, uint8_t *buf) +{ + /* Exit P/E mode to read flash correctly (P/E mode returns 0xFF) */ + FLASH_FENTRYR = FLASH_FENTRYR_KEY; + while (!(FLASH_FSTATR & FLASH_FSTATR_FRDY)); + + memcpy(buf, (const uint8_t *)addr, FACI_PROG_UNIT); -error: - return -1; + /* Re-enter P/E mode (FMEPROT already cleared in hal_flash_unlock) */ + FLASH_FENTRYR = FLASH_FENTRYR_KEY | FLASH_FENTRYR_CODE_PR; + while (!(FLASH_FSTATR & FLASH_FSTATR_FRDY)); } -int hal_flash_erase(uint32_t address, int int_len) +/* ------------------------------------------------------------------ */ +/* hal_flash_write: write int_len bytes to addr */ +/* Unaligned start/end are handled with read-modify-write. */ +/* Reads from code flash require exiting P/E mode first */ +/* (RA6M4 FACI HP returns 0xFF for all reads while in P/E mode). */ +/* ------------------------------------------------------------------ */ +int RAMFUNCTION hal_flash_write(uint32_t addr, + const uint8_t *data, int int_len) { - uint32_t len = (uint32_t)int_len; - #ifdef WOLFBOOT_DUALBANK - uint32_t block_size = (address <= 0x80000 && address >= 0x10000) - || address >= 0x210000 ? (32*1024) : (8*1024); - #else /* Lenier mode */ - uint32_t block_size = address >= 0x10000 ? (32*1024) : (8*1024); - #endif - - if(len % block_size != 0) - return -1; + uint32_t len = (uint32_t)int_len; + uint32_t unaligned = addr % FACI_PROG_UNIT; + + /* --- Handle unaligned start --- */ + if (unaligned) { + uint32_t aligned = addr - unaligned; + uint32_t chunk = FACI_PROG_UNIT - unaligned; + if (chunk > len) + chunk = len; + + flash_read_sector(aligned, prog_buf); + memcpy(prog_buf + unaligned, data, chunk); + if (flash_write_128(aligned, prog_buf) < 0) + return -1; + + addr += chunk; + data += chunk; + len -= chunk; + } + + /* --- Aligned 128-byte blocks --- */ + while (len >= FACI_PROG_UNIT) { + memcpy(prog_buf, data, FACI_PROG_UNIT); + if (flash_write_128(addr, prog_buf) < 0) + return -1; + addr += FACI_PROG_UNIT; + data += FACI_PROG_UNIT; + len -= FACI_PROG_UNIT; + } - for( ; len; address+=block_size, len-=block_size) { - if(R_FLASH_HP_Erase(&g_flash0_ctrl, address, 1) - != FSP_SUCCESS) + /* --- Handle trailing partial block --- */ + if (len > 0) { + flash_read_sector(addr, prog_buf); + memcpy(prog_buf, data, len); + if (flash_write_128(addr, prog_buf) < 0) return -1; } + return 0; } +/* ------------------------------------------------------------------ */ +/* Dual-bank support */ +/* ------------------------------------------------------------------ */ #ifdef WOLFBOOT_DUALBANK - #define FLASH_START_ADDR 0x0 - #define FLASH_END_ADDR 0x7ffff - #define FLASH1_START_ADDR 0x200000 - #define FLASH1_END_ADDR 0x27ffff -#else - #define FLASH_START_ADDR 0x0 - #define FLASH_END_ADDR 0xfffff -#endif -void hal_flash_unlock(void) -{ - if(R_FLASH_HP_AccessWindowClear(&g_flash0_ctrl) != FSP_SUCCESS) - hal_panic(); - return; -} - -void hal_flash_lock(void) -{ - if(R_FLASH_HP_AccessWindowSet(&g_flash0_ctrl, - FLASH_START_ADDR, FLASH_END_ADDR) - != FSP_SUCCESS) - hal_panic(); - - #ifdef WOLFBOOT_DUALBANK - if(R_FLASH_HP_AccessWindowSet(&g_flash0_ctrl, - FLASH1_START_ADDR, FLASH1_END_ADDR) - != FSP_SUCCESS) - hal_panic(); - #endif - return; -} +/* FSUAC: Flash Startup Area Control Register */ +#define FLASH_FSUAC REG16(R_FACI_BASE + 0x54) +#define FLASH_FSUAC_KEY (0x6600) +#define FLASH_FSUAC_SAS_MSK (0x3) -#if WOLFBOOT_DUALBANK void RAMFUNCTION hal_flash_dualbank_swap(void) { - flash_cmd_t cmd = FLASH_CMD_SWAPFLAG_TOGGLE; - + uint16_t cur = FLASH_FSUAC & FLASH_FSUAC_SAS_MSK; hal_flash_unlock(); - - if(R_FLASH_HP_Control(cmd, NULL) != FSP_SUCCESS) - hal_panic(); - + FLASH_FSUAC = (uint16_t)(FLASH_FSUAC_KEY | (cur ^ 1u)); hal_flash_lock(); - } -void* hal_get_primary_address(void) +void *hal_get_primary_address(void) { - return (void*)WOLFBOOT_PARTITION_BOOT_ADDRESS; + return (void *)WOLFBOOT_PARTITION_BOOT_ADDRESS; } -void* hal_get_update_address(void) +void *hal_get_update_address(void) { - return (void*)WOLFBOOT_PARTITION_UPDATE_ADDRESS; + return (void *)WOLFBOOT_PARTITION_UPDATE_ADDRESS; } -#endif + +#endif /* WOLFBOOT_DUALBANK */ diff --git a/hal/renesas-ra.h b/hal/renesas-ra.h new file mode 100644 index 0000000000..2277cff837 --- /dev/null +++ b/hal/renesas-ra.h @@ -0,0 +1,149 @@ +/* renesas-ra.h + * + * Copyright (C) 2026 wolfSSL Inc. + * + * This file is part of wolfBoot. + * + * wolfBoot is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfBoot is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1335, USA + */ + +/* Base addresses */ +#define R_SYSTEM_BASE 0x4001E000UL +#define R_FACI_BASE 0x407FE000UL +#define R_FCACHE_BASE 0x4001C100UL + +/* Register access macros */ +#define REG8(addr) (*(volatile uint8_t *)(addr)) +#define REG16(addr) (*(volatile uint16_t *)(addr)) +#define REG32(addr) (*(volatile uint32_t *)(addr)) + +/* --- FACI HP registers --- */ +/* 0x407FE080: Flash Status Register */ +#define FLASH_FSTATR REG32(R_FACI_BASE + 0x80) +/* 0x407FE084: P/E Mode Entry Register */ +#define FLASH_FENTRYR REG16(R_FACI_BASE + 0x84) +/* 0x407FE030: Flash Start Address Register */ +#define FLASH_FSADDR REG32(R_FACI_BASE + 0x30) +/* 0x407FE01C: Flash Reset Register */ +#define FLASH_FRESETR REG8 (R_FACI_BASE + 0x1C) + +/* --- System register --- */ +/* 0x4001E416: Flash Write/Erase Protect Register */ +#define FLASH_FWEPROR REG8(R_SYSTEM_BASE + 0x416) +#define FLASH_FWEPROR_FLWE (1 << 0) /* 1 = P/E enabled */ +#define FLASH_FWEPROR_FLWD (1 << 1) /* 1 = P/E disabled */ + +/* --- FACI command issuing area (code flash) --- */ +#define FACI_CMD_AREA 0x407E0000UL +#define FACI_CMD8 (*(volatile uint8_t *)FACI_CMD_AREA) +#define FACI_CMD16 (*(volatile uint16_t *)FACI_CMD_AREA) + +/* --- FACI command bytes --- */ +#define FACI_CMD_PROGRAM 0xE8 /* Program (128-byte unit) */ +#define FACI_CMD_PROGRAM_LEN 0x40 /* 64 words = 128 bytes */ +#define FACI_CMD_BLOCK_ERASE 0x20 /* Block erase */ +#define FACI_CMD_EXECUTE 0xD0 /* Execute */ +#define FACI_CMD_STATUS_CLR 0x50 /* Clear status */ +#define FACI_CMD_FORCED_STOP 0xB3 /* Forced stop / cancel */ + +/* Minimum program unit: bytes per write operation */ +#define FACI_PROG_UNIT 128 + +/* --- FSTATR status flags --- */ +#define FLASH_FSTATR_FLWEERR (1 << 6) /* P/E Protect Error */ +#define FLASH_FSTATR_PRGSPD (1 << 8) /* Program Suspend */ +#define FLASH_FSTATR_ERSSPD (1 << 9) /* Erase Suspend */ +#define FLASH_FSTATR_DBFULL (1 << 10) /* Data Buffer Full */ +#define FLASH_FSTATR_SUSRDY (1 << 11) /* Suspend Ready */ +#define FLASH_FSTATR_PRGERR (1 << 12) /* Program Error */ +#define FLASH_FSTATR_ERSERR (1 << 13) /* Erase Error */ +#define FLASH_FSTATR_ILGLERR (1 << 14) /* Illegal Error */ +#define FLASH_FSTATR_FRDY (1 << 15) /* Flash Ready */ +#define FLASH_FSTATR_OTERR (1 << 20) /* Other Error */ +#define FLASH_FSTATR_SECERR (1 << 21) /* Security Error */ +#define FLASH_FSTATR_FESETERR (1 << 22) /* FENTRY Setting Error */ +#define FLASH_FSTATR_ILGCOMERR (1 << 23) /* Illegal Command Err */ + +/* 0x407FE0E4: Flash Sequencer Processing Clock Frequency Notification */ +#define FLASH_FPCKAR REG16(R_FACI_BASE + 0xE4) +/* KEY must be written as 0x1E in bits[15:8] to enable the PCKA write. + * PCKA[7:0] = PCLKA frequency in MHz, minus 1. */ +#define FLASH_FPCKAR_KEY (0x1E00U) + +/* PCLKA frequency for FPCKAR.PCKA (ICLK=200MHz, PCLKA_DIV=/2 -> 100MHz) */ +#ifndef RA_PCLKA + #define RA_PCLKA 100000000U /* 100 MHz */ +#endif +#define RA_PCLKA_MHZ (RA_PCLKA / 1000000U) + +/* --- FENTRYR constants --- */ +/* Upper byte must be 0xAA on write */ +#define FLASH_FENTRYR_KEY (0xAA00) +#define FLASH_FENTRYR_CODE_READ (0) +#define FLASH_FENTRYR_CODE_PR (1 << 0) /* Code Flash P/E mode */ + +/* 0x407FE044: Flash P/E Mode Entry Protection Register + * CEPROT bit0=1 silently blocks FENTRYR writes (P/E mode cannot be entered). + * KEY=0xD9 must be written in bits[15:8] simultaneously with CEPROT. + * Write FMEPROT_KEY|0 to clear CEPROT before entering P/E mode. */ +#define FLASH_FMEPROT REG16(R_FACI_BASE + 0x44) +#define FLASH_FMEPROT_KEY (0xD900U) + +/* UART registers (SCI7: P613=TXD7, P614=RXD7, J23 on EK-RA6M4) */ +#define R_SCI7_BASE 0x40118700UL +#define SCI_SMR REG8(R_SCI7_BASE + 0x00) /* Serial Mode */ +#define SCI_BRR REG8(R_SCI7_BASE + 0x01) /* Baud Rate */ +#define SCI_SCR REG8(R_SCI7_BASE + 0x02) /* Control */ +#define SCI_TDR REG8(R_SCI7_BASE + 0x03) /* Transmit Data */ +#define SCI_SSR REG8(R_SCI7_BASE + 0x04) /* Status */ +#define SCI_SCMR REG8(R_SCI7_BASE + 0x06) /* */ +#define SCI_SEMR REG8(R_SCI7_BASE + 0x07) /* */ +#define SCI_SCR_TE (1u << 5) +#define SCI_SCR_RE (1u << 4) +#define SCI_SSR_TEND (1u << 2) +#define SCI_SSR_TDRE (1u << 7) +#define SCI_SEMR_BGDM (1u << 6) +#define SCI_SEMR_ABCS (1u << 4) +#define SCI_SCMR_CHR1 (1u << 4) +#define R_MSTP_MSTPCRB REG32(0x40084004UL) +#define MSTPCRB_SCI7 (1u << 24) /* MSTPCRB bit24 = SCI7 */ +#define R_PFS_P613 REG32(0x400809B4UL) +#define R_PFS_P614 REG32(0x400809B8UL) +#define PFS_PMR (1u << 16) +#define PFS_PDR (1u << 2) +#define PFS_PODR (1u << 0) +#define PFS_PSEL_SCI7 (0x05u << 24) /* PSEL=0x05: SCI1/3/5/7/9 odd channels */ +#define R_PMISC_PWPR REG8(0x40080D03UL) +#define PWPR_PFSWE (1u << 6) +#define PWPR_B0WI (1u << 7) +#ifndef DEBUG_BAUD_RATE + #define DEBUG_BAUD_RATE 115200U +#endif +#ifndef RA_PCLKB + #define RA_PCLKB 50000000U +#endif +#define SCI_BRR_VAL (RA_PCLKB / (8U * DEBUG_BAUD_RATE) - 1U) +/* --- Flash error codes (used by flash_check_error) --- */ +typedef enum { + FLASH_OK = 0, + FLASH_ERR_ILGL, + FLASH_ERR_PRG, + FLASH_ERR_ERS, + FLASH_ERR_FLWE, + FLASH_ERR_FESET, + FLASH_ERR_SEC, + FLASH_ERR_OT, +} flash_err_t; diff --git a/src/boot_renesas.c b/src/boot_renesas.c index 4983caa782..309aadf563 100644 --- a/src/boot_renesas.c +++ b/src/boot_renesas.c @@ -36,6 +36,10 @@ extern uint32_t IMAGE_APP_RAM_start; #include "r_smc_entry.h" #endif +#if defined(_RENESAS_RA_) +#include "bsp_api.h" +#endif + void RAMFUNCTION arch_reboot(void) { #if defined(__RX__) @@ -67,7 +71,11 @@ void do_boot(const uint32_t *app_offset) #if defined(__CCRX__) clrpsw_i(); #elif defined(__GNUC__) +#if defined(_RENESAS_RA_) + __disable_irq(); +#else __builtin_rx_clrpsw('I'); +#endif #elif defined(__ICCRX__) __disable_interrupt(); #endif @@ -90,19 +98,28 @@ void do_boot(const uint32_t *app_offset) app_entry(); #endif #elif defined(_RENESAS_RA_) - app_sp = VECTOR_SP; - - __asm__ ("ldr r3, [%0]" ::"r"(app_sp)); - __asm__ ("mov sp, r3"); - - /* - * address of Reset Handler is stored in Vector table[] that is defined in startup.c. - * The vector for Reset Handler is placed right after Initial Stack Pointer. - * The application assumes to start from 0x10200. - * - */ - app_entry = (void(*)(void))(*VECTOR_Reset_Handler); - (*app_entry)(); + uint32_t app_reset; + + /* app_offset points to the application vector table (past wolfBoot header). + * Read Initial SP and Reset Handler from the application vector table. */ + app_sp = app_offset[0]; + app_reset = app_offset[1]; + + /* switch vector table to application */ + SCB->VTOR = (uint32_t)app_offset; + __DSB(); + __ISB(); + + /* Clear MSPLIM before changing MSP. + * wolfBoot's SystemInit() sets MSPLIM to wolfBoot's stack limit via + * __set_MSPLIM(BSP_PRV_STACK_LIMIT) (BSP_FEATURE_TZ_HAS_TRUSTZONE=1). + * If MSP is set to a value below MSPLIM, the CPU immediately triggers + * a UsageFault (STKOVF) which escalates to HardFault. */ + __set_MSPLIM(0U); + + __set_MSP(app_sp); + app_entry = (void(*)(void))app_reset; + app_entry(); #elif defined(_RENESAS_RZN_) app_entry = (void(*))(&IMAGE_APP_RAM_start); /* Jump to the application project */ diff --git a/src/string.c b/src/string.c index 7245ead8cd..c3033be2ba 100644 --- a/src/string.c +++ b/src/string.c @@ -27,6 +27,9 @@ #endif #include +#if defined(_RENESAS_RA_) +#include +#endif #ifndef TARGET_library #include #else @@ -40,7 +43,8 @@ size_t strlen(const char *s); /* forward declaration */ #endif #endif -#if !defined(__IAR_SYSTEMS_ICC__) && !defined(TARGET_X86_64_EFI) +#if !defined(__IAR_SYSTEMS_ICC__) && !defined(TARGET_X86_64_EFI) && \ + !defined(_RENESAS_RA_) /* for RAMFUNCTION */ #include "image.h" #endif