Skip to content

Commit b26db4d

Browse files
committed
[nrf noup] boot/zephyr: nRF54h20 resume from S2RAM (hardened)
Application need special support in the bootloader in order to resume for suspend to RAM. MCUboot is immediate actor which redirects execution to the application (application reset vector) when wake-up from S2RAM is detected. Detection is based on HW (NRF_RESETINFO) and hardened using additional check over independent source of truth (variable with magic value). Thanks to above the application is resuming using its routines - instead of mocking that by routines compiled in by the MCUboot. Implementation is able to support only MCUboot modes with a swap. Direct-XIP is not handled as it require a way to run-time recognization of active application slot. Signed-off-by: Karol Lasończyk <[email protected]> Signed-off-by: Tomasz Chyrowicz <[email protected]> Signed-off-by: Andrzej Puzdrowski <[email protected]>
1 parent b6b46a7 commit b26db4d

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

boot/zephyr/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,10 @@ zephyr_library_sources(
491491
)
492492
endif()
493493

494+
if(CONFIG_SOC_NRF54H20_PM_S2RAM_OVERRIDE)
495+
zephyr_library_sources(${BOOT_DIR}/zephyr/nrf54h20_custom_s2ram.c)
496+
endif()
497+
494498
if(CONFIG_MCUBOOT_BOOT_BANNER)
495499
# Replace Zephyr's boot banner with the MCUboot one
496500
zephyr_sources(kernel/banner.c)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* Copyright (c) 2025 Nordic Semiconductor ASA
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
#include <stdbool.h>
7+
#include <zephyr/arch/common/pm_s2ram.h>
8+
#include <hal/nrf_resetinfo.h>
9+
#include "pm_s2ram.h"
10+
#include "power.h"
11+
12+
#include <zephyr/devicetree.h>
13+
#include <zephyr/storage/flash_map.h>
14+
15+
#include "bootutil/fault_injection_hardening.h"
16+
17+
#if DT_NODE_EXISTS(DT_NODELABEL(mcuboot_s2ram)) &&\
18+
DT_NODE_HAS_COMPAT(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region)
19+
/* Linker section name is given by `zephyr,memory-region` property of
20+
* `zephyr,memory-region` compatible DT node with nodelabel `mcuboot_s2ram`.
21+
*/
22+
__attribute__((section(DT_PROP(DT_NODELABEL(mcuboot_s2ram), zephyr_memory_region))))
23+
volatile struct mcuboot_resume_s mcuboot_resume;
24+
#else
25+
#error "mcuboot resume support section not defined in dts"
26+
#endif
27+
28+
#define FIXED_PARTITION_ADDR(node_label) \
29+
(DT_REG_ADDR(DT_NODELABEL(node_label)) + \
30+
COND_CODE_0(DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(node_label)), (0), \
31+
(DT_REG_ADDR(DT_GPARENT(DT_NODELABEL(node_label))))))
32+
33+
34+
int soc_s2ram_suspend(pm_s2ram_system_off_fn_t system_off)
35+
{
36+
(void)(system_off);
37+
return -1;
38+
}
39+
40+
void pm_s2ram_mark_set(void)
41+
{
42+
/* empty */
43+
}
44+
45+
struct arm_vector_table {
46+
uint32_t msp;
47+
uint32_t reset;
48+
};
49+
50+
/* This could be read from slot's image_header.ih_hdr_size, but immediate value
51+
* is much faster to reach
52+
*/
53+
#define APP_EXE_START_OFFSET 0x800 /* nRF54H20 */
54+
55+
bool pm_s2ram_mark_check_and_clear(void)
56+
{
57+
uint32_t reset_reason = nrf_resetinfo_resetreas_local_get(NRF_RESETINFO);
58+
59+
if (reset_reason != NRF_RESETINFO_RESETREAS_LOCAL_UNRETAINED_MASK) {
60+
/* Normal boot */
61+
return false;
62+
}
63+
64+
/* S2RAM resume expected, do doublecheck */
65+
if (mcuboot_resume.magic == MCUBOOT_S2RAM_RESUME_MAGIC) {
66+
/* clear magic to avoid accidental reuse */
67+
mcuboot_resume.magic = 0;
68+
} else {
69+
/* magic not valid, normal boot */
70+
goto resume_failed;
71+
}
72+
73+
/* s2ram boot */
74+
struct arm_vector_table *vt;
75+
vt = (struct arm_vector_table *)
76+
(FIXED_PARTITION_ADDR(slot0_partition) + APP_EXE_START_OFFSET);
77+
78+
/* Jump to application */
79+
__asm__ volatile (
80+
/* vt->reset -> r0 */
81+
" mov r0, %0\n"
82+
/* vt->msp -> r1 */
83+
" mov r1, %1\n"
84+
/* set stack pointer */
85+
" msr msp, r1\n"
86+
/* jump to reset vector of an app */
87+
" bx r0\n"
88+
:
89+
: "r" (vt->reset), "r" (vt->msp)
90+
: "r0", "r1", "memory"
91+
);
92+
93+
resume_failed:
94+
FIH_PANIC;
95+
96+
return true;
97+
}

0 commit comments

Comments
 (0)