boot: boot_serial: add raw (non-console) SMP recovery protocol#4
boot: boot_serial: add raw (non-console) SMP recovery protocol#4JPHutchins wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a build-time-selectable raw SMP transport (BOOT_SERIAL_RAW_PROTOCOL) to mcuboot's serial recovery, mirroring Zephyr's CONFIG_UART_MCUMGR_RAW_PROTOCOL. In raw mode the SMP header + payload is exchanged as plain binary (no base64, length prefix, CRC16, NLIP framing or \n); packet boundaries come from the SMP header nh_len. The console encoding remains the default; the two modes are mutually exclusive and the base64/CRC libraries are dropped in raw mode.
Changes:
- New raw TX path in
boot_serial_outputplus aboot_serial_input_rawreassembler that drains complete packets and keeps residue, with the legacy console decode path#ifdef-gated. serial_adapter.cgains a binary-safe ISR path (no\nsplit, end-of-IRQ fragment flush) and aconsole_read_rawreader that retains an unconsumed fragment tail across calls.- New
BOOT_SERIAL_RAW_PROTOCOLKconfig (conditionallyselects BASE64/CRC),CONFIG_→MCUBOOT_SERIAL_RAW_PROTOCOLmapping, aserial_recovery_raw.confsample, plus docs and a release note.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| boot/boot_serial/src/boot_serial.c | Raw TX in boot_serial_output; gates console decode; adds boot_serial_input_raw and raw branch in the read loop. |
| boot/zephyr/serial_adapter.c | Binary-safe ISR fragment delivery and console_read_raw with persistent pending-tail. |
| boot/zephyr/Kconfig.serial_recovery | Adds BOOT_SERIAL_RAW_PROTOCOL; makes BASE64/CRC conditional. |
| boot/zephyr/include/mcuboot_config/mcuboot_config.h | Maps CONFIG_BOOT_SERIAL_RAW_PROTOCOL to MCUBOOT_SERIAL_RAW_PROTOCOL. |
| boot/zephyr/serial_recovery_raw.conf | Sample Kconfig fragment for raw mode. |
| docs/serial_recovery.md | Documents the new transport encoding option. |
| docs/release-notes.d/serial-recovery-raw-protocol.md | Release note for the new option. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
77bf50c to
acbf7d0
Compare
| /* | ||
| * Raw protocol read: the data is binary, so it is returned without a NUL | ||
| * terminator. A fragment may be larger than the caller's buffer, so retain the | ||
| * unconsumed tail for the next call rather than dropping it (the fragment's | ||
| * buffer is not recycled by boot_uart_fifo_getline() until it is fully consumed | ||
| * here). Returns the number of bytes copied into "str". | ||
| */ | ||
| static int __maybe_unused |
There was a problem hiding this comment.
Doesn't need __maybe_unused, put it in ifdef
There was a problem hiding this comment.
Done — wrapped console_read_raw in #ifdef CONFIG_BOOT_SERIAL_RAW_PROTOCOL and dropped __maybe_unused (0c95767).
| if (IS_ENABLED(CONFIG_BOOT_SERIAL_RAW_PROTOCOL)) { | ||
| return console_read_raw(str, str_size, newline); | ||
| } | ||
|
|
There was a problem hiding this comment.
Done — console_read now dispatches with #ifdef ... #else; the line/len locals only exist in the console branch now (0c95767).
| if (IS_ENABLED(CONFIG_BOOT_SERIAL_RAW_PROTOCOL)) { | ||
| cmd->line[cur++] = byte; | ||
| } | ||
|
|
||
| if (byte == '\n') { | ||
| cmd->len = cur; | ||
| sys_slist_append(&lines_queue, &cmd->node); | ||
| cur = 0; | ||
| cmd = NULL; | ||
| if (cur >= CONFIG_BOOT_MAX_LINE_INPUT_LEN) { | ||
| cmd->len = cur; | ||
| sys_slist_append(&lines_queue, &cmd->node); | ||
| cur = 0; | ||
| cmd = NULL; | ||
| } | ||
| } else { | ||
| if (cur < CONFIG_BOOT_MAX_LINE_INPUT_LEN) { | ||
| cmd->line[cur++] = byte; | ||
| } | ||
|
|
||
| if (byte == '\n') { | ||
| cmd->len = cur; | ||
| sys_slist_append(&lines_queue, &cmd->node); | ||
| cur = 0; | ||
| cmd = NULL; | ||
| } | ||
| } |
There was a problem hiding this comment.
Done — converted the in-loop branch and the trailing flush to #ifdef ... #else / #ifdef (0c95767).
JPHutchins
left a comment
There was a problem hiding this comment.
A few cleanups to make the diff better
acbf7d0 to
0c95767
Compare
Add the BOOT_SERIAL_RAW_PROTOCOL option, which exchanges SMP packets over the serial port as raw binary instead of the SMP-over-console encoding: no base64, no two-byte length prefix, no CRC16 and no SHELL_NLIP framing. Packet boundaries are derived from the length field of the SMP header, so the encoding is transport-agnostic (UART, CDC ACM, CAN, ...) and only requires a binary-capable link. The mcumgr client must be configured to use a matching raw transport. This mirrors Zephyr's CONFIG_UART_MCUMGR_RAW_PROTOCOL. The two encodings are mutually exclusive and selected at build time; in raw mode the base64 and CRC code and libraries are dropped, saving roughly 1 KiB of flash and 1 KiB of RAM and increasing transfer speed. Because the raw encoding has no CRC or framing to detect a truncated packet, also add BOOT_SERIAL_RAW_PROTOCOL_INPUT_TIMEOUT (enabled by default with the raw protocol): a partially received packet is dropped after BOOT_SERIAL_RAW_PROTOCOL_INPUT_TIMEOUT_MS without new data so a stalled transfer cannot wedge recovery. This mirrors Zephyr's CONFIG_MCUMGR_TRANSPORT_RAW_UART_INPUT_TIMEOUT. A serial_recovery_raw.conf fragment and a matching Twister build test (sample.bootloader.mcuboot.serial_recovery_raw) are added so the raw configuration is built in CI. Signed-off-by: JP Hutchins <jp@intercreate.io> Assisted-By: Claude:opus-4.8
0c95767 to
03bb198
Compare
Summary
Adds the
BOOT_SERIAL_RAW_PROTOCOLoption to mcuboot serial recovery (the bootloader-side SMP server). In raw mode the SMP packet (nmgr_hdr+ payload) is exchanged as plain binary instead of the SMP over console encoding — no base64, no two-byte length prefix, no CRC16, noSHELL_NLIPframing, no\n. Packet boundaries are derived from the length field of the SMP header, so the encoding is transport-agnostic (UART, CDC ACM, CAN, RTT, …) and only requires a binary-capable link.This mirrors Zephyr's
CONFIG_UART_MCUMGR_RAW_PROTOCOLso the same raw mcumgr client talks to both the application and the bootloader. The two encodings are mutually exclusive, selected at build time; in raw mode the base64 and CRC code and libraries are dropped.Changes
boot_serial.c— raw TX inboot_serial_output; console-onlyboot_serial_in_dec/dec_bufcompiled out in raw mode; newboot_serial_input_raw()that drains every complete packet from the receive buffer (by header length) and preserves the residue.serial_adapter.c—IS_ENABLED-gated raw paths; binary-safe byte collection (no\nsplit);console_read_raw()retains an unconsumed fragment tail across calls instead of truncating.Kconfig.serial_recovery— new option;BASE64/CRCselected only for the console encoding.mcuboot_config.h—CONFIG_→MCUBOOT_SERIAL_RAW_PROTOCOLmapping.serial_recovery.md+ release note) and aserial_recovery_raw.confsample fragment.Verification
Built for
nrf52840dk/nrf52840(Zephyr 4.4.0, SDK 0.17.4,-Werror -Wall -Wextra) in both raw and console configurations — each compiles clean and links. Console output is byte-identical to before this change (no regression). Raw mode saves ~1 KiB flash and ~1 KiB RAM vs the console encoding, matching the Zephyr PR's reported win.Reviewed across two adversarial passes; three issues found and fixed (multi-packet residue handling, the
boot_serial_outputraw guard, and a fragment-truncation data-loss path).🤖 Generated with Claude Code