Initial commit

Initial commit.
This commit is contained in:
kntran1
2026-03-23 14:40:39 -05:00
parent e84b2b4166
commit 4e2a5258a5
872 changed files with 165227 additions and 0 deletions

View File

@@ -0,0 +1,59 @@
/*
* 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_SERIAL_H__
#define __BOOT_SERIAL_H__
#ifdef __cplusplus
extern "C" {
#endif
/**
* Function pointers to read/write data from uart.
* read returns the number of bytes read, str points to buffer to fill,
* cnt is the number of bytes to fill within buffer, *newline will be
* set if newline is the last character.
* write takes as it's arguments pointer to data to write, and the count
* of bytes.
*/
struct boot_uart_funcs {
int (*read)(char *str, int cnt, int *newline);
void (*write)(const char *ptr, int cnt);
};
/**
* Start processing newtmgr commands for uploading image0 over serial.
* Assumes serial port is open and waits for download command.
*/
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
#endif /* __BOOT_SERIAL_H__ */

View File

@@ -0,0 +1,32 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2023 Nordic Semiconductor ASA
*/
#ifndef H_BOOT_SERIAL_ENCRYPTION_
#define H_BOOT_SERIAL_ENCRYPTION_
#include "bootutil/fault_injection_hardening.h"
/**
* Validate hash of a primary boot image doing on the fly decryption as well
*
* @param[in] fa_p flash area pointer
* @param[in] hdr boot image header pointer
* @param[in] buf buffer which is used for validating data
* @param[in] buf_size size of input buffer
*
* @return FIH_SUCCESS on success, error code otherwise
*/
fih_ret
boot_image_validate_encrypted(const struct flash_area *fa_p,
struct image_header *hdr, uint8_t *buf,
uint16_t buf_size);
/**
* Handle an encrypted firmware in the main flash.
* This will decrypt the image inplace
*/
int boot_handle_enc_fw(const struct flash_area *flash_area);
#endif

View File

