blob: 6097173d61f107b2b5d2a0fdf8bd036a54fe66ce [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 Okhrimenko89ecdac2020-02-28 17:05:55 +020025
Roman Okhrimenko977b3752022-03-31 14:40:48 +030026#ifdef CYW20829
27#include "cy_retarget_io.h"
28#include "cybsp.h"
29#include "cyhal_wdt.h"
30#include "cyw_20829_utils.h"
31#include "cy_service_app.h"
32#else
33#include "cy_retarget_io_pdl.h"
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -050034#include "cycfg_clocks.h"
35#include "cycfg_peripherals.h"
Roman Okhrimenko977b3752022-03-31 14:40:48 +030036#endif /* CYW20829 */
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -050037
38#include "flash_qspi.h"
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
Roman Okhrimenko0c7aebc2020-09-02 13:37:51 +030053#include "watchdog.h"
54
Roman Okhrimenko977b3752022-03-31 14:40:48 +030055#define CY_RSLT_MODULE_MCUBOOTAPP 0x500U
56#define CY_RSLT_MODULE_MCUBOOTAPP_MAIN 0x51U
57
58/** General module error */
59#define MCUBOOTAPP_RSLT_ERR \
60 (CY_RSLT_CREATE_EX(CY_RSLT_TYPE_ERROR, CY_RSLT_MODULE_MCUBOOTAPP, CY_RSLT_MODULE_MCUBOOTAPP_MAIN, 0))
61
Roman Okhrimenko0c7aebc2020-09-02 13:37:51 +030062/* WDT time out for reset mode, in milliseconds. */
63#define WDT_TIME_OUT_MS 4000
64
dmiv8672c8e2020-09-16 12:59:20 +030065#ifdef CY_BOOT_USE_EXTERNAL_FLASH
66/* Choose SMIF slot number (slave select).
67 * Acceptable values are:
68 * 0 - SMIF disabled (no external memory);
69 * 1, 2, 3 or 4 - slave select line memory module is connected to.
70 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +030071#define SMIF_ID (1U) /* Assume SlaveSelect_0 is used for External Memory */
72#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
dmiv8672c8e2020-09-16 12:59:20 +030073
Roman Okhrimenko977b3752022-03-31 14:40:48 +030074#define BOOT_MSG_FINISH "MCUBoot Bootloader finished.\n" \
75 "Deinitializing hardware..."
dmiv8672c8e2020-09-16 12:59:20 +030076
Roman Okhrimenko977b3752022-03-31 14:40:48 +030077static void hw_deinit(void);
dmiv8672c8e2020-09-16 12:59:20 +030078
Roman Okhrimenko977b3752022-03-31 14:40:48 +030079static inline __attribute__((always_inline))
80fih_uint calc_app_addr(uintptr_t flash_base, const struct boot_rsp *rsp)
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +020081{
Roman Okhrimenko977b3752022-03-31 14:40:48 +030082 return fih_uint_encode(flash_base +
83 rsp->br_image_off +
84 rsp->br_hdr->ih_hdr_size);
85}
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +020086
Roman Okhrimenko977b3752022-03-31 14:40:48 +030087#ifdef CYW20829
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +020088
Roman Okhrimenko977b3752022-03-31 14:40:48 +030089#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP)
90CY_RAMFUNC_BEGIN /* SMIF will be deinitialized in this case! */
91#else
92inline __attribute__((always_inline))
93#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) */
94__NO_RETURN
95static void cyw20829_launch_app(fih_uint app_addr, uint32_t *key, uint32_t *iv)
96{
97#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP)
98 qspi_deinit(SMIF_ID);
99#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) */
100 cyw20829_RunApp(app_addr, key, iv);
101}
102#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP)
103CY_RAMFUNC_END /* SMIF will be deinitialized in this case! */
104#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) */
Roman Okhrimenkoff026122020-09-23 12:58:07 +0300105
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300106#endif /* CYW20829 */
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200107
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300108static bool do_boot(struct boot_rsp *rsp)
109{
110 uintptr_t flash_base = 0;
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200111
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300112#ifdef CYW20829
113 uint32_t *key = NULL;
114 uint32_t *iv = NULL;
115#endif /* CYW20829 */
116
117 if (rsp != NULL) {
118 int rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
119
120 if (0 == rc) {
121 fih_uint app_addr = calc_app_addr(flash_base, rsp);
122
123 BOOT_LOG_INF("Starting User Application (wait)...");
124 if (IS_ENCRYPTED(rsp->br_hdr)) {
125 BOOT_LOG_DBG(" * User application is encrypted");
126 }
127 BOOT_LOG_INF("Start slot Address: 0x%08" PRIx32, (uint32_t)fih_uint_decode(app_addr));
128
129 rc = flash_device_base(rsp->br_flash_dev_id, &flash_base);
130 if ((rc != 0) || fih_uint_not_eq(calc_app_addr(flash_base, rsp), app_addr)) {
131 return false;
132 }
133
134#ifdef CYW20829
135#ifdef MCUBOOT_ENC_IMAGES_XIP
136 if (IS_ENCRYPTED(rsp->br_hdr)) {
137 key = rsp->xip_key;
138 iv = rsp->xip_iv;
139 } else {
140 BOOT_LOG_ERR("User image is not encrypted, while MCUBootApp is compiled with encryption support.");
141 return false;
142 }
143#endif /* MCUBOOT_ENC_IMAGES_XIP */
144 /* This function does not return */
145 BOOT_LOG_INF(BOOT_MSG_FINISH);
146 hw_deinit();
147 cyw20829_launch_app(app_addr, key, iv);
148#else
149 /* This function turns on CM4 and returns */
150 BOOT_LOG_INF(BOOT_MSG_FINISH);
151
152 hw_deinit();
153#ifdef USE_XIP
154 BOOT_LOG_DBG("XIP: Switch to SMIF XIP mode");
155 qspi_set_mode(CY_SMIF_MEMORY);
156#endif
157 Cy_SysEnableCM4(fih_uint_decode(app_addr));
158 return true;
159#endif /* CYW20829 */
160 } else {
161 BOOT_LOG_ERR("Flash device ID not found");
162 return false;
163 }
164 }
165
166 return false;
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200167}
168
169int main(void)
170{
Bohdan Kovalchuka333a452020-07-09 16:55:58 +0300171 struct boot_rsp rsp;
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300172 cy_rslt_t rc = MCUBOOTAPP_RSLT_ERR;
Roman Okhrimenkoff026122020-09-23 12:58:07 +0300173 bool boot_succeeded = false;
Tamas Ban4e8d8382020-09-30 08:01:58 +0100174 fih_int fih_rc = FIH_FAILURE;
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200175
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300176#ifdef CYW20829
177 rc = cybsp_init();
178 if (rc != CY_RSLT_SUCCESS) {
179 CY_ASSERT((bool)0);
180 /* Loop forever... */
181 while (true) {
182 __WFI();
183 }
184 }
185#else
Roman Okhrimenko4bc28102021-02-01 19:31:41 +0200186 SystemInit();
Bohdan Kovalchuk77256522020-04-15 18:03:43 +0300187 init_cycfg_peripherals();
188 init_cycfg_pins();
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300189#endif /* CYW20829 */
190 /* enable interrupts */
191 __enable_irq();
dmiv8672c8e2020-09-16 12:59:20 +0300192
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300193 /* Certain PSoC 6 devices enable CM4 by default at startup. It must be
Roman Okhrimenko4bc28102021-02-01 19:31:41 +0200194 * either disabled or enabled & running a valid application for flash write
195 * to work from CM0+. Since flash write may happen in boot_go() for updating
196 * the image before this bootloader app can enable CM4 in do_boot(), we need
197 * to keep CM4 disabled. Note that debugging of CM4 is not supported when it
198 * is disabled.
199 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300200#ifndef CYW20829
201#if defined(CY_DEVICE_PSOC6ABLE2)
202 if (CY_SYS_CM4_STATUS_ENABLED == Cy_SysGetCM4Status()) {
Roman Okhrimenko4bc28102021-02-01 19:31:41 +0200203 Cy_SysDisableCM4();
204 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300205#endif /* defined(CY_DEVICE_PSOC6ABLE2) */
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200206
Bohdan Kovalchuk77256522020-04-15 18:03:43 +0300207 /* Initialize retarget-io to use the debug UART port (CYBSP_UART_HW) */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300208 rc = cy_retarget_io_pdl_init(CY_RETARGET_IO_BAUDRATE);
209#else
210 /* Initialize retarget-io to use the debug UART port */
211 rc = cy_retarget_io_init(CYBSP_DEBUG_UART_TX,
212 CYBSP_DEBUG_UART_RX,
213 CY_RETARGET_IO_BAUDRATE);
214#endif /* CYW20829 */
215 if (rc != CY_RSLT_SUCCESS) {
216 CY_ASSERT((bool)0);
217 /* Loop forever... */
218 while (true) {
219 __WFI();
220 }
dmiv8672c8e2020-09-16 12:59:20 +0300221 }
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200222
223 BOOT_LOG_INF("MCUBoot Bootloader Started");
224
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -0500225#ifdef CY_BOOT_USE_EXTERNAL_FLASH
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300226 {
227 cy_en_smif_status_t qspi_status = qspi_init_sfdp(SMIF_ID);
Bohdan Kovalchuka333a452020-07-09 16:55:58 +0300228
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300229 if (CY_SMIF_SUCCESS == qspi_status) {
230 rc = CY_RSLT_SUCCESS;
231 BOOT_LOG_INF("External Memory initialized w/ SFDP.");
232 } else {
233 rc = MCUBOOTAPP_RSLT_ERR;
234 BOOT_LOG_ERR("External Memory initialization w/ SFDP FAILED: 0x%08" PRIx32, (uint32_t)qspi_status);
235 }
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -0500236 }
Tamas Ban4e8d8382020-09-30 08:01:58 +0100237
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300238 if (CY_RSLT_SUCCESS == rc)
239#endif /* CY_BOOT_USE_EXTERNAL_FLASH */
240 {
241#if defined(CYW20829) && defined(MCUBOOT_HW_ROLLBACK_PROT)
242 /* Check service application completion status */
243 if (check_service_app_status() != 0) {
244 BOOT_LOG_ERR("Service application failed");
245 CY_ASSERT((bool)0);
246 /* Loop forever... */
247 while (true) {
248 __WFI();
249 }
250 }
251#endif /* CYW20829 && MCUBOOT_HW_ROLLBACK_PROT */
252
253 (void)memset(&rsp, 0, sizeof(rsp));
Tamas Ban4e8d8382020-09-30 08:01:58 +0100254 FIH_CALL(boot_go, fih_rc, &rsp);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300255 if (true == fih_eq(fih_rc, FIH_SUCCESS)) {
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -0500256 BOOT_LOG_INF("User Application validated successfully");
Roman Okhrimenko0c7aebc2020-09-02 13:37:51 +0300257 /* initialize watchdog timer. it should be updated from user app
258 * to mark successful start up of this app. if the watchdog is not updated,
259 * reset will be initiated by watchdog timer and swap revert operation started
260 * to roll back to operable image.
261 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300262#ifdef CYW20829
263 cyhal_wdt_t *cyw20829_wdt = NULL;
264
265 rc = cyhal_wdt_init(cyw20829_wdt, WDT_TIME_OUT_MS);
266#else
267 rc = cy_wdg_init(WDT_TIME_OUT_MS);
268#endif /* CYW20829 */
269 if (CY_RSLT_SUCCESS == rc) {
270
271 boot_succeeded = do_boot(&rsp);
272
273 if (!boot_succeeded) {
274 BOOT_LOG_ERR("Boot of next app failed");
275 }
276 } else {
277 BOOT_LOG_ERR("Failed to init WDT");
278 }
279 } else {
280 BOOT_LOG_ERR("MCUBoot Bootloader found none of bootable images");
dmiv8672c8e2020-09-16 12:59:20 +0300281 }
Bohdan Kovalchuk0324f1b2020-05-26 08:04:24 -0500282 }
dmiv8672c8e2020-09-16 12:59:20 +0300283
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300284 while (true) {
Roman Okhrimenkoff026122020-09-23 12:58:07 +0300285 if (boot_succeeded) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300286 (void)Cy_SysPm_CpuEnterDeepSleep(CY_SYSPM_WAIT_FOR_INTERRUPT);
287 } else {
Roman Okhrimenkoff026122020-09-23 12:58:07 +0300288 __WFI();
289 }
dmiv8672c8e2020-09-16 12:59:20 +0300290 }
Roman Okhrimenko89ecdac2020-02-28 17:05:55 +0200291}
dmiv8672c8e2020-09-16 12:59:20 +0300292
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300293static void hw_deinit(void)
dmiv8672c8e2020-09-16 12:59:20 +0300294{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300295#ifdef CYW20829
296 /* Flush the TX buffer, need to be fixed in retarget_io */
297 Cy_SysLib_Delay(50);
298
299 cy_retarget_io_deinit();
300 cy_wdg_stop();
301 cy_wdg_free();
302 /* Note: qspi_deinit() is called (if needed) in cyw20829_launch_app() above */
303#else
304 cy_retarget_io_wait_tx_complete(CYBSP_UART_HW, 10);
dmiv8672c8e2020-09-16 12:59:20 +0300305 cy_retarget_io_pdl_deinit();
306 Cy_GPIO_Port_Deinit(CYBSP_UART_RX_PORT);
307 Cy_GPIO_Port_Deinit(CYBSP_UART_TX_PORT);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300308#if defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) && !defined(USE_XIP)
309 qspi_deinit(SMIF_ID);
310#endif /* defined(CY_BOOT_USE_EXTERNAL_FLASH) && !defined(MCUBOOT_ENC_IMAGES_XIP) */
311#endif /* CYW20829 */
dmiv8672c8e2020-09-16 12:59:20 +0300312}