-
Notifications
You must be signed in to change notification settings - Fork 674
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
zephyr: Add firmware loader MCUboot operation style
Adds a new operation style in which the secondary slot has an image which is used to update the primary image only. Signed-off-by: Jamie McCrae <jamie.mccrae@nordicsemi.no>
- Loading branch information
Showing
11 changed files
with
294 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Copyright (c) 2023 Nordic Semiconductor ASA | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
if BOOT_FIRMWARE_LOADER | ||
|
||
menu "Firmware loader entrance methods" | ||
|
||
menuconfig BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO | ||
bool "GPIO" | ||
depends on GPIO | ||
help | ||
Use a GPIO to enter firmware loader mode. | ||
|
||
config BOOT_FIRMWARE_LOADER_DETECT_DELAY | ||
int "Serial detect pin detection delay time [ms]" | ||
default 0 | ||
depends on BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO | ||
help | ||
Used to prevent the bootloader from loading on button press. | ||
Useful for powering on when using the same button as | ||
the one used to place the device in bootloader mode. | ||
|
||
config BOOT_FIRMWARE_LOADER_BOOT_MODE | ||
bool "Check boot mode via retention subsystem" | ||
depends on RETENTION_BOOT_MODE | ||
help | ||
Allows for entering firmware loader mode by using Zephyr's boot mode | ||
retention system (i.e. an application must set the boot mode to stay | ||
in firmware loader mode and reboot the module). | ||
|
||
config BOOT_FIRMWARE_LOADER_NO_APPLICATION | ||
bool "Stay in bootloader if no application" | ||
help | ||
Allows for entering firmware loader mode if there is no bootable | ||
application that the bootloader can jump to. | ||
|
||
config BOOT_FIRMWARE_LOADER_PIN_RESET | ||
bool "Check for device reset by pin" | ||
select HWINFO | ||
help | ||
Checks if the module reset was caused by the reset pin and will | ||
remain in bootloader firmware loader mode if it was. | ||
|
||
endmenu | ||
|
||
endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
/* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* | ||
* Copyright (c) 2020 Arm Limited | ||
* Copyright (c) 2020-2023 Nordic Semiconductor ASA | ||
*/ | ||
|
||
#include <assert.h> | ||
#include <zephyr/kernel.h> | ||
#include <zephyr/devicetree.h> | ||
#include <zephyr/drivers/gpio.h> | ||
#include "bootutil/image.h" | ||
#include "bootutil_priv.h" | ||
#include "bootutil/bootutil_log.h" | ||
#include "bootutil/bootutil_public.h" | ||
#include "bootutil/fault_injection_hardening.h" | ||
|
||
#include "io/io.h" | ||
#include "mcuboot_config/mcuboot_config.h" | ||
|
||
BOOT_LOG_MODULE_DECLARE(mcuboot); | ||
|
||
/* Variables passed outside of unit via poiters. */ | ||
static const struct flash_area *_fa_p; | ||
static struct image_header _hdr = { 0 }; | ||
|
||
#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) || defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) | ||
/** | ||
* Validate hash of a primary boot image. | ||
* | ||
* @param[in] fa_p flash area pointer | ||
* @param[in] hdr boot image header pointer | ||
* | ||
* @return FIH_SUCCESS on success, error code otherwise | ||
*/ | ||
fih_ret | ||
boot_image_validate(const struct flash_area *fa_p, | ||
struct image_header *hdr) | ||
{ | ||
static uint8_t tmpbuf[BOOT_TMPBUF_SZ]; | ||
FIH_DECLARE(fih_rc, FIH_FAILURE); | ||
|
||
/* NOTE: The first argument to boot_image_validate, for enc_state pointer, | ||
* is allowed to be NULL only because the single image loader compiles | ||
* with BOOT_IMAGE_NUMBER == 1, which excludes the code that uses | ||
* the pointer from compilation. | ||
*/ | ||
/* Validate hash */ | ||
if (IS_ENCRYPTED(hdr)) | ||
{ | ||
/* Clear the encrypted flag we didn't supply a key | ||
* This flag could be set if there was a decryption in place | ||
* was performed. We will try to validate the image, and if still | ||
* encrypted the validation will fail, and go in panic mode | ||
*/ | ||
hdr->ih_flags &= ~(ENCRYPTIONFLAGS); | ||
} | ||
FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, hdr, fa_p, tmpbuf, | ||
BOOT_TMPBUF_SZ, NULL, 0, NULL); | ||
|
||
FIH_RET(fih_rc); | ||
} | ||
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT || MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE*/ | ||
|
||
inline static fih_ret | ||
boot_image_validate_once(const struct flash_area *fa_p, | ||
struct image_header *hdr) | ||
{ | ||
static struct boot_swap_state state; | ||
int rc; | ||
FIH_DECLARE(fih_rc, FIH_FAILURE); | ||
|
||
memset(&state, 0, sizeof(struct boot_swap_state)); | ||
rc = boot_read_swap_state(fa_p, &state); | ||
if (rc != 0) | ||
FIH_RET(FIH_FAILURE); | ||
if (state.magic != BOOT_MAGIC_GOOD | ||
|| state.image_ok != BOOT_FLAG_SET) { | ||
/* At least validate the image once */ | ||
FIH_CALL(boot_image_validate, fih_rc, fa_p, hdr); | ||
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { | ||
FIH_RET(FIH_FAILURE); | ||
} | ||
if (state.magic != BOOT_MAGIC_GOOD) { | ||
rc = boot_write_magic(fa_p); | ||
if (rc != 0) | ||
FIH_RET(FIH_FAILURE); | ||
} | ||
rc = boot_write_image_ok(fa_p); | ||
if (rc != 0) | ||
FIH_RET(FIH_FAILURE); | ||
} | ||
FIH_RET(FIH_SUCCESS); | ||
} | ||
|
||
/** | ||
* Validates that an image in a slot is OK to boot. | ||
* | ||
* @param[in] slot Slot number to check | ||
* @param[out] rsp Parameters for booting image, on success | ||
* | ||
* @return FIH_SUCCESS on success; non-zero on failure. | ||
*/ | ||
static fih_ret validate_image_slot(int slot, struct boot_rsp *rsp) | ||
{ | ||
int rc = -1; | ||
FIH_DECLARE(fih_rc, FIH_FAILURE); | ||
|
||
rc = flash_area_open(slot, &_fa_p); | ||
assert(rc == 0); | ||
|
||
rc = boot_image_load_header(_fa_p, &_hdr); | ||
if (rc != 0) { | ||
goto other; | ||
} | ||
|
||
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT | ||
FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr); | ||
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { | ||
goto other; | ||
} | ||
#elif defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE) | ||
FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr); | ||
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { | ||
goto other; | ||
} | ||
#else | ||
fih_rc = FIH_SUCCESS; | ||
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */ | ||
|
||
rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p); | ||
rsp->br_image_off = flash_area_get_off(_fa_p); | ||
rsp->br_hdr = &_hdr; | ||
|
||
other: | ||
flash_area_close(_fa_p); | ||
|
||
FIH_RET(fih_rc); | ||
} | ||
|
||
/** | ||
* Gather information on image and prepare for booting. Will boot from main | ||
* image if none of the enabled entrance modes for the firmware loader are set, | ||
* otherwise will boot the firmware loader. Note: firmware loader must be a | ||
* valid signed image with the same signing key as the application image. | ||
* | ||
* @param[out] rsp Parameters for booting image, on success | ||
* | ||
* @return FIH_SUCCESS on success; non-zero on failure. | ||
*/ | ||
fih_ret | ||
boot_go(struct boot_rsp *rsp) | ||
{ | ||
bool boot_firmware_loader = false; | ||
FIH_DECLARE(fih_rc, FIH_FAILURE); | ||
|
||
#ifdef CONFIG_BOOT_FIRMWARE_LOADER_ENTRANCE_GPIO | ||
if (io_detect_pin() && | ||
!io_boot_skip_serial_recovery()) { | ||
boot_firmware_loader = true; | ||
} | ||
#endif | ||
|
||
#ifdef CONFIG_BOOT_FIRMWARE_LOADER_PIN_RESET | ||
if (io_detect_pin_reset()) { | ||
boot_firmware_loader = true; | ||
} | ||
#endif | ||
|
||
#ifdef CONFIG_BOOT_FIRMWARE_LOADER_BOOT_MODE | ||
if (io_detect_boot_mode()) { | ||
boot_firmware_loader = true; | ||
} | ||
#endif | ||
|
||
/* Check if firmware loader button is pressed. TODO: check all entrance methods */ | ||
if (boot_firmware_loader == true) { | ||
FIH_CALL(validate_image_slot, fih_rc, FLASH_AREA_IMAGE_SECONDARY(0), rsp); | ||
|
||
if (FIH_EQ(fih_rc, FIH_SUCCESS)) { | ||
FIH_RET(fih_rc); | ||
} | ||
} | ||
|
||
FIH_CALL(validate_image_slot, fih_rc, FLASH_AREA_IMAGE_PRIMARY(0), rsp); | ||
|
||
#ifdef CONFIG_BOOT_FIRMWARE_LOADER_NO_APPLICATION | ||
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) { | ||
FIH_CALL(validate_image_slot, fih_rc, FLASH_AREA_IMAGE_SECONDARY(0), rsp); | ||
} | ||
#endif | ||
|
||
FIH_RET(fih_rc); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.