Add boot_serial support for multi-images
This updates `image list` and `image upload` objects to support
multi-images. The information about which image is being handled was
added to the CBOR as "image" field, which when not available, is
considered to have value 0.
Signed-off-by: Fabio Utzig <utzig@apache.org>
diff --git a/boot/boot_serial/src/boot_serial.c b/boot/boot_serial/src/boot_serial.c
index 6f964d4..c0bcc2d 100644
--- a/boot/boot_serial/src/boot_serial.c
+++ b/boot/boot_serial/src/boot_serial.c
@@ -62,7 +62,7 @@
MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
#define BOOT_SERIAL_INPUT_MAX 512
-#define BOOT_SERIAL_OUT_MAX 80
+#define BOOT_SERIAL_OUT_MAX 128
#ifdef __ZEPHYR__
/* base64 lib encodes data to null-terminated string */
@@ -75,6 +75,16 @@
#define htons(x) sys_cpu_to_be16(x)
#endif
+#ifndef BOOT_IMAGE_NUMBER
+#define BOOT_IMAGE_NUMBER MCUBOOT_IMAGE_NUMBER
+#endif
+
+#if (BOOT_IMAGE_NUMBER > 1)
+#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x))
+#else
+#define IMAGES_ITER(x)
+#endif
+
static char in_buf[BOOT_SERIAL_INPUT_MAX + 1];
static char dec_buf[BOOT_SERIAL_INPUT_MAX + 1];
const struct boot_uart_funcs *boot_uf;
@@ -163,36 +173,46 @@
CborEncoder image;
struct image_header hdr;
uint8_t tmpbuf[64];
- int i, area_id;
+ int slot, area_id;
const struct flash_area *fap;
+ uint8_t image_index;
cbor_encoder_create_map(&bs_root, &bs_rsp, CborIndefiniteLength);
cbor_encode_text_stringz(&bs_rsp, "images");
cbor_encoder_create_array(&bs_rsp, &images, CborIndefiniteLength);
- for (i = 0; i < 2; i++) {
- area_id = flash_area_id_from_image_slot(i);
- if (flash_area_open(area_id, &fap)) {
- continue;
- }
+ image_index = 0;
+ IMAGES_ITER(image_index) {
+ for (slot = 0; slot < 2; slot++) {
+ area_id = flash_area_id_from_multi_image_slot(image_index, slot);
+ if (flash_area_open(area_id, &fap)) {
+ continue;
+ }
- flash_area_read(fap, 0, &hdr, sizeof(hdr));
+ flash_area_read(fap, 0, &hdr, sizeof(hdr));
- if (hdr.ih_magic != IMAGE_MAGIC ||
- bootutil_img_validate(NULL, 0, &hdr, fap, tmpbuf, sizeof(tmpbuf),
- NULL, 0, NULL)) {
+ if (hdr.ih_magic != IMAGE_MAGIC ||
+ bootutil_img_validate(NULL, 0, &hdr, fap, tmpbuf, sizeof(tmpbuf),
+ NULL, 0, NULL)) {
+ flash_area_close(fap);
+ continue;
+ }
flash_area_close(fap);
- continue;
+
+ cbor_encoder_create_map(&images, &image, CborIndefiniteLength);
+
+#if (BOOT_IMAGE_NUMBER > 1)
+ cbor_encode_text_stringz(&image, "image");
+ cbor_encode_int(&image, image_index);
+#endif
+
+ cbor_encode_text_stringz(&image, "slot");
+ cbor_encode_int(&image, slot);
+ cbor_encode_text_stringz(&image, "version");
+
+ bs_list_img_ver((char *)tmpbuf, sizeof(tmpbuf), &hdr.ih_ver);
+ cbor_encode_text_stringz(&image, (char *)tmpbuf);
+ cbor_encoder_close_container(&images, &image);
}
- flash_area_close(fap);
-
- cbor_encoder_create_map(&images, &image, CborIndefiniteLength);
- cbor_encode_text_stringz(&image, "slot");
- cbor_encode_int(&image, i);
- cbor_encode_text_stringz(&image, "version");
-
- bs_list_img_ver((char *)tmpbuf, sizeof(tmpbuf), &hdr.ih_ver);
- cbor_encode_text_stringz(&image, (char *)tmpbuf);
- cbor_encoder_close_container(&images, &image);
}
cbor_encoder_close_container(&bs_rsp, &images);
cbor_encoder_close_container(&bs_root, &bs_rsp);
@@ -214,6 +234,7 @@
size_t img_blen = 0;
uint8_t rem_bytes;
long long int data_len = UINT_MAX;
+ int img_num;
size_t slen;
char name_str[8];
const struct flash_area *fap = NULL;
@@ -224,11 +245,13 @@
#endif
memset(img_data, 0, sizeof(img_data));
+ img_num = 0;
/*
* Expected data format.
* {
- * "data":<img_data>
+ * "image":<image number in a multi-image set (OPTIONAL)>
+ * "data":<image data>
* "len":<image len>
* "off":<current offset of image data>
* }
@@ -306,6 +329,20 @@
if (cbor_value_advance(&value)) {
goto out_invalid_data;
}
+ } else if (!strcmp(name_str, "image")) {
+ /*
+ * In a multi-image system, image number to upload to, if not
+ * present will upload to slot 0 of image set 0.
+ */
+ if (value.type != CborIntegerType) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_get_int(&value, &img_num)) {
+ goto out_invalid_data;
+ }
+ if (cbor_value_advance(&value)) {
+ goto out_invalid_data;
+ }
} else {
/*
* Unknown keys.
@@ -322,7 +359,7 @@
goto out_invalid_data;
}
- rc = flash_area_open(flash_area_id_from_image_slot(0), &fap);
+ rc = flash_area_open(flash_area_id_from_multi_image_slot(img_num, 0), &fap);
if (rc) {
rc = MGMT_ERR_EINVAL;
goto out;
@@ -581,33 +618,34 @@
return -1;
}
#endif
+
*out_off += rc;
-
- if (*out_off > sizeof(uint16_t)) {
- len = ntohs(*(uint16_t *)out);
- if (len != *out_off - sizeof(uint16_t)) {
- return 0;
- }
-
- if (len > *out_off - sizeof(uint16_t)) {
- len = *out_off - sizeof(uint16_t);
- }
-
- out += sizeof(uint16_t);
-#ifdef __ZEPHYR__
- crc = crc16(out, len, CRC_CITT_POLYMINAL, CRC16_INITIAL_CRC, true);
-#else
- crc = crc16_ccitt(CRC16_INITIAL_CRC, out, len);
-#endif
- if (crc || len <= sizeof(crc)) {
- return 0;
- }
- *out_off -= sizeof(crc);
- out[*out_off] = '\0';
-
- return 1;
+ if (*out_off <= sizeof(uint16_t)) {
+ return 0;
}
- return 0;
+
+ len = ntohs(*(uint16_t *)out);
+ if (len != *out_off - sizeof(uint16_t)) {
+ return 0;
+ }
+
+ if (len > *out_off - sizeof(uint16_t)) {
+ len = *out_off - sizeof(uint16_t);
+ }
+
+ out += sizeof(uint16_t);
+#ifdef __ZEPHYR__
+ crc = crc16(out, len, CRC_CITT_POLYMINAL, CRC16_INITIAL_CRC, true);
+#else
+ crc = crc16_ccitt(CRC16_INITIAL_CRC, out, len);
+#endif
+ if (crc || len <= sizeof(crc)) {
+ return 0;
+ }
+ *out_off -= sizeof(crc);
+ out[*out_off] = '\0';
+
+ return 1;
}
/*