@@ -0,0 +1,38 @@
#
# 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/boot_serial
pkg.description: The boot_serial library is used when downloading image over serial port.
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
- boot
- bootloader
pkg.deps:
- "@apache-mynewt-core/hw/hal"
- "@apache-mynewt-core/kernel/os"
- "@apache-mynewt-core/encoding/base64"
- "@mcuboot/boot/mynewt/flash_map_backend"
- "@mcuboot/boot/mynewt/boot_uart"
- "@mcuboot/boot/zcbor"
- "@apache-mynewt-core/util/crc"
pkg.req_apis:
- bootloader

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,308 @@
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2020-2023 Nordic Semiconductor ASA
* Copyright (c) 2020 Arm Limited
*/
#include <assert.h>
#include "bootutil/image.h"
#include <../src/bootutil_priv.h>
#include "bootutil/bootutil_log.h"
#include "bootutil/bootutil_public.h"
#include "bootutil/fault_injection_hardening.h"
#include "bootutil/enc_key.h"
#include "mcuboot_config/mcuboot_config.h"
#ifdef MCUBOOT_ENC_IMAGES
BOOT_LOG_MODULE_DECLARE(serial_encryption);
fih_ret
boot_image_validate_encrypted(const struct flash_area *fa_p,
struct image_header *hdr, uint8_t *buf,
uint16_t buf_size)
{
FIH_DECLARE(fih_rc, FIH_FAILURE);
struct boot_loader_state boot_data;
struct boot_loader_state *state = &boot_data;
struct boot_status _bs;
struct boot_status *bs = &_bs;
uint8_t image_index;
int rc;
memset(&boot_data, 0, sizeof(struct boot_loader_state));
image_index = BOOT_CURR_IMG(state);
if(IS_ENCRYPTED(hdr)) {
rc = boot_enc_load(BOOT_CURR_ENC(state), 1, hdr, fa_p, bs);
if (rc < 0) {
FIH_RET(fih_rc);
}
rc = boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs);
if (rc < 0) {
FIH_RET(fih_rc);
}
}
FIH_CALL(bootutil_img_validate, fih_rc, BOOT_CURR_ENC(state), image_index,
hdr, fa_p, buf, buf_size, NULL, 0, NULL);
FIH_RET(fih_rc);
}
/*
* Compute the total size of the given image. Includes the size of
* the TLVs.
*/
static int
read_image_size(const struct flash_area *fa_p,
struct image_header *hdr,
uint32_t *size)
{
struct image_tlv_info info;
uint32_t off;
uint32_t protect_tlv_size;
int rc;
off = BOOT_TLV_OFF(hdr);
if (flash_area_read(fa_p, off, &info, sizeof(info))) {
rc = BOOT_EFLASH;
goto done;
}
protect_tlv_size = hdr->ih_protect_tlv_size;
if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
if (protect_tlv_size != info.it_tlv_tot) {
rc = BOOT_EBADIMAGE;
goto done;
}
if (flash_area_read(fa_p, off + info.it_tlv_tot, &info, sizeof(info))) {
rc = BOOT_EFLASH;
goto done;
}
} else if (protect_tlv_size != 0) {
rc = BOOT_EBADIMAGE;
goto done;
}
if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
rc = BOOT_EBADIMAGE;
goto done;
}
*size = off + protect_tlv_size + info.it_tlv_tot;
rc = 0;
done:
return rc;
}
/**
* reads, decrypts in RAM & write back the decrypted image in the same region
* This function is NOT power failsafe since the image is decrypted in the RAM
* buffer.
*
* @param flash_area The ID of the source flash area.
* @param off_src The offset within the flash area to
* copy from.
* @param sz The number of bytes to copy. should match erase sector
*
* @return 0 on success; nonzero on failure.
*/
static int
decrypt_region_inplace(struct boot_loader_state *state,
const struct flash_area *fap,
struct image_header *hdr,
uint32_t off, uint32_t sz)
{
uint32_t bytes_copied;
int chunk_sz;
int rc;
uint32_t tlv_off;
size_t blk_off;
uint16_t idx;
uint32_t blk_sz;
int slot = flash_area_id_to_multi_image_slot(BOOT_CURR_IMG(state),
flash_area_get_id(fap));
uint8_t buf[sz] __attribute__((aligned));
assert(sz <= sizeof buf);
assert(slot >= 0);
bytes_copied = 0;
while (bytes_copied < sz) {
if (sz - bytes_copied > sizeof buf) {
chunk_sz = sizeof buf;
} else {
chunk_sz = sz - bytes_copied;
}
rc = flash_area_read(fap, off + bytes_copied, buf, chunk_sz);
if (rc != 0) {
return BOOT_EFLASH;
}
if (IS_ENCRYPTED(hdr)) {
blk_sz = chunk_sz;
idx = 0;
if (off + bytes_copied < hdr->ih_hdr_size) {
/* do not decrypt header */
if (hdr->ih_hdr_size > (off + bytes_copied + chunk_sz)) {
/* all bytes in header, skip decryption */
blk_sz = 0;
}
else {
blk_sz = off + bytes_copied + chunk_sz - hdr->ih_hdr_size;
}
blk_off = 0;
idx = hdr->ih_hdr_size;
} else {
blk_off = ((off + bytes_copied) - hdr->ih_hdr_size) & 0xf;
}
tlv_off = BOOT_TLV_OFF(hdr);
if (off + bytes_copied + chunk_sz > tlv_off) {
/* do not decrypt TLVs */
if (off + bytes_copied >= tlv_off) {
blk_sz = 0;
} else {
blk_sz = tlv_off - (off + bytes_copied);
}
}
boot_enc_decrypt(BOOT_CURR_ENC(state), slot,
(off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
blk_off, &buf[idx]);
}
rc = flash_area_erase(fap, off + bytes_copied, chunk_sz);
if (rc != 0) {
return BOOT_EFLASH;
}
rc = flash_area_write(fap, off + bytes_copied, buf, chunk_sz);
if (rc != 0) {
return BOOT_EFLASH;
}
bytes_copied += chunk_sz;
MCUBOOT_WATCHDOG_FEED();
}
return 0;
}
/**
* Check if a image was encrypted into the first slot, and decrypt it
* in place. this operation is not power failsafe.
*
* The operation is done by checking the last flash sector, and using it as a
* temporarely scratch partition. The
*
* @param[in] fa_p flash area pointer
* @param[in] hdr boot image header pointer
*
* @return FIH_SUCCESS on success, error code otherwise
*/
inline static fih_ret
decrypt_image_inplace(const struct flash_area *fa_p,
struct image_header *hdr)
{
FIH_DECLARE(fih_rc, FIH_FAILURE);
int rc;
struct boot_loader_state boot_data;
struct boot_loader_state *state = &boot_data;
struct boot_status _bs;
struct boot_status *bs = &_bs;
size_t size;
size_t sect_size;
size_t sect_count;
size_t sect;
struct flash_sector sector;
memset(&boot_data, 0, sizeof(struct boot_loader_state));
memset(&_bs, 0, sizeof(struct boot_status));
/* Get size from last sector to know page/sector erase size */
rc = flash_area_get_sector(fa_p, boot_status_off(fa_p), &sector);
if(IS_ENCRYPTED(hdr)) {
#if 0 //Skip this step?, the image will just not boot if it's not decrypted properly
static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
/* First check if the encrypted image is a good image before decrypting */
FIH_CALL(boot_image_validate_encrypted,fih_rc,fa_p,&_hdr,tmpbuf,BOOT_TMPBUF_SZ);
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
FIH_RET(fih_rc);
}
#endif
memset(&boot_data, 0, sizeof(struct boot_loader_state));
/* Load the encryption keys into cache */
rc = boot_enc_load(BOOT_CURR_ENC(state), 0, hdr, fa_p, bs);
if (rc < 0) {
FIH_RET(fih_rc);
}
if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs)) {
FIH_RET(fih_rc);
}
}
else
{
/* Expected encrypted image! */
FIH_RET(fih_rc);
}
uint32_t src_size = 0;
rc = read_image_size(fa_p,hdr, &src_size);
if (rc != 0) {
FIH_RET(fih_rc);
}
/* TODO: This assumes every sector has an equal size, should instead use
* flash_area_get_sectors() to get the size of each sector and iterate
* over it.
*/
sect_size = sector.fs_size;
sect_count = fa_p->fa_size / sect_size;
for (sect = 0, size = 0; size < src_size && sect < sect_count; sect++) {
rc = decrypt_region_inplace(state, fa_p,hdr, size, sect_size);
if (rc != 0) {
FIH_RET(fih_rc);
}
size += sect_size;
}
fih_rc = FIH_SUCCESS;
FIH_RET(fih_rc);
}
int
boot_handle_enc_fw(const struct flash_area *flash_area)
{
int rc = -1;
struct image_header _hdr = { 0 };
FIH_DECLARE(fih_rc, FIH_FAILURE);
rc = boot_image_load_header(flash_area, &_hdr);
if (rc != 0) {
goto out;
}
if (IS_ENCRYPTED(&_hdr)) {
//encrypted, we need to decrypt in place
FIH_CALL(decrypt_image_inplace,fih_rc,flash_area,&_hdr);
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
rc = -1;
goto out;
}
}
else
{
rc = 0;
}
out:
return rc;
}
#endif

