Initial commit
Initial commit.
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Open Source Foundries Limited
|
||||
* Copyright (c) 2019-2024 Arm Limited
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __MCUBOOT_CONFIG_H__
|
||||
#define __MCUBOOT_CONFIG_H__
|
||||
|
||||
/*
|
||||
* Template configuration file for MCUboot.
|
||||
*
|
||||
* When porting MCUboot to a new target, copy it somewhere that your
|
||||
* include path can find it as mcuboot_config/mcuboot_config.h, and
|
||||
* make adjustments to suit your platform.
|
||||
*
|
||||
* For examples, see:
|
||||
*
|
||||
* boot/zephyr/include/mcuboot_config/mcuboot_config.h
|
||||
* boot/mynewt/mcuboot_config/include/mcuboot_config/mcuboot_config.h
|
||||
*/
|
||||
|
||||
/*
|
||||
* Signature types
|
||||
*
|
||||
* You must choose exactly one signature type.
|
||||
*/
|
||||
|
||||
/* Uncomment for RSA signature support */
|
||||
/* #define MCUBOOT_SIGN_RSA */
|
||||
|
||||
/* Uncomment for ECDSA signatures using curve P-256. */
|
||||
/* #define MCUBOOT_SIGN_EC256 */
|
||||
|
||||
/*
|
||||
* Public key handling
|
||||
*
|
||||
* Choose one or none from the different public key handling options.
|
||||
*/
|
||||
|
||||
/* Uncomment to use key hash(es) instead of incorporating
|
||||
* the public key into the code. */
|
||||
/* #define MCUBOOT_HW_KEY */
|
||||
/* Uncomment to use builtin key(s) instead of incorporating
|
||||
* the public key into the code. */
|
||||
/* #define MCUBOOT_BUILTIN_KEY */
|
||||
|
||||
/*
|
||||
* Upgrade mode
|
||||
*
|
||||
* The default is to support A/B image swapping with rollback. Other modes
|
||||
* with simpler code path, which only supports overwriting the existing image
|
||||
* with the update image or running the newest image directly from its flash
|
||||
* partition, are also available.
|
||||
*
|
||||
* You can enable only one mode at a time from the list below to override
|
||||
* the default upgrade mode.
|
||||
*/
|
||||
|
||||
/* Uncomment to enable the overwrite-only code path. */
|
||||
/* #define MCUBOOT_OVERWRITE_ONLY */
|
||||
|
||||
#ifdef MCUBOOT_OVERWRITE_ONLY
|
||||
/* Uncomment to only erase and overwrite those primary slot sectors needed
|
||||
* to install the new image, rather than the entire image slot. */
|
||||
/* #define MCUBOOT_OVERWRITE_ONLY_FAST */
|
||||
#endif
|
||||
|
||||
/* Uncomment to enable the direct-xip code path. */
|
||||
/* #define MCUBOOT_DIRECT_XIP */
|
||||
/* Uncomment to enable the revert mechanism in direct-xip mode. */
|
||||
/* #define MCUBOOT_DIRECT_XIP_REVERT */
|
||||
|
||||
/* Uncomment to enable the ram-load code path. */
|
||||
/* #define MCUBOOT_RAM_LOAD */
|
||||
|
||||
/*
|
||||
* Cryptographic settings
|
||||
*
|
||||
* You must choose between mbedTLS and Tinycrypt as source of
|
||||
* cryptographic primitives. Other cryptographic settings are also
|
||||
* available.
|
||||
*/
|
||||
|
||||
/* Uncomment to use ARM's mbedTLS cryptographic primitives */
|
||||
/* #define MCUBOOT_USE_MBED_TLS */
|
||||
/* Uncomment to use Tinycrypt's. */
|
||||
/* #define MCUBOOT_USE_TINYCRYPT */
|
||||
|
||||
/*
|
||||
* Encrypted images
|
||||
*
|
||||
* Uncomment one of the below options (MCUBOOT_ENCRYPT_x) to enable
|
||||
* encrypted image upgrades.
|
||||
*/
|
||||
|
||||
/* Uncomment to use RSA-OAEP for key encryption */
|
||||
/* #define MCUBOOT_ENCRYPT_RSA */
|
||||
/* Uncomment to use AES-KW for key encryption */
|
||||
/* #define MCUBOOT_ENCRYPT_KW */
|
||||
/* Uncomment to use ECIES-P256 for key encryption */
|
||||
/* #define MCUBOOT_ENCRYPT_EC256 */
|
||||
/* Uncomment to use ECIES-X25519 for key encryption */
|
||||
/* #define MCUBOOT_ENCRYPT_X25519 */
|
||||
|
||||
/* Uncomment to use a builtin key-encryption key (retrieved from a trusted
|
||||
* source - if implemented) instead of a key embedded in the bootloader. */
|
||||
/* #define MCUBOOT_ENC_BUILTIN_KEY */
|
||||
|
||||
#if defined(MCUBOOT_ENCRYPT_RSA) || \
|
||||
defined(MCUBOOT_ENCRYPT_KW) || \
|
||||
defined(MCUBOOT_ENCRYPT_EC256) || \
|
||||
defined(MCUBOOT_ENCRYPT_X25519)
|
||||
#define MCUBOOT_ENC_IMAGES
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Always check the signature of the image in the primary slot before booting,
|
||||
* even if no upgrade was performed. This is recommended if the boot
|
||||
* time penalty is acceptable.
|
||||
*/
|
||||
#define MCUBOOT_VALIDATE_PRIMARY_SLOT
|
||||
|
||||
/*
|
||||
* Flash abstraction
|
||||
*/
|
||||
|
||||
/* Uncomment if your flash map API supports flash_area_get_sectors().
|
||||
* See the flash APIs for more details. */
|
||||
/* #define MCUBOOT_USE_FLASH_AREA_GET_SECTORS */
|
||||
|
||||
/* Default maximum number of flash sectors per image slot; change
|
||||
* as desirable. */
|
||||
#define MCUBOOT_MAX_IMG_SECTORS 128
|
||||
|
||||
/* Default number of separately updateable images; change in case of
|
||||
* multiple images. */
|
||||
#define MCUBOOT_IMAGE_NUMBER 1
|
||||
|
||||
/*
|
||||
* Logging
|
||||
*/
|
||||
|
||||
/*
|
||||
* If logging is enabled the following functions must be defined by the
|
||||
* platform:
|
||||
*
|
||||
* MCUBOOT_LOG_MODULE_REGISTER(domain)
|
||||
* Register a new log module and add the current C file to it.
|
||||
*
|
||||
* MCUBOOT_LOG_MODULE_DECLARE(domain)
|
||||
* Add the current C file to an existing log module.
|
||||
*
|
||||
* MCUBOOT_LOG_ERR(...)
|
||||
* MCUBOOT_LOG_WRN(...)
|
||||
* MCUBOOT_LOG_INF(...)
|
||||
* MCUBOOT_LOG_DBG(...)
|
||||
*
|
||||
* The function priority is:
|
||||
*
|
||||
* MCUBOOT_LOG_ERR > MCUBOOT_LOG_WRN > MCUBOOT_LOG_INF > MCUBOOT_LOG_DBG
|
||||
*/
|
||||
#define MCUBOOT_HAVE_LOGGING 1
|
||||
|
||||
/*
|
||||
* Assertions
|
||||
*/
|
||||
|
||||
/* Uncomment if your platform has its own mcuboot_config/mcuboot_assert.h.
|
||||
* If so, it must provide an ASSERT macro for use by bootutil. Otherwise,
|
||||
* "assert" is used. */
|
||||
/* #define MCUBOOT_HAVE_ASSERT_H */
|
||||
|
||||
/*
|
||||
* Watchdog feeding
|
||||
*/
|
||||
|
||||
/* This macro might be implemented if the OS / HW watchdog is enabled while
|
||||
* doing a swap upgrade and the time it takes for a swapping is long enough
|
||||
* to cause an unwanted reset. If implementing this, the OS main.c must also
|
||||
* enable the watchdog (if required)!
|
||||
*
|
||||
* #define MCUBOOT_WATCHDOG_FEED()
|
||||
* do { do watchdog feeding here! } while (0)
|
||||
*/
|
||||
|
||||
/* If a OS ports support single thread mode or is bare-metal then:
|
||||
* This macro implements call that switches CPU to an idle state, from which
|
||||
* the CPU may be woken up by, for example, UART transmission event.
|
||||
*
|
||||
* Otherwise this macro should be no-op.
|
||||
*/
|
||||
#define MCUBOOT_CPU_IDLE() \
|
||||
do { \
|
||||
} while (0)
|
||||
|
||||
#endif /* __MCUBOOT_CONFIG_H__ */
|
||||
2
bootloader/mcuboot/samples/zephyr/.gitignore
vendored
Normal file
2
bootloader/mcuboot/samples/zephyr/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
*.bin
|
||||
test-images.zip
|
||||
295
bootloader/mcuboot/samples/zephyr/Makefile
Normal file
295
bootloader/mcuboot/samples/zephyr/Makefile
Normal file
@@ -0,0 +1,295 @@
|
||||
###########################################################################
|
||||
# Sample multi-part application Makefile
|
||||
#
|
||||
# Copyright (c) 2017 Linaro Limited
|
||||
# Copyright (c) 2017 Open Source Foundries Limited
|
||||
#
|
||||
# Licensed 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.
|
||||
###########################################################################
|
||||
|
||||
# This is an example Makefile to demonstrate how to use mcuboot to
|
||||
# deploy and upgrade images. The image building should work on any
|
||||
# supported target, however flashing will likely require changes to
|
||||
# the flash addresses, depending on the partition layout of the device
|
||||
# in question.
|
||||
#
|
||||
# running
|
||||
#
|
||||
# make BOARD=frdm_k64f all
|
||||
#
|
||||
# should generate three "*.bin" files in this directory:
|
||||
#
|
||||
# mcuboot.bin: The bootloader itself
|
||||
# signed-hello1.bin: A signed sample.
|
||||
# signed-hello2.bin: An upgrade image, signed and marked for
|
||||
# upgrade.
|
||||
#
|
||||
# "make flash_boot" should flash the bootloader into the flash,
|
||||
# erasing the rest of the device. If you examine the device at this
|
||||
# time, you should see a message about the bootloader not being able
|
||||
# to find a bootable image.
|
||||
#
|
||||
# "make flash_hello1" will then flash the first application into the
|
||||
# "primary slot". This should boot into this app, print a small message, and
|
||||
# give the zephyr console.
|
||||
#
|
||||
# "make flash_hello2" will flash hello2 into the "secondary slot". The
|
||||
# reset should upgrade and run the new image. Resetting again should
|
||||
# then revert back to the first app, since we did not mark this image
|
||||
# as good.
|
||||
|
||||
# Extra .conf fragments to merge into the MCUboot .config, as a
|
||||
# semicolon-separated list (i.e., a CMake list).
|
||||
BOOTLOADER_OVERLAY_CONFIG ?=
|
||||
|
||||
BOARD ?= frdm_k64f
|
||||
SLOT_SIZE ?= 0x60000
|
||||
BOOT_ADDR ?= 0x0
|
||||
IMG0_ADDR ?= 0x20000
|
||||
IMG1_ADDR ?= 0x80000
|
||||
|
||||
.PHONY: check boot hello1 clean_boot clean_hello1 \
|
||||
hello2 clean_hello2 flash_boot flash_hello1 flash_hello2
|
||||
|
||||
# For signing, use the default RSA demo key, to match the default in
|
||||
# the mcuboot Makefile.
|
||||
SIGNING_KEY ?= ../../root-rsa-2048.pem
|
||||
|
||||
# The header size should match that in hello1/prj.conf
|
||||
# CONFIG_TEXT_SECTION_OFFSET. This value needs to be a power of two
|
||||
# that is at least as large as the size of the vector table. The
|
||||
# value given here of 0x200 should be sufficient for any supported
|
||||
# devices, but it can be made smaller, as long as this value matches
|
||||
# that used to build the app.
|
||||
BOOT_HEADER_LEN = 0x200
|
||||
|
||||
# For upgrades, the signing tool needs to know the device alignment.
|
||||
# This requirement will be going away soon.
|
||||
FLASH_ALIGNMENT = 8
|
||||
|
||||
IMGTOOL = ../../scripts/imgtool.py
|
||||
ASSEMBLE = ../../scripts/assemble.py
|
||||
PYOCD = pyocd
|
||||
|
||||
SOURCE_DIRECTORY := $(CURDIR)
|
||||
BUILD_DIRECTORY := $(CURDIR)/build/$(BOARD)
|
||||
BUILD_DIR_BOOT := $(BUILD_DIRECTORY)/mcuboot
|
||||
BUILD_DIR_HELLO1 := $(BUILD_DIRECTORY)/hello1
|
||||
BUILD_DIR_HELLO2 := $(BUILD_DIRECTORY)/hello2
|
||||
|
||||
help:
|
||||
@echo "make <target> BOARD=<board>"
|
||||
@echo "<target>: all, boot, hello1, full.bin"
|
||||
@echo "<board>: frdm_k64f only for now"
|
||||
|
||||
all: boot hello1 hello2
|
||||
|
||||
full.bin: boot hello1 hello2
|
||||
$(ASSEMBLE) -b $(BUILD_DIR_BOOT) \
|
||||
-z $(ZEPHYR_BASE) \
|
||||
-p signed-hello1.bin \
|
||||
-s signed-hello2.bin \
|
||||
-o full.bin
|
||||
|
||||
clean: clean_boot clean_hello1 clean_hello2
|
||||
@rm -f signed-hello1.bin
|
||||
@rm -f signed-hello2.bin
|
||||
@rm -f mcuboot.bin
|
||||
|
||||
boot: check
|
||||
@rm -f mcuboot.bin
|
||||
(mkdir -p $(BUILD_DIR_BOOT) && \
|
||||
cd $(BUILD_DIR_BOOT) && \
|
||||
cmake -DOVERLAY_CONFIG=$(BOOTLOADER_OVERLAY_CONFIG) \
|
||||
-G"Ninja" \
|
||||
-DBOARD=$(BOARD) \
|
||||
$(SOURCE_DIRECTORY)/../../boot/zephyr && \
|
||||
ninja)
|
||||
cp $(BUILD_DIR_BOOT)/zephyr/zephyr.bin mcuboot.bin
|
||||
|
||||
clean_boot: check
|
||||
rm -rf $(BUILD_DIR_BOOT)
|
||||
|
||||
# Build and sign "hello1".
|
||||
hello1: check
|
||||
(mkdir -p $(BUILD_DIR_HELLO1) && \
|
||||
cd $(BUILD_DIR_HELLO1) && \
|
||||
cmake -DFROM_WHO=hello1 \
|
||||
-G"Ninja" \
|
||||
-DBOARD=$(BOARD) \
|
||||
$(SOURCE_DIRECTORY)/hello-world && \
|
||||
ninja)
|
||||
$(IMGTOOL) sign \
|
||||
--key $(SIGNING_KEY) \
|
||||
--header-size $(BOOT_HEADER_LEN) \
|
||||
--align $(FLASH_ALIGNMENT) \
|
||||
--version 1.2 \
|
||||
--slot-size $(SLOT_SIZE) \
|
||||
$(BUILD_DIR_HELLO1)/zephyr/zephyr.bin \
|
||||
signed-hello1.bin
|
||||
|
||||
clean_hello1: check
|
||||
rm -rf $(BUILD_DIR_HELLO1)
|
||||
|
||||
# Build and sign "hello2".
|
||||
# This is the same signing command as above, except that it adds the
|
||||
# "--pad" argument. This will also add the trailer that indicates
|
||||
# this image is intended to be an upgrade. It should be flashed into
|
||||
# the secondary slot instead of the primary slot.
|
||||
hello2: check
|
||||
(mkdir -p $(BUILD_DIR_HELLO2) && \
|
||||
cd $(BUILD_DIR_HELLO2) && \
|
||||
cmake -DFROM_WHO=hello2 \
|
||||
-G"Ninja" \
|
||||
-DBOARD=$(BOARD) \
|
||||
$(SOURCE_DIRECTORY)/hello-world && \
|
||||
ninja)
|
||||
$(IMGTOOL) sign \
|
||||
--key $(SIGNING_KEY) \
|
||||
--header-size $(BOOT_HEADER_LEN) \
|
||||
--align $(FLASH_ALIGNMENT) \
|
||||
--version 1.2 \
|
||||
--slot-size $(SLOT_SIZE) \
|
||||
--pad \
|
||||
$(BUILD_DIR_HELLO2)/zephyr/zephyr.bin \
|
||||
signed-hello2.bin
|
||||
|
||||
clean_hello2: check
|
||||
rm -rf $(BUILD_DIR_HELLO2)
|
||||
|
||||
# These flash_* targets use pyocd to flash the images. The addresses
|
||||
# are hardcoded at this time.
|
||||
|
||||
flash_boot:
|
||||
$(PYOCD) flash -e chip -a $(BOOT_ADDR) mcuboot.bin
|
||||
|
||||
flash_hello1:
|
||||
$(PYOCD) flash -a $(IMG0_ADDR) signed-hello1.bin
|
||||
|
||||
flash_hello2:
|
||||
$(PYOCD) flash -a $(IMG1_ADDR) signed-hello2.bin
|
||||
|
||||
flash_full:
|
||||
$(PYOCD) flash -e chip -a $(BOOT_ADDR) full.bin
|
||||
|
||||
# These test- targets reinvoke make with the configuration set to test
|
||||
# various configurations. This will generally be followed by using
|
||||
# the above flash targets.
|
||||
|
||||
# Test a good image, with a good upgrade, using RSA signatures.
|
||||
# flash_boot: Unable to find bootable image
|
||||
# flash_hello1: hello1 runs
|
||||
# flash_hello2: hello2 runs
|
||||
# reset: hello1 runs
|
||||
test-good-rsa: clean
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-rsa.conf \
|
||||
all
|
||||
|
||||
# Test a good image, with a good upgrade, using ECDSA signatures.
|
||||
# flash_boot: Unable to find bootable image
|
||||
# flash_hello1: hello1 runs
|
||||
# flash_hello2: hello2 runs
|
||||
# reset: hello1 runs
|
||||
test-good-ecdsa: clean
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-ecdsa-p256.conf \
|
||||
SIGNING_KEY=../../root-ec-p256.pem \
|
||||
all
|
||||
|
||||
# Test (with RSA) that overwrite-only works. This should boot,
|
||||
# upgrade correctly, but not revert once the upgrade has been done.
|
||||
# flash_boot: Unable to find bootable image
|
||||
# flash_hello1: hello1 runs
|
||||
# flash_hello2: hello2 runs
|
||||
# reset: hello2 runs
|
||||
test-overwrite: clean
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-upgrade-only.conf \
|
||||
all
|
||||
|
||||
# Test that when configured for RSA, a wrong signature in the upgrade
|
||||
# image will fail to upgrade.
|
||||
# flash_boot: Unable to find bootable image
|
||||
# flash_hello1: hello1 runs
|
||||
# flash_hello2: hello1 runs
|
||||
# reset: hello1 runs
|
||||
test-bad-rsa-upgrade: clean
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-rsa.conf \
|
||||
boot hello1
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-rsa.conf \
|
||||
SIGNING_KEY=../../root-ec-p256.pem \
|
||||
hello2
|
||||
|
||||
# Test that when configured for ECDSA, a wrong signature in the upgrade
|
||||
# image will fail to upgrade.
|
||||
# flash_boot: Unable to find bootable image
|
||||
# flash_hello1: hello1 runs
|
||||
# flash_hello2: hello1 runs
|
||||
# reset: hello1 runs
|
||||
test-bad-ecdsa-upgrade: clean
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-ecdsa-p256.conf \
|
||||
SIGNING_KEY=../../root-ec-p256.pem \
|
||||
boot hello1
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-ecdsa-p256.conf \
|
||||
SIGNING_KEY=../../root-rsa-2048.pem \
|
||||
hello2
|
||||
|
||||
# Test that when configured to not validate the primary slot, we still boot, but
|
||||
# don't upgrade.
|
||||
# flash_boot: tries to boot and resets
|
||||
# flash_hello1: hello1 runs
|
||||
# flash_hello2: hello1 runs
|
||||
# reset: hello1 runs
|
||||
test-no-bootcheck: clean
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-skip-primary-slot-validate.conf \
|
||||
SIGNING_KEY=../../root-ec-p256.pem \
|
||||
all
|
||||
|
||||
# Test a good image, with a wrong-signature upgrade, using RSA signatures.
|
||||
# flash_boot: Unable to find bootable image
|
||||
# flash_hello1: hello1 runs
|
||||
# flash_hello2: hello1 runs
|
||||
# reset: hello1 runs
|
||||
test-wrong-rsa: clean
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-rsa.conf \
|
||||
boot hello1
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-rsa.conf \
|
||||
SIGNING_KEY=bad-keys/bad-rsa-2048.pem \
|
||||
hello2
|
||||
|
||||
# Test a good image, with a wrong-signature upgrade, using ECDSA signatures.
|
||||
# flash_boot: Unable to find bootable image
|
||||
# flash_hello1: hello1 runs
|
||||
# flash_hello2: hello1 runs
|
||||
# reset: hello1 runs
|
||||
test-wrong-ecdsa: clean
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-ecdsa-p256.conf \
|
||||
SIGNING_KEY=../../root-ec-p256.pem \
|
||||
boot hello1
|
||||
$(MAKE) \
|
||||
BOOTLOADER_OVERLAY_CONFIG=$(PWD)/overlay-ecdsa-p256.conf \
|
||||
SIGNING_KEY=bad-keys/bad-ec-p256.pem \
|
||||
hello2
|
||||
|
||||
check:
|
||||
@if [ -z "$$ZEPHYR_BASE" ]; then echo "Zephyr environment not set up"; false; fi
|
||||
@if [ -z "$(BOARD)" ]; then echo "You must specify BOARD=<board>"; false; fi
|
||||
24
bootloader/mcuboot/samples/zephyr/README.md
Normal file
24
bootloader/mcuboot/samples/zephyr/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Zephyr sample application.
|
||||
|
||||
In order to successfully deploy an application using MCUboot, it is
|
||||
necessary to build at least one other binary: the application itself.
|
||||
It is beyond the scope of this documentation to describe what an
|
||||
application is able to do, however a working example is certainly
|
||||
useful.
|
||||
|
||||
Please see the comments in the Makefile in this directory for more
|
||||
details on how to build and test this application.
|
||||
|
||||
Note that this sample uses the "ninja" build tool, which can be
|
||||
installed on most systems using the system package manager, e.g., for
|
||||
a Debian-based distro:
|
||||
|
||||
```
|
||||
$ sudo apt-get install ninja
|
||||
```
|
||||
|
||||
or in Fedora:
|
||||
|
||||
```
|
||||
$ sudo dnf install ninja
|
||||
```
|
||||
6
bootloader/mcuboot/samples/zephyr/bad-keys/README.md
Normal file
6
bootloader/mcuboot/samples/zephyr/bad-keys/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Bad keys for testing
|
||||
|
||||
This directory contains some alternate keys that can be used for
|
||||
testing. Signing the images with either of these keys, but leaving
|
||||
the demo keys's public keys in the bootloader should result in it not
|
||||
upgrading, or not booting.
|
||||
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEILmqmiH6y3EGhLkTcnNtU7hZ1wnc51MIL53npseRX7vJoAoGCCqGSM49
|
||||
AwEHoUQDQgAEcX9ExNjZfsckp6AdutjPjVJsvP6ZZkKfLsGnRpKR+9OpO9/qmJHs
|
||||
ks+ZXo70SEANjWnNlxKNAVci8aUm8UskLw==
|
||||
-----END EC PRIVATE KEY-----
|
||||
27
bootloader/mcuboot/samples/zephyr/bad-keys/bad-rsa-2048.pem
Normal file
27
bootloader/mcuboot/samples/zephyr/bad-keys/bad-rsa-2048.pem
Normal file
@@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEowIBAAKCAQEAzXhCIc6kig0DRWEyKj4N8v/bfvh/RmU73Jo0Z0RAFSLnFrE5
|
||||
5W5C9tsdDalhN5HV7xBQCzr7GSW1C6MNvtw/lVr4+x4LvgwYD6kl+9IZc5udPIJ1
|
||||
R7aLBP2o4r6rJWtCj9Y6bifsMlVkHCONIHDGhp3bSl+9C2EqfwqJENg3mHYyZcbr
|
||||
kBfLhILE24T+MhxkPZiI3Ox6XthwT7Is8ZCXF6VCYaK6N8jXAXz8OiEhIpMl3Z3m
|
||||
DqxaM0ovSXfXvOfMeKN76iI9m8S4JnPbuzu+/5GdSnNbIxoluzXU7e52FoKgthNM
|
||||
2mArAak5x3IqsStY0qDCODSlNnSha9+jfk8ULwIDAQABAoIBAQC7Z6dx7GdY3vuP
|
||||
yVIXA1h3vfP2gDKeA3GxCRko4zBL1vTNVsJGx+XeAAYk0suwAp0NGmTXiWlDC4hw
|
||||
37yGy55W3I3hhQsSwTck+ZOCdqPuNQ4aBadwzEdKOw5SGbRCQe2JAc1zcYhWdFoF
|
||||
7EspPpNkbxB3apEjkvFOxE42Be/XZrwxig1OQJ9DpOhTeV8+jljg6aSzOuQxdR4G
|
||||
ZXTzACnb20jnefnwmC5lhZxRWYEXkc96onYIvrDpIMdTzTnTbshJjg5HNPOEEgpF
|
||||
U1x2iCRB3tN9QHbzdH/XrnRBr9Yy62SUIDXf4LBqin/pRQPodh9ZM7zanrhzsuiy
|
||||
Tro2WKhRAoGBANoAT73haGrUb9ZSdzpu5qOD0eaQZPCIlubRrT5BCXPS2xVIGe+g
|
||||
eDaBljdlXDJnKvBqjOVQyU7lrZAIVWgz6qD1HNIQZI30WivXejL4GeoXnAnp/ohh
|
||||
1QmjMVvlcGe/22jpDmJa3Qgm4leaUxnxxilO/pQlZzzndBP88Df4/hIJAoGBAPFI
|
||||
xBRq0SdBWhSydeEFvm8n37/icrN+V9f/Ka9tbPZcJaowzqQPrAHtu2CBD1JVyo2G
|
||||
sKxFy867vCHntFu8zq2KSpCPVyeR+pDvwknr9PDm+DiLScBCGdyKqjBazT5+mHzP
|
||||
fKk6nRV8uoNXLZQtnqKJzN61bYrnFaOQx6GZM6J3AoGAUHqA9bY7GAUo7FQxU88R
|
||||
Mhg96wIvYWTrYHbToAHefXXAD1E40e/JsUWRsQ2oRas0fOC49wcl6gx8UInjDb7s
|
||||
xVL3usz2cjlc+IZpxFs3JeZlYnuRzcNgJFispiJDpul7FHXFK6YjpxjDwldkilVp
|
||||
NGLHNOXCAQfpIF/mRqOTGBECgYAmb7kMp5d58WcwNN2iYw/bFTcHkkNDZLUJq5Qw
|
||||
ZfYdqMA3RF8ms3hrNjvLO8P9Eb2angI270dwP2fQ3uBUXNdvvb/zF2KC4zZPMGJ6
|
||||
9COo3KJeH5I4Fk+YWl6SJWTct74C4+qv6q5rZdswYQrZuAq1Sc5hC/XPUtCXpdCn
|
||||
ZYhcMQKBgEHN3ZYe7gOfxR4rqk+OIsAUN9P3zyu6kQzUL1BQ7t7Gwi1dv6+E+BGQ
|
||||
vGUt4RGG10g3K9twfhOHnwAiruEk6CK2+1G/ZsGCrPIE21KCcucUCPvzUGhintO+
|
||||
b+Q5kAeZFg5CB9b616SY/GvlzPraNx5OZfI8nw39U9do7N/yFiKT
|
||||
-----END RSA PRIVATE KEY-----
|
||||
22
bootloader/mcuboot/samples/zephyr/build-boot.sh
Normal file
22
bootloader/mcuboot/samples/zephyr/build-boot.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#! /bin/bash
|
||||
|
||||
# Build the bootloader.
|
||||
|
||||
# In order to build successfully, ZEPHYR_SDK_INSTALL_DIR and
|
||||
# ZEPHYR_GCC_VARIANT need to be set, as well as zephyr/zephyr-env.sh
|
||||
# must be sourced.
|
||||
|
||||
die() {
|
||||
echo error: "$@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ -z "$ZEPHYR_BASE" ]; then
|
||||
die "Please setup for a Zephyr build before running this script."
|
||||
fi
|
||||
|
||||
if [ -z "$BOARD" ]; then
|
||||
die "Please set BOARD to a valid board before running this script."
|
||||
fi
|
||||
|
||||
make BOARD=${BOARD} -j$(nproc) boot || die "Build mcuboot"
|
||||
22
bootloader/mcuboot/samples/zephyr/build-hello.sh
Normal file
22
bootloader/mcuboot/samples/zephyr/build-hello.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#! /bin/bash
|
||||
|
||||
# Build the Sample hello program
|
||||
|
||||
# In order to build successfully, ZEPHYR_SDK_INSTALL_DIR and
|
||||
# ZEPHYR_GCC_VARIANT need to be set, as well as zephyr/zephyr-env.sh
|
||||
# must be sourced.
|
||||
|
||||
die() {
|
||||
echo error: "$@"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ -z "$ZEPHYR_BASE" ]; then
|
||||
die "Please setup for a Zephyr build before running this script."
|
||||
fi
|
||||
|
||||
if [ -z "$BOARD" ]; then
|
||||
die "Please set BOARD to a valid board before running this script."
|
||||
fi
|
||||
|
||||
make BOARD=${BOARD} -j$(nproc) hello1 || die "Build hello1"
|
||||
26
bootloader/mcuboot/samples/zephyr/hello-world/CMakeLists.txt
Normal file
26
bootloader/mcuboot/samples/zephyr/hello-world/CMakeLists.txt
Normal file
@@ -0,0 +1,26 @@
|
||||
# Top-level CMakeLists.txt for the skeleton application.
|
||||
#
|
||||
# Copyright (c) 2017 Open Source Foundries Limited
|
||||
# Copyright (c) 2018 Foundries.io Ltd
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# This provides a basic application structure suitable for loading by
|
||||
# mcuboot, which is easy to customize on a per-board basis. It can be
|
||||
# used as a starting point for new applications.
|
||||
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
|
||||
# find_package(Zephyr) in order to load application boilerplate:
|
||||
# https://docs.zephyrproject.org/latest/develop/application/index.html
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(NONE)
|
||||
|
||||
# This string ends up getting printed in the device console
|
||||
if (NOT DEFINED FROM_WHO)
|
||||
set(FROM_WHO Zephyr)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(app PRIVATE "-DMCUBOOT_HELLO_WORLD_FROM=\"${FROM_WHO}\"")
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
6
bootloader/mcuboot/samples/zephyr/hello-world/README.rst
Normal file
6
bootloader/mcuboot/samples/zephyr/hello-world/README.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
This is a "Hello world" skeleton application which can be used as a
|
||||
starting point for Zephyr application development using mcuboot.
|
||||
|
||||
It includes the configuration "glue" needed to make the application
|
||||
loadable by mcuboot in addition to a basic Zephyr hello world
|
||||
application's code.
|
||||
1
bootloader/mcuboot/samples/zephyr/hello-world/boards/.gitignore
vendored
Normal file
1
bootloader/mcuboot/samples/zephyr/hello-world/boards/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*-local.conf
|
||||
@@ -0,0 +1,2 @@
|
||||
You can place per-board configuration here. See the comments in the
|
||||
CMakeLists.txt for more information.
|
||||
12
bootloader/mcuboot/samples/zephyr/hello-world/prj.conf
Normal file
12
bootloader/mcuboot/samples/zephyr/hello-world/prj.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
# Print a banner on the UART on startup.
|
||||
CONFIG_BOOT_BANNER=y
|
||||
|
||||
# Enable console and printk()
|
||||
CONFIG_PRINTK=y
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
|
||||
# Enable Zephyr application to be booted by MCUboot
|
||||
CONFIG_BOOTLOADER_MCUBOOT=y
|
||||
|
||||
# Use the default MCUBoot PEM key file (BOOT_SIGNATURE_KEY_FILE)
|
||||
CONFIG_MCUBOOT_SIGNATURE_KEY_FILE="bootloader/mcuboot/root-rsa-2048.pem"
|
||||
@@ -0,0 +1,9 @@
|
||||
sample:
|
||||
name: Application Skeleton
|
||||
description: Basic "hello world" application, but loadable by mcuboot
|
||||
platforms: all
|
||||
tests:
|
||||
- test:
|
||||
build_only: true
|
||||
tags: samples tests
|
||||
min_ram: 16
|
||||
@@ -0,0 +1 @@
|
||||
obj-y = main.o
|
||||
14
bootloader/mcuboot/samples/zephyr/hello-world/src/main.c
Normal file
14
bootloader/mcuboot/samples/zephyr/hello-world/src/main.c
Normal file
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Linaro, Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/sys/printk.h>
|
||||
|
||||
void main(void)
|
||||
{
|
||||
printk("Hello World from %s on %s!\n",
|
||||
MCUBOOT_HELLO_WORLD_FROM, CONFIG_BOARD);
|
||||
}
|
||||
281
bootloader/mcuboot/samples/zephyr/mcutests/mcutests.go
Normal file
281
bootloader/mcuboot/samples/zephyr/mcutests/mcutests.go
Normal file
@@ -0,0 +1,281 @@
|
||||
// Package mcutests
|
||||
package mcutests // github.com/mcu-tools/mcuboot/samples/zephyr/mcutests
|
||||
|
||||
// The main driver of this consists of a series of tests. Each test
|
||||
// then contains a series of commands and expect results.
|
||||
var Tests = []struct {
|
||||
Name string
|
||||
ShortName string
|
||||
Tests []OneTest
|
||||
}{
|
||||
{
|
||||
Name: "Good RSA",
|
||||
ShortName: "good-rsa",
|
||||
Tests: []OneTest{
|
||||
{
|
||||
Build: [][]string{
|
||||
{"make", "test-good-rsa"},
|
||||
},
|
||||
Commands: [][]string{
|
||||
{"make", "flash_boot"},
|
||||
},
|
||||
Expect: "Unable to find bootable image",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello1"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello2"},
|
||||
},
|
||||
Expect: "Hello World from hello2",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"pyocd", "commander", "-c", "reset"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Good ECDSA",
|
||||
ShortName: "good-ecdsa",
|
||||
Tests: []OneTest{
|
||||
{
|
||||
Build: [][]string{
|
||||
{"make", "test-good-ecdsa"},
|
||||
},
|
||||
Commands: [][]string{
|
||||
{"make", "flash_boot"},
|
||||
},
|
||||
Expect: "Unable to find bootable image",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello1"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello2"},
|
||||
},
|
||||
Expect: "Hello World from hello2",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"pyocd", "commander", "-c", "reset"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Overwrite",
|
||||
ShortName: "overwrite",
|
||||
Tests: []OneTest{
|
||||
{
|
||||
Build: [][]string{
|
||||
{"make", "test-overwrite"},
|
||||
},
|
||||
Commands: [][]string{
|
||||
{"make", "flash_boot"},
|
||||
},
|
||||
Expect: "Unable to find bootable image",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello1"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello2"},
|
||||
},
|
||||
Expect: "Hello World from hello2",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"pyocd", "commander", "-c", "reset"},
|
||||
},
|
||||
Expect: "Hello World from hello2",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Bad RSA",
|
||||
ShortName: "bad-rsa-upgrade",
|
||||
Tests: []OneTest{
|
||||
{
|
||||
Build: [][]string{
|
||||
{"make", "test-bad-rsa-upgrade"},
|
||||
},
|
||||
Commands: [][]string{
|
||||
{"make", "flash_boot"},
|
||||
},
|
||||
Expect: "Unable to find bootable image",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello1"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello2"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"pyocd", "commander", "-c", "reset"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Bad RSA",
|
||||
ShortName: "bad-ecdsa-upgrade",
|
||||
Tests: []OneTest{
|
||||
{
|
||||
Build: [][]string{
|
||||
{"make", "test-bad-ecdsa-upgrade"},
|
||||
},
|
||||
Commands: [][]string{
|
||||
{"make", "flash_boot"},
|
||||
},
|
||||
Expect: "Unable to find bootable image",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello1"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello2"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"pyocd", "commander", "-c", "reset"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "No bootcheck",
|
||||
ShortName: "no-bootcheck",
|
||||
Tests: []OneTest{
|
||||
{
|
||||
Build: [][]string{
|
||||
{"make", "test-no-bootcheck"},
|
||||
},
|
||||
Commands: [][]string{
|
||||
{"make", "flash_boot"},
|
||||
},
|
||||
Expect: "Unable to find bootable image",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello1"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello2"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"pyocd", "commander", "-c", "reset"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Wrong RSA",
|
||||
ShortName: "wrong-rsa",
|
||||
Tests: []OneTest{
|
||||
{
|
||||
Build: [][]string{
|
||||
{"make", "test-wrong-rsa"},
|
||||
},
|
||||
Commands: [][]string{
|
||||
{"make", "flash_boot"},
|
||||
},
|
||||
Expect: "Unable to find bootable image",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello1"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello2"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"pyocd", "commander", "-c", "reset"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Wrong ECDSA",
|
||||
ShortName: "wrong-ecdsa",
|
||||
Tests: []OneTest{
|
||||
{
|
||||
Build: [][]string{
|
||||
{"make", "test-wrong-ecdsa"},
|
||||
},
|
||||
Commands: [][]string{
|
||||
{"make", "flash_boot"},
|
||||
},
|
||||
Expect: "Unable to find bootable image",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello1"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"make", "flash_hello2"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
{
|
||||
Commands: [][]string{
|
||||
{"pyocd", "commander", "-c", "reset"},
|
||||
},
|
||||
Expect: "Hello World from hello1",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type OneTest struct {
|
||||
Build [][]string
|
||||
Commands [][]string
|
||||
Expect string
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
# Kconfig overlay for building with ECDSA-P256 signatures
|
||||
CONFIG_BOOT_SIGNATURE_TYPE_ECDSA_P256=y
|
||||
CONFIG_BOOT_SIGNATURE_KEY_FILE="root-ec-p256.pem"
|
||||
CONFIG_BOOT_SWAP_USING_MOVE=y
|
||||
3
bootloader/mcuboot/samples/zephyr/overlay-rsa.conf
Normal file
3
bootloader/mcuboot/samples/zephyr/overlay-rsa.conf
Normal file
@@ -0,0 +1,3 @@
|
||||
# Kconfig overlay for building with RSA signatures
|
||||
CONFIG_BOOT_SIGNATURE_TYPE_RSA=y
|
||||
CONFIG_BOOT_SWAP_USING_MOVE=y
|
||||
@@ -0,0 +1,4 @@
|
||||
# Kconfig overlay for building without validating primary slot.
|
||||
|
||||
# CONFIG_BOOT_VALIDATE_SLOT0 is not set
|
||||
CONFIG_BOOT_SWAP_USING_MOVE=y
|
||||
@@ -0,0 +1,2 @@
|
||||
# Kconfig overlay for building in upgrade-only mode.
|
||||
CONFIG_BOOT_UPGRADE_ONLY=y
|
||||
290
bootloader/mcuboot/samples/zephyr/run-tests.go
Normal file
290
bootloader/mcuboot/samples/zephyr/run-tests.go
Normal file
@@ -0,0 +1,290 @@
|
||||
// +build ignore
|
||||
//
|
||||
// Build multiple configurations of MCUboot for Zephyr, making sure
|
||||
// that they run properly.
|
||||
//
|
||||
// Run as:
|
||||
//
|
||||
// go run run-tests.go [flags]
|
||||
//
|
||||
// Add -help as a flag to get help. See comment below for logIn on
|
||||
// how to configure terminal output to a file so this program can see
|
||||
// the output of the Zephyr device.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mcu-tools/mcuboot/samples/zephyr/mcutests"
|
||||
)
|
||||
|
||||
// logIn gives the pathname of the log output from the Zephyr device.
|
||||
// In order to see the serial output, but still be useful for human
|
||||
// debugging, the output of the terminal emulator should be teed to a
|
||||
// file that this program will read from. This can be done with
|
||||
// something like:
|
||||
//
|
||||
// picocom -b 115200 /dev/ttyACM0 | tee /tmp/zephyr.out
|
||||
//
|
||||
// Other terminal programs should also have logging options.
|
||||
var logIn = flag.String("login", "/tmp/zephyr.out", "File name of terminal log from Zephyr device")
|
||||
|
||||
// Output from this test run is written to the given log file.
|
||||
var logOut = flag.String("logout", "tests.log", "Log file to write to")
|
||||
|
||||
var preBuilt = flag.String("prebuilt", "", "Name of file with prebuilt tests")
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
flag.Parse()
|
||||
|
||||
lines := make(chan string, 30)
|
||||
go readLog(lines)
|
||||
|
||||
// Write output to a log file
|
||||
logFile, err := os.Create(*logOut)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer logFile.Close()
|
||||
lg := bufio.NewWriter(logFile)
|
||||
defer lg.Flush()
|
||||
|
||||
var extractor *Extractor
|
||||
|
||||
if *preBuilt != "" {
|
||||
// If there are pre-built images, open them.
|
||||
extractor, err = NewExtractor(*preBuilt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer extractor.Close()
|
||||
}
|
||||
|
||||
for _, group := range mcutests.Tests {
|
||||
fmt.Printf("Running %q\n", group.Name)
|
||||
fmt.Fprintf(lg, "-------------------------------------\n")
|
||||
fmt.Fprintf(lg, "---- Running %q\n", group.Name)
|
||||
|
||||
for _, test := range group.Tests {
|
||||
if *preBuilt == "" {
|
||||
// No prebuilt, build the tests
|
||||
// ourselves.
|
||||
err = runCommands(test.Build, lg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Extract the build artifacts from
|
||||
// the zip file.
|
||||
err = extractor.Extract(group.ShortName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = runCommands(test.Commands, lg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = expect(lg, lines, test.Expect)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Fprintf(lg, "---- Passed\n")
|
||||
}
|
||||
fmt.Printf(" Passed!\n")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run a set of commands
|
||||
func runCommands(cmds [][]string, lg io.Writer) error {
|
||||
for _, cmd := range cmds {
|
||||
fmt.Printf(" %s\n", cmd)
|
||||
fmt.Fprintf(lg, "---- Run: %s\n", cmd)
|
||||
err := runCommand(cmd, lg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Run a single command.
|
||||
func runCommand(cmd []string, lg io.Writer) error {
|
||||
c := exec.Command(cmd[0], cmd[1:]...)
|
||||
c.Stdout = lg
|
||||
c.Stderr = lg
|
||||
return c.Run()
|
||||
}
|
||||
|
||||
// Expect the given string.
|
||||
func expect(lg io.Writer, lines <-chan string, exp string) error {
|
||||
// Read lines, and if we hit a timeout before seeing our
|
||||
// expected line, then consider that an error.
|
||||
fmt.Fprintf(lg, "---- expect: %q\n", exp)
|
||||
|
||||
stopper := time.NewTimer(10 * time.Second)
|
||||
defer stopper.Stop()
|
||||
outer:
|
||||
for {
|
||||
select {
|
||||
case line := <-lines:
|
||||
fmt.Fprintf(lg, "---- target: %q\n", line)
|
||||
if strings.Contains(line, exp) {
|
||||
break outer
|
||||
}
|
||||
case <-stopper.C:
|
||||
fmt.Fprintf(lg, "timeout, didn't receive output\n")
|
||||
return fmt.Errorf("timeout, didn't receive expected string: %q", exp)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read things from the log file, discarding everything already there.
|
||||
func readLog(sink chan<- string) {
|
||||
file, err := os.Open(*logIn)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = file.Seek(0, 2)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
prefix := ""
|
||||
for {
|
||||
// Read lines until EOF, then delay a bit, and do it
|
||||
// all again.
|
||||
rd := bufio.NewReader(file)
|
||||
|
||||
for {
|
||||
line, err := rd.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
// A partial line can happen because
|
||||
// we are racing with the writer.
|
||||
if line != "" {
|
||||
prefix = line
|
||||
}
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
line = prefix + line
|
||||
prefix = ""
|
||||
sink <- line
|
||||
// fmt.Printf("line: %q\n", line)
|
||||
}
|
||||
|
||||
// Pause a little
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
// An Extractor holds an opened Zip file, and is able to extract files
|
||||
// based on the directory name.
|
||||
type Extractor struct {
|
||||
file *os.File
|
||||
zip *zip.Reader
|
||||
}
|
||||
|
||||
// NewExtractor returns an Extractor based on the contents of a zip
|
||||
// file.
|
||||
func NewExtractor(name string) (*Extractor, error) {
|
||||
f, err := os.Open(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
size, err := f.Seek(0, 2)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rd, err := zip.NewReader(f, size)
|
||||
if err != nil {
|
||||
f.Close()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Extractor{
|
||||
file: f,
|
||||
zip: rd,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (e *Extractor) Close() error {
|
||||
return e.file.Close()
|
||||
}
|
||||
|
||||
// Extract extracts the files of the given directory name into the
|
||||
// current directory. These files will overwrite any files of these
|
||||
// names that already exist (presumably from previous extractions).
|
||||
func (e *Extractor) Extract(dir string) error {
|
||||
prefix := dir + "/"
|
||||
|
||||
count := 0
|
||||
for _, file := range e.zip.File {
|
||||
if len(file.Name) > len(prefix) && strings.HasPrefix(file.Name, prefix) {
|
||||
outName := file.Name[len(prefix):len(file.Name)]
|
||||
fmt.Printf("->%q\n", outName)
|
||||
|
||||
err := e.single(file, outName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
count += 1
|
||||
}
|
||||
}
|
||||
|
||||
if count == 0 {
|
||||
return fmt.Errorf("File for %s missing from archive", dir)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// single extracts a single file from the zip archive, writing the
|
||||
// results to a file 'outName'.
|
||||
func (e *Extractor) single(file *zip.File, outName string) error {
|
||||
inf, err := file.Open()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
outf, err := os.Create(outName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer outf.Close()
|
||||
|
||||
_, err = io.Copy(outf, inf)
|
||||
return err
|
||||
}
|
||||
4
bootloader/mcuboot/samples/zephyr/run-tests.sh
Normal file
4
bootloader/mcuboot/samples/zephyr/run-tests.sh
Normal file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "Please use the new test runner: go run run-tests.go"
|
||||
exit 1
|
||||
156
bootloader/mcuboot/samples/zephyr/test-compile.go
Normal file
156
bootloader/mcuboot/samples/zephyr/test-compile.go
Normal file
@@ -0,0 +1,156 @@
|
||||
// +build ignore
|
||||
//
|
||||
// Build all of the tests.
|
||||
//
|
||||
// Run as:
|
||||
//
|
||||
// go run test-compile.go -out name.tar
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
|
||||
"github.com/mcu-tools/mcuboot/samples/zephyr/mcutests"
|
||||
)
|
||||
|
||||
var outFile = flag.String("out", "test-images.zip", "Name of zip file to put built tests into")
|
||||
|
||||
func main() {
|
||||
err := run()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func run() error {
|
||||
flag.Parse()
|
||||
|
||||
zipper, err := NewBuilds()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer zipper.Close()
|
||||
|
||||
for _, group := range mcutests.Tests {
|
||||
fmt.Printf("Compiling %q\n", group.ShortName)
|
||||
c := exec.Command("make",
|
||||
fmt.Sprintf("test-%s", group.ShortName))
|
||||
// TODO: Should capture the output and show it if
|
||||
// there is an error.
|
||||
err = c.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = zipper.Capture(group.ShortName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// A Builds create a zipfile of the contents of various builds. The
|
||||
// names will be constructed.
|
||||
type Builds struct {
|
||||
// The file being written to.
|
||||
file *os.File
|
||||
|
||||
// The zip writer writing the data.
|
||||
zip *zip.Writer
|
||||
}
|
||||
|
||||
func NewBuilds() (*Builds, error) {
|
||||
name := *outFile
|
||||
file, err := os.OpenFile(name, os.O_CREATE|os.O_EXCL|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
z := zip.NewWriter(file)
|
||||
|
||||
return &Builds{
|
||||
file: file,
|
||||
zip: z,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *Builds) Close() error {
|
||||
return b.zip.Close()
|
||||
}
|
||||
|
||||
func (b *Builds) Capture(testName string) error {
|
||||
// Collect stat information from the test directory, which
|
||||
// should be close enough to make the zip file meaningful.
|
||||
info, err := os.Stat(".")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name = testName + "/"
|
||||
|
||||
_, err = b.zip.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, name := range []string{
|
||||
"mcuboot.bin",
|
||||
"signed-hello1.bin",
|
||||
"signed-hello2.bin",
|
||||
} {
|
||||
err = b.add(testName, name, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Builds) add(baseName, zipName, fileName string) error {
|
||||
inp, err := os.Open(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer inp.Close()
|
||||
|
||||
info, err := inp.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header, err := zip.FileInfoHeader(info)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
header.Name = path.Join(baseName, zipName)
|
||||
header.Method = zip.Deflate
|
||||
|
||||
wr, err := b.zip.CreateHeader(header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(wr, inp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user