boot/mcuboot: Add support for MCUboot bootloader
Signed-off-by: Gustavo Henrique Nihei <gustavo.nihei@espressif.com>
This commit is contained in:
parent
e6b767f185
commit
794cfd0c5c
1
boot/.gitignore
vendored
Normal file
1
boot/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/Kconfig
|
21
boot/Make.defs
Normal file
21
boot/Make.defs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
############################################################################
|
||||||
|
# apps/boot/Make.defs
|
||||||
|
#
|
||||||
|
# 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 $(wildcard $(APPDIR)/boot/*/Make.defs)
|
23
boot/Makefile
Normal file
23
boot/Makefile
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
############################################################################
|
||||||
|
# apps/boot/Makefile
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
MENUDESC = "Bootloader Utilities"
|
||||||
|
|
||||||
|
include $(APPDIR)/Directory.mk
|
2
boot/mcuboot/.gitignore
vendored
Normal file
2
boot/mcuboot/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/mcuboot
|
||||||
|
/*.tar.gz
|
122
boot/mcuboot/Kconfig
Normal file
122
boot/mcuboot/Kconfig
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
#
|
||||||
|
# For a description of the syntax of this configuration file,
|
||||||
|
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||||
|
#
|
||||||
|
|
||||||
|
menuconfig BOOT_MCUBOOT
|
||||||
|
bool "MCUboot"
|
||||||
|
default n
|
||||||
|
select BCH
|
||||||
|
---help---
|
||||||
|
Enable support for the MCUboot bootloader.
|
||||||
|
|
||||||
|
if BOOT_MCUBOOT
|
||||||
|
|
||||||
|
config MCUBOOT_VERSION
|
||||||
|
string "MCUboot version"
|
||||||
|
default "01184bd0361c4128c6382aa9c640b02e7f1422f6"
|
||||||
|
|
||||||
|
config MCUBOOT_ENABLE_LOGGING
|
||||||
|
bool "Enable MCUboot logging"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Enable MCUboot's logging infrastructure.
|
||||||
|
|
||||||
|
config MCUBOOT_BOOTLOADER
|
||||||
|
bool "MCUboot bootloader application"
|
||||||
|
default n
|
||||||
|
select BOARDCTL
|
||||||
|
select BOARDCTL_BOOT_IMAGE
|
||||||
|
---help---
|
||||||
|
MCUboot bootloader application.
|
||||||
|
|
||||||
|
config MCUBOOT_UPDATE_AGENT_EXAMPLE
|
||||||
|
bool "MCUboot update agent example"
|
||||||
|
default n
|
||||||
|
depends on NET_TCP
|
||||||
|
---help---
|
||||||
|
Example application that implements an update agent that downloads
|
||||||
|
an application firmware image from a given URL and saves it to the
|
||||||
|
secondary slot as a pending update.
|
||||||
|
|
||||||
|
if MCUBOOT_UPDATE_AGENT_EXAMPLE
|
||||||
|
|
||||||
|
config MCUBOOT_UPDATE_AGENT_EXAMPLE_UPDATE_URL
|
||||||
|
string "URL for update image"
|
||||||
|
default ""
|
||||||
|
|
||||||
|
config MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_BUFFER_SIZE
|
||||||
|
int "Download buffer size in bytes"
|
||||||
|
default 512
|
||||||
|
|
||||||
|
config MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
bool "Calculate MD5 of update image"
|
||||||
|
default n
|
||||||
|
depends on CODECS_HASH_MD5
|
||||||
|
|
||||||
|
config MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_MD5_HASH
|
||||||
|
string "Expected MD5 sum of update image"
|
||||||
|
default ""
|
||||||
|
depends on MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
|
||||||
|
endif # MCUBOOT_UPDATE_AGENT_EXAMPLE
|
||||||
|
|
||||||
|
config MCUBOOT_SLOT_CONFIRM_EXAMPLE
|
||||||
|
tristate "MCUboot slot confirm example"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Example application for confirming a newly installed application
|
||||||
|
application firmware image using MCUboot public APIs.
|
||||||
|
This application should be used as the OTA update package of the
|
||||||
|
MCUBOOT_UPDATE_AGENT_EXAMPLE example.
|
||||||
|
|
||||||
|
config MCUBOOT_WATCHDOG
|
||||||
|
bool "Watchdog feeding support"
|
||||||
|
default n
|
||||||
|
depends on WATCHDOG
|
||||||
|
---help---
|
||||||
|
This config must be selected in case the Watchdog is enabled while
|
||||||
|
performing a swap upgrade and the time it takes for a swapping is long
|
||||||
|
enough to cause an unwanted reset.
|
||||||
|
|
||||||
|
config MCUBOOT_WATCHDOG_DEVPATH
|
||||||
|
string "Watchdog device path"
|
||||||
|
default "/dev/watchdog0"
|
||||||
|
depends on MCUBOOT_WATCHDOG
|
||||||
|
---help---
|
||||||
|
The path to the watchdog device.
|
||||||
|
Default: /dev/watchdog0
|
||||||
|
|
||||||
|
config MCUBOOT_PRIMARY_SLOT_PATH
|
||||||
|
string "Application firmware image primary slot path"
|
||||||
|
default "/dev/ota0"
|
||||||
|
---help---
|
||||||
|
The path to the application firmware image primary slot character
|
||||||
|
device driver.
|
||||||
|
Default: /dev/ota0
|
||||||
|
|
||||||
|
config MCUBOOT_SECONDARY_SLOT_PATH
|
||||||
|
string "Application firmware image secondary slot path"
|
||||||
|
default "/dev/ota1"
|
||||||
|
---help---
|
||||||
|
The path to the application firmware image secondary slot character
|
||||||
|
device driver.
|
||||||
|
Default: /dev/ota1
|
||||||
|
|
||||||
|
config MCUBOOT_SCRATCH_PATH
|
||||||
|
string "Scratch partition path"
|
||||||
|
default "/dev/otascratch"
|
||||||
|
---help---
|
||||||
|
The path to the scratch partition character device driver.
|
||||||
|
Default: /dev/otascratch
|
||||||
|
|
||||||
|
config MCUBOOT_DEFAULT_FLASH_ERASE_STATE
|
||||||
|
hex "Default flash erase state"
|
||||||
|
default 0xff
|
||||||
|
---help---
|
||||||
|
MCUboot will attempt to retrieve this value from the underlying MTD
|
||||||
|
driver.
|
||||||
|
In case of failure, the value from this config will be used as a
|
||||||
|
fallback.
|
||||||
|
|
||||||
|
endif # BOOT_MCUBOOT
|
34
boot/mcuboot/Make.defs
Normal file
34
boot/mcuboot/Make.defs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
############################################################################
|
||||||
|
# apps/boot/mcuboot/Make.defs
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
############################################################################
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_BOOT_MCUBOOT),y)
|
||||||
|
CONFIGURED_APPS += $(APPDIR)/boot/mcuboot
|
||||||
|
|
||||||
|
# It allows import of NuttX implementation headers for MCUboot interfaces.
|
||||||
|
|
||||||
|
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(APPDIR)/boot/mcuboot/mcuboot/boot/nuttx/include}
|
||||||
|
CXXFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(APPDIR)/boot/mcuboot/mcuboot/boot/nuttx/include}
|
||||||
|
|
||||||
|
# It allows import of MCUboot's bootutil library headers.
|
||||||
|
|
||||||
|
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(APPDIR)/boot/mcuboot/mcuboot/boot/bootutil/include}
|
||||||
|
CXXFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(APPDIR)/boot/mcuboot/mcuboot/boot/bootutil/include}
|
||||||
|
|
||||||
|
endif
|
92
boot/mcuboot/Makefile
Normal file
92
boot/mcuboot/Makefile
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
############################################################################
|
||||||
|
# apps/boot/mcuboot/Makefile
|
||||||
|
#
|
||||||
|
# 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 $(APPDIR)/Make.defs
|
||||||
|
|
||||||
|
MCUBOOT_VERSION := $(patsubst "%",%,$(CONFIG_MCUBOOT_VERSION))
|
||||||
|
MCUBOOT_TARBALL = $(MCUBOOT_VERSION).tar.gz
|
||||||
|
MCUBOOT_UNPACK = mcuboot
|
||||||
|
MCUBOOT_SRCDIR = $(MCUBOOT_UNPACK)$(DELIM)boot$(DELIM)bootutil$(DELIM)src
|
||||||
|
|
||||||
|
DEPPATH += --dep-path $(MCUBOOT_UNPACK)$(DELIM)src
|
||||||
|
DEPPATH += --dep-path $(MCUBOOT_SRCDIR)
|
||||||
|
VPATH += :$(MCUBOOT_UNPACK)$(DELIM)src
|
||||||
|
VPATH += :$(MCUBOOT_SRCDIR)
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE),)
|
||||||
|
MAINSRC = mcuboot_agent_main.c
|
||||||
|
|
||||||
|
PROGNAME = mcuboot_agent
|
||||||
|
PRIORITY = SCHED_PRIORITY_DEFAULT
|
||||||
|
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
|
||||||
|
else ifneq ($(CONFIG_MCUBOOT_SLOT_CONFIRM_EXAMPLE),)
|
||||||
|
MAINSRC = mcuboot_confirm_main.c
|
||||||
|
|
||||||
|
PROGNAME = mcuboot_confirm
|
||||||
|
PRIORITY = SCHED_PRIORITY_DEFAULT
|
||||||
|
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
|
||||||
|
else ifneq ($(CONFIG_MCUBOOT_BOOTLOADER),)
|
||||||
|
MAINSRC = mcuboot/boot/nuttx/main.c
|
||||||
|
|
||||||
|
PROGNAME = mcuboot_loader
|
||||||
|
PRIORITY = SCHED_PRIORITY_DEFAULT
|
||||||
|
STACKSIZE = $(CONFIG_DEFAULT_TASK_STACKSIZE)
|
||||||
|
endif
|
||||||
|
|
||||||
|
CSRCS := mcuboot/boot/bootutil/src/boot_record.c \
|
||||||
|
mcuboot/boot/bootutil/src/bootutil_misc.c \
|
||||||
|
mcuboot/boot/bootutil/src/bootutil_public.c \
|
||||||
|
mcuboot/boot/bootutil/src/caps.c \
|
||||||
|
mcuboot/boot/bootutil/src/encrypted.c \
|
||||||
|
mcuboot/boot/bootutil/src/fault_injection_hardening.c \
|
||||||
|
mcuboot/boot/bootutil/src/fault_injection_hardening_delay_rng_mbedtls.c \
|
||||||
|
mcuboot/boot/bootutil/src/image_ec.c \
|
||||||
|
mcuboot/boot/bootutil/src/image_ec256.c \
|
||||||
|
mcuboot/boot/bootutil/src/image_ed25519.c \
|
||||||
|
mcuboot/boot/bootutil/src/image_rsa.c \
|
||||||
|
mcuboot/boot/bootutil/src/image_validate.c \
|
||||||
|
mcuboot/boot/bootutil/src/loader.c \
|
||||||
|
mcuboot/boot/bootutil/src/swap_misc.c \
|
||||||
|
mcuboot/boot/bootutil/src/swap_move.c \
|
||||||
|
mcuboot/boot/bootutil/src/swap_scratch.c \
|
||||||
|
mcuboot/boot/bootutil/src/tlv.c \
|
||||||
|
mcuboot/boot/nuttx/src/flash_map_backend/flash_map_backend.c
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_MCUBOOT_WATCHDOG),)
|
||||||
|
CSRCS += mcuboot/boot/nuttx/src/watchdog/watchdog.c
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(MCUBOOT_TARBALL):
|
||||||
|
$(Q) echo "Downloading MCUboot-$(MCUBOOT_VERSION)"
|
||||||
|
$(Q) curl -O -L https://github.com/mcu-tools/mcuboot/archive/$(MCUBOOT_TARBALL)
|
||||||
|
|
||||||
|
$(MCUBOOT_UNPACK): $(MCUBOOT_TARBALL)
|
||||||
|
$(Q) echo "Unpacking: $(MCUBOOT_TARBALL) -> $(MCUBOOT_UNPACK)"
|
||||||
|
$(Q) tar zxf $(MCUBOOT_TARBALL)
|
||||||
|
$(Q) mv mcuboot-$(MCUBOOT_VERSION) $(MCUBOOT_UNPACK)
|
||||||
|
$(Q) touch $(MCUBOOT_UNPACK)
|
||||||
|
|
||||||
|
context:: $(MCUBOOT_UNPACK)
|
||||||
|
|
||||||
|
distclean::
|
||||||
|
$(call DELFILE, $(MCUBOOT_TARBALL))
|
||||||
|
$(call DELDIR, $(MCUBOOT_UNPACK))
|
||||||
|
|
||||||
|
include $(APPDIR)/Application.mk
|
52
boot/mcuboot/README.md
Normal file
52
boot/mcuboot/README.md
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Boot / `mcuboot` MCUboot
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
The NuttX port of MCUboot secure boot library expects that the platform provides a Flash storage with the following partitions:
|
||||||
|
- `CONFIG_MCUBOOT_PRIMARY_SLOT_PATH`: MTD partition for the application firmware image PRIMARY slot;
|
||||||
|
- `CONFIG_MCUBOOT_SECONDARY_SLOT_PATH`: MTD partition for the application firmware image SECONDARY slot;
|
||||||
|
- `CONFIG_MCUBOOT_SCRATCH_PATH`: MTD partition for the Scratch area;
|
||||||
|
|
||||||
|
Also, these are optional features that may be enabled:
|
||||||
|
|
||||||
|
- `CONFIG_MCUBOOT_WATCHDOG`: If `CONFIG_WATCHDOG` is enabled, MCUboot shall reset the watchdog timer indicated by `CONFIG_MCUBOOT_WATCHDOG_DEVPATH` to the current timeout value, preventing any imminent watchdog timeouts.
|
||||||
|
|
||||||
|
The porting layer of MCUboot library consists of the following interfaces:
|
||||||
|
- `<flash_map_backend/flash_map_backend.h>`, for enabling MCUboot to manage the application firmware image slots in the device storage.
|
||||||
|
- `<mcuboot_config/mcuboot_config.h>`, for configuration of MCUboot's features.
|
||||||
|
- `<mcuboot_config/mcuboot_logging.h>`, for providing logging capabilities.
|
||||||
|
- `<os/os_malloc.h>`, for providing MCUboot access to the OS memory management interfaces.
|
||||||
|
- `<sysflash/sysflash.h>`, for configuration of the system's flash area organization.
|
||||||
|
|
||||||
|
The NuttX port of MCUboot is implemented at application-level and requires minimal knowledge about characteristics of the underlying storage device. This is achieved by means of the `BCH` and `FTL` subsystems, which enable MCUboot to manage MTD partitions via character device drivers using standard POSIX filesystem operations (e.g. `open()` / `close()` / `read()` / `write()`).
|
||||||
|
|
||||||
|
## Creating MCUboot-compatible application firmware images
|
||||||
|
|
||||||
|
One common use case for MCUboot is to integrate it to a firmware update agent, which is an important component of a secure firmware update subsystem. Through MCUboot APIs an application is able to install a newly received application firmware image and, once this application firmware image is assured to be valid, the application may confirm it as a stable image. In case that application firmware image is deemed bogus, MCUboot provides an API for invalidating that update, which will induce a rollback procedure to the most recent stable application firmware image.
|
||||||
|
|
||||||
|
The `CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE` example demonstrates this workflow by downloading an application firmware image from a webserver, installing it and triggering the firmware update process for the next boot after a system reset. There is also the `CONFIG_MCUBOOT_SLOT_CONFIRM_EXAMPLE`, which is a fairly simple example that just calls an MCUboot API for confirming the executing application firmware image as stable.
|
||||||
|
|
||||||
|
## Using MCUboot on NuttX as a secure boot solution
|
||||||
|
|
||||||
|
NuttX port for MCUboot also enables the creation of a secure bootloader application requiring minimal platform-specific implementation. The logical implementation for the secure boot is performed at application-level by the MCUboot library. Once MCUboot validates the application firmware image, it delegates the loading and execution of the application firmware image to a platform-specific routine, which is accessed via `boardctl(BOARDIOC_BOOT_IMAGE)` call. Each platform must then provide an implementation for the `board_boot_image()` for executing the required actions in order to boot a new application firmware image (e.g. deinitialize peripherals, load the Program Counter register with the application firmware image entry point address).
|
||||||
|
|
||||||
|
The MCUboot bootloader application may be enabled by selecting the `CONFIG_MCUBOOT_BOOTLOADER` option.
|
||||||
|
|
||||||
|
## Assumptions
|
||||||
|
|
||||||
|
### IOCTL MTD commands
|
||||||
|
|
||||||
|
The implementation of `<flash_map_backend/flash_map_backend.h>` expects that the MTD driver for a given image partition handles the following `ioctl` commands:
|
||||||
|
- `MTDIOC_GEOMETRY`, for retrieving information about the geometry of the MTD, required for the configuration of the size of each flash area.
|
||||||
|
- `MTDIOC_ERASESTATE`, for retrieving the byte value of an erased cell of the MTD, required for the implementation of `flash_area_erased_val()` interface.
|
||||||
|
|
||||||
|
### Write access alignment
|
||||||
|
|
||||||
|
Through `flash_area_align()` interface MCUboot expects that the implementation provides the shortest data length that may be written via `flash_area_write()` interface. The NuttX implementation passes through the `BCH` and `FTL` layers, which appropriately handle the write alignment restrictions of the underlying MTD. So The NuttX implementation of `flash_area_align()` is able to return a fixed value of 1 byte, even if the MTD does not support byte operations.
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
### `<flash_map_backend/flash_map_backend.h>` functions are not multitasking-safe
|
||||||
|
|
||||||
|
MCUboot's documentation imposes no restrictions regarding the usage of its public interfaces, which doesn't mean they are thread-safe.
|
||||||
|
But, regarding NuttX implementation of the `<flash_map_backend/flash_map_backend.h>`, it is safe to state that they are **not** multitasking-safe. NuttX implementation manages the MTD partitions via character device drivers. As file-descriptors cannot be shared between different tasks, if one task calls `flash_area_open` and another task calls `flash_area_<read/write/close>` passing the same `struct flash_area` instance, it will result in failure.
|
291
boot/mcuboot/mcuboot_agent_main.c
Normal file
291
boot/mcuboot/mcuboot_agent_main.c
Normal file
@ -0,0 +1,291 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* apps/boot/mcuboot/mcuboot_agent_main.c
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/boardctl.h>
|
||||||
|
|
||||||
|
#include <bootutil/bootutil_public.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
#include "netutils/md5.h"
|
||||||
|
#endif
|
||||||
|
#include "netutils/netlib.h"
|
||||||
|
#include "netutils/webclient.h"
|
||||||
|
|
||||||
|
#include "flash_map_backend/flash_map_backend.h"
|
||||||
|
#include "sysflash/sysflash.h"
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Preprocessor Definitions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#define DL_BUFFER_SIZE CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_BUFFER_SIZE
|
||||||
|
|
||||||
|
#define DL_UPDATE_URL CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_UPDATE_URL
|
||||||
|
|
||||||
|
#ifdef CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
# define MD5_HASH_LENGTH 32
|
||||||
|
# define MD5_DIGEST_LENGTH 16
|
||||||
|
# define MD5_EXPECTED_HASH CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_MD5_HASH
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Types
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
struct download_context_s
|
||||||
|
{
|
||||||
|
FAR const struct flash_area *fa;
|
||||||
|
uint32_t fa_offset;
|
||||||
|
ssize_t image_size;
|
||||||
|
#ifdef CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
MD5_CTX md5_ctx;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Data
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static char g_iobuffer[DL_BUFFER_SIZE];
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Private Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: header_callback
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int header_callback(FAR const char *line, bool truncated,
|
||||||
|
FAR void *arg)
|
||||||
|
{
|
||||||
|
FAR struct download_context_s *ctx = (FAR struct download_context_s *)arg;
|
||||||
|
|
||||||
|
if (ctx->image_size == -1)
|
||||||
|
{
|
||||||
|
char *pos = strstr(line, "Content-Length:");
|
||||||
|
if (pos != NULL)
|
||||||
|
{
|
||||||
|
long i;
|
||||||
|
int errcode;
|
||||||
|
|
||||||
|
i = strtol(pos + sizeof("Content-Length:"), NULL, 10);
|
||||||
|
errcode = errno;
|
||||||
|
if (errcode == ERANGE)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Error reading \"Content-Length\": %s\n",
|
||||||
|
strerror(errcode));
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Firmware Update size: %ld bytes\n", i);
|
||||||
|
|
||||||
|
ctx->image_size = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: sink_callback
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int sink_callback(FAR char **buffer, int offset, int datend,
|
||||||
|
FAR int *buflen, FAR void *arg)
|
||||||
|
{
|
||||||
|
FAR struct download_context_s *ctx = (FAR struct download_context_s *)arg;
|
||||||
|
uint32_t length = datend - offset;
|
||||||
|
|
||||||
|
if (length > 0)
|
||||||
|
{
|
||||||
|
uint32_t progress;
|
||||||
|
|
||||||
|
flash_area_write(ctx->fa, ctx->fa_offset, &((*buffer)[offset]),
|
||||||
|
length);
|
||||||
|
|
||||||
|
ctx->fa_offset += length;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
md5_update(&ctx->md5_ctx,
|
||||||
|
(FAR const unsigned char *)&((*buffer)[offset]),
|
||||||
|
length);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
progress = (ctx->fa_offset * 100) / ctx->image_size;
|
||||||
|
|
||||||
|
printf("Received: %-8" PRIu32 " of %zd bytes [%" PRIu32 "%%]\n",
|
||||||
|
ctx->fa_offset, ctx->image_size, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: download_firmware_image
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int download_firmware_image(FAR const char *url)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct webclient_context client_ctx;
|
||||||
|
struct download_context_s dl_ctx;
|
||||||
|
#ifdef CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
uint8_t digest[MD5_DIGEST_LENGTH];
|
||||||
|
char hash[MD5_HASH_LENGTH + 1];
|
||||||
|
int i;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dl_ctx.fa = NULL;
|
||||||
|
dl_ctx.fa_offset = 0;
|
||||||
|
dl_ctx.image_size = -1;
|
||||||
|
|
||||||
|
#ifdef CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
md5_init(&dl_ctx.md5_ctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
webclient_set_defaults(&client_ctx);
|
||||||
|
client_ctx.method = "GET";
|
||||||
|
client_ctx.buffer = g_iobuffer;
|
||||||
|
client_ctx.buflen = sizeof(g_iobuffer);
|
||||||
|
client_ctx.header_callback = header_callback;
|
||||||
|
client_ctx.header_callback_arg = &dl_ctx;
|
||||||
|
client_ctx.sink_callback = sink_callback;
|
||||||
|
client_ctx.sink_callback_arg = &dl_ctx;
|
||||||
|
client_ctx.url = url;
|
||||||
|
|
||||||
|
ret = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &dl_ctx.fa);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to open flash area\n");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = webclient_perform(&client_ctx);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "webclient_perform failed with %d\n", ret);
|
||||||
|
|
||||||
|
goto exit_close;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_MCUBOOT_UPDATE_AGENT_EXAMPLE_DL_VERIFY_MD5
|
||||||
|
md5_final(digest, &dl_ctx.md5_ctx);
|
||||||
|
|
||||||
|
for (i = 0; i < MD5_DIGEST_LENGTH; i++)
|
||||||
|
{
|
||||||
|
sprintf(&hash[i * 2], "%02x", digest[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
hash[MD5_HASH_LENGTH] = '\0';
|
||||||
|
|
||||||
|
if (strncmp(hash, MD5_EXPECTED_HASH, sizeof(hash)) != 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Download checksum verification failure:\n");
|
||||||
|
fprintf(stderr, "%s Expected\n", MD5_EXPECTED_HASH);
|
||||||
|
fprintf(stderr, "%s Got\n", hash);
|
||||||
|
|
||||||
|
ret = ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Download checksum verification successful!\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
exit_close:
|
||||||
|
flash_area_close(dl_ctx.fa);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* mcuboot_agent_main
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int main(int argc, FAR char *argv[])
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
FAR const char *url;
|
||||||
|
|
||||||
|
printf("MCUboot Update Agent example\n");
|
||||||
|
|
||||||
|
if (argc > 1)
|
||||||
|
{
|
||||||
|
url = argv[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
url = DL_UPDATE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url[0] == '\0')
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: mcuboot_agent <URL>\n");
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Downloading from %s\n", url);
|
||||||
|
|
||||||
|
ret = download_firmware_image(url);
|
||||||
|
if (ret != OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Application Image download failure.\n");
|
||||||
|
fprintf(stderr, "Update aborted.\n");
|
||||||
|
|
||||||
|
return ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Application Image successfully downloaded!\n");
|
||||||
|
|
||||||
|
boot_set_pending_multi(0, 0);
|
||||||
|
|
||||||
|
printf("Requested update for next boot. Restarting...\n");
|
||||||
|
|
||||||
|
fflush(stdout);
|
||||||
|
fflush(stderr);
|
||||||
|
|
||||||
|
usleep(1000);
|
||||||
|
|
||||||
|
boardctl(BOARDIOC_RESET, EXIT_SUCCESS);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
46
boot/mcuboot/mcuboot_confirm_main.c
Normal file
46
boot/mcuboot/mcuboot_confirm_main.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
* apps/boot/mcuboot/mcuboot_confirm_main.c
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Included Files
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <nuttx/config.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <bootutil/bootutil_public.h>
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Public Functions
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* mcuboot_confirm_main
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
int main(int argc, FAR char *argv[])
|
||||||
|
{
|
||||||
|
boot_set_confirmed_multi(0);
|
||||||
|
|
||||||
|
printf("Application Image successfully confirmed!\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user