1 /*
2  * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 #ifndef __TFM_PLAT_NV_COUNTERS_H__
9 #define __TFM_PLAT_NV_COUNTERS_H__
10 
11 /**
12  * \file tfm_plat_nv_counters.h
13  *
14  * \note The interfaces defined in this file must be implemented for each
15  *       SoC.
16  * \note The interface must be implemented in a fail-safe way that is
17  *       resistant to asynchronous power failures or it can use hardware
18  *       counters that have this capability, if supported by the platform.
19  *       When a counter incrementation was interrupted it must be able to
20  *       continue the incrementation process or recover the previous consistent
21  *       status of the counters. If the counters have reached a stable status
22  *       (every counter incrementation operation has finished), from that point
23  *       their value cannot decrease due to any kind of power failure.
24  */
25 
26 #include <stdint.h>
27 #include "tfm_plat_defs.h"
28 
29 #ifndef PLATFORM_NS_NV_COUNTERS
30 #define PLATFORM_NS_NV_COUNTERS 0
31 #endif
32 
33 #ifdef PLATFORM_DEFAULT_NV_COUNTERS
34 enum tfm_nv_counter_t {
35     PLAT_NV_COUNTER_PS_0 = 0,  /* Used by PS service */
36     PLAT_NV_COUNTER_PS_1,      /* Used by PS service */
37     PLAT_NV_COUNTER_PS_2,      /* Used by PS service */
38 
39     /* BL2 NV counters must be contiguous */
40     PLAT_NV_COUNTER_BL2_0,     /* Used by bootloader */
41     PLAT_NV_COUNTER_BL2_1,     /* Used by bootloader */
42     PLAT_NV_COUNTER_BL2_2,     /* Used by bootloader */
43     PLAT_NV_COUNTER_BL2_3,     /* Used by bootloader */
44 
45     PLAT_NV_COUNTER_BL1_0,     /* Used by bootloader */
46 
47     /* NS counters must be contiguous */
48     PLAT_NV_COUNTER_NS_0,      /* Used by NS */
49     PLAT_NV_COUNTER_NS_1,      /* Used by NS */
50     PLAT_NV_COUNTER_NS_2,      /* Used by NS */
51 
52     PLAT_NV_COUNTER_MAX,
53     PLAT_NV_COUNTER_BOUNDARY = UINT32_MAX  /* Fix  tfm_nv_counter_t size
54                                               to 4 bytes */
55 };
56 #else
57 #include "platform_nv_counters_ids.h"
58 #endif
59 
60 #ifdef __cplusplus
61 extern "C" {
62 #endif
63 
64 /**
65  * \brief Initialises all non-volatile (NV) counters.
66  *
67  * \return  TFM_PLAT_ERR_SUCCESS if the initialization succeeds, otherwise
68  *          TFM_PLAT_ERR_SYSTEM_ERR
69  */
70 enum tfm_plat_err_t tfm_plat_init_nv_counter(void);
71 
72 /**
73  * \brief Reads the given non-volatile (NV) counter.
74  *
75  * \param[in]  counter_id  NV counter ID.
76  * \param[in]  size        Size of the buffer to store NV counter value
77  *                         in bytes.
78  * \param[out] val         Pointer to store the current NV counter value.
79  *
80  * \return  TFM_PLAT_ERR_SUCCESS if the value is read correctly. Otherwise,
81  *          it returns TFM_PLAT_ERR_SYSTEM_ERR.
82  */
83 enum tfm_plat_err_t tfm_plat_read_nv_counter(enum tfm_nv_counter_t counter_id,
84                                              uint32_t size, uint8_t *val);
85 
86 /**
87  * \brief Increments the given non-volatile (NV) counter.
88  *
89  * \param[in] counter_id  NV counter ID.
90  *
91  * \return  When the NV counter reaches its maximum value, the
92  *          TFM_PLAT_ERR_MAX_VALUE error is returned to indicate the value
93  *          cannot be incremented. Otherwise, it returns TFM_PLAT_ERR_SUCCESS.
94  */
95 enum tfm_plat_err_t tfm_plat_increment_nv_counter(
96                                               enum tfm_nv_counter_t counter_id);
97 
98 /**
99  * \brief Sets the given non-volatile (NV) counter to the specified value.
100  *
101  * \param[in] counter_id  NV counter ID.
102  * \param[in] value       New value of the NV counter. The maximum value that
103  *                        can be set depends on the constraints of the
104  *                        underlying implementation, but it always must be
105  *                        greater than or equal to the current NV counter value.
106  *
107  * \retval TFM_PLAT_ERR_SUCCESS         The NV counter is set successfully
108  * \retval TFM_PLAT_ERR_INVALID_INPUT   The new value is less than the current
109  *                                      counter value
110  * \retval TFM_PLAT_ERR_MAX_VALUE       The new value is greater than the
111  *                                      maximum value of the NV counter
112  * \retval TFM_PLAT_ERR_UNSUPPORTED     The function is not implemented for
113  *                                      the given platform or the new value is
114  *                                      not representable on the underlying
115  *                                      counter implementation
116  * \retval TFM_PLAT_ERR_SYSTEM_ERR      An unspecified error occurred
117  *                                      (none of the other standard error codes
118  *                                      are applicable)
119  */
120 enum tfm_plat_err_t tfm_plat_set_nv_counter(enum tfm_nv_counter_t counter_id,
121                                             uint32_t value);
122 
123 #ifdef __cplusplus
124 }
125 #endif
126 
127 #endif /* __TFM_PLAT_NV_COUNTERS_H__ */
128