Commit e3822f81 authored by Wouter Cappelle's avatar Wouter Cappelle Committed by David Brown
Browse files

boot_serial: zephyr: Add optional timeout to enter serial recovery



This PR adds the possibility to only enter the bootloader's
serial recovery mode when a mcumgr command is received within a
given timeout.
Signed-off-by: default avatarWouter Cappelle <wouter.cappelle@crodeon.com>
parent c028d450
......@@ -43,6 +43,15 @@ struct boot_uart_funcs {
*/
void boot_serial_start(const struct boot_uart_funcs *f);
/**
* Start processing newtmgr commands for uploading image0 over serial.
* Assumes serial port is open and waits for download command.
* This function will return if there is no mcumgr command received within
* the given timeout. If a command is received within this timeout, the
* function is similar to boot_serial_start
*/
void boot_serial_check_start(const struct boot_uart_funcs *f, int timeout_in_ms);
#ifdef __cplusplus
}
#endif
......
......@@ -93,6 +93,7 @@ const struct boot_uart_funcs *boot_uf;
static uint32_t curr_off;
static uint32_t img_size;
static struct nmgr_hdr *bs_hdr;
static bool bs_entry;
static char bs_obuf[BOOT_SERIAL_OUT_MAX];
......@@ -563,6 +564,9 @@ boot_serial_input(char *buf, int len)
} else {
bs_rc_rsp(MGMT_ERR_ENOTSUP);
}
#ifdef MCUBOOT_SERIAL_WAIT_FOR_DFU
bs_entry = true;
#endif
}
static void
......@@ -678,25 +682,29 @@ boot_serial_in_dec(char *in, int inlen, char *out, int *out_off, int maxout)
* Task which waits reading console, expecting to get image over
* serial port.
*/
void
boot_serial_start(const struct boot_uart_funcs *f)
static void
boot_serial_read_console(const struct boot_uart_funcs *f,int timeout_in_ms)
{
int rc;
int off;
int dec_off = 0;
int full_line;
int max_input;
int elapsed_in_ms = 0;
boot_uf = f;
max_input = sizeof(in_buf);
off = 0;
while (1) {
while (timeout_in_ms > 0 || bs_entry) {
MCUBOOT_CPU_IDLE();
MCUBOOT_WATCHDOG_FEED();
#ifdef MCUBOOT_SERIAL_WAIT_FOR_DFU
uint32_t start = k_uptime_get_32();
#endif
rc = f->read(in_buf + off, sizeof(in_buf) - off, &full_line);
if (rc <= 0 && !full_line) {
continue;
goto check_timeout;
}
off += rc;
if (!full_line) {
......@@ -706,7 +714,7 @@ boot_serial_start(const struct boot_uart_funcs *f)
*/
off = 0;
}
continue;
goto check_timeout;
}
if (in_buf[0] == SHELL_NLIP_PKT_START1 &&
in_buf[1] == SHELL_NLIP_PKT_START2) {
......@@ -722,5 +730,36 @@ boot_serial_start(const struct boot_uart_funcs *f)
boot_serial_input(&dec_buf[2], dec_off - 2);
}
off = 0;
check_timeout:
/* Subtract elapsed time */
#ifdef MCUBOOT_SERIAL_WAIT_FOR_DFU
elapsed_in_ms = (k_uptime_get_32() - start);
#endif
timeout_in_ms -= elapsed_in_ms;
}
}
/*
* Task which waits reading console, expecting to get image over
* serial port.
*/
void
boot_serial_start(const struct boot_uart_funcs *f)
{
bs_entry = true;
boot_serial_read_console(f,0);
}
#ifdef MCUBOOT_SERIAL_WAIT_FOR_DFU
/*
* Task which waits reading console for a certain amount of timeout.
* If within this timeout no mcumgr command is received, the function is
* returning, else the serial boot is never exited
*/
void
boot_serial_check_start(const struct boot_uart_funcs *f, int timeout_in_ms)
{
bs_entry = false;
boot_serial_read_console(f,timeout_in_ms);
}
#endif
......@@ -618,6 +618,21 @@ config BOOT_SERIAL_ENCRYPT_EC256
encryption mechanism used in this case is ECIES using primitives
described under "ECIES-P256 encryption" in docs/encrypted_images.md.
config BOOT_SERIAL_WAIT_FOR_DFU
bool "Wait for a prescribed duration to see if DFU is invoked by receiving a mcumgr comand"
depends on BOOT_SERIAL_UART
help
If y, MCUboot waits for a prescribed duration of time to allow
for DFU to be invoked. The serial recovery can be entered by receiving any
mcumgr command.
config BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT
int "Duration to wait for the serial DFU timeout in ms"
default 500
depends on BOOT_SERIAL_WAIT_FOR_DFU
help
timeout in ms for MCUboot to wait to allow for DFU to be invoked.
endif # MCUBOOT_SERIAL
config BOOT_INTR_VEC_RELOC
......
......@@ -189,6 +189,10 @@
#define MCUBOOT_SERIAL_DIRECT_IMAGE_UPLOAD
#endif
#ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU
#define MCUBOOT_SERIAL_WAIT_FOR_DFU
#endif
/*
* The option enables code, currently in boot_serial, that attempts
* to erase flash progressively, as update fragments are received,
......
......@@ -506,7 +506,28 @@ void main(void)
}
#endif
#ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU
/* Initialize the boot console, so we can already fill up our buffers while
* waiting for the boot image check to finish. This image check, can take
* some time, so it's better to reuse thistime to already receive the
* initial mcumgr command(s) into our buffers
*/
rc = boot_console_init();
int timeout_in_ms = CONFIG_BOOT_SERIAL_WAIT_FOR_DFU_TIMEOUT;
uint32_t start = k_uptime_get_32();
#endif
FIH_CALL(boot_go, fih_rc, &rsp);
#ifdef CONFIG_BOOT_SERIAL_WAIT_FOR_DFU
timeout_in_ms -= (k_uptime_get_32() - start);
if( timeout_in_ms <= 0 ) {
/* at least one check if time was expired */
timeout_in_ms = 1;
}
boot_serial_check_start(&boot_funcs,timeout_in_ms);
#endif
if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
BOOT_LOG_ERR("Unable to find bootable image");
FIH_PANIC;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment