Platform: Add NV counters for reference targets
This patch adds dummy NV counters implementation for supported
platforms AN521, AN519 and Musca A1.
Change-Id: I8d830d9bf9abb56ac3aaad6172ef551fac5bebaa
Signed-off-by: Marc Moreno <marc.morenoberengue@arm.com>
diff --git a/platform/ext/Mps2AN519.cmake b/platform/ext/Mps2AN519.cmake
old mode 100755
new mode 100644
index 31f4d15..f1475bf
--- a/platform/ext/Mps2AN519.cmake
+++ b/platform/ext/Mps2AN519.cmake
@@ -125,6 +125,16 @@
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an519/dummy_crypto_keys.c")
endif()
+if (NOT DEFINED BUILD_TARGET_NV_COUNTERS)
+ message(FATAL_ERROR "Configuration variable BUILD_TARGET_NV_COUNTERS (true|false) is undefined!")
+elseif(BUILD_TARGET_NV_COUNTERS)
+ # NOTE: This non-volatile counters implementation is a dummy
+ # implementation. Platform vendors have to implement the
+ # API ONLY if the target has non-volatile counters.
+ list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an519/dummy_nv_counters.c")
+ set(TARGET_NV_COUNTERS_ENABLE ON)
+endif()
+
if (NOT DEFINED BUILD_CMSIS_DRIVERS)
message(FATAL_ERROR "Configuration variable BUILD_CMSIS_DRIVERS (true|false) is undefined!")
elseif(BUILD_CMSIS_DRIVERS)
diff --git a/platform/ext/Mps2AN521.cmake b/platform/ext/Mps2AN521.cmake
old mode 100755
new mode 100644
index 97d28d8..a0c453f
--- a/platform/ext/Mps2AN521.cmake
+++ b/platform/ext/Mps2AN521.cmake
@@ -126,6 +126,16 @@
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an521/dummy_crypto_keys.c")
endif()
+if (NOT DEFINED BUILD_TARGET_NV_COUNTERS)
+ message(FATAL_ERROR "Configuration variable BUILD_TARGET_NV_COUNTERS (true|false) is undefined!")
+elseif(BUILD_TARGET_NV_COUNTERS)
+ # NOTE: This non-volatile counters implementation is a dummy
+ # implementation. Platform vendors have to implement the
+ # API ONLY if the target has non-volatile counters.
+ list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an521/dummy_nv_counters.c")
+ set(TARGET_NV_COUNTERS_ENABLE ON)
+endif()
+
if (NOT DEFINED BUILD_CMSIS_DRIVERS)
message(FATAL_ERROR "Configuration variable BUILD_CMSIS_DRIVERS (true|false) is undefined!")
elseif(BUILD_CMSIS_DRIVERS)
diff --git a/platform/ext/musca_a.cmake b/platform/ext/musca_a.cmake
index 78434fe..e9c06c5 100755
--- a/platform/ext/musca_a.cmake
+++ b/platform/ext/musca_a.cmake
@@ -129,6 +129,16 @@
list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/dummy_crypto_keys.c")
endif()
+if (NOT DEFINED BUILD_TARGET_NV_COUNTERS)
+ message(FATAL_ERROR "Configuration variable BUILD_TARGET_NV_COUNTERS (true|false) is undefined!")
+elseif(BUILD_TARGET_NV_COUNTERS)
+ # NOTE: This non-volatile counters implementation is a dummy
+ # implementation. Platform vendors have to implement the
+ # API ONLY if the target has non-volatile counters.
+ list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/dummy_nv_counters.c")
+ set(TARGET_NV_COUNTERS_ENABLE ON)
+endif()
+
if (NOT DEFINED BUILD_CMSIS_DRIVERS)
message(FATAL_ERROR "Configuration variable BUILD_CMSIS_DRIVERS (true|false) is undefined!")
elseif(BUILD_CMSIS_DRIVERS)
diff --git a/platform/ext/target/mps2/an519/armclang/mps2_an519_s.sct b/platform/ext/target/mps2/an519/armclang/mps2_an519_s.sct
index 5216d50..4c043c3 100644
--- a/platform/ext/target/mps2/an519/armclang/mps2_an519_s.sct
+++ b/platform/ext/target/mps2/an519/armclang/mps2_an519_s.sct
@@ -44,6 +44,7 @@
TFM_UNPRIV_CODE +0 ALIGN 32 {
tfm_unpriv_api.o (+RO)
dummy_crypto_keys.o (+RO)
+ dummy_nv_counters.o (+RO)
platform_retarget_dev.o (+RO)
*(SFN)
*armlib*
@@ -91,6 +92,7 @@
TFM_UNPRIV_RO_DATA +0 ALIGN 32 {
tfm_unpriv_api.o (+RW +ZI)
dummy_crypto_keys.o (+RW +ZI)
+ dummy_nv_counters.o (+RW +ZI)
platform_retarget_dev.o (+RW +ZI)
}
diff --git a/platform/ext/target/mps2/an519/dummy_nv_counters.c b/platform/ext/target/mps2/an519/dummy_nv_counters.c
new file mode 100644
index 0000000..6f8ea62
--- /dev/null
+++ b/platform/ext/target/mps2/an519/dummy_nv_counters.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* NOTE: This API should be implemented by platform vendor. For the
+ * security of the secure storage system rollback protection and others, it is
+ * CRITICAL to use a internal (in-die) persistent memory for multiple time
+ * programabe (MTP) non-volatile counters or use a One-time Programmable (OTP)
+ * non-volatile counters solution.
+ *
+ * AN519 does not have any available MTP or OTP non-volatile counters, so a
+ * software dummy implementation has been implemented in this case.
+ */
+
+#include "platform/include/tfm_plat_nv_counters.h"
+
+#include <limits.h>
+#include "Driver_Flash.h"
+#include "flash_layout.h"
+
+/* Compilation time checks to be sure the defines are well defined */
+#ifndef TFM_NV_COUNTERS_AREA_ADDR
+#error "TFM_NV_COUNTERS_AREA_ADDR must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_AREA_SIZE
+#error "TFM_NV_COUNTERS_AREA_SIZE must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_SECTOR_ADDR
+#error "TFM_NV_COUNTERS_SECTOR_ADDR must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_SECTOR_SIZE
+#error "TFM_NV_COUNTERS_SECTOR_SIZE must be defined in flash_layout.h"
+#endif
+
+#ifndef FLASH_DEV_NAME
+#error "FLASH_DEV_NAME must be defined in flash_layout.h"
+#endif
+/* End of compilation time checks to be sure the defines are well defined */
+
+#define SECTOR_OFFSET 0
+#define NV_COUNTER_SIZE sizeof(uint32_t)
+#define INIT_VALUE_SIZE NV_COUNTER_SIZE
+#define NV_COUNTERS_AREA_OFFSET (TFM_NV_COUNTERS_AREA_ADDR - \
+ TFM_NV_COUNTERS_SECTOR_ADDR)
+
+#define NV_COUNTERS_INITIALIZED 0xC0DE0042
+
+/* Import the CMSIS flash device driver */
+extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
+
+enum tfm_plat_err_t tfm_plat_init_nv_counter(void)
+{
+ int32_t err;
+ uint32_t i;
+ uint32_t nbr_counters = ((TFM_NV_COUNTERS_AREA_SIZE - INIT_VALUE_SIZE)
+ / NV_COUNTER_SIZE);
+ uint32_t *p_nv_counter;
+ uint8_t sector_data[TFM_NV_COUNTERS_SECTOR_SIZE] = {0};
+
+ /* Read the whole sector to be able to erase and write later in the flash */
+ err = FLASH_DEV_NAME.ReadData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Set the pointer to nv counters position */
+ p_nv_counter = (uint32_t *)(sector_data + NV_COUNTERS_AREA_OFFSET);
+
+ if (p_nv_counter[nbr_counters] == NV_COUNTERS_INITIALIZED) {
+ return TFM_PLAT_ERR_SUCCESS;
+ }
+
+ /* Add watermark, at the end of the NV counters area, to indicate that NV
+ * counters have been initialized.
+ */
+ p_nv_counter[nbr_counters] = NV_COUNTERS_INITIALIZED;
+
+ /* Initialize all counters to 0 */
+ for (i = 0; i < nbr_counters; i++) {
+ p_nv_counter[i] = 0;
+ }
+
+ /* Erase sector before write in it */
+ err = FLASH_DEV_NAME.EraseSector(TFM_NV_COUNTERS_SECTOR_ADDR);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Write in flash the in-memory block content after modification */
+ err = FLASH_DEV_NAME.ProgramData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_read_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t size, uint8_t *val)
+{
+ int32_t err;
+ uint32_t flash_addr;
+
+ if (size != NV_COUNTER_SIZE) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ flash_addr = TFM_NV_COUNTERS_AREA_ADDR + (counter_id * NV_COUNTER_SIZE);
+
+ err = FLASH_DEV_NAME.ReadData(flash_addr, val, NV_COUNTER_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_increment_nv_counter(
+ enum tfm_nv_counter_t counter_id)
+{
+ int32_t err;
+ uint32_t *p_nv_counter;
+ uint8_t sector_data[TFM_NV_COUNTERS_SECTOR_SIZE];
+
+ /* Read the whole sector to be able to erase and write later in the flash */
+ err = FLASH_DEV_NAME.ReadData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Set the pointer to nv counter position */
+ p_nv_counter = (uint32_t *)(sector_data + NV_COUNTERS_AREA_OFFSET +
+ (counter_id * NV_COUNTER_SIZE));
+
+ if (*p_nv_counter == UINT32_MAX) {
+ return TFM_PLAT_ERR_MAX_VALUE;
+ }
+
+ /* Next value is the current value + 1 */
+ *p_nv_counter = *p_nv_counter + 1;
+
+ /* Erase sector before write in it */
+ err = FLASH_DEV_NAME.EraseSector(TFM_NV_COUNTERS_SECTOR_ADDR);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Write in flash the in-memory block content after modification */
+ err = FLASH_DEV_NAME.ProgramData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
diff --git a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
index 7b1ea60..9c33da4 100644
--- a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
+++ b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld
@@ -170,6 +170,8 @@
*tfm_unpriv_api.o(.rodata*)
*dummy_crypto_keys.o(.text*)
*dummy_crypto_keys.o(.rodata*)
+ *dummy_nv_counters.o(.text*)
+ *dummy_nv_counters.o(.rodata*)
*platform_retarget_dev.o(.text*)
*platform_retarget_dev.o(.rodata*)
*(SFN)
@@ -331,6 +333,7 @@
{
*/tfm_unpriv_api.o(.data*)
*/dummy_crypto_keys.o(.data*)
+ */dummy_nv_counters.o(.data*)
*/platform_retarget_dev.o(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
@@ -342,9 +345,11 @@
*/tfm_unpriv_api.o(.bss*)
*/platform_retarget_dev.o(.bss*)
*/dummy_crypto_keys.o(.bss*)
+ */dummy_nv_counters.o(.bss*)
*/tfm_unpriv_api.o(COMMON)
*/platform_retarget_dev.o(COMMON)
*/dummy_crypto_keys.o(COMMON)
+ */dummy_nv_counters.o(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS);
diff --git a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld.template b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld.template
index ededa5c..14f7629 100644
--- a/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld.template
+++ b/platform/ext/target/mps2/an519/gcc/mps2_an519_s.ld.template
@@ -135,6 +135,8 @@
*tfm_unpriv_api.o(.rodata*)
*dummy_crypto_keys.o(.text*)
*dummy_crypto_keys.o(.rodata*)
+ *dummy_nv_counters.o(.text*)
+ *dummy_nv_counters.o(.rodata*)
*platform_retarget_dev.o(.text*)
*platform_retarget_dev.o(.rodata*)
*(SFN)
@@ -233,6 +235,7 @@
{
*/tfm_unpriv_api.o(.data*)
*/dummy_crypto_keys.o(.data*)
+ */dummy_nv_counters.o(.data*)
*/platform_retarget_dev.o(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
@@ -244,9 +247,11 @@
*/tfm_unpriv_api.o(.bss*)
*/platform_retarget_dev.o(.bss*)
*/dummy_crypto_keys.o(.bss*)
+ */dummy_nv_counters.o(.bss*)
*/tfm_unpriv_api.o(COMMON)
*/platform_retarget_dev.o(COMMON)
*/dummy_crypto_keys.o(COMMON)
+ */dummy_nv_counters.o(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS);
diff --git a/platform/ext/target/mps2/an519/partition/flash_layout.h b/platform/ext/target/mps2/an519/partition/flash_layout.h
index e792f7b..e953227 100644
--- a/platform/ext/target/mps2/an519/partition/flash_layout.h
+++ b/platform/ext/target/mps2/an519/partition/flash_layout.h
@@ -27,8 +27,9 @@
* 0x0018_0000 Secure image secondary
* 0x0020_0000 Non-secure image secondary
* 0x0028_0000 Scratch area(1 MB)
- * 0x0038_0000 Secure Storage Area (0.02 MB)
- * 0x0038_5000 Unused(0.482 MB)
+ * 0x0038_0000 Secure Storage Area(0.02 MB)
+ * 0x0038_5000 NV counters area(16 Bytes)
+ * 0x0038_5010 Unused(0.491 MB)
*
* Flash layout on MPS2 AN519, if BL2 not defined:
* 0x0000_0000 Secure image
@@ -83,6 +84,9 @@
#define FLASH_SST_AREA_OFFSET (0x380000)
#define FLASH_SST_AREA_SIZE (0x5000) /* 20 KB */
+#define FLASH_NV_COUNTERS_AREA_OFFSET (0x385000)
+#define FLASH_NV_COUNTERS_AREA_SIZE (0x10) /* 16 Bytes */
+
/* Offset and size definition in flash area, used by assemble.py */
#define SECURE_IMAGE_OFFSET 0x0
#define SECURE_IMAGE_MAX_SIZE 0x80000
@@ -106,4 +110,10 @@
/* Specifies the smallest flash programmable unit in bytes */
#define SST_FLASH_PROGRAM_UNIT 0x1
+/* NV Counters definitions */
+#define TFM_NV_COUNTERS_AREA_ADDR FLASH_NV_COUNTERS_AREA_OFFSET
+#define TFM_NV_COUNTERS_AREA_SIZE FLASH_NV_COUNTERS_AREA_SIZE
+#define TFM_NV_COUNTERS_SECTOR_ADDR FLASH_NV_COUNTERS_AREA_OFFSET
+#define TFM_NV_COUNTERS_SECTOR_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE
+
#endif /* __FLASH_LAYOUT_H__ */
diff --git a/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct b/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
index 5216d50..4c043c3 100644
--- a/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
+++ b/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
@@ -44,6 +44,7 @@
TFM_UNPRIV_CODE +0 ALIGN 32 {
tfm_unpriv_api.o (+RO)
dummy_crypto_keys.o (+RO)
+ dummy_nv_counters.o (+RO)
platform_retarget_dev.o (+RO)
*(SFN)
*armlib*
@@ -91,6 +92,7 @@
TFM_UNPRIV_RO_DATA +0 ALIGN 32 {
tfm_unpriv_api.o (+RW +ZI)
dummy_crypto_keys.o (+RW +ZI)
+ dummy_nv_counters.o (+RW +ZI)
platform_retarget_dev.o (+RW +ZI)
}
diff --git a/platform/ext/target/mps2/an521/dummy_nv_counters.c b/platform/ext/target/mps2/an521/dummy_nv_counters.c
new file mode 100644
index 0000000..e82cd7c
--- /dev/null
+++ b/platform/ext/target/mps2/an521/dummy_nv_counters.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* NOTE: This API should be implemented by platform vendor. For the
+ * security of the secure storage system rollback protection and others, it is
+ * CRITICAL to use a internal (in-die) persistent memory for multiple time
+ * programabe (MTP) non-volatile counters or use a One-time Programmable (OTP)
+ * non-volatile counters solution.
+ *
+ * AN521 does not have any available MTP or OTP non-volatile counters, so a
+ * software dummy implementation has been implemented in this case.
+ */
+
+#include "platform/include/tfm_plat_nv_counters.h"
+
+#include <limits.h>
+#include "Driver_Flash.h"
+#include "flash_layout.h"
+
+/* Compilation time checks to be sure the defines are well defined */
+#ifndef TFM_NV_COUNTERS_AREA_ADDR
+#error "TFM_NV_COUNTERS_AREA_ADDR must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_AREA_SIZE
+#error "TFM_NV_COUNTERS_AREA_SIZE must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_SECTOR_ADDR
+#error "TFM_NV_COUNTERS_SECTOR_ADDR must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_SECTOR_SIZE
+#error "TFM_NV_COUNTERS_SECTOR_SIZE must be defined in flash_layout.h"
+#endif
+
+#ifndef FLASH_DEV_NAME
+#error "FLASH_DEV_NAME must be defined in flash_layout.h"
+#endif
+/* End of compilation time checks to be sure the defines are well defined */
+
+#define SECTOR_OFFSET 0
+#define NV_COUNTER_SIZE sizeof(uint32_t)
+#define INIT_VALUE_SIZE NV_COUNTER_SIZE
+#define NV_COUNTERS_AREA_OFFSET (TFM_NV_COUNTERS_AREA_ADDR - \
+ TFM_NV_COUNTERS_SECTOR_ADDR)
+
+#define NV_COUNTERS_INITIALIZED 0xC0DE0042
+
+/* Import the CMSIS flash device driver */
+extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
+
+enum tfm_plat_err_t tfm_plat_init_nv_counter(void)
+{
+ int32_t err;
+ uint32_t i;
+ uint32_t nbr_counters = ((TFM_NV_COUNTERS_AREA_SIZE - INIT_VALUE_SIZE)
+ / NV_COUNTER_SIZE);
+ uint32_t *p_nv_counter;
+ uint8_t sector_data[TFM_NV_COUNTERS_SECTOR_SIZE] = {0};
+
+ /* Read the whole sector to be able to erase and write later in the flash */
+ err = FLASH_DEV_NAME.ReadData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Set the pointer to nv counters position */
+ p_nv_counter = (uint32_t *)(sector_data + NV_COUNTERS_AREA_OFFSET);
+
+ if (p_nv_counter[nbr_counters] == NV_COUNTERS_INITIALIZED) {
+ return TFM_PLAT_ERR_SUCCESS;
+ }
+
+ /* Add watermark, at the end of the NV counters area, to indicate that NV
+ * counters have been initialized.
+ */
+ p_nv_counter[nbr_counters] = NV_COUNTERS_INITIALIZED;
+
+ /* Initialize all counters to 0 */
+ for (i = 0; i < nbr_counters; i++) {
+ p_nv_counter[i] = 0;
+ }
+
+ /* Erase sector before write in it */
+ err = FLASH_DEV_NAME.EraseSector(TFM_NV_COUNTERS_SECTOR_ADDR);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Write in flash the in-memory block content after modification */
+ err = FLASH_DEV_NAME.ProgramData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_read_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t size, uint8_t *val)
+{
+ int32_t err;
+ uint32_t flash_addr;
+
+ if (size != NV_COUNTER_SIZE) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ flash_addr = TFM_NV_COUNTERS_AREA_ADDR + (counter_id * NV_COUNTER_SIZE);
+
+ err = FLASH_DEV_NAME.ReadData(flash_addr, val, NV_COUNTER_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_increment_nv_counter(
+ enum tfm_nv_counter_t counter_id)
+{
+ int32_t err;
+ uint32_t *p_nv_counter;
+ uint8_t sector_data[TFM_NV_COUNTERS_SECTOR_SIZE];
+
+ /* Read the whole sector to be able to erase and write later in the flash */
+ err = FLASH_DEV_NAME.ReadData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Set the pointer to nv counter position */
+ p_nv_counter = (uint32_t *)(sector_data + NV_COUNTERS_AREA_OFFSET +
+ (counter_id * NV_COUNTER_SIZE));
+
+ if (*p_nv_counter == UINT32_MAX) {
+ return TFM_PLAT_ERR_MAX_VALUE;
+ }
+
+ /* Next value is the current value + 1 */
+ *p_nv_counter = *p_nv_counter + 1;
+
+ /* Erase sector before write in it */
+ err = FLASH_DEV_NAME.EraseSector(TFM_NV_COUNTERS_SECTOR_ADDR);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Write in flash the in-memory block content after modification */
+ err = FLASH_DEV_NAME.ProgramData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
diff --git a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
index 5012c70..d3cfc21 100644
--- a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
+++ b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld
@@ -170,6 +170,8 @@
*tfm_unpriv_api.o(.rodata*)
*dummy_crypto_keys.o(.text*)
*dummy_crypto_keys.o(.rodata*)
+ *dummy_nv_counters.o(.text*)
+ *dummy_nv_counters.o(.rodata*)
*platform_retarget_dev.o(.text*)
*platform_retarget_dev.o(.rodata*)
*(SFN)
@@ -331,6 +333,7 @@
{
*/tfm_unpriv_api.o(.data*)
*/dummy_crypto_keys.o(.data*)
+ */dummy_nv_counters.o(.data*)
*/platform_retarget_dev.o(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
@@ -342,9 +345,11 @@
*/tfm_unpriv_api.o(.bss*)
*/platform_retarget_dev.o(.bss*)
*/dummy_crypto_keys.o(.bss*)
+ */dummy_nv_counters.o(.bss*)
*/tfm_unpriv_api.o(COMMON)
*/platform_retarget_dev.o(COMMON)
*/dummy_crypto_keys.o(COMMON)
+ */dummy_nv_counters.o(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS);
diff --git a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld.template b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld.template
index f14457d..bb3db93 100644
--- a/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld.template
+++ b/platform/ext/target/mps2/an521/gcc/mps2_an521_s.ld.template
@@ -135,6 +135,8 @@
*tfm_unpriv_api.o(.rodata*)
*dummy_crypto_keys.o(.text*)
*dummy_crypto_keys.o(.rodata*)
+ *dummy_nv_counters.o(.text*)
+ *dummy_nv_counters.o(.rodata*)
*platform_retarget_dev.o(.text*)
*platform_retarget_dev.o(.rodata*)
*(SFN)
@@ -233,6 +235,7 @@
{
*/tfm_unpriv_api.o(.data*)
*/dummy_crypto_keys.o(.data*)
+ */dummy_nv_counters.o(.data*)
*/platform_retarget_dev.o(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
@@ -244,9 +247,11 @@
*/tfm_unpriv_api.o(.bss*)
*/platform_retarget_dev.o(.bss*)
*/dummy_crypto_keys.o(.bss*)
+ */dummy_nv_counters.o(.bss*)
*/tfm_unpriv_api.o(COMMON)
*/platform_retarget_dev.o(COMMON)
*/dummy_crypto_keys.o(COMMON)
+ */dummy_nv_counters.o(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS);
diff --git a/platform/ext/target/mps2/an521/partition/flash_layout.h b/platform/ext/target/mps2/an521/partition/flash_layout.h
index cf0d1ab..c77f012 100644
--- a/platform/ext/target/mps2/an521/partition/flash_layout.h
+++ b/platform/ext/target/mps2/an521/partition/flash_layout.h
@@ -27,8 +27,9 @@
* 0x0018_0000 Secure image secondary
* 0x0020_0000 Non-secure image secondary
* 0x0028_0000 Scratch area(1 MB)
- * 0x0038_0000 Secure Storage Area (0.02 MB)
- * 0x0038_5000 Unused(0.482 MB)
+ * 0x0038_0000 Secure Storage Area(0.02 MB)
+ * 0x0038_5000 NV counters area(16 Bytes)
+ * 0x0038_5010 Unused(0.491 MB)
*
* Flash layout on MPS2 AN521, if BL2 not defined:
* 0x0000_0000 Secure image
@@ -83,6 +84,9 @@
#define FLASH_SST_AREA_OFFSET (0x380000)
#define FLASH_SST_AREA_SIZE (0x5000) /* 20 KB */
+#define FLASH_NV_COUNTERS_AREA_OFFSET (0x385000)
+#define FLASH_NV_COUNTERS_AREA_SIZE (0x10) /* 16 Bytes */
+
/* Offset and size definition in flash area, used by assemble.py */
#define SECURE_IMAGE_OFFSET 0x0
#define SECURE_IMAGE_MAX_SIZE 0x80000
@@ -106,4 +110,10 @@
/* Specifies the smallest flash programmable unit in bytes */
#define SST_FLASH_PROGRAM_UNIT 0x1
+/* NV Counters definitions */
+#define TFM_NV_COUNTERS_AREA_ADDR FLASH_NV_COUNTERS_AREA_OFFSET
+#define TFM_NV_COUNTERS_AREA_SIZE FLASH_NV_COUNTERS_AREA_SIZE
+#define TFM_NV_COUNTERS_SECTOR_ADDR FLASH_NV_COUNTERS_AREA_OFFSET
+#define TFM_NV_COUNTERS_SECTOR_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE
+
#endif /* __FLASH_LAYOUT_H__ */
diff --git a/platform/ext/target/musca_a/Device/Source/armclang/musca_s.sct b/platform/ext/target/musca_a/Device/Source/armclang/musca_s.sct
index abcf4e9..d9d278d 100755
--- a/platform/ext/target/musca_a/Device/Source/armclang/musca_s.sct
+++ b/platform/ext/target/musca_a/Device/Source/armclang/musca_s.sct
@@ -44,6 +44,7 @@
TFM_UNPRIV_CODE +0 ALIGN 32 {
tfm_unpriv_api.o (+RO)
dummy_crypto_keys.o (+RO)
+ dummy_nv_counters.o (+RO)
platform_retarget_dev.o (+RO)
*(SFN)
*armlib*
@@ -92,6 +93,7 @@
TFM_UNPRIV_RO_DATA +0 ALIGN 32 {
tfm_unpriv_api.o (+RW +ZI)
dummy_crypto_keys.o (+RW +ZI)
+ dummy_nv_counters.o (+RW +ZI)
platform_retarget_dev.o (+RW +ZI)
}
diff --git a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
index 32d21a1..04ba26f 100644
--- a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
+++ b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld
@@ -170,6 +170,8 @@
*tfm_unpriv_api.o(.rodata*)
*dummy_crypto_keys.o(.text*)
*dummy_crypto_keys.o(.rodata*)
+ *dummy_nv_counters.o(.text*)
+ *dummy_nv_counters.o(.rodata*)
*platform_retarget_dev.o(.text*)
*platform_retarget_dev.o(.rodata*)
*(SFN)
@@ -331,6 +333,7 @@
{
*/tfm_unpriv_api.o(.data*)
*/dummy_crypto_keys.o(.data*)
+ */dummy_nv_counters.o(.data*)
*/platform_retarget_dev.o(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
@@ -342,9 +345,11 @@
*/tfm_unpriv_api.o(.bss*)
*/platform_retarget_dev.o(.bss*)
*/dummy_crypto_keys.o(.bss*)
+ */dummy_nv_counters.o(.bss*)
*/tfm_unpriv_api.o(COMMON)
*/platform_retarget_dev.o(COMMON)
*/dummy_crypto_keys.o(COMMON)
+ */dummy_nv_counters.o(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS);
diff --git a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld.template b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld.template
index 4634c8c..4189b56 100644
--- a/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld.template
+++ b/platform/ext/target/musca_a/Device/Source/gcc/musca_s.ld.template
@@ -135,6 +135,8 @@
*tfm_unpriv_api.o(.rodata*)
*dummy_crypto_keys.o(.text*)
*dummy_crypto_keys.o(.rodata*)
+ *dummy_nv_counters.o(.text*)
+ *dummy_nv_counters.o(.rodata*)
*platform_retarget_dev.o(.text*)
*platform_retarget_dev.o(.rodata*)
*(SFN)
@@ -233,6 +235,7 @@
{
*/tfm_unpriv_api.o(.data*)
*/dummy_crypto_keys.o(.data*)
+ */dummy_nv_counters.o(.data*)
*/platform_retarget_dev.o(.data*)
. = ALIGN(32);
} > RAM AT> FLASH
@@ -244,9 +247,11 @@
*/tfm_unpriv_api.o(.bss*)
*/platform_retarget_dev.o(.bss*)
*/dummy_crypto_keys.o(.bss*)
+ */dummy_nv_counters.o(.bss*)
*/tfm_unpriv_api.o(COMMON)
*/platform_retarget_dev.o(COMMON)
*/dummy_crypto_keys.o(COMMON)
+ */dummy_nv_counters.o(COMMON)
. = ALIGN(32);
} > RAM AT> FLASH
Image$$TFM_UNPRIV_RO_DATA$$ZI$$Base = ADDR(.TFM_UNPRIV_RO_BSS);
diff --git a/platform/ext/target/musca_a/dummy_nv_counters.c b/platform/ext/target/musca_a/dummy_nv_counters.c
new file mode 100644
index 0000000..f2a7801
--- /dev/null
+++ b/platform/ext/target/musca_a/dummy_nv_counters.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+/* NOTE: This API should be implemented by platform vendor. For the
+ * security of the secure storage system rollback protection and others, it is
+ * CRITICAL to use a internal (in-die) persistent memory for multiple time
+ * programabe (MTP) non-volatile counters or use a One-time Programmable (OTP)
+ * non-volatile counters solution.
+ *
+ * Musca A1 does not have any available MTP or OTP non-volatile counters, so a
+ * software dummy implementation has been implemented in this case.
+ */
+
+#include "platform/include/tfm_plat_nv_counters.h"
+
+#include <limits.h>
+#include "Driver_Flash.h"
+#include "flash_layout.h"
+
+/* Compilation time checks to be sure the defines are well defined */
+#ifndef TFM_NV_COUNTERS_AREA_ADDR
+#error "TFM_NV_COUNTERS_AREA_ADDR must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_AREA_SIZE
+#error "TFM_NV_COUNTERS_AREA_SIZE must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_SECTOR_ADDR
+#error "TFM_NV_COUNTERS_SECTOR_ADDR must be defined in flash_layout.h"
+#endif
+
+#ifndef TFM_NV_COUNTERS_SECTOR_SIZE
+#error "TFM_NV_COUNTERS_SECTOR_SIZE must be defined in flash_layout.h"
+#endif
+
+#ifndef FLASH_DEV_NAME
+#error "FLASH_DEV_NAME must be defined in flash_layout.h"
+#endif
+/* End of compilation time checks to be sure the defines are well defined */
+
+#define SECTOR_OFFSET 0
+#define NV_COUNTER_SIZE sizeof(uint32_t)
+#define INIT_VALUE_SIZE NV_COUNTER_SIZE
+#define NV_COUNTERS_AREA_OFFSET (TFM_NV_COUNTERS_AREA_ADDR - \
+ TFM_NV_COUNTERS_SECTOR_ADDR)
+
+#define NV_COUNTERS_INITIALIZED 0xC0DE0042
+
+/* Import the CMSIS flash device driver */
+extern ARM_DRIVER_FLASH FLASH_DEV_NAME;
+
+enum tfm_plat_err_t tfm_plat_init_nv_counter(void)
+{
+ int32_t err;
+ uint32_t i;
+ uint32_t nbr_counters = ((TFM_NV_COUNTERS_AREA_SIZE - INIT_VALUE_SIZE)
+ / NV_COUNTER_SIZE);
+ uint32_t *p_nv_counter;
+ uint8_t sector_data[TFM_NV_COUNTERS_SECTOR_SIZE] = {0};
+
+ /* Read the whole sector to be able to erase and write later in the flash */
+ err = FLASH_DEV_NAME.ReadData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Set the pointer to nv counters position */
+ p_nv_counter = (uint32_t *)(sector_data + NV_COUNTERS_AREA_OFFSET);
+
+ if (p_nv_counter[nbr_counters] == NV_COUNTERS_INITIALIZED) {
+ return TFM_PLAT_ERR_SUCCESS;
+ }
+
+ /* Add watermark, at the end of the NV counters area, to indicate that NV
+ * counters have been initialized.
+ */
+ p_nv_counter[nbr_counters] = NV_COUNTERS_INITIALIZED;
+
+ /* Initialize all counters to 0 */
+ for (i = 0; i < nbr_counters; i++) {
+ p_nv_counter[i] = 0;
+ }
+
+ /* Erase sector before write in it */
+ err = FLASH_DEV_NAME.EraseSector(TFM_NV_COUNTERS_SECTOR_ADDR);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Write in flash the in-memory block content after modification */
+ err = FLASH_DEV_NAME.ProgramData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_read_nv_counter(enum tfm_nv_counter_t counter_id,
+ uint32_t size, uint8_t *val)
+{
+ int32_t err;
+ uint32_t flash_addr;
+
+ if (size != NV_COUNTER_SIZE) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ flash_addr = TFM_NV_COUNTERS_AREA_ADDR + (counter_id * NV_COUNTER_SIZE);
+
+ err = FLASH_DEV_NAME.ReadData(flash_addr, val, NV_COUNTER_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t tfm_plat_increment_nv_counter(
+ enum tfm_nv_counter_t counter_id)
+{
+ int32_t err;
+ uint32_t *p_nv_counter;
+ uint8_t sector_data[TFM_NV_COUNTERS_SECTOR_SIZE];
+
+ /* Read the whole sector to be able to erase and write later in the flash */
+ err = FLASH_DEV_NAME.ReadData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Set the pointer to nv counter position */
+ p_nv_counter = (uint32_t *)(sector_data + NV_COUNTERS_AREA_OFFSET +
+ (counter_id * NV_COUNTER_SIZE));
+
+ if (*p_nv_counter == UINT32_MAX) {
+ return TFM_PLAT_ERR_MAX_VALUE;
+ }
+
+ /* Next value is the current value + 1 */
+ *p_nv_counter = *p_nv_counter + 1;
+
+ /* Erase sector before write in it */
+ err = FLASH_DEV_NAME.EraseSector(TFM_NV_COUNTERS_SECTOR_ADDR);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ /* Write in flash the in-memory block content after modification */
+ err = FLASH_DEV_NAME.ProgramData(TFM_NV_COUNTERS_SECTOR_ADDR, sector_data,
+ TFM_NV_COUNTERS_SECTOR_SIZE);
+ if (err != ARM_DRIVER_OK) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ return TFM_PLAT_ERR_SUCCESS;
+}
diff --git a/platform/ext/target/musca_a/partition/flash_layout.h b/platform/ext/target/musca_a/partition/flash_layout.h
index 2cd435b..3f1d1ce 100755
--- a/platform/ext/target/musca_a/partition/flash_layout.h
+++ b/platform/ext/target/musca_a/partition/flash_layout.h
@@ -25,8 +25,9 @@
* 0x0032_0000 Flash_area_image_1(1 MB)
* 0x0032_0000 Secure image secondary
* 0x003A_0000 Non-secure image secondary
- * 0x0042_0000 Secure Storage Area (0.02 MB)
- * 0x0042_5000 Unused
+ * 0x0042_0000 Secure Storage Area(0.02 MB)
+ * 0x0042_5000 NV counters area(16 Bytes)
+ * 0x0042_5010 Unused
*/
/* Code SRAM layout on Musca (with BL2, which is mandatory) after the newest
@@ -89,6 +90,10 @@
FLASH_AREA_IMAGE_SCRATCH_SIZE)
#define FLASH_SST_AREA_SIZE (0x5000) /* 20 KB */
+#define FLASH_NV_COUNTERS_AREA_OFFSET (FLASH_SST_AREA_OFFSET + \
+ FLASH_SST_AREA_SIZE)
+#define FLASH_NV_COUNTERS_AREA_SIZE (0x10) /* 16 Bytes */
+
/* Offset and size definition in flash area, used by assemble.py */
#define SECURE_IMAGE_OFFSET 0x0
#define SECURE_IMAGE_MAX_SIZE 0x80000
@@ -126,4 +131,10 @@
/* Specifies the smallest flash programmable unit in bytes */
#define SST_FLASH_PROGRAM_UNIT 0x1
+/* NV Counters definitions */
+#define TFM_NV_COUNTERS_AREA_ADDR FLASH_NV_COUNTERS_AREA_OFFSET
+#define TFM_NV_COUNTERS_AREA_SIZE FLASH_NV_COUNTERS_AREA_SIZE
+#define TFM_NV_COUNTERS_SECTOR_ADDR FLASH_NV_COUNTERS_AREA_OFFSET
+#define TFM_NV_COUNTERS_SECTOR_SIZE FLASH_AREA_IMAGE_SECTOR_SIZE
+
#endif /* __FLASH_LAYOUT_H__ */