blob: a054fa965a07926f9410470b8f18fe511e2f5f06 [file] [log] [blame]
Christopher Collinscf18a032017-02-06 15:10:45 -08001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
Fabio Utzig1a2e41a2017-11-17 12:13:09 -020020#include "mcuboot_config/mcuboot_config.h"
Fabio Utzig1a2e41a2017-11-17 12:13:09 -020021
Christopher Collinscf18a032017-02-06 15:10:45 -080022#include <assert.h>
23#include <stddef.h>
24#include <inttypes.h>
Fabio Utzig1d46c942018-02-26 10:38:00 -030025#include <stdio.h>
Marko Kiiskilace50ab02018-06-06 11:33:33 +030026
27#include <syscfg/syscfg.h>
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020028#include <flash_map_backend/flash_map_backend.h>
Christopher Collinscf18a032017-02-06 15:10:45 -080029#include <os/os.h>
30#include <bsp/bsp.h>
31#include <hal/hal_bsp.h>
32#include <hal/hal_system.h>
33#include <hal/hal_flash.h>
Marko Kiiskila149b4572018-06-06 14:18:54 +030034#include <hal/hal_watchdog.h>
Fabio Utzig1d46c942018-02-26 10:38:00 -030035#include <sysinit/sysinit.h>
Fabio Utzig19356bf2017-05-11 16:19:36 -030036#ifdef MCUBOOT_SERIAL
Christopher Collinscf18a032017-02-06 15:10:45 -080037#include <hal/hal_gpio.h>
Marko Kiiskila316d3612018-06-05 12:03:27 +030038#include <hal/hal_nvreg.h>
Christopher Collinscf18a032017-02-06 15:10:45 -080039#include <boot_serial/boot_serial.h>
Christopher Collinscf18a032017-02-06 15:10:45 -080040#endif
Marko Kiiskila149b4572018-06-06 14:18:54 +030041#if defined(MCUBOOT_SERIAL)
Marko Kiiskilace50ab02018-06-06 11:33:33 +030042#include <boot_uart/boot_uart.h>
43#endif
Christopher Collinscf18a032017-02-06 15:10:45 -080044#include <console/console.h>
45#include "bootutil/image.h"
46#include "bootutil/bootutil.h"
Fabio Utzig94912c52018-05-07 08:38:23 -030047#include "bootutil/bootutil_log.h"
Tamas Ban76177e12020-09-30 08:01:05 +010048#include "bootutil/fault_injection_hardening.h"
Christopher Collinscf18a032017-02-06 15:10:45 -080049
Fabio Utzige47ccd62019-10-18 10:55:22 -030050#if MYNEWT_VAL(BOOT_CUSTOM_START)
51void boot_custom_start(uintptr_t flash_base, struct boot_rsp *rsp);
52#endif
53
Jerzy Kasenbergcbb5b232021-11-25 10:21:11 +010054#if MYNEWT_VAL(BOOT_PREBOOT)
55void boot_preboot(void);
56#endif
57
Marko Kiiskila149b4572018-06-06 14:18:54 +030058#if defined(MCUBOOT_SERIAL)
59#define BOOT_SERIAL_REPORT_DUR \
60 (MYNEWT_VAL(OS_CPUTIME_FREQ) / MYNEWT_VAL(BOOT_SERIAL_REPORT_FREQ))
Marko Kiiskila316d3612018-06-05 12:03:27 +030061#define BOOT_SERIAL_INPUT_MAX (512)
Christopher Collinscf18a032017-02-06 15:10:45 -080062
Marko Kiiskila149b4572018-06-06 14:18:54 +030063static int boot_read(char *str, int cnt, int *newline);
64static const struct boot_uart_funcs boot_uart_funcs = {
65 .read = boot_read,
66 .write = boot_uart_write
67};
68
69static int
70boot_read(char *str, int cnt, int *newline)
Marti Bolivareb940802017-05-01 23:15:29 -040071{
Marko Kiiskila149b4572018-06-06 14:18:54 +030072#if MYNEWT_VAL(BOOT_SERIAL_REPORT_PIN) != -1
73 static uint32_t tick = 0;
74
75 if (tick == 0) {
76 /*
77 * Configure GPIO line as output. This is a pin we toggle at the
78 * given frequency.
79 */
80 hal_gpio_init_out(MYNEWT_VAL(BOOT_SERIAL_REPORT_PIN), 0);
81 tick = os_cputime_get32();
82 } else {
83 if (os_cputime_get32() - tick > BOOT_SERIAL_REPORT_DUR) {
84 hal_gpio_toggle(MYNEWT_VAL(BOOT_SERIAL_REPORT_PIN));
85 tick = os_cputime_get32();
86 }
87 }
88#endif
89 hal_watchdog_tickle();
90
91 return boot_uart_read(str, cnt, newline);
Marti Bolivareb940802017-05-01 23:15:29 -040092}
93
Marko Kiiskilace50ab02018-06-06 11:33:33 +030094#if MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) != 0
95
96/** Don't include null-terminator in comparison. */
97#define BOOT_SERIAL_DETECT_STRING_LEN \
98 (sizeof MYNEWT_VAL(BOOT_SERIAL_DETECT_STRING) - 1)
99
100/**
101 * Listens on the UART for the management string. Blocks for up to
102 * BOOT_SERIAL_DETECT_TIMEOUT milliseconds.
103 *
104 * @return true if the management string was received;
105 * false if the management string was not received
106 * before the UART listen timeout expired.
107 */
108static bool
109serial_detect_uart_string(void)
110{
111 uint32_t start_tick;
112 char buf[BOOT_SERIAL_DETECT_STRING_LEN] = { 0 };
113 char ch;
114 int newline;
115 int rc;
116
117 /* Calculate the timeout duration in OS cputime ticks. */
118 static const uint32_t timeout_dur =
119 MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) /
120 (1000.0 / MYNEWT_VAL(OS_CPUTIME_FREQ));
121
Marko Kiiskila149b4572018-06-06 14:18:54 +0300122 rc = boot_uart_open();
Marko Kiiskilace50ab02018-06-06 11:33:33 +0300123 assert(rc == 0);
124
125 start_tick = os_cputime_get32();
126
127 while (1) {
128 /* Read a single character from the UART. */
Marko Kiiskila149b4572018-06-06 14:18:54 +0300129 rc = boot_uart_read(&ch, 1, &newline);
Marko Kiiskilace50ab02018-06-06 11:33:33 +0300130 if (rc > 0) {
131 /* Eliminate the oldest character in the buffer to make room for
132 * the new one.
133 */
134 memmove(buf, buf + 1, BOOT_SERIAL_DETECT_STRING_LEN - 1);
135 buf[BOOT_SERIAL_DETECT_STRING_LEN - 1] = ch;
136
137 /* If the full management string has been received, indicate that
138 * the serial boot loader should start.
139 */
140 rc = memcmp(buf,
141 MYNEWT_VAL(BOOT_SERIAL_DETECT_STRING),
142 BOOT_SERIAL_DETECT_STRING_LEN);
143 if (rc == 0) {
Marko Kiiskila149b4572018-06-06 14:18:54 +0300144 boot_uart_close();
Marko Kiiskilace50ab02018-06-06 11:33:33 +0300145 return true;
146 }
147 }
148
149 /* Abort the listen on timeout. */
150 if (os_cputime_get32() >= start_tick + timeout_dur) {
Marko Kiiskila149b4572018-06-06 14:18:54 +0300151 boot_uart_close();
Marko Kiiskilace50ab02018-06-06 11:33:33 +0300152 return false;
153 }
154 }
155}
156#endif
157
Marko Kiiskila316d3612018-06-05 12:03:27 +0300158static void
159serial_boot_detect(void)
160{
161 /*
162 * Read retained register and compare with expected magic value.
163 * If it matches, await for download commands from serial.
164 */
165#if MYNEWT_VAL(BOOT_SERIAL_NVREG_INDEX) != -1
166 if (hal_nvreg_read(MYNEWT_VAL(BOOT_SERIAL_NVREG_INDEX)) ==
167 MYNEWT_VAL(BOOT_SERIAL_NVREG_MAGIC)) {
168
169 hal_nvreg_write(MYNEWT_VAL(BOOT_SERIAL_NVREG_INDEX), 0);
Marko Kiiskila149b4572018-06-06 14:18:54 +0300170 goto serial_boot;
Marko Kiiskila316d3612018-06-05 12:03:27 +0300171 }
Marko Kiiskila316d3612018-06-05 12:03:27 +0300172#endif
173
174 /*
175 * Configure a GPIO as input, and compare it against expected value.
176 * If it matches, await for download commands from serial.
177 */
178#if MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN) != -1
179 hal_gpio_init_in(MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN),
180 MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN_CFG));
181 if (hal_gpio_read(MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN)) ==
182 MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN_VAL)) {
Marko Kiiskila149b4572018-06-06 14:18:54 +0300183 goto serial_boot;
Marko Kiiskila316d3612018-06-05 12:03:27 +0300184 }
185#endif
186
187 /*
188 * Listen for management pattern in UART input. If detected, await for
189 * download commands from serial.
190 */
191#if MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) != 0
Marko Kiiskilace50ab02018-06-06 11:33:33 +0300192 if (serial_detect_uart_string()) {
Marko Kiiskila149b4572018-06-06 14:18:54 +0300193 goto serial_boot;
Marko Kiiskila316d3612018-06-05 12:03:27 +0300194 }
195#endif
Marko Kiiskila149b4572018-06-06 14:18:54 +0300196 return;
197serial_boot:
198 boot_uart_open();
199 boot_serial_start(&boot_uart_funcs);
200 assert(0);
Marko Kiiskila316d3612018-06-05 12:03:27 +0300201}
202#endif
203
Marko Kiiskila149b4572018-06-06 14:18:54 +0300204/*
205 * Temporary flash_device_base() implementation.
206 *
207 * TODO: remove this when mynewt needs to support flash_device_base()
208 * for devices with nonzero base addresses.
209 */
210int flash_device_base(uint8_t fd_id, uintptr_t *ret)
211{
212 *ret = 0;
213 return 0;
214}
215
Christopher Collinscf18a032017-02-06 15:10:45 -0800216int
217main(void)
218{
219 struct boot_rsp rsp;
Marti Bolivareb940802017-05-01 23:15:29 -0400220 uintptr_t flash_base;
Christopher Collinscf18a032017-02-06 15:10:45 -0800221 int rc;
Michael Grand5047f032022-11-24 16:49:56 +0100222 fih_ret fih_rc = FIH_FAILURE;
Christopher Collinscf18a032017-02-06 15:10:45 -0800223
Andrzej Kaczmarekc49099c2018-02-16 17:10:51 +0100224 hal_bsp_init();
Fabio Utzig1d46c942018-02-26 10:38:00 -0300225
Fabio Utzig0f29c482018-07-26 14:53:36 -0300226#if !MYNEWT_VAL(OS_SCHEDULING) && MYNEWT_VAL(WATCHDOG_INTERVAL)
227 rc = hal_watchdog_init(MYNEWT_VAL(WATCHDOG_INTERVAL));
228 assert(rc == 0);
229#endif
230
Fabio Utzigaf1e02e2019-06-14 08:56:41 -0300231#if defined(MCUBOOT_SERIAL) || defined(MCUBOOT_HAVE_LOGGING) || \
232 MYNEWT_VAL(CRYPTO) || MYNEWT_VAL(HASH)
Fabio Utzigad0e9b82019-02-18 16:13:01 -0300233 /* initialize uart/crypto without os */
Fabio Utzig9f7c3d22018-02-16 14:55:28 -0200234 os_dev_initialize_all(OS_DEV_INIT_PRIMARY);
Marko Kiiskila316d3612018-06-05 12:03:27 +0300235 os_dev_initialize_all(OS_DEV_INIT_SECONDARY);
Christopher Collinscf18a032017-02-06 15:10:45 -0800236 sysinit();
Fabio Utzig1d46c942018-02-26 10:38:00 -0300237 console_blocking_mode();
Marko Kiiskila316d3612018-06-05 12:03:27 +0300238#if defined(MCUBOOT_SERIAL)
239 serial_boot_detect();
Fabio Utzig3b69d6f2018-06-25 13:59:36 -0300240 hal_timer_deinit(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM));
Marko Kiiskila316d3612018-06-05 12:03:27 +0300241#endif
Fabio Utzig94912c52018-05-07 08:38:23 -0300242#else
243 flash_map_init();
244#endif
Christopher Collinscf18a032017-02-06 15:10:45 -0800245
Jerzy Kasenbergcbb5b232021-11-25 10:21:11 +0100246#if MYNEWT_VAL(BOOT_PREBOOT)
247 boot_preboot();
248#endif
Tamas Ban76177e12020-09-30 08:01:05 +0100249 FIH_CALL(boot_go, fih_rc, &rsp);
Michael Grand5047f032022-11-24 16:49:56 +0100250 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
251 assert(fih_rc == FIH_SUCCESS);
Tamas Ban76177e12020-09-30 08:01:05 +0100252 FIH_PANIC;
253 }
Christopher Collinscf18a032017-02-06 15:10:45 -0800254
Fabio Utzigb00d6482017-06-20 19:28:22 -0300255 rc = flash_device_base(rsp.br_flash_dev_id, &flash_base);
Marti Bolivareb940802017-05-01 23:15:29 -0400256 assert(rc == 0);
257
Fabio Utzige47ccd62019-10-18 10:55:22 -0300258#if MYNEWT_VAL(BOOT_CUSTOM_START)
259 boot_custom_start(flash_base, &rsp);
260#else
Jerzy Kasenberg1d0467e2020-11-21 23:45:34 +0100261 hal_bsp_deinit();
Marti Bolivareb940802017-05-01 23:15:29 -0400262 hal_system_start((void *)(flash_base + rsp.br_image_off +
263 rsp.br_hdr->ih_hdr_size));
Fabio Utzige47ccd62019-10-18 10:55:22 -0300264#endif
Christopher Collinscf18a032017-02-06 15:10:45 -0800265
266 return 0;
267}