blob: 28e9cdf15279646e6b406a0229f555a92361fa86 [file] [log] [blame]
Dominik Ermel8101c0c2020-05-19 13:01:16 +00001/*
2 * SPDX-License-Identifier: Apache-2.0
3 *
4 * Copyright (c) 2020 Nordic Semiconductor ASA
Tamas Banee6615d2020-09-30 07:58:48 +01005 * Copyright (c) 2020 Arm Limited
Dominik Ermel8101c0c2020-05-19 13:01:16 +00006 */
7
8#include <assert.h>
9#include "bootutil/image.h"
10#include "bootutil_priv.h"
Dane Wagnerf2a61462024-12-04 10:46:40 -060011#include "bootutil/boot_record.h"
12#include "bootutil/bootutil.h"
Dominik Ermel8101c0c2020-05-19 13:01:16 +000013#include "bootutil/bootutil_log.h"
Jamie McCraec9fa6082023-07-21 10:23:17 +010014#include "bootutil/bootutil_public.h"
Tamas Banee6615d2020-09-30 07:58:48 +010015#include "bootutil/fault_injection_hardening.h"
Dominik Ermel8101c0c2020-05-19 13:01:16 +000016
17#include "mcuboot_config/mcuboot_config.h"
18
Carlos Falgueras GarcĂ­aa4b4b0f2021-06-22 10:00:22 +020019BOOT_LOG_MODULE_DECLARE(mcuboot);
Dominik Ermel8101c0c2020-05-19 13:01:16 +000020
21/* Variables passed outside of unit via poiters. */
22static const struct flash_area *_fa_p;
23static struct image_header _hdr = { 0 };
Ederson de Souza98a66812024-12-20 12:34:19 -080024static struct boot_loader_state boot_data;
25
26struct boot_loader_state *boot_get_loader_state(void)
27{
28 return &boot_data;
29}
Dominik Ermel8101c0c2020-05-19 13:01:16 +000030
Wouter Cappelle953a7612021-05-03 16:53:05 +020031#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT) || defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE)
Dominik Ermel8101c0c2020-05-19 13:01:16 +000032/**
33 * Validate hash of a primary boot image.
34 *
35 * @param[in] fa_p flash area pointer
36 * @param[in] hdr boot image header pointer
37 *
Tamas Banee6615d2020-09-30 07:58:48 +010038 * @return FIH_SUCCESS on success, error code otherwise
Dominik Ermel8101c0c2020-05-19 13:01:16 +000039 */
Michael Grand5047f032022-11-24 16:49:56 +010040fih_ret
Dominik Ermel8101c0c2020-05-19 13:01:16 +000041boot_image_validate(const struct flash_area *fa_p,
42 struct image_header *hdr)
43{
44 static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
Michael Grand5047f032022-11-24 16:49:56 +010045 FIH_DECLARE(fih_rc, FIH_FAILURE);
Dominik Ermel8101c0c2020-05-19 13:01:16 +000046
Dominik Ermeld8db0252020-10-07 11:22:45 +000047 /* NOTE: The first argument to boot_image_validate, for enc_state pointer,
48 * is allowed to be NULL only because the single image loader compiles
49 * with BOOT_IMAGE_NUMBER == 1, which excludes the code that uses
50 * the pointer from compilation.
Dominik Ermel8101c0c2020-05-19 13:01:16 +000051 */
52 /* Validate hash */
Wouter Cappelle76792152022-01-19 17:28:55 +010053 if (IS_ENCRYPTED(hdr))
Wouter Cappelle953a7612021-05-03 16:53:05 +020054 {
55 /* Clear the encrypted flag we didn't supply a key
56 * This flag could be set if there was a decryption in place
57 * was performed. We will try to validate the image, and if still
58 * encrypted the validation will fail, and go in panic mode
59 */
Wouter Cappelle76792152022-01-19 17:28:55 +010060 hdr->ih_flags &= ~(ENCRYPTIONFLAGS);
Wouter Cappelle953a7612021-05-03 16:53:05 +020061 }
Jamie McCrae2fe9cd42025-01-14 16:42:00 +000062 FIH_CALL(bootutil_img_validate, fih_rc, NULL, hdr, fa_p, tmpbuf,
Tamas Banee6615d2020-09-30 07:58:48 +010063 BOOT_TMPBUF_SZ, NULL, 0, NULL);
Dominik Ermel8101c0c2020-05-19 13:01:16 +000064
Tamas Banee6615d2020-09-30 07:58:48 +010065 FIH_RET(fih_rc);
Dominik Ermel8101c0c2020-05-19 13:01:16 +000066}
Wouter Cappelle953a7612021-05-03 16:53:05 +020067#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT || MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE*/
Dominik Ermel8101c0c2020-05-19 13:01:16 +000068
Jamie McCrae21299732023-12-07 09:41:55 +000069#if defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE)
Michael Grand5047f032022-11-24 16:49:56 +010070inline static fih_ret
Wouter Cappellebb7a39d2021-05-03 16:44:44 +020071boot_image_validate_once(const struct flash_area *fa_p,
72 struct image_header *hdr)
73{
74 static struct boot_swap_state state;
75 int rc;
Michael Grand5047f032022-11-24 16:49:56 +010076 FIH_DECLARE(fih_rc, FIH_FAILURE);
Wouter Cappellebb7a39d2021-05-03 16:44:44 +020077
78 memset(&state, 0, sizeof(struct boot_swap_state));
79 rc = boot_read_swap_state(fa_p, &state);
80 if (rc != 0)
81 FIH_RET(FIH_FAILURE);
82 if (state.magic != BOOT_MAGIC_GOOD
83 || state.image_ok != BOOT_FLAG_SET) {
84 /* At least validate the image once */
85 FIH_CALL(boot_image_validate, fih_rc, fa_p, hdr);
Michael Grand5047f032022-11-24 16:49:56 +010086 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
Wouter Cappellebb7a39d2021-05-03 16:44:44 +020087 FIH_RET(FIH_FAILURE);
88 }
89 if (state.magic != BOOT_MAGIC_GOOD) {
90 rc = boot_write_magic(fa_p);
91 if (rc != 0)
92 FIH_RET(FIH_FAILURE);
93 }
94 rc = boot_write_image_ok(fa_p);
95 if (rc != 0)
96 FIH_RET(FIH_FAILURE);
97 }
98 FIH_RET(FIH_SUCCESS);
99}
Jamie McCrae21299732023-12-07 09:41:55 +0000100#endif
Wouter Cappellebb7a39d2021-05-03 16:44:44 +0200101
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000102/**
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000103 * Gather information on image and prepare for booting.
104 *
105 * @parami[out] rsp Parameters for booting image, on success
106 *
Tamas Banee6615d2020-09-30 07:58:48 +0100107 * @return FIH_SUCCESS on success; nonzero on failure.
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000108 */
Michael Grand5047f032022-11-24 16:49:56 +0100109fih_ret
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000110boot_go(struct boot_rsp *rsp)
111{
112 int rc = -1;
Michael Grand5047f032022-11-24 16:49:56 +0100113 FIH_DECLARE(fih_rc, FIH_FAILURE);
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000114
115 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &_fa_p);
116 assert(rc == 0);
117
118 rc = boot_image_load_header(_fa_p, &_hdr);
119 if (rc != 0)
120 goto out;
121
Ederson de Souza040fc422024-08-15 16:35:07 -0700122#ifdef MCUBOOT_RAM_LOAD
123 static struct boot_loader_state state;
Ederson de Souza993c2ff2025-03-24 20:36:21 -0700124 BOOT_IMG_AREA(&state, 0) = _fa_p;
Ederson de Souza040fc422024-08-15 16:35:07 -0700125 state.imgs[0][0].hdr = _hdr;
126
127 rc = boot_load_image_to_sram(&state);
128 if (rc != 0)
129 goto out;
130#endif
131
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000132#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
Tamas Banee6615d2020-09-30 07:58:48 +0100133 FIH_CALL(boot_image_validate, fih_rc, _fa_p, &_hdr);
Michael Grand5047f032022-11-24 16:49:56 +0100134 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
Ederson de Souza040fc422024-08-15 16:35:07 -0700135#ifdef MCUBOOT_RAM_LOAD
136 boot_remove_image_from_sram(&state);
137#endif
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000138 goto out;
139 }
Wouter Cappellebb7a39d2021-05-03 16:44:44 +0200140#elif defined(MCUBOOT_VALIDATE_PRIMARY_SLOT_ONCE)
141 FIH_CALL(boot_image_validate_once, fih_rc, _fa_p, &_hdr);
Michael Grand5047f032022-11-24 16:49:56 +0100142 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
Ederson de Souza040fc422024-08-15 16:35:07 -0700143#ifdef MCUBOOT_RAM_LOAD
144 boot_remove_image_from_sram(&state);
145#endif
Wouter Cappellebb7a39d2021-05-03 16:44:44 +0200146 goto out;
147 }
Tamas Banee6615d2020-09-30 07:58:48 +0100148#else
149 fih_rc = FIH_SUCCESS;
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000150#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
151
Dane Wagnerf2a61462024-12-04 10:46:40 -0600152#ifdef MCUBOOT_MEASURED_BOOT
153 rc = boot_save_boot_status(0, &_hdr, _fa_p);
154 if (rc != 0) {
155 BOOT_LOG_ERR("Failed to add image data to shared area");
156 return rc;
157 }
158#endif /* MCUBOOT_MEASURED_BOOT */
159
160#ifdef MCUBOOT_DATA_SHARING
161 rc = boot_save_shared_data(&_hdr, _fa_p, 0, NULL);
162 if (rc != 0) {
163 BOOT_LOG_ERR("Failed to add data to shared memory area.");
164 return rc;
165 }
166#endif /* MCUBOOT_DATA_SHARING */
167
Dominik Ermel036d5212021-07-01 11:07:41 +0000168 rsp->br_flash_dev_id = flash_area_get_device_id(_fa_p);
169 rsp->br_image_off = flash_area_get_off(_fa_p);
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000170 rsp->br_hdr = &_hdr;
171
172out:
173 flash_area_close(_fa_p);
Tamas Banee6615d2020-09-30 07:58:48 +0100174
175 FIH_RET(fih_rc);
Dominik Ermel8101c0c2020-05-19 13:01:16 +0000176}