From 4cbfdf8cf1734afb0e5a22981227322949b83e64 Mon Sep 17 00:00:00 2001 From: Daniele Lacamera Date: Fri, 23 Aug 2024 07:05:03 +0200 Subject: [PATCH] [SAMA5D3] Port for 32bit Cortex-A --- Makefile | 4 ++ arch.mk | 141 ++++++++++++++++++++++------------------- docs/Targets.md | 46 ++++++++++++++ hal/sama5d3.c | 94 +++++++++++++++++++++++++++ hal/sama5d3.ld | 53 ++++++++++++++++ src/boot_arm32.c | 100 +++++++++++++++++++++++++++++ src/boot_arm32_start.S | 98 ++++++++++++++++++++++++++++ 7 files changed, 472 insertions(+), 64 deletions(-) create mode 100644 hal/sama5d3.c create mode 100644 hal/sama5d3.ld create mode 100644 src/boot_arm32.c create mode 100644 src/boot_arm32_start.S diff --git a/Makefile b/Makefile index d803e91e..3accc2b4 100644 --- a/Makefile +++ b/Makefile @@ -130,6 +130,10 @@ ifeq ($(TARGET),nxp_t1024) MAIN_TARGET:=factory_wstage1.bin endif +ifeq ($(TARGET),sama5d3) + MAIN_TARGET:=wolfboot.bin +endif + ifeq ($(FLASH_OTP_KEYSTORE),1) MAIN_TARGET+=tools/keytools/otp/otp-keystore-primer.bin endif diff --git a/arch.mk b/arch.mk index 92dbe831..f37ca9d1 100644 --- a/arch.mk +++ b/arch.mk @@ -70,7 +70,6 @@ ifeq ($(ARCH),ARM) CROSS_COMPILE?=arm-none-eabi- CFLAGS+=-mthumb -mlittle-endian -mthumb-interwork -DARCH_ARM LDFLAGS+=-mthumb -mlittle-endian -mthumb-interwork - OBJS+=src/boot_arm.o ## Target specific configuration ifeq ($(TARGET),samr21) @@ -176,88 +175,102 @@ ifeq ($(ARCH),ARM) SPI_TARGET=stm32 endif - ## Cortex-M CPU -ifeq ($(CORTEX_M33),1) - CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33 - LDFLAGS+=-mcpu=cortex-m33 - ifeq ($(TZEN),1) - OBJS+=hal/stm32_tz.o - CFLAGS+=-mcmse - ifeq ($(WOLFCRYPT_TZ),1) - SECURE_OBJS+=./src/wc_callable.o - SECURE_OBJS+=./lib/wolfssl/wolfcrypt/src/random.o - CFLAGS+=-DWOLFCRYPT_SECURE_MODE - SECURE_LDFLAGS+=-Wl,--cmse-implib -Wl,--out-implib=./src/wc_secure_calls.o - endif - endif # TZEN=1 - ifeq ($(NO_ASM),1) - ifeq ($(SPMATH),1) - ifeq ($(NO_ASM),1) - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o - else - CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o - endif - endif - else - ifeq ($(SPMATH),1) - CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o - endif + ifeq ($(TARGET),sama5d3) + CORTEX_A5=1 endif + +## Cortex CPU + +ifeq ($(CORTEX_A5),1) + CFLAGS+=-mcpu=cortex-a5 -mtune=cortex-a5 -mfpu=vfpv4-d16 -static -z noexecstack + LDLAGS+=-mcpu=cortex-a5 -mtune=cortex-a5 -mtune=cortex-a5 -mfpu=vfpv4-d16 -static -z noexecstack -Ttext 0x300000 + # Cortex-A uses boot_arm32.o + OBJS+=src/boot_arm32.o src/boot_arm32_start.o + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o else - ifeq ($(CORTEX_M7),1) - CFLAGS+=-mcpu=cortex-m7 - LDFLAGS+=-mcpu=cortex-m7 - ifeq ($(SPMATH),1) - ifeq ($(NO_ASM),1) - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o - else - CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o + # All others use boot_arm.o + OBJS+=src/boot_arm.o + ifeq ($(CORTEX_M33),1) + CFLAGS+=-mcpu=cortex-m33 -DCORTEX_M33 + LDFLAGS+=-mcpu=cortex-m33 + ifeq ($(TZEN),1) + OBJS+=hal/stm32_tz.o + CFLAGS+=-mcmse + ifeq ($(WOLFCRYPT_TZ),1) + SECURE_OBJS+=./src/wc_callable.o + SECURE_OBJS+=./lib/wolfssl/wolfcrypt/src/random.o + CFLAGS+=-DWOLFCRYPT_SECURE_MODE + SECURE_LDFLAGS+=-Wl,--cmse-implib -Wl,--out-implib=./src/wc_secure_calls.o endif - endif - else - ifeq ($(CORTEX_M0),1) - CFLAGS+=-mcpu=cortex-m0 - LDFLAGS+=-mcpu=cortex-m0 + endif # TZEN=1 + ifeq ($(NO_ASM),1) ifeq ($(SPMATH),1) ifeq ($(NO_ASM),1) MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o else - CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_THUMB_ASM - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_armthumb.o + CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o endif endif else - ifeq ($(CORTEX_M3),1) - - CFLAGS+=-mcpu=cortex-m3 - LDFLAGS+=-mcpu=cortex-m3 + ifeq ($(SPMATH),1) + CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o + endif + endif + else + ifeq ($(CORTEX_M7),1) + CFLAGS+=-mcpu=cortex-m7 + LDFLAGS+=-mcpu=cortex-m7 + ifeq ($(SPMATH),1) + ifeq ($(NO_ASM),1) + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o + else + CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o + endif + endif + else + ifeq ($(CORTEX_M0),1) + CFLAGS+=-mcpu=cortex-m0 + LDFLAGS+=-mcpu=cortex-m0 + ifeq ($(SPMATH),1) + ifeq ($(NO_ASM),1) + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o + else + CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_THUMB_ASM + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_armthumb.o + endif + endif + else + ifeq ($(CORTEX_M3),1) + CFLAGS+=-mcpu=cortex-m3 + LDFLAGS+=-mcpu=cortex-m3 + ifeq ($(NO_ASM),1) + ifeq ($(SPMATH),1) + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o + endif + else + ifeq ($(SPMATH),1) + CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM -DWOLFSSL_SP_NO_UMAAL + MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o + endif + endif + else + # default Cortex M4 + CFLAGS+=-mcpu=cortex-m4 + LDFLAGS+=-mcpu=cortex-m4 ifeq ($(NO_ASM),1) ifeq ($(SPMATH),1) MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o endif else + CFLAGS+=-fomit-frame-pointer # required with debug builds only ifeq ($(SPMATH),1) - CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM -DWOLFSSL_SP_NO_UMAAL + CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o endif endif - else - # default Cortex M4 - CFLAGS+=-mcpu=cortex-m4 - LDFLAGS+=-mcpu=cortex-m4 - ifeq ($(NO_ASM),1) - ifeq ($(SPMATH),1) - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_c32.o - endif - else - CFLAGS+=-fomit-frame-pointer # required with debug builds only - ifeq ($(SPMATH),1) - CFLAGS+=-DWOLFSSL_SP_ASM -DWOLFSSL_SP_ARM_CORTEX_M_ASM - MATH_OBJS += ./lib/wolfssl/wolfcrypt/src/sp_cortexm.o - endif endif endif endif diff --git a/docs/Targets.md b/docs/Targets.md index c100d452..bf570c48 100644 --- a/docs/Targets.md +++ b/docs/Targets.md @@ -8,6 +8,7 @@ This README describes configuration of supported targets. * [Cypress PSoC-6](#cypress-psoc-6) * [Infineon AURIX TC3xx](#infineon-aurix-tc3xx) * [Intel x86-64 Intel FSP](#intel-x86_64-with-intel-fsp-support) +* [Microchip SAMA5D3](#microchip-sama5d3) * [Microchip SAME51](#microchip-same51) * [NXP Kinetis](#nxp-kinetis) * [NXP LPC54xxx](#nxp-lpc54xxx) @@ -1405,6 +1406,51 @@ the monitor command sequence below: (gdb) mon psoc6 reset_halt ``` + +## Microchip SAMA5D3 + +SAMA5D3 is a Cortex-A5 Microprocessor. The ATSAMA5D3-XPLAINED is the evaluation +board used for wolfBoot port, which also equips a 2MB NAND flash. WolfBoot +replaces the default first stage bootloader (at91bootstrap). + +### Building wolfBoot + +An example configuration file is provided. + +`cp config/examples/sama5d3.config .config` + +Run make to build wolfBoot.bin and the test application + +`make` + +### Programming wolfboot.bin into NAND flash + +To flash any firmware image into the device NVMs, you need the tool `sam-ba`, +distributed by Microchip. + +This procedure has been tested using sam-ba v.3.8 using ATSAMA5D3-XPLAINED board, +with JP6 (aka the `SPI_CS` jumper) removed, so the system boots from NAND by +default. + +Step 1: install the tool, connect a J-Link device to the J24 JTAG connector then run the +following command to activate "lowlevel" mode: + +`sam-ba -p j-link -b sama5d3-xplained -t 5 -a lowlevel` + +Step 2: erase the entire NAND flash: + +`sam-ba -p j-link -b sama5d3-xplained -t 5 -a nandflash -c erase` + +Step 3: program `wolfboot.bin` to the beginning of the flash: + +`sam-ba -p j-link -b sama5d3-xplained -t 5 -a nandflash -c writeboot:wolfboot.bin` + +### Programming the test application into NAND flash + +(TODO) + + + ## Microchip SAME51 SAME51 is a Cortex-M4 microcontroller with a dual-bank, 1MB flash memory divided diff --git a/hal/sama5d3.c b/hal/sama5d3.c new file mode 100644 index 00000000..cce4054f --- /dev/null +++ b/hal/sama5d3.c @@ -0,0 +1,94 @@ +/* atsama5d3.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 + */ + +#include +#include +#include +#include "image.h" +#ifndef ARCH_ARM +# error "wolfBoot atsama5d3 HAL: wrong architecture selected. Please compile with ARCH=ARM." +#endif + +#define TEST_ENCRYPT + +/* Fixed addresses */ +extern void *kernel_addr, *update_addr, *dts_addr; + +void* hal_get_primary_address(void) +{ + return (void*)&kernel_addr; +} + +void* hal_get_update_address(void) +{ + return (void*)&update_addr; +} + +void* hal_get_dts_address(void) +{ + return (void*)&dts_addr; +} + +void* hal_get_dts_update_address(void) +{ + return NULL; /* Not yet supported */ +} + +/* QSPI functions */ +void qspi_init(uint32_t cpu_clock, uint32_t flash_freq) +{ +} + + +void zynq_init(uint32_t cpu_clock) +{ +} + + + +/* public HAL functions */ +void hal_init(void) +{ +} + +void hal_prepare_boot(void) +{ +} + + +int RAMFUNCTION hal_flash_write(uintptr_t address, const uint8_t *data, int len) +{ + return 0; +} + +void RAMFUNCTION hal_flash_unlock(void) +{ +} + +void RAMFUNCTION hal_flash_lock(void) +{ +} + + +int RAMFUNCTION hal_flash_erase(uintptr_t address, int len) +{ + return 0; +} diff --git a/hal/sama5d3.ld b/hal/sama5d3.ld new file mode 100644 index 00000000..b9fd3fbc --- /dev/null +++ b/hal/sama5d3.ld @@ -0,0 +1,53 @@ +OUTPUT_FORMAT("elf32-littlearm") +OUTPUT_ARCH(arm) + +MEMORY +{ + DDR_MEM(rwx): ORIGIN = 0x00300000, LENGTH = 0x000100000 +} + +ENTRY(reset_vector_entry) +SECTIONS +{ + .text : { + _start_text = .; + *(.text) + *(.rodata) + *(.rodata*) + . = ALIGN(4); + *(.glue_7) + . = ALIGN(4); + *(.eh_frame) + . = ALIGN(4); + _end_text = . ; + } + + /* collect all initialized .data sections */ + /* .data : AT ( ADDR (.text) + SIZEOF (.text) SIZEOF (.ARM.*) { */ + + . = ALIGN(4); + .dummy : { + _edummy = .; + } + + .data : AT (LOADADDR(.dummy)) { + _start_data = .; + *(.vectors) + *(.data) + _end_data = .; + } + + /* collect all uninitialized .bss sections */ + .bss (NOLOAD) : { + . = ALIGN(4); + _start_bss = .; + *(.bss) + _end_bss = .; + } +} +_romsize = _end_data - _start_text; +_sramsize = _end_bss - _start_text; +END_STACK = _start_text; +_stack_top = ORIGIN(DDR_MEM) + LENGTH(DDR_MEM); +end = .; /* define a global symbol marking the end of application */ + diff --git a/src/boot_arm32.c b/src/boot_arm32.c new file mode 100644 index 00000000..5502ff15 --- /dev/null +++ b/src/boot_arm32.c @@ -0,0 +1,100 @@ +/* boot_arm32.c + * + * Bring up, vectors and do_boot for 32bit Cortex-A microprocessors. + * + * 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 "image.h" +#include "loader.h" +#include "wolfboot/wolfboot.h" + +extern unsigned int __bss_start__; +extern unsigned int __bss_end__; +static volatile unsigned int cpu_id; +extern unsigned int *END_STACK; + +extern void main(void); + +void boot_entry_C(void) +{ + register unsigned int *dst; + /* Initialize the BSS section to 0 */ + dst = &__bss_start__; + while (dst < (unsigned int *)&__bss_end__) { + *dst = 0U; + dst++; + } + + /* Run wolfboot! */ + main(); +} + +/* This is the main loop for the bootloader. + * + * It performs the following actions: + * - Call the application entry point + * + */ + +#ifdef MMU +void RAMFUNCTION do_boot(const uint32_t *app_offset, const uint32_t* dts_offset) +#else +void RAMFUNCTION do_boot(const uint32_t *app_offset) +#endif +{ + /* Set application address via r4 */ + asm volatile("mov r4, %0" : : "r"(app_offset)); + +#ifdef MMU + /* Move the dts pointer to r5 (as first argument) */ + asm volatile("mov r5, %0" : : "r"(dts_offset)); +#else + asm volatile("mov r5, 0"); +#endif + + /* Zero registers r1, r2, r3 */ + asm volatile("mov r3, 0"); + asm volatile("mov r2, 0"); + asm volatile("mov r1, 0"); + + /* Move the dts pointer to r0 (as first argument) */ + asm volatile("mov r0, r5"); + + /* Unconditionally jump to app_entry at r4 */ + asm volatile("bx r4"); +} + +#ifdef RAM_CODE + +#define AIRCR *(volatile uint32_t *)(0xE000ED0C) +#define AIRCR_VKEY (0r05FA << 16) +#define AIRCR_SYSRESETREQ (1 << 2) + +void RAMFUNCTION arch_reboot(void) +{ + AIRCR = AIRCR_SYSRESETREQ | AIRCR_VKEY; + while(1) + ; + wolfBoot_panic(); + +} +#endif diff --git a/src/boot_arm32_start.S b/src/boot_arm32_start.S new file mode 100644 index 00000000..57520ba7 --- /dev/null +++ b/src/boot_arm32_start.S @@ -0,0 +1,98 @@ +/** + * Arm32 (32bit Cortex-A) boot up + * 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 + */ +.section start + .text + +/* startup entry point */ + .globl reset_vector_entry + .align 4 +reset_vector_entry: +/* Exception vectors (should be a branch to be detected as a valid code by the rom */ +_exception_vectors: + b isr_reset /* reset */ + b isr_empty /* Undefined Instruction */ + b isr_swi /* Software Interrupt */ + b isr_pabt /* Prefetch Abort */ + b dabt_vector /* Data Abort */ +.word _romsize /* Size of the binary for ROMCode loading */ + b isr_irq /* IRQ : read the AIC */ + b isr_fiq /* FIQ */ + +isr_empty: + b isr_empty +isr_swi: + b isr_swi +isr_pabt: + b isr_pabt +dabt_vector: + subs pc, r14, #4 /* return */ + nop +isr_rsvd: + b isr_rsvd +isr_irq: + b isr_irq +isr_fiq: + b isr_fiq + + +/* Reset handler procedure. Prepare the memory and call main() */ +isr_reset: + /* Initialize the stack pointer */ + ldr sp,=_stack_top + /* Save BootROM supplied boot source information to stack */ + push {r4} + + /* Copy the data section */ + ldr r2, =_lp_data + ldmia r2, {r1, r3, r4} + 1: + cmp r3, r4 + ldrcc r2, [r1], #4 + strcc r2, [r3], #4 + bcc 1b + + /* Zero bss area */ + adr r2, _lp_bss + ldmia r2, {r3, r4} + mov r2, #0 + 1: + cmp r3, r4 + strcc r2, [r3], #4 + bcc 1b + + /* Jump to main() */ + ldr r4, = main + mov lr, pc + bx r4 + + /* main() should never return */ +_panic: + b _panic + +.align +_lp_data: +.word _start_data +.word _end_data + +_lp_bss: +.word _start_bss +.word _end_bss +