Can't use CONFIG_FPROTECT=y in MCUBOOT+APP (with TFM), compilation results in "No fprotect backend selected." CMake error

Hi all,

I wanted to enable read/write protection for MCUBOOT partition in my firmware from the application and encountered a strange problem. The build (build system - default, device nrf9160, SDK v2.7.0) for nrf9160dk_nrf9160_ns with MCUBOOT(child image) and TFM results with error:

CMake Error at C:/ncs/v2.7.0/nrf/lib/fprotect/CMakeLists.txt:15 (message):
No fprotect backend selected.

My research showed that the device tree for NS board has no SPU, ficr and uicr peripherals (why??). And if I try to add these peripherals in a device tree overlay file I get following compilation errors:

In file included from C:/ncs/v2.7.0/zephyr/include/zephyr/toolchain.h:50,
from C:/ncs/v2.7.0/zephyr/include/zephyr/kernel_includes.h:23,
from C:/ncs/v2.7.0/zephyr/include/zephyr/kernel.h:17,
from C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:7:
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:176:20: error: 'NRF_FICR' undeclared here (not in a function); did you mean 'NRF_FICR_S'?
176 | CHECK_DT_REG(ficr, NRF_FICR);
| ^~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/toolchain/gcc.h:87:51: note: in definition of macro 'BUILD_ASSERT'
87 | #define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG)
| ^~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:69:53: note: in expansion of macro '__DEBRACKET'
69 | #define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:64:9: note: in expansion of macro '__GET_ARG2_DEBRACKET'
64 | __GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
| ^~~~~~~~~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:59:9: note: in expansion of macro '__COND_CODE'
59 | __COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:180:9: note: in expansion of macro 'Z_COND_CODE_1'
180 | Z_COND_CODE_1(_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:378:23: note: in expansion of macro 'COND_CODE_1'
378 | #define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b))
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:101:17: note: in expansion of macro 'UTIL_OR'
101 | UTIL_OR(UTIL_NOT(DT_REG_HAS_IDX(DT_NODELABEL(lbl), 0)), \
| ^~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:176:1: note: in expansion of macro 'CHECK_DT_REG'
176 | CHECK_DT_REG(ficr, NRF_FICR);
| ^~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:102:25: error: expression in static assertion is not an integer
102 | (DT_REG_ADDR(DT_NODELABEL(lbl)) == (uint32_t)(mdk_addr))))
| ^
C:/ncs/v2.7.0/zephyr/include/zephyr/toolchain/gcc.h:87:51: note: in definition of macro 'BUILD_ASSERT'
87 | #define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG)
| ^~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:69:53: note: in expansion of macro '__DEBRACKET'
69 | #define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:64:9: note: in expansion of macro '__GET_ARG2_DEBRACKET'
64 | __GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
| ^~~~~~~~~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:59:9: note: in expansion of macro '__COND_CODE'
59 | __COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:180:9: note: in expansion of macro 'Z_COND_CODE_1'
180 | Z_COND_CODE_1(_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:378:23: note: in expansion of macro 'COND_CODE_1'
378 | #define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b))
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:101:17: note: in expansion of macro 'UTIL_OR'
101 | UTIL_OR(UTIL_NOT(DT_REG_HAS_IDX(DT_NODELABEL(lbl), 0)), \
| ^~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:176:1: note: in expansion of macro 'CHECK_DT_REG'
176 | CHECK_DT_REG(ficr, NRF_FICR);
| ^~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:275:19: error: 'NRF_SPU' undeclared here (not in a function); did you mean 'NRF_FPU'?
275 | CHECK_DT_REG(spu, NRF_SPU);
| ^~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/toolchain/gcc.h:87:51: note: in definition of macro 'BUILD_ASSERT'
87 | #define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG)
| ^~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:69:53: note: in expansion of macro '__DEBRACKET'
69 | #define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:64:9: note: in expansion of macro '__GET_ARG2_DEBRACKET'
64 | __GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
| ^~~~~~~~~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:59:9: note: in expansion of macro '__COND_CODE'
59 | __COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:180:9: note: in expansion of macro 'Z_COND_CODE_1'
180 | Z_COND_CODE_1(_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:378:23: note: in expansion of macro 'COND_CODE_1'
378 | #define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b))
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:101:17: note: in expansion of macro 'UTIL_OR'
101 | UTIL_OR(UTIL_NOT(DT_REG_HAS_IDX(DT_NODELABEL(lbl), 0)), \
| ^~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:275:1: note: in expansion of macro 'CHECK_DT_REG'
275 | CHECK_DT_REG(spu, NRF_SPU);
| ^~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:102:25: error: expression in static assertion is not an integer
102 | (DT_REG_ADDR(DT_NODELABEL(lbl)) == (uint32_t)(mdk_addr))))
| ^
C:/ncs/v2.7.0/zephyr/include/zephyr/toolchain/gcc.h:87:51: note: in definition of macro 'BUILD_ASSERT'
87 | #define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG)
| ^~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:69:53: note: in expansion of macro '__DEBRACKET'
69 | #define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:64:9: note: in expansion of macro '__GET_ARG2_DEBRACKET'
64 | __GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
| ^~~~~~~~~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:59:9: note: in expansion of macro '__COND_CODE'
59 | __COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:180:9: note: in expansion of macro 'Z_COND_CODE_1'
180 | Z_COND_CODE_1(_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:378:23: note: in expansion of macro 'COND_CODE_1'
378 | #define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b))
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:101:17: note: in expansion of macro 'UTIL_OR'
101 | UTIL_OR(UTIL_NOT(DT_REG_HAS_IDX(DT_NODELABEL(lbl), 0)), \
| ^~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:275:1: note: in expansion of macro 'CHECK_DT_REG'
275 | CHECK_DT_REG(spu, NRF_SPU);
| ^~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:326:20: error: 'NRF_UICR' undeclared here (not in a function); did you mean 'NRF_UICR_S'?
326 | CHECK_DT_REG(uicr, NRF_UICR);
| ^~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/toolchain/gcc.h:87:51: note: in definition of macro 'BUILD_ASSERT'
87 | #define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG)
| ^~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:69:53: note: in expansion of macro '__DEBRACKET'
69 | #define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:64:9: note: in expansion of macro '__GET_ARG2_DEBRACKET'
64 | __GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
| ^~~~~~~~~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:59:9: note: in expansion of macro '__COND_CODE'
59 | __COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:180:9: note: in expansion of macro 'Z_COND_CODE_1'
180 | Z_COND_CODE_1(_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:378:23: note: in expansion of macro 'COND_CODE_1'
378 | #define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b))
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:101:17: note: in expansion of macro 'UTIL_OR'
101 | UTIL_OR(UTIL_NOT(DT_REG_HAS_IDX(DT_NODELABEL(lbl), 0)), \
| ^~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:326:1: note: in expansion of macro 'CHECK_DT_REG'
326 | CHECK_DT_REG(uicr, NRF_UICR);
| ^~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:102:25: error: expression in static assertion is not an integer
102 | (DT_REG_ADDR(DT_NODELABEL(lbl)) == (uint32_t)(mdk_addr))))
| ^
C:/ncs/v2.7.0/zephyr/include/zephyr/toolchain/gcc.h:87:51: note: in definition of macro 'BUILD_ASSERT'
87 | #define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG)
| ^~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:69:53: note: in expansion of macro '__DEBRACKET'
69 | #define __GET_ARG2_DEBRACKET(ignore_this, val, ...) __DEBRACKET val
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:64:9: note: in expansion of macro '__GET_ARG2_DEBRACKET'
64 | __GET_ARG2_DEBRACKET(one_or_two_args _if_code, _else_code)
| ^~~~~~~~~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_internal.h:59:9: note: in expansion of macro '__COND_CODE'
59 | __COND_CODE(_XXXX##_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:180:9: note: in expansion of macro 'Z_COND_CODE_1'
180 | Z_COND_CODE_1(_flag, _if_1_code, _else_code)
| ^~~~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/include/zephyr/sys/util_macro.h:378:23: note: in expansion of macro 'COND_CODE_1'
378 | #define UTIL_OR(a, b) COND_CODE_1(UTIL_BOOL(a), (a), (b))
| ^~~~~~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:101:17: note: in expansion of macro 'UTIL_OR'
101 | UTIL_OR(UTIL_NOT(DT_REG_HAS_IDX(DT_NODELABEL(lbl), 0)), \
| ^~~~~~~
C:/ncs/v2.7.0/zephyr/soc/nordic/validate_base_addresses.c:326:1: note: in expansion of macro 'CHECK_DT_REG'
326 | CHECK_DT_REG(uicr, NRF_UICR);
| ^~~~~~~~~~~~

 Are there any examples of how to apply readout flash protection in nrf9160 ns builds?

Best regards, Valerii

  • The feature you are describing is what we call APPROTECT or Access Port Protection. See Enabling access port protection mechanism:

    "

    Several Nordic Semiconductor SoCs or SiPs supported in the nRF Connect SDK offer an implementation of the access port protection mechanism (AP-Protect). When enabled, this mechanism blocks the debugger from read and write access to all CPU registers and memory-mapped addresses. Accessing these registers and addresses again requires disabling the mechanism and erasing the flash.

    "

    valerii7 said:
    Could you please confirm that my understanding is correct? The main purpose of the protection is to prevent the code from running on unauthorized hw (

    If you run Access Port Protection, noone should be able to read out your fw.

    If you then also encrypt your DFU, people should not be able to use intercepted DFU images.

    I agree with your understanding.

Related