diff --git a/boot/zephyr/CMakeLists.txt b/boot/zephyr/CMakeLists.txt index 159962543..37900d2e3 100644 --- a/boot/zephyr/CMakeLists.txt +++ b/boot/zephyr/CMakeLists.txt @@ -439,9 +439,17 @@ if(CONFIG_BOOT_ENCRYPTION_KEY_FILE AND NOT CONFIG_BOOT_ENCRYPTION_KEY_FILE STREQ endif() if(CONFIG_MCUBOOT_CLEANUP_ARM_CORE) -zephyr_library_sources( - ${BOOT_DIR}/zephyr/arm_cleanup.c -) + # ARM Cortex-M + zephyr_library_sources_ifdef( + CONFIG_CPU_CORTEX_M + ${BOOT_DIR}/zephyr/cleanup/arm_cortex_m.c + ) + + # ARM Cortex-R + zephyr_library_sources_ifdef( + CONFIG_ARMV7_R + ${BOOT_DIR}/zephyr/cleanup/arm_cortex_r.c + ) endif() if(CONFIG_MCUBOOT_BOOT_BANNER) diff --git a/boot/zephyr/Kconfig b/boot/zephyr/Kconfig index acc0314a6..f2db6f137 100644 --- a/boot/zephyr/Kconfig +++ b/boot/zephyr/Kconfig @@ -344,7 +344,7 @@ config BOOT_SIGNATURE_KEY_FILE config MCUBOOT_CLEANUP_ARM_CORE bool "Perform core cleanup before chain-load the application" - depends on CPU_CORTEX_M + depends on CPU_CORTEX_M || ARMV7_R default y help This option instructs MCUboot to perform a clean-up of a set of diff --git a/boot/zephyr/arm_cleanup.c b/boot/zephyr/cleanup/arm_cortex_m.c similarity index 96% rename from boot/zephyr/arm_cleanup.c rename to boot/zephyr/cleanup/arm_cortex_m.c index 1ad793822..9b3f37c16 100644 --- a/boot/zephyr/arm_cleanup.c +++ b/boot/zephyr/cleanup/arm_cortex_m.c @@ -11,7 +11,9 @@ #include #endif -void cleanup_arm_nvic(void) { + +void cleanup_arm_interrupts(void) +{ /* Allow any pending interrupts to be recognized */ __ISB(); __disable_irq(); diff --git a/boot/zephyr/cleanup/arm_cortex_r.c b/boot/zephyr/cleanup/arm_cortex_r.c new file mode 100644 index 000000000..4611cd109 --- /dev/null +++ b/boot/zephyr/cleanup/arm_cortex_r.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 Nordic Semiconductor ASA + * Copyright (c) 2025 Siemens Mobility GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#ifdef CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER +extern void z_soc_irq_eoi(unsigned int irq); +#else +#include +#endif + +#define READ_COPROCESSOR_REGISTER(out, coproc, opc1, crn, crm, opc2) \ + __asm__ volatile("mrc " #coproc ", " #opc1 ", %0, " #crn ", " #crm ", " #opc2 "\n" : "=r" (out) ::); + +#define WRITE_COPROCESSOR_REGISTER(in, coproc, opc1, crn, crm, opc2) \ + __asm__ volatile("mcr " #coproc ", " #opc1 ", %0, " #crn ", " #crm ", " #opc2 "\n" :: "r" (in) :) + +void cleanup_arm_interrupts(void) +{ + /* Allow any pending interrupts to be recognized */ + __ISB(); + __disable_irq(); + + for (unsigned int i = 0; i < CONFIG_NUM_IRQS; ++i) { + irq_disable(i); + } + + for (unsigned int i = 0; i < CONFIG_NUM_IRQS; ++i) { +#ifdef CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER + z_soc_irq_eoi(i); +#else + arm_gic_eoi(i); +#endif /* CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ + } +} + +#if CONFIG_CPU_HAS_ARM_MPU +__weak void z_arm_clear_arm_mpu_config(void) +{ + uint8_t i; + uint8_t num_regions; + uint32_t mpu_type_register; + + /* Disable MPU */ + uint32_t val; + READ_COPROCESSOR_REGISTER(val, p15, 0, c1, c0, 0); + val &= ~BIT(0); + __DSB(); + + WRITE_COPROCESSOR_REGISTER(val, p15, 0, c1, c0, 0); + __ISB(); + + /* The number of MPU regions is stored in bits 15:8 of the MPU type register */ + READ_COPROCESSOR_REGISTER(mpu_type_register, p15, 0, c0, c0, 4); + num_regions = (uint8_t) ((mpu_type_register >> 8) & BIT_MASK(8)); + + for (i = 0; i < num_regions; ++i) { + /* Select region in the MPU and clear the region size field */ + WRITE_COPROCESSOR_REGISTER(i, p15, 0, c6, c2, 0); + WRITE_COPROCESSOR_REGISTER(0, p15, 0, c6, c1, 2); + } +} +#endif diff --git a/boot/zephyr/include/arm_cleanup.h b/boot/zephyr/include/arm_cleanup.h index cb3a679bc..8df50420b 100644 --- a/boot/zephyr/include/arm_cleanup.h +++ b/boot/zephyr/include/arm_cleanup.h @@ -11,7 +11,7 @@ /** * Cleanup interrupt priority and interupt enable registers. */ -void cleanup_arm_nvic(void); +void cleanup_arm_interrupts(void); #if defined(CONFIG_CPU_HAS_ARM_MPU) || defined(CONFIG_CPU_HAS_NXP_SYSMPU) /** diff --git a/boot/zephyr/main.c b/boot/zephyr/main.c index 758a90840..180236c74 100644 --- a/boot/zephyr/main.c +++ b/boot/zephyr/main.c @@ -3,6 +3,7 @@ * Copyright (c) 2020 Arm Limited * Copyright (c) 2021-2023 Nordic Semiconductor ASA * Copyright (c) 2025 Aerlync Labs Inc. + * Copyright (c) 2025 Siemens Mobility GmbH * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -32,7 +33,7 @@ #include #endif -#if defined(CONFIG_ARM) +#if defined(CONFIG_CPU_CORTEX_M) #include #endif @@ -142,8 +143,19 @@ extern void *_vector_table_pointer; #endif struct arm_vector_table { +#ifdef CONFIG_CPU_CORTEX_M uint32_t msp; uint32_t reset; +#else + uint32_t reset; + uint32_t undef_instruction; + uint32_t svc; + uint32_t abort_prefetch; + uint32_t abort_data; + uint32_t reserved; + uint32_t irq; + uint32_t fiq; +#endif }; static void do_boot(struct boot_rsp *rsp) @@ -183,7 +195,7 @@ static void do_boot(struct boot_rsp *rsp) usb_disable(); #endif #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE - cleanup_arm_nvic(); /* cleanup NVIC registers */ + cleanup_arm_interrupts(); /* Disable and acknowledge all interrupts */ #if defined(CONFIG_BOOT_DISABLE_CACHES) /* Flush and disable instruction/data caches before chain-loading the application */ @@ -226,10 +238,31 @@ static void do_boot(struct boot_rsp *rsp) #endif #endif /* CONFIG_BOOT_INTR_VEC_RELOC */ +#ifdef CONFIG_CPU_CORTEX_M __set_MSP(vt->msp); +#endif + #if CONFIG_MCUBOOT_CLEANUP_ARM_CORE +#ifdef CONFIG_CPU_CORTEX_M __set_CONTROL(0x00); /* application will configures core on its own */ __ISB(); +#else + /* Set mode to supervisor and A, I and F bit as described in the + * Cortex R5 TRM */ + __asm__ volatile( + " mrs r0, CPSR\n" + /* change mode bits to supervisor */ + " bic r0, #0x1f\n" + " orr r0, #0x13\n" + /* set the A, I and F bit */ + " mov r1, #0b111\n" + " lsl r1, #0x6\n" + " orr r0, r1\n" + + " msr CPSR, r0\n" + ::: "r0", "r1"); +#endif /* CONFIG_CPU_CORTEX_M */ + #endif #if CONFIG_MCUBOOT_CLEANUP_RAM __asm__ volatile ( @@ -257,7 +290,18 @@ static void do_boot(struct boot_rsp *rsp) : "r0", "r1", "r2", "r3", "memory" ); #else + +#ifdef CONFIG_CPU_CORTEX_M ((void (*)(void))vt->reset)(); +#else + /* Some ARM CPUs like the Cortex-R5 can run in thumb mode but reset into ARM + * mode (depending on a CPU signal configurations). To do the switch into ARM + * mode, if needed, an explicit branch with exchange instruction set + * instruction is needed + */ + __asm__("bx %0\n" : : "r" (&vt->reset)); +#endif + #endif } diff --git a/docs/release-notes.d/add-cortex-r-support-00-basic.md b/docs/release-notes.d/add-cortex-r-support-00-basic.md new file mode 100644 index 000000000..a7005af5c --- /dev/null +++ b/docs/release-notes.d/add-cortex-r-support-00-basic.md @@ -0,0 +1 @@ +- Added support for booting Cortex-R5 images diff --git a/docs/release-notes.d/add-cortex-r-support-01-cleanup-core.md b/docs/release-notes.d/add-cortex-r-support-01-cleanup-core.md new file mode 100644 index 000000000..27b5039d0 --- /dev/null +++ b/docs/release-notes.d/add-cortex-r-support-01-cleanup-core.md @@ -0,0 +1 @@ +- Add support for cleaning up the Cortex-R core before final jumping