View File

@@ -0,0 +1,106 @@
/*
* 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 __BOOTUTIL_SERIAL_PRIV_H__
#define __BOOTUTIL_SERIAL_PRIV_H__
#ifdef __cplusplus
extern "C" {
#endif
/*
* From shell.h
*/
#define SHELL_NLIP_PKT_START1 6
#define SHELL_NLIP_PKT_START2 9
#define SHELL_NLIP_DATA_START1 4
#define SHELL_NLIP_DATA_START2 20
/*
* From newtmgr.h
*/
#define MGMT_ERR_OK 0
#define MGMT_ERR_EUNKNOWN 1
#define MGMT_ERR_ENOMEM 2
#define MGMT_ERR_EINVAL 3
#define MGMT_ERR_ENOENT 5
#define MGMT_ERR_ENOTSUP 8
#define MGMT_ERR_EBUSY 10
#define NMGR_OP_READ 0
#define NMGR_OP_WRITE 2
#define MGMT_GROUP_ID_DEFAULT 0
#define MGMT_GROUP_ID_IMAGE 1
#define MGMT_GROUP_ID_PERUSER 64
#define NMGR_ID_ECHO 0
#define NMGR_ID_CONS_ECHO_CTRL 1
#define NMGR_ID_RESET 5
#ifndef __packed
#define __packed __attribute__((__packed__))
#endif
struct nmgr_hdr {
#if (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
uint8_t _res1:3;
uint8_t nh_version:2;
uint8_t nh_op:3; /* NMGR_OP_XXX */
#else
uint8_t nh_op:3; /* NMGR_OP_XXX */
uint8_t nh_version:2;
uint8_t _res1:3;
#endif
uint8_t nh_flags;
uint16_t nh_len; /* length of the payload */
uint16_t nh_group; /* NMGR_GROUP_XXX */
uint8_t nh_seq; /* sequence number */
uint8_t nh_id; /* message ID within group */
} __packed;
/*
* From imgmgr.h
*/
#define IMGMGR_NMGR_ID_STATE 0
#define IMGMGR_NMGR_ID_UPLOAD 1
#define IMGMGR_NMGR_ID_SLOT_INFO 6
void boot_serial_input(char *buf, int len);
extern const struct boot_uart_funcs *boot_uf;
/**
* @brief Selects direct image to upload according to the "image"
* parameter of the mcumgr update frame.
*
* @param[in] image_id the value of the "image" parameter of the
* mcumgr update frame to be translated.
*
* @return flash area ID for the image if defined;
* -EINVAL when flash area for given image number has not been
* defined.
*/
extern int flash_area_id_from_direct_image(int image_id);
#ifdef __cplusplus
}
#endif
#endif /* __BOOTUTIL_SERIAL_PRIV_H__ */

