diff --git a/.gitignore b/.gitignore index 598c26416..4fc8d00c1 100644 --- a/.gitignore +++ b/.gitignore @@ -227,6 +227,13 @@ IDE/Renesas/e2studio/RX72N/app_RenesasRX01/src/smc_gen IDE/Renesas/e2studio/RX72N/wolfBoot/HardwareDebug IDE/Renesas/e2studio/RX72N/wolfBoot/src/smc_gen +# IDE pico-sdk build directories +IDE/pico-sdk/rp2350/wolfboot/build +IDE/pico-sdk/rp2350/test-app/build + +# Third party test application distributed off-tree +IDE/pico-sdk/rp2350/test-app/blink.c + # Renesas Libraries lib/r_bsp lib/r_config diff --git a/IDE/pico-sdk/rp2350/README.md b/IDE/pico-sdk/rp2350/README.md new file mode 100644 index 000000000..b3290fcd0 --- /dev/null +++ b/IDE/pico-sdk/rp2350/README.md @@ -0,0 +1,95 @@ +## wolfBoot port for rp2350 (Raspberry pi pico 2) + +### Requirements + +#### External debugger + +As the two images (bootloader + application) are stored in different areas in +the flash memory, a SWD connector is required to upload the binary images into +the flash, as opposed to the default bootloader, allowing to upload non-signed +applications into a storage device + +#### PicoSDK + +Clone the repository from raspberrypi's github: + +``` +git clone https://github.com/raspberrypi/pico-sdk.git +``` + +Export the `PICO_SDK_PATH` environment variable to point to the pico-sdk directory: + +``` +export PICO_SDK_PATH=/path/to/pico-sdk +``` + +### Configuring wolfBoot to build with pico-sdk + +From wolfBoot root directory, copy the example configuration: + +``` +cp config/examples/rp2350.config .config +``` + +By default, the config file indicates the following partition layout: + +``` +wolfBoot partition: 256 KB, at address 0x10000000 to 0x1003FFFF +Boot partition: 768 KB, at address 0x10040000 to 0x1007FFFF +Update partition: 768 KB, at address 0x10100000 to 0x1013FFFF +Swap space: 4 KB, at address 0x101C0000 to 0x101C0FFF +Unused flash space: 252 KB, at address 0x101C1000 to 0x101FFFFF +``` + +You can now edit the .config file to change partition sizes/offsets, algorithms, +add/remove features, etc. + +When the configuration is complete, run `make`. This will: + +- Build the key tools (keygen & sign): +- Generate the configuration header `target.h` +- Generate a new keypair (only once), and place the public key in the +keystore + +The environment has now been prepared to build and flash the two images +(wolfBoot + test application). + +### Building and uploading wolfBoot.bin + +After preparing the configuration and creating the keypair, +return to this directory and run: + +``` +cd wolfboot +./build-wolfboot.sh +``` + +The script above will compile wolfboot as rp2350 second-stage bootloader. +This version of wolfboot incorporates the `.boot2` sequence needed to enable +the QSPI device, provided by the pico-sdk and always embedded in all +applications. + +wolfboot.bin contains the bootloader, configured as follows: + +### Building and uploading the application + +``` +cd test-app +./build-signed-app.sh +``` +The script above will compile the test application and sign it with the +wolfBoot private key. The signed application is then uploaded to the boot +partition of the flash memory, at address 0x10040000. + +The linker script included is modified to change the application entry point +from 0x10000000 to 0x10040400, which is the start of the application code, +taking into account the wolfBoot header size. + + +### Testing the application + +The application is a simple blinky example, which toggles the LED on the board +every 500ms. + +If the above steps are successful, the LED on the board should start blinking. + diff --git a/IDE/pico-sdk/rp2350/test-app/CMakeLists.txt b/IDE/pico-sdk/rp2350/test-app/CMakeLists.txt new file mode 100644 index 000000000..cd7825a58 --- /dev/null +++ b/IDE/pico-sdk/rp2350/test-app/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.13) +set(WOLFBOOT_PATH ../../../../) +set(CMAKE_CXX_COMPILER arm-none-eabi-gcc) + +include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + +set(PICOTOOL_FETCH_FROM_GIT_PATH ../wolfboot/build/picotool) +set(BOOT_STAGE2_FILE ${CMAKE_CURRENT_LIST_DIR}/boot2_empty.S) + +project(blink) + +# initialize the Raspberry Pi Pico SDK +pico_sdk_init() + + +add_executable(blink + blink.c +) + +target_link_libraries(blink pico_stdlib) + +# create map/bin/hex/uf2 file etc. +pico_add_extra_outputs(blink) + diff --git a/IDE/pico-sdk/rp2350/test-app/build-signed-app.sh b/IDE/pico-sdk/rp2350/test-app/build-signed-app.sh new file mode 100755 index 000000000..e96eaca48 --- /dev/null +++ b/IDE/pico-sdk/rp2350/test-app/build-signed-app.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +mkdir -p build +cd build +cmake .. -DPICO_SDK_PATH=$PICO_SDK_PATH -DPICO_PLATFORM=rp2350 +cat pico_flash_region.ld | sed -e "s/0x10000000/0x10040400/g" >pico_flash_region_wolfboot.ld +cp pico_flash_region_wolfboot.ld pico_flash_region.ld + +# Get off-tree source file from raspberry pico-examples +curl -o blink.c https://raw.githubusercontent.com/raspberrypi/pico-examples/refs/tags/sdk-2.1.0/blink/blink.c + +make clean && make + +IMAGE_HEADER_SIZE=1024 ../../../../../tools/keytools/sign --sha256 --ecc256 blink.bin \ + ../../../../../wolfboot_signing_private_key.der 1 + +cd .. + +JLinkExe -Device RP2350_M33_0 -If swd -Speed 4000 -CommanderScript flash_app.jlink diff --git a/IDE/pico-sdk/rp2350/test-app/flash_app.jlink b/IDE/pico-sdk/rp2350/test-app/flash_app.jlink new file mode 100644 index 000000000..d0d9e4bd1 --- /dev/null +++ b/IDE/pico-sdk/rp2350/test-app/flash_app.jlink @@ -0,0 +1,6 @@ +connect +r +loadfile build/blink_v1_signed.bin 0x10040000 +r +g +exit diff --git a/IDE/pico-sdk/rp2350/wolfboot/.gdbinit b/IDE/pico-sdk/rp2350/wolfboot/.gdbinit new file mode 100644 index 000000000..6facaeb01 --- /dev/null +++ b/IDE/pico-sdk/rp2350/wolfboot/.gdbinit @@ -0,0 +1,5 @@ +tar rem:3333 +file build/wolfboot.elf +add-symbol-file ../test-app/build/blink.elf +foc c + diff --git a/IDE/pico-sdk/rp2350/wolfboot/CMakeLists.txt b/IDE/pico-sdk/rp2350/wolfboot/CMakeLists.txt new file mode 100644 index 000000000..5ae1fb32b --- /dev/null +++ b/IDE/pico-sdk/rp2350/wolfboot/CMakeLists.txt @@ -0,0 +1,72 @@ +cmake_minimum_required(VERSION 3.13) +set(WOLFBOOT_PATH ../../../../) +set(CMAKE_CXX_COMPILER arm-none-eabi-gcc) + +include(${PICO_SDK_PATH}/pico_sdk_init.cmake) + +set(PICOTOOL_FETCH_FROM_GIT_PATH build/picotool) + +project(wolfboot) + +# initialize the Raspberry Pi Pico SDK +pico_sdk_init() + + +add_executable(wolfboot + ${WOLFBOOT_PATH}/src/image.c + ${WOLFBOOT_PATH}/src/loader.c + ${WOLFBOOT_PATH}/src/update_flash.c + ${WOLFBOOT_PATH}/src/keystore.c + ${WOLFBOOT_PATH}/src/libwolfboot.c + ${WOLFBOOT_PATH}/src/boot_arm.c + + ${WOLFBOOT_PATH}/hal/rp2350.c + + ${WOLFBOOT_PATH}/lib/wolfssl/wolfcrypt/src/sp_int.c + ${WOLFBOOT_PATH}/lib/wolfssl/wolfcrypt/src/sp_cortexm.c + ${WOLFBOOT_PATH}/lib/wolfssl/wolfcrypt/src/memory.c + ${WOLFBOOT_PATH}/lib/wolfssl/wolfcrypt/src/random.c + ${WOLFBOOT_PATH}/lib/wolfssl/wolfcrypt/src/sha256.c + ${WOLFBOOT_PATH}/lib/wolfssl/wolfcrypt/src/sha512.c + ${WOLFBOOT_PATH}/lib/wolfssl/wolfcrypt/src/aes.c + ${WOLFBOOT_PATH}/lib/wolfssl/wolfcrypt/src/ecc.c +) + +# Add cflags +target_compile_options(wolfboot PRIVATE + -D__WOLFBOOT + -D__ARM_ARCH_6M__ + -DWOLFSSL_USER_SETTINGS + -mcpu=cortex-m33 + -DCORTEX_M33 + -DWOLFSSL_SP_ASM + -DWOLFSSL_SP_ARM_CORTEX_M_ASM + -DWOLFSSL_ARM_ARCH=8 + -DARCH_FLASH_OFFSET=0x10000000 + -DWOLFBOOT_ORIGIN=0x10000000 + -DBOOTLOADER_PARTITION_SIZE=0x40000 + -DWOLFBOOT_ARCH_ARM + -DTARGET_rp2350 + -DWOLFBOOT_SIGN_ECC256 + -DRAM_CODE + -DFILL_BYTE=0xFF + -Os + -DWOLFBOOT_NO_MPU + -DWOLFBOOT_HASH_SHA256 + -DIMAGE_HEADER_SIZE=1024 + -Wstack-usage=7632 +) + + +target_include_directories(wolfboot PRIVATE + ${WOLFBOOT_PATH}/include + ${WOLFBOOT_PATH}/lib/wolfssl +) + +target_link_libraries(wolfboot pico_stdlib hardware_flash) + +pico_enable_stdio_usb(wolfboot 1) +pico_enable_stdio_uart(wolfboot 0) + + +pico_add_extra_outputs(wolfboot) diff --git a/IDE/pico-sdk/rp2350/wolfboot/build-wolfboot.sh b/IDE/pico-sdk/rp2350/wolfboot/build-wolfboot.sh new file mode 100755 index 000000000..8a96587a7 --- /dev/null +++ b/IDE/pico-sdk/rp2350/wolfboot/build-wolfboot.sh @@ -0,0 +1,10 @@ +#!/bin/bash +#cd ../../../.. && make keytools && make src/keystore.c && cd - +cd ../../../.. && make include/target.h && cd - +mkdir -p build +cd build +cmake .. -DPICO_SDK_PATH=$PICO_SDK_PATH -DPICO_PLATFORM=rp2350 +make clean && make +cd .. +JLinkExe -Device RP2350_M33_0 -If swd -Speed 4000 -CommanderScript erase.jlink +JLinkExe -Device RP2350_M33_0 -If swd -Speed 4000 -CommanderScript flash_wolfboot.jlink diff --git a/IDE/pico-sdk/rp2350/wolfboot/debug.sh b/IDE/pico-sdk/rp2350/wolfboot/debug.sh new file mode 100755 index 000000000..008ad0a8d --- /dev/null +++ b/IDE/pico-sdk/rp2350/wolfboot/debug.sh @@ -0,0 +1,2 @@ +#!/bin/bash +JLinkGDBServer -Device RP2350_M33_0 -If swd -Speed 4000 -port 3333 diff --git a/IDE/pico-sdk/rp2350/wolfboot/erase.jlink b/IDE/pico-sdk/rp2350/wolfboot/erase.jlink new file mode 100644 index 000000000..a4f1f72aa --- /dev/null +++ b/IDE/pico-sdk/rp2350/wolfboot/erase.jlink @@ -0,0 +1,6 @@ +connect +r +erase +r +h +exit diff --git a/IDE/pico-sdk/rp2350/wolfboot/flash_wolfboot.jlink b/IDE/pico-sdk/rp2350/wolfboot/flash_wolfboot.jlink new file mode 100644 index 000000000..bc0515010 --- /dev/null +++ b/IDE/pico-sdk/rp2350/wolfboot/flash_wolfboot.jlink @@ -0,0 +1,6 @@ +connect +r +loadfile build/wolfboot.bin 0x10000000 +r +g +exit diff --git a/Makefile b/Makefile index cf9fdec2d..fee715291 100644 --- a/Makefile +++ b/Makefile @@ -148,6 +148,10 @@ ifeq ($(TARGET),sama5d3) MAIN_TARGET:=wolfboot.bin test-app/image_v1_signed.bin endif +ifeq ($(TARGET),rp2350) + MAIN_TARGET:=include/target.h keytools wolfboot_signing_private_key.der pico-sdk-info +endif + ifeq ($(FLASH_OTP_KEYSTORE),1) MAIN_TARGET+=tools/keytools/otp/otp-keystore-primer.bin @@ -447,6 +451,9 @@ secondary: $(SECONDARY_PRIVATE_KEY) @echo "\t[AS-$(ARCH)] $@" $(Q)$(CC) $(CFLAGS) -c $(OUTPUT_FLAG) $@ $^ +pico-sdk-info: FORCE + @echo "To complete the build, check IDE/pico-sdk/rp2350" + FORCE: .PHONY: FORCE clean keytool_check diff --git a/arch.mk b/arch.mk index b517062f3..18de2e484 100644 --- a/arch.mk +++ b/arch.mk @@ -211,6 +211,21 @@ ifeq ($(ARCH),ARM) SPI_TARGET=stm32 endif + ifeq ($(TARGET),rp2350) + CORTEX_M33=1 + CFLAGS+=-Ihal + ARCH_FLASH_OFFSET=0x10000000 + WOLFBOOT_ORIGIN=0x10000000 + ifeq ($(TZEN),1) + LSCRIPT_IN=hal/$(TARGET).ld + else + LSCRIPT_IN=hal/$(TARGET)-ns.ld + endif + SPI_TARGET=raspberrypi_pico + CFLAGS+=-DPICO_SDK_PATH=$(PICO_SDK_PATH) + CFLAGS+=-I$(PICO_SDK_PATH)/src/common/pico_stdlib_headers/include + endif + ifeq ($(TARGET),sama5d3) CORTEX_A5=1 UPDATE_OBJS:=src/update_ram.o @@ -1070,7 +1085,7 @@ ifeq ($(TARGET),sim) CFLAGS+=-DWOLFSSL_SP_DIV_WORD_HALF endif ifeq ($(WOLFHSM_CLIENT),1) - WOLFHSM_CLIENT_OBJS += $(LIBDIR)/wolfHSM/port/posix/posix_transport_tcp.o + WOLFHSM_CLIENT_OBJS += $(LIBDIR)/wolfHSM/port/posix/posix_transport_tcp.o endif endif diff --git a/config/examples/rp2350.config b/config/examples/rp2350.config new file mode 100644 index 000000000..bf08911a6 --- /dev/null +++ b/config/examples/rp2350.config @@ -0,0 +1,25 @@ +ARCH?=ARM +TZEN?=0 +TARGET?=rp2350 +SIGN?=ECC256 +HASH?=SHA256 +DEBUG?=0 +VTOR?=1 +CORTEX_M33?=1 +NO_ASM?=0 +NO_MPU=1 +EXT_FLASH?=0 +SPI_FLASH?=0 +ALLOW_DOWNGRADE?=0 +SPMATH?=1 +RAM_CODE?=1 +WOLFBOOT_PARTITION_SIZE?=0xC0000 +WOLFBOOT_SECTOR_SIZE?=0x2000 +WOLFBOOT_PARTITION_BOOT_ADDRESS=0x10040000 +WOLFBOOT_PARTITION_UPDATE_ADDRESS=0x10100000 +WOLFBOOT_PARTITION_SWAP_ADDRESS=0x101C0000 + +PICO_SDK_PATH=/home/dan/src/pico-sdk + +# Use a larger image header size to enforce alignment requirements for the interrupt vector table +IMAGE_HEADER_SIZE?=1024 diff --git a/docs/Targets.md b/docs/Targets.md index 435088b57..6ccee1ae2 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -22,6 +22,7 @@ This README describes configuration of supported targets. * [NXP T1024 PPC](#nxp-qoriq-t1024-ppc) * [NXP T2080 PPC](#nxp-qoriq-t2080-ppc) * [Qemu x86-64 UEFI](#qemu-x86-64-uefi) +* [Raspberry Pi pico 2 (rp2350)](#raspberry-pi-pico-rp2350) * [Renesas RA6M4](#renesas-ra6m4) * [Renesas RX65N](#renesas-rx65n) * [Renesas RX72N](#renesas-rx72n) @@ -2510,6 +2511,10 @@ 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`. +## Raspberry Pi Pico rp2350 + +See instructions in [IDE/pico-sdk/rp2350/README.md](/IDE/pico-sdk/rp2350/README.md) + ## Renesas RX65N Tested on the: diff --git a/hal/rp2350.c b/hal/rp2350.c new file mode 100644 index 000000000..c47c4a71c --- /dev/null +++ b/hal/rp2350.c @@ -0,0 +1,61 @@ +/* rp2350.c + * + * Stubs for custom HAL implementation. Defines the + * functions used by wolfboot for a specific target. + * + * Copyright (C) 2021 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 "image.h" +#include "printf.h" + +#ifdef __WOLFBOOT +void hal_init(void) +{ +#ifdef PRINTF_ENABLED + stdio_init_all(); +#endif +} + +void hal_prepare_boot(void) +{ +} + +#endif + +int RAMFUNCTION hal_flash_write(uint32_t address, const uint8_t *data, int len) +{ + return 0; /* on success. */ +} + +void RAMFUNCTION hal_flash_unlock(void) +{ +} + +void RAMFUNCTION hal_flash_lock(void) +{ +} + +int RAMFUNCTION hal_flash_erase(uint32_t address, int len) +{ + return 0; /* on success. */ +} + diff --git a/src/boot_arm.c b/src/boot_arm.c index d975365c0..a1f2790e4 100644 --- a/src/boot_arm.c +++ b/src/boot_arm.c @@ -397,7 +397,7 @@ void isr_empty(void) -#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && defined(TZEN) # define isr_securefault isr_fault #else # define isr_securefault 0 @@ -446,7 +446,7 @@ void RAMFUNCTION do_boot(const uint32_t *app_offset) /* Update IV */ VTOR = ((uint32_t)app_offset); asm volatile("msr msplim, %0" ::"r"(0)); -# if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) +# if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U) && defined(TZEN) asm volatile("msr msp_ns, %0" ::"r"(app_end_stack)); /* Jump to non secure app_entry */ asm volatile("mov r7, %0" ::"r"(app_entry)); @@ -527,7 +527,7 @@ void (* const IV[])(void) = /* Fill with extra unused handlers */ #if defined(TARGET_stm32l5) || defined(TARGET_stm32u5) || \ - defined(TARGET_stm32h7) + defined(TARGET_stm32h7) || defined(TARGET_rp2350) isr_empty, isr_empty, isr_empty, diff --git a/src/update_flash.c b/src/update_flash.c index 20cc67cc0..3fbf83091 100644 --- a/src/update_flash.c +++ b/src/update_flash.c @@ -39,7 +39,12 @@ int WP11_Library_Init(void); #endif #ifdef RAM_CODE +#ifndef TARGET_rp2350 extern unsigned int _start_text; +#else +extern unsigned int __logical_binary_start; +unsigned int _start_text = (unsigned int)&__logical_binary_start; +#endif static volatile const uint32_t __attribute__((used)) wolfboot_version = WOLFBOOT_VERSION; #ifdef EXT_FLASH