1 /*
2  * SPDX-FileCopyrightText: Copyright The TrustedFirmware-M Contributors
3  * Copyright 2020-2022 NXP. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  */
8 
9 #include "tfm_hal_device_header.h"
10 #include "target_cfg.h"
11 #include "tfm_hal_platform.h"
12 #include "tfm_plat_defs.h"
13 #include "uart_stdout.h"
14 #include "fih.h"
15 #include "region_defs.h"
16 #include "region.h"
17 #include "tfm_log.h"
18 
19 /* The section names come from the scatter file */
20 REGION_DECLARE(Load$$LR$$, LR_NS_PARTITION, $$Base);
21 REGION_DECLARE(Image$$, ER_VENEER, $$Base);
22 REGION_DECLARE(Image$$, VENEER_ALIGN, $$Limit);
23 #ifdef BL2
24 REGION_DECLARE(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base);
25 #endif /* BL2 */
26 
27 const struct memory_region_limits memory_regions = {
28     .non_secure_code_start =
29         (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
30         BL2_HEADER_SIZE,
31 
32     .non_secure_partition_base =
33         (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base),
34 
35     .non_secure_partition_limit =
36         (uint32_t)&REGION_NAME(Load$$LR$$, LR_NS_PARTITION, $$Base) +
37         NS_PARTITION_SIZE - 1,
38 
39     .veneer_base =
40         (uint32_t)&REGION_NAME(Image$$, ER_VENEER, $$Base),
41 
42     .veneer_limit =
43         (uint32_t)&REGION_NAME(Image$$, VENEER_ALIGN, $$Limit) - 1,
44 
45 #ifdef BL2
46     .secondary_partition_base =
47         (uint32_t)&REGION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base),
48 
49     .secondary_partition_limit =
50         (uint32_t)&REGION_NAME(Load$$LR$$, LR_SECONDARY_PARTITION, $$Base) +
51         SECONDARY_PARTITION_SIZE - 1,
52 #endif /* BL2 */
53 };
54 
55 extern void BOARD_InitHardware(void);
56 
tfm_hal_platform_init(void)57 FIH_RET_TYPE(enum tfm_hal_status_t) tfm_hal_platform_init(void)
58 {
59     enum tfm_plat_err_t plat_err = TFM_PLAT_ERR_SYSTEM_ERR;
60 
61     BOARD_InitHardware();
62 
63     stdio_init();
64 
65     plat_err = enable_fault_handlers();
66     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
67         FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
68     }
69 
70     plat_err = system_reset_cfg();
71     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
72         FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
73     }
74 
75     plat_err = init_debug();
76     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
77         FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
78     }
79 
80     __enable_irq();
81 
82     plat_err = nvic_interrupt_target_state_cfg();
83     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
84         FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
85     }
86 
87     plat_err = nvic_interrupt_enable();
88     if (plat_err != TFM_PLAT_ERR_SUCCESS) {
89         FIH_RET(fih_int_encode(TFM_HAL_ERROR_GENERIC));
90     }
91 
92     FIH_RET(fih_int_encode(TFM_HAL_SUCCESS));
93 }
94 
tfm_hal_get_ns_VTOR(void)95 uint32_t tfm_hal_get_ns_VTOR(void)
96 {
97     return memory_regions.non_secure_code_start;
98 }
99 
tfm_hal_get_ns_MSP(void)100 uint32_t tfm_hal_get_ns_MSP(void)
101 {
102     return *((uint32_t *)memory_regions.non_secure_code_start);
103 }
104 
tfm_hal_get_ns_entry_point(void)105 uint32_t tfm_hal_get_ns_entry_point(void)
106 {
107     return *((uint32_t *)(memory_regions.non_secure_code_start + 4));
108 }
109 
enable_fault_handlers(void)110 enum tfm_plat_err_t enable_fault_handlers(void)
111 {
112     /* Explicitly set secure fault priority to the highest */
113     NVIC_SetPriority(SecureFault_IRQn, 0);
114 
115     /* Enables BUS, MEM, USG and Secure faults */
116     SCB->SHCSR |= SCB_SHCSR_USGFAULTENA_Msk
117                   | SCB_SHCSR_BUSFAULTENA_Msk
118                   | SCB_SHCSR_MEMFAULTENA_Msk
119                   | SCB_SHCSR_SECUREFAULTENA_Msk;
120     return TFM_PLAT_ERR_SUCCESS;
121 }
122 
123 /* To write into AIRCR register, 0x5FA value must be write to the VECTKEY field,
124  * otherwise the processor ignores the write.
125  */
126 #define SCB_AIRCR_WRITE_MASK ((0x5FAUL << SCB_AIRCR_VECTKEY_Pos))
127 
system_reset_cfg(void)128 enum tfm_plat_err_t system_reset_cfg(void)
129 {
130     uint32_t reg_value = SCB->AIRCR;
131 
132     /* Clear SCB_AIRCR_VECTKEY value */
133     reg_value &= ~(uint32_t)(SCB_AIRCR_VECTKEY_Msk);
134 
135     /* Enable system reset request only to the secure world */
136     reg_value |= (uint32_t)(SCB_AIRCR_WRITE_MASK | SCB_AIRCR_SYSRESETREQS_Msk);
137 
138     SCB->AIRCR = reg_value;
139 
140     return TFM_PLAT_ERR_SUCCESS;
141 }
142 
init_debug(void)143 enum tfm_plat_err_t init_debug(void)
144 {
145 
146 #if !defined(DAUTH_CHIP_DEFAULT)
147 #error "Debug features are set during provisioning. Application is not able to change them as the SYSCTRL->DEBUG_LOCK_EN is locked by the MCU secure boot.  "
148 #endif
149     return TFM_PLAT_ERR_SUCCESS;
150 }
151 
152 /*----------------- NVIC interrupt target state to NS configuration ----------*/
nvic_interrupt_target_state_cfg(void)153 enum tfm_plat_err_t nvic_interrupt_target_state_cfg(void)
154 {
155     /* Target every interrupt to NS; unimplemented interrupts will be WI */
156     for (uint8_t i=0; i<sizeof(NVIC->ITNS)/sizeof(NVIC->ITNS[0]); i++) {
157         NVIC->ITNS[i] = 0xFFFFFFFF;
158     }
159 
160     /* Make sure that MPC and PPC are targeted to S state */
161     NVIC_ClearTargetState(SEC_VIO_IRQn);
162 
163     return TFM_PLAT_ERR_SUCCESS;
164 }
165 
166 /*----------------- NVIC interrupt enabling for S peripherals ----------------*/
nvic_interrupt_enable(void)167 enum tfm_plat_err_t nvic_interrupt_enable(void)
168 {
169     /* MPC/PPC interrupt enabling */
170     NVIC_EnableIRQ(SEC_VIO_IRQn);
171 
172     return TFM_PLAT_ERR_SUCCESS;
173 }
174 
175 /* Alternative Control Flow Integrity, using  Code Watchdog Timer */
176 #if defined(FIH_ENABLE_CFI) & defined(FIH_CFI_ALT) & defined(CDOG)
177 
178 #include "fsl_cdog.h"
179 
180 static volatile bool cdog_init_is_done = false;
fih_cdog_init(void)181 static void fih_cdog_init(void)
182 {
183     status_t result = kStatus_Fail;
184     cdog_config_t conf;
185 
186     /* Initialize CDOG */
187     CDOG_GetDefaultConfig(&conf);
188 
189     conf.timeout    = kCDOG_FaultCtrl_EnableInterrupt;
190     conf.miscompare = kCDOG_FaultCtrl_EnableInterrupt;
191     conf.sequence   = kCDOG_FaultCtrl_EnableInterrupt;
192     conf.state      = kCDOG_FaultCtrl_EnableInterrupt;
193     conf.address    = kCDOG_FaultCtrl_EnableInterrupt;
194     conf.irq_pause  = kCDOG_IrqPauseCtrl_Pause;
195     conf.debug_halt = kCDOG_DebugHaltCtrl_Pause;
196     conf.lock       = kCDOG_LockCtrl_Lock; /* Lock */ //kCDOG_LockCtrl_Unlock;
197 
198     /* Clears pending FLAGS and sets CONTROL register */
199     result = CDOG_Init(CDOG, &conf);
200     if (result != kStatus_Success)
201     {
202         ERROR_RAW("[CDOG] Init error.\n");
203         FIH_PANIC;
204     }
205 
206     cdog_init_is_done = true;
207 }
208 
CDOG_DriverIRQHandler(void)209 void CDOG_DriverIRQHandler(void)
210 {
211     NVIC_ClearPendingIRQ(CDOG_IRQn);
212 
213     ERROR_RAW("[CDOG IRQ] ");
214 
215     if ((CDOG->FLAGS & CDOG_FLAGS_TO_FLAG_MASK))
216     {
217         ERROR_RAW("Timeout ");
218     }
219     if ((CDOG->FLAGS & CDOG_FLAGS_MISCOM_FLAG_MASK))
220     {
221         ERROR_RAW("Miscompare ");
222     }
223     if ((CDOG->FLAGS & CDOG_FLAGS_SEQ_FLAG_MASK))
224     {
225         ERROR_RAW("Sequence ");
226     }
227     if ((CDOG->FLAGS & CDOG_FLAGS_CNT_FLAG_MASK))
228     {
229         ERROR_RAW("Control ");
230     }
231     if ((CDOG->FLAGS & CDOG_FLAGS_STATE_FLAG_MASK))
232     {
233         ERROR_RAW("State ");
234     }
235     if ((CDOG->FLAGS & CDOG_FLAGS_ADDR_FLAG_MASK))
236     {
237         ERROR_RAW("Address ");
238     }
239     ERROR_RAW("fault occured\n");
240 
241     FIH_PANIC;
242 }
243 
fih_cfi_get_and_increment(uint8_t cnt)244 fih_int fih_cfi_get_and_increment(uint8_t cnt)
245 {
246     fih_int saved_ctr = _fih_cfi_ctr;
247 
248     /* HW */
249     if(cdog_init_is_done == false)
250     {
251         fih_cdog_init();
252     }
253 
254     /* Start if in the IDLE state */
255     if((CDOG->STATUS & CDOG_STATUS_CURST_MASK) == CDOG_STATUS_CURST(0x5)) {
256         CDOG_Start(CDOG, 0xFFFFFFFF, fih_int_decode(saved_ctr));
257     }
258 
259     CDOG_Add(CDOG, cnt);
260 
261     /* SW */
262     _fih_cfi_ctr = fih_int_encode(fih_int_decode(_fih_cfi_ctr) + cnt);
263 
264     return saved_ctr;
265 }
266 
fih_cfi_validate(fih_int saved)267 void fih_cfi_validate(fih_int saved)
268 {
269     /* HW */
270     CDOG_Stop(CDOG, fih_int_decode(saved));
271 }
272 
fih_cfi_decrement(void)273 void fih_cfi_decrement(void)
274 {
275     /* HW */
276     /* Start if in the IDLE state */
277     if((CDOG->STATUS & 0xF0000000) == 0x50000000) {
278         CDOG_Start(CDOG, 0xFFFFFFFF, (fih_int_decode(_fih_cfi_ctr)));
279     }
280     CDOG_Sub1(CDOG);
281 
282     /* SW */
283     _fih_cfi_ctr = fih_int_encode(fih_int_decode(_fih_cfi_ctr) - 1);
284 }
285 #endif /* defined(FIH_ENABLE_CFI) & defined(FIH_CFI_ALT) & defined(CDOG) */
286 
287