View File

@@ -0,0 +1,69 @@
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <errno.h>
#include "zcbor_bulk.h"
int zcbor_map_decode_bulk(zcbor_state_t *zsd, struct zcbor_map_decode_key_val *map,
size_t map_size, size_t *matched)
{
bool ok;
struct zcbor_map_decode_key_val *dptr = map;
if (!zcbor_map_start_decode(zsd)) {
return -EBADMSG;
}
*matched = 0;
ok = true;
do {
struct zcbor_string key;
bool found = false;
size_t map_count = 0;
ok = zcbor_tstr_decode(zsd, &key);
while (ok && map_count < map_size) {
if (dptr >= (map + map_size)) {
dptr = map;
}
if (key.len == dptr->key.len &&
memcmp(key.value, dptr->key.value, key.len) == 0) {
if (dptr->found) {
return -EADDRINUSE;
}
if (!dptr->decoder(zsd, dptr->value_ptr)) {
/* Failure to decode value matched to key
* means that either decoder has been
* incorrectly assigned or SMP payload
* is broken anyway.
*/
return -ENOMSG;
}
dptr->found = true;
found = true;
++dptr;
++(*matched);
break;
}
++dptr;
++map_count;
}
if (!found && ok) {
ok = zcbor_any_skip(zsd, NULL);
}
} while (ok);
return zcbor_map_end_decode(zsd) ? 0 : -EBADMSG;
}

View File

