blob: b50489626782e529c510504a038f1e6927344755 [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>
Fabio Utzig1d46c942018-02-26 10:38:00 -030034#include <sysinit/sysinit.h>
Fabio Utzig19356bf2017-05-11 16:19:36 -030035#ifdef MCUBOOT_SERIAL
Christopher Collinscf18a032017-02-06 15:10:45 -080036#include <hal/hal_gpio.h>
Marko Kiiskila316d3612018-06-05 12:03:27 +030037#include <hal/hal_nvreg.h>
Christopher Collinscf18a032017-02-06 15:10:45 -080038#include <boot_serial/boot_serial.h>
Christopher Collinscf18a032017-02-06 15:10:45 -080039#endif
Marko Kiiskilace50ab02018-06-06 11:33:33 +030040#if defined(MCUBOOT_SERIAL) && MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) != 0
41#include <boot_uart/boot_uart.h>
42#endif
Christopher Collinscf18a032017-02-06 15:10:45 -080043#include <console/console.h>
44#include "bootutil/image.h"
45#include "bootutil/bootutil.h"
Fabio Utzig94912c52018-05-07 08:38:23 -030046#include "bootutil/bootutil_log.h"
Christopher Collinscf18a032017-02-06 15:10:45 -080047
Fabio Utzig12f819f2018-03-29 16:20:53 -030048#define BOOT_AREA_DESC_MAX (256)
49#define AREA_DESC_MAX (BOOT_AREA_DESC_MAX)
Christopher Collinscf18a032017-02-06 15:10:45 -080050
Fabio Utzig19356bf2017-05-11 16:19:36 -030051#ifdef MCUBOOT_SERIAL
Marko Kiiskila316d3612018-06-05 12:03:27 +030052#define BOOT_SERIAL_INPUT_MAX (512)
Christopher Collinscf18a032017-02-06 15:10:45 -080053#endif
54
Marti Bolivareb940802017-05-01 23:15:29 -040055/*
56 * Temporary flash_device_base() implementation.
57 *
58 * TODO: remove this when mynewt needs to support flash_device_base()
59 * for devices with nonzero base addresses.
60 */
61int flash_device_base(uint8_t fd_id, uintptr_t *ret)
62{
63 *ret = 0;
64 return 0;
65}
66
Marko Kiiskila316d3612018-06-05 12:03:27 +030067#ifdef MCUBOOT_SERIAL
Marko Kiiskilace50ab02018-06-06 11:33:33 +030068#if MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) != 0
69
70/** Don't include null-terminator in comparison. */
71#define BOOT_SERIAL_DETECT_STRING_LEN \
72 (sizeof MYNEWT_VAL(BOOT_SERIAL_DETECT_STRING) - 1)
73
74/**
75 * Listens on the UART for the management string. Blocks for up to
76 * BOOT_SERIAL_DETECT_TIMEOUT milliseconds.
77 *
78 * @return true if the management string was received;
79 * false if the management string was not received
80 * before the UART listen timeout expired.
81 */
82static bool
83serial_detect_uart_string(void)
84{
85 uint32_t start_tick;
86 char buf[BOOT_SERIAL_DETECT_STRING_LEN] = { 0 };
87 char ch;
88 int newline;
89 int rc;
90
91 /* Calculate the timeout duration in OS cputime ticks. */
92 static const uint32_t timeout_dur =
93 MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) /
94 (1000.0 / MYNEWT_VAL(OS_CPUTIME_FREQ));
95
96 rc = boot_serial_uart_open();
97 assert(rc == 0);
98
99 start_tick = os_cputime_get32();
100
101 while (1) {
102 /* Read a single character from the UART. */
103 rc = boot_serial_uart_read(&ch, 1, &newline);
104 if (rc > 0) {
105 /* Eliminate the oldest character in the buffer to make room for
106 * the new one.
107 */
108 memmove(buf, buf + 1, BOOT_SERIAL_DETECT_STRING_LEN - 1);
109 buf[BOOT_SERIAL_DETECT_STRING_LEN - 1] = ch;
110
111 /* If the full management string has been received, indicate that
112 * the serial boot loader should start.
113 */
114 rc = memcmp(buf,
115 MYNEWT_VAL(BOOT_SERIAL_DETECT_STRING),
116 BOOT_SERIAL_DETECT_STRING_LEN);
117 if (rc == 0) {
118 boot_serial_uart_close();
119 return true;
120 }
121 }
122
123 /* Abort the listen on timeout. */
124 if (os_cputime_get32() >= start_tick + timeout_dur) {
125 boot_serial_uart_close();
126 return false;
127 }
128 }
129}
130#endif
131
Marko Kiiskila316d3612018-06-05 12:03:27 +0300132static void
133serial_boot_detect(void)
134{
135 /*
136 * Read retained register and compare with expected magic value.
137 * If it matches, await for download commands from serial.
138 */
139#if MYNEWT_VAL(BOOT_SERIAL_NVREG_INDEX) != -1
140 if (hal_nvreg_read(MYNEWT_VAL(BOOT_SERIAL_NVREG_INDEX)) ==
141 MYNEWT_VAL(BOOT_SERIAL_NVREG_MAGIC)) {
142
143 hal_nvreg_write(MYNEWT_VAL(BOOT_SERIAL_NVREG_INDEX), 0);
144
145 boot_serial_start(BOOT_SERIAL_INPUT_MAX);
146 assert(0);
147 }
148
149#endif
150
151 /*
152 * Configure a GPIO as input, and compare it against expected value.
153 * If it matches, await for download commands from serial.
154 */
155#if MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN) != -1
156 hal_gpio_init_in(MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN),
157 MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN_CFG));
158 if (hal_gpio_read(MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN)) ==
159 MYNEWT_VAL(BOOT_SERIAL_DETECT_PIN_VAL)) {
160 boot_serial_start(BOOT_SERIAL_INPUT_MAX);
161 assert(0);
162 }
163#endif
164
165 /*
166 * Listen for management pattern in UART input. If detected, await for
167 * download commands from serial.
168 */
169#if MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) != 0
Marko Kiiskilace50ab02018-06-06 11:33:33 +0300170 if (serial_detect_uart_string()) {
Marko Kiiskila316d3612018-06-05 12:03:27 +0300171 boot_serial_start(BOOT_SERIAL_INPUT_MAX);
172 assert(0);
173 }
174#endif
175}
176#endif
177
Christopher Collinscf18a032017-02-06 15:10:45 -0800178int
179main(void)
180{
181 struct boot_rsp rsp;
Marti Bolivareb940802017-05-01 23:15:29 -0400182 uintptr_t flash_base;
Christopher Collinscf18a032017-02-06 15:10:45 -0800183 int rc;
184
Andrzej Kaczmarekc49099c2018-02-16 17:10:51 +0100185 hal_bsp_init();
Fabio Utzig1d46c942018-02-26 10:38:00 -0300186
Fabio Utzig94912c52018-05-07 08:38:23 -0300187#if defined(MCUBOOT_SERIAL) || defined(MCUBOOT_HAVE_LOGGING)
Fabio Utzig9f7c3d22018-02-16 14:55:28 -0200188 /* initialize uart without os */
189 os_dev_initialize_all(OS_DEV_INIT_PRIMARY);
Marko Kiiskila316d3612018-06-05 12:03:27 +0300190 os_dev_initialize_all(OS_DEV_INIT_SECONDARY);
Christopher Collinscf18a032017-02-06 15:10:45 -0800191 sysinit();
Fabio Utzig1d46c942018-02-26 10:38:00 -0300192 console_blocking_mode();
Marko Kiiskila316d3612018-06-05 12:03:27 +0300193#if defined(MCUBOOT_SERIAL)
194 serial_boot_detect();
195#endif
Fabio Utzig94912c52018-05-07 08:38:23 -0300196#else
197 flash_map_init();
198#endif
Christopher Collinscf18a032017-02-06 15:10:45 -0800199
Christopher Collinscf18a032017-02-06 15:10:45 -0800200 rc = boot_go(&rsp);
201 assert(rc == 0);
202
Fabio Utzigb00d6482017-06-20 19:28:22 -0300203 rc = flash_device_base(rsp.br_flash_dev_id, &flash_base);
Marti Bolivareb940802017-05-01 23:15:29 -0400204 assert(rc == 0);
205
206 hal_system_start((void *)(flash_base + rsp.br_image_off +
207 rsp.br_hdr->ih_hdr_size));
Christopher Collinscf18a032017-02-06 15:10:45 -0800208
209 return 0;
210}