blob: 926e36d1cdfc4ed2fd094a0e5de2d1b8f3798334 [file] [log] [blame]
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +02001/***************************************************************************//**
2* \file main.c
3* \version 1.0
4********************************************************************************
5* \copyright
6* SPDX-License-Identifier: Apache-2.0
7*
8* Licensed under the Apache License, Version 2.0 (the "License");
9* you may not use this file except in compliance with the License.
10* You may obtain a copy of the License at
11*
12* http://www.apache.org/licenses/LICENSE-2.0
13*
14* Unless required by applicable law or agreed to in writing, software
15* distributed under the License is distributed on an "AS IS" BASIS,
16* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17* See the License for the specific language governing permissions and
18* limitations under the License.
19*******************************************************************************/
Roman Okhrimenko977b3752022-03-31 14:40:48 +030020#include <inttypes.h>
21#include <stdbool.h>
22
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +020023/* Cypress pdl headers */
24#include "cy_pdl.h"
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030025#include "cyhal.h"
Roman Okhrimenko977b3752022-03-31 14:40:48 +030026#include "cyhal_wdt.h"
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030027
28#if defined CYW20829
Roman Okhrimenko977b3752022-03-31 14:40:48 +030029#include "cy_service_app.h"
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030030#endif
31
32#include "cybsp.h"
33#include "cy_retarget_io.h"
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +000034#include "cyw_platform_utils.h"
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -050035
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +000036#if defined(CY_BOOT_USE_EXTERNAL_FLASH) || defined(CYW20829)
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -050037#include "flash_qspi.h"
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +000038#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) || defined(CYW20829) */
Roman Okhrimenko977b3752022-03-31 14:40:48 +030039
40#include "cycfg_pins.h"
41#include "cy_result.h"
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +020042#include "sysflash/sysflash.h"
43#include "flash_map_backend/flash_map_backend.h"
44
45#include "bootutil/image.h"
46#include "bootutil/bootutil.h"
47#include "bootutil/sign_key.h"
48
49#include "bootutil/bootutil_log.h"
50
Tamas Ban4e8d8382020-09-30 08:01:58 +010051#include "bootutil/fault_injection_hardening.h"
Tamas Ban4e8d8382020-09-30 08:01:58 +010052
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +000053#ifdef USE_EXEC_TIME_CHECK
54#include "misc/timebase_us.h"
55#include "misc/exec_time_check.h"
56#endif /* USE_EXEC_TIME_CHECK */
57
58#ifdef USE_LOG_TIMESTAMP
59#include "timestamp.h"
60#endif /* USE_LOG_TIMESTAMP */
61
Roman Okhrimenko977b3752022-03-31 14:40:48 +030062#define CY_RSLT_MODULE_MCUBOOTAPP 0x500U
63#define CY_RSLT_MODULE_MCUBOOTAPP_MAIN 0x51U
64
65/** General module error */
66#define MCUBOOTAPP_RSLT_ERR \
67 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MCUBOOTAPP, CY_RSLT_MODULE_MCUBOOTAPP_MAIN, 0))
68
Roman Okhrimenko0c7aebc2020-09-02 13:37:51 +030069/* WDT time out for reset mode, in milliseconds. */
70#define WDT_TIME_OUT_MS 4000
71
dmiv8672c8e2020-09-16 12:59:20 +030072#ifdef CY_BOOT_USE_EXTERNAL_FLASH
73/* Choose SMIF slot number (slave select).
74 * Acceptable values are:
75 * 0 - SMIF disabled (no external memory);
76 * 1, 2, 3 or 4 - slave select line memory module is connected to.
77 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +030078#define SMIF_ID (1U) /* Assume SlaveSelect_0 is used for External Memory */
79#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
dmiv8672c8e2020-09-16 12:59:20 +030080
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030081#define BOOT_MSG_FINISH "MCUBoot Bootloader finished.\r\n" \
Roman Okhrimenko977b3752022-03-31 14:40:48 +030082 "Deinitializing hardware..."
dmiv8672c8e2020-09-16 12:59:20 +030083
Roman Okhrimenko977b3752022-03-31 14:40:48 +030084static void hw_deinit(void);
dmiv8672c8e2020-09-16 12:59:20 +030085
Roman Okhrimenko977b3752022-03-31 14:40:48 +030086static inline __attribute__((always_inline))
87fih_uint calc_app_addr(uintptr_t flash_base, const struct boot_rsp *rsp)
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +020088{
Roman Okhrimenko977b3752022-03-31 14:40:48 +030089 return fih_uint_encode(flash_base +
90 rsp->br_image_off +
91 rsp->br_hdr->ih_hdr_size);
92}
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +020093
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030094#if defined CYW20829
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +020095
Roman Okhrimenko977b3752022-03-31 14:40:48 +030096#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP)
97CY_RAMFUNC_BEGIN /* SMIF will be deinitialized in this case! */
98#else
99inline __attribute__((always_inline))
100#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) */
101__NO_RETURN
102static void cyw20829_launch_app(fih_uint app_addr, uint32_t *key, uint32_t *iv)
103{
104#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP)
105 qspi_deinit(SMIF_ID);
106#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) */
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000107 platform_RunNextApp(app_addr, key, iv);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300108}
109#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP)
110CY_RAMFUNC_END /* SMIF will be deinitialized in this case! */
111#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) */
Roman Okhrimenkoff026122020-09-23 12:58:07 +0300112
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300113#endif /* defined CYW20829 */
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200114
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300115static bool do_boot(struct boot_rsp *rsp)
116{
117 uintptr_t flash_base = 0;
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200118
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300119#if defined CYW20829
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300120 uint32_t *key = NULL;
121 uint32_t *iv = NULL;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300122#endif /* defined CYW20829 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300123
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300124 if ((rsp != NULL) && (rsp->br_hdr != NULL)) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300125 int rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
126
127 if (0 == rc) {
128 fih_uint app_addr = calc_app_addr(flash_base, rsp);
129
130 BOOT_LOG_INF("Starting User Application (wait)...");
131 if (IS_ENCRYPTED(rsp->br_hdr)) {
132 BOOT_LOG_DBG(" * User application is encrypted");
133 }
134 BOOT_LOG_INF("Start slot Address: 0x%08" PRIx32, (uint32_t)fih_uint_decode(app_addr));
135
136 rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300137 if (rc != 0 || fih_uint_eq(calc_app_addr(flash_base, rsp), app_addr) != FIH_TRUE) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300138 return false;
139 }
140
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300141#if defined CYW20829
142
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300143#ifdef MCUBOOT_ENC_IMAGES_XIP
144 if (IS_ENCRYPTED(rsp->br_hdr)) {
145 key = rsp->xip_key;
146 iv = rsp->xip_iv;
147 } else {
148 BOOT_LOG_ERR("User image is not encrypted, while MCUBootApp is compiled with encryption support.");
149 return false;
150 }
151#endif /* MCUBOOT_ENC_IMAGES_XIP */
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000152
153
154#ifdef APP_CM33
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300155 /* This function does not return */
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000156 BOOT_LOG_INF("Launching app on CM33 core");
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300157 BOOT_LOG_INF(BOOT_MSG_FINISH);
158 hw_deinit();
159 cyw20829_launch_app(app_addr, key, iv);
160#else
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000161#error "Application should run on Cortex-M33"
162#endif /* APP_CM33 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300163
Roman Okhrimenko25165622023-05-23 08:58:29 +0300164#else /* defined CYW20829 */
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000165
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300166#ifdef USE_XIP
167 BOOT_LOG_DBG("XIP: Switch to SMIF XIP mode");
168 qspi_set_mode(CY_SMIF_MEMORY);
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000169#endif /* USE_XIP */
170
171#ifdef APP_CM4
172 /* This function turns on CM4 and returns */
173 BOOT_LOG_INF("Launching app on CM4 core");
174 BOOT_LOG_INF(BOOT_MSG_FINISH);
175 hw_deinit();
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300176#ifdef BOOT_CM0P
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300177 Cy_SysEnableCM4(fih_uint_decode(app_addr));
178 return true;
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000179#else
180 psoc6_launch_cm4_app(app_addr);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300181#endif /* BOOT_CM0P */
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000182
183#elif defined APP_CM0P
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300184#ifdef BOOT_CM0P
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000185 /* This function does not return */
186 BOOT_LOG_INF("Launching app on CM0P core");
187 BOOT_LOG_INF(BOOT_MSG_FINISH);
188 hw_deinit();
189 psoc6_launch_cm0p_app(app_addr);
190#else
191#error "Application should run on Cortex-M4"
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300192#endif /* BOOT_CM0P */
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000193
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300194#elif defined APP_CM7
195 /* This function does not return */
196 BOOT_LOG_INF("Launching app on CM7 core");
197 BOOT_LOG_INF(BOOT_MSG_FINISH);
198 hw_deinit();
199 xmc7000_launch_cm7_app(app_addr);
200 return true;
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000201#else
202#error "Application should run on either Cortex-M0+ or Cortex-M4"
203#endif /* APP_CM4 */
204
205#endif /* defined CYW20829 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300206 } else {
207 BOOT_LOG_ERR("Flash device ID not found");
208 return false;
209 }
210 }
211
212 return false;
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200213}
214
215int main(void)
216{
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300217 struct boot_rsp rsp = {};
Roman Okhrimenkoff026122020-09-23 12:58:07 +0300218 bool boot_succeeded = false;
Tamas Ban4e8d8382020-09-30 08:01:58 +0100219 fih_int fih_rc = FIH_FAILURE;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300220 cy_rslt_t rc = cybsp_init();
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200221
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300222
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300223 if (rc != CY_RSLT_SUCCESS) {
224 CY_ASSERT((bool)0);
225 /* Loop forever... */
226 while (true) {
227 __WFI();
228 }
229 }
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000230
231#ifdef USE_EXEC_TIME_CHECK
232 timebase_us_init();
233#endif /* USE_EXEC_TIME_CHECK */
234
235#ifdef USE_LOG_TIMESTAMP
236 log_timestamp_init();
237#endif /* USE_LOG_TIMESTAMP */
238
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300239 /* enable interrupts */
240 __enable_irq();
dmiv8672c8e2020-09-16 12:59:20 +0300241
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300242 /* Certain PSoC 6 devices enable CM4 by default at startup. It must be
Roman Okhrimenko4bc28102021-02-01 19:31:41 +0200243 * either disabled or enabled & running a valid application for flash write
244 * to work from CM0+. Since flash write may happen in boot_go() for updating
245 * the image before this bootloader app can enable CM4 in do_boot(), we need
246 * to keep CM4 disabled. Note that debugging of CM4 is not supported when it
247 * is disabled.
248 */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300249#if defined(CY_DEVICE_PSOC6ABLE2) && !defined(BOOT_CM4)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300250 if (CY_SYS_CM4_STATUS_ENABLED == Cy_SysGetCM4Status()) {
Roman Okhrimenko4bc28102021-02-01 19:31:41 +0200251 Cy_SysDisableCM4();
252 }
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300253#endif /* defined(CY_DEVICE_PSOC6ABLE2) && !defined(BOOT_CM4) */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300254 /* Initialize retarget-io to use the debug UART port */
255 rc = cy_retarget_io_init(CYBSP_DEBUG_UART_TX,
256 CYBSP_DEBUG_UART_RX,
257 CY_RETARGET_IO_BAUDRATE);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300258
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300259 if (rc != CY_RSLT_SUCCESS) {
260 CY_ASSERT((bool)0);
261 /* Loop forever... */
262 while (true) {
263 __WFI();
264 }
dmiv8672c8e2020-09-16 12:59:20 +0300265 }
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200266
267 BOOT_LOG_INF("MCUBoot Bootloader Started");
268
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -0500269#ifdef CY_BOOT_USE_EXTERNAL_FLASH
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300270 {
271 cy_en_smif_status_t qspi_status = qspi_init_sfdp(SMIF_ID);
Bohdan Kovalchuka333a452020-07-09 16:55:58 +0300272
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300273 if (CY_SMIF_SUCCESS == qspi_status) {
274 rc = CY_RSLT_SUCCESS;
275 BOOT_LOG_INF("External Memory initialized w/ SFDP.");
276 } else {
277 rc = MCUBOOTAPP_RSLT_ERR;
278 BOOT_LOG_ERR("External Memory initialization w/ SFDP FAILED: 0x%08" PRIx32, (uint32_t)qspi_status);
279 }
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -0500280 }
Tamas Ban4e8d8382020-09-30 08:01:58 +0100281
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300282 if (CY_RSLT_SUCCESS == rc)
283#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
284 {
285#if defined(CYW20829) && defined(MCUBOOT_HW_ROLLBACK_PROT)
286 /* Check service application completion status */
287 if (check_service_app_status() != 0) {
288 BOOT_LOG_ERR("Service application failed");
289 CY_ASSERT((bool)0);
290 /* Loop forever... */
291 while (true) {
292 __WFI();
293 }
294 }
295#endif /* CYW20829 && MCUBOOT_HW_ROLLBACK_PROT */
296
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000297#ifdef USE_EXEC_TIME_CHECK
298 {
299 uint32_t exec_time;
300 EXEC_TIME_CHECK_BEGIN(&exec_time);
301#endif /* USE_EXEC_TIME_CHECK */
302 FIH_CALL(boot_go, fih_rc, &rsp);
303#ifdef USE_EXEC_TIME_CHECK
304 EXEC_TIME_CHECK_END();
305 BOOT_LOG_INF("Exec time: %" PRIu32 " [ms]", exec_time / 1000U);
306 }
307#endif /* USE_EXEC_TIME_CHECK */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300308 if (FIH_TRUE == fih_eq(fih_rc, FIH_SUCCESS)) {
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -0500309 BOOT_LOG_INF("User Application validated successfully");
Roman Okhrimenko0c7aebc2020-09-02 13:37:51 +0300310 /* initialize watchdog timer. it should be updated from user app
311 * to mark successful start up of this app. if the watchdog is not updated,
312 * reset will be initiated by watchdog timer and swap revert operation started
313 * to roll back to operable image.
314 */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300315 cyhal_wdt_t *wdt = NULL;
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300316
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300317 rc = cyhal_wdt_init(wdt, WDT_TIME_OUT_MS);
318
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300319 if (CY_RSLT_SUCCESS == rc) {
320
321 boot_succeeded = do_boot(&rsp);
322
323 if (!boot_succeeded) {
324 BOOT_LOG_ERR("Boot of next app failed");
325 }
326 } else {
327 BOOT_LOG_ERR("Failed to init WDT");
328 }
329 } else {
330 BOOT_LOG_ERR("MCUBoot Bootloader found none of bootable images");
dmiv8672c8e2020-09-16 12:59:20 +0300331 }
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -0500332 }
dmiv8672c8e2020-09-16 12:59:20 +0300333
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300334 while (true) {
Roman Okhrimenkoff026122020-09-23 12:58:07 +0300335 if (boot_succeeded) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300336 (void)Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
337 } else {
Roman Okhrimenkoff026122020-09-23 12:58:07 +0300338 __WFI();
339 }
dmiv8672c8e2020-09-16 12:59:20 +0300340 }
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200341}
dmiv8672c8e2020-09-16 12:59:20 +0300342
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300343static void hw_deinit(void)
dmiv8672c8e2020-09-16 12:59:20 +0300344{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300345#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) && !defined(USE_XIP)
346 qspi_deinit(SMIF_ID);
347#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300348
349 /* Flush the TX buffer, need to be fixed in retarget_io */
350 while(cy_retarget_io_is_tx_active()){}
351 cy_retarget_io_deinit();
Dovhal Artem (CSUKR CSS ICW SW FW 1)f7a3d1b2022-04-01 15:07:37 +0000352
353#ifdef USE_EXEC_TIME_CHECK
354 timebase_us_deinit();
355#endif /* USE_EXEC_TIME_CHECK */
356
357#ifdef USE_LOG_TIMESTAMP
358 log_timestamp_deinit();
359#endif /* USE_LOG_TIMESTAMP */
dmiv8672c8e2020-09-16 12:59:20 +0300360}