@@ -0,0 +1,116 @@
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef H_ZCBOR_BULK_PRIV_
#define H_ZCBOR_BULK_PRIV_
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __ZEPHYR__
#include <zcbor_common.h>
#include <zcbor_decode.h>
#else
#include "zcbor_common.h"
#include "zcbor_decode.h"
#endif
/** @cond INTERNAL_HIDDEN */
struct zcbor_map_decode_key_val {
struct zcbor_string key; /* Map key string */
zcbor_decoder_t *decoder; /* Key corresponding decoder */
void *value_ptr;
bool found;
};
/** @brief Define single key-decoder mapping
*
* The macro creates a single zcbor_map_decode_key_val type object.
*
* @param k key is "" enclosed string representing key;
* @param dec decoder function; this should be zcbor_decoder_t
* type function from zcbor or a user provided implementation
* compatible with the type.
* @param vp non-NULL pointer for result of decoding; should correspond
* to type served by decoder function for the mapping.
*/
#define ZCBOR_MAP_DECODE_KEY_DECODER(k, dec, vp) \
{ \
{ \
.value = (uint8_t *)k, \
.len = sizeof(k) - 1, \
}, \
.decoder = (zcbor_decoder_t *)dec, \
.value_ptr = vp, \
}
/** @brief Define single key-value decode mapping
*
* ZCBOR_MAP_DECODE_KEY_DECODER should be used instead of this macro as,
* this macro does not allow keys with whitespaces embeeded, which CBOR
* does allow.
*
* The macro creates a single zcbor_map_decode_key_val type object.
*
* @param k key; the @p k will be stringified so should be given
* without "";
* @param dec decoder function; this should be zcbor_decoder_t
* type function from zcbor or a user provided implementation
* compatible with the type.
* @param vp non-NULL pointer for result of decoding; should correspond
* to type served by decoder function for the mapping.
*/
#define ZCBOR_MAP_DECODE_KEY_VAL(k, dec, vp) \
ZCBOR_MAP_DECODE_KEY_DECODER(STRINGIFY(k), dec, vp)
/** @brief Decodes single level map according to a provided key-decode map.
*
* The function takes @p map of key to decoder array defined as:
*
* struct zcbor_map_decode_key_val map[] = {
* ZCBOR_MAP_DECODE_KEY_DECODER("key0", decode_fun0, val_ptr0),
* ZCBOR_MAP_DECODE_KEY_DECODER("key1", decode_fun1, val_ptr1),
* ...
* };
*
* where "key?" is string representing key; the decode_fun? is
* zcbor_decoder_t compatible function, either from zcbor or defined by
* user; val_ptr? are pointers to variables where decoder function for
* a given key will place a decoded value - they have to agree in type
* with decoder function.
*
* Failure to decode any of values will cause the function to return
* negative error, and leave the map open: map is broken anyway or key-decoder
* mapping is broken, and we can not really decode the map.
*
* Note that the function opens map by itself and will fail if map
* is already opened.
*
* @param zsd zcbor decoder state;
* @param map key-decoder mapping list;
* @param map_size size of maps, both maps have to have the same size;
* @param matched pointer to the counter of matched keys, zeroed upon
* successful map entry and incremented only for successful
* decoded fields.
* @return 0 when the whole map has been parsed, there have been
* no decoding errors, and map has been closed successfully;
* -ENOMSG when given decoder function failed to decode
* value;
* -EADDRINUSE when key appears twice within map, map is then
* parsed up to they key that has appeared twice;
* -EBADMSG when failed to close map.
*/
int zcbor_map_decode_bulk(zcbor_state_t *zsd, struct zcbor_map_decode_key_val *map,
size_t map_size, size_t *matched);
/** @endcond */
#ifdef __cplusplus
}
#endif
#endif /* H_ZCBOR_BULK_PRIV_ */

View File

