blob: 28e9cdf15279646e6b406a0229f555a92361fa86 [file] [log] [blame]
/*
* SPDX-License-Identifier: Apache-2.0
*
* Copyright (c) 2020 Nordic Semiconductor ASA
* Copyright (c) 2020 Arm Limited
*/
#include <assert.h>
#include "bootutil/image.h"
#include "bootutil_priv.h"
#include "bootutil/boot_record.h"
#include "bootutil/bootutil.h"
#include "bootutil/bootutil_log.h"
#include "bootutil/bootutil_public.h"
#include "bootutil/fault_injection_hardening.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 };
static struct boot_loader_state boot_data;
struct boot_loader_state *boot_get_loader_state(void)
{
return &boot_data;
}
#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, hdr, fa_p, tmpbuf,
BOOT_TMPBUF_SZ, NULL, 0, NULL);
FIH_RET(fih_rc);
}
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT || MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE*/
#if defined(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);
}
#endif
/**
* Gather information on image and prepare for booting.
*
* @parami[out] rsp Parameters for booting image, on success
*
* @return FIH_SUCCESS on success; nonzero on failure.
*/
fih_ret
boot_go(struct boot_rsp *rsp)
{
int rc = -1;
FIH_DECLARE(fih_rc, FIH_FAILURE);
rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p);
assert(rc == 0);
rc = boot_image_load_header(_fa_p, &_hdr);
if (rc != 0)
goto out;
#ifdef MCUBOOT_RAM_LOAD
static struct boot_loader_state state;
BOOT_IMG_AREA(&state, 0) = _fa_p;
state.imgs[0][0].hdr = _hdr;
rc = boot_load_image_to_sram(&state);
if (rc != 0)
goto out;
#endif
#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr);
if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
#ifdef MCUBOOT_RAM_LOAD
boot_remove_image_from_sram(&state);
#endif
goto out;
}
#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)) {
#ifdef MCUBOOT_RAM_LOAD
boot_remove_image_from_sram(&state);
#endif
goto out;
}
#else
fih_rc = FIH_SUCCESS;
#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
#ifdef MCUBOOT_MEASURED_BOOT
rc = boot_save_boot_status(0, &_hdr, _fa_p);
if (rc != 0) {
BOOT_LOG_ERR("Failed to add image data to shared area");
return rc;
}
#endif /* MCUBOOT_MEASURED_BOOT */
#ifdef MCUBOOT_DATA_SHARING
rc = boot_save_shared_data(&_hdr, _fa_p, 0, NULL);
if (rc != 0) {
BOOT_LOG_ERR("Failed to add data to shared memory area.");
return rc;
}
#endif /* MCUBOOT_DATA_SHARING */
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;
out:
flash_area_close(_fa_p);
FIH_RET(fih_rc);
}