From 2ca78bbe4d1018d710ab9df53eaec969d9e33c91 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 16 Jul 2024 17:51:08 -0700 Subject: [PATCH] * Added support for RX65N and RX72N with native Makefile and RX ELF GCC compiler. * Added initialization of the clocks and UART driver. - wolfBoot uses on chip high speed oscillator (HOCO) at (120MHz RX65N and 240Mhz for RX72N). * Added RX RSPI and QSPI driver support with external SPI flash * Improve documentation and fix spelling errors. * Added .srec (s-record) format support * Added RX TSIP support for ECDSA (requires https://github.com/wolfSSL/wolfssl/pull/7685). * Allow custom implementation of `get_trailer_at`, `set_trailer_at` and `set_partition_magic` using `CUSTOM_PARTITION_TRAILER` --- .../workflows/test-powerfail-simulator.yml | 58 +- .gitignore | 16 + IDE/Renesas/e2studio/RA6M4/Readme.md | 61 +- IDE/Renesas/e2studio/RA6M4/Readme_wSCE.md | 52 +- IDE/Renesas/e2studio/RX72N/Readme.md | 50 +- IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md | 64 +- IDE/Renesas/e2studio/RZN2L/user_settings.h | 2 +- Makefile | 12 +- README.md | 2 +- arch.mk | 162 +++- config/examples/renesas-rx65n.config | 56 ++ config/examples/renesas-rx72n.config | 56 ++ .../sim-nobackup-nvm-writeonce.config | 2 +- docs/Renesas.md | 172 ++++ docs/Targets.md | 257 +++++- docs/flash_partitions.md | 45 +- hal/renesas-ra.c | 40 +- hal/renesas-rx.c | 629 ++++++++++--- hal/renesas-rx.h | 411 +++++++++ hal/rx65n.c | 23 + hal/rx65n.ld | 195 +++++ hal/rx72n.c | 23 + hal/rx72n.ld | 194 ++++ hal/spi/spi_drv_renesas_rx.c | 446 ++++++++++ hal/spi/spi_drv_renesas_rx.h | 30 + hal/zynq.c | 4 +- include/keystore.h | 8 +- include/printf.h | 3 + include/spi_drv.h | 11 + include/user_settings.h | 77 +- options.mk | 24 +- src/boot_renesas.c | 828 +++++++++++++++++- src/boot_renesas_start.S | 141 +++ src/image.c | 38 +- src/libwolfboot.c | 204 +++-- src/qspi_flash.c | 31 +- src/spi_flash.c | 73 +- src/update_flash.c | 6 +- stage1/Makefile | 2 + test-app/Makefile | 42 +- test-app/RENESAS_RX.ld | 182 ++++ test-app/app_renesas_rx.c | 151 ++++ tools/config.mk | 3 +- tools/keytools/Makefile | 16 +- tools/keytools/keygen.c | 237 ++--- 45 files changed, 4507 insertions(+), 632 deletions(-) create mode 100644 config/examples/renesas-rx65n.config create mode 100644 config/examples/renesas-rx72n.config create mode 100644 docs/Renesas.md create mode 100644 hal/renesas-rx.h create mode 100644 hal/rx65n.c create mode 100644 hal/rx65n.ld create mode 100644 hal/rx72n.c create mode 100644 hal/rx72n.ld create mode 100644 hal/spi/spi_drv_renesas_rx.c create mode 100644 hal/spi/spi_drv_renesas_rx.h create mode 100644 src/boot_renesas_start.S create mode 100644 test-app/RENESAS_RX.ld create mode 100644 test-app/app_renesas_rx.c diff --git a/.github/workflows/test-powerfail-simulator.yml b/.github/workflows/test-powerfail-simulator.yml index c4b06d7dc..b6e927a9b 100644 --- a/.github/workflows/test-powerfail-simulator.yml +++ b/.github/workflows/test-powerfail-simulator.yml @@ -60,12 +60,12 @@ jobs: tools/scripts/sim-update-emergency-fallback.sh - # TEST with NVM_WRITEONCE enabled + # TEST with NVM_FLASH_WRITEONCE enabled - name: make clean run: | make distclean - - name: Select config with NVM_WRITEONCE + - name: Select config with NVM_FLASH_WRITEONCE run: | cp config/examples/sim-nvm-writeonce.config .config @@ -77,7 +77,7 @@ jobs: run: | make clean && make test-sim-internal-flash-with-update - - name: Run sunny day update test (NVM_WRITEONCE) + - name: Run sunny day update test (NVM_FLASH_WRITEONCE) run: | tools/scripts/sim-sunnyday-update.sh @@ -85,7 +85,7 @@ jobs: run: | make clean && make test-sim-internal-flash-with-update - - name: Run update-revert test (NVM_WRITEONCE) + - name: Run update-revert test (NVM_FLASH_WRITEONCE) run: | tools/scripts/sim-update-fallback.sh @@ -93,7 +93,7 @@ jobs: run: | make clean && make test-sim-internal-flash-with-update - - name: Run update-revert test with power failures (NVM_WRITEONCE) + - name: Run update-revert test with power failures (NVM_FLASH_WRITEONCE) run: | tools/scripts/sim-update-powerfail-resume.sh @@ -106,12 +106,12 @@ jobs: tools/scripts/sim-update-emergency-fallback.sh - # TEST with NVM_WRITEONCE AND FLAGS_HOME enabled + # TEST with NVM_FLASH_WRITEONCE AND FLAGS_HOME enabled - name: make clean run: | make distclean - - name: Select config with NVM_WRITEONCE and FLAGS_HOME + - name: Select config with NVM_FLASH_WRITEONCE and FLAGS_HOME run: | cp config/examples/sim-nvm-writeonce-flags-home.config .config @@ -123,7 +123,7 @@ jobs: run: | make clean && make test-sim-internal-flash-with-update - - name: Run sunny day update test (NVM_WRITEONCE FLAGS_HOME) + - name: Run sunny day update test (NVM_FLASH_WRITEONCE FLAGS_HOME) run: | tools/scripts/sim-sunnyday-update.sh @@ -131,7 +131,7 @@ jobs: run: | make clean && make test-sim-internal-flash-with-update - - name: Run update-revert test (NVM_WRITEONCE FLAGS_HOME) + - name: Run update-revert test (NVM_FLASH_WRITEONCE FLAGS_HOME) run: | tools/scripts/sim-update-fallback.sh @@ -139,7 +139,7 @@ jobs: run: | make clean && make test-sim-internal-flash-with-update - - name: Run update-revert test with power failures (NVM_WRITEONCE FLAGS_HOME) + - name: Run update-revert test with power failures (NVM_FLASH_WRITEONCE FLAGS_HOME) run: | tools/scripts/sim-update-powerfail-resume.sh @@ -152,12 +152,12 @@ jobs: tools/scripts/sim-update-emergency-fallback.sh - # TEST with NVM_WRITEONCE AND FLAGS_HOME AND FLAGS_INVERT enabled + # TEST with NVM_FLASH_WRITEONCE AND FLAGS_HOME AND FLAGS_INVERT enabled - name: make clean run: | make distclean - - name: Select config with NVM_WRITEONCE and FLAGS_HOME and FLAGS_INVERT + - name: Select config with NVM_FLASH_WRITEONCE and FLAGS_HOME and FLAGS_INVERT run: | cp config/examples/sim-nvm-writeonce-flags-home-invert.config .config @@ -169,7 +169,7 @@ jobs: run: | make clean && make test-sim-external-flash-with-update - - name: Run sunny day update test (NVM_WRITEONCE FLAGS_HOME FLAGS_INVERT) + - name: Run sunny day update test (NVM_FLASH_WRITEONCE FLAGS_HOME FLAGS_INVERT) run: | tools/scripts/sim-sunnyday-update.sh @@ -177,7 +177,7 @@ jobs: run: | make clean && make test-sim-external-flash-with-update - - name: Run update-revert test (NVM_WRITEONCE FLAGS_HOME) + - name: Run update-revert test (NVM_FLASH_WRITEONCE FLAGS_HOME) run: | tools/scripts/sim-update-fallback.sh @@ -185,7 +185,7 @@ jobs: run: | make clean && make test-sim-external-flash-with-update - - name: Run update-revert test with power failures (NVM_WRITEONCE FLAGS_HOME FLAGS_INVERT) + - name: Run update-revert test with power failures (NVM_FLASH_WRITEONCE FLAGS_HOME FLAGS_INVERT) run: | tools/scripts/sim-update-powerfail-resume.sh @@ -325,7 +325,7 @@ jobs: tools/scripts/sim-update-powerfail-resume.sh - # TEST with encryption (aes128) and NVM_WRITEONCE + # TEST with encryption (aes128) and NVM_FLASH_WRITEONCE - name: make clean run: | make distclean @@ -342,7 +342,7 @@ jobs: run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run sunny day update test (AES128 NVM_WRITEONCE) + - name: Run sunny day update test (AES128 NVM_FLASH_WRITEONCE) run: | tools/scripts/sim-sunnyday-update.sh @@ -350,7 +350,7 @@ jobs: run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run update-revert test (AES128 NVM_WRITEONCE) + - name: Run update-revert test (AES128 NVM_FLASH_WRITEONCE) run: | tools/scripts/sim-update-fallback.sh @@ -358,7 +358,7 @@ jobs: run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run update-revert test with power failures (AES128 NVM_WRITEONCE) + - name: Run update-revert test with power failures (AES128 NVM_FLASH_WRITEONCE) run: | tools/scripts/sim-update-powerfail-resume.sh @@ -370,7 +370,7 @@ jobs: run: | tools/scripts/sim-update-emergency-fallback.sh - # TEST with encryption (aes128) and NVM_WRITEONCE and FLAGS_HOME + # TEST with encryption (aes128) and NVM_FLASH_WRITEONCE and FLAGS_HOME - name: make clean run: | @@ -387,19 +387,19 @@ jobs: - name: Build wolfboot.elf run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run sunny day update test (AES128 NVM_WRITEONCE FLAGS_HOME) + - name: Run sunny day update test (AES128 NVM_FLASH_WRITEONCE FLAGS_HOME) run: | tools/scripts/sim-sunnyday-update.sh - name: Rebuild wolfboot.elf run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run update-revert test (AES128 NVM_WRITEONCE FLAGS_HOME) + - name: Run update-revert test (AES128 NVM_FLASH_WRITEONCE FLAGS_HOME) run: | tools/scripts/sim-update-fallback.sh - name: Rebuild wolfboot.elf run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run update-revert test with power failures (AES128 NVM_WRITEONCE FLAGS_HOME) + - name: Run update-revert test with power failures (AES128 NVM_FLASH_WRITEONCE FLAGS_HOME) run: | tools/scripts/sim-update-powerfail-resume.sh @@ -411,7 +411,7 @@ jobs: run: | tools/scripts/sim-update-emergency-fallback.sh - # TEST with encryption (aes128) and NVM_WRITEONCE and FLAGS_HOME and FLAGS_INVERT + # TEST with encryption (aes128) and NVM_FLASH_WRITEONCE and FLAGS_HOME and FLAGS_INVERT - name: make clean run: | @@ -428,19 +428,19 @@ jobs: - name: Build wolfboot.elf run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run sunny day update test (AES128 NVM_WRITEONCE FLAGS_HOME FLAGS_INVERT) + - name: Run sunny day update test (AES128 NVM_FLASH_WRITEONCE FLAGS_HOME FLAGS_INVERT) run: | tools/scripts/sim-sunnyday-update.sh - name: Rebuild wolfboot.elf run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run update-revert test (AES128 NVM_WRITEONCE FLAGS_HOME FLAGS_INVERT) + - name: Run update-revert test (AES128 NVM_FLASH_WRITEONCE FLAGS_HOME FLAGS_INVERT) run: | tools/scripts/sim-update-fallback.sh - name: Rebuild wolfboot.elf run: | make clean && make test-sim-external-flash-with-enc-update - - name: Run update-revert test with power failures (AES128 NVM_WRITEONCE FLAGS_HOME FLAGS_INVERT) + - name: Run update-revert test with power failures (AES128 NVM_FLASH_WRITEONCE FLAGS_HOME FLAGS_INVERT) run: | tools/scripts/sim-update-powerfail-resume.sh @@ -452,7 +452,7 @@ jobs: run: | tools/scripts/sim-update-emergency-fallback.sh - # TEST with encryption (aes128) and NVM_WRITEONCE and DELTA updates + # TEST with encryption (aes128) and NVM_FLASH_WRITEONCE and DELTA updates - name: make clean run: | make distclean @@ -516,7 +516,7 @@ jobs: run: | tools/scripts/sim-update-powerfail-resume-nobackup.sh - # TEST with backup disabled + NVM_WRITEONCE + # TEST with backup disabled + NVM_FLASH_WRITEONCE - name: make clean run: | make distclean diff --git a/.gitignore b/.gitignore index 9262b9992..cb828f3f5 100644 --- a/.gitignore +++ b/.gitignore @@ -60,6 +60,9 @@ src/ecc384_pub_key.c src/ecc512_pub_key.c src/rsa2048_pub_key.c src/rsa4096_pub_key.c +# Renesas key data files +include/key_data.c +include/key_data.h # keygen binaries tools/keytools/sign @@ -149,6 +152,7 @@ debug/lauterbach *.gcda *.gcno coverage.* + IDE/MPLAB/test-app/test-usb-updater.same51.X/dist/ IDE/MPLAB/test-app/test-usb-updater.same51.X/.generated_files/ IDE/MPLAB/bootloader/wolfboot-same51.dualbank.X/dist/ @@ -205,3 +209,15 @@ include/x86/fsp/FspmUpd.h include/x86/fsp/FspsUpd.h include/x86/fsp/FsptUpd.h include/x86/fsp/MemInfoHob.h + +# IDE Renesas e2Studio generated +IDE/Renesas/e2studio/RX72N/app_RenesasRX01/HardwareDebug +IDE/Renesas/e2studio/RX72N/app_RenesasRX01/src/smc_gen +IDE/Renesas/e2studio/RX72N/wolfBoot/HardwareDebug +IDE/Renesas/e2studio/RX72N/wolfBoot/src/smc_gen + +# Renesas Libraries +lib/r_bsp +lib/r_config +lib/r_flash_rx +lib/r_tsip_rx diff --git a/IDE/Renesas/e2studio/RA6M4/Readme.md b/IDE/Renesas/e2studio/RA6M4/Readme.md index eb7e3d312..8d9b95269 100644 --- a/IDE/Renesas/e2studio/RA6M4/Readme.md +++ b/IDE/Renesas/e2studio/RA6M4/Readme.md @@ -2,16 +2,16 @@ ## 1. Overview -This example demonstrates simple secure firmware update by wolfBoot. -A sample application v1 is securely updated to v2. Both versions behave the same except displaying its version of v1 or v2. +This example demonstrates simple secure firmware update by wolfBoot. +A sample application v1 is securely updated to v2. Both versions behave the same except displaying its version of v1 or v2. They are compiled by e2Studio and running on the target board. -In this demo, you may download two versions of the application binary file by Renesas Flash Programmer. -You can download and excute wolfBoot by e2Studio debugger. Use a USB connection between PC and the board for the debugger and flash programmer. +In this demo, you may download two versions of the application binary file by Renesas Flash Programmer. +You can download and execute wolfBoot by e2Studio debugger. Use a USB connection between PC and the board for the debugger and flash programmer. Please see `Readme_wSCE.md` for Renesas SCE use case. -## 2. Components and Tools +## 2. Components and Tools |Item|Name/Version|Note| |:--|:--|:--| @@ -25,7 +25,6 @@ Please see `Readme_wSCE.md` for Renesas SCE use case. |Key tool|keygen and sign|Included in wolfBoot| - |FIT Components|Version| |:--|:--| |Board Support Package Common Files|v3.6.0| @@ -38,7 +37,6 @@ Please see `Readme_wSCE.md` for Renesas SCE use case. |Flash Memory High Performance|v3.6.0| - e2Studio Project:\ wolfBoot IDE/Renesas/e2studio/RA6M4/wolfBoot\ Sample app IDE/Renesas/e2studio/RA6M4/app_RA @@ -80,7 +78,7 @@ 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. -You can specify various signature algorithms such as +You can specify various signature algorithms such as ```les --ed25519 --ed448 --ecc256 --ecc384 --ecc521 --rsa2048 --rsa3072 --rsa4096 @@ -90,7 +88,7 @@ You can specify various signature algorithms such as Open project under IDE/Renesas/e2studio/RA6M4/wolfBoot with e2Studio, and build the project. Project properties are preset for the demo. -`WOLFBOOT_PARTION_INFO` is for debug information about partitions. Eliminate them for operational use. +`PRINTF_ENABLED` is for debug information about partitions. Eliminate them for operational use. #### 2-1) Create `dummy_library` Static Library + Click File->New->`RA C/C++ Project`. @@ -103,9 +101,9 @@ Open project under IDE/Renesas/e2studio/RA6M4/wolfBoot with e2Studio, and build + 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_falsh_hp)` stack from `New Stack` -> `Storage` ++ Add `g_flash0 Flash(r_flash_hp)` stack from `New Stack` -> `Storage` -Modify `g_flash0 Flash(r_flash_hp)` properites as follows: +Modify `g_flash0 Flash(r_flash_hp)` properties as follows: |Property|Value| |:--|:--| |Data Flash Background Operation|Disabled| @@ -115,7 +113,8 @@ Modify `g_flash0 Flash(r_flash_hp)` properites as follows: + 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` projet ++ Build `wolfBoot` project + ### 3) Compile the sample application Open project under IDE/Renesas/e2studio/RA6M4/app_RA with e2Studio, and build the project. @@ -140,20 +139,20 @@ Project properties are preset for the demo. 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_falsh_hp)` stack from `New Stack` -> `Storage` ++ Go to `BSP` tab and Add `g_flash0 Flash(r_flash_hp)` stack from `New Stack` -> `Storage` -Modify `g_flash0 Flash(r_flash_hp)` properites as follows: +Modify `g_flash0 Flash(r_flash_hp)` properties as follows: |Property|Value| |:--|:--| |Data Flash Background Operation|Disabled| @@ -163,18 +162,18 @@ Modify `g_flash0 Flash(r_flash_hp)` properites as follows: + 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` projet ++ Build `app_RA` project -Code Origin and entry point is "0x00010200". app_RA.elf is generated under Debug. +Code Origin and entry point is "0x00010200". app_RA.elf is generated under Debug. ### 4) Generate Signature for app V1 -You can derive bair binary file (app_RA.bin) by objcopy command as follows. +You can derive the binary file (app_RA.bin) using objcopy command as follows: ``` $ aarch64-none-elf-objcopy.exe -O binary -j .text -j .data app_RA.elf app_RA.bin ``` -"sign" command under tools/keytools benerates a signature for the binary with a specified version. +"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. @@ -204,10 +203,10 @@ You can convert the binary file to hex format and download it to the board by Fl $ aarch64-none-elf-objcopy.exe -I binary -O srec --change-addresses=0x00010000 app_RA_v1.0_signed.bin app_RA_v1.0_signed.hex ``` -### 6) Execute inital boot +### 6) Execute initial boot -Now, you can download and start wolfBoot program by e2Studio debugger. -After starting the program, you can see the partition information as follows. +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` @@ -230,13 +229,13 @@ Application Entry Address: 0x00010200 Magic: WOLF Version: 01 Status: FF -Tail Mgc: +Tail Mgc: === Update Partition[00080000] === -Magic: +Magic: Version: 00 Status: FF -Tail Mgc: +Tail Mgc: Current Firmware Version : 1 Calling wolfBoot_success() @@ -254,7 +253,7 @@ Status: 00 Tail Mgc: BOOT === Update Partition[00080000] === -Magic: +Magic: Version: 00 Status: FF Tail Mgc: @@ -267,7 +266,7 @@ We are going to generate and download V2 application into "Update partition". ### 7) Generate Signed app V2 and download it -Similar to V1, you can signe and generate a binary of V2. The update partition starts at "0x00080000". +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. Updtate partition: @@ -309,7 +308,7 @@ Tail Mgc: BOOT Magic: WOLF Version: 01 Status: FF -Tail Mgc: +Tail Mgc: Current Firmware Version : 2 Calling wolfBoot_success() @@ -324,8 +323,8 @@ Tail Mgc: BOOT Magic: WOLF Version: 01 Status: FF -Tail Mgc: +Tail Mgc: ``` You can see "Current Firmware Version : 2". The state is Success("00") and Tail Magic number becomes "BOOT". -You can also see flashing each LED light in 5 second at this new version. \ No newline at end of file +You can also see flashing each LED light in 5 second at this new version. diff --git a/IDE/Renesas/e2studio/RA6M4/Readme_wSCE.md b/IDE/Renesas/e2studio/RA6M4/Readme_wSCE.md index efaf433ce..875a7b2f7 100644 --- a/IDE/Renesas/e2studio/RA6M4/Readme_wSCE.md +++ b/IDE/Renesas/e2studio/RA6M4/Readme_wSCE.md @@ -2,10 +2,10 @@ ## 1. Overview -This example demonstrates simple secure firmware update by wolfBoot and uses Renesas SCE. +This example demonstrates simple secure firmware update by wolfBoot and uses Renesas SCE. A sample application v1 is securely updated to v2. Both versions behave the same except displaying its version of v1 or v2. They are compiled by e2Studio and running on the target board. -In this demo, you may download two versions of the application binary file by Renesas Flash Programmer. You can download and excute wolfBoot by e2Studio debugger. Use a USB connection between PC and the board for the debugger and flash programmer.It is only available RSA with Renesas SCE now. +In this demo, you may download two versions of the application binary file by Renesas Flash Programmer. You can download and execute wolfBoot by e2Studio debugger. Use a USB connection between PC and the board for the debugger and flash programmer.It is only available RSA with Renesas SCE now. ## 2. Components and Tools @@ -95,7 +95,7 @@ Enabled `WOLFBOOT_RENESAS_SCEPROTECT` expects to use Renesas SCE. + Add `SCE Protected Mode` stack from `New Stack` -> `Security` + Add `g_flash0 Flash(r_falsh_hp)` stack from `New Stack` -> `Storage` -Modify `g_flash0 Flash(r_flash_hp)` properites as follows: +Modify `g_flash0 Flash(r_flash_hp)` properties as follows: |Property|Value| |:--|:--| |Data Flash Background Operation|Disabled| @@ -105,7 +105,8 @@ Modify `g_flash0 Flash(r_flash_hp)` properites as follows: + 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` projet ++ Build `wolfBoot` project + ### 3) Compile the sample application Open project under IDE/Renesas/e2studio/RA6M4/app_RA with e2Studio. @@ -129,12 +130,12 @@ Open project under IDE/Renesas/e2studio/RA6M4/app_RA with e2Studio. 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. @@ -143,7 +144,7 @@ Open project under IDE/Renesas/e2studio/RA6M4/app_RA with e2Studio. + Check `Bare Metal Minimal`. Click Finish. + Go to `BSP` tab and Add `g_flash0 Flash(r_falsh_hp)` stack from `New Stack` -> `Storage` -Modify `g_flash0 Flash(r_flash_hp)` properites as follows: +Modify `g_flash0 Flash(r_flash_hp)` properties as follows: |Property|Value| |:--|:--| |Data Flash Background Operation|Disabled| @@ -154,10 +155,11 @@ Modify `g_flash0 Flash(r_flash_hp)` properites as follows: + Click `Generate Project Content` on Smart Configurator + Set `BSP_FEATURE_FLASH_SUPPORTS_ACCESS_WINDOW` to 1) + Linker option update, Click project->`Properties`->`C/C++ Build`->`Settings`->`GNU Arm Cross Linker`->`Miscellaneous`. Modify `--defsym=FLASH_IMAGE_START=0x10200` to `--defsym=FLASH_IMAGE_START=0x10200` -+ Build `app_RA` projet ++ Build `app_RA` project -Code Origin and entry point is "0x00020200". app_RA.elf is gnerated under Debug. +Code Origin and entry point is "0x00020200". app_RA.elf is generated under Debug. + ### 4) Generate Wrapped Key for SCE SCE needs to have a wrapped key for sign verification installed in advance. @@ -182,16 +184,16 @@ Please refer Renesas Manual to generate ufpk.key and upfk.key_enc.key. After generating "rfp" format key, you can download it to flash data area by using Renesas flash programmer. The default address for "rfp" key is `0x08001000U` which is set at `user_settings.h`. -### 4) Generate Signature for app V1 -You can derive bair binary file (app_RA.bin) by objcopy command as follows. +### 5) Generate Signature for app V1 +You can derive the binary file (app_RA.bin) by objcopy command as follows. ``` $ aarch64-none-elf-objcopy.exe -O binary -j .text -j .data app_RA.elf app_RA.bin ``` -`sign` command under tools/keytools benerates a signature for the binary with a specified version. +`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. +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. It needs to specify `--rsa2048enc` option to sign the image because SCE assumes to have DigestInfo structure before hashed data. @@ -211,18 +213,18 @@ Signing the digest... Output image(s) successfully created. ``` -### 5) Download the app V1 +### 6) Download the app V1 You can convert the binary file to hex format and download it to the board by Flash Programmer. The partition starts at "0x00020000". ``` $ aarch64-none-elf-objcopy.exe -I binary -O srec --change-addresses=0x00020000 app_RA_v1.0_signed.bin app_RA_v1.0_signed.hex ``` -### 6) Execute inital boot +### 7) Execute initial boot 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 integlity and authenticity check, it initiate the application V1. +If the boot program succeeds successfully and authenticity check then start application V1. To initially run `wolfBoot` project, 1.) Right-Click the Project name. 2.) Select `Debug As` -> `Renesas GDB Hardware Debugging` @@ -245,13 +247,13 @@ Application Entry Address: 0x00020200 Magic: WOLF Version: 01 Status: FF -Tail Mgc: +Tail Mgc: === Update Partition[00090000] === -Magic: +Magic: Version: 00 Status: FF -Tail Mgc: +Tail Mgc: Current Firmware Version : 1 Calling wolfBoot_success() @@ -270,7 +272,7 @@ Status: 00 Tail Mgc: BOOT === Update Partition[00090000] === -Magic: +Magic: Version: 00 Status: FF Tail Mgc: @@ -281,7 +283,7 @@ You can also see flashing each LED light in 1 second. Notable things about V1 ap 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". -### 7) Generate Signed app V2 and download it +### 8) Generate Signed app V2 and download it Similar to V1, you can sign and generate a binary of V2. The update partition starts at "0x00090000". You can download it by the flash programmer. @@ -294,9 +296,9 @@ $ sign --rsa2048enc app_RA.bin ../../../../../pri-rsa2048.der 2.0 $ aarch64-none-elf-objcopy.exe -I binary -O srec --change-addresses=0x00090000 app_RA_v2.0_signed.bin app_RA_v2.0_signed.hex ``` -### 8) Reboot and secure update to V2 +### 9) Reboot and secure update to V2 -The boot program checks integlity and authenticity of V2, swap the partition safely and initiates 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. @@ -322,7 +324,7 @@ Tail Mgc: BOOT Magic: WOLF Version: 01 Status: FF -Tail Mgc: +Tail Mgc: Current Firmware Version : 2 Calling wolfBoot_success() diff --git a/IDE/Renesas/e2studio/RX72N/Readme.md b/IDE/Renesas/e2studio/RX72N/Readme.md index 70e0af53f..c4c6098c9 100644 --- a/IDE/Renesas/e2studio/RX72N/Readme.md +++ b/IDE/Renesas/e2studio/RX72N/Readme.md @@ -2,7 +2,8 @@ ## 1. Overview -This example demonstrates simple secure firmware update by wolfBoot. A sample application v1 is + +This example for `Renesas RX72N` demonstrates simple secure firmware update by wolfBoot. A sample application v1 is securely updated to v2. Both versions behave the same except displaying its version of v1 or v2. They are compiled by e2Studio and running on the target board. @@ -48,19 +49,21 @@ Flash Allocation: 0xffdf8100: Update partition (Application image) /* When it uses IMAGE_HEADER_SIZE 256, e.g. ED25519, EC256, EC384 or EC512 */ 0xffdf8200: Update partition (Application image) /* When it uses IMAGE_HEADER_SIZE 512, e.g. RSA2048, RSA3072 */ 0xfffe0000: Swap sector - ``` Note : Depending on IMAGE_HEADER_SIZE, it needs to change the address of Power Reset vector by Linker section. Application default is set to 0xffc10200. It means that you need to change it when you use 256 IMAGE_HEADER_SIZE. +To resolve the "RPFRAM" section not assigned / overflow follow the RX Family Flash Module guide section 5.3.1.1 or 5.3.12 for adding that section. +https://www.renesas.com/us/en/document/apn/rx-family-flash-module-using-firmware-integration-technology + ## 3. How to build and use It has key tools running under the host environment such as Linux, Windows or MacOS. -For comiling the tools, follow the instruction described in the user manual. +For compiling the tools, follow the instruction described in the user manual. It demonstrates simple secure firmware update by wolfBoot. A sample application v1 is -cerurely updated to v2. Both versions behave the same except displaying its version of v1 or v2. +securely updated to v2. Both versions behave the same except displaying its version of v1 or v2. They are compiled by e2Studio and running on the target board. In this demo, you may download two versions of application binary file by Renesas Flash Programmer. @@ -72,14 +75,14 @@ board for the debugger and flash programmer. ``` $ cd -$ export PATH:$PATH:/tools/keytools -$ keygen --ecc256 -g ./pri-ecc256.der +$ make keytools +$ ./tools/keytools/keygen --ecc256 -g ./pri-ecc256.der ``` This generates a pair of private and public keys 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" soo that it can be compiled and linked with wolfBoot. -If you have an existing key pair, you can use -i option to import the pablic +If you have an existing key pair, you can use -i option to import the public key to the store. You can specify various signature algorithms such as @@ -94,6 +97,8 @@ Open project under IDE/Renesas/e2studio/RX72N/wolfBoot with e2Studio, and build Project properties are preset for the demo. +Open the wolfBoot.scfg from e2Studio and allow it to download/install the required FIT modules for the RX72N and `r_flash_rx`. + ``` Smart Configurator Flash Driver: r_flash_rx @@ -104,17 +109,15 @@ Include Paths ../../../../../../lib/wolfssl/ : /lib/wolfssl Pre-Include -../../include/user_settings.h : /IDE/Renesas/e2studio/RX72N/include/user_settigs.h +../../include/user_settings.h : /IDE/Renesas/e2studio/RX72N/include/user_settings.h ../../include/target.h : /IDE/Renesas/e2studio/RX72N/include/target.h Pre-defined Pre-processor Macro __WOLFBOOT -WOLFBOOT_PARTIION_INFO PRINTF_ENABLED - ``` -WOLFBOOT_PARTION_INFO, PRINTF_ENABLED are for debug information about partitions. +`PRINTF_ENABLED` is for debug information about partitions. Eliminate them for operational use. @@ -135,15 +138,18 @@ Include Paths ../../../../../../include : /include Pre-Include -../../include/user_settings.h : /IDE/Renesas/e2studio/RX72N/include/user_settigs.h +../../include/user_settings.h : /IDE/Renesas/e2studio/RX72N/include/user_settings.h ../../include/target.h : /IDE/Renesas/e2studio/RX72N/include/target.h Code Origin and entry point (PResetPRG) is "0xffc10200" (See Section Viewer of Linker Section). ``` -app_RenesasRx01.x in ELF is generated under HardwareDebug. You can derive bair binary file -(app_RenesasRx01.bin) by rx-elf-objcopy.exe command as follows. -R are for eliminate unnecessary -secrions. +`app_RenesasRx01.x` in ELF is generated under HardwareDebug (`IDE/Renesas/e2studio/RX72N/app_RenesasRX01/HardwareDebug`). + +Build tools are typically located here: +`C:\ProgramData\GCC for Renesas RX 8.3.0.202305-GNURX-ELF\rx-elf\rx-elf\bin` or `/c/ProgramData/GCC\ for\ Renesas\ RX\ 8.3.0.202305-GNURX-ELF/rx-elf/rx-elf/bin` + +You can derive the binary file `app_RenesasRx01.bin` by using `rx-elf-objcopy.exe` as follows: ``` $ rx-elf-objcopy.exe -O binary\ @@ -152,15 +158,17 @@ $ rx-elf-objcopy.exe -O binary\ -R '$ADDR_C_FE7F5D70' -R EXCEPTVECT -R RESETVECT app_RenesasRx01.x app_RenesasRx01.bin ``` +Note `-R` is for eliminate unnecessary sections. + ### 3-5 Generate Signature for app V1 -The `sign` command under tools/keytools generates a signature for the binary with a specified version. +The sign tool (`tools/keytools/sign`) generates a signature for the binary with a specified version. It generates a file containing a partition header and application image. The partition header includes the 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. +the input file name and version like `app_RenesasRx01_v1.0_signed.bin`. ``` -$ sign --ecc256 app_RenesasRx01.bin ../../../../../pri-ecc256.der 1.0 ecc256.der 1.0 +$ ./tools/keytools/sign --ecc256 IDE/Renesas/e2studio/RX72N/app_RenesasRX01/HardwareDebug/app_RenesasRx01.bin pri-ecc256.der 1.0 ecc256.der 1.0 wolfBoot KeyTools (Compiled C version) wolfBoot version 10B0000 Update type: Firmware @@ -177,11 +185,11 @@ Output image(s) successfully created. ### 3-6 Download the app V1 -You can convert the binary file to hex format and download it to the board by Flash Programmer. +You can convert the binary file to hex format and download it to the board by Renesas Flash Programmer tool. Use E2 emulator lite and FINE interface. The partition starts at "0xffc10000". ``` -$ rx-elf-objcopy.exe -I binary -O srec --change-addresses=0xffc10000 app_RenesasRx01_v1.0_signed.bin app_RenesasRx01_v1.0_signed.hex +$ rx-elf-objcopy.exe -I binary -O srec --change-addresses=0xffc10000 IDE/Renesas/e2studio/RX72N/app_RenesasRX01/HardwareDebug/app_RenesasRx01_v1.0_signed.bin IDE/Renesas/e2studio/RX72N/app_RenesasRX01/HardwareDebug/app_RenesasRx01_v1.0_signed.hex ``` @@ -236,7 +244,7 @@ You can see the state is Success("00"). ### 3-8 Generate Signed app V2 and download it -Similar to V1, you can signe and generate a binary of V2. The update partition starts at "0xffdf8000". +Similar to V1, you can sign and generate a binary of V2. The update partition starts at "0xffdf8000". You can download it by the flash programmer. diff --git a/IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md b/IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md index 0d27ef395..b407c2da2 100644 --- a/IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md +++ b/IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md @@ -7,10 +7,9 @@ securely updated to v2. Both versions behave the same except displaying its vers They are compiled by e2Studio and running on the target board. In this demo, you may download two versions of application binary file by Renesas Flash Programmer. -You can download and excute wolfBoot by e2Studio debugger. Use a USB connection between PC and the +You can download and execute wolfBoot by e2Studio debugger. Use a USB connection between PC and the board for the debugger and flash programmer. It is only available RSA with Renesas TSIP now. - ## 2. Components and Tools |Item|Name/Version|Note| @@ -34,7 +33,7 @@ FIT Module |r_tsip_rx|v1.18.J|Library or Source Version. Please contact Renesas to get source code version.| -Flash Allocation(TSIP Library version use): +Flash Allocation (TSIP Library version use): ``` +---------------------------+------------------------+-----+ | B |H| |H| | | @@ -48,7 +47,6 @@ Flash Allocation(TSIP Library version use): 0xffe20000: Update partition (Header) 0xffe20200: Update partition (Application image) 0xfffd0000: Swap sector - ``` Note : Depending on IMAGE_HEADER_SIZE, it needs to change the address of Power Reset vector by Linker section. @@ -77,14 +75,14 @@ Note : By enabling `WOLFBOOT_RENESAS_TSIP_SRCVERSION`, this example uses the all ## 3. How to build and use It has key tools running under the host environment such as Linux, Windows or MacOS. -For comiling the tools, follow the instruction described in the user manual. +For compiling the tools, follow the instruction described in the user manual. It demonstrates simple secure firmware update by wolfBoot. A sample application v1 is -cerurely updated to v2. Both versions behave the same except displaying its version of v1 or v2. +securely updated to v2. Both versions behave the same except displaying its version of v1 or v2. They are compiled by e2Studio and running on the target board. In this demo, you may download two versions of application binary file by Renesas Flash Programmer. -You can download and excute wolfBoot by e2Studio debugger. Use a USB connection between PC and the +You can download and execute wolfBoot by e2Studio debugger. Use a USB connection between PC and the board for the debugger and flash programmer. @@ -93,8 +91,7 @@ board for the debugger and flash programmer. ``` $ cd $ make keytools RENESAS_KEY=2 -$ export PATH:$PATH:/tools/keytools -$ keygen --rsa2048 -g ./pri-rsa2048.der +$ ./tools/keytools/keygen --rsa2048 -g ./pri-rsa2048.der Keytype: RSA2048 Gen ./pri-rsa2048.der Generating key (type: RSA2048) @@ -105,10 +102,10 @@ Public key slot: 0 Done. ``` -This generates a pair of private and public keys 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 +This generates a pair of private and public keys 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" soo that it can be compiled and linked with wolfBoot. -If you have an existing key pair, you can use -i option to import the pablic +If you have an existing key pair, you can use -i option to import the public key to the store. ### 3-2 Compile wolfBoot @@ -127,19 +124,19 @@ Include Paths ../../../../../../lib/wolfssl/ : /lib/wolfssl Pre-Include -../../include/user_settings.h : /IDE/Renesas/e2studio/RX72N/include/user_settigs.h +../../include/user_settings.h : /IDE/Renesas/e2studio/RX72N/include/user_settings.h ../../include/target.h : /IDE/Renesas/e2studio/RX72N/include/target.h ``` To enable TSIP use, it needs commenting out `WOLFBOOT_RENESAS_TSIP`. To enable TSIP Source code version, please comment out `WOLFBOOT_RENESAS_TSIP_SRCVERSION`. -`WOLFBOOT_PARTION_INFO` and `PRINTF_ENABLED` are for debug information about partitions. +`PRINTF_ENABLED` are for debug information about partitions. Eliminate them for operational use. When you use TSIP source code version, taking the following two steps optimize TSIP driver size. -* Set unnecessary ciphers to "No using XXXX" by Smart Configuration. Only select +* Set unnecessary ciphers to "No using XXXX" by Smart Configuration. Only select * Check "Deletes variables/functions that are not referenced)" Liker optimization option, [Project]->[Properties]->[C/C++ Build]->[Settings]->[Linker]->[Optimization] @@ -160,7 +157,7 @@ Include Paths ../../../../../../include : /include Pre-Include -../../include/user_settings.h : /IDE/Renesas/e2studio/RX72N/include/user_settigs.h +../../include/user_settings.h : /IDE/Renesas/e2studio/RX72N/include/user_settings.h ../../include/target.h : /IDE/Renesas/e2studio/RX72N/include/target.h Code Origin and entry point (PResetPRG) is "0xffc70200" (See Section Viewer of Linker Section). @@ -168,9 +165,9 @@ Code Origin and entry point (PResetPRG) is "0xffc10200" (TSIP source code versio You would need updating section settings depending on either TSIP version use. ``` -app_RenesasRx01.x in ELF is gnerated under HardwareDebug. You can derive bair binary file +app_RenesasRx01.x in ELF is generated under HardwareDebug. You can derive the binary file (app_RenesasRx01.bin) by rx-elf-objcopy.exe command as follows. -R are for eliminate unnecessary -secrions. +sections. ``` $ rx-elf-objcopy.exe -O binary\ @@ -182,7 +179,7 @@ $ rx-elf-objcopy.exe -O binary\ ### 3-3 Generate Encrypted Key for TSIP TSIP requires to have a encrypted public key for sign verification to generate its own Renesas TSIP Key. -This example supports RSA2048. +This example supports RSA2048. You can generate a RSA key pair by wolfBoot "keygen" command along with Renesas Security Key Management Tool "skmt". "skmt" command creates the encrypted Renesas key, generating Motorola hex file for writing it to flash memory and also generates a c header and source file for an application program with TSIP. @@ -193,22 +190,23 @@ To generate a RSA key for sign and verify, you can follow the following commands $ export PATH:$PATH:/tools/keytools $ export PATH:$PATH: $ cd -$ keygen --rsa2048 -g ./rsa-pri2048.der -$ openssl rsa -in rsa-pri2048.der -pubout -out rsa-pub2048.pem +$ keygen --rsa2048 -g ./pri-rsa2048.der +$ openssl rsa -inform der -in ./pri-rsa2048.der -pubout -out ./pub-rsa2048.pem ``` Generate a c header and source file from PEM file : ``` -$ skmt.exe /genkey /ufpk file=./sample.key /wufpk file=./sample.key_enc.key -key file=./pub-rsa2048.pem -mcu RX-TSIP -keytype RSA-2048-public /output key_data.c /filetype csource /keyname rsa2048_pub +$ export PATH="$PATH:C:\Renesas\SecurityKeyManagementTool\cli" +$ skmt.exe -genkey -ufpk file=./sample.key -wufpk file=./sample.key_enc.key -key file=./pub-rsa2048.pem -mcu RX-TSIP -keytype RSA-2048-public -output key_data.c -filetype csource -keyname enc_pub_key ``` -The value of option `/keyname` becomes structure name and macro definition defined in key_data.h. Therefore, please specify `rsa2048_pub` like above unless there is some particular reason. - +The value of option `-keyname` becomes structure name and macro definition defined in key_data.h. Therefore, please specify `enc_pub_key` like above unless there is some particular reason. + Copy a generated c header file, which is `key_data.h` to `/include/` folder Generate Motorola hex file to write it to flash memory from PEM file : ``` -$ skmt.exe /genkey /ufpk file=./sample.key /wufpk file=./sample.key_enc.key -key file=./pub-rsa2048.pem -mcu RX-TSIP -keytype RSA-2048-public /output rsa_pub2048.mot /filetype "mot" /address "FFFF0000" +$ skmt.exe -genkey -ufpk file=./sample.key -wufpk file=./sample.key_enc.key -key file=./pub-rsa2048.pem -mcu RX-TSIP -keytype RSA-2048-public -output rsa_pub2048.mot -filetype "mot" -address "FFFF0000" ``` The generated `mot` key is written to `0xFFFF0000` address. The flash memory address is set by macro, which is `RENESAS_TSIP_INSTALLEDKEY_ADDR` in `user_settings.h` After generating "mot" format key, you can download it to flash data area by using Renesas flash programmer. @@ -248,18 +246,18 @@ The partition starts at "0xffc70000"(TSIP library version) or "0xffc10000"(TSIP ``` For TSIP Library version $ rx-elf-objcopy.exe -I binary -O srec --change-addresses=0xffc70000 app_RenesasRx01_v1.0_signed.bin app_RenesasRx01_v1.0_signed.hex -or +or For TSIP Source version $ rx-elf-objcopy.exe -I binary -O srec --change-addresses=0xffc10000 app_RenesasRx01_v1.0_signed.bin app_RenesasRx01_v1.0_signed.hex ``` -### 3-7 Execute inital boot +### 3-7 Execute initial boot 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. +application V1. ``` @@ -285,9 +283,9 @@ Hit any key to call wolfBoot_success the firmware. ``` After hitting any key, the application calls wolfBoot_success() to set boot partition -state and wait for any key again. +state and wait for any key again. -If you re-start the boot program at this moment, +If you re-start the boot program at this moment, after checking the integrity and authenticity, it jumps to the application. You can see the state is Success("00"). @@ -309,7 +307,7 @@ Hit any key to update the firmware. ### 3-8 Generate Signed app V2 and download it -Similar to V1, you can signe and generate a binary of V2. The update partition starts at "0xffdf0000". +Similar to V1, you can sign and generate a binary of V2. The update partition starts at "0xffdf0000". You can download it by the flash programmer. @@ -327,7 +325,7 @@ $ rx-elf-objcopy.exe -I binary -O srec --change-addresses=0xffdf0000 app_Renesas Now the image is downloaded but note that the partition status is not changed yet. When it is re-boot, it checks integrity and authenticity of V1 and initiate V1 as in -step 6. +step 6. ``` | -------------------------------------------------------------------------------- | @@ -340,7 +338,7 @@ Firmware Update is triggered ``` After you see the message, hit any key so that the application calls -wolfBoot_update_trigger() whcih changes the partition status and triggers +wolfBoot_update_trigger(), which changes the partition status and triggers updating the firmware. Since this is just a trigger, the application can continue the process. diff --git a/IDE/Renesas/e2studio/RZN2L/user_settings.h b/IDE/Renesas/e2studio/RZN2L/user_settings.h index 5ced0adc0..a7c848a29 100644 --- a/IDE/Renesas/e2studio/RZN2L/user_settings.h +++ b/IDE/Renesas/e2studio/RZN2L/user_settings.h @@ -56,7 +56,7 @@ #define RENESAS_RSIP_INSTALLEDKEY_FLASH_ADDR 0x60200000 #define RENESAS_RSIP_INSTALLEDKEY_RAM_ADDR 0x10000100 #define RENESAS_DEVID 7890 - + #if defined(WOLFBOOT_SIGN_RSA3072) ||\ defined(WOLFBOOT_SIGN_RSA4096) ||\ defined(WOLFBOOT_SIGN_ED25519) ||\ diff --git a/Makefile b/Makefile index dfb1d5a4e..ae7b0be4b 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,10 @@ DEBUG_UART?=0 LIBS= SIGN_ALG= OBJCOPY_FLAGS= +BIG_ENDIAN?=0 +USE_GCC?=1 +USE_GCC_HEADLESS?=1 +FLASH_OTP_KEYSTORE?=0 OBJS:= \ ./src/string.o \ @@ -247,7 +251,7 @@ factory_wstage1.bin: $(BINASSEMBLE) stage1/loader_stage1.bin wolfboot.bin $(BOOT wolfboot_stage1.bin: wolfboot.elf stage1/loader_stage1.bin $(Q) cp stage1/loader_stage1.bin wolfboot_stage1.bin -wolfboot.elf: include/target.h $(LSCRIPT) $(OBJS) $(LIBS) $(BINASSEMBLE) FORCE +wolfboot.elf: include/target.h $(LSCRIPT) $(OBJS) $(BINASSEMBLE) FORCE $(Q)(test $(SIGN) = NONE) || (test $(FLASH_OTP_KEYSTORE) = 1) || (grep -q $(SIGN_ALG) src/keystore.c) || \ (echo "Key mismatch: please run 'make distclean' to remove all keys if you want to change algorithm" && false) @echo "\t[LD] $@" @@ -281,11 +285,16 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE > $@ hex: wolfboot.hex +srec: wolfboot.srec %.hex:%.elf @echo "\t[ELF2HEX] $@" @$(OBJCOPY) -O ihex $^ $@ +%.srec:%.elf + @echo "\t[ELF2SREC] $@" + @$(OBJCOPY) -O srec $^ $@ + src/keystore.c: $(PRIVATE_KEY) flash_keystore: src/flash_otp_keystore.o @@ -299,6 +308,7 @@ keys: $(PRIVATE_KEY) clean: $(Q)rm -f src/*.o hal/*.o hal/spi/*.o test-app/*.o src/x86/*.o $(Q)rm -f lib/wolfssl/wolfcrypt/src/*.o lib/wolfTPM/src/*.o lib/wolfTPM/hal/*.o + $(Q)rm -f lib/wolfssl/wolfcrypt/src/port/Renesas/*.o $(Q)rm -f wolfboot.bin wolfboot.elf wolfboot.map test-update.rom wolfboot.hex $(Q)rm -f $(MACHINE_OBJ) $(MAIN_TARGET) $(LSCRIPT) $(Q)rm -f $(OBJS) diff --git a/README.md b/README.md index 02032878a..f3c00a9a7 100644 --- a/README.md +++ b/README.md @@ -369,7 +369,7 @@ Use `make keysclean` to delete keys and regenerate. * Fix RSA keygen tool * wolfTPM integration: improvements and bugfixes * Fix configuration and documentation for STM32WB - * Fix alignment of trailers in NVM_WRITEONCE mode + * Fix alignment of trailers in NVM_FLASH_WRITEONCE mode * Fix uint16_t index overflow on platforms with very small flash pages * Fix for building C key tools on windows (Cygwin/MinGW/Visual Studio) * Fix in LPC driver: correct page alignment in flash write diff --git a/arch.mk b/arch.mk index 039082b81..056c6891a 100644 --- a/arch.mk +++ b/arch.mk @@ -269,6 +269,146 @@ ifeq ($(TZEN),1) CFLAGS+=-DTZEN endif + +## Renesas RX +ifeq ($(ARCH),RENESAS_RX) + RX_GCC_PATH?=~/toolchains/gcc_8.3.0.202311_rx_elf + CROSS_COMPILE?=$(RX_GCC_PATH)/bin/rx-elf- + + ## Toolchain setup + ifeq ($(USE_GCC),0) + CC=$(CROSS_COMPILE)gcc + # Must use LD directly (gcc link calls LD with sysroot and is not supported) + LD=$(CROSS_COMPILE)ld + AS=$(CROSS_COMPILE)gcc + OBJCOPY?=$(CROSS_COMPILE)objcopy + SIZE=$(CROSS_COMPILE)size + + # Override flags + USE_GCC_HEADLESS=0 + LD_START_GROUP=--start-group + LD_END_GROUP=--end-group + CFLAGS+=-Wall -Wextra -ffreestanding -Wno-unused -nostartfiles -fno-common + CFLAGS+=-ffunction-sections -fdata-sections + CFLAGS+=-B$(dir $(CROSS_COMPILE)) + LDFLAGS+=-gc-sections -Map=wolfboot.map + LDFLAGS+=-T $(LSCRIPT) -L$(dir $(CROSS_COMPILE))../lib + LIBS+=-lgcc + endif + + # Renesas specific files + OBJS+=src/boot_renesas.o src/boot_renesas_start.o hal/renesas-rx.o + ifeq ($(SPMATH),1) + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o + endif + + # RX parts support big or little endian data depending on MDE register + CFLAGS+=-fomit-frame-pointer -nofpu + ifeq ($(BIG_ENDIAN),1) + CFLAGS+=-mbig-endian-data + ifeq ($(USE_GCC),1) + LDFLAGS+=-Wl,--oformat=elf32-rx-be + CFLAGS+=-misa=v2 + else + LDFLAGS+=--oformat=elf32-rx-be + endif + else + CFLAGS+=-mlittle-endian-data + ifeq ($(USE_GCC),1) + LDFLAGS+=-Wl,--oformat=elf32-rx-le + CFLAGS+=-misa=v2 + else + LDFLAGS+=--oformat=elf32-rx-le + endif + endif + + ifeq ($(PKA),1) + CFLAGS+=-DWOLFBOOT_RENESAS_TSIP + RX_DRIVER_PATH?=./lib + + OBJS+=./lib/wolfssl/wolfcrypt/src/cryptocb.o \ + ./lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_common.o \ + ./lib/wolfssl/wolfcrypt/src/port/Renesas/renesas_tsip_util.o + + # RX TSIP uses pre-compiled .a library by default + ifeq ($(RX_TSIP_SRC),) + ifeq ($(TARGET),rx65n) + ifeq ($(BIG_ENDIAN),1) + LIBS+=$(RX_DRIVER_PATH)/r_tsip_rx/lib/gcc/libr_tsip_rx65n_big.a + else + LIBS+=$(RX_DRIVER_PATH)/r_tsip_rx/lib/gcc/libr_tsip_rx65n_little.a + endif + endif + ifeq ($(TARGET),rx72n) + ifeq ($(BIG_ENDIAN),1) + LIBS+=$(RX_DRIVER_PATH)/r_tsip_rx/lib/gcc/libr_tsip_rx72m_rx72n_rx66n_big.a + else + LIBS+=$(RX_DRIVER_PATH)/r_tsip_rx/lib/gcc/libr_tsip_rx72m_rx72n_rx66n_little.a + endif + endif + else + CFLAGS+=-DRX_TSIP_SRC + ifeq ($(TARGET),rx65n) + RX_TSIP_SRC_PATH?=$(RX_DRIVER_PATH)/r_tsip_rx/src/targets/rx65n + endif + ifeq ($(TARGET),rx72n) + RX_TSIP_SRC_PATH?=$(RX_DRIVER_PATH)/r_tsip_rx/src/targets/rx72m_rx72n_rx66n + endif + # Use RX_TSIP_SRC if building TSIP sources directly + OBJS+=$(RX_TSIP_SRC_PATH)/r_tsip_rx.o \ + $(RX_TSIP_SRC_PATH)/r_tsip_rx_private.o \ + $(RX_TSIP_SRC_PATH)/r_tsip_aes_rx.o \ + $(RX_TSIP_SRC_PATH)/r_tsip_hash_rx.o \ + $(RX_TSIP_SRC_PATH)/r_tsip_ecc_rx.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_pfa.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_pfb.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_pf1.o \ + $(RX_TSIP_SRC_PATH)/ip/s_flash.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_p00.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_p01.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_p02.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_p23.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_p26.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_p72.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_subprc01.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_subprc02.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function004.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function005.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function006.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function009.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function010.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function011.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function023.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function050.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function051.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function052.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function053.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function054.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function100.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function101.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function102.o \ + $(RX_TSIP_SRC_PATH)/ip/r_tsip_rx_function103.o + endif + + OBJS+=$(RX_DRIVER_PATH)/r_bsp/mcu/all/r_bsp_cpu.o \ + $(RX_DRIVER_PATH)/r_bsp/mcu/all/r_bsp_interrupts.o \ + $(RX_DRIVER_PATH)/r_bsp/mcu/all/r_rx_intrinsic_functions.o + ifeq ($(TARGET),rx65n) + OBJS+=$(RX_DRIVER_PATH)/r_bsp/mcu/rx65n/mcu_interrupts.o + endif + ifeq ($(TARGET),rx72n) + OBJS+=$(RX_DRIVER_PATH)/r_bsp/mcu/rx72n/mcu_interrupts.o + endif + + CFLAGS+=-Ihal -I./lib/wolfssl \ + -I$(RX_DRIVER_PATH)/r_bsp \ + -I$(RX_DRIVER_PATH)/r_config \ + -I$(RX_DRIVER_PATH)/r_tsip_rx \ + -I$(RX_DRIVER_PATH)/r_tsip_rx/src + endif +endif + + ## RISCV ifeq ($(ARCH),RISCV) CROSS_COMPILE?=riscv32-unknown-elf- @@ -479,7 +619,8 @@ endif ifeq ($(TARGET),nxp_t1024) # Power PC big endian ARCH_FLAGS=-mhard-float -mcpu=e5500 - CFLAGS+=$(ARCH_FLAGS) -DBIG_ENDIAN_ORDER + CFLAGS+=$(ARCH_FLAGS) + BIG_ENDIAN=1 CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT CFLAGS+=-pipe # use pipes instead of temp files CFLAGS+=-feliminate-unused-debug-types @@ -503,7 +644,8 @@ endif ifeq ($(TARGET),nxp_t2080) # Power PC big endian ARCH_FLAGS=-mhard-float -mcpu=e6500 - CFLAGS+=$(ARCH_FLAGS) -DBIG_ENDIAN_ORDER + CFLAGS+=$(ARCH_FLAGS) + BIG_ENDIAN=1 CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT CFLAGS+=-pipe # use pipes instead of temp files CFLAGS+=-feliminate-unused-debug-types @@ -524,7 +666,8 @@ ifeq ($(TARGET),nxp_p1021) # Power PC big endian ARCH_FLAGS=-m32 -mhard-float -mcpu=e500mc ARCH_FLAGS+=-fno-builtin -ffreestanding -nostartfiles - CFLAGS+=$(ARCH_FLAGS) -DBIG_ENDIAN_ORDER + CFLAGS+=$(ARCH_FLAGS) + BIG_ENDIAN=1 CFLAGS+=-DWOLFBOOT_DUALBOOT CFLAGS+=-pipe # use pipes instead of temp files LDFLAGS+=$(ARCH_FLAGS) @@ -552,7 +695,8 @@ endif ifeq ($(TARGET),ti_hercules) # HALCoGen Source and Include? CORTEX_R5=1 - CFLAGS+=-D"CORTEX_R5" -D"BIG_ENDIAN_ORDER" -D"NVM_FLASH_WRITEONCE" -D"FLASHBUFFER_SIZE=32" + CFLAGS+=-D"CORTEX_R5" -D"NVM_FLASH_WRITEONCE" -D"FLASHBUFFER_SIZE=32" + BIG_ENDIAN=1 STACK_USAGE=0 USE_GCC=0 USE_GCC_HEADLESS=0 @@ -660,10 +804,6 @@ ifeq ($(TARGET),psoc6) endif endif - - -USE_GCC?=1 -USE_GCC_HEADLESS?=1 ifeq ($(USE_GCC),1) ## Toolchain setup CC=$(CROSS_COMPILE)gcc @@ -671,8 +811,8 @@ ifeq ($(USE_GCC),1) AS=$(CROSS_COMPILE)gcc OBJCOPY?=$(CROSS_COMPILE)objcopy SIZE=$(CROSS_COMPILE)size - OUTPUT_FLAG=-o endif +OUTPUT_FLAG?=-o ifeq ($(filter $(TARGET),x86_fsp_qemu kontron_vx3060_s2),$(TARGET)) FSP=1 @@ -861,5 +1001,9 @@ ifeq ($(NXP_CUSTOM_DCD),1) OBJS+=$(NXP_CUSTOM_DCD_OBJS) endif +ifeq ($(BIG_ENDIAN),1) + CFLAGS+=-D"BIG_ENDIAN_ORDER" +endif + CFLAGS+=-DWOLFBOOT_ARCH_$(ARCH) CFLAGS+=-DTARGET_$(TARGET) diff --git a/config/examples/renesas-rx65n.config b/config/examples/renesas-rx65n.config new file mode 100644 index 000000000..64eb33d14 --- /dev/null +++ b/config/examples/renesas-rx65n.config @@ -0,0 +1,56 @@ +ARCH?=RENESAS_RX +TARGET?=rx65n +SIGN?=ECC256 +HASH?=SHA256 +DEBUG?=0 +DEBUG_UART?=0 +VTOR?=1 +NO_ASM?=0 +NO_MPU=1 +EXT_FLASH?=1 +SPI_FLASH?=1 +QSPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=0 +WOLFBOOT_VERSION?=0 +SPMATH?=1 +RAM_CODE?=1 +DUALBANK_SWAP?=0 + +# reserve 1KB for wolfBoot header +# Requires building keytools with "make IMAGE_HEADER_SIZE=1024" +#IMAGE_HEADER_SIZE=1024 + +# Optionally switch to big endian data if MDE is set +#BIG_ENDIAN=1 + +# Flash is 2MB with 32KB sector size +WOLFBOOT_SECTOR_SIZE?=0x8000 + +# wolfBoot is last sector of flash and includes vector tables +WOLFBOOT_ORIGIN=0xFFFF0000 + +# wolfBoot partition size (64KB) +BOOTLOADER_PARTITION_SIZE=0x10000 +# Application Partition Size (960KB) +WOLFBOOT_PARTITION_SIZE?=0xF0000 + +# Location in Flash for Application Partition +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xFFE00000 +# Location in Flash for Update Partition +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0xFFEF0000 + +# Location of temporary sector used during updates +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFE0000 + +# TSIP +PKA?=0 + +# Use optimization level 2 (default is -Os, which causes issues) +#OPTIMIZATION_LEVEL=2 + +# Include debug symbols (even for release build) +#DEBUG_SYMBOLS=1 + +# Location of reset entry point from start of flash +#CFLAGS_EXTRA+=-DBOOT_ENTRY_OFFSET=0x2C diff --git a/config/examples/renesas-rx72n.config b/config/examples/renesas-rx72n.config new file mode 100644 index 000000000..971fedc29 --- /dev/null +++ b/config/examples/renesas-rx72n.config @@ -0,0 +1,56 @@ +ARCH?=RENESAS_RX +TARGET?=rx72n +SIGN?=ECC256 +HASH?=SHA256 +DEBUG?=0 +DEBUG_UART?=1 +VTOR?=1 +NO_ASM?=0 +NO_MPU=1 +EXT_FLASH?=0 +SPI_FLASH?=0 +QSPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +NVM_FLASH_WRITEONCE?=0 +WOLFBOOT_VERSION?=0 +SPMATH?=1 +RAM_CODE?=1 +DUALBANK_SWAP?=0 + +# reserve 1KB for wolfBoot header +# Requires building keytools with "make IMAGE_HEADER_SIZE=1024" +#IMAGE_HEADER_SIZE=1024 + +# Optionally switch to big endian data if MDE is set +#BIG_ENDIAN=1 + +# Flash is 4MB with 32KB sector size +WOLFBOOT_SECTOR_SIZE?=0x8000 + +# wolfBoot is last sector of flash and includes vector tables +WOLFBOOT_ORIGIN=0xFFFF0000 + +# wolfBoot partition size (64KB) +BOOTLOADER_PARTITION_SIZE=0x10000 +# Application Partition Size (1984KB) +WOLFBOOT_PARTITION_SIZE?=0x1F0000 + +# Location in Flash for Application Partition +WOLFBOOT_PARTITION_BOOT_ADDRESS?=0xFFC00000 +# Location in Flash for Update Partition +WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0xFFDF0000 + +# Location of temporary sector used during updates +WOLFBOOT_PARTITION_SWAP_ADDRESS?=0xFFFE0000 + +# TSIP +PKA?=0 + +# Use optimization level 2 (default is -Os, which causes issues) +#OPTIMIZATION_LEVEL=2 + +# Include debug symbols (even for release build) +#DEBUG_SYMBOLS=1 + +# Location of reset entry point from start of flash +#CFLAGS_EXTRA+=-DBOOT_ENTRY_OFFSET=0x2C diff --git a/config/examples/sim-nobackup-nvm-writeonce.config b/config/examples/sim-nobackup-nvm-writeonce.config index 48da7ebfd..aa70af340 100644 --- a/config/examples/sim-nobackup-nvm-writeonce.config +++ b/config/examples/sim-nobackup-nvm-writeonce.config @@ -7,7 +7,7 @@ SPI_FLASH=0 DEBUG=1 SPMATH?=0 DISABLE_BACKUP=1 -NVM_WRITEONCE=1 +NVM_FLASH_WRITEONCE=1 # sizes should be multiple of system page size WOLFBOOT_PARTITION_SIZE=0x40000 diff --git a/docs/Renesas.md b/docs/Renesas.md new file mode 100644 index 000000000..72b41abeb --- /dev/null +++ b/docs/Renesas.md @@ -0,0 +1,172 @@ +# Renesas wolfBoot + +Platforms Supported: +* Renesas RZ (RZN2L) (RSIP) + - [docs/Targets.md#renesas-rzn2l](/docs/Targets.md#renesas-rzn2l) + - [IDE/Renesas/e2studio/RZN2L/Readme.md](/IDE/Renesas/e2studio/RZN2L/Readme.md) + - [IDE/Renesas/e2studio/RZN2L/Readme_wRSIP.md](/IDE/Renesas/e2studio/RZN2L/Readme_wRSIP.md) +* Renesas RA (RA6M4) (SCE) + - [docs/Targets.md#renesas-ra6m4](/docs/Targets.md#renesas-ra6m4) + - [IDE/Renesas/e2studio/RA6M4/Readme.md](/IDE/Renesas/e2studio/RA6M4/Readme.md) + - [IDE/Renesas/e2studio/RA6M4/Readme_withSCE.md](/IDE/Renesas/e2studio/RA6M4/Readme_withSCE.md) +* Renesas RX (RX65N/RX72N) (TSIP) + - [docs/Targets.md#renesas-rx72n](/docs/Targets.md#renesas-rx72n) + - [IDE/Renesas/e2studio/RX72N/Readme.md](/IDE/Renesas/e2studio/RX72N/Readme.md) + - [IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md](/IDE/Renesas/e2studio/RX72N/Readme_withTSIP.md) + +All of the Renesas examples support using e2Studio. +The Renesas RX parts support using wolfBoot Makefile's with the rx-elf-gcc cross-compiler and example .config files. + +### Security Key Management Tool (SKMT) Key Wrapping + +1) Setup a Renesas KeyWrap account and do the PGP key exchange. +https://dlm.renesas.com/keywrap +You will get a public key from Renesas `keywrap-pub.key` that needs imported to PGP/GPG. +Note: You cannot use RSA 4096-bit key, must be RSA-2048 or RSA-3072. + +2) Using "Security Key Management Tool" create 32-byte UFPK (User Factory Programming Key). This can be a random 32-byte value. +Example: Random 32-bytes `B94A2B96 1C755101 74F0C967 ECFC20B3 77C7FB25 6DB627B1 BFFADEE0 5EE98AC4` + +3) Sign and Encrypt the 32-byte binary file with PGP the `sample.key`. Result is `sample.key.gpg`. +Use GPG4Win and the Sign/Encrypt option. Sign with your own GPG key and encrypt with the Renesas public key. + +4) Use https://dlm.renesas.com/keywrap to wrap `sample.key.gpg`. +It will use the Hidden Root Key (HRK) that both Renesas and the RX TSIP have pre-provisioned from Renesas Factory. +Result is `sample.key_enc.key`. Example: `00000001 6CCB9A1C 8AA58883 B1CB02DE 6C37DA60 54FB94E2 06EAE720 4D9CCF4C 6EEB288C` + +### RX TSIP + +1) Build key tools for Renesas + +```sh +# Build keytools for Renesas RX (TSIP) +$ make keytools RENESAS_KEY=2 +``` + +2) wolfBoot public key (create or import existing) + +Instructions below for ECDSA P384 (SECP384R1). +For SECP256R1 replace "ecc384" with "ecc256" and "secp384r1" with "secp256r1". + +Create new signing key: + +```sh +# Create new signing key +$ ./tools/keytools/keygen --ecc384 -g ./pri-ecc384.der +Keytype: ECC384 +Generating key (type: ECC384) +Associated key file: ./pri-ecc384.der +Partition ids mask: ffffffff +Key type : ECC384 +Public key slot: 0 +Done. + +# Export public portion of key as PEM +$ openssl ec -inform der -in ./pri-ecc384.der -pubout -out ./pub-ecc384.pem +``` + +OR + +Import Public Key: + +```sh +# Export public portion of key as DER +$ openssl ec -inform der -in ./pri-ecc384.der -pubout -outform der -out ./pub-ecc384.der + +# Import public key and populate src/keystore.c +$ ./tools/keytools/keygen --ecc384 -i ./pub-ecc384.der +Keytype: ECC384 +Associated key file: ./pub-ecc384.der +Partition ids mask: ffffffff +Key type : ECC384 +Public key slot: 0 +Done. +``` + +3) Create wrapped public key (code files) + +Use the Security Key Management Tool (SKMT) command line tool (CLI) to create a wrapped public key. + +This will use the user encryption key to wrap the public key and output key_data.c / key_data.h files. + +```sh +$ C:\Renesas\SecurityKeyManagementTool\cli\skmt.exe -genkey -ufpk file=./sample.key -wufpk file=./sample.key_enc.key -key file=./pub-ecc384.pem -mcu RX-TSIP -keytype secp384r1-public -output include/key_data.c -filetype csource -keyname enc_pub_key +Output File: include\key_data.h +Output File: include\key_data.c +UFPK: B94A2B961C75510174F0C967ECFC20B377C7FB256DB627B1BFFADEE05EE98AC4 +W-UFPK: 000000016CCB9A1C8AA58883B1CB02DE6C37DA6054FB94E206EAE7204D9CCF4C6EEB288C +IV: 6C296A040EEF5EDD687E8D3D98D146D0 +Encrypted key: 5DD8D7E59E6AC85AE340BBA60AA8F8BE56C4C1FE02340C49EB8F36DA79B8D6640961FE9EAECDD6BADF083C5B6060C1D0309D28EFA25946F431979B9F9D21E77BDC5B1CC7165DE2F4AE51E418746260F518ED0C328BD3020DEC9B774DC00270B0CFBBE3DD738FDF715342CFBF2D461239 +``` + +4) Create wrapped public key (flash file) + +Generate Motorola HEX file to write wrapped key to flash. + +```sh +$ C:\Renesas\SecurityKeyManagementTool\cli\skmt.exe -genkey -ufpk file=./sample.key -wufpk file=./sample.key_enc.key -key file=./pub-ecc384.pem -mcu RX-TSIP -keytype secp384r1-public -output pub-ecc384.srec -filetype "mot" -address FFFF0000 +Output File: Y:\GitHub\wolfboot\pub-ecc384.srec +UFPK: B94A2B961C75510174F0C967ECFC20B377C7FB256DB627B1BFFADEE05EE98AC4 +W-UFPK: 000000016CCB9A1C8AA58883B1CB02DE6C37DA6054FB94E206EAE7204D9CCF4C6EEB288C +IV: 9C13402DF1AF631DC2A10C2424182601 +Encrypted key: C4A0B368552EB921A3AF3427FD7403BBE6CB8EE259D6CC0692AA72D46F7343F5FFE7DA97A1C811B21BF392E3834B67C3CE6F84707CCB8923D4FBB8DA003EF23C1CD785B6F58E5DB161F575F78D646434AC2BFAF207F6FFF6363C800CFF7E7BFF4857452A70C496B675D08DD6924CAB5E +``` + +The generated file is a Motorola HEX (S-Record) formatted image containing the wrapped public key with instructions to use the `0xFFFF0000` address. + +``` +S00E00007075622D65636333737265D5 +S315FFFF000000000000000000006CCB9A1C8AA58883C5 +S315FFFF0010B1CB02DE6C37DA6054FB94E206EAE720E7 +S315FFFF00204D9CCF4C6EEB288C9C13402DF1AF631D7F +S315FFFF0030C2A10C2424182601C4A0B368552EB921EA +S315FFFF0040A3AF3427FD7403BBE6CB8EE259D6CC06AE +S315FFFF005092AA72D46F7343F5FFE7DA97A1C811B27D +S315FFFF00601BF392E3834B67C3CE6F84707CCB8923ED +S315FFFF0070D4FBB8DA003EF23C1CD785B6F58E5DB1F0 +S315FFFF008061F575F78D646434AC2BFAF207F6FFF66C +S315FFFF0090363C800CFF7E7BFF4857452A70C496B6D9 +S311FFFF00A075D08DD6924CAB5ED6FF44C5E3 +S705FFFF0000FC +``` + +The default flash memory address is `0xFFFF0000`, but it can be changed. The following two places must be set: +a) The `user_settings.h` build macro `RENESAS_TSIP_INSTALLEDKEY_ADDR` +b) The linker script `.rot` section (example `hal/rx72n.ld` or `hal/rx65n.ld`). + +5) Edit .config `PKA?=1`. + +6) Rebuild wolfBoot. `make clean && make wolfboot.srec` + +7) Sign application + +Sign application using the created private key above `pri-ecc384.der`: + +```sh +$ ./tools/keytools/sign --ecc384 --sha256 test-app/image.bin pri-ecc384.der 1 +wolfBoot KeyTools (Compiled C version) +wolfBoot version 2010000 +Update type: Firmware +Input image: test-app/image.bin +Selected cipher: ECC384 +Selected hash : SHA256 +Public key: pri-ecc384.der +Output image: test-app/image_v1_signed.bin +Target partition id : 1 +image header size overridden by config value (1024 bytes) +Calculating SHA256 digest... +Signing the digest... +Output image(s) successfully created. +``` + +8) Flash wolfboot.srec, pub-ecc384.srec and signed application binary + +Download files to flash using Renesas flash programmer. + + +#### RX TSIP Benchmarks + +| Algorithm | RX TSIP | Debug | Release (-Os) | Release (-O2) | +| ----------------- | -------- | -------- | ------------- | ------------- | +| ECDSA Verify P384 | 17.26 ms | 1570 ms | 441 ms | 313 ms | +| ECDSA Verify P256 | 2.73 ms | 469 ms | 135 ms | 107 ms | diff --git a/docs/Targets.md b/docs/Targets.md index bbfe6780f..5207cbd77 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -29,6 +29,7 @@ This README describes configuration of supported targets. * [STM32WB55](#stm32wb55) * [TI Hercules TMS570LC435](#ti-hercules-tms570lc435) * [Xilinx Zynq UltraScale](#xilinx-zynq-ultrascale) +* [Renesas RX65N](#renesas-rx65n) * [Renesas RX72N](#renesas-rx72n) * [Renesas RA6M4](#renesas-ra6m4) * [Renesas RZN2L](#renesas-rzn2l) @@ -2025,35 +2026,249 @@ make test-sim-internal-flash-with-update Note: This also works on Mac OS, but `objcopy` does not exist. Install with `brew install binutils` and make using `OBJCOPY=/usr/local/Cellar//binutils/2.41/bin/objcopy make`. +## Renesas RX65N + +Tested on the: +* RX65N-2MB-Starter-Kit-Plus +* RX65N Target Board (RTK5RX65N0C00000BR) (includes onboard E2 Lite emulator) + +Both include an E2 Lite Emulator. + +### Renesas Console + +Console output is supported with `DEBUG_UART=1`. + +RSK+: +This board includes a USB to Serial port that uses SCI8 and PJ1/PJ2. +This is the wolfBoot HAL default for RX65N. + +RX65N target board: + +Can route UART Serial output to PC3 via PMOD1-IO0 at Pin 9. +This requires an external TTL UART to USB adapter. +You will need to set `CFLAGS_EXTRA+="-DDEBUG_UART_SCI=3"` in .config. +In the renesas-rx.c uart_init these port mode and port function select settings are needed: + +```c +/* Configure PC3/PC2 for UART */ +PORT_PMR(0xC) |= ((1 << 2) | (1 << 3)); +/* SCI Function Select = 0xA (UART) */ +MPC_PFS(0xC2) = 0xA; /* PC2-RXD5 */ +MPC_PFS(0xC3) = 0xA; /* PC3-TXD5 */ +``` + +Example Boot Output (with DEBUG_UART=1): + +``` +wolfBoot HAL Init +Boot partition: 0xFFE00000 +Image size 25932 + +| ------------------------------------------------------------------- | +| Renesas RX User Application in BOOT partition started by wolfBoot | +| ------------------------------------------------------------------- | + +wolfBoot HAL Init + +=== Boot Partition[ffe00000] === +Magic: WOLF +Version: 01 +Status: ff (New) +Tail Mgc: ˇˇˇˇ + +=== Update Partition[ffef0000] === +Magic: ˇˇˇˇ +Version: 00 +Status: ff (New) +Tail Mgc: ˇˇˇˇ + +Current Firmware Version: 1 +Hit any key to call wolfBoot_success the firmware. +``` + +### Renesas Flash Layout + +Default Onboard Flash Memory Layout (2MB) (32KB sector): + +| Description | Address | Size | +| ----------------- | ---------- | ------------------- | +| OFSM Option Mem | 0xFE7F5D00 | 0x00000080 (128 B ) | +| Application | 0xFFE00000 | 0x000F0000 (960 KB) | +| Update | 0xFFEF0000 | 0x000F0000 (960 KB) | +| Swap | 0xFFFE0000 | 0x00010000 ( 64 KB) | +| wolfBoot | 0xFFFF0000 | 0x00010000 ( 64 KB) | + + +### Renesas Data Endianess + +To switch RX parts to big endian data use: + +```sh +# Big Endian +rfp-cli -if fine -t e2l -device RX65x -auth id FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -write32 0xFE7F5D00 0xFFFFFFF8 +OR +# Little Endian +rfp-cli -if fine -t e2l -device RX65x -auth id FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -write32 0xFE7F5D00 0xFFFFFFFF +``` + +### Building Renesas RX65N + +Building RX wolfBoot requires the RX-ELF compiler. Please Download and install the Renesas RX GCC toolchain: +https://llvm-gcc-renesas.com/rx-download-toolchains/ + +Default installation path (Linux): `~/toolchains/gcc_8.3.0.202311_rx_elf` +Default installation path (Windows): `C:\ProgramData\GCC for Renesas RX 8.3.0.202305-GNURX-ELF\rx-elf\rx-elf` + +Configuration: +Use `./config/examples/renesas-rx65n.config` as a starting point by copying it to the wolfBoot root as `.config`. + +```sh +cp ./config/examples/renesas-rx65n.config .config +make +``` + +With RX GCC path or or custom cross compiler directly: +`make CROSS_COMPILE="~/toolchains/gcc_8.3.0.202311_rx_elf/bin/rx-elf-"` +OR +`make RX_GCC_PATH="~/toolchains/gcc_8.3.0.202311_rx_elf"` + +TSIP: To enable TSIP use `make PKA=1`. See [docs/Renesas.md](docs/Renesas.md) for details. + +### Flashing Renesas RX65N + +Download the Renesas Flashing Tool: https://www.renesas.com/us/en/software-tool/renesas-flash-programmer-programming-gui +Download the Renesas E2 Lite Linux Driver: https://www.renesas.com/us/en/document/swo/e2-emulator-e2-emulator-lite-linux-driver?r=488806 + +Default Flash ID Code: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + +Flash Using: + +``` +rfp-cli -if fine -t e2l -device RX65x -auto -auth id FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \ + -bin FFFF0000 wolfboot.bin \ + -bin FFE00000 test-app/image_v1_signed.bin \ + -run +``` + +Note: Endianess: if using big endian add `-endian big` + +Note: Linux Install E2 Lite USB Driver: + +```sh +sudo cp 99-renesas-emu.rules /etc/udev/rules.d/ +sudo udevadm control --reload-rules +``` + +### Debugging Renesas RX65N + +Create a new "Renesas Debug" project. Choose the "E2 Lite" emulator and the built `wolfboot.elf`. After project is created open the "Debug Configuration" and change the debugger interface from "JTAG" to "FINE". Run debug and it will stop in the "reset" code in `boot_renesas_start.S`. If using Big Endian change endianess mode in "Debugger -> Debug Tool Settings -> Memory Endian -> Big Endian". + + ## Renesas RX72N -This example for `Renesas RX72N` demonstrates simple secure firmware update by wolfBoot. A sample application v1 is -securely updated to v2. Both versions behave the same except displaying its version of v1 or v2. -They are compiled by e2Studio and running on the target board. +Tested on the RX72N ENVISION KIT (HMI development kit for IoT systems). This includes an onboard E2 Lite emulator. -In this demo, you may download two versions of application binary file by Renesas Flash Programmer. -You can download and execute wolfBoot by e2Studio debugger. Use a USB connection between PC and the -board for the debugger and flash programmer. +The Renesas RX72N is supported either natively with "make" or through e2Studio. If using e2Studio see [Readme.md](../IDE/Renesas/e2studio/RX72N/Readme.md). + +Default UART Serial on SCI2 at P12-RXD2 P13-TXD2. Use USB on CN8 to attach a Virtual USB COM port. This feaure is enabled with `DEBUG_UART=1`. + +Example Boot Output (with DEBUG_UART=1): -Flash Allocation: ``` -+---------------------------+------------------------+-----+ -| B |H| |H| | | -| o |e| Primary |e| Update |Swap | -| o |a| Partition |a| Partition |Sect | -| t |d| |d| | | -+---------------------------+------------------------+-----+ -0xffc00000: wolfBoot -0xffc10000: Primary partition (Header) -0xffc10100: Primary partition (Application image) /* When it uses IMAGE_HEADER_SIZE 256, e.g. ED25519, EC256, EC384 or EC512 */ -0xffc10200: Primary partition (Application image) /* When it uses IMAGE_HEADER_SIZE 512, e.g. RSA2048, RSA3072 */ -0xffdf0000: Update partition (Header) -0xffdf0100: Update partition (Application image) -0xfffd0000: Swap sector +wolfBoot HAL Init +Boot partition: 0xFFC00000 +Image size 27772 + +| ------------------------------------------------------------------- | +| Renesas RX User Application in BOOT partition started by wolfBoot | +| ------------------------------------------------------------------- | + +wolfBoot HAL Init +=== Boot Partition[ffc00000] === +Magic: WOLF +Version: 01 +Status: ff (New) +Tail Mgc: ˇˇˇˇ + +=== Update Partition[ffdf0000] === +Magic: ˇˇˇˇ +Version: 00 +Status: ff (New) +Tail Mgc: ˇˇˇˇ + +Current Firmware Version: 1 +Hit any key to call wolfBoot_success the firmware. ``` -Detailed steps can be found at [Readme.md](../IDE/Renesas/e2studio/RX72N/Readme.md). +Default Onboard Flash Memory Layout (4MB) (32KB sector): + +| Description | Address | Size | +| ----------------- | ---------- | -------------------- | +| OFSM Option Mem | 0xFE7F5D00 | 0x00000080 ( 128 B ) | +| Application | 0xFFC00000 | 0x001F0000 (1984 KB) | +| Update | 0xFFDF0000 | 0x001F0000 (1984 KB) | +| Swap | 0xFFFE0000 | 0x00010000 ( 64 KB) | +| wolfBoot | 0xFFFF0000 | 0x00010000 ( 64 KB) | + +To switch RX parts to big endian data use: + +```sh +# Big Endian +rfp-cli -if fine -t e2l -device RX72x -auth id FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -write32 0xFE7F5D00 0xFFFFFFF8 +OR +# Little Endian +rfp-cli -if fine -t e2l -device RX72x -auth id FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -write32 0xFE7F5D00 0xFFFFFFFF +``` + +### Building Renesas RX72N + +Building RX wolfBoot requires the RX-ELF compiler. Please Download and install the Renesas RX GCC toolchain: +https://llvm-gcc-renesas.com/rx-download-toolchains/ + +Default installation path (Linux): `~/toolchains/gcc_8.3.0.202311_rx_elf` +Default installation path (Windows): `C:\ProgramData\GCC for Renesas RX 8.3.0.202305-GNURX-ELF\rx-elf\rx-elf` + +Configuration: +Use `./config/examples/renesas-rx72n.config` as a starting point by copying it to the wolfBoot root as `.config`. + +```sh +cp ./config/examples/renesas-rx72n.config .config +make +``` + +With RX GCC path or or custom cross compiler directly: +`make CROSS_COMPILE="~/toolchains/gcc_8.3.0.202311_rx_elf/bin/rx-elf-"` +OR +`make RX_GCC_PATH="~/toolchains/gcc_8.3.0.202311_rx_elf"` + + +TSIP: To enable TSIP use `make PKA=1`. See [docs/Renesas.md](docs/Renesas.md) for details. + +### Flashing Renesas RX72N + +Download the Renesas Flashing Tool: https://www.renesas.com/us/en/software-tool/renesas-flash-programmer-programming-gui +Download the Renesas E2 Lite Linux Driver: https://www.renesas.com/us/en/document/swo/e2-emulator-e2-emulator-lite-linux-driver?r=488806 + +Default Flash ID Code: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + +Flash Using: + +``` +rfp-cli -if fine -t e2l -device RX72x -auto -auth id FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF \ + -bin FFFF0000 wolfboot.bin \ + -bin FFC00000 test-app/image_v1_signed.bin \ + -run +``` + +Note: Endianess: if using big endian add `-endian big` + +Note: Linux Install E2 Lite USB Driver: + +```sh +sudo cp 99-renesas-emu.rules /etc/udev/rules.d/ +sudo udevadm control --reload-rules +``` ## Renesas RA6M4 diff --git a/docs/flash_partitions.md b/docs/flash_partitions.md index bd776655e..4ea510679 100644 --- a/docs/flash_partitions.md +++ b/docs/flash_partitions.md @@ -2,10 +2,10 @@ ## Flash memory partitions -To integrate wolfBoot you need to partition the flash into +To integrate wolfBoot you need to partition the flash into separate areas (partitions), taking into account the geometry of the flash memory. -Images boundaries **must** be aligned to physical sectors, because the +Images boundaries **must** be aligned to physical sectors, because the bootloader erases all the flash sectors before storing a new firmware image, and swaps the content of the two partitions, one sector at a time. @@ -22,7 +22,7 @@ The flash memory of the target is partitioned into the following areas: - Secondary slot (UPDATE partition) starting at address `WOLFBOOT_PARTITION_UPDATE_ADDRESS` - both partitions share the same size, defined as `WOLFBOOT_PARTITION_SIZE` - Swapping space (SWAP partition) starting at address `WOLFBOOT_PARTITION_SWAP_ADDRESS` - - the swap space size is defined as `WOLFBOOT_SECTOR_SIZE` and must be as big as the + - the swap space size is defined as `WOLFBOOT_SECTOR_SIZE` and must be as big as the largest sector used in either BOOT/UPDATE partitions. A proper partitioning configuration must be set up for the specific use, by setting @@ -36,9 +36,9 @@ as part of the firmware image. ### BOOT partition -This is the only partition from where it is possible to chain-load and execute a +This is the only partition from where it is possible to chain-load and execute a firmware image. The firmware image must be linked so that its entry-point is at address -`WOLFBOOT_PARTITION_BOOT_ADDRESS + 256`. +`WOLFBOOT_PARTITION_BOOT_ADDRESS + 256`. ### UPDATE partition @@ -50,16 +50,39 @@ the firmware in the boot partition at the next reboot. ## Partition status and sector flags Partitions are used to store firmware images currently in use (BOOT) or ready to swap in (UPDATE). -In order to track the status of the firmware in each partition, a 1-Byte state field is stored at the end of +In order to track the status of the firmware in each partition, a 1-Byte state field is stored at the end of each partition space. This byte is initialized when the partition is erased and accessed for the first time. Possible states are: - - `STATE_NEW` (0xFF): The image was never staged for boot, or triggered for an update. If an image is present, no flags are active. - - `STATE_UPDATING` (0x70): Only valid in the UPDATE partition. The image is marked for update and should replace the current image in BOOT. - - `STATE_TESTING` (0x10): Only valid in the BOOT partition. The image has been just updated, and never completed its boot. If present after reboot, it means that the updated image failed to boot, despite being correctly verified. This particular situation triggers a rollback. - - `STATE_SUCCESS` (0x00): Only valid in the BOOT partition. The image stored in BOOT has been successfully staged at least once, and the update is now complete. + - `IMG_STATE_NEW` (0xFF): The image was never staged for boot, or triggered for an update. If an image is present, no flags are active. + - `IMG_STATE_UPDATING` (0x70): Only valid in the UPDATE partition. The image is marked for update and should replace the current image in BOOT. + - `IMG_STATE_TESTING` (0x10): Only valid in the BOOT partition. The image has been just updated, and never completed its boot. If present after reboot, it means that the updated image failed to boot, despite being correctly verified. This particular situation triggers a rollback. + - `IMG_STATE_SUCCESS` (0x00): Only valid in the BOOT partition. The image stored in BOOT has been successfully staged at least once, and the update is now complete. + +Starting from the State byte and growing backwards, the bootloader keeps track of the state of each sector, using 4-bits per sector at the end of the UPDATE partition. Whenever an update is initiated, the firmware is transferred from UPDATE to BOOT one sector at a time, and storing a backup of the original firmware from BOOT to UPDATE. Each flash access operation correspond to a different value of the flags for the sector in the sector flags area, so that if the operation is interrupted, it can be resumed upon reboot. + +End of flash layout: + * 4-bits flag (sector 1) + * 4-bits flag (sector 0) + * 1-byte partition state + * 4-byte trailer "BOOT" + +If the `FLAGS_HOME` build option is used then all flags are placed at the end of the boot partition: + + ``` + / -12 /-8 /-4 / END + |Sn| ... |S2|S1|S0|PU| MAGIC |X|X|X|PB| MAGIC | + ^--sectors --^ ^--update ^---boot partition + flags partition flag + flag +``` + +You can use the `CUSTOM_PARTITION_TRAILER` option to implement your own functions for: `get_trailer_at`, `set_trailer_at` and `set_partition_magic`. + +To enable: +1) Add the `CUSTOM_PARTITION_TRAILER` build option to your `.config`: `CFLAGS_EXTRA+=--DCUSTOM_PARTITION_TRAILER` +2) Add your own .c file using `OBJS_EXTRA`. For example for your own `src/custom_trailer.c` add this to your `.config`: `OBJS_EXTRA=src/custom_trailer.o`. -Starting from the State byte and growing backwards, the bootloader keeps track of the state of each sector, using 4 bits per sector at the end of the UPDATE partition. Whenever an update is initiated, the firmware is transferred from UPDATE to BOOT one sector at a time, and storing a backup of the original firmware from BOOT to UPDATE. Each flash access operation correspond to a different value of the flags for the sector in the sector flags area, so that if the operation is interrupted, it can be resumed upon reboot. ## Overview of the content of the FLASH partitions diff --git a/hal/renesas-ra.c b/hal/renesas-ra.c index 1f6b00e6c..4e90ff867 100644 --- a/hal/renesas-ra.c +++ b/hal/renesas-ra.c @@ -1,6 +1,6 @@ /* renesas-ra.c * - * Stubs for custom HAL implementation. Defines the + * Stubs for custom HAL implementation. Defines the * functions used by wolfboot for a specific target. * * Copyright (C) 2023 wolfSSL Inc. @@ -64,12 +64,12 @@ void hal_init(void) #endif err = R_FLASH_HP_Close(&g_flash0_ctrl); err = R_FLASH_HP_Open(&g_flash0_ctrl, &g_flash0_cfg); - + if(err != FSP_ERR_ALREADY_OPEN && err != FSP_SUCCESS){ printf("ERROR: %d\n", err); hal_panic(); } - + /* 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){ @@ -120,7 +120,7 @@ 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); - + if(R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t)save, addr, MINIMUM_BLOCK) != FSP_SUCCESS) return -1; @@ -128,7 +128,7 @@ static int blockWrite(const uint8_t *data, uint32_t addr, uint32_t len) return 0; } -#define IS_FLASH(addr) (addr) >= 0xffc00000 ? 1 : 0 +#define IS_FLASH_ADDR(addr) (addr) >= 0xffc00000 ? 1 : 0 int hal_flash_write(uint32_t addr, const uint8_t *data, int int_len) { @@ -138,21 +138,21 @@ int hal_flash_write(uint32_t addr, const uint8_t *data, int int_len) uint8_t address_tmp = (uint8_t)(addr - ALIGN_FLASH(addr)); if(addr != ALIGN_FLASH(addr)) { - + memset(save, 0, sizeof(save)); - - save_len = (addr - ALIGN_FLASH(addr)) < len ? + + save_len = (addr - ALIGN_FLASH(addr)) < len ? (addr - ALIGN_FLASH(addr)) : len; - - memcpy(save, (const void *)ALIGN_FLASH(addr), + + memcpy(save, (const void *)ALIGN_FLASH(addr), MINIMUM_BLOCK * sizeof(uint32_t)); memcpy(save + (address_tmp), data, save_len); addr = ALIGN_FLASH(addr); - + if((err=R_FLASH_HP_Erase(&g_flash0_ctrl, addr, 1)) != FSP_SUCCESS) return -1; - - if((err=R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t)save, addr, + + if((err=R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t)save, addr, MINIMUM_BLOCK * sizeof(uint32_t))) != FSP_SUCCESS) return -1; @@ -180,12 +180,12 @@ int hal_flash_write(uint32_t addr, const uint8_t *data, int int_len) 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, + if(R_FLASH_HP_Write(&g_flash0_ctrl, (uint32_t)save, addr, MINIMUM_BLOCK) != FSP_SUCCESS) goto error; } return 0; - + error: return -1; } @@ -194,7 +194,7 @@ int hal_flash_erase(uint32_t address, int int_len) { uint32_t len = (uint32_t)int_len; #ifdef WOLFBOOT_DUALBANK - uint32_t block_size = (address <= 0x80000 && address >= 0x10000) + 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); @@ -234,9 +234,9 @@ void hal_flash_lock(void) FLASH_START_ADDR, FLASH_END_ADDR) != FSP_SUCCESS) hal_panic(); - + #ifdef WOLFBOOT_DUALBANK - if(R_FLASH_HP_AccessWindowSet(&g_flash0_ctrl, + if(R_FLASH_HP_AccessWindowSet(&g_flash0_ctrl, FLASH1_START_ADDR, FLASH1_END_ADDR) != FSP_SUCCESS) hal_panic(); @@ -250,10 +250,10 @@ void RAMFUNCTION hal_flash_dualbank_swap(void) flash_cmd_t cmd = FLASH_CMD_SWAPFLAG_TOGGLE; hal_flash_unlock(); - + if(R_FLASH_HP_Control(cmd, NULL) != FSP_SUCCESS) hal_panic(); - + hal_flash_lock(); } diff --git a/hal/renesas-rx.c b/hal/renesas-rx.c index 6c1783e40..a31b250bc 100644 --- a/hal/renesas-rx.c +++ b/hal/renesas-rx.c @@ -1,7 +1,7 @@ -/* remesas-rx.c +/* renesas-rx.c * - * Stubs for custom HAL implementation. Defines the - * functions used by wolfboot for a specific target. + * Stubs for custom HAL implementation. Defines the + * functions used by wolfBoot for a specific target. * * Copyright (C) 2022 wolfSSL Inc. * @@ -22,100 +22,413 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA */ +/* HAL for Renesas RX boards */ +/* Tested with: + * - RX65N Target Board + * + * - RX72N Envision Kit (HMI IoT) + * R5F572NNHDFB 144-pin LFQFP (PLQP0144KA-B) + * 4MB Flash, 1MB RAM, 32KB Data Flash, 240MHz, TSIP + * QSPI: Macronix MX25L3233FM2I-08G: 4MB QSPI Serial Flash + */ + + #include #include #include #include #include "image.h" #include "hal.h" -#include "r_flash_rx.h" +#include "printf.h" +#include "renesas-rx.h" +#include "printf.h" -#if defined(WOLFBOOT_RENESAS_TSIP) && \ - !defined(WOLFBOOT_RENESAS_APP) -# include "wolfssl/wolfcrypt/wc_port.h" -# include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" -# include "wolfssl/wolfcrypt/port/Renesas/renesas_sync.h" -# include "key_data.h" -# include "wolfssl/wolfcrypt/port/Renesas/renesas_tsip_types.h" -TsipUserCtx pkInfo; +#if defined(WOLFBOOT_RENESAS_TSIP) && \ + !defined(WOLFBOOT_RENESAS_APP) + #include "wolfssl/wolfcrypt/settings.h" + #include "wolfssl/wolfcrypt/types.h" + #include "wolfssl/wolfcrypt/wc_port.h" + #include "wolfssl/wolfcrypt/port/Renesas/renesas-tsip-crypt.h" + #include "wolfssl/wolfcrypt/port/Renesas/renesas_sync.h" + #include "wolfssl/wolfcrypt/port/Renesas/renesas_tsip_types.h" + #include "wolfssl/wolfcrypt/port/Renesas/renesas_cmn.h" + static TsipUserCtx pkInfo; + + #include "key_data.h" #endif -static inline void hal_panic(void) +/* forward declaration */ +int hal_flash_init(void); +#ifdef TEST_FLASH +static int test_flash(void); +#endif + +static void hal_panic(void) { while(1) ; } +void hal_delay_us(uint32_t us) +{ + uint32_t delay; + for (delay = 0; delay < (us * (SYS_CLK / 1000000)); delay++) { + RX_NOP(); + } +} + +#ifdef DEBUG_UART + +#ifndef DEBUG_UART_SCI + #ifdef TARGET_rx72n + /* SCI2: TXD2/PC13, RXD2/PC12 */ + #define DEBUG_UART_SCI 2 + #else + /* SCI8: TXD8/PJ2, RXD8/PJ1 */ + #define DEBUG_UART_SCI 8 + #endif +#endif +#ifndef DEBUG_BAUD_RATE +#define DEBUG_BAUD_RATE 115200 +#endif + +void uart_init(void) +{ + /* Release SCI module stop (clear bit) */ + PROTECT_OFF(); +#if DEBUG_UART_SCI >= 0 && DEBUG_UART_SCI <= 7 + /* bit 31=SCI0, 30=SCI1, 29=SCI2, 28=SCI3, 27=SCI4, 26=SCI5, 25=SCI6, 24=SCI7 */ + SYS_MSTPCRB &= ~(1 << (31-DEBUG_UART_SCI)); +#elif DEBUG_UART_SCI >= 8 && DEBUG_UART_SCI <= 11 + /* bit 27=SCI8, 26=SCI9, 25=SCI10, 24=SCI11 */ + SYS_MSTPCRC &= ~(1 << (27-(DEBUG_UART_SCI-8))); +#else + #error SCI module stop not known +#endif + PROTECT_ON(); + + /* Disable RX/TX */ + SCI_SCR(DEBUG_UART_SCI) = 0; + +#ifdef TARGET_rx72n + /* Configure P13/P12 for UART */ + PORT_PMR(0x1) |= ((1 << 2) | (1 << 3)); +#else + /* Configure PJ1/PJ2 for UART */ + PORT_PMR(0x12) |= ((1 << 1) | (1 << 2)); +#endif + + /* Disable MPC Write Protect for PFS */ + MPC_PWPR &= ~MPC_PWPR_B0WI; + MPC_PWPR |= MPC_PWPR_PFSWE; + + /* Enable TXD/RXD */ + /* SCI Function Select = 0xA (UART) */ +#ifdef TARGET_rx72n + MPC_PFS(0xA) = 0xA; /* P12-RXD2 */ + MPC_PFS(0xB) = 0xA; /* P13-TXD2 */ +#else + MPC_PFS(0xF1) = 0xA; /* PJ1-RXD8 */ + MPC_PFS(0xF2) = 0xA; /* PJ2-TXD8 */ +#endif + + /* Enable MPC Write Protect for PFS */ + MPC_PWPR &= ~(MPC_PWPR_PFSWE | MPC_PWPR_B0WI); + MPC_PWPR |= MPC_PWPR_PFSWE; + + /* baud rate table: */ + /* divisor, abcs, bgdm, cks + * 8, 1, 1, 0 + * 16, 0, 1, 0 + * 32, 0, 0, 0 + * 64, 0, 1, 1 + * 128, 0, 0, 1 + * 256, 0, 1, 2 + * 512, 0, 0, 2 (using this one) + * 1024, 0, 1, 3 + * 2048, 0, 0, 3 + */ + + /* 8-bit, 1-stop, no parity, cks=2 (/512), bgdm=0, abcs=0 */ + SCI_BRR(DEBUG_UART_SCI) = (PCLKB / (512 * DEBUG_BAUD_RATE)) - 1; + SCI_SEMR(DEBUG_UART_SCI) &= ~SCI_SEMR_ABCS; + SCI_SEMR(DEBUG_UART_SCI) &= ~SCI_SEMR_BGDM; + SCI_SMR(DEBUG_UART_SCI) = SCI_SMR_CKS(2); + SCI_SCMR(DEBUG_UART_SCI) |= SCI_SCMR_CHR1; + /* Enable TX/RX */ + SCI_SCR(DEBUG_UART_SCI) = (SCI_SCR_RE | SCI_SCR_TE); +} +void uart_write(const char* buf, unsigned int sz) +{ + uint32_t pos = 0; + while (sz-- > 0) { + char c = buf[pos++]; + if (c == '\n') { /* handle CRLF */ + while ((SCI_SSR(DEBUG_UART_SCI) & SCI_SSR_TEND) == 0); + SCI_TDR(DEBUG_UART_SCI) = '\r'; + } + while ((SCI_SSR(DEBUG_UART_SCI) & SCI_SSR_TEND) == 0); + SCI_TDR(DEBUG_UART_SCI) = c; + } +} +#endif /* DEBUG_UART */ + +/* LOCO clock is used out of reset */ +/* This function will switch to using on-chip HOCO through PLL */ +#define CFG_CKSEL 1 /* 0=LOCO, 1=HOCO, 2=Main, 3=Sub, 4=PLL */ +#define CFG_HCO_FRQ (16000000) +#define CFD_PLL_DIV (0) +#define CFG_PLL_MUL (SYS_CLK / (CFG_HCO_FRQ / 2)) + +void hal_clk_init(void) +{ + uint32_t reg, i; + uint16_t stc; + uint8_t cksel = CFG_CKSEL; + + PROTECT_OFF(); /* write protect off */ + + /* ---- High Speed OSC (HOCO) ---- */ +#if CFG_CKSEL == 1 + if (SYS_HOCOCR & SYS_HOCOCR_HCSTP) { + /* Turn on power to HOCO */ + SYS_HOCOPCR &= ~SYS_HOCOPCR_HOCOPCNT; + /* Stop HOCO */ + SYS_HOCOCR |= SYS_HOCOCR_HCSTP; + /* Wait for HOCO to stop */ + while (SYS_OSCOVFSR & SYS_OSCOVFSR_HCOVF) { RX_NOP(); } + + /* Set 16MHz -> CFG_HCO_FRQ */ + SYS_HOCOCR2 = SYS_HOCOCR2_HCFRQ(0); + + /* Enable HOCO */ + SYS_HOCOCR &= ~SYS_HOCOCR_HCSTP; + reg = SYS_HOCOCR; /* dummy ready (required) */ + } + /* Wait for HOCO oscisllator stabilization */ + while ((SYS_OSCOVFSR & SYS_OSCOVFSR_HCOVF) == 0) { RX_NOP(); } +#else + if (SYS_HOCOCR & SYS_HOCOCR_HCSTP) { + /* Turn off power to HOCO */ + SYS_HOCOPCR |= SYS_HOCOPCR_HOCOPCNT; + } +#endif + + /* ---- Main-Clock ---- */ +#if CFG_CKSEL == 2 + /* MOFXIN=0 (not controlled), MODRV2=0 (24MHz), MOSEL=0 (resonator) */ + SYS_MOFCR = 0; + + /* OSC stabilization time (9.98 ms * (264 kHZ) + 16)/32 = 82.83) */ + SYS_MOSCWTCR = SYS_MOSCWTCR_MSTS(83); + + /* Enable Main OSC */ + SYS_MOSCCR = 0; + reg = SYS_MOSCCR; /* dummy read (required) */ + while (SYS_MOSCCR != 0) { RX_NOP(); } +#else + /* Stop main clock */ + SYS_MOSCCR = SYS_MOSCCR_MOSTP; + reg = SYS_MOSCCR; /* dummy read (required) */ + while ((SYS_OSCOVFSR & SYS_OSCOVFSR_MOOVF) != 0) { RX_NOP(); } +#endif + + /* ---- RTC Clock ---- */ + if ((SYS_RSTSR1 & SYS_RSTSR1_CWSF) == 0) { /* cold start */ + /* Stop the RTC sub-clock */ + RTC_RCR4 &= ~RTC_RCR4_RCKSEL; /* select sub-clock */ + for (i=0; i<4; i++) { + reg = RTC_RCR4; /* dummy read (required) */ + } + if ((RTC_RCR4 & RTC_RCR4_RCKSEL) != 0) { RX_NOP(); } + RTC_RCR3 &= ~RTC_RCR3_RTCEN; /* stop osc */ + for (i=0; i<4; i++) { + reg = RTC_RCR3; /* dummy read (required) */ + } + if ((RTC_RCR3 & RTC_RCR3_RTCEN) != 0) { RX_NOP(); } + } + + /* ---- Sub-Clock OSC ---- */ +#if CFG_CKSEL == 3 + /* TODO: Add support for running from sub-clock */ +#else + /* Stop the sub-clock */ + SYS_SOSCCR = SYS_SOSCCR_SOSTP; + reg = SYS_SOSCCR; /* dummy read (required) */ + while ((SYS_OSCOVFSR & SYS_OSCOVFSR_SOOVF) != 0) { RX_NOP(); } +#endif + +#if CFG_CKSEL == 1 || CFG_CKSEL == 2 + /* ---- PLL ---- */ + /* Frequency Multiplication Factor */ + #if CFG_CKSEL == 2 + #define PLL_SRCSEL /* main */ + #else + #define PLL_SRCSEL SYS_PLLCR_PLLSRCSEL /* HOCO */ + #endif + /* convert multiplier to STC value */ + #define PLL_MUL_STC ((CFG_PLL_MUL * 2) - 1) + reg = ( + SYS_PLLCR_PLIDIV(CFD_PLL_DIV) | /* no div */ + PLL_SRCSEL | /* clock source (0=main, 1=HOCO) */ + SYS_PLLCR_STC(PLL_MUL_STC) /* multiplier */ + ); + + SYS_PLLCR = reg; + SYS_PLLCR2 = 0; /* enable PLL */ + while ((SYS_OSCOVFSR & SYS_OSCOVFSR_PLOVF) == 0) { RX_NOP(); } + cksel = 4; /* PLL */ +#endif + + /* ---- FLASH ---- */ + /* Flash Wait Cycles */ +#ifdef TARGET_rx72n + /* Flash Wait Cycles */ + FLASH_MEMWAIT = FLASH_MEMWAIT_MEMWAIT(1); /* (1=<120MHz) */ + reg = FLASH_MEMWAIT; +#else + FLASH_ROMWT = FLASH_ROMWT_ROMWT(2); /* (1=50-100MHz, 2= >100MHz) */ + reg = FLASH_ROMWT; +#endif + + /* ---- Clock Select ---- */ +#if SYS_CLK >= 240000000 + reg = ( + SYS_SCKCR_ICK(1) | /* System Clock (ICK)=1: 1/2 = 240MHz */ + SYS_SCKCR_BCK(2) | /* External Bus Clock (BCK)=2: 1/4 = 120MHz */ + SYS_SCKCR_FCK(3) | /* Flash-IF Clock FCK=3: 1/8 = 60MHz */ + SYS_SCKCR_PCKA(2) | /* Peripheral Module Clock A (PCKA)=2: 1/4 = 120MHz */ + SYS_SCKCR_PCKB(3) | /* Peripheral Module Clock D (PCKB)=3: 1/8 = 60MHz */ + SYS_SCKCR_PCKC(3) | /* Peripheral Module Clock C (PCKC)=3: 1/8 = 60MHz */ + SYS_SCKCR_PCKD(3) | /* Peripheral Module Clock D (PCKD)=3: 1/8 = 60MHz */ + SYS_SCKCR_PSTOP1 | /* BCLK Pin Output (PSTOP1): 0=Disabled */ + SYS_SCKCR_PSTOP0 /* SDCLK Pin Output (PSTOP0): 0=Disabled */ + ); +#else + reg = ( + SYS_SCKCR_ICK(1) | /* System Clock (ICK)=1: 1/2 = 120MHz */ + SYS_SCKCR_BCK(1) | /* External Bus Clock (BCK)=1: 1/2 = 120MHz */ + SYS_SCKCR_FCK(2) | /* Flash-IF Clock FCK=2: 1/4 = 60MHz */ + SYS_SCKCR_PCKA(1) | /* Peripheral Module Clock A (PCKA)=1: 1/2 = 120MHz */ + SYS_SCKCR_PCKB(2) | /* Peripheral Module Clock D (PCKB)=2: 1/4 = 60MHz */ + SYS_SCKCR_PCKC(2) | /* Peripheral Module Clock C (PCKC)=2: 1/4 = 60MHz */ + SYS_SCKCR_PCKD(2) | /* Peripheral Module Clock D (PCKD)=2: 1/4 = 60MHz */ + SYS_SCKCR_PSTOP1 | /* BCLK Pin Output (PSTOP1): 0=Disabled */ + SYS_SCKCR_PSTOP0 /* SDCLK Pin Output (PSTOP0): 0=Disabled */ + ); +#endif + SYS_SCKCR = reg; + reg = SYS_SCKCR; /* dummy read (required) */ + +#if CFG_CKSEL == 2 /* USB only on main clock */ + /* USB Clock=4: 1/5 = 48MHz */ + SYS_SCKCR2 |= SYS_SCKCR2_UCK(4); + reg = SYS_SCKCR2; /* dummy read (required) */ +#endif + + /* Clock Source */ + SYS_SCKCR3 = SYS_SCKCR3_CKSEL(cksel); + reg = SYS_SCKCR3; /* dummy read (required) */ + + /* ---- Low Speed OSC (LOCO) ---- */ +#if CFG_CKSEL != 0 + /* Disable on-chip Low Speed Oscillator */ + SYS_LOCOCR |= SYS_LOCOCR_LCSTP; + hal_delay_us(25); +#endif + + PROTECT_ON(); /* write protect on */ +} + void hal_init(void) { -#if defined(WOLFBOOT_RENESAS_TSIP) &&\ +#if defined(WOLFBOOT_RENESAS_TSIP) && \ !defined(WOLFBOOT_RENESAS_APP) int err; uint32_t key_type = 0; int tsip_key_type = -1; - /* retrive installed pubkey data from flash */ - struct rsa2048_pub *encrypted_user_key_data = - (struct rsa2048_pub*)keystore_get_buffer(0); + struct enc_pub_key *encrypted_user_key_data; #endif - if(R_FLASH_Open() != FLASH_SUCCESS) - hal_panic(); + hal_clk_init(); + +#ifdef DEBUG_UART + uart_init(); + uart_write("wolfBoot HAL Init\n", 18); +#endif + + hal_flash_init(); + +#ifdef TEST_FLASH + test_flash(); +#endif #if defined(WOLFBOOT_RENESAS_TSIP) && \ !defined(WOLFBOOT_RENESAS_APP) err = wolfCrypt_Init(); if (err != 0) { - printf("ERROR: wolfCrypt_Init %d\n", err); + wolfBoot_printf("ERROR: wolfCrypt_Init %d\n", err); hal_panic(); } - key_type = keystore_get_key_type(0); - switch(key_type){ + /* retrive installed pubkey data from flash */ + encrypted_user_key_data = (struct enc_pub_key*)keystore_get_buffer(0); + key_type = keystore_get_key_type(0); + switch (key_type) { case AUTH_KEY_RSA2048: tsip_key_type = TSIP_RSA2048; break; + case AUTH_KEY_RSA3072: + tsip_key_type = TSIP_RSA3072; + break; case AUTH_KEY_RSA4096: tsip_key_type = TSIP_RSA4096; break; - case AUTH_KEY_ED448: + case AUTH_KEY_ECC256: + tsip_key_type = TSIP_ECCP256; + break; case AUTH_KEY_ECC384: + tsip_key_type = TSIP_ECCP384; + break; case AUTH_KEY_ECC521: case AUTH_KEY_ED25519: - case AUTH_KEY_ECC256: - case AUTH_KEY_RSA3072: + case AUTH_KEY_ED448: default: tsip_key_type = -1; break; } - if (tsip_key_type == -1) { - printf("key type (%d) not supported\n", key_type); + wolfBoot_printf("key type (%d) not supported\n", key_type); hal_panic(); } - /* inform user key */ - tsip_inform_user_keys_ex((byte*)&encrypted_user_key_data->wufpk, - (byte*)&encrypted_user_key_data->initial_vector, - (byte*)&encrypted_user_key_data->encrypted_user_key, - 0/* dummy */); - /* TSIP specific RSA public key */ + + /* Load encrypted UFPK (User Factory Programming Key) */ + tsip_inform_user_keys_ex( + (byte*)&encrypted_user_key_data->wufpk, + (byte*)&encrypted_user_key_data->initial_vector, + (byte*)&encrypted_user_key_data->encrypted_user_key, + 0/* dummy */ + ); + + /* Load a wrapped public key into TSIP */ if (tsip_use_PublicKey_buffer_crypt(&pkInfo, (const char*)&encrypted_user_key_data->encrypted_user_key, - RSA2048_PUB_SIZE, - tsip_key_type) != 0) { - printf("ERROR tsip_use_PublicKey_buffer\n"); - hal_panic(); + sizeof(encrypted_user_key_data->encrypted_user_key), + tsip_key_type) != 0) { + wolfBoot_printf("ERROR tsip_use_PublicKey_buffer\n"); + hal_panic(); } + /* Init Crypt Callback */ - pkInfo.sing_hash_type = sha256_mac; + pkInfo.sign_hash_type = sha256_mac; /* TSIP does not support SHA2-384/512 */ pkInfo.keyflgs_crypt.bits.message_type = 1; err = wc_CryptoCb_CryptInitRenesasCmn(NULL, &pkInfo); if (err < 0) { - printf("ERROR: wc_CryptoCb_CryptInitRenesasCmn %d\n", err); + wolfBoot_printf("ERROR: wc_CryptoCb_CryptInitRenesasCmn %d\n", err); hal_panic(); } -#endif - +#endif /* TSIP */ } void hal_prepare_boot(void) @@ -123,116 +436,147 @@ void hal_prepare_boot(void) } -#define MIN_PROG (0x8000) -#define ALIGN_FLASH(a) ((a) / MIN_PROG * MIN_PROG) -static uint8_t save[MIN_PROG]; +int hal_flash_init(void) +{ + /* Flash Write Enable */ + FLASH_FWEPROR = FLASH_FWEPROR_FLWE; + + /* Disable FCU interrupts */ + FLASH_FAEINT &= ~( + FLASH_FAEINT_DFAEIE | + FLASH_FAEINT_CMDLKIE | + FLASH_FAEINT_CFAEIE); + + /* Set the flash clock speed */ + FLASH_FPCKAR = (FLASH_FPCKAR_KEY | + FLASH_FPCKAR_PCKA(FCLK / 1000000UL)); -int blockWrite(const uint8_t *data, uint32_t addr, int len) + return 0; +} + +/* write up to 256 bytes at a time */ +int RAMFUNCTION hal_flash_write(uint32_t addr, const uint8_t *data, int len) { - for(; len; len-=MIN_PROG, data+=MIN_PROG, addr+=MIN_PROG) { - memcpy(save, data, MIN_PROG); /* for the case "data" ls a flash address */ - if(R_FLASH_Write((uint32_t)save, addr, MIN_PROG) != FLASH_SUCCESS) - return -1; + int ret, i; + const uint16_t* data16 = (const uint16_t*)data; + + while (len > 0) { + FLASH_FSADDR = addr; + + FLASH_FACI_CMD8 = FLASH_FACI_CMD_PROGRAM; + FLASH_FACI_CMD8 = FLASH_FACI_CMD_PROGRAM_CODE_LENGTH; + + /* write 64 * 2 bytes */ + for (i=0; i < FLASH_FACI_CMD_PROGRAM_CODE_LENGTH; i++) { + FLASH_FACI_CMD16 = *data16++; + + /* wait for data buffer not full */ + while (FLASH_FSTATR & FLASH_FSTATR_DBFULL); + } + + FLASH_FACI_CMD8 = FLASH_FACI_CMD_FINAL; + + /* Wait for FCU operation to complete */ + while ((FLASH_FSTATR & FLASH_FSTATR_FRDY) == 0); + + len -= (FLASH_FACI_CMD_PROGRAM_CODE_LENGTH * + FLASH_FACI_CMD_PROGRAM_DATA_LENGTH); + addr += (FLASH_FACI_CMD_PROGRAM_CODE_LENGTH * + FLASH_FACI_CMD_PROGRAM_DATA_LENGTH); } return 0; } -#define IS_FLASH(addr) (addr) >= 0xffc00000 ? 1 : 0 - -int hal_flash_write(uint32_t addr, const uint8_t *data, int len) +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) { - uint32_t save_len = 0; + int block_size; - if(addr != ALIGN_FLASH(addr)) { - save_len = (addr - ALIGN_FLASH(addr)) < len ? (addr - ALIGN_FLASH(addr)) : len; - memcpy(save, (const void *)ALIGN_FLASH(addr), MIN_PROG); - memcpy(save + (addr - ALIGN_FLASH(addr)), data, save_len); - addr = ALIGN_FLASH(addr); - if(R_FLASH_Erase((flash_block_address_t)addr, 1) != FLASH_SUCCESS) - return -1; - if(R_FLASH_Write((uint32_t)save, addr, MIN_PROG) != FLASH_SUCCESS) - return -1; - len -= save_len; - data += save_len; - addr += MIN_PROG; + /* verify this is a flash address */ + if (!IS_FLASH_ADDR(address)) { + return -1; } - 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); + /* make sure len is multiple of block sizze */ + block_size = FLASH_BLOCK_SIZE(address); + if (len % block_size != 0) { + return -1; } - if(len > 0) { - memcpy(save, (const void *)addr, MIN_PROG); - memcpy(save, data, len); - if(R_FLASH_Erase((flash_block_address_t)addr, 1) != FLASH_SUCCESS) - return -1; - if(R_FLASH_Write((uint32_t)save, addr, MIN_PROG) != FLASH_SUCCESS) - goto error; + /* erase block(s) */ + while (len > 0) { + FLASH_FSADDR = address; + + FLASH_FACI_CMD8 = FLASH_FACI_CMD_BLOCK_ERASE; + FLASH_FACI_CMD8 = FLASH_FACI_CMD_FINAL; + + /* Wait for FCU operation to complete */ + while ((FLASH_FSTATR & FLASH_FSTATR_FRDY) == 0); + + address += block_size; + len -= block_size; } return 0; -error: - return -1; } - -int hal_flash_erase(uint32_t address, int len) +static int RAMFUNCTION hal_flash_write_faw(uint32_t faw) { - int block_size = address >= 0xffff0000 ? - FLASH_CF_SMALL_BLOCK_SIZE : FLASH_CF_MEDIUM_BLOCK_SIZE; + volatile uint8_t* cmdArea = (volatile uint8_t*)FLASH_FACI_CMD_AREA; + +#ifndef BIG_ENDIAN_ORDER + faw = __builtin_bswap32(faw); +#endif + + hal_flash_unlock(); + + /* Flash Access Window Write */ + FLASH_FSADDR = 0x00FF5D60; /* FAW Register Start */ + FLASH_FACI_CMD8 = FLASH_FACI_CMD_CONFIGURATION_SET; + FLASH_FACI_CMD8 = FLASH_FACI_CMD_CONFIGURATION_LENGTH; /* len=8 */ + FLASH_FACI_CMD16 = 0xFFFF; + FLASH_FACI_CMD16 = 0xFFFF; + FLASH_FACI_CMD16 = (uint16_t)(faw & 0xFFFF); + FLASH_FACI_CMD16 = (uint16_t)((faw >> 16) & 0xFFFF); + FLASH_FACI_CMD16 = 0xFFFF; + FLASH_FACI_CMD16 = 0xFFFF; + FLASH_FACI_CMD16 = 0xFFFF; + FLASH_FACI_CMD16 = 0xFFFF; + FLASH_FACI_CMD8 = FLASH_FACI_CMD_FINAL; + + /* Wait for FCU operation to complete */ + while ((FLASH_FSTATR & FLASH_FSTATR_FRDY) == 0); + + hal_flash_lock(); - if(len % block_size != 0) - return -1; - for( ; len; address+=block_size, len-=block_size) { - if(R_FLASH_Erase((flash_block_address_t)address, 1) - != FLASH_SUCCESS) - return -1; - } return 0; } +void RAMFUNCTION hal_flash_dualbank_swap(void) +{ + uint32_t faw = FLASH_FAWMON; + faw ^= FLASH_FAWMON_BTFLG; /* flip BTFLG */ + hal_flash_write_faw(faw); +} + void RAMFUNCTION hal_flash_unlock(void) { - flash_access_window_config_t info; + /* Enable code flash entry for program/erase */ + FLASH_FENTRYR = (FLASH_FENTRYR_KEY | + FLASH_FENTRYR_DATA_READ | FLASH_FENTRYR_CODE_PR); + + /* Make sure any pending FACI commands are cancelled */ + FLASH_FCMDR = FLASH_FACI_CMD_FORCED_STOP; + while ((FLASH_FSTATR & FLASH_FSTATR_FRDY) == 0); - info.start_addr = (uint32_t) FLASH_CF_BLOCK_132; - info.end_addr = (uint32_t) FLASH_CF_BLOCK_0; - R_BSP_InterruptsDisable(); - if(R_FLASH_Control(FLASH_CMD_ACCESSWINDOW_SET, (void *)&info) - != FLASH_SUCCESS) - hal_panic(); - R_BSP_InterruptsEnable(); return; } - void RAMFUNCTION hal_flash_lock(void) { - flash_access_window_config_t info; - info.start_addr = (uint32_t) FLASH_CF_BLOCK_END; - info.end_addr = (uint32_t) FLASH_CF_BLOCK_END; - R_BSP_InterruptsDisable(); - if(R_FLASH_Control(FLASH_CMD_ACCESSWINDOW_SET, (void *)&info) - != FLASH_SUCCESS) - hal_panic(); - R_BSP_InterruptsEnable(); + /* Disable code flash entry */ + FLASH_FENTRYR = (FLASH_FENTRYR_KEY | + FLASH_FENTRYR_CODE_READ | FLASH_FENTRYR_DATA_READ); return; } - -void RAMFUNCTION hal_flash_dualbank_swap(void) -{ - flash_cmd_t cmd = FLASH_CMD_SWAPFLAG_TOGGLE; - printf("FLASH_CMD_SWAPFLAG_TOGGLE=%d\n", FLASH_CMD_SWAPFLAG_TOGGLE); - hal_flash_unlock(); - if(R_FLASH_Control(cmd, NULL) != FLASH_SUCCESS) - hal_panic(); - hal_flash_lock(); - -} - void* hal_get_primary_address(void) { return (void*)WOLFBOOT_PARTITION_BOOT_ADDRESS; @@ -242,3 +586,48 @@ void* hal_get_update_address(void) { return (void*)WOLFBOOT_PARTITION_UPDATE_ADDRESS; } + +#ifdef TEST_FLASH + +#ifndef TEST_ADDRESS +#define TEST_ADDRESS (0xFFFC0000) /* 3,840 KB offset in 4MB flash */ +#endif + +/* #define TEST_FLASH_READONLY */ + +static uint32_t pageData[WOLFBOOT_SECTOR_SIZE/sizeof(uint32_t)]; /* force 32-bit alignment */ + +static int test_flash(void) +{ + int ret; + uint32_t i; + uint8_t* pagePtr = (uint8_t*)TEST_ADDRESS; + +#ifndef TEST_FLASH_READONLY + /* Erase sector */ + hal_flash_unlock(); + ret = hal_flash_erase(TEST_ADDRESS, sizeof(pageData)); + hal_flash_lock(); + wolfBoot_printf("Erase Sector: Ret %d\n", ret); + + /* Write Pages */ + for (i=0; i 120MHz) */ +#else + #define FLASH_SIZE 0x200000UL /* 2MB */ + + #define FLASH_ROMWT (*(volatile uint8_t *)(FLASH_BASE + 0x1C)) + #define FLASH_ROMWT_ROMWT(n) ((n) << 0) /* 0=no wait, 1=one wait cycle, 2=two wait cycles */ +#endif + +#define FLASH_BOOT_BLOCK_START (0xFFFF0000UL) +#define FLASH_BLOCK_SIZE_SMALL (8192) +#define FLASH_BLOCK_SIZE_MEDIUM (32768) + +#define FLASH_BLOCK_SIZE(addr) \ + (((addr) >= FLASH_BOOT_BLOCK_START) ? \ + FLASH_BLOCK_SIZE_SMALL : FLASH_BLOCK_SIZE_MEDIUM) + +#define FLASH_ADDR (0xFFFFFFFFUL - FLASH_SIZE + 1) +#define IS_FLASH_ADDR(addr) ((addr) >= FLASH_ADDR ? 1 : 0) + +/* FCAI Commands (RX72N RM Table 62.11) */ +#define FLASH_FACI_CMD_PROGRAM 0xE8 +#define FLASH_FACI_CMD_PROGRAM_CODE_LENGTH 64 +#define FLASH_FACI_CMD_PROGRAM_DATA_LENGTH 2 +#define FLASH_FACI_CMD_BLOCK_ERASE 0x20 +#define FLASH_FACI_CMD_PROGRAM_ERASE_SUSPEND 0xB0 +#define FLASH_FACI_CMD_STATUS_CLEAR 0x50 +#define FLASH_FACI_CMD_FORCED_STOP 0xB3 +#define FLASH_FACI_CMD_BLANK_CHECK 0x71 +#define FLASH_FACI_CMD_CONFIGURATION_SET 0x40 +#define FLASH_FACI_CMD_CONFIGURATION_LENGTH 8 +#define FLASH_FACI_CMD_LOCK_BIT_PROGRAM 0x77 +#define FLASH_FACI_CMD_LOCK_BIT_READ 0x71 +#define FLASH_FACI_CMD_FINAL 0xD0 + + +/* Serial Communication Interface */ +#define SCI_BASE(n) (SYSTEM_BASE + 0xA000 + ((n) * 0x20)) +#define SCI_SMR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x00)) +#define SCI_SMR_CKS(clk) (clk & 0x3) /* 0=PCLK, 1=PCLK/4, 2=PCLK/16, 3=PCLK/64 */ +#define SCI_SMR_STOP (1 << 3) /* 0=1 stop bit */ +#define SCI_SMR_CHR (1 << 6) /* 0=8-bit */ +#define SCI_SMR_CM (1 << 7) /* Mode: 0=Async/Simple I2C, 1=Sync/simple SPI */ +#define SCI_BRR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x01)) /* Bit Rate Reg < 255 */ +#define SCI_SCR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x02)) +#define SCI_SCR_RE (1 << 4) +#define SCI_SCR_TE (1 << 5) +#define SCI_TDR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x03)) /* Transmit Data Register */ +#define SCI_SSR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x04)) +#define SCI_SSR_TEND (1 << 2) /* Transmit End Flag */ +#define SCI_SSR_RDRF (1 << 6) /* Receive Data Full Flag */ +#define SCI_SSR_TDRE (1 << 7) /* Transmit Data Empty Flag */ +#define SCI_RDR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x05)) /* Receive Data Register */ +#define SCI_SCMR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x06)) +#define SCI_SCMR_CHR1 (1 << 4) /* 1=8-bit */ +#define SCI_SCMR_SDIR (1 << 3) /* Transmitted/Received Data Transfer Direction */ +#define SCI_SCMR_SINV (1 << 2) /* Transmitted/Received Data Invert */ + +#define SCI_SEMR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x08)) +#define SCI_SEMR_ASC0 (1 << 0) /* Asynchronous Mode Clock Source Select 0=external clock input */ +#define SCI_SEMR_BRME (1 << 2) /* Bit Rate Modulation Enable */ +#define SCI_SEMR_ABCS (1 << 4) /* Asynchronous Mode Base Clock Select */ +#define SCI_SEMR_NFEN (1 << 5) /* Digital Noise Filter Function Enable */ +#define SCI_SEMR_BGDM (1 << 6) /* Baud Rate Generator Double-Speed Mode Select */ +#define SCI_SEMR_RXDESEL (1 << 7) /* Asynchronous Start Bit Edge Detection Select */ + +/* SPI */ +#define SCI_SPMR(n) (*(volatile uint8_t *)(SCI_BASE(n) + 0x0D)) +#define SCI_SPMR_SSE (1 << 0) /* 0=SSn# pin func disabled, 1=enabled */ +#define SCI_SPMR_MSS (1 << 2) /* Master slave select: 0=master, 1=slave */ +#define SCI_SPMR_CKPOL (1 << 6) /* Clock Polarity: 0=not inverted, 1=inverted */ +#define SCI_SPMR_CKPH (1 << 7) /* Clock Phase: 0=not delayed, 1=delayed */ + +/* MPC (Multi-Function Pin Controller) */ +#define MPC_PWPR (*(volatile uint8_t *)(SYSTEM_BASE + 0xC11F)) +#define MPC_PWPR_B0WI (1 << 7) +#define MPC_PWPR_PFSWE (1 << 6) + +#ifdef TARGET_rx72n +#define MPC_PFS(n) (*(volatile uint8_t *)(SYSTEM_BASE + 0xC140 + (n))) +#else +#define MPC_PFS(n) (*(volatile uint8_t *)(SYSTEM_BASE + 0xC0E0 + (n))) +#endif + +/* Ports */ +#define PORT_BASE (SYSTEM_BASE + 0xC000) +#define PORT_PDR(n) (*(volatile uint8_t*)(PORT_BASE + 0x00 + (n))) /* Port Direction Register: 0=Input, 1=Output */ +#define PORT_PODR(n) (*(volatile uint8_t*)(PORT_BASE + 0x20 + (n))) /* Port Output Data Register: 0=Low, 1=High */ +#define PORT_PIDR(n) (*(volatile uint8_t*)(PORT_BASE + 0x40 + (n))) /* Port Input Register: 0=Low input, 1=Hight Input */ +#define PORT_PMR(n) (*(volatile uint8_t*)(PORT_BASE + 0x60 + (n))) /* Port Mode Register: 0=General, 1=Peripheral */ +#define PORT_ODR(n) (*(volatile uint8_t*)(PORT_BASE + 0x80 + (n))) /* Open-Drain Control Register: 0=CMOS, 1=NMOS open-drain */ +#define PORT_PCR(n) (*(volatile uint8_t*)(PORT_BASE + 0xC0 + (n))) /* Pull-Up Resistor Control Register: 0=Disable pull-up, 1=Enable input pull-up */ +#define PORT_DSCR(n) (*(volatile uint8_t*)(PORT_BASE + 0xE0 + (n))) /* Drive Capacity Control Register: 0=Normal, 1=High-drive output */ + +/* RSPI */ +#define RSPI_BASE(n) (SYSTEM_BASE + 0x50100 + ((n) * 0x40)) /* n=0-2 (RSPI0,RSPI1,RSPI2) */ +#define RSPI_SPCR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x00)) /* Control */ +#define RSPI_SPCR_SPMS (1 << 0) /* RSPI Mode Select 0=SPI operation (4-wire method) */ +#define RSPI_SPCR_TXMD (1 << 1) +#define RSPI_SPCR_MSTR (1 << 3) /* 0=Slave, 1=Master */ +#define RSPI_SPCR_SPE (1 << 6) /* 1=Enable RSPI */ +#define RSPI_SPPCR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x02)) /* Pin Control */ +#define RSPI_SPPCR_MOIFV (1 << 4) /* MOSI Idle Fixed Value */ +#define RSPI_SPPCR_MOIDE (1 << 5) /* MOSI Idle Value Fixing Enable */ +#define RSPI_SPSR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x03)) /* Status */ +#define RSPI_SPSR_OVRF (1 << 0) /* Overrun Error Flag */ +#define RSPI_SPSR_IDLNF (1 << 1) /* Idle Flag */ +#define RSPI_SPSR_MODF (1 << 2) /* Mode Fault Error Flag */ +#define RSPI_SPSR_PERF (1 << 3) /* Parity Error Flag */ +#define RSPI_SPSR_UDRF (1 << 4) /* Underrun Error Flag */ +#define RSPI_SPSR_SPTEF (1 << 5) /* Transmit Buffer Empty Flag */ +#define RSPI_SPSR_SPRF (1 << 7) /* Receive Buffer Full Flag */ +#define RSPI_SPSR8(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x04)) /* Data */ +#define RSPI_SPSR16(n) (*(volatile uint16_t *)(RSPI_BASE(n) + 0x04)) /* Data */ +#define RSPI_SPSR32(n) (*(volatile uint32_t *)(RSPI_BASE(n) + 0x04)) /* Data */ +#define RSPI_SPSCR(n) (*(volatile uint32_t *)(RSPI_BASE(n) + 0x08)) /* Sequence Control */ +#define RSPI_SPSCR_SPSLN(s) ((s) & 0x7) /* Sequence Length Specification: 0=seq len 1 */ +#define RSPI_SPBR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0A)) /* Bit Rate = PCLKA / (2 x (n + 1) X 2^n): 1=30 Mbps, 2=20Mpbs, 3=15Mbps, 4=12Mbps, 5=10Mbps */ +#define RSPI_SPDCR(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0B)) /* Data Control */ +#define RSPI_SPDCR_SPFC(f) ((f) & 0x3) /* Number of Frames Specification: 0=1 frame, 1=2 frames */ +#define RSPI_SPDCR_SPRDTD (1 << 4) /* Receive/Transmit Data Select */ +#define RSPI_SPDCR_SPLW (1 << 5) /* Longword Access/ Word Access Specification */ +#define RSPI_SPDCR_SPBYT (1 << 6) /* Byte Access Specification */ +#define RSPI_SPCKD(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0C)) /* Clock Delay */ +#define RSPI_SPCKD_SCKDL(d) ((d) & 0x7) /* RSPCK Delay Setting: 0=1 RSPCK, 1=2 RSPCK */ +#define RSPI_SSLND(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0D)) /* Slave Select Negation Delay */ +#define RSPI_SSLND_SLNDL(d) ((d) & 0x7) /* RSPCK Delay Setting: 0=1 RSPCK, 1=2 RSPCK */ +#define RSPI_SPND(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0D)) /* Next-Access Delay */ +#define RSPI_SPND_SPNDL(d) ((d) & 0x7) /* Next-Access Delay Setting: 0=1RSPCK+2PCLK, 1=2RSPCK+2PCLK */ +#define RSPI_SPCR2(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x0F)) /* Control 2 */ +#define RSPI_SPCR2_SPPE (1 << 0) /* Parity Enable */ +#define RSPI_SPCR2_SPOE (1 << 1) /* Parity Mode */ +#define RSPI_SPCMD(n, m) (*(volatile uint16_t *)(RSPI_BASE(n) + 0x10 + (((m) & 0x7)*2))) /* Command Register m */ +#define RSPI_SPCMD_CPHA (1 << 0) /* Phase: 0=Data sampling on odd edge, data variation on even edge */ +#define RSPI_SPCMD_CPOL (1 << 1) /* Polarity: 0=RSPCK is low when idle, 1=High when idle */ +#define RSPI_SPCMD_BRDV(d) (((d) & 0x3) << 2) /* Bit Rate Division : 0=none,1=div2,2=div4,3=div8 */ +#define RSPI_SPCMD_SSLA(s) (((s) & 0x7) << 4) /* Signal Assert 0=SSL0, 1=SSL1 */ +#define RSPI_SPCMD_SSLKP (1 << 7) /* Signal Level Keeping: 0=Deassert on transfer complete, 1=Keep asserted */ +#define RSPI_SPCMD_SPB(l) (((l) & 0xF) << 8) /* Data Length: 7=8bits, 15=16=bits, 1=24bits, 3=32bits */ +#define RSPI_SPCMD_LSBF (1 << 12) /* LSB First: 0=MSB First, 1=LSB First */ +#define RSPI_SPCMD_SPNDEN (1 << 13) /* Next-Access Delay Enable */ +#define RSPI_SPCMD_SLNDEN (1 << 14) /* SSL Negation Delay Setting Enable */ +#define RSPI_SPCMD_SCKDEN (1 << 15) /* RSPCK Delay Setting Enable */ +#define RSPI_SPDCR2(n) (*(volatile uint8_t *)(RSPI_BASE(n) + 0x20)) /* Data Control 2 */ +#define RSPI_SPDCR2_BYSW (1 << 0) /* Byte Swap: 0=Byte swapping of SPDR data disabled, 1=Byte swapping of SPDR data enabled */ + +/* QSPI */ +#define QSPI_BASE (SYSTEM_BASE + 0x9E00) +#define QSPI_SPCR (*(volatile uint8_t *)(QSPI_BASE + 0x00)) /* QSPI Control Register */ +#define QSPI_SPCR_MSTR (1 << 3) /* 0=Slave, 1=Master */ +#define QSPI_SPCR_SPE (1 << 6) /* 1=Enable RSPI */ +#define QSPI_SSLP (*(volatile uint8_t *)(QSPI_BASE + 0x01)) /* QSPI Slave Select Polarity */ +#define QSPI_SSLP_SSLP (1 << 0) /* 0=active low (default), 1=active high */ +#define QSPI_SPPCR (*(volatile uint8_t *)(QSPI_BASE + 0x02)) /* Pin Control */ +#define QSPI_SPPCR_IO2FV (1 << 1) /* Single-/Dual-SPI Mode QIO2 */ +#define QSPI_SPPCR_IO3FV (1 << 2) /* Single-/Dual-SPI Mode QIO3 */ +#define QSPI_SPPCR_MOIFV (1 << 4) /* MOSI Idle Fixed Value */ +#define QSPI_SPPCR_MOIDE (1 << 5) /* MOSI Idle Value Fixing Enable */ +#define QSPI_SPSR (*(volatile uint8_t *)(QSPI_BASE + 0x03)) /* Status */ +#define QSPI_SPSR_SPSSLF (1 << 4) /* QSSL Negation Flag */ +#define QSPI_SPSR_SPTEF (1 << 5) /* Transmit Buffer Empty Flag */ +#define QSPI_SPSR_TREND (1 << 6) /* Transmit End Flag */ +#define QSPI_SPSR_SPRFF (1 << 7) /* Receive Buffer Full Flag */ +#define QSPI_SPDR8 (*(volatile uint8_t *)(QSPI_BASE + 0x04)) /* Data */ +#define QSPI_SPDR16 (*(volatile uint16_t *)(QSPI_BASE + 0x04)) /* Data */ +#define QSPI_SPDR32 (*(volatile uint32_t *)(QSPI_BASE + 0x04)) /* Data */ +#define QSPI_SPSCR (*(volatile uint8_t *)(QSPI_BASE + 0x08)) /* Sequence Control */ +#define QSPI_SPSCR_SPSC(s) ((s) & 0x3) /* Number of SPCMDn register to be referenced (n = 0 to 3) */ +#define QSPI_SPSSR (*(volatile uint8_t *)(QSPI_BASE + 0x09)) /* Sequence Status */ +#define QSPI_SPSSR_MASK (0x3) /* Sequence Status: 0=SPCMD0, 1=SPCMD1, 2=SPCMD2, 3=SPCMD3 */ +#define QSPI_SPBR (*(volatile uint8_t *)(QSPI_BASE + 0x0A)) /* Bit Rate = f(PCLK) / (2 x m x 2^n): 1=30 Mbps, 2=15Mpbs, 3=10Mbps, 4=7.5Mbps, 5=6Mbps */ +#define QSPI_SPDCR (*(volatile uint8_t *)(QSPI_BASE + 0x0B)) /* Data Control */ +#define QSPI_SPDCR_TXDMY (1 << 7) /* Dummy Data Transmission Enable */ +#define QSPI_SPCKD (*(volatile uint8_t *)(QSPI_BASE + 0x0C)) /* Clock Delay */ +#define QSPI_SPCKD_SCKDL(d) ((d) & 0x7) /* Clock Delay Setting: 0=1.5, 1=2.5, 3=3.5 QSPCLK */ +#define QSPI_SSLND (*(volatile uint8_t *)(QSPI_BASE + 0x0D)) /* Slave Select Negation Delay */ +#define QSPI_SSLND_SLNDL(d) ((d) & 0x7) /* QSSL Neg Delay Setting: 0=1, 1=2 QSPCLK */ +#define QSPI_SPND (*(volatile uint8_t *)(QSPI_BASE + 0x0D)) /* Next-Access Delay */ +#define QSPI_SPND_SPNDL(d) ((d) & 0x7) /* Next-Access Delay Setting: 0=1, 1=2 QSPCLK */ +#define QSPI_SPCMD(n) (*(volatile uint16_t *)(QSPI_BASE + 0x10 + (((n) & 0x3) * 2))) /* Command Register */ +#define QSPI_SPCMD_CPHA (1 << 0) /* Phase: 0=Data sampling on odd edge, data variation on even edge */ +#define QSPI_SPCMD_CPOL (1 << 1) /* Polarity: 0=QSPCLK is low when idle, 1=High when idle */ +#define QSPI_SPCMD_BRDV_MASK (0x3 << 2) +#define QSPI_SPCMD_BRDV(d) (((d) & 0x3) << 2) /* Bit Rate Division : 0=none,1=div2,2=div4,3=div8 */ +#define QSPI_SPCMD_SPRW (1 << 4) /* SPI Read/Write Access: 0=Write operation (QIO1 and QIO0/QIO3 to QIO0: Output), 1=Read operation (QIO1 and QIO0/QIO3 to QIO0: Input) */ +#define QSPI_SPCMD_SPREAD QSPI_SPCMD_SPRW +#define QSPI_SPCMD_SPWRITE 0 +#define QSPI_SPCMD_SPIMOD(n) (((n) & 0x3) << 5) /* SPI Operating Mode: 0=Single SPI, 1=Dual SPI, 2=Quad SPI */ +#define QSPI_SPCMD_SSLKP (1 << 7) /* Signal Level Keeping: 0=Deassert on transfer complete, 1=Keep asserted */ +#define QSPI_SPCMD_SPB_MASK (0xF << 8) +#define QSPI_SPCMD_SPB(l) (((l) & 0xF) << 8) /* Data Length: 0=1 byte, 1=2 bytes, 2=4 bytes */ +#define QSPI_SPCMD_LSBF (1 << 12) /* LSB First: 0=MSB First, 1=LSB First */ +#define QSPI_SPCMD_SPNDEN (1 << 13) /* Next-Access Delay Enable */ +#define QSPI_SPCMD_SLNDEN (1 << 14) /* SSL Negation Delay Setting Enable */ +#define QSPI_SPCMD_SCKDEN (1 << 15) /* QSPCLK Delay Setting Enable */ +#define QSPI_SPBFCR (*(volatile uint8_t *)(QSPI_BASE + 0x18)) /* Buffer Control */ +#define QSPI_SPBFCR_RXTRG(n) ((n) & 0x7) /* Receive Buffer Data Trigger Num */ +#define QSPI_SPBFCR_TXTRG(n) (((n) & 0x7) << 3) /* Transmit Buffer Data Trigger Num */ +#define QSPI_SPBFCR_RXRST (1 << 6) /* Receive Buffer Data Reset */ +#define QSPI_SPBFCR_TXRST (1 << 7) /* Transmit Buffer Data Reset */ +#define QSPI_SPBDCR (*(volatile uint16_t *)(QSPI_BASE + 0x1A)) /* Buffer Data Count Set */ +#define QSPI_SPBDCR_RXBC (QSPI_SPBDCR & 0x3F) +#define QSPI_SPBDCR_TXBC ((QSPI_SPBDCR >> 8) & 0x3F) +#define QSPI_SPBMUL(n) (*(volatile uint32_t *)(QSPI_BASE + 0x1C + (((n) & 0x3) * 4))) /* Transfer Data Length Multiplier Setting */ + +#define QSPI_FIFO_SIZE 32 /* bytes */ + + +#endif /* !_WOLFBOOT_RENESAS_RX_H_ */ diff --git a/hal/rx65n.c b/hal/rx65n.c new file mode 100644 index 000000000..4ecd8311c --- /dev/null +++ b/hal/rx65n.c @@ -0,0 +1,23 @@ +/* rx65n.c + * + * Copyright (C) 2024 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 + */ + +/* See hal/renesas-rx.c for HAL. + * Differences adjusted with TARGET_rx65n macro. */ diff --git a/hal/rx65n.ld b/hal/rx65n.ld new file mode 100644 index 000000000..74b6599ec --- /dev/null +++ b/hal/rx65n.ld @@ -0,0 +1,195 @@ +OUTPUT_ARCH(rx) +ENTRY(_PowerON_Reset) + +MEMORY +{ + /* Do not use 0x0 RAM base, as it will fail NULL checks */ + RAM : ORIGIN = 0x1000, LENGTH = 262144 - 0x1000 + RAM2 : ORIGIN = 0x00800000, LENGTH = 393216 + ROM : ORIGIN = @WOLFBOOT_ORIGIN@ /* 0xFFE00000 */, LENGTH = @BOOTLOADER_PARTITION_SIZE@ /* 2097152 */ + OFS : ORIGIN = 0xFE7F5D00, LENGTH = 128 +} + +SECTIONS +{ + .exvectors 0xFFFFFF80: + { + KEEP(*(.exvectors)) + } = 0x7F + . = ALIGN(4); + + .fvectors 0xFFFFFFFC: + { + KEEP(*(.fvectors)) + } = 0x4 + + .rot 0xFFFF0000 : + { + /* Reserved space for Wrapped Public Key (See docs/Renesas.md) */ + KEEP(*(.rot)) + } = 0x2000 /* 8KB (min sector size) */ + + .rvectors ORIGIN(ROM) : + { + _rvectors_start = .; + KEEP(*(.rvectors)) + _rvectors_end = .; + } > ROM + + .text : + { + _start_text = .; + __start_text = .; + *(.text) + *(.text.*) + *(P) + etext = .; + } > ROM + + .init : + { + KEEP(*(.init)) + __preinit_array_start = .; + KEEP(*(.preinit_array)) + __preinit_array_end = .; + __init_array_start = (. + 3) & ~ 3; + KEEP(*(.init_array)) + KEEP(*(SORT(.init_array.*))) + __init_array_end = .; + __fini_array_start = .; + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + __fini_array_end = .; + } > ROM + + .fini : + { + KEEP(*(.fini)) + } > ROM + + .got : + { + *(.got) + *(.got.plt) + } > ROM + + .rodata : + { + *(.rodata) + *(.rodata.*) + *(C_1) + *(C_2) + *(C) + _erodata = .; + } > ROM + + gcc_exceptions_table : + { + KEEP (*(.gcc_except_table)) + *(.gcc_except_table.*) + } > ROM + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > ROM + + .eh_frame : + { + *(.eh_frame) + } > ROM + + .jcr : + { + *(.jcr) + } > ROM + + .tors : + { + __CTOR_LIST__ = .; + . = ALIGN(2); + ___ctors = .; + *(.ctors) + ___ctors_end = .; + __CTOR_END__ = .; + __DTOR_LIST__ = .; + ___dtors = .; + *(.dtors) + ___dtors_end = .; + __DTOR_END__ = .; + . = ALIGN(2); + _mdata = .; + } > ROM + + .data : AT(_mdata) + { + _data = .; + . = ALIGN(4); + KEEP(*(.ramcode)) + *(.data) + *(.data.*) + *(D) + *(D_1) + *(D_2) + _edata = .; + } > RAM + + .bss : + { + _bss = .; + *(.dynbss) + *(.bss) + *(.bss.**) + *(COMMON) + *(B) + *(B_1) + *(B_2) + _ebss = .; + . = ALIGN(128); + _end = .; + } > RAM + + .ofs1 0xFE7F5D00: AT(0xFE7F5D00) + { + KEEP(*(.ofs1)) + } > OFS + .ofs2 0xFE7F5D10: AT(0xFE7F5D10) + { + KEEP(*(.ofs2)) + } > OFS + .ofs3 0xFE7F5D20: AT(0xFE7F5D20) + { + KEEP(*(.ofs3)) + } > OFS + .ofs4 0xFE7F5D40: AT(0xFE7F5D40) + { + KEEP(*(.ofs4)) + } > OFS + .ofs5 0xFE7F5D48: AT(0xFE7F5D48) + { + KEEP(*(.ofs5)) + } > OFS + .ofs6 0xFE7F5D50: AT(0xFE7F5D50) + { + KEEP(*(.ofs6)) + } > OFS + .ofs7 0xFE7F5D64: AT(0xFE7F5D64) + { + KEEP(*(.ofs7)) + } > OFS + .ofs8 0xFE7F5D70: AT(0xFE7F5D70) + { + KEEP(*(.ofs8)) + } > OFS +} + + +/* reserve 16KB user stack */ +PROVIDE(_ustack = ORIGIN(RAM) + LENGTH(RAM) - 0x4000 ); +/* reserve 4KB interrupt stack */ +PROVIDE(_istack = ORIGIN(RAM) + LENGTH(RAM) - 0x4000 - 0x1000 ); + +_wolfboot_partition_boot_address = @WOLFBOOT_PARTITION_BOOT_ADDRESS@; +_wolfboot_partition_size = @WOLFBOOT_PARTITION_SIZE@; +_wolfboot_partition_update_address = @WOLFBOOT_PARTITION_UPDATE_ADDRESS@; +_wolfboot_partition_swap_address = @WOLFBOOT_PARTITION_SWAP_ADDRESS@; diff --git a/hal/rx72n.c b/hal/rx72n.c new file mode 100644 index 000000000..be0689f41 --- /dev/null +++ b/hal/rx72n.c @@ -0,0 +1,23 @@ +/* rx72n.c + * + * Copyright (C) 2024 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 + */ + +/* See hal/renesas-rx.c for HAL. + * Differences adjusted with TARGET_rx72n macro. */ diff --git a/hal/rx72n.ld b/hal/rx72n.ld new file mode 100644 index 000000000..6e632c01a --- /dev/null +++ b/hal/rx72n.ld @@ -0,0 +1,194 @@ +OUTPUT_ARCH(rx) +ENTRY(_PowerON_Reset) + +MEMORY +{ + RAM : ORIGIN = 0x0, LENGTH = 524288 + RAM2 : ORIGIN = 0x00800000, LENGTH = 393216 + ROM : ORIGIN = @WOLFBOOT_ORIGIN@ /* 0xFFC00000 */, LENGTH = @BOOTLOADER_PARTITION_SIZE@ /* 4194304 */ + OFS : ORIGIN = 0xFE7F5D00, LENGTH = 128 +} + +SECTIONS +{ + .exvectors 0xFFFFFF80: + { + KEEP(*(.exvectors)) + } = 0x7F + . = ALIGN(4); + + .fvectors 0xFFFFFFFC: + { + KEEP(*(.fvectors)) + } = 0x4 + + .rot 0xFFFF0000 : + { + /* Reserved space for Wrapped Public Key (See docs/Renesas.md) */ + KEEP(*(.rot)) + } = 0x2000 /* 8KB (min sector size) */ + + .rvectors ORIGIN(ROM) : + { + _rvectors_start = .; + KEEP(*(.rvectors)) + _rvectors_end = .; + } > ROM + + .text : + { + _start_text = .; + __start_text = .; + *(.text) + *(.text.*) + *(P) + etext = .; + } > ROM + + .init : + { + KEEP(*(.init)) + __preinit_array_start = .; + KEEP(*(.preinit_array)) + __preinit_array_end = .; + __init_array_start = (. + 3) & ~ 3; + KEEP(*(.init_array)) + KEEP(*(SORT(.init_array.*))) + __init_array_end = .; + __fini_array_start = .; + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + __fini_array_end = .; + } > ROM + + .fini : + { + KEEP(*(.fini)) + } > ROM + + .got : + { + *(.got) + *(.got.plt) + } > ROM + + .rodata : + { + *(.rodata) + *(.rodata.*) + *(C_1) + *(C_2) + *(C) + _erodata = .; + } > ROM + + gcc_exceptions_table : + { + KEEP (*(.gcc_except_table)) + *(.gcc_except_table.*) + } > ROM + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > ROM + + .eh_frame : + { + *(.eh_frame) + } > ROM + + .jcr : + { + *(.jcr) + } > ROM + + .tors : + { + __CTOR_LIST__ = .; + . = ALIGN(2); + ___ctors = .; + *(.ctors) + ___ctors_end = .; + __CTOR_END__ = .; + __DTOR_LIST__ = .; + ___dtors = .; + *(.dtors) + ___dtors_end = .; + __DTOR_END__ = .; + . = ALIGN(2); + _mdata = .; + } > ROM + + .data : AT(_mdata) + { + _data = .; + . = ALIGN(4); + KEEP(*(.ramcode)) + *(.data) + *(.data.*) + *(D) + *(D_1) + *(D_2) + _edata = .; + } > RAM + + .bss : + { + _bss = .; + *(.dynbss) + *(.bss) + *(.bss.**) + *(COMMON) + *(B) + *(B_1) + *(B_2) + _ebss = .; + . = ALIGN(128); + _end = .; + } > RAM + + .ofs1 0xFE7F5D00: AT(0xFE7F5D00) + { + KEEP(*(.ofs1)) + } > OFS + .ofs2 0xFE7F5D10: AT(0xFE7F5D10) + { + KEEP(*(.ofs2)) + } > OFS + .ofs3 0xFE7F5D20: AT(0xFE7F5D20) + { + KEEP(*(.ofs3)) + } > OFS + .ofs4 0xFE7F5D40: AT(0xFE7F5D40) + { + KEEP(*(.ofs4)) + } > OFS + .ofs5 0xFE7F5D48: AT(0xFE7F5D48) + { + KEEP(*(.ofs5)) + } > OFS + .ofs6 0xFE7F5D50: AT(0xFE7F5D50) + { + KEEP(*(.ofs6)) + } > OFS + .ofs7 0xFE7F5D64: AT(0xFE7F5D64) + { + KEEP(*(.ofs7)) + } > OFS + .ofs8 0xFE7F5D70: AT(0xFE7F5D70) + { + KEEP(*(.ofs8)) + } > OFS +} + + +/* reserve 16KB user stack */ +PROVIDE(_ustack = ORIGIN(RAM) + LENGTH(RAM) - 0x4000 ); +/* reserve 4KB interrupt stack */ +PROVIDE(_istack = ORIGIN(RAM) + LENGTH(RAM) - 0x4000 - 0x1000 ); + +_wolfboot_partition_boot_address = @WOLFBOOT_PARTITION_BOOT_ADDRESS@; +_wolfboot_partition_size = @WOLFBOOT_PARTITION_SIZE@; +_wolfboot_partition_update_address = @WOLFBOOT_PARTITION_UPDATE_ADDRESS@; +_wolfboot_partition_swap_address = @WOLFBOOT_PARTITION_SWAP_ADDRESS@; diff --git a/hal/spi/spi_drv_renesas_rx.c b/hal/spi/spi_drv_renesas_rx.c new file mode 100644 index 000000000..c7fbdb1a6 --- /dev/null +++ b/hal/spi/spi_drv_renesas_rx.c @@ -0,0 +1,446 @@ +/* spi_drv_renesas_rx.c + * + * Driver for the SPI back-end of the SPI_FLASH module. + * + * Example implementation for Renesas RX65N. + * + * Copyright (C) 2024 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 + */ +#include +#include "spi_drv.h" +#include +#include +#include +#include "printf.h" + +#include "hal/renesas-rx.h" +#include "spi_drv_renesas_rx.h" + +#if defined(SPI_FLASH) || defined(QSPI_FLASH) + +#ifdef SPI_FLASH +static int rx_spi_init_done = 0; +#endif +#ifdef QSPI_FLASH +static int rx_qspi_init_done = 0; +static uint16_t rx_qspi_cmd_def; +#endif + +/* RSPI1: P27/RSPCKB-A, P26/MOSIB-A, P30/MISOB-A, P31/SSLB0-A */ +/* QSPI: PD2/QIO2-B, PD3/QIO3-B, PD4/QSSL-B, PD5/QSPCLK-B, PD6/QIO0-B, PD7/QIO1-B */ +void spi_init(int polarity, int phase) +{ +#ifdef SPI_FLASH + /* Release RSPI1 module stop (clear bit) */ + PROTECT_OFF(); + /* SYS_MSTPCRB: bit 17=RSPI0, 16=RSPI1, SYS_MSTPCRC: bit 22=RSPI2 */ +#if FLASH_RSPI_PORT == 0 + SYS_MSTPCRB &= ~(1 << 17); +#elif FLASH_RSPI_PORT == 1 + SYS_MSTPCRB &= ~(1 << 16); +#elif FLASH_RSPI_PORT == 2 + SYS_MSTPCRC &= ~(1 << 22); +#endif + PROTECT_ON(); + + /* Configure P26-27 and P30-31 for alt mode */ + PORT_PMR(0x2) |= ((1 << 6) | (1 << 7)); + PORT_PMR(0x3) |= (1 << 0); + PORT_PDR(0x3) &= ~(1 << 0); /* input */ + #ifdef FLASH_SPI_USE_HW_CS + PORT_PMR(0x3) |= (1 << 1); + #else + PORT_PDR(0x3) |= (1 << 1); /* output */ + #endif + + /* Disable MPC Write Protect for PFS */ + MPC_PWPR &= ~MPC_PWPR_B0WI; + MPC_PWPR |= MPC_PWPR_PFSWE; + + /* Pin Function Select */ + MPC_PFS(0x76) = 0xD; /* P26/MOSIB-A */ + MPC_PFS(0x77) = 0xD; /* P27/RSPCKB-A */ + MPC_PFS(0x78) = 0xD; /* P30/MISOB-A */ + #ifdef FLASH_SPI_USE_HW_CS + MPC_PFS(0x79) = 0xD; /* P31/SSLB0-A */ + #endif + + /* Enable MPC Write Protect for PFS */ + MPC_PWPR &= ~(MPC_PWPR_PFSWE | MPC_PWPR_B0WI); + MPC_PWPR |= MPC_PWPR_PFSWE; + + /* Configure RSPI */ + RSPI_SPPCR(FLASH_RSPI_PORT) = (RSPI_SPPCR_MOIFV | RSPI_SPPCR_MOIDE); /* enable idle fixing */ + RSPI_SPSCR(FLASH_RSPI_PORT) = RSPI_SPSCR_SPSLN(0); /* seq len 1 */ + RSPI_SPBR(FLASH_RSPI_PORT) = 5; /* 5Mbps */ + RSPI_SPDCR(FLASH_RSPI_PORT) = (RSPI_SPDCR_SPFC(0) | RSPI_SPDCR_SPBYT); /* frames=1, SPDR=byte */ + RSPI_SPCKD(FLASH_RSPI_PORT) = RSPI_SPCKD_SCKDL(0); /* 1 clock delay (SSL assert and first clock cycle) */ + RSPI_SSLND(FLASH_RSPI_PORT) = RSPI_SSLND_SLNDL(0); /* 1 clock delay (last clock cycle and SSL negation) */ + RSPI_SPND(FLASH_RSPI_PORT) = RSPI_SPND_SPNDL(0); /* Next-Access Delay: 1RSPCK+2PCLK */ + RSPI_SPCR2(FLASH_RSPI_PORT) = 0; /* no parity */ + RSPI_SPCMD(FLASH_RSPI_PORT, 0) = ( + RSPI_SPCMD_BRDV(1) | /* div/1 */ + RSPI_SPCMD_SSLA(0) | /* slave select 0 */ + RSPI_SPCMD_SSLKP | /* keep signal level between transfers */ + RSPI_SPCMD_SPB(7) | /* 8-bit data */ + RSPI_SPCMD_SPNDEN | /* enable Next-Access Delay */ + RSPI_SPCMD_SCKDEN /* enable RSPCK Delay */ + ); + if (polarity) + RSPI_SPCMD(FLASH_RSPI_PORT, 0) |= RSPI_SPCMD_CPOL; + if (phase) + RSPI_SPCMD(FLASH_RSPI_PORT, 0) |= RSPI_SPCMD_CPHA; + + /* Master SPI operation (4-wire method) */ + RSPI_SPCR(FLASH_RSPI_PORT) = RSPI_SPCR_MSTR; + + rx_spi_init_done++; +#endif /* SPI_FLASH */ + +#ifdef QSPI_FLASH + /* Release QSPI module stop (clear bit) */ + PROTECT_OFF(); + /* SYS_MSTPCRC: bit 23=QSPI */ + SYS_MSTPCRC &= ~(1 << 23); + PROTECT_ON(); + + /* Configure PD2-PD7 for alt mode */ + PORT_PMR(0xD) |= ((1 << 2) | (1 << 3) | (1 << 4) | + (1 << 5) | (1 << 6) | (1 << 7)); + + /* Disable MPC Write Protect for PFS */ + MPC_PWPR &= ~MPC_PWPR_B0WI; + MPC_PWPR |= MPC_PWPR_PFSWE; + + /* Pin Function Select */ + MPC_PFS(0x6A) = 0x1B; /* PD2/QIO2-B */ + MPC_PFS(0x6B) = 0x1B; /* PD3/QIO3-B */ + MPC_PFS(0x6C) = 0x1B; /* PD4/QSSL-B */ + MPC_PFS(0x6D) = 0x1B; /* PD5/QSPCLK-B */ + MPC_PFS(0x6E) = 0x1B; /* PD6/QIO0-B */ + MPC_PFS(0x6F) = 0x1B; /* PD7/QIO1-B */ + + /* Enable MPC Write Protect for PFS */ + MPC_PWPR &= ~(MPC_PWPR_PFSWE | MPC_PWPR_B0WI); + MPC_PWPR |= MPC_PWPR_PFSWE; + + /* Configure QSPI */ + QSPI_SPCR = QSPI_SPCR_MSTR; /* Master mode */ + QSPI_SSLP &= ~QSPI_SSLP_SSLP; /* SS Active low */ + QSPI_SPPCR = (QSPI_SPPCR_MOIFV | QSPI_SPPCR_MOIDE); /* enable idle fixing */ + QSPI_SPBR = 1; /* 30Mhz */ + QSPI_SPCKD = QSPI_SPCKD_SCKDL(0); /* 1 clock delay (SSL assert and first clock cycle) */ + QSPI_SSLND = QSPI_SSLND_SLNDL(0); /* 1 clock delay (last clock cycle and SSL negation) */ + QSPI_SPND = QSPI_SPND_SPNDL(0); /* Next-Access Delay: 1RSPCK+2PCLK */ + QSPI_SPDCR = 0; /* no dummy TX */ + + /* Setup default QSPI commands */ + rx_qspi_cmd_def = ( + QSPI_SPCMD_SPIMOD(0) | /* Single SPI */ + QSPI_SPCMD_SPB(0) | /* use byte */ + QSPI_SPCMD_BRDV(0) | /* div/1 (no div) */ + QSPI_SPCMD_SSLKP | /* keep signal level between transfers */ + QSPI_SPCMD_SPNDEN | /* enable Next-Access Delay */ + QSPI_SPCMD_SLNDEN | /* enable negation Delay */ + QSPI_SPCMD_SCKDEN /* enable RSPCK Delay */ + ); + if (polarity) + rx_qspi_cmd_def |= QSPI_SPCMD_CPOL; + if (phase) + rx_qspi_cmd_def |= QSPI_SPCMD_CPHA; + QSPI_SPCMD(0) = rx_qspi_cmd_def; + QSPI_SPCMD(1) = rx_qspi_cmd_def; + QSPI_SPCMD(2) = rx_qspi_cmd_def; + QSPI_SPCMD(3) = rx_qspi_cmd_def; + + rx_qspi_init_done++; +#endif /* QSPI_FLASH */ + (void)polarity; + (void)phase; +} + +void spi_release(void) +{ +#ifdef SPI_FLASH + RSPI_SPCR(FLASH_RSPI_PORT) &= ~RSPI_SPCR_SPE; /* Disable SPI master */ +#endif +#ifdef QSPI_FLASH + QSPI_SPCR &= ~QSPI_SPCR_SPE; /* Disable QSPI master */ +#endif +} +#endif /* SPI_FLASH || QSPI_FLASH */ + + +#ifdef SPI_FLASH +void spi_cs_on(uint32_t base, int pin) +{ + (void)base; + (void)pin; +#ifdef FLASH_SPI_USE_HW_CS + /* Enable SPI Master */ + RSPI_SPCR(FLASH_RSPI_PORT) |= RSPI_SPCR_SPE; + RSPI_SPCMD(FLASH_RSPI_PORT, 0) |= RSPI_SPCMD_SSLKP; +#else + PORT_PODR(0x3) &= ~(1 << 1); /* drive low */ +#endif +} +void spi_cs_off(uint32_t base, int pin) +{ + (void)base; + (void)pin; +#ifdef FLASH_SPI_USE_HW_CS + RSPI_SPCMD(FLASH_RSPI_PORT, 0) &= ~RSPI_SPCMD_SSLKP; + RSPI_SPCR(FLASH_RSPI_PORT) &= ~RSPI_SPCR_SPE; +#else + PORT_PODR(0x3) |= (1 << 1); /* drive high */ +#endif +} + +void spi_write(const char byte) +{ + while ((RSPI_SPSR(FLASH_RSPI_PORT) & RSPI_SPSR_SPTEF) == 0); + RSPI_SPSR8(FLASH_RSPI_PORT) = byte; +} +uint8_t spi_read(void) +{ + while ((RSPI_SPSR(FLASH_RSPI_PORT) & RSPI_SPSR_SPRF) == 0); + return RSPI_SPSR8(FLASH_RSPI_PORT); +} + +#ifdef WOLFBOOT_TPM +int spi_xfer(int cs, const uint8_t* tx, uint8_t* rx, uint32_t sz, int flags) +{ + uint32_t i; + if (!rx_spi_init_done) { + wolfBoot_printf("SPI init not yet called\n"); + return -1; + } + + spi_cs_on(SPI_CS_TPM_PIO_BASE, cs); + for (i = 0; i < sz; i++) { + spi_write((const char)tx[i]); + rx[i] = spi_read(); + } + if (!(flags & SPI_XFER_FLAG_CONTINUE)) { + spi_cs_off(SPI_CS_TPM_PIO_BASE, cs); + } + return 0; +} +#endif /* WOLFBOOT_TPM */ + +#endif /* SPI_FLASH */ + + +#ifdef QSPI_FLASH + +static uint32_t fifoLvl = 0; +static void qspi_cmd(const uint8_t* cmd, uint32_t cmdSz) +{ + uint8_t tmp; + while (cmdSz > 0) { + while ((QSPI_SPSR & QSPI_SPSR_SPTEF) == 0); + if (cmd != NULL) + QSPI_SPDR8 = *cmd++; + else + QSPI_SPDR8 = 0xFF; + QSPI_SPSR &= ~QSPI_SPSR_SPTEF; + cmdSz--; + fifoLvl++; + } +} + +/* dataSz in bytes */ +static int qspi_data(const uint32_t* txData, uint32_t* rxData, uint32_t dataSz) +{ + volatile uint32_t tmp; + uint32_t i; + uint8_t *pTx, *pRx; + + /* flush anything in the RX FIFO */ + while (fifoLvl > 0) { + while ((QSPI_SPSR & QSPI_SPSR_SPRFF) == 0); + tmp = QSPI_SPDR8; + QSPI_SPSR &= ~QSPI_SPSR_SPRFF; + fifoLvl--; + } + + /* Do full FIFO (32 bytes) TX/RX - word */ + while (dataSz >= (QSPI_FIFO_SIZE/2)) { + /* Transfer bytes - fill 16 bytes */ + while ((QSPI_SPSR & QSPI_SPSR_SPTEF) == 0); + for (i=0; i<(QSPI_FIFO_SIZE/2); i+=4) { + tmp = 0xFFFFFFFF; + if (txData) { + tmp = *txData++; + #ifndef BIG_ENDIAN_ORDER + tmp = __builtin_bswap32(tmp); + #endif + } + QSPI_SPDR32 = tmp; + dataSz -= 4; + fifoLvl += 4; + } + QSPI_SPSR &= ~QSPI_SPSR_SPTEF; + + /* Recieve bytes - (previous 16 bytes) */ + while ((QSPI_SPSR & QSPI_SPSR_SPRFF) == 0); + while (fifoLvl > (QSPI_FIFO_SIZE/2)) { + tmp = QSPI_SPDR32; + if (rxData) { + #ifndef BIG_ENDIAN_ORDER + tmp = __builtin_bswap32(tmp); + #endif + *rxData++ = tmp; + } + fifoLvl -= 4; + } + QSPI_SPSR &= ~QSPI_SPSR_SPRFF; + } + + /* Remainder < FIFO TX/RX - byte */ + pTx = (uint8_t*)txData; + pRx = (uint8_t*)rxData; + + /* Transmit Data */ + while (dataSz > 0) { + while ((QSPI_SPSR & QSPI_SPSR_SPTEF) == 0); + if (pTx) + QSPI_SPDR8 = *pTx++; + else + QSPI_SPDR8 = 0xFF; + QSPI_SPSR &= ~QSPI_SPSR_SPTEF; + dataSz--; + fifoLvl++; + } + + /* wait for transfer to finish */ + while ((QSPI_SPSR & QSPI_SPSR_SPSSLF) == 0); + + /* Recieve bytes */ + while (fifoLvl > 0) { + while ((QSPI_SPSR & QSPI_SPSR_SPRFF) == 0); + if (pRx) + *pRx++ = QSPI_SPDR8; + else + tmp = QSPI_SPDR8; + fifoLvl--; + QSPI_SPSR &= ~QSPI_SPSR_SPRFF; + } + + return 0; +} + +/* fmode = read (1) / write (0) */ +int qspi_transfer(uint8_t fmode, const uint8_t cmd, + uint32_t addr, uint32_t addrSz, uint32_t addrMode, + uint32_t alt, uint32_t altSz, uint32_t altMode, + uint32_t dummySz, + uint8_t* data, uint32_t dataSz, uint32_t dataMode) +{ + int ret; + uint8_t seq = 0; + volatile uint32_t reg; + uint32_t timeout = 10000; + + if (!rx_qspi_init_done) { + wolfBoot_printf("QSPI init not yet called\n"); + return -1; + } + + /* Clear flags - write 0 to bit to clear */ + QSPI_SPSR &= ~(QSPI_SPSR_SPTEF | QSPI_SPSR_SPRFF | QSPI_SPSR_SPSSLF); + + /* Reset buffers */ + QSPI_SPBFCR |= (QSPI_SPBFCR_RXRST | QSPI_SPBFCR_TXRST); + reg = QSPI_SPBFCR; /* SPBFCR requires dummy read after write */ + /* Set FIFO Trigger Level - must be set when SPCR.SPE=0 */ + //QSPI_SPBFCR = QSPI_SPBFCR_RXTRG(5) | QSPI_SPBFCR_TXTRG(3); /* RX Trig=16 bytes, TX Trig=16 bytes */ + QSPI_SPBFCR = QSPI_SPBFCR_RXTRG(0) | QSPI_SPBFCR_TXTRG(6); /* RX Trig=1 byte, TX Trig=0 bytes */ + reg = QSPI_SPBFCR; /* SPBFCR requires dummy read after write */ + + /* Command / Instruction - Write (command always SPI mode) */ + QSPI_SPBMUL(seq) = 1; /* Set Data length */ + QSPI_SPCMD(seq) = (rx_qspi_cmd_def | QSPI_SPCMD_SPIMOD(0)); + seq++; + + /* Address Write */ + if (addrSz > 0 && addrMode != QSPI_DATA_MODE_NONE) { + QSPI_SPBMUL(seq) = addrSz; + QSPI_SPCMD(seq) = (rx_qspi_cmd_def | QSPI_SPCMD_SPIMOD(addrMode-1)); + seq++; + } + + /* Alternate bytes */ + if (altSz > 0 && altMode != QSPI_DATA_MODE_NONE) { + QSPI_SPBMUL(seq) = altSz; + QSPI_SPCMD(seq) = (rx_qspi_cmd_def | QSPI_SPCMD_SPIMOD(altMode-1)); + seq++; + } + + /* Data */ + if (dataSz > 0 && dataMode != QSPI_DATA_MODE_NONE) { + QSPI_SPBMUL(seq) = dataSz; + QSPI_SPCMD(seq) = (rx_qspi_cmd_def | QSPI_SPCMD_SPIMOD(dataMode-1)); + if (fmode == QSPI_MODE_READ) + QSPI_SPCMD(seq) |= QSPI_SPCMD_SPREAD; + seq++; + } + + /* End CS (set high) on last transaction */ + QSPI_SPCMD(seq-1) &= ~QSPI_SPCMD_SSLKP; + + /* Set number of sequences */ + QSPI_SPSCR = QSPI_SPSCR_SPSC(seq-1); + + /* Enable the QSPI peripheral */ + QSPI_SPCR |= QSPI_SPCR_SPE; + + /* Transfer Data for sequences */ + qspi_cmd(&cmd, 1); + if (addrMode != QSPI_DATA_MODE_NONE) { + qspi_cmd((const uint8_t*)&addr, addrSz); + } + if (altMode != QSPI_DATA_MODE_NONE) { + qspi_cmd((const uint8_t*)&alt, altSz); + } + if (dummySz > 0) { + qspi_cmd(NULL, dummySz/8); + } + if (fmode == QSPI_MODE_READ) + qspi_data(NULL, (uint32_t*)data, dataSz); + else + qspi_data((const uint32_t*)data, NULL, dataSz); + + /* wait for slave select to de-assert */ + while ((QSPI_SPSR & QSPI_SPSR_SPSSLF) == 0 && --timeout > 0) { + hal_delay_us(1); + } + + /* check for timeout (-1) or success */ + ret = (timeout == 0) ? -1 : 0; + + /* Clear flags - write 0 to bit to clear */ + QSPI_SPSR &= ~(QSPI_SPSR_SPTEF | QSPI_SPSR_SPRFF | QSPI_SPSR_SPSSLF); + + /* Disable QSPI */ + QSPI_SPCR &= ~QSPI_SPCR_SPE; + + return ret; +} +#endif /* QSPI_FLASH */ diff --git a/hal/spi/spi_drv_renesas_rx.h b/hal/spi/spi_drv_renesas_rx.h new file mode 100644 index 000000000..cc655c102 --- /dev/null +++ b/hal/spi/spi_drv_renesas_rx.h @@ -0,0 +1,30 @@ +/* spi_drv_renesas_rx.h + * + * 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 + */ + +#ifndef SPI_DRV_RENESAS_RX_H_INCLUDED +#define SPI_DRV_RENESAS_RX_H_INCLUDED + +#include + +#ifndef FLASH_RSPI_PORT +#define FLASH_RSPI_PORT 1 /* RSPI1 */ +#endif + +/* use RSPI HW chip select */ +#define FLASH_SPI_USE_HW_CS + +#endif /* !SPI_DRV_RENESAS_RX_H_INCLUDED */ diff --git a/hal/zynq.c b/hal/zynq.c index 36b23179c..94df7aa9d 100644 --- a/hal/zynq.c +++ b/hal/zynq.c @@ -342,7 +342,7 @@ static int test_flash(QspiDev_t* dev); #define DEBUG_UART_BAUD 115200 #define DEBUG_UART_DIV 4 -static void uart_init(void) +void uart_init(void) { /* Enable TX/RX and Reset */ ZYNQMP_UART_CR = (ZYNQMP_UART_CR_TX_EN | ZYNQMP_UART_CR_RX_EN | @@ -355,7 +355,7 @@ static void uart_init(void) ZYNQMP_UART_BR_GEN = UART_MASTER_CLOCK / DEBUG_UART_BAUD / (DEBUG_UART_DIV+1); } -static void uart_write(const char* buf, uint32_t sz) +void uart_write(const char* buf, uint32_t sz) { uint32_t pos = 0; while (sz-- > 0) { diff --git a/include/keystore.h b/include/keystore.h index 12882579c..4f0719e4b 100644 --- a/include/keystore.h +++ b/include/keystore.h @@ -49,13 +49,7 @@ struct keystore_slot { /* KeyStore API */ int keystore_num_pubkeys(void); -#if defined(WOLFBOOT_RENESAS_SCEPROTECT) ||\ - defined(WOLFBOOT_RENESAS_TSIP) ||\ - defined(WOLFBOOT_RENESAS_RSIP) - uint32_t *keystore_get_buffer(int id); -#else - uint8_t *keystore_get_buffer(int id); -#endif +uint8_t *keystore_get_buffer(int id); int keystore_get_size(int id); uint32_t keystore_get_key_type(int id); uint32_t keystore_get_mask(int id); diff --git a/include/printf.h b/include/printf.h index 265a04143..c43c8bbbd 100644 --- a/include/printf.h +++ b/include/printf.h @@ -35,6 +35,9 @@ #endif #if defined(DEBUG_UART) + #if !defined(UART_FLASH) && !defined(WOLFBOOT_FSP) + void uart_init(void); + #endif void uart_write(const char* buf, unsigned int sz); /* turn on small printf support */ diff --git a/include/spi_drv.h b/include/spi_drv.h index 8c08d0792..9a8a4ca8c 100644 --- a/include/spi_drv.h +++ b/include/spi_drv.h @@ -58,6 +58,10 @@ #include "hal/spi/spi_drv_nxp.h" #endif +#if defined(WOLFBOOT_ARCH_RENESAS_RX) +#include "hal/spi/spi_drv_renesas_rx.h" +#endif + void spi_init(int polarity, int phase); void spi_release(void); @@ -93,6 +97,13 @@ int qspi_transfer(uint8_t fmode, const uint8_t cmd, ); #endif /* QSPI_FLASH || OCTOSPI_FLASH */ +#ifndef SPI_CS_FLASH +#define SPI_CS_FLASH 0 +#endif +#ifndef SPI_CS_PIO_BASE +#define SPI_CS_PIO_BASE 0UL +#endif + #endif /* SPI_FLASH || WOLFBOOT_TPM || QSPI_FLASH || OCTOSPI_FLASH */ #endif /* !SPI_DRV_H_INCLUDED */ diff --git a/include/user_settings.h b/include/user_settings.h index 4636307c5..30a28e37e 100644 --- a/include/user_settings.h +++ b/include/user_settings.h @@ -23,8 +23,8 @@ * 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_ #ifdef WOLFBOOT_PKCS11_APP # include "test-app/wcs/user_settings.h" @@ -39,6 +39,7 @@ #define WOLFCRYPT_ONLY #define SIZEOF_LONG_LONG 8 +/* Stdlib Types */ #define CTYPE_USER /* don't let wolfCrypt types.h include ctype.h */ #ifndef toupper extern int toupper(int c); @@ -50,10 +51,13 @@ extern int tolower(int c); #define XTOLOWER(c) tolower((c)) #ifdef USE_FAST_MATH + /* wolfBoot only does public asymmetric operations, + * so timing resistenace and hardening is not required */ # define WC_NO_HARDEN #endif #if defined(WOLFBOOT_TPM_KEYSTORE) || defined(WOLFBOOT_TPM_SEAL) + /* TPM Parameter Encryption */ # define WOLFBOOT_TPM_PARMENC /* used in this file to gate features */ #endif @@ -72,7 +76,7 @@ extern int tolower(int c); # define USE_SLOW_SHA512 #endif -/* ED448 */ +/* ED448 and SHA3/SHAKE256 */ #ifdef WOLFBOOT_SIGN_ED448 # define HAVE_ED448 # define HAVE_ED448_VERIFY @@ -93,7 +97,7 @@ extern int tolower(int c); # define ECC_TIMING_RESISTANT # define ECC_USER_CURVES /* enables only 256-bit by default */ -/* Kinetis LTC support */ + /* Kinetis LTC support */ # ifdef FREESCALE_USE_LTC # define FREESCALE_COMMON # define FSL_HW_CRYPTO_MANUAL_SELECTION @@ -102,7 +106,7 @@ extern int tolower(int c); # endif -/* Some ECC options are disabled to reduce size */ + /* Some ECC options are disabled to reduce size */ # if !defined(WOLFCRYPT_SECURE_MODE) # if !defined(WOLFBOOT_TPM) # define NO_ECC_SIGN @@ -117,7 +121,6 @@ extern int tolower(int c); #ifndef PKCS11_SMALL # define HAVE_ECC_CDH #endif -# define WOLFSSL_SP # define WOLFSSL_SP_MATH # define WOLFSSL_SP_SMALL # define SP_WORD_SIZE 32 @@ -128,14 +131,13 @@ extern int tolower(int c); /* SP MATH */ # if !defined(USE_FAST_MATH) && !defined(WOLFSSL_SP_MATH_ALL) -# define WOLFSSL_SP # define WOLFSSL_SP_MATH # define WOLFSSL_SP_SMALL # define WOLFSSL_HAVE_SP_ECC # endif -/* Curve */ + /* Curve */ # if defined(WOLFBOOT_SIGN_ECC256) || defined(WOLFCRYPT_SECURE_MODE) # define HAVE_ECC256 # elif defined(WOLFBOOT_SIGN_ECC384) @@ -145,7 +147,8 @@ extern int tolower(int c); # define HAVE_ECC521 # define WOLFSSL_SP_521 # endif - /* FP MAX BITS */ + + /* FP MAX BITS */ # if defined(HAVE_ECC521) # define FP_MAX_BITS ((528 * 2)) # elif defined(HAVE_ECC384) @@ -172,6 +175,7 @@ extern int tolower(int c); #endif /* WOLFBOOT_SIGN_ECC521 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC256 */ +/* RSA */ #if defined(WOLFBOOT_SIGN_RSA2048) || \ defined(WOLFBOOT_SIGN_RSA3072) || \ defined(WOLFBOOT_SIGN_RSA4096) || \ @@ -254,7 +258,7 @@ extern int tolower(int c); # define SP_WORD_SIZE 32 # endif - /* SP Math needs to understand long long */ + /* SP Math needs to understand long long */ # ifndef ULLONG_MAX # define ULLONG_MAX 18446744073709551615ULL # endif @@ -287,9 +291,9 @@ extern int tolower(int c); #endif #if defined(WOLFBOOT_TPM_SEAL) && defined(WOLFBOOT_ATA_DISK_LOCK) -#define WOLFSSL_BASE64_ENCODE +# define WOLFSSL_BASE64_ENCODE #else -#define NO_CODING +# define NO_CODING #endif #ifdef WOLFBOOT_TPM @@ -313,7 +317,8 @@ extern int tolower(int c); /* Configure RNG seed */ #include "loader.h" - #define CUSTOM_RAND_GENERATE_SEED(buf, sz) ({(void)buf; (void)sz; wolfBoot_panic(); 0;}) /* stub, not used */ + #define CUSTOM_RAND_GENERATE_SEED(buf, sz) \ + ({(void)buf; (void)sz; wolfBoot_panic(); 0;}) /* stub, not used */ #define WC_RNG_SEED_CB #endif @@ -364,6 +369,7 @@ extern int tolower(int c); # endif #endif +/* Algorithms and features not used */ #define NO_CMAC #define NO_DH #define WOLFSSL_NO_PEM @@ -402,10 +408,9 @@ extern int tolower(int c); /* Memory model */ - #if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL) /* Disable VLAs */ - #define WOLFSSL_SP_NO_DYN_STACK +# define WOLFSSL_SP_NO_DYN_STACK #endif #ifndef WOLFBOOT_SMALL_STACK @@ -423,6 +428,46 @@ extern int tolower(int c); # define WOLFSSL_SMALL_STACK #endif + +/* Renesas */ +#if defined(WOLFBOOT_RENESAS_TSIP) || \ + defined(WOLFBOOT_RENESAS_RSIP) || \ + defined(WOLFBOOT_RENESAS_SCEPROTECT) + + #define WOLFBOOT_SMALL_STACK + #define WOLF_CRYPTO_CB + #define WOLF_CRYPTO_CB_ONLY_ECC + #define WOLF_CRYPTO_CB_ONLY_RSA + #define WOLFSSL_NO_SW_MATH + + #ifdef WOLFBOOT_RENESAS_TSIP + #define WOLFSSL_RENESAS_TSIP + #define WOLFSSL_RENESAS_TSIP_VER 117 + #define WOLFSSL_RENESAS_TSIP_CRYPT + #define WOLFSSL_RENESAS_TSIP_CRYPTONLY + #define NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH + #define RENESAS_TSIP_INSTALLEDKEY_ADDR 0xFFFF0000 + #define ENCRYPTED_KEY_BYTE_SIZE ENC_PUB_KEY_SIZE + #define RENESAS_DEVID 7890 + #endif + #ifdef WOLFBOOT_RENESAS_SCEPROTECT + #define WOLFSSL_RENESAS_SCEPROTECT_CRYPTONLY + #define RENESAS_SCE_INSTALLEDKEY_ADDR 0x08001000U + #define SCE_ID 7890 + #endif + #ifdef WOLFBOOT_RENESAS_RSIP + #define WOLFSSL_RENESAS_FSPSM + #define WOLFSSL_RENESAS_FSPSM_CRYPTONLY + #define WOLFSSL_RENESAS_RSIP_CRYPTONLY + #undef WOLFSSL_RENESAS_FSPSM_TLS + #define RENESAS_RSIP_INSTALLEDKEY_FLASH_ADDR 0x60200000 + #define RENESAS_RSIP_INSTALLEDKEY_RAM_ADDR 0x10000100 + #define RENESAS_DEVID 7890 + #endif +#endif + + + #endif /* WOLFBOOT_PKCS11_APP */ -#endif /* !H_USER_SETTINGS_ */ +#endif /* !_WOLFBOOT_USER_SETTINGS_H_ */ diff --git a/options.mk b/options.mk index 5622b41f4..14ae9cdc0 100644 --- a/options.mk +++ b/options.mk @@ -511,7 +511,11 @@ ifeq ($(SPI_FLASH),1) EXT_FLASH=1 CFLAGS+=-D"SPI_FLASH=1" OBJS+= src/spi_flash.o - WOLFCRYPT_OBJS+=hal/spi/spi_drv_$(SPI_TARGET).o + ifeq ($(ARCH),RENESAS_RX) + WOLFCRYPT_OBJS+=hal/spi/spi_drv_renesas_rx.o + else + WOLFCRYPT_OBJS+=hal/spi/spi_drv_$(SPI_TARGET).o + endif endif ifeq ($(OCTOSPI_FLASH),1) @@ -524,7 +528,11 @@ ifeq ($(QSPI_FLASH),1) EXT_FLASH=1 CFLAGS+=-D"QSPI_FLASH=1" OBJS+= src/qspi_flash.o - WOLFCRYPT_OBJS+=hal/spi/spi_drv_$(SPI_TARGET).o + ifeq ($(ARCH),RENESAS_RX) + WOLFCRYPT_OBJS+=hal/spi/spi_drv_renesas_rx.o + else + WOLFCRYPT_OBJS+=hal/spi/spi_drv_$(SPI_TARGET).o + endif endif ifeq ($(UART_FLASH),1) @@ -594,7 +602,12 @@ endif # allow elf inclusion of debug symbols even with optimizations enabled # make DEBUG_SYMBOLS=1 ifeq ($(DEBUG_SYMBOLS),1) - CFLAGS+=-g -ggdb3 + CFLAGS+=-g + ifeq ($(USE_GCC),1) + CFLAGS+=-ggdb3 + else + CFLAGS+=-gstabs + endif endif @@ -807,9 +820,12 @@ ifeq ($(FSP), 1) endif CFLAGS+=$(CFLAGS_EXTRA) +OBJS:=$(OBJS_EXTRA) $(OBJS) ifeq ($(USE_GCC_HEADLESS),1) - CFLAGS+="-Wstack-usage=$(STACK_USAGE)" + ifneq ($(ARCH),RENESAS_RX) + CFLAGS+="-Wstack-usage=$(STACK_USAGE)" + endif endif ifeq ($(SIGN_ALG),) diff --git a/src/boot_renesas.c b/src/boot_renesas.c index 512baa1ce..6f0697ccf 100644 --- a/src/boot_renesas.c +++ b/src/boot_renesas.c @@ -1,6 +1,6 @@ /* boot_renesas.c * - * Copyright (C) 2023 wolfSSL Inc. + * Copyright (C) 2024 wolfSSL Inc. * * This file is part of wolfBoot. * @@ -20,25 +20,31 @@ */ #include -#include #include "wolfboot/wolfboot.h" #include "hal.h" +#include "image.h" #ifdef _RENESAS_RZN_ extern uint32_t IMAGE_APP_RAM_start; #endif -/* This is the main loop for the bootloader. - * - * It performs the following actions: - * - globally disable interrupts - * - update the Interrupt Vector using the address of the app - * - Set the initial stack pointer and the offset of the app - * - Change the stack pointer - * - Call the application entry point - * - */ -#if !defined(_RENESAS_RA_) && !defined(_RENESAS_RZN_) +#ifdef __RX__ +#include "hal/renesas-rx.h" +#endif + +void RAMFUNCTION arch_reboot(void) +{ +#if defined(__RX__) + /* Disable protect registers */ + PROTECT_OFF(); + + /* Issue software reset */ + SYS_SWRR = SYS_SWRR_RESET; +#endif +} + + +#if defined(__RX__) && defined(__CCRX__) #pragma inline_asm longJump static void longJump(const uint32_t *app_offset) { @@ -46,33 +52,783 @@ static void longJump(const uint32_t *app_offset) } #endif +/* Calls the application entry point */ void do_boot(const uint32_t *app_offset) { - void (*app_entry)(void); - uint32_t app_sp; - (void) app_offset; - (void) app_sp; - (void) app_entry; -#if defined(__CCRX__) - longJump(app_offset); + void (*app_entry)(void); + uint32_t app_sp; + +#ifdef BOOT_ENTRY_OFFSET + /* add byte offset to uint32_t */ + app_offset += BOOT_ENTRY_OFFSET/sizeof(uint32_t); +#endif + + (void) app_offset; + (void) app_sp; + (void) app_entry; + +#if defined(__RX__) + /* Do unconditional jump (r1 = app_offset) */ + #if defined(__CCRX__) + longJump(app_offset); + #else + app_entry = (void(*))(*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)(); + 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)(); #elif defined(_RENESAS_RZN_) - app_entry = (void(*))(&IMAGE_APP_RAM_start); - /* Jump to the application project */ - app_entry(); + app_entry = (void(*))(&IMAGE_APP_RAM_start); + /* Jump to the application project */ + app_entry(); +#else + #error No do_boot defined! #endif } + +/* Interrupt Handling and Linker Sections for RX */ +#if defined(__RX__) +typedef void (*fp) (void); /* generic interrupt function pointer typedef */ +#ifdef NO_LEADING_UNDERSCORE +extern void _PowerON_Reset(void); +#else +extern void PowerON_Reset(void); +#endif + +#define EXVECT_SECT __attribute__ ((section (".exvectors"))) +#define FVECT_SECT __attribute__ ((section (".fvectors"))) +#define RVECT_SECT __attribute__ ((section (".rvectors"))) +#define OFS_REG __attribute__ ((section (".ofs1"))) /* 0xFE7F5D00 */ /* MDE, OFS0, OFS1 */ +#define OFS_TMINF __attribute__ ((section (".ofs2"))) /* 0xFE7F5D10 */ +#define OFS_BANKSEL __attribute__ ((section (".ofs3"))) /* 0xFE7F5D20 */ +#define OFS_SPCC __attribute__ ((section (".ofs4"))) /* 0xFE7F5D40 */ +#define OFS_TMEF __attribute__ ((section (".ofs5"))) /* 0xFE7F5D48 */ +#define OFS_OSIS __attribute__ ((section (".ofs6"))) /* 0xFE7F5D50 */ +#define OFS_FAW __attribute__ ((section (".ofs7"))) /* 0xFE7F5D64 */ +#define OFS_RCP __attribute__ ((section (".ofs8"))) /* 0xFE7F5D70 */ + +/* Generic Interrupt Handler */ +void INT_Dummy(void) __attribute__ ((interrupt)); +void INT_Dummy(void) { + /* brk(); */ + /* wait(); */ +} + + +const void *ExceptVectors[] EXVECT_SECT = { +#ifdef __RXv2__ +//;0xffffff80 Reserved + (fp)0, +//;0xffffff84 Reserved + (fp)0, +//;0xffffff88 Reserved + (fp)0, +//;0xffffff8C Reserved + (fp)0, +//;0xffffff90 Reserved + (fp)0, +//;0xffffff94 Reserved + (fp)0, +//;0xffffff98 Reserved + (fp)0, +//;0xffffff9C Reserved + (fp)0, +//;0xffffffA0 Reserved + (fp)0xFFFFFFFF, +//;0xffffffA4 Reserved + (fp)0xFFFFFFFF, +//;0xffffffA8 Reserved + (fp)0xFFFFFFFF, +//;0xffffffAC Reserved + (fp)0xFFFFFFFF, +//;0xffffffB0 Reserved + (fp)0, +//;0xffffffB4 Reserved + (fp)0, +//;0xffffffB8 Reserved + (fp)0, +//;0xffffffBC Reserved + (fp)0, +//;0xffffffC0 Reserved + (fp)0, +//;0xffffffC4 Reserved + (fp)0, +//;0xffffffC8 Reserved + (fp)0, +//;0xffffffCC Reserved + (fp)0, +//;0xffffffd0 Exception(Supervisor Instruction) + INT_Dummy /* INT_Excep_SuperVisorInst */, +//;0xffffffd4 Exception(Access Instruction) + INT_Dummy /* INT_Excep_AccessInst */, +//;0xffffffd8 Reserved + INT_Dummy, +//;0xffffffdc Exception(Undefined Instruction) + INT_Dummy /* INT_Excep_UndefinedInst */, +//;0xffffffe0 Reserved + INT_Dummy, +//;0xffffffe4 Exception(Floating Point) + INT_Dummy /* INT_Excep_FloatingPoint */, +//;0xffffffe8 Reserved + INT_Dummy, +//;0xffffffec Reserved + INT_Dummy, +//;0xfffffff0 Reserved + INT_Dummy, +//;0xfffffff4 Reserved + INT_Dummy, +//;0xfffffff8 NMI + INT_Dummy /* INT_NonMaskableInterrupt */, +#else +//;0xffffff80 MDES Endian Select Register +#ifdef __RX_LITTLE_ENDIAN__ + (fp)0xffffffff, +#endif +#ifdef __RX_BIG_ENDIAN__ + (fp)0xfffffff8, +#endif +//;0xffffff84 Reserved + (fp)0, +//;0xffffff88 Reserved + (fp)0xFFFFFFFF, +//;0xffffff8c Reserved + (fp)0xFFFFFFFF, +//;0xffffff90 Reserved + (fp)0xFFFFFFFF, +//;0xffffff94 Reserved + (fp)0xFFFFFFFF, +//;0xffffff98 Reserved + (fp)0xFFFFFFFF, +//;0xffffff9c Reserved + (fp)0xFFFFFFFF, +//;0xffffffa0 ID + (fp)0xFFFFFFFF, +//;0xffffffa4 ID + (fp)0xFFFFFFFF, +//;0xffffffa8 ID + (fp)0xFFFFFFFF, +//;0xffffffac ID + (fp)0xFFFFFFFF, +//;0xffffffb0 Reserved + (fp)0xFFFFFFFF, +//;0xffffffb4 Reserved + (fp)0xFFFFFFFF, +//;0xffffffb8 Reserved + (fp)0xFFFFFFFF, +//;0xffffffbc Reserved + (fp)0xFFFFFFFF, +//;0xffffffc0 Reserved + (fp)0xFFFFFFFF, +//;0xffffffc4 Reserved + (fp)0xFFFFFFFF, +//;0xffffffc8 Reserved + (fp)0xFFFFFFFF, +//;0xffffffcc Reserved + (fp)0xFFFFFFFF, +//;0xffffffd0 Exception(Supervisor Instruction) + INT_Dummy /* INT_Excep_SuperVisorInst */, +//;0xffffffd4 Exception(Access Instruction) + INT_Dummy /* INT_Excep_AccessInst */, +//;0xffffffd8 Reserved + (fp)0xFFFFFFFF, +//;0xffffffdc Exception(Undefined Instruction) + INT_Dummy /* INT_Excep_UndefinedInst */, +//;0xffffffe0 Reserved + (fp)0xFFFFFFFF, +//;0xffffffe4 Exception(Floating Point) + INT_Dummy /* INT_Excep_FloatingPoint */, +//;0xffffffe8 Reserved + (fp)0xFFFFFFFF, +//;0xffffffec Reserved + (fp)0xFFFFFFFF, +//;0xfffffff0 Reserved + (fp)0xFFFFFFFF, +//;0xfffffff4 Reserved + (fp)0xFFFFFFFF, +//;0xfffffff8 NMI + INT_Dummy /* INT_NonMaskableInterrupt */, +#endif /* __RXv2__ */ +}; + +const void *HardwareVectors[] FVECT_SECT = { +#ifdef NO_LEADING_UNDERSCORE + _PowerON_Reset +#else + PowerON_Reset +#endif +}; + +const fp RelocatableVectors[] RVECT_SECT = { +//;0x0000 Reserved + (fp)0, +//;0x0004 Reserved + (fp)0, +//;0x0008 Reserved + (fp)0, +//;0x000C Reserved + (fp)0, +//;0x0010 Reserved + (fp)0, +//;0x0014 Reserved + (fp)0, +//;0x0018 Reserved + (fp)0, +//;0x001C Reserved + (fp)0, +//;0x0020 Reserved + (fp)0, +//;0x0024 Reserved + (fp)0, +//;0x0028 Reserved + (fp)0, +//;0x002C Reserved + (fp)0, +//;0x0030 Reserved + (fp)0, +//;0x0034 Reserved + (fp)0, +//;0x0038 Reserved + (fp)0, +//;0x003C Reserved + (fp)0, +//;0x0040 BSC_BUSERR + (fp)INT_Dummy /* INT_Excep_BSC_BUSERR */, +//;0x0044 ICU_GROUPIE0 + (fp)INT_Dummy /* INT_Excep_ICU_GROUPIE0 */, +//;0x0048 RAM_RAMERR + (fp)INT_Dummy /* INT_Excep_RAM_RAMERR */, +//;0x004C Reserved + (fp)0, +//;0x0050 Reserved + (fp)0, +//;0x0054 FCU_FIFERR + (fp)INT_Dummy /* INT_Excep_FCU_FIFERR */, +//;0x0058 Reserved + (fp)0, +//;0x005C FCU_FRDYI + (fp)INT_Dummy /* INT_Excep_FCU_FRDYI */, +//;0x0060 Reserved + (fp)0, +//;0x0064 Reserved + (fp)0, +//;0x0068 ICU_SWINT2 + (fp)INT_Dummy /* INT_Excep_ICU_SWINT2 */, +//;0x006C ICU_SWINT + (fp)INT_Dummy /* INT_Excep_ICU_SWINT */, +//;0x0070 CMT0_CMI0 + (fp)INT_Dummy /* INT_Excep_CMT0_CMI0 */, +//;0x0074 CMT1_CMI1 + (fp)INT_Dummy /* INT_Excep_CMT1_CMI1 */, +//;0x0078 CMTW0_CMWI0 + (fp)INT_Dummy /* INT_Excep_CMTW0_CMWI0 */, +//;0x007C CMTW1_CMWI1 + (fp)INT_Dummy /* INT_Excep_CMTW1_CMWI1 */, +//;0x0080 Reserved + (fp)0, +//;0x0084 Reserved + (fp)0, +//;0x0088 USB0_D0FIFO0 + (fp)INT_Dummy /* INT_Excep_USB0_D0FIFO0 */, +//;0x008C USB0_D1FIFO0 + (fp)INT_Dummy /* INT_Excep_USB0_D1FIFO0 */, +//;0x0090 Reserved + (fp)0, +//;0x0094 Reserved + (fp)0, +//;0x0098 RSPI0_SPRI0 + (fp)INT_Dummy /* INT_Excep_RSPI0_SPRI0 */, +//;0x009C RSPI0_SPTI0 + (fp)INT_Dummy /* INT_Excep_RSPI0_SPTI0 */, +//;0x00A0 RSPI1_SPRI1 + (fp)INT_Dummy /* INT_Excep_RSPI1_SPRI1 */, +//;0x00A4 RSPI1_SPTI1 + (fp)INT_Dummy /* INT_Excep_RSPI1_SPTI1 */, +//;0x00A8 QSPI_SPRI + (fp)INT_Dummy /* INT_Excep_QSPI_SPRI */, +//;0x00AC QSPI_SPTI + (fp)INT_Dummy /* INT_Excep_QSPI_SPTI */, +//;0x00B0 SDHI_SBFAI + (fp)INT_Dummy /* INT_Excep_SDHI_SBFAI */, +//;0x00B4 MMCIF_MBFAI + (fp)INT_Dummy /* INT_Excep_MMCIF_MBFAI */, +//;0x00B8 SSIE0_SSITXI0 + (fp)INT_Dummy /* INT_Excep_SSIE0_SSITXI0 */, +//;0x00BC SSIE0_SSIRXI0 + (fp)INT_Dummy /* INT_Excep_SSIE0_SSIRXI0 */, +//;0x00C0 SSIE1_SSIRTI1 + (fp)INT_Dummy /* INT_Excep_SSIE1_SSIRTI1 */, +//;0x00C4 Reserved + (fp)0, +//;0x00C8 RIIC1_RXI1 + (fp)INT_Dummy /* INT_Excep_RIIC1_RXI1 */, +//;0x00CC RIIC1_TXI1 + (fp)INT_Dummy /* INT_Excep_RIIC1_TXI1 */, +//;0x00D0 RIIC0_RXI0 + (fp)INT_Dummy /* INT_Excep_RIIC0_RXI0 */, +//;0x00D4 RIIC0_TXI0 + (fp)INT_Dummy /* INT_Excep_RIIC0_TXI0 */, +//;0x00D8 RIIC2_RXI2 + (fp)INT_Dummy /* INT_Excep_RIIC2_RXI2 */, +//;0x00DC RIIC2_TXI2 + (fp)INT_Dummy /* INT_Excep_RIIC2_TXI2 */, +//;0x00E0 Reserved + (fp)0, +//;0x00E4 Reserved + (fp)0, +//;0x00E8 SCI0_RXI0 + (fp)INT_Dummy /* INT_Excep_SCI0_RXI0 */, +//;0x00EC SCI0_TXI0 + (fp)INT_Dummy /* INT_Excep_SCI0_TXI0 */, +//;0x00F0 SCI1_RXI1 + (fp)INT_Dummy /* INT_Excep_SCI1_RXI1 */, +//;0x00F4 SCI1_TXI1 + (fp)INT_Dummy /* INT_Excep_SCI1_TXI1 */, +//;0x00F8 SCI2_RXI2 + (fp)INT_Dummy /* INT_Excep_SCI2_RXI2 */, +//;0x00FC SCI2_TXI2 + (fp)INT_Dummy /* INT_Excep_SCI2_TXI2 */, +//;0x0100 ICU_IRQ0 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ0 */, +//;0x0104 ICU_IRQ1 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ1 */, +//;0x0108 ICU_IRQ2 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ2 */, +//;0x010C ICU_IRQ3 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ3 */, +//;0x0110 ICU_IRQ4 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ4 */, +//;0x0114 ICU_IRQ5 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ5 */, +//;0x0118 ICU_IRQ6 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ6 */, +//;0x011C ICU_IRQ7 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ7 */, +//;0x0120 ICU_IRQ8 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ8 */, +//;0x0124 ICU_IRQ9 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ9 */, +//;0x0128 ICU_IRQ10 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ10 */, +//;0x012C ICU_IRQ11 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ11 */, +//;0x0130 ICU_IRQ12 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ12 */, +//;0x0134 ICU_IRQ13 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ13 */, +//;0x0138 ICU_IRQ14 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ14 */, +//;0x013C ICU_IRQ15 + (fp)INT_Dummy /* INT_Excep_ICU_IRQ15 */, +//;0x0140 SCI3_RXI3 + (fp)INT_Dummy /* INT_Excep_SCI3_RXI3 */, +//;0x0144 SCI3_TXI3 + (fp)INT_Dummy /* INT_Excep_SCI3_TXI3 */, +//;0x0148 SCI4_RXI4 + (fp)INT_Dummy /* INT_Excep_SCI4_RXI4 */, +//;0x014C SCI4_TXI4 + (fp)INT_Dummy /* INT_Excep_SCI4_TXI4 */, +//;0x0150 SCI5_RXI5 + (fp)INT_Dummy /* INT_Excep_SCI5_RXI5 */, +//;0x0154 SCI5_TXI5 + (fp)INT_Dummy /* INT_Excep_SCI5_TXI5 */, +//;0x0158 SCI6_RXI6 + (fp)INT_Dummy /* INT_Excep_SCI6_RXI6 */, +//;0x015C SCI6_TXI6 + (fp)INT_Dummy /* INT_Excep_SCI6_TXI6 */, +//;0x0160 LVD1_LVD1 + (fp)INT_Dummy /* INT_Excep_LVD1_LVD1 */, +//;0x0164 LVD2_LVD2 + (fp)INT_Dummy /* INT_Excep_LVD2_LVD2 */, +//;0x0168 USB0_USBR0 + (fp)INT_Dummy /* INT_Excep_USB0_USBR0 */, +//;0x016C Reserved + (fp)0, +//;0x0170 RTC_ALM + (fp)INT_Dummy /* INT_Excep_RTC_ALM */, +//;0x0174 RTC_PRD + (fp)INT_Dummy /* INT_Excep_RTC_PRD */, +//;0x0178 Reserved + (fp)0, +//;0x017C IWDT_IWUNI + (fp)INT_Dummy /* INT_Excep_IWDT_IWUNI */, +//;0x0180 WDT_WUNI + (fp)INT_Dummy /* INT_Excep_WDT_WUNI */, +//;0x0184 PDC_PCDFI + (fp)INT_Dummy /* INT_Excep_PDC_PCDFI */, +//;0x0188 SCI7_RXI7 + (fp)INT_Dummy /* INT_Excep_SCI7_RXI7 */, +//;0x018C SCI7_TXI7 + (fp)INT_Dummy /* INT_Excep_SCI7_TXI7 */, +//;0x0190 SCI8_RXI8 + (fp)INT_Dummy /* INT_Excep_SCI8_RXI8 */, +//;0x0194 SCI8_TXI8 + (fp)INT_Dummy /* INT_Excep_SCI8_TXI8 */, +//;0x0198 SCI9_RXI9 + (fp)INT_Dummy /* INT_Excep_SCI9_RXI9 */, +//;0x019C SCI9_TXI9 + (fp)INT_Dummy /* INT_Excep_SCI9_TXI9 */, +//;0x01A0 SCI10_RXI10 + (fp)INT_Dummy /* INT_Excep_SCI10_RXI10 */, +//;0x01A4 SCI10_TXI10 + (fp)INT_Dummy /* INT_Excep_SCI10_TXI10 */, +//;0x01A8 ICU_GROUPBE0 + (fp)INT_Dummy /* INT_Excep_ICU_GROUPBE0 */, +//;0x01AC ICU_GROUPBL2 + (fp)INT_Dummy /* INT_Excep_ICU_GROUPBL2 */, +//;0x01B0 RSPI2_SPRI2 + (fp)INT_Dummy /* INT_Excep_RSPI2_SPRI2 */, +//;0x01B4 RSPI2_SPTI2 + (fp)INT_Dummy /* INT_Excep_RSPI2_SPTI2 */, +//;0x01B8 ICU_GROUPBL0 + (fp)INT_Dummy /* INT_Excep_ICU_GROUPBL0 */, +//;0x01BC ICU_GROUPBL1 + (fp)INT_Dummy /* INT_Excep_ICU_GROUPBL1 */, +//;0x01C0 ICU_GROUPAL0 + (fp)INT_Dummy /* INT_Excep_ICU_GROUPAL0 */, +//;0x01C4 ICU_GROUPAL1 + (fp)INT_Dummy /* INT_Excep_ICU_GROUPAL1 */, +//;0x01C8 SCI11_RXI11 + (fp)INT_Dummy /* INT_Excep_SCI11_RXI11 */, +//;0x01CC SCI11_TXI11 + (fp)INT_Dummy /* INT_Excep_SCI11_TXI11 */, +//;0x01D0 SCI12_RXI12 + (fp)INT_Dummy /* INT_Excep_SCI12_RXI12 */, +//;0x01D4 SCI12_TXI12 + (fp)INT_Dummy /* INT_Excep_SCI12_TXI12 */, +//;0x01D8 Reserved + (fp)0, +//;0x01DC Reserved + (fp)0, +//;0x01E0 DMAC_DMAC0I + (fp)INT_Dummy /* INT_Excep_DMAC_DMAC0I */, +//;0x01E4 DMAC_DMAC1I + (fp)INT_Dummy /* INT_Excep_DMAC_DMAC1I */, +//;0x01E8 DMAC_DMAC2I + (fp)INT_Dummy /* INT_Excep_DMAC_DMAC2I */, +//;0x01EC DMAC_DMAC3I + (fp)INT_Dummy /* INT_Excep_DMAC_DMAC3I */, +//;0x01F0 DMAC_DMAC74I + (fp)INT_Dummy /* INT_Excep_DMAC_DMAC74I */, +//;0x01F4 OST_OSTDI + (fp)INT_Dummy /* INT_Excep_OST_OSTDI */, +//;0x01F8 EXDMAC_EXDMAC0I + (fp)INT_Dummy /* INT_Excep_EXDMAC_EXDMAC0I */, +//;0x01FC EXDMAC_EXDMAC1I + (fp)INT_Dummy /* INT_Excep_EXDMAC_EXDMAC1I */, +//;0x0200 PERIB_INTB128 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB128 */, +//;0x0204 PERIB_INTB129 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB129 */, +//;0x0208 PERIB_INTB130 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB130 */, +//;0x020C PERIB_INTB131 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB131 */, +//;0x0210 PERIB_INTB132 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB132 */, +//;0x0214 PERIB_INTB133 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB133 */, +//;0x0218 PERIB_INTB134 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB134 */, +//;0x021C PERIB_INTB135 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB135 */, +//;0x0220 PERIB_INTB136 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB136 */, +//;0x0224 PERIB_INTB137 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB137 */, +//;0x0228 PERIB_INTB138 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB138 */, +//;0x022C PERIB_INTB139 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB139 */, +//;0x0230 PERIB_INTB140 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB140 */, +//;0x0234 PERIB_INTB141 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB141 */, +//;0x0238 PERIB_INTB142 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB142 */, +//;0x023C PERIB_INTB143 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB143 */, +//;0x0240 PERIB_INTB144 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB144 */, +//;0x0244 PERIB_INTB145 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB145 */, +//;0x0248 PERIB_INTB146 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB146 */, +//;0x024C PERIB_INTB147 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB147 */, +//;0x0250 PERIB_INTB148 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB148 */, +//;0x0254 PERIB_INTB149 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB149 */, +//;0x0258 PERIB_INTB150 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB150 */, +//;0x025C PERIB_INTB151 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB151 */, +//;0x0260 PERIB_INTB152 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB152 */, +//;0x0264 PERIB_INTB153 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB153 */, +//;0x0268 PERIB_INTB154 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB154 */, +//;0x026C PERIB_INTB155 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB155 */, +//;0x0270 PERIB_INTB156 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB156 */, +//;0x0274 PERIB_INTB157 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB157 */, +//;0x0278 PERIB_INTB158 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB158 */, +//;0x027C PERIB_INTB159 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB159 */, +//;0x0280 PERIB_INTB160 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB160 */, +//;0x0284 PERIB_INTB161 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB161 */, +//;0x0288 PERIB_INTB162 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB162 */, +//;0x028C PERIB_INTB163 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB163 */, +//;0x0290 PERIB_INTB164 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB164 */, +//;0x0294 PERIB_INTB165 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB165 */, +//;0x0298 PERIB_INTB166 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB166 */, +//;0x029C PERIB_INTB167 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB167 */, +//;0x02A0 PERIB_INTB168 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB168 */, +//;0x02A4 PERIB_INTB169 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB169 */, +//;0x02A8 PERIB_INTB170 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB170 */, +//;0x02AC PERIB_INTB171 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB171 */, +//;0x02B0 PERIB_INTB172 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB172 */, +//;0x02B4 PERIB_INTB173 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB173 */, +//;0x02B8 PERIB_INTB174 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB174 */, +//;0x02BC PERIB_INTB175 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB175 */, +//;0x02C0 PERIB_INTB176 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB176 */, +//;0x02C4 PERIB_INTB177 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB177 */, +//;0x02C8 PERIB_INTB178 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB178 */, +//;0x02CC PERIB_INTB179 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB179 */, +//;0x02D0 PERIB_INTB180 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB180 */, +//;0x02D4 PERIB_INTB181 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB181 */, +//;0x02D8 PERIB_INTB182 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB182 */, +//;0x02DC PERIB_INTB183 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB183 */, +//;0x02E0 PERIB_INTB184 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB184 */, +//;0x02E4 PERIB_INTB185 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB185 */, +//;0x02E8 PERIB_INTB186 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB186 */, +//;0x02EC PERIB_INTB187 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB187 */, +//;0x02F0 PERIB_INTB188 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB188 */, +//;0x02F4 PERIB_INTB189 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB189 */, +//;0x02F8 PERIB_INTB190 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB190 */, +//;0x02FC PERIB_INTB191 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB191 */, +//;0x0300 PERIB_INTB192 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB192 */, +//;0x0304 PERIB_INTB193 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB193 */, +//;0x0308 PERIB_INTB194 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB194 */, +//;0x030C PERIB_INTB195 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB195 */, +//;0x0310 PERIB_INTB196 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB196 */, +//;0x0314 PERIB_INTB197 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB197 */, +//;0x0318 PERIB_INTB198 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB198 */, +//;0x031C PERIB_INTB199 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB199 */, +//;0x0320 PERIB_INTB200 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB200 */, +//;0x0324 PERIB_INTB201 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB201 */, +//;0x0328 PERIB_INTB202 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB202 */, +//;0x032C PERIB_INTB203 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB203 */, +//;0x0330 PERIB_INTB204 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB204 */, +//;0x0334 PERIB_INTB205 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB205 */, +//;0x0338 PERIB_INTB206 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB206 */, +//;0x033C PERIB_INTB207 + (fp)INT_Dummy /* INT_Excep_PERIB_INTB207 */, +//;0x0340 PERIA_INTA208 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA208 */, +//;0x0344 PERIA_INTA209 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA209 */, +//;0x0348 PERIA_INTA210 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA210 */, +//;0x034C PERIA_INTA211 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA211 */, +//;0x0350 PERIA_INTA212 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA212 */, +//;0x0354 PERIA_INTA213 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA213 */, +//;0x0358 PERIA_INTA214 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA214 */, +//;0x035C PERIA_INTA215 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA215 */, +//;0x0360 PERIA_INTA216 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA216 */, +//;0x0364 PERIA_INTA217 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA217 */, +//;0x0368 PERIA_INTA218 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA218 */, +//;0x036C PERIA_INTA219 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA219 */, +//;0x0370 PERIA_INTA220 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA220 */, +//;0x0374 PERIA_INTA221 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA221 */, +//;0x0378 PERIA_INTA222 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA222 */, +//;0x037C PERIA_INTA223 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA223 */, +//;0x0380 PERIA_INTA224 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA224 */, +//;0x0384 PERIA_INTA225 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA225 */, +//;0x0388 PERIA_INTA226 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA226 */, +//;0x038C PERIA_INTA227 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA227 */, +//;0x0390 PERIA_INTA228 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA228 */, +//;0x0394 PERIA_INTA229 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA229 */, +//;0x0398 PERIA_INTA230 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA230 */, +//;0x039C PERIA_INTA231 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA231 */, +//;0x03A0 PERIA_INTA232 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA232 */, +//;0x03A4 PERIA_INTA233 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA233 */, +//;0x03A8 PERIA_INTA234 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA234 */, +//;0x03AC PERIA_INTA235 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA235 */, +//;0x03B0 PERIA_INTA236 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA236 */, +//;0x03B4 PERIA_INTA237 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA237 */, +//;0x03B8 PERIA_INTA238 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA238 */, +//;0x03BC PERIA_INTA239 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA239 */, +//;0x03C0 PERIA_INTA240 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA240 */, +//;0x03C4 PERIA_INTA241 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA241 */, +//;0x03C8 PERIA_INTA242 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA242 */, +//;0x03CC PERIA_INTA243 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA243 */, +//;0x03D0 PERIA_INTA244 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA244 */, +//;0x03D4 PERIA_INTA245 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA245 */, +//;0x03D8 PERIA_INTA246 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA246 */, +//;0x03DC PERIA_INTA247 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA247 */, +//;0x03E0 PERIA_INTA248 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA248 */, +//;0x03E4 PERIA_INTA249 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA249 */, +//;0x03E8 PERIA_INTA250 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA250 */, +//;0x03EC PERIA_INTA251 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA251 */, +//;0x03F0 PERIA_INTA252 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA252 */, +//;0x03F4 PERIA_INTA253 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA253 */, +//;0x03F8 PERIA_INTA254 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA254 */, +//;0x03FC PERIA_INTA255 + (fp)INT_Dummy /* INT_Excep_PERIA_INTA255 */, +}; + +/* Optional inclusion of Option Setting Memory region (OFSM) */ +#ifdef WOLFBOOT_RENESAS_OSM + +/* MDE, OFS0, OFS1 register */ +#ifdef __RX_BIG_ENDIAN__ + #define __MDE_VALUE (0xfffffff8) /* big */ +#else + #define __MDE_VALUE (0xffffffff) /* little */ +#endif +#define __OFS0_VALUE (0xffffffff) +#define __OFS1_VALUE (0xffffffff) + +const unsigned long __ofsm_sec_ofs1[] OFS_REG = { + __MDE_VALUE, + __OFS0_VALUE, + __OFS1_VALUE, +}; + +/* TMINF register */ +const unsigned long __TMINFreg OFS_TMINF = 0xffffffff; + +/* BANKSEL register */ +const unsigned long __BANKSELreg OFS_BANKSEL = 0xffffffff; + +/* SPCC register */ +const unsigned long __SPCCreg OFS_SPCC = 0xffffffff; + +/* TMEF register */ +const unsigned long __TMEFreg OFS_TMEF = 0xffffffff; + +/* OSIS register (ID codes) */ +const unsigned long __OSISreg[4] OFS_OSIS = { + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, +}; + +/* FAW register */ +const unsigned long __FAWreg OFS_FAW = 0xffffffff; + +/* RCP register */ +const unsigned long __RCPreg OFS_RCP = 0xffffffff; +#endif /* WOLFBOOT_RENESAS_OSM */ + +#endif /* __RX__ */ diff --git a/src/boot_renesas_start.S b/src/boot_renesas_start.S new file mode 100644 index 000000000..8d658d0ba --- /dev/null +++ b/src/boot_renesas_start.S @@ -0,0 +1,141 @@ +/* boot_renesas_start.S + * + * Copyright (C) 2024 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 + */ + +/* Reference startup code based on from Renesas RX BSP start.c */ + + .list + .section .text + + .extern _data + .extern _mdata + .extern _ebss + .extern _bss + .extern _edata + .extern _ustack + .extern _istack + .extern _rvectors +#ifdef NO_LEADING_UNDERSCORE + .extern main +#else + .extern _main +#endif + + .global _PowerON_Reset /* global Start routine */ + .type _PowerON_Reset, @function +_PowerON_Reset : +/* initialise user stack pointer */ + mvtc #_ustack,USP + +/* initialise interrupt stack pointer */ + mvtc #_istack,ISP + +#ifdef __RXv2__ +/* setup exception vector */ + mvtc #_ExceptVectors, extb /* EXCEPTION VECTOR ADDRESS */ +#endif +/* setup intb */ + mvtc #_rvectors_start, intb /* INTERRUPT VECTOR ADDRESS definition */ + +/* setup FPSW */ + mvtc #100h, fpsw + +/* load data section from ROM to RAM */ + mov #_mdata, r2 /* src ROM address of data section in R2 */ + mov #_data, r1 /* dest start RAM address of data section in R1 */ + mov #_edata, r3 /* end RAM address of data section in R3 */ + sub r1, r3 /* size of data section in R3 (R3=R3-R1) */ +#ifdef __RX_ALLOW_STRING_INSNS__ + smovf /* block copy R3 bytes from R2 to R1 */ +#else + cmp #0, r3 + beq 2f + +1: mov.b [r2+], r5 + mov.b r5, [r1+] + sub #1, r3 + bne 1b +2: +#endif + +/* bss initialisation : zero out bss */ + mov #00h,r2 /* load R2 reg with zero */ + mov #_ebss, r3 /* store the end address of bss in R3 */ + mov #_bss, r1 /* store the start address of bss in R1 */ +#ifdef __RX_ALLOW_STRING_INSNS__ + sub r1, r3 /* size of bss section in R3 (R3=R3-R1) */ + sstr.b +#else +1: cmp r1, r3 + beq 2f + mov.b r2, [r1+] + bra 1b +2: +#endif + +#ifdef RX_PSW_USER_MODE +/* check and skip PSW setup if already in "user mode" */ + mvfc psw, r1 + btst #20, r1 /* Processor Mode: 0=Supervisor, 1=User */ + bne skip_psw_setup + +/* change PSW Processor Mode (PM) to user-mode */ + mvtc #10000h, psw /* Set Interupt Enable bit */ + or #00100000h, r1 /* Set PM = 1 (user mode) */ + push.l r1 + mvfc pc, r1 + add #10, r1 + push.l r1 + rte + nop + nop +skip_psw_setup: +#endif + +/* start user program */ +#ifdef NO_LEADING_UNDERSCORE + mov #main, r7 +#else + mov #_main, r7 +#endif + jsr r7 + mov #_exit, r7 + jsr r7 + + + .global __rx_fini + .type __rx_fini, @function +__rx_fini: + rts + + .global _exit + .type _exit, @function +/* call to exit */ +_exit: + mov #0, r2 +#ifndef NO_LEADING_UNDERSCORE + mov #___call_exitprocs, r7 +#endif + jsr r7 +_loop_here: + bra _loop_here + + .text + .end diff --git a/src/image.c b/src/image.c index 8165ec160..6cab3cf65 100644 --- a/src/image.c +++ b/src/image.c @@ -178,8 +178,29 @@ static void wolfBoot_verify_signature(uint8_t key_slot, return; } +#if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \ + defined(WOLFBOOT_RENESAS_TSIP) || \ + defined(WOLFBOOT_RENESAS_RSIP) + ret = wc_ecc_init_ex(&ecc, NULL, RENESAS_DEVID); +#else ret = wc_ecc_init(&ecc); +#endif if (ret == 0) { + #if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \ + defined(WOLFBOOT_RENESAS_TSIP) || \ + defined(WOLFBOOT_RENESAS_RSIP) + /* The public key is wrapped and cannot be imported. + * Key must be loaded to TSIP and unwrapped. + * Then ECDSA crypto callback will perform verify on TSIP hardware */ + wc_ecc_set_curve(&ecc, 0, ECC_KEY_TYPE); + + /* The wc_ecc_verify_hash must be used since _ex version does not + * trigger crypto callback. Building with NO_ASN allows us to send R+S + * directly without ASN.1 encoded DSA header */ + VERIFY_FN(img, &verify_res, wc_ecc_verify_hash, + sig, IMAGE_SIGNATURE_SIZE, + img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &verify_res, &ecc) + #else /* Import public key */ ret = wc_ecc_import_unsigned(&ecc, pubkey, pubkey + point_sz, NULL, ECC_KEY_TYPE); @@ -192,8 +213,9 @@ static void wolfBoot_verify_signature(uint8_t key_slot, VERIFY_FN(img, &verify_res, wc_ecc_verify_hash_ex, &r, &s, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, &verify_res, &ecc); } - wc_ecc_free(&ecc); + #endif } + wc_ecc_free(&ecc); } #endif /* WOLFBOOT_SIGN_ECC256 || WOLFBOOT_SIGN_ECC384 || WOLFBOOT_SIGN_ECC521 */ @@ -274,9 +296,8 @@ static void wolfBoot_verify_signature(uint8_t key_slot, return; } - /* wolfCrypt software RSA verify */ -#if defined(WOLFBOOT_RENESAS_SCEPROTECT) ||\ - defined(WOLFBOOT_RENESAS_TSIP) ||\ +#if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \ + defined(WOLFBOOT_RENESAS_TSIP) || \ defined(WOLFBOOT_RENESAS_RSIP) ret = wc_InitRsaKey_ex(&rsa, NULL, RENESAS_DEVID); if (ret == 0) { @@ -284,12 +305,13 @@ static void wolfBoot_verify_signature(uint8_t key_slot, RSA_VERIFY_FN(ret, wc_RsaSSL_Verify, img->sha_hash, WOLFBOOT_SHA_DIGEST_SIZE, output, IMAGE_SIGNATURE_SIZE, &rsa); - /* SCE SignatureVerify API has verified */ + /* The crypto callback success also verifies hash */ if (ret == 0) wolfBoot_image_confirm_signature_ok(img); } (void)digest_out; #else + /* wolfCrypt software RSA verify */ ret = wc_InitRsaKey(&rsa, NULL); if (ret == 0) { /* Import public key */ @@ -1022,12 +1044,12 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img) return -1; pubkey_hint_size = get_header(img, HDR_PUBKEY, &pubkey_hint); if (pubkey_hint_size == WOLFBOOT_SHA_DIGEST_SIZE) { -#if defined(WOLFBOOT_RENESAS_SCEPROTECT) ||\ - defined(WOLFBOOT_RENESAS_TSIP) ||\ +#if defined(WOLFBOOT_RENESAS_SCEPROTECT) || \ + defined(WOLFBOOT_RENESAS_TSIP) || \ defined(WOLFBOOT_RENESAS_RSIP) /* SCE wrapped key is installed at * RENESAS_SCE_INSTALLEDKEY_ADDR - * TSIP encrypted key is installed ad + * TSIP encrypted key is installed at * RENESAS_TSIP_INSTALLEDKEY_ADDR */ key_slot = 0; diff --git a/src/libwolfboot.c b/src/libwolfboot.c index 58f335155..1dba6b73b 100644 --- a/src/libwolfboot.c +++ b/src/libwolfboot.c @@ -391,15 +391,45 @@ static int RAMFUNCTION partition_magic_write(uint8_t part, uintptr_t addr) # define trailer_write(part,addr, val) hal_flash_write(addr, (void *)&val, 1) # define partition_magic_write(part,addr) hal_flash_write(addr, \ (void*)&wolfboot_magic_trail, sizeof(uint32_t)); -#endif +#endif /* NVM_FLASH_WRITEONCE */ -#ifndef MOCK_PARTITION_TRAILER -#ifdef EXT_FLASH +#ifndef MOCK_PARTITION_TRAILER /* used for unit-mock-state.c */ +#ifdef CUSTOM_PARTITION_TRAILER + +/* Custom partition trailer + * Function implementation externally defined + */ +uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at); +void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val); +void RAMFUNCTION set_partition_magic(uint8_t part); + +#elif !defined(WOLFBOOT_FIXED_PARTITIONS) +static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at) +{ + (void)part; + (void)at; + return 0; +} +static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val) +{ + (void)part; + (void)at; + (void)val; + return; +} +static void RAMFUNCTION set_partition_magic(uint8_t part) +{ + (void)part; + return; +} + +#else /** - * @brief Get the trailer at a specific address in a fixed partition. + * @brief Get the trailer at a specific address * - * This function retrieves the trailer at a specific address in a fixed partition. + * This function retrieves the trailer at a specific address in external or + * internal flash * * @param[in] part Partition number. * @param[in] at Address offset. @@ -409,30 +439,39 @@ static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at) { uint8_t *ret = NULL; uint32_t sel_sec = 0; + if (part == PART_BOOT) { + #ifdef EXT_FLASH if (FLAGS_BOOT_EXT()){ ext_flash_check_read(PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&ext_cache, sizeof(uint32_t)); ret = (uint8_t *)&ext_cache; - } else { + } + else + #endif + { /* only internal flash should be writeonce */ -#ifdef NVM_FLASH_WRITEONCE + #ifdef NVM_FLASH_WRITEONCE sel_sec = nvm_select_fresh_sector(part); -#endif + #endif ret = (void *)(PART_BOOT_ENDFLAGS - (WOLFBOOT_SECTOR_SIZE * sel_sec + (sizeof(uint32_t) + at))); } } else if (part == PART_UPDATE) { + #ifdef EXT_FLASH if (FLAGS_UPDATE_EXT()) { ext_flash_check_read(PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&ext_cache, sizeof(uint32_t)); ret = (uint8_t *)&ext_cache; - } else { + } + else + #endif + { /* only internal flash should be writeonce */ -#ifdef NVM_FLASH_WRITEONCE + #ifdef NVM_FLASH_WRITEONCE sel_sec = nvm_select_fresh_sector(part); -#endif + #endif ret = (void *)(PART_UPDATE_ENDFLAGS - (WOLFBOOT_SECTOR_SIZE * sel_sec + (sizeof(uint32_t) + at))); } @@ -441,9 +480,10 @@ static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at) } /** - * @brief Set the trailer at a specific address in an external flash. + * @brief Set the trailer at a specific address * - * This function sets the trailer at a specific address in an external flash. + * This function sets the trailer at a specific address in external or + * internal flash. * * @param[in] part Partition number. * @param[in] at Address offset. @@ -452,109 +492,67 @@ static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at) static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val) { if (part == PART_BOOT) { + #ifdef EXT_FLASH if (FLAGS_BOOT_EXT()) { ext_flash_check_write(PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&val, 1); - } else { + } + else + #endif + { trailer_write(part, PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at), val); } } else if (part == PART_UPDATE) { + #ifdef EXT_FLASH if (FLAGS_UPDATE_EXT()) { ext_flash_check_write(PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), (void *)&val, 1); - } else { + } + else + #endif + { trailer_write(part, PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), val); } } } /** - * @brief Set the partition magic trailer in an external flash. + * @brief Set the partition magic trailer * - * This function sets the partition magic trailer in an external flash. + * This function sets the partition magic trailer in external or internal flash. * * @param[in] part Partition number. */ static void RAMFUNCTION set_partition_magic(uint8_t part) { if (part == PART_BOOT) { + #ifdef EXT_FLASH if (FLAGS_BOOT_EXT()) { ext_flash_check_write(PART_BOOT_ENDFLAGS - sizeof(uint32_t), (void *)&wolfboot_magic_trail, sizeof(uint32_t)); - } else { + } + else + #endif + { partition_magic_write(part, PART_BOOT_ENDFLAGS - sizeof(uint32_t)); } } else if (part == PART_UPDATE) { + #ifdef EXT_FLASH if (FLAGS_UPDATE_EXT()) { ext_flash_check_write(PART_UPDATE_ENDFLAGS - sizeof(uint32_t), (void *)&wolfboot_magic_trail, sizeof(uint32_t)); - } else { + } + else + #endif + { partition_magic_write(part, PART_UPDATE_ENDFLAGS - sizeof(uint32_t)); } } } -#elif !defined(WOLFBOOT_FIXED_PARTITIONS) -static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at) -{ - (void)part; - (void)at; - return 0; -} -static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val) -{ - (void)part; - (void)at; - (void)val; - return; -} -static void RAMFUNCTION set_partition_magic(uint8_t part) -{ - (void)part; - return; -} - -#else -static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at) -{ - uint8_t *ret = NULL; - uint32_t sel_sec = 0; -#ifdef NVM_FLASH_WRITEONCE - sel_sec = nvm_select_fresh_sector(part); #endif - if (part == PART_BOOT) { - ret = (void *)(PART_BOOT_ENDFLAGS - - (WOLFBOOT_SECTOR_SIZE * sel_sec + (sizeof(uint32_t) + at))); - } - else if (part == PART_UPDATE) { - ret = (void *)(PART_UPDATE_ENDFLAGS - - (WOLFBOOT_SECTOR_SIZE * sel_sec + (sizeof(uint32_t) + at))); - } - return ret; -} - -static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val) -{ - if (part == PART_BOOT) { - trailer_write(part, PART_BOOT_ENDFLAGS - (sizeof(uint32_t) + at), val); - } - else if (part == PART_UPDATE) { - trailer_write(part, PART_UPDATE_ENDFLAGS - (sizeof(uint32_t) + at), val); - } -} - -static void RAMFUNCTION set_partition_magic(uint8_t part) -{ - if (part == PART_BOOT) { - partition_magic_write(part, PART_BOOT_ENDFLAGS - sizeof(uint32_t)); - } - else if (part == PART_UPDATE) { - partition_magic_write(part, PART_UPDATE_ENDFLAGS - sizeof(uint32_t)); - } -} -#endif /* EXT_FLASH */ -#endif /* MOCK_PARTITION_TRAILER */ +#endif /* !MOCK_PARTITION_TRAILER */ @@ -634,7 +632,17 @@ int RAMFUNCTION wolfBoot_set_partition_state(uint8_t part, uint8_t newst) return 0; } -int RAMFUNCTION wolfBoot_set_update_sector_flag(uint16_t sector, uint8_t newflag) +/** + * @brief Set the flag for sector + * + * This function sets the sector flag for update partition. + * + * @param[in] sector Sector number. + * @param[in] newflag Nibble (4-bits) for sector flag + * @return 0 on success, -1 on failure. + */ +int RAMFUNCTION wolfBoot_set_update_sector_flag(uint16_t sector, + uint8_t newflag) { uint32_t *magic; uint8_t *flags; @@ -678,6 +686,18 @@ int RAMFUNCTION wolfBoot_get_partition_state(uint8_t part, uint8_t *st) return 0; } +/** + * @brief Get the flag for sector + * + * This function retrieves the sector flag for update partition. + * + * User may override this is function for cases where the update partition + * flags are not at the end of partition + * + * @param[in] sector Sector number. + * @param[out] flag Nibble (4-bits) for sector flags + * @return 0 on success, -1 on failure. + */ int wolfBoot_get_update_sector_flag(uint16_t sector, uint8_t *flag) { uint32_t *magic; @@ -752,7 +772,7 @@ void RAMFUNCTION wolfBoot_update_trigger(void) uint8_t selSec = 0; #endif - /* if PART_UPDATE_ENDFLAGS stradles a sector, (all non FLAGS_HOME builds) + /* if PART_UPDATE_ENDFLAGS straddles a sector, (all non FLAGS_HOME builds) * align it to the correct sector */ if (PART_UPDATE_ENDFLAGS % WOLFBOOT_SECTOR_SIZE == 0) lastSector -= WOLFBOOT_SECTOR_SIZE; @@ -839,7 +859,7 @@ void RAMFUNCTION wolfBoot_success(void) uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr) { uint8_t *p = haystack; - uint16_t len; + uint16_t len, htype; const volatile uint8_t *max_p = (haystack - IMAGE_HEADER_OFFSET) + IMAGE_HEADER_SIZE; *ptr = NULL; @@ -848,33 +868,41 @@ uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr) return 0; } while ((p + 4) < max_p) { - if ((p[0] == 0) && (p[1] == 0)) { + htype = p[0] | (p[1] << 8); + if (htype == 0) { unit_dbg("Explicit end of options reached\n"); break; } - /* Sanity check to prevent dereferencing unaligned half-words and skip - * past padding bytes */ - if ((*p == HDR_PADDING) || ((((size_t)p) & 0x01) != 0)) { + /* skip unaligned half-words and padding bytes */ + if ((p[0] == HDR_PADDING) || ((((size_t)p) & 0x01) != 0)) { p++; continue; } + len = p[2] | (p[3] << 8); + /* check len */ if ((4 + len) > (uint16_t)(IMAGE_HEADER_SIZE - IMAGE_HEADER_OFFSET)) { unit_dbg("This field is too large (bigger than the space available " "in the current header)\n"); unit_dbg("%d %d %d\n", len, IMAGE_HEADER_SIZE, IMAGE_HEADER_OFFSET); break; } + /* check max pointer */ if (p + 4 + len > max_p) { unit_dbg("This field is too large and would overflow the image " "header\n"); break; } - if ((p[0] | (p[1] << 8)) == type) { - *ptr = (p + 4); + + /* skip header [type|len] */ + p += 4; + + if (htype == type) { + /* found, return pointer to data portion */ + *ptr = p; return len; } - p += 4 + len; + p += len; } return 0; } diff --git a/src/qspi_flash.c b/src/qspi_flash.c index 6a98161e4..04a4915e6 100644 --- a/src/qspi_flash.c +++ b/src/qspi_flash.c @@ -144,8 +144,8 @@ /* forward declarations */ static int qspi_wait_ready(void); static int qspi_status(uint8_t* status); -#ifdef TEST_FLASH -static int test_flash(void); +#ifdef TEST_EXT_FLASH +static int test_ext_flash(void); #endif static inline int qspi_command_simple(uint8_t fmode, uint8_t cmd, @@ -173,8 +173,8 @@ static int qspi_flash_read_id(uint8_t* id, uint32_t idSz) ret = qspi_command_simple(QSPI_MODE_READ, READ_ID_CMD, data, 3); #ifdef DEBUG_QSPI - wolfBoot_printf("Flash ID (ret %d): 0x%x\n", - ret, *((uint32_t*)data)); + wolfBoot_printf("Flash ID (ret %d): 0x%02x 0x%02x 0x%02x\n", + ret, data[0], data[1], data[2]); #endif /* optionally return id data */ @@ -352,8 +352,8 @@ uint16_t spi_flash_probe(void) qspi_enter_4byte_addr(); #endif -#ifdef TEST_FLASH - test_flash(); +#ifdef TEST_EXT_FLASH + test_ext_flash(); #endif return 0; } @@ -477,11 +477,14 @@ void spi_flash_release(void) #endif /* QSPI_FLASH || OCTOSPI_FLASH */ -#ifdef TEST_FLASH -/* Start Address for test - 2MB */ -#define TEST_ADDRESS (2 * 1024 * 1024) +#ifdef TEST_EXT_FLASH -static int test_flash(void) +#ifndef TEST_EXT_ADDRESS + /* Start Address for test - 2MB */ + #define TEST_EXT_ADDRESS (2 * 1024 * 1024) +#endif + +static int test_ext_flash(void) { int ret; uint32_t i; @@ -490,20 +493,20 @@ static int test_flash(void) #ifndef TEST_FLASH_READONLY /* Erase sector */ - ret = ext_flash_erase(TEST_ADDRESS, FLASH_SECTOR_SIZE); + ret = ext_flash_erase(TEST_EXT_ADDRESS, FLASH_SECTOR_SIZE); wolfBoot_printf("Sector Erase: Ret %d\n", ret); /* Write Page */ for (i=0; i 1 + wolfBoot_printf("check[%3d] %02x\n", i, pageData[i]); + #endif + if (pageData[i] != (i & 0xff)) { + wolfBoot_printf("Check Data @ %d failed\n", i); + return -1; + } + } + + wolfBoot_printf("Flash Test Passed\n"); + return ret; +} +#endif /* TEST_EXT_FLASH */ + #endif /* SPI_FLASH */ diff --git a/src/update_flash.c b/src/update_flash.c index 308f2fa96..468ac1827 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -822,7 +822,6 @@ void RAMFUNCTION wolfBoot_start(void) #ifndef DISABLE_BACKUP /* resume the final erase in case the power failed before it finished */ resumedFinalErase = wolfBoot_swap_and_final_erase(1); - if (resumedFinalErase != 0) #endif { @@ -831,9 +830,10 @@ void RAMFUNCTION wolfBoot_start(void) */ if ((bootRet == 0) && (bootState == IMG_STATE_TESTING)) { wolfBoot_update(1); + } + /* Check for new updates in the UPDATE partition or if we were * interrupted during the flags setting */ - } else if ((updateRet == 0) && (updateState == IMG_STATE_UPDATING)) { /* Check for new updates in the UPDATE partition */ wolfBoot_update(0); @@ -842,7 +842,7 @@ void RAMFUNCTION wolfBoot_start(void) if ((wolfBoot_open_image(&boot, PART_BOOT) < 0) || (wolfBoot_verify_integrity(&boot) < 0) || (wolfBoot_verify_authenticity(&boot) < 0) - ) { + ) { wolfBoot_printf("Boot failed: Hdr %d, Hash %d, Sig %d\n", boot.hdr_ok, boot.sha_ok, boot.signature_ok); wolfBoot_printf("Trying emergency update\n"); diff --git a/stage1/Makefile b/stage1/Makefile index 538aecc3f..48acdd7f8 100644 --- a/stage1/Makefile +++ b/stage1/Makefile @@ -20,6 +20,8 @@ LD_END_GROUP:=-Wl,--end-group V?=0 DEBUG?=0 DEBUG_UART?=0 +USE_GCC?=1 +USE_GCC_HEADLESS?=1 ifeq ($(ARCH),PPC) OBJS:= \ diff --git a/test-app/Makefile b/test-app/Makefile index 7dd98e8fc..74bc55c1d 100644 --- a/test-app/Makefile +++ b/test-app/Makefile @@ -10,6 +10,8 @@ CFLAGS+=-I. -I.. CFLAGS+=-I./wcs DEBUG?=1 DELTA_DATA_SIZE?=2000 +USE_GCC?=1 +USE_GCC_HEADLESS?=1 ifeq ($(SIGN),RSA2048) IMAGE_HEADER_SIZE:=512 @@ -38,10 +40,22 @@ ifeq ($(TARGET),ti_hercules) APP_OBJS:=app_$(TARGET).o ../test-app/libwolfboot.o CFLAGS+=-I"../include" else - CFLAGS+=-g -ggdb -Wall -Wstack-usage=1024 -ffreestanding -Wno-unused -DPLATFORM_$(TARGET) -I../include -nostartfiles - APP_OBJS:=app_$(TARGET).o led.o system.o timer.o ../test-app/libwolfboot.o -endif + CFLAGS+=-Wall -Wstack-usage=1024 -ffreestanding -Wno-unused -DPLATFORM_$(TARGET) -I../include -nostartfiles + CFLAGS+=-g + ifeq ($(USE_GCC),1) + CFLAGS+=-ggdb3 + else + CFLAGS+=-gstabs + endif + ifeq ($(ARCH),RENESAS_RX) + APP_OBJS:=app_renesas_rx.o ../test-app/libwolfboot.o ../src/boot_renesas.o ../src/boot_renesas_start.o ../hal/renesas-rx.o + LDFLAGS+=-ffreestanding -nostartfiles + CFLAGS+=-DWOLFBOOT_RENESAS_APP + else + APP_OBJS:=app_$(TARGET).o led.o system.o timer.o ../test-app/libwolfboot.o + endif +endif include ../arch.mk @@ -213,7 +227,12 @@ endif ifeq ($(SPI_FLASH),1) CFLAGS+=-D"SPI_FLASH" - APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET).o ../src/spi_flash.o + APP_OBJS+=../src/spi_flash.o + ifeq ($(ARCH),RENESAS_RX) + APP_OBJS+=../hal/spi/spi_drv_renesas_rx.o + else + APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET).o + endif endif ifeq ($(OCTOSPI_FLASH),1) @@ -223,7 +242,12 @@ endif ifeq ($(QSPI_FLASH),1) CFLAGS+=-D"QSPI_FLASH" - APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET).o ../src/qspi_flash.o + APP_OBJS+=../src/qspi_flash.o + ifeq ($(ARCH),RENESAS_RX) + APP_OBJS+=../hal/spi/spi_drv_renesas_rx.o + else + APP_OBJS+=../hal/spi/spi_drv_$(SPI_TARGET).o + endif endif ifeq ($(UART_FLASH),1) @@ -397,6 +421,14 @@ image.bin: image.elf @echo "\t[BIN] $@" $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O binary $^ $@ +image.hex: image.elf + @echo "\t[HEX] $@" + $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O ihex $^ $@ + +image.srec: image.elf + @echo "\t[SREC] $@" + $(Q)$(OBJCOPY) $(OBJCOPY_FLAGS) -O srec $^ $@ + image.elf: $(APP_OBJS) $(LSCRIPT) @echo "\t[LD] $@" $(Q)$(LD) $(LDFLAGS) $(APP_OBJS) $(OUTPUT_FLAG) $@ diff --git a/test-app/RENESAS_RX.ld b/test-app/RENESAS_RX.ld new file mode 100644 index 000000000..b9ef6b34d --- /dev/null +++ b/test-app/RENESAS_RX.ld @@ -0,0 +1,182 @@ +OUTPUT_ARCH(rx) +ENTRY(_PowerON_Reset) + +MEMORY +{ + RAM : ORIGIN = 0x0, LENGTH = 262144 + RAM2 : ORIGIN = 0x00800000, LENGTH = 393216 + ROM : ORIGIN = @WOLFBOOT_TEST_APP_ADDRESS@, LENGTH = @WOLFBOOT_TEST_APP_SIZE@ + OFS : ORIGIN = 0xFE7F5D00, LENGTH = 128 +} + +SECTIONS +{ + .fvectors : + { + KEEP(*(.fvectors)) + } > ROM + + .exvectors : + { + KEEP(*(.exvectors)) + } > ROM + + .rvectors : + { + _rvectors_start = .; + KEEP(*(.rvectors)) + _rvectors_end = .; + } > ROM + + .text : + { + *(.text) + *(.text.*) + *(P) + etext = .; + } > ROM + + .init : + { + KEEP(*(.init)) + __preinit_array_start = .; + KEEP(*(.preinit_array)) + __preinit_array_end = .; + __init_array_start = (. + 3) & ~ 3; + KEEP(*(.init_array)) + KEEP(*(SORT(.init_array.*))) + __init_array_end = .; + __fini_array_start = .; + KEEP(*(.fini_array)) + KEEP(*(SORT(.fini_array.*))) + __fini_array_end = .; + } > ROM + + .fini : + { + KEEP(*(.fini)) + } > ROM + + .got : + { + *(.got) + *(.got.plt) + } > ROM + + .rodata : + { + *(.rodata) + *(.rodata.*) + *(C_1) + *(C_2) + *(C) + _erodata = .; + } > ROM + + gcc_exceptions_table : + { + KEEP (*(.gcc_except_table)) + *(.gcc_except_table.*) + } > ROM + + .eh_frame_hdr : + { + *(.eh_frame_hdr) + } > ROM + + .eh_frame : + { + *(.eh_frame) + } > ROM + + .jcr : + { + *(.jcr) + } > ROM + + .tors : + { + __CTOR_LIST__ = .; + . = ALIGN(2); + ___ctors = .; + *(.ctors) + ___ctors_end = .; + __CTOR_END__ = .; + __DTOR_LIST__ = .; + ___dtors = .; + *(.dtors) + ___dtors_end = .; + __DTOR_END__ = .; + . = ALIGN(2); + _mdata = .; + } > ROM + + .data : AT(_mdata) + { + _data = .; + *(.data) + *(.data.*) + *(D) + *(D_1) + *(D_2) + _edata = .; + } > RAM + + .bss : + { + _bss = .; + *(.bss) + *(.bss.**) + *(COMMON) + *(B) + *(B_1) + *(B_2) + _ebss = .; + . = ALIGN(128); + _end = .; + } > RAM + + .ofs1 0xFE7F5D00: AT(0xFE7F5D00) + { + KEEP(*(.ofs1)) + } > OFS + .ofs2 0xFE7F5D10: AT(0xFE7F5D10) + { + KEEP(*(.ofs2)) + } > OFS + .ofs3 0xFE7F5D20: AT(0xFE7F5D20) + { + KEEP(*(.ofs3)) + } > OFS + .ofs4 0xFE7F5D40: AT(0xFE7F5D40) + { + KEEP(*(.ofs4)) + } > OFS + .ofs5 0xFE7F5D48: AT(0xFE7F5D48) + { + KEEP(*(.ofs5)) + } > OFS + .ofs6 0xFE7F5D50: AT(0xFE7F5D50) + { + KEEP(*(.ofs6)) + } > OFS + .ofs7 0xFE7F5D64: AT(0xFE7F5D64) + { + KEEP(*(.ofs7)) + } > OFS + .ofs8 0xFE7F5D70: AT(0xFE7F5D70) + { + KEEP(*(.ofs8)) + } > OFS +} + + +/* reserve 16KB user stack */ +PROVIDE(_ustack = ORIGIN(RAM) + LENGTH(RAM) - 0x4000 ); +/* reserve 4KB interrupt stack */ +PROVIDE(_istack = ORIGIN(RAM) + LENGTH(RAM) - 0x4000 - 0x1000 ); + +_wolfboot_partition_boot_address = @WOLFBOOT_PARTITION_BOOT_ADDRESS@; +_wolfboot_partition_size = @WOLFBOOT_PARTITION_SIZE@; +_wolfboot_partition_update_address = @WOLFBOOT_PARTITION_UPDATE_ADDRESS@; +_wolfboot_partition_swap_address = @WOLFBOOT_PARTITION_SWAP_ADDRESS@; diff --git a/test-app/app_renesas_rx.c b/test-app/app_renesas_rx.c new file mode 100644 index 000000000..aa93c9a63 --- /dev/null +++ b/test-app/app_renesas_rx.c @@ -0,0 +1,151 @@ +/* app_renesas_rx.c + * + * Test bare-metal application. + * + * Copyright (C) 2024 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 + */ + +#include +#include +#include +#include +#include "hal.h" +#include "printf.h" +#include "wolfboot/wolfboot.h" + +/* route stdout to UART */ +int write(int fileno, char *buf, int count) +{ + (void)fileno; + uart_write(buf, count); + return count; +} + +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 void printPart(uint8_t *part) +{ + uint8_t *magic; + uint32_t ver; + uint8_t state; +#ifdef WOLFBOOT_DEBUG_PARTION + uint32_t *v; + int i; +#endif + + magic = part; + printf("Magic: %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]); + ver = wolfBoot_get_blob_version(part); + printf("Version: %02x\n", (uint8_t)ver); + state = *(part + WOLFBOOT_PARTITION_SIZE - sizeof(uint32_t) - 1); + printf("Status: %02x (%s)\n", state, state2str(state)); + magic = part + WOLFBOOT_PARTITION_SIZE - sizeof(uint32_t); + printf("Tail Mgc: %c%c%c%c\n", magic[0], magic[1], magic[2], magic[3]); + +#ifdef WOLFBOOT_DEBUG_PARTION + v = (uint32_t*)part; + for (i = 0; i < 0x100/4; i++) { + if(i % 4 == 0) + print("\n%08x: ", (uint32_t)v+i*4); + print("%08x ", v[i]); + } +#endif +} + +static void printPartitions(void) +{ + printf("\n=== Boot Partition[%08x] ===\n", WOLFBOOT_PARTITION_BOOT_ADDRESS); + printPart((uint8_t*)WOLFBOOT_PARTITION_BOOT_ADDRESS); + printf("\n=== Update Partition[%08x] ===\n", WOLFBOOT_PARTITION_UPDATE_ADDRESS); + printPart((uint8_t*)WOLFBOOT_PARTITION_UPDATE_ADDRESS); +} + +int main(void) +{ + uint8_t firmware_version = 0; + + uart_init(); + +#if !defined(WOLFBOOT_RENESAS_TSIP) + printf("| ------------------------------------------------------------------- |\n"); + printf("| Renesas RX User Application in BOOT partition started by wolfBoot |\n"); + printf("| ------------------------------------------------------------------- |\n\n"); +#elif defined(WOLFBOOT_RENESAS_TSIP_SRCVERSION) + printf("| ------------------------------------------------------------------------------- |\n"); + printf("| Renesas RX w/ TSIP(SRC) User Application in BOOT partition started by wolfBoot |\n"); + printf("| ------------------------------------------------------------------------------- |\n\n"); +#else + printf("| ------------------------------------------------------------------------------- |\n"); + printf("| Renesas RX w/ TSIP(LIB) User Application in BOOT partition started by wolfBoot |\n"); + printf("| ------------------------------------------------------------------------------- |\n\n"); +#endif + + hal_init(); + + printPartitions(); + + /* The same as: wolfBoot_get_image_version(PART_BOOT); */ + firmware_version = wolfBoot_current_firmware_version(); + + printf("\nCurrent Firmware Version: %d\n", firmware_version); + + if (firmware_version >= 1) { + if (firmware_version == 1) { + printf("Hit any key to call wolfBoot_success the firmware.\n"); + getchar(); + + wolfBoot_success(); + printPartitions(); + + printf("\nHit any key to update the firmware.\n"); + getchar(); + + wolfBoot_update_trigger(); + printf("Firmware Update is triggered\n"); + printPartitions(); + } + else if (firmware_version == 2) { + printf("Hit any key to call wolfBoot_success the firmware.\n"); + getchar(); + + wolfBoot_success(); + printPartitions(); + } + } + else { + printf("Invalid Firmware Version\n"); + goto busy_idle; + } + +busy_idle: + /* busy wait */ + while (1) + ; + + return 0; +} diff --git a/tools/config.mk b/tools/config.mk index 4b1e8e88f..32e1abac0 100644 --- a/tools/config.mk +++ b/tools/config.mk @@ -79,6 +79,7 @@ ifeq ($(ARCH),) DISK_LOCK?=0 DISK_LOCK_PASSWORD?= FLASH_OTP_KEYSTORE?=0 + BIG_ENDIAN?=0 endif CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO_DRIVERS \ @@ -98,6 +99,6 @@ CONFIG_VARS:= ARCH TARGET SIGN HASH MCUXSDK MCUXPRESSO MCUXPRESSO_CPU MCUXPRESSO LMS_LEVELS LMS_HEIGHT LMS_WINTERNITZ \ WOLFBOOT_UNIVERSAL_KEYSTORE \ XMSS_PARAMS \ - ELF \ + ELF BIG_ENDIAN \ NXP_CUSTOM_DCD NXP_CUSTOM_DCD_OBJS \ FLASH_OTP_KEYSTORE diff --git a/tools/keytools/Makefile b/tools/keytools/Makefile index eb1527a24..bbb1f5b54 100644 --- a/tools/keytools/Makefile +++ b/tools/keytools/Makefile @@ -78,12 +78,16 @@ endif CFLAGS+=-DIMAGE_HEADER_SIZE=$(IMAGE_HEADER_SIZE) CFLAGS+=-DDELTA_UPDATES -ifeq ($(RENESAS_KEY),1) - CFLAGS+=-DWOLFBOOT_RENESAS_SCEPROTECT -else ifeq ($(RENESAS_KEY),2) - CFLAGS+=-DWOLFBOOT_RENESAS_TSIP -else ifeq ($(RENESAS_KEY),3) - CFLAGS+=-DWOLFBOOT_RENESAS_RSIP +ifneq ($(RENESAS_KEY),) + CFLAGS+=-DRENESAS_KEY=$(RENESAS_KEY) + + ifeq ($(RENESAS_KEY),1) + CFLAGS+=-DWOLFBOOT_RENESAS_SCEPROTECT + else ifeq ($(RENESAS_KEY),2) + CFLAGS+=-DWOLFBOOT_RENESAS_TSIP + else ifeq ($(RENESAS_KEY),3) + CFLAGS+=-DWOLFBOOT_RENESAS_RSIP + endif endif # Sources diff --git a/tools/keytools/keygen.c b/tools/keytools/keygen.c index 8b4234b12..9d2c67f71 100644 --- a/tools/keytools/keygen.c +++ b/tools/keytools/keygen.c @@ -131,123 +131,137 @@ struct keystore_slot { char pubkeyfile[PATH_MAX]= "src/keystore.c"; char pubkeyimg[PATH_MAX] = "keystore.der"; -const char Cfile_Banner[]="/* Keystore file for wolfBoot, automatically generated. Do not edit. */\n" - "/*\n" - " * This file has been generated and contains the public keys\n" - " * used by wolfBoot to verify the updates.\n" - " */" - "\n#include \n#include \"wolfboot/wolfboot.h\"\n#include \"keystore.h\"\n" - #if defined(WOLFBOOT_RENESAS_TSIP) || defined(WOLFBOOT_RENESAS_RSIP) - "#include \"user_settings.h\"\n" - #if defined(WOLFBOOT_RENESAS_TSIP) - "#include \"key_data.h\"\n" - #elif defined(WOLFBOOT_RENESAS_RSIP) - "#include \"rsa_pub.h\"\n" - #endif - #endif - "#ifdef WOLFBOOT_NO_SIGN\n\t#define NUM_PUBKEYS 0\n#else\n\n" - "#if !defined(KEYSTORE_ANY) && (KEYSTORE_PUBKEY_SIZE != KEYSTORE_PUBKEY_SIZE_%s)\n\t" - "#error Key algorithm mismatch. Remove old keys via 'make keysclean'\n" - "#else\n"; +const char Cfile_Banner[]= + "/* Keystore file for wolfBoot, automatically generated. Do not edit. */\n" + "/*\n" + " * This file has been generated and contains the public keys\n" + " * used by wolfBoot to verify the updates.\n" + " */" + "\n" + "#include \n" + "#include \"wolfboot/wolfboot.h\"\n" + "#include \"keystore.h\"\n" +#ifdef RENESAS_KEY + "#if defined(WOLFBOOT_RENESAS_TSIP) || defined(WOLFBOOT_RENESAS_RSIP)\n" + " #include \"user_settings.h\"\n" + " #if defined(WOLFBOOT_RENESAS_TSIP)\n" + " #include \"key_data.h\"\n" + " #elif defined(WOLFBOOT_RENESAS_RSIP)\n" + " #include \"rsa_pub.h\"\n" + " #endif\n" + "#endif\n" +#endif + "\n" + "#ifdef WOLFBOOT_NO_SIGN\n" + " #define NUM_PUBKEYS 0\n#else\n" + "\n" + "#if !defined(KEYSTORE_ANY) && (KEYSTORE_PUBKEY_SIZE != KEYSTORE_PUBKEY_SIZE_%s)\n" + " #error Key algorithm mismatch. Remove old keys via 'make keysclean'\n" + "#else\n"; const char Store_hdr[] = "\n" - "#if defined(__APPLE__) && defined(__MACH__)\n" - "#define KEYSTORE_SECTION __attribute__((section (\"__KEYSTORE,__keystore\")))\n" - "#elif defined(__CCRX__) /* Renesas RX */\n" - "#define KEYSTORE_SECTION\n" - "#elif defined(TARGET_x86_64_efi)\n" - "#define KEYSTORE_SECTION\n" - "#else\n" - "#define KEYSTORE_SECTION __attribute__((section (\".keystore\")))\n" - "#endif\n\n" - "#define NUM_PUBKEYS %d\n" - "const KEYSTORE_SECTION struct keystore_slot PubKeys[NUM_PUBKEYS] = {\n\n"; + "#if defined(__APPLE__) && defined(__MACH__)\n" + "#define KEYSTORE_SECTION __attribute__((section (\"__KEYSTORE,__keystore\")))\n" + "#elif defined(__CCRX__) /* Renesas RX */\n" + "#define KEYSTORE_SECTION\n" + "#elif defined(TARGET_x86_64_efi)\n" + "#define KEYSTORE_SECTION\n" + "#else\n" + "#define KEYSTORE_SECTION __attribute__((section (\".keystore\")))\n" + "#endif\n\n" + "#define NUM_PUBKEYS %d\n" + "const KEYSTORE_SECTION struct keystore_slot PubKeys[NUM_PUBKEYS] = {\n" + "\n"; const char Slot_hdr[] = - "\t /* Key associated to file '%s' */\n" - "\t{\n\t\t.slot_id = %d,\n\t\t.key_type = %s,\n" - "\t\t.part_id_mask = 0x%08X,\n\t\t.pubkey_size = %u,\n" - "\t\t.pubkey = {\n" -#if defined(WOLFBOOT_RENESAS_RSIP) - "#if !defined(WOLFBOOT_RENESAS_RSIP)\n" -#elif defined(WOLFBOOT_RENESAS_TSIP) - "#if !defined(WOLFBOOT_RENESAS_TSIP)\n" -#elif defined(WOLFBOOT_RENESAS_SCEPROTECT) - "#if !defined(WOLFBOOT_RENESAS_SCEPROTECT)\n" + " /* Key associated to file '%s' */\n" + " {\n" + " .slot_id = %d,\n" + " .key_type = %s,\n" + " .part_id_mask = 0x%08X,\n" + " .pubkey_size = %u,\n" + " .pubkey = {\n" +#ifdef RENESAS_KEY + "#if !defined(WOLFBOOT_RENESAS_RSIP) && \\\n" + " !defined(WOLFBOOT_RENESAS_TSIP) && \\\n" + " !defined(WOLFBOOT_RENESAS_SCEPROTECT)\n" #endif - "\t\t\t"; + " "; const char Pubkey_footer[] = -#if defined(WOLFBOOT_RENESAS_RSIP) || \ - defined(WOLFBOOT_RENESAS_TSIP) || \ - defined(WOLFBOOT_RENESAS_SCEPROTECT) - "\n\t#endif\n" + "\n" +#ifdef RENESAS_KEY + "#endif" #endif - "\n\t\t},"; -const char Slot_footer[] = "\n\t},\n\n"; -const char Store_footer[] = "\n};\n\n"; + "\n" + "\n" + " },"; +const char Slot_footer[] = "\n" + " },\n" + "\n"; +const char Store_footer[] = "\n" + "};" + "\n" + "\n"; const char Keystore_API[] = - "int keystore_num_pubkeys(void)\n" - "{\n" - " return NUM_PUBKEYS;\n" - "}\n\n" - #if defined(WOLFBOOT_RENESAS_SCEPROTECT) - "uint32_t *keystore_get_buffer(int id)\n" - "{\n" - " (void)id;\n" - " return (uint32_t *)RENESAS_SCE_INSTALLEDKEY_ADDR;\n" - "}\n\n" - "int keystore_get_size(int id)\n" - "{\n" - " return (int)260;\n" - "}\n\n" - #elif defined(WOLFBOOT_RENESAS_TSIP) - "uint32_t *keystore_get_buffer(int id)\n" - "{\n" - " (void)id;\n" - " return (uint32_t *)RENESAS_TSIP_INSTALLEDKEY_ADDR;\n" - "}\n\n" - "int keystore_get_size(int id)\n" - "{\n" - " return (int)ENCRYPTED_KEY_BYTE_SIZE;\n" - "}\n\n" - #elif defined(WOLFBOOT_RENESAS_RSIP) - "uint32_t *keystore_get_buffer(int id)\n" - "{\n" - " (void)id;\n" - " return (uint32_t *)RENESAS_RSIP_INSTALLEDKEY_RAM_ADDR;\n" - "}\n\n" - "int keystore_get_size(int id)\n" - "{\n" - " return (int)sizeof(rsa_public_t);\n" - "}\n\n" - #else - "uint8_t *keystore_get_buffer(int id)\n" - "{\n" - " if (id >= keystore_num_pubkeys())\n" - " return (uint8_t *)0;\n" - " return (uint8_t *)PubKeys[id].pubkey;\n" - "}\n\n" - "int keystore_get_size(int id)\n" - "{\n" - " if (id >= keystore_num_pubkeys())\n" - " return -1;\n" - " return (int)PubKeys[id].pubkey_size;\n" - "}\n\n" - #endif - "uint32_t keystore_get_mask(int id)\n" - "{\n" - " if (id >= keystore_num_pubkeys())\n" - " return 0;\n" - " return (int)PubKeys[id].part_id_mask;\n" - "}\n\n" - "uint32_t keystore_get_key_type(int id)\n" - "{\n" - " return PubKeys[id].key_type;\n" - "}\n\n" - - "#endif /* Keystore public key size check */\n" - "#endif /* WOLFBOOT_NO_SIGN */\n"; - +"int keystore_num_pubkeys(void)\n" + "{\n" + " return NUM_PUBKEYS;\n" + "}\n" + "\n" + "uint8_t *keystore_get_buffer(int id)\n" + "{\n" + " (void)id;\n" +#ifdef RENESAS_KEY + "#if defined(WOLFBOOT_RENESAS_SCEPROTECT)\n" + " return (uint8_t*)RENESAS_SCE_INSTALLEDKEY_ADDR;\n" + "#elif defined(WOLFBOOT_RENESAS_TSIP)\n" + " return (uint8_t*)RENESAS_TSIP_INSTALLEDKEY_ADDR;\n" + "#elif defined(WOLFBOOT_RENESAS_RSIP)\n" + " return (uint8_t*)RENESAS_RSIP_INSTALLEDKEY_RAM_ADDR;\n" + "#else\n" +#endif + " if (id >= keystore_num_pubkeys())\n" + " return (uint8_t *)0;\n" + " return (uint8_t *)PubKeys[id].pubkey;\n" +#ifdef RENESAS_KEY + "#endif\n" +#endif + "}\n" + "\n" + "int keystore_get_size(int id)\n" + "{\n" + " (void)id;\n" +#ifdef RENESAS_KEY + "#if defined(WOLFBOOT_RENESAS_SCEPROTECT)\n" + " return (int)260;\n" + "#elif defined(WOLFBOOT_RENESAS_TSIP)\n" + " return (int)ENCRYPTED_KEY_BYTE_SIZE;\n" + "#elif defined(WOLFBOOT_RENESAS_RSIP)\n" + " return (int)sizeof(rsa_public_t);\n" + "#else\n" +#endif + " if (id >= keystore_num_pubkeys())\n" + " return -1;\n" + " return (int)PubKeys[id].pubkey_size;\n" +#ifdef RENESAS_KEY + "#endif\n" +#endif + "}\n" + "\n" + "uint32_t keystore_get_mask(int id)\n" + "{\n" + " if (id >= keystore_num_pubkeys())\n" + " return 0;\n" + " return (int)PubKeys[id].part_id_mask;\n" + "}\n" + "\n" + "uint32_t keystore_get_key_type(int id)\n" + "{\n" + " return PubKeys[id].key_type;\n" + "}\n" + "\n" + "#endif /* Keystore public key size check */\n" + "#endif /* WOLFBOOT_NO_SIGN */\n"; static void usage(const char *pname) /* implies exit */ @@ -262,12 +276,11 @@ static void usage(const char *pname) /* implies exit */ static void fwritekey(uint8_t *key, int len, FILE *f) { int i; - for (i = 0; i < len; i++) - { + for (i = 0; i < len; i++) { if ((i % 8) == 0) { if (i != 0) fprintf(f, ","); - fprintf(f, "\n\t\t\t"); + fprintf(f, "\n "); } else { fprintf(f, ", ");