@@ -0,0 +1,96 @@
# 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.
#
syscfg.defs:
BOOT_SERIAL_DETECT_PIN:
description: >
Start the serial boot loader if this pin is asserted at boot time.
value: '-1'
restrictions:
- '(BOOT_SERIAL_DETECT_PIN != -1) ||
(BOOT_SERIAL_DETECT_TIMEOUT != 0) ||
(BOOT_SERIAL_NVREG_INDEX != -1)'
BOOT_SERIAL_DETECT_PIN_CFG:
description: >
GPIO configuration for the serial boot loader detect pin.
value: 'HAL_GPIO_PULL_UP'
BOOT_SERIAL_DETECT_PIN_VAL:
description: >
The value the detect pin must be set to for the serial boot loader
to start.
value: 0
BOOT_SERIAL_DETECT_TIMEOUT:
description: >
The duration, in milliseconds, to listen on the UART for the
management string (BOOT_SERIAL_DETECT_STRING). If the management
string is detected during this period, the serial boot loader is
started. If the period expires without the management string being
received, the boot loader runs in the normal (non-serial) mode.
Specify 0 to disable listening on the UART for the management
string.
value: 0
restrictions:
- '(BOOT_SERIAL_DETECT_PIN != -1) ||
(BOOT_SERIAL_DETECT_TIMEOUT != 0) ||
(BOOT_SERIAL_NVREG_INDEX != -1)'
BOOT_SERIAL_DETECT_STRING:
description: >
The string to listen for on the UART. If this management string is
detected during the timeout period, the serial boot loader is
started. If the period expires without this string being received,
the boot loader runs in the normal (non-serial) mode. This setting
has no effect if BOOT_SERIAL_DETECT_TIMEOUT is set to 0.
value: '"nmgr"'
BOOT_SERIAL_REPORT_PIN:
description: >
The GPIO to toggle while the serial boot loader is running. Set to
-1 to disable reporting.
value: 'LED_BLINK_PIN'
BOOT_SERIAL_REPORT_FREQ:
description: >
The toggle rate, in Hz, of the serial boot loader report pin.
value: 4
BOOT_SERIAL_NVREG_MAGIC:
description: >
Magic number, to be saved in a retained (reset-surviving) register.
If the value in the register matches, the serial bootloader will
load. Value must not be 0.
value: 0xB7
restrictions:
- '(BOOT_SERIAL_NVREG_MAGIC != 0)'
BOOT_SERIAL_NVREG_INDEX:
description: >
Index of retained register to use (using hal_nvreg_read) for reading
magic value.
value: -1
restrictions:
- '(BOOT_SERIAL_DETECT_PIN != -1) ||
(BOOT_SERIAL_DETECT_TIMEOUT != 0) ||
(BOOT_SERIAL_NVREG_INDEX != -1)'
BOOT_SERIAL_MGMT_ECHO:
description: If enabled, support for the mcumgr echo command is being added.
value: 0

View File

@@ -0,0 +1,35 @@
# 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/boot_serial/test
pkg.type: unittest
pkg.description: "Boot serial unit tests."
pkg.author: "Apache Mynewt <dev@mynewt.apache.org>"
pkg.homepage: "http://mynewt.apache.org/"
pkg.keywords:
pkg.deps:
- "@mcuboot/boot/boot_serial"
- "@mcuboot/boot/bootutil"
- "@apache-mynewt-core/sys/log/stub"
- "@apache-mynewt-core/test/testutil"
pkg.deps.SELFTEST:
- "@apache-mynewt-core/sys/console/stub"
pkg.cflags:
- '-DMCUBOOT_MYNEWT=1'

View File

@@ -0,0 +1,85 @@
/*
* 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "syscfg/syscfg.h"
#include "sysflash/sysflash.h"
#include "os/endian.h"
#include "base64/base64.h"
#include "crc/crc16.h"
#include "testutil/testutil.h"
#include "hal/hal_flash.h"
#include "flash_map_backend/flash_map_backend.h"
#include "boot_serial/boot_serial.h"
#include "boot_serial_priv.h"
TEST_CASE_DECL(boot_serial_setup)
TEST_CASE_DECL(boot_serial_empty_msg)
TEST_CASE_DECL(boot_serial_empty_img_msg)
TEST_CASE_DECL(boot_serial_img_msg)
TEST_CASE_DECL(boot_serial_upload_bigger_image)
static void
test_uart_write(const char *str, int len)
{
}
static const struct boot_uart_funcs test_uart = {
.write = test_uart_write
};
void
tx_msg(void *src, int len)
{
boot_serial_input(src, len);
}
TEST_SUITE(boot_serial_suite)
{
boot_serial_setup();
boot_serial_empty_msg();
boot_serial_empty_img_msg();
boot_serial_img_msg();
boot_serial_upload_bigger_image();
}
int
boot_serial_test(void)
{
boot_uf = &test_uart;
boot_serial_suite();
return tu_any_failed;
}
#if MYNEWT_VAL(SELFTEST)
int
main(void)
{
sysinit();
boot_serial_test();
return tu_any_failed;
}
#endif

View File

@@ -0,0 +1,50 @@
/*
* 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_TEST_H
#define _BOOT_TEST_H
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "syscfg/syscfg.h"
#include "sysflash/sysflash.h"
#include "os/endian.h"
#include "base64/base64.h"
#include "crc/crc16.h"
#include "testutil/testutil.h"
#include "hal/hal_flash.h"
#include "flash_map_backend/flash_map_backend.h"
#include "bootutil/bootutil.h"
#include "boot_serial_priv.h"
#ifdef __cplusplus
extern "C" {
#endif
void tx_msg(void *src, int len);
#ifdef __cplusplus
}
#endif
#endif /* _BOOT_TEST_H */

