boot_serial; text size reduction.
- Remove dependency to sprintf()
- Remove dependency to cborattr
- mynewt: replace console with more direct interface to uart
- mynewt: settings to reduce included os code
Signed-off-by: Marko Kiiskila <marko@runtime.io>
diff --git a/boot/boot_serial/pkg.yml b/boot/boot_serial/pkg.yml
index dd92cf4..69d90e1 100644
--- a/boot/boot_serial/pkg.yml
+++ b/boot/boot_serial/pkg.yml
@@ -32,8 +32,8 @@
- "@apache-mynewt-core/encoding/cborattr"
- "@apache-mynewt-core/encoding/base64"
- "@mcuboot/boot/mynewt/flash_map_backend"
+ - "@mcuboot/boot/mynewt/boot_uart"
- "@apache-mynewt-core/util/crc"
pkg.req_apis:
- - console
- bootloader
diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c
index 623225c..e67e68d 100644
--- a/boot/boot_serial/src/boot_serial.c
+++ b/boot/boot_serial/src/boot_serial.c
@@ -40,11 +40,15 @@
#include <hal/hal_system.h>
#include <os/endian.h>
#include <os/os_cputime.h>
-#include <console/console.h>
+#include <boot_uart/boot_uart.h>
#include <crc/crc16.h>
#include <base64/base64.h>
#include <tinycbor/cbor.h>
#include <tinycbor/cbor_buf_reader.h>
+
+#define console_write boot_uart_write
+#define console_read boot_uart_read
+
#endif /* __ZEPHYR__ */
#include <cborattr/cborattr.h>
@@ -58,7 +62,7 @@
#include "boot_serial/boot_serial.h"
#include "boot_serial_priv.h"
-#define BOOT_SERIAL_OUT_MAX 48
+#define BOOT_SERIAL_OUT_MAX 80
#ifdef __ZEPHYR__
/* base64 lib encodes data to null-terminated string */
@@ -93,6 +97,10 @@
int
bs_cbor_writer(struct cbor_encoder_writer *cew, const char *data, int len)
{
+ if (cew->bytes_written + len > sizeof(bs_obuf)) {
+ return CborErrorOutOfMemory;
+ }
+
memcpy(&bs_obuf[cew->bytes_written], data, len);
cew->bytes_written += len;
@@ -100,31 +108,49 @@
}
/*
- * Looks for 'name' from NULL-terminated json data in buf.
- * Returns pointer to first character of value for that name.
- * Returns NULL if 'name' is not found.
+ * Convert version into string without use of snprintf().
*/
-char *
-bs_find_val(char *buf, char *name)
+static int
+u32toa(char *tgt, uint32_t val)
{
- char *ptr;
+ char *dst;
+ uint32_t d = 1;
+ uint32_t dgt;
+ int n = 0;
- ptr = strstr(buf, name);
- if (!ptr) {
- return NULL;
+ dst = tgt;
+ while (val / d >= 10) {
+ d *= 10;
}
- ptr += strlen(name);
-
- while (*ptr != '\0') {
- if (*ptr != ':' && !isspace((int)*ptr)) {
- break;
+ while (d) {
+ dgt = val / d;
+ val %= d;
+ d /= 10;
+ if (n || dgt > 0 || d == 0) {
+ *dst++ = dgt + '0';
+ ++n;
}
- ++ptr;
}
- if (*ptr == '\0') {
- ptr = NULL;
- }
- return ptr;
+ *dst = '\0';
+
+ return dst - tgt;
+}
+
+/*
+ * dst has to be able to fit "255.255.65535.4294967295" (25 characters).
+ */
+static void
+bs_list_img_ver(char *dst, int maxlen, struct image_version *ver)
+{
+ int off;
+
+ off = u32toa(dst, ver->iv_major);
+ dst[off++] = '.';
+ off += u32toa(dst + off, ver->iv_minor);
+ dst[off++] = '.';
+ off += u32toa(dst + off, ver->iv_revision);
+ dst[off++] = '.';
+ off += u32toa(dst + off, ver->iv_build_num);
}
/*
@@ -164,9 +190,7 @@
cbor_encode_int(&image, i);
cbor_encode_text_stringz(&image, "version");
- len = snprintf((char *)tmpbuf, sizeof(tmpbuf),
- "%u.%u.%u.%u", hdr.ih_ver.iv_major, hdr.ih_ver.iv_minor,
- hdr.ih_ver.iv_revision, (unsigned int)hdr.ih_ver.iv_build_num);
+ bs_list_img_ver((char *)tmpbuf, sizeof(tmpbuf), &hdr.ih_ver);
cbor_encode_text_stringz(&image, (char *)tmpbuf);
cbor_encoder_close_container(&images, &image);
}
@@ -183,47 +207,115 @@
{
CborParser parser;
struct cbor_buf_reader reader;
+ struct CborValue root_value;
struct CborValue value;
- uint8_t img_data[400];
- long long unsigned int off = UINT_MAX;
+ uint8_t img_data[512];
+ long long int off = UINT_MAX;
size_t img_blen = 0;
uint8_t rem_bytes;
- long long unsigned int data_len = UINT_MAX;
- const struct cbor_attr_t attr[4] = {
- [0] = {
- .attribute = "data",
- .type = CborAttrByteStringType,
- .addr.bytestring.data = img_data,
- .addr.bytestring.len = &img_blen,
- .len = sizeof(img_data)
- },
- [1] = {
- .attribute = "off",
- .type = CborAttrUnsignedIntegerType,
- .addr.uinteger = &off,
- .nodefault = true
- },
- [2] = {
- .attribute = "len",
- .type = CborAttrUnsignedIntegerType,
- .addr.uinteger = &data_len,
- .nodefault = true
- }
- };
+ long long int data_len = UINT_MAX;
+ size_t slen;
+ char name_str[8];
const struct flash_area *fap = NULL;
int rc;
memset(img_data, 0, sizeof(img_data));
+
+ /*
+ * Expected data format.
+ * {
+ * "data":<img_data>
+ * "len":<image len>
+ * "off":<current offset of image data>
+ * }
+ */
+
+ /*
+ * Object comes within { ... }
+ */
cbor_buf_reader_init(&reader, (uint8_t *)buf, len);
#ifdef __ZEPHYR__
- cbor_parser_cust_reader_init(&reader.r, 0, &parser, &value);
+ cbor_parser_cust_reader_init(&reader.r, 0, &parser, &root_value);
#else
- cbor_parser_init(&reader.r, 0, &parser, &value);
+ cbor_parser_init(&reader.r, 0, &parser, &root_value);
#endif
- rc = cbor_read_object(&value, attr);
- if (rc || off == UINT_MAX) {
- rc = MGMT_ERR_EINVAL;
- goto out;
+ if (!cbor_value_is_container(&root_value)) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_enter_container(&root_value, &value)) {
+ goto out_invalid_data;
+ }
+ while (cbor_value_is_valid(&value)) {
+ /*
+ * Decode key.
+ */
+ if (cbor_value_calculate_string_length(&value, &slen)) {
+ goto out_invalid_data;
+ }
+ if (!cbor_value_is_text_string(&value) ||
+ slen >= sizeof(name_str) - 1) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_copy_text_string(&value, name_str, &slen, &value)) {
+ goto out_invalid_data;
+ }
+ name_str[slen] = '\0';
+ if (!strcmp(name_str, "data")) {
+ /*
+ * Image data
+ */
+ if (value.type != CborByteStringType) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_calculate_string_length(&value, &slen) ||
+ slen >= sizeof(img_data)) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_copy_byte_string(&value, img_data, &slen, &value)) {
+ goto out_invalid_data;
+ }
+ img_blen = slen;
+ } else if (!strcmp(name_str, "off")) {
+ /*
+ * Offset of the data.
+ */
+ if (value.type != CborIntegerType) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_get_int64(&value, &off)) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_advance(&value)) {
+ goto out_invalid_data;
+ }
+ } else if (!strcmp(name_str, "len")) {
+ /*
+ * Length of the image. This should only be present in the first
+ * block of data; when offset is 0.
+ */
+ if (value.type != CborIntegerType) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_get_int64(&value, &data_len)) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_advance(&value)) {
+ goto out_invalid_data;
+ }
+ } else {
+ /*
+ * Unknown keys.
+ */
+ if (cbor_value_advance(&value)) {
+ goto out_invalid_data;
+ }
+ }
+ }
+ if (off == UINT_MAX) {
+ /*
+ * Offset must be set in every block.
+ */
+ goto out_invalid_data;
}
rc = flash_area_open(flash_area_id_from_image_slot(0), &fap);
@@ -235,13 +327,11 @@
if (off == 0) {
curr_off = 0;
if (data_len > fap->fa_size) {
- rc = MGMT_ERR_EINVAL;
- goto out;
+ goto out_invalid_data;
}
rc = flash_area_erase(fap, 0, fap->fa_size);
if (rc) {
- rc = MGMT_ERR_EINVAL;
- goto out;
+ goto out_invalid_data;
}
img_size = data_len;
}
@@ -256,12 +346,12 @@
}
}
rc = flash_area_write(fap, curr_off, img_data, img_blen);
- if (rc) {
+ if (rc == 0) {
+ curr_off += img_blen;
+ } else {
+ out_invalid_data:
rc = MGMT_ERR_EINVAL;
- goto out;
}
- curr_off += img_blen;
-
out:
BOOT_LOG_INF("RX: 0x%x", rc);
cbor_encoder_create_map(&bs_root, &bs_rsp, CborIndefiniteLength);
@@ -278,11 +368,15 @@
}
/*
- * Console echo control. Send empty response, don't do anything.
+ * Console echo control/image erase. Send empty response, don't do anything.
*/
static void
-bs_echo_ctl(char *buf, int len)
+bs_empty_rsp(char *buf, int len)
{
+ cbor_encoder_create_map(&bs_root, &bs_rsp, CborIndefiniteLength);
+ cbor_encode_text_stringz(&bs_rsp, "rc");
+ cbor_encode_int(&bs_rsp, 0);
+ cbor_encoder_close_container(&bs_root, &bs_rsp);
boot_serial_output();
}
@@ -293,12 +387,8 @@
static void
bs_reset(char *buf, int len)
{
- cbor_encoder_create_map(&bs_root, &bs_rsp, CborIndefiniteLength);
- cbor_encode_text_stringz(&bs_rsp, "rc");
- cbor_encode_int(&bs_rsp, 0);
- cbor_encoder_close_container(&bs_root, &bs_rsp);
+ bs_empty_rsp(buf, len);
- boot_serial_output();
#ifdef __ZEPHYR__
k_sleep(250);
sys_reboot(SYS_REBOOT_COLD);
@@ -328,6 +418,7 @@
buf += sizeof(*hdr);
len -= sizeof(*hdr);
+
bs_writer.bytes_written = 0;
#ifdef __ZEPHYR__
cbor_encoder_cust_writer_init(&bs_root, &bs_writer, 0);
@@ -340,19 +431,20 @@
*/
if (hdr->nh_group == MGMT_GROUP_ID_IMAGE) {
switch (hdr->nh_id) {
- case IMGMGR_NMGR_OP_STATE:
+ case IMGMGR_NMGR_ID_STATE:
bs_list(buf, len);
break;
- case IMGMGR_NMGR_OP_UPLOAD:
+ case IMGMGR_NMGR_ID_UPLOAD:
bs_upload(buf, len);
break;
default:
+ bs_empty_rsp(buf, len);
break;
}
} else if (hdr->nh_group == MGMT_GROUP_ID_DEFAULT) {
switch (hdr->nh_id) {
case NMGR_ID_CONS_ECHO_CTRL:
- bs_echo_ctl(buf, len);
+ bs_empty_rsp(buf, len);
break;
case NMGR_ID_RESET:
bs_reset(buf, len);
@@ -378,13 +470,13 @@
len = bs_writer.bytes_written;
bs_hdr->nh_op++;
- bs_hdr->nh_flags = NMGR_F_CBOR_RSP_COMPLETE;
+ bs_hdr->nh_flags = 0;
bs_hdr->nh_len = htons(len);
bs_hdr->nh_group = htons(bs_hdr->nh_group);
#ifdef __ZEPHYR__
- crc = crc16((u8_t *)bs_hdr, sizeof(*bs_hdr), CRC_CITT_POLYMINAL, CRC16_INITIAL_CRC,
- false);
+ crc = crc16((u8_t *)bs_hdr, sizeof(*bs_hdr), CRC_CITT_POLYMINAL,
+ CRC16_INITIAL_CRC, false);
crc = crc16(data, len, CRC_CITT_POLYMINAL, crc, true);
#else
crc = crc16_ccitt(CRC16_INITIAL_CRC, bs_hdr, sizeof(*bs_hdr));
@@ -413,7 +505,7 @@
totlen = base64_encode(buf, totlen, encoded_buf, 1);
#endif
console_write(encoded_buf, totlen);
- console_write("\n", 1);
+ console_write("\n\r", 2);
BOOT_LOG_INF("TX");
}
@@ -484,13 +576,13 @@
dec = dec_buf;
assert(max_input <= sizeof(in_buf) && max_input <= sizeof(dec_buf));
#else
- rc = console_init(NULL);
+ rc = boot_uart_open();
assert(rc == 0);
- console_echo(0);
+
buf = os_malloc(max_input);
dec = os_malloc(max_input);
-#endif
assert(buf && dec);
+#endif
off = 0;
while (1) {
@@ -500,6 +592,12 @@
}
off += rc;
if (!full_line) {
+ if (off == max_input) {
+ /*
+ * Full line, no newline yet. Reset the input buffer.
+ */
+ off = 0;
+ }
continue;
}
if (buf[0] == SHELL_NLIP_PKT_START1 &&
diff --git a/boot/boot_serial/src/boot_serial_priv.h b/boot/boot_serial/src/boot_serial_priv.h
index 146aa6a..3b4c1ec 100644
--- a/boot/boot_serial/src/boot_serial_priv.h
+++ b/boot/boot_serial/src/boot_serial_priv.h
@@ -41,8 +41,6 @@
#define NMGR_OP_READ 0
#define NMGR_OP_WRITE 2
-#define NMGR_F_CBOR_RSP_COMPLETE 0x01
-
#define MGMT_GROUP_ID_DEFAULT 0
#define MGMT_GROUP_ID_IMAGE 1
@@ -61,9 +59,8 @@
/*
* From imgmgr.h
*/
-#define IMGMGR_NMGR_OP_STATE 0
-#define IMGMGR_NMGR_OP_UPLOAD 1
-
+#define IMGMGR_NMGR_ID_STATE 0
+#define IMGMGR_NMGR_ID_UPLOAD 1
void boot_serial_input(char *buf, int len);
diff --git a/boot/mynewt/boot_uart/include/boot_uart/boot_uart.h b/boot/mynewt/boot_uart/include/boot_uart/boot_uart.h
new file mode 100644
index 0000000..29b6d00
--- /dev/null
+++ b/boot/mynewt/boot_uart/include/boot_uart/boot_uart.h
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _BOOT_UART_H_
+#define _BOOT_UART_H_
+
+int boot_uart_open(void);
+void boot_uart_close(void);
+int boot_uart_read(char *str, int cnt, int *newline);
+void boot_uart_write(char *ptr, int cnt);
+
+#endif /* _BOOT_UART_H_ */
diff --git a/boot/mynewt/boot_uart/pkg.yml b/boot/mynewt/boot_uart/pkg.yml
new file mode 100644
index 0000000..a100a20
--- /dev/null
+++ b/boot/mynewt/boot_uart/pkg.yml
@@ -0,0 +1,32 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: boot/mynewt/boot_uart
+pkg.description: "For interfacing with uart from boot_serial"
+pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+ - loader
+ - boot
+ - bootloader
+
+pkg.deps:
+ - "@apache-mynewt-core/hw/hal"
+
+
diff --git a/boot/mynewt/boot_uart/src/boot_uart.c b/boot/mynewt/boot_uart/src/boot_uart.c
new file mode 100644
index 0000000..5e2fbbe
--- /dev/null
+++ b/boot/mynewt/boot_uart/src/boot_uart.c
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include <assert.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include "os/mynewt.h"
+#include <uart/uart.h>
+
+/*
+ * RX is a ring buffer, which gets drained constantly.
+ * TX blocks until buffer has been completely transmitted.
+ */
+#define CONSOLE_HEAD_INC(cr) (((cr)->head + 1) & (sizeof((cr)->buf) - 1))
+#define CONSOLE_TAIL_INC(cr) (((cr)->tail + 1) & (sizeof((cr)->buf) - 1))
+
+struct {
+ uint8_t head;
+ uint8_t tail;
+ uint8_t buf[16];
+} bs_uart_rx;
+
+struct {
+ uint8_t *ptr;
+ int cnt;
+} volatile bs_uart_tx;
+
+static struct uart_dev *bs_uart;
+
+static int bs_rx_char(void *arg, uint8_t byte);
+static int bs_tx_char(void *arg);
+
+int
+boot_uart_open(void)
+{
+ struct uart_conf uc = {
+ .uc_speed = MYNEWT_VAL(CONSOLE_UART_BAUD),
+ .uc_databits = 8,
+ .uc_stopbits = 1,
+ .uc_parity = UART_PARITY_NONE,
+ .uc_flow_ctl = MYNEWT_VAL(CONSOLE_UART_FLOW_CONTROL),
+ .uc_tx_char = bs_tx_char,
+ .uc_rx_char = bs_rx_char,
+ };
+
+ bs_uart = (struct uart_dev *)os_dev_open(MYNEWT_VAL(CONSOLE_UART_DEV),
+ OS_TIMEOUT_NEVER, &uc);
+ if (!bs_uart) {
+ return -1;
+ }
+ return 0;
+}
+
+void
+boot_uart_close(void)
+{
+ os_dev_close(&bs_uart->ud_dev);
+ bs_uart_rx.head = 0;
+ bs_uart_rx.tail = 0;
+ bs_uart_tx.cnt = 0;
+}
+
+static int
+bs_rx_char(void *arg, uint8_t byte)
+{
+ if (CONSOLE_HEAD_INC(&bs_uart_rx) == bs_uart_rx.tail) {
+ /*
+ * RX queue full. Reader must drain this.
+ */
+ return -1;
+ }
+ bs_uart_rx.buf[bs_uart_rx.head] = byte;
+ bs_uart_rx.head = CONSOLE_HEAD_INC(&bs_uart_rx);
+ return 0;
+}
+
+static uint8_t
+bs_pull_char(void)
+{
+ uint8_t ch;
+
+ ch = bs_uart_rx.buf[bs_uart_rx.tail];
+ bs_uart_rx.tail = CONSOLE_TAIL_INC(&bs_uart_rx);
+ return ch;
+}
+
+int
+boot_uart_read(char *str, int cnt, int *newline)
+{
+ int i;
+ int sr;
+ uint8_t ch;
+
+ *newline = 0;
+ OS_ENTER_CRITICAL(sr);
+ for (i = 0; i < cnt; i++) {
+ if (bs_uart_rx.head == bs_uart_rx.tail) {
+ break;
+ }
+
+ ch = bs_pull_char();
+ if (ch == '\n') {
+ *str = '\0';
+ *newline = 1;
+ break;
+ }
+ *str++ = ch;
+ }
+ OS_EXIT_CRITICAL(sr);
+ if (i > 0 || *newline) {
+ uart_start_rx(bs_uart);
+ }
+ return i;
+}
+
+static int
+bs_tx_char(void *arg)
+{
+ uint8_t ch;
+
+ if (!bs_uart_tx.cnt) {
+ return -1;
+ }
+
+ bs_uart_tx.cnt--;
+ ch = *bs_uart_tx.ptr;
+ bs_uart_tx.ptr++;
+ return ch;
+}
+
+#if MYNEWT_VAL(SELFTEST)
+/*
+ * OS is not running, so native uart 'driver' cannot run either.
+ * At the moment unit tests don't check the responses to messages it
+ * sends, so we can drop the outgoing data here.
+ */
+void
+boot_uart_write(char *ptr, int cnt)
+{
+}
+
+#else
+
+void
+boot_uart_write(char *ptr, int cnt)
+{
+ int sr;
+
+ OS_ENTER_CRITICAL(sr);
+ bs_uart_tx.ptr = (uint8_t *)ptr;
+ bs_uart_tx.cnt = cnt;
+ OS_EXIT_CRITICAL(sr);
+
+ uart_start_tx(bs_uart);
+ while (bs_uart_tx.cnt);
+}
+
+#endif
diff --git a/boot/mynewt/mcuboot_config/syscfg.yml b/boot/mynewt/mcuboot_config/syscfg.yml
index 467bcee..5eecf98 100644
--- a/boot/mynewt/mcuboot_config/syscfg.yml
+++ b/boot/mynewt/mcuboot_config/syscfg.yml
@@ -52,6 +52,13 @@
BOOTUTIL_HAVE_LOGGING:
description: 'Enable serial logging'
value: 0
+ restrictions:
+ - "!BOOTUTIL_NO_LOGGING"
+ BOOTUTIL_NO_LOGGING:
+ description: 'No serial logging'
+ value: 1
+ restrictions:
+ - "!BOOTUTIL_HAVE_LOGGING"
BOOTUTIL_LOG_LEVEL:
description: >
Default console log level. Valid values are:
diff --git a/boot/mynewt/pkg.yml b/boot/mynewt/pkg.yml
index 396df49..1cbd1ab 100644
--- a/boot/mynewt/pkg.yml
+++ b/boot/mynewt/pkg.yml
@@ -33,7 +33,13 @@
- "@mcuboot/boot/bootutil"
- "@mcuboot/boot/mynewt/flash_map_backend"
- "@apache-mynewt-core/kernel/os"
+
+pkg.deps.BOOTUTIL_NO_LOGGING:
+ - "@apache-mynewt-core/sys/console/stub"
+
+pkg.deps.BOOTUTIL_HAVE_LOGGING:
- "@apache-mynewt-core/sys/console/minimal"
pkg.deps.BOOT_SERIAL:
- "@mcuboot/boot/boot_serial"
+ - "@mcuboot/boot/mynewt/boot_uart"
diff --git a/boot/mynewt/src/main.c b/boot/mynewt/src/main.c
index 083d03e..b504896 100755
--- a/boot/mynewt/src/main.c
+++ b/boot/mynewt/src/main.c
@@ -23,7 +23,8 @@
#include <stddef.h>
#include <inttypes.h>
#include <stdio.h>
-#include "syscfg/syscfg.h"
+
+#include <syscfg/syscfg.h>
#include <flash_map_backend/flash_map_backend.h>
#include <os/os.h>
#include <bsp/bsp.h>
@@ -36,6 +37,9 @@
#include <hal/hal_nvreg.h>
#include <boot_serial/boot_serial.h>
#endif
+#if defined(MCUBOOT_SERIAL) && MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) != 0
+#include <boot_uart/boot_uart.h>
+#endif
#include <console/console.h>
#include "bootutil/image.h"
#include "bootutil/bootutil.h"
@@ -61,6 +65,70 @@
}
#ifdef MCUBOOT_SERIAL
+#if MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) != 0
+
+/** Don't include null-terminator in comparison. */
+#define BOOT_SERIAL_DETECT_STRING_LEN \
+ (sizeof MYNEWT_VAL(BOOT_SERIAL_DETECT_STRING) - 1)
+
+/**
+ * Listens on the UART for the management string. Blocks for up to
+ * BOOT_SERIAL_DETECT_TIMEOUT milliseconds.
+ *
+ * @return true if the management string was received;
+ * false if the management string was not received
+ * before the UART listen timeout expired.
+ */
+static bool
+serial_detect_uart_string(void)
+{
+ uint32_t start_tick;
+ char buf[BOOT_SERIAL_DETECT_STRING_LEN] = { 0 };
+ char ch;
+ int newline;
+ int rc;
+
+ /* Calculate the timeout duration in OS cputime ticks. */
+ static const uint32_t timeout_dur =
+ MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) /
+ (1000.0 / MYNEWT_VAL(OS_CPUTIME_FREQ));
+
+ rc = boot_serial_uart_open();
+ assert(rc == 0);
+
+ start_tick = os_cputime_get32();
+
+ while (1) {
+ /* Read a single character from the UART. */
+ rc = boot_serial_uart_read(&ch, 1, &newline);
+ if (rc > 0) {
+ /* Eliminate the oldest character in the buffer to make room for
+ * the new one.
+ */
+ memmove(buf, buf + 1, BOOT_SERIAL_DETECT_STRING_LEN - 1);
+ buf[BOOT_SERIAL_DETECT_STRING_LEN - 1] = ch;
+
+ /* If the full management string has been received, indicate that
+ * the serial boot loader should start.
+ */
+ rc = memcmp(buf,
+ MYNEWT_VAL(BOOT_SERIAL_DETECT_STRING),
+ BOOT_SERIAL_DETECT_STRING_LEN);
+ if (rc == 0) {
+ boot_serial_uart_close();
+ return true;
+ }
+ }
+
+ /* Abort the listen on timeout. */
+ if (os_cputime_get32() >= start_tick + timeout_dur) {
+ boot_serial_uart_close();
+ return false;
+ }
+ }
+}
+#endif
+
static void
serial_boot_detect(void)
{
@@ -99,7 +167,7 @@
* download commands from serial.
*/
#if MYNEWT_VAL(BOOT_SERIAL_DETECT_TIMEOUT) != 0
- if (boot_serial_detect_uart_string()) {
+ if (serial_detect_uart_string()) {
boot_serial_start(BOOT_SERIAL_INPUT_MAX);
assert(0);
}
diff --git a/boot/mynewt/syscfg.yml b/boot/mynewt/syscfg.yml
index 778ba5f..3460954 100644
--- a/boot/mynewt/syscfg.yml
+++ b/boot/mynewt/syscfg.yml
@@ -29,5 +29,5 @@
syscfg.vals:
SYSINIT_CONSTRAIN_INIT: 0
OS_SCHEDULING: 0
- OS_CPUTIME_TIMER_NUM: -1
+ MSYS_1_BLOCK_COUNT: 0
CONSOLE_COMPAT: 1