View File

@@ -0,0 +1,35 @@
/*
* 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 "boot_test.h"
TEST_CASE(boot_serial_empty_img_msg)
{
char buf[sizeof(struct nmgr_hdr) + 32];
struct nmgr_hdr *hdr;
hdr = (struct nmgr_hdr *)buf;
memset(hdr, 0, sizeof(*hdr));
hdr->nh_op = NMGR_OP_WRITE;
hdr->nh_group = htons(MGMT_GROUP_ID_IMAGE);
hdr->nh_id = IMGMGR_NMGR_ID_UPLOAD;
hdr->nh_len = htons(2);
strcpy((char *)(hdr + 1), "{}");
tx_msg(buf, sizeof(*hdr) + 2);
}

View File

@@ -0,0 +1,37 @@
/*
* 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 "boot_test.h"
TEST_CASE(boot_serial_empty_msg)
{
char buf[4];
struct nmgr_hdr hdr;
tx_msg(buf, 0);
strcpy(buf, "--");
tx_msg(buf, 2);
memset(&hdr, 0, sizeof(hdr));
tx_msg(&hdr, sizeof(hdr));
hdr.nh_op = NMGR_OP_WRITE;
tx_msg(&hdr, sizeof(hdr));
}

View File

@@ -0,0 +1,70 @@
/*
* 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 "boot_test.h"
TEST_CASE(boot_serial_img_msg)
{
char img[16];
char enc_img[BASE64_ENCODE_SIZE(sizeof(img)) + 1];
char buf[sizeof(struct nmgr_hdr) + sizeof(enc_img) + 32];
int len;
int rc;
struct nmgr_hdr *hdr;
const struct flash_area *fap;
/* 00000000 a3 64 64 61 74 61 58 10 |.ddataX.|
* 00000008 a5 a5 a5 a5 a5 a5 a5 a5 |........|
* 00000010 a5 a5 a5 a5 a5 a5 a5 a5 |........|
* 00000018 63 6c 65 6e 1a 00 01 14 |clen....|
* 00000020 e8 63 6f 66 66 00 |.coff.|
*/
static const uint8_t payload[] = {
0xa3, 0x64, 0x64, 0x61, 0x74, 0x61, 0x58, 0x10,
/* 16 bytes of image data starts here. */
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
0x63, 0x6c, 0x65, 0x6e, 0x1a, 0x00, 0x01, 0x14,
0xe8, 0x63, 0x6f, 0x66, 0x66, 0x00,
};
memset(img, 0xa5, sizeof(img));
hdr = (struct nmgr_hdr *)buf;
memset(hdr, 0, sizeof(*hdr));
hdr->nh_op = NMGR_OP_WRITE;
hdr->nh_group = htons(MGMT_GROUP_ID_IMAGE);
hdr->nh_id = IMGMGR_NMGR_ID_UPLOAD;
memcpy(hdr + 1, payload, sizeof payload);
hdr->nh_len = htons(sizeof payload);
len = sizeof(*hdr) + sizeof payload;
tx_msg(buf, len);
/*
* Validate contents inside the primary slot
*/
rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &fap);
assert(rc == 0);
rc = flash_area_read(fap, 0, enc_img, sizeof(img));
assert(rc == 0);
assert(!memcmp(enc_img, img, sizeof(img)));
}

View File

@@ -0,0 +1,24 @@
/*
* 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 "boot_test.h"
TEST_CASE(boot_serial_setup)
{
}

View File

@@ -0,0 +1,117 @@
/*
* 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 <flash_map_backend/flash_map_backend.h>
#include "boot_test.h"
#include "zcbor_common.h"
TEST_CASE(boot_serial_upload_bigger_image)
{
char img[256];
char enc_img[64];
char buf[sizeof(struct nmgr_hdr) + 128];
int len;
int off;
int rc;
struct nmgr_hdr *hdr;
const struct flash_area *fap;
int i;
const int payload_off = sizeof *hdr;
const int img_data_off = payload_off + 8;
/* 00000000 a3 64 64 61 74 61 58 20 |.ddataX.|
* 00000008 00 00 00 00 00 00 00 00 |........|
* 00000010 00 00 00 00 00 00 00 00 |........|
* 00000018 00 00 00 00 00 00 00 00 |........|
* 00000020 00 00 00 00 00 00 00 00 |........|
* 00000028 63 6c 65 6e 1a 00 01 14 |clen....|
* 00000030 e8 63 6f 66 66 00 |.coff.|
*/
static const uint8_t payload_first[] = {
0xa3, 0x64, 0x64, 0x61, 0x74, 0x61, 0x58, 0x20,
/* 32 bytes of image data starts here. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x63, 0x6c, 0x65, 0x6e, 0x1a, 0x00, 0x01, 0x14,
0xe8, 0x63, 0x6f, 0x66, 0x66, 0x00,
};
/* 00000000 a3 64 64 61 74 61 58 20 |.ddataX.|
* 00000008 00 00 00 00 00 00 00 00 |........|
* 00000010 00 00 00 00 00 00 00 00 |........|
* 00000018 00 00 00 00 00 00 00 00 |........|
* 00000020 00 00 00 00 00 00 00 00 |........|
* 00000028 63 6f 66 66 00 00 |coff..|
*/
static const uint8_t payload_next[] = {
0xa2, 0x64, 0x64, 0x61, 0x74, 0x61, 0x58, 0x20,
/* 32 bytes of image data starts here. */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x63, 0x6f, 0x66, 0x66,
/* 2 bytes of offset value starts here. */
0x00, 0x00
};
for (i = 0; i < sizeof(img); i++) {
img[i] = i;
}
for (off = 0; off < sizeof(img); off += 32) {
hdr = (struct nmgr_hdr *)buf;
memset(hdr, 0, sizeof(*hdr));
hdr->nh_op = NMGR_OP_WRITE;
hdr->nh_group = htons(MGMT_GROUP_ID_IMAGE);
hdr->nh_id = IMGMGR_NMGR_ID_UPLOAD;
if (off) {
memcpy(buf + payload_off, payload_next, sizeof payload_next);
len = sizeof payload_next;
buf[payload_off + len - 2] = ZCBOR_VALUE_IS_1_BYTE;
buf[payload_off + len - 1] = off;
} else {
memcpy(buf + payload_off, payload_first, sizeof payload_first);
len = sizeof payload_first;
}
memcpy(buf + img_data_off, img + off, 32);
hdr->nh_len = htons(len);
len = sizeof(*hdr) + len;
tx_msg(buf, len);
}
/*
* Validate contents inside the primary slot
*/
rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &fap);
assert(rc == 0);
for (off = 0; off < sizeof(img); off += sizeof(enc_img)) {
rc = flash_area_read(fap, off, enc_img, sizeof(enc_img));
assert(rc == 0);
assert(!memcmp(enc_img, &img[off], sizeof(enc_img)));
}
}

View File

@@ -0,0 +1,23 @@
# 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.
#
# Package: boot/boot_serial/test
syscfg.vals:
# This is here to work around the $notnull syscfg restriction.
BOOT_SERIAL_DETECT_PIN: 0