blob: ba5350ef60710073e203530df271e7521fe40e71 [file] [log] [blame]
Christopher Collins92ea77f2016-12-12 15:59:26 -08001/*
David Brownaac71112020-02-03 16:13:42 -07002 * SPDX-License-Identifier: Apache-2.0
3 *
4 * Copyright (c) 2016-2020 Linaro LTD
5 * Copyright (c) 2016-2019 JUUL Labs
Roman Okhrimenko977b3752022-03-31 14:40:48 +03006 * Copyright (c) 2019-2021 Arm Limited
David Brownaac71112020-02-03 16:13:42 -07007 *
8 * Original license:
9 *
Christopher Collins92ea77f2016-12-12 15:59:26 -080010 * Licensed to the Apache Software Foundation (ASF) under one
11 * or more contributor license agreements. See the NOTICE file
12 * distributed with this work for additional information
13 * regarding copyright ownership. The ASF licenses this file
14 * to you under the Apache License, Version 2.0 (the
15 * "License"); you may not use this file except in compliance
16 * with the License. You may obtain a copy of the License at
17 *
18 * http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing,
21 * software distributed under the License is distributed on an
22 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
23 * KIND, either express or implied. See the License for the
24 * specific language governing permissions and limitations
25 * under the License.
26 */
27
28/**
29 * This file provides an interface to the boot loader. Functions defined in
30 * this file should only be called while the boot loader is running.
31 */
32
Christopher Collins92ea77f2016-12-12 15:59:26 -080033#include <stddef.h>
David Brown52eee562017-07-05 11:25:09 -060034#include <stdbool.h>
Christopher Collins92ea77f2016-12-12 15:59:26 -080035#include <inttypes.h>
36#include <stdlib.h>
37#include <string.h>
Christopher Collins92ea77f2016-12-12 15:59:26 -080038#include "bootutil/bootutil.h"
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030039#include "bootutil/bootutil_public.h"
Christopher Collins92ea77f2016-12-12 15:59:26 -080040#include "bootutil/image.h"
41#include "bootutil_priv.h"
Fabio Utzig12d59162019-11-28 10:01:59 -030042#include "swap_priv.h"
Marti Bolivarfd20c762017-02-07 16:52:50 -050043#include "bootutil/bootutil_log.h"
David Vinczec3084132020-02-18 14:50:47 +010044#include "bootutil/security_cnt.h"
David Vincze1cf11b52020-03-24 07:51:09 +010045#include "bootutil/boot_record.h"
Raef Colese8fe6cf2020-05-26 13:07:40 +010046#include "bootutil/fault_injection_hardening.h"
Roman Okhrimenko977b3752022-03-31 14:40:48 +030047#include "bootutil/ramload.h"
48#include "bootutil/boot_hooks.h"
Marti Bolivarfd20c762017-02-07 16:52:50 -050049
Fabio Utzigba829042018-09-18 08:29:34 -030050#ifdef MCUBOOT_ENC_IMAGES
51#include "bootutil/enc_key.h"
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +020052#ifdef MCUBOOT_ENC_IMAGES_XIP_MULTI
53#include "xip_encryption.h"
54#endif /* MCUBOOT_ENC_IMAGES_XIP_MULTI */
55#endif /* MCUBOOT_ENC_IMAGES */
Fabio Utzigba829042018-09-18 08:29:34 -030056
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030057#if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || defined(MCUBOOT_MULTI_MEMORY_LOAD)
Roman Okhrimenko977b3752022-03-31 14:40:48 +030058#include <os/os_malloc.h>
59#endif
60
Fabio Utzigba1fbe62017-07-21 14:01:20 -030061#include "mcuboot_config/mcuboot_config.h"
Fabio Utzigeed80b62017-06-10 08:03:05 -030062
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +020063#ifdef USE_IFX_SE_CRYPTO
64#include "ifx_se_utils.h"
65#endif /* USE_IFX_SE_CRYPTO */
66
Roman Okhrimenko977b3752022-03-31 14:40:48 +030067BOOT_LOG_MODULE_DECLARE(mcuboot);
Emanuele Di Santo9f1933d2018-11-20 10:59:59 +010068
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +020069bool boot_ram = false;
Marti Bolivar9b1f8bb2017-06-12 15:24:13 -040070static struct boot_loader_state boot_data;
Christopher Collins92ea77f2016-12-12 15:59:26 -080071
Fabio Utzigabec0732019-07-31 08:40:22 -030072#if (BOOT_IMAGE_NUMBER > 1)
73#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x))
74#else
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030075#define IMAGES_ITER(x) for (int iter = 0; iter < 1; ++iter)
Fabio Utzigabec0732019-07-31 08:40:22 -030076#endif
77
Fabio Utzig10ee6482019-08-01 12:04:52 -030078/*
79 * This macro allows some control on the allocation of local variables.
80 * When running natively on a target, we don't want to allocated huge
81 * variables on the stack, so make them global instead. For the simulator
82 * we want to run as many threads as there are tests, and it's safer
83 * to just make those variables stack allocated.
84 */
85#if !defined(__BOOTSIM__)
86#define TARGET_STATIC static
87#else
88#define TARGET_STATIC
89#endif
90
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030091#if BOOT_MAX_ALIGN > 1024
92#define BUF_SZ BOOT_MAX_ALIGN
93#else
94#define BUF_SZ 1024U
95#endif
96
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +020097static fih_int FIH_SWAP_TYPE_NONE = FIH_INT_INIT_GLOBAL(0x3A5C742E);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +030098
David Vinczee574f2d2020-07-10 11:42:03 +020099static int
100boot_read_image_headers(struct boot_loader_state *state, bool require_all,
101 struct boot_status *bs)
102{
103 int rc;
104 int i;
105
106 for (i = 0; i < BOOT_NUM_SLOTS; i++) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300107 rc = BOOT_HOOK_CALL(boot_read_image_header_hook, BOOT_HOOK_REGULAR,
108 BOOT_CURR_IMG(state), i, boot_img_hdr(state, i));
109 if (rc == BOOT_HOOK_REGULAR)
110 {
111 rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs);
112 }
David Vinczee574f2d2020-07-10 11:42:03 +0200113 if (rc != 0) {
114 /* If `require_all` is set, fail on any single fail, otherwise
115 * if at least the first slot's header was read successfully,
116 * then the boot loader can attempt a boot.
117 *
118 * Failure to read any headers is a fatal error.
119 */
120 if (i > 0 && !require_all) {
121 return 0;
122 } else {
123 return rc;
124 }
125 }
126 }
127
128 return 0;
129}
130
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300131/**
132 * Saves boot status and shared data for current image.
133 *
134 * @param state Boot loader status information.
135 * @param active_slot Index of the slot will be loaded for current image.
136 *
137 * @return 0 on success; nonzero on failure.
138 */
139static int
140boot_add_shared_data(struct boot_loader_state *state,
141 uint32_t active_slot)
142{
143#if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING)
144 int rc;
145
146#ifdef MCUBOOT_MEASURED_BOOT
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200147 rc = boot_save_boot_status(GET_SW_MODULE_ID(BOOT_CURR_IMG(state)),
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300148 boot_img_hdr(state, active_slot),
149 BOOT_IMG_AREA(state, active_slot));
150 if (rc != 0) {
151 BOOT_LOG_ERR("Failed to add image data to shared area");
152 return rc;
153 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200154 else {
155 BOOT_LOG_INF("Successfully added image data to shared area");
156 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300157#endif /* MCUBOOT_MEASURED_BOOT */
158
159#ifdef MCUBOOT_DATA_SHARING
160 rc = boot_save_shared_data(boot_img_hdr(state, active_slot),
161 BOOT_IMG_AREA(state, active_slot));
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
168 return 0;
169
170#else /* MCUBOOT_MEASURED_BOOT || MCUBOOT_DATA_SHARING */
171 (void) (state);
172 (void) (active_slot);
173
174 return 0;
175#endif
176}
177
178/**
179 * Fills rsp to indicate how booting should occur.
180 *
181 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300182 * @param rsp boot_rsp struct to fill.
183 */
184static void
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300185fill_rsp(struct boot_loader_state *state, struct boot_rsp *rsp)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300186{
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300187 uint32_t active_slot = BOOT_PRIMARY_SLOT;
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300188
189#if (BOOT_IMAGE_NUMBER > 1)
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300190 /* Always boot from the first enabled image. */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300191 BOOT_CURR_IMG(state) = 0;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300192 IMAGES_ITER(BOOT_CURR_IMG(state)) {
193 if (!state->img_mask[BOOT_CURR_IMG(state)]) {
194 break;
195 }
196 }
197 /* At least one image must be active, otherwise skip the execution */
198 if(BOOT_CURR_IMG(state) >= BOOT_IMAGE_NUMBER)
199 {
200 return;
201 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300202#endif
203
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300204#if defined(MCUBOOT_MULTI_MEMORY_LOAD)
205 if ((state->slot_usage[BOOT_CURR_IMG(state)].active_slot != BOOT_PRIMARY_SLOT) &&
206 (state->slot_usage[BOOT_CURR_IMG(state)].active_slot != NO_ACTIVE_SLOT))
207#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300208#if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300209 {
210 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
211 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300212#endif
213
214 rsp->br_flash_dev_id = flash_area_get_device_id(BOOT_IMG_AREA(state, active_slot));
215 rsp->br_image_off = boot_img_slot_off(state, active_slot);
216 rsp->br_hdr = boot_img_hdr(state, active_slot);
217}
218
219/**
220 * Closes all flash areas.
221 *
222 * @param state Boot loader status information.
223 */
224static void
225close_all_flash_areas(struct boot_loader_state *state)
226{
227 uint32_t slot;
228
229 IMAGES_ITER(BOOT_CURR_IMG(state)) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300230#if BOOT_IMAGE_NUMBER > 1
231 if (state->img_mask[BOOT_CURR_IMG(state)]) {
232 continue;
233 }
234#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300235#if MCUBOOT_SWAP_USING_SCRATCH
236 flash_area_close(BOOT_SCRATCH_AREA(state));
237#endif
238 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
239 flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot));
240 }
241 }
242}
243
Tamas Banfe031092020-09-10 17:32:39 +0200244#if !defined(MCUBOOT_DIRECT_XIP)
David Brownf5b33d82017-09-01 10:58:27 -0600245/*
246 * Compute the total size of the given image. Includes the size of
247 * the TLVs.
248 */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300249#if !defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_OVERWRITE_ONLY_FAST) || defined(MCUBOOT_RAM_LOAD)
David Brownf5b33d82017-09-01 10:58:27 -0600250static int
Fabio Utzigd638b172019-08-09 10:38:05 -0300251boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
David Brownf5b33d82017-09-01 10:58:27 -0600252{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300253 const struct flash_area *fap = NULL;
Fabio Utzig61fd8882019-09-14 20:00:20 -0300254 struct image_tlv_info info;
Fabio Utzig233af7d2019-08-26 12:06:16 -0300255 uint32_t off;
Fabio Utzige52c08e2019-09-11 19:32:00 -0300256 uint32_t protect_tlv_size;
David Brownf5b33d82017-09-01 10:58:27 -0600257 int area_id;
258 int rc;
259
Fabio Utzig10ee6482019-08-01 12:04:52 -0300260#if (BOOT_IMAGE_NUMBER == 1)
261 (void)state;
262#endif
263
264 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
David Brownf5b33d82017-09-01 10:58:27 -0600265 rc = flash_area_open(area_id, &fap);
266 if (rc != 0) {
267 rc = BOOT_EFLASH;
268 goto done;
269 }
270
Fabio Utzig61fd8882019-09-14 20:00:20 -0300271 off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
272
273 if (flash_area_read(fap, off, &info, sizeof(info))) {
274 rc = BOOT_EFLASH;
David Brownf5b33d82017-09-01 10:58:27 -0600275 goto done;
276 }
Fabio Utzig61fd8882019-09-14 20:00:20 -0300277
Fabio Utzige52c08e2019-09-11 19:32:00 -0300278 protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
279 if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
280 if (protect_tlv_size != info.it_tlv_tot) {
281 rc = BOOT_EBADIMAGE;
282 goto done;
283 }
284
285 if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
286 rc = BOOT_EFLASH;
287 goto done;
288 }
289 } else if (protect_tlv_size != 0) {
290 rc = BOOT_EBADIMAGE;
291 goto done;
292 }
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300293 else
294 {
295 /* acc. to MISRA R.15.7 */
296 }
Fabio Utzige52c08e2019-09-11 19:32:00 -0300297
Fabio Utzig61fd8882019-09-14 20:00:20 -0300298 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
299 rc = BOOT_EBADIMAGE;
300 goto done;
301 }
302
Fabio Utzige52c08e2019-09-11 19:32:00 -0300303 *size = off + protect_tlv_size + info.it_tlv_tot;
David Brownf5b33d82017-09-01 10:58:27 -0600304 rc = 0;
305
306done:
307 flash_area_close(fap);
Fabio Utzig2eebf112017-09-04 15:25:08 -0300308 return rc;
David Brownf5b33d82017-09-01 10:58:27 -0600309}
310
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300311#endif
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200312
David Brownab449182019-11-15 09:32:52 -0700313static uint32_t
Fabio Utzig10ee6482019-08-01 12:04:52 -0300314boot_write_sz(struct boot_loader_state *state)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800315{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300316 size_t elem_sz;
Fabio Utzig12d59162019-11-28 10:01:59 -0300317#if MCUBOOT_SWAP_USING_SCRATCH
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300318 size_t align;
Fabio Utzig12d59162019-11-28 10:01:59 -0300319#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800320
321 /* Figure out what size to write update status update as. The size depends
322 * on what the minimum write size is for scratch area, active image slot.
323 * We need to use the bigger of those 2 values.
324 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300325
Fabio Utzig10ee6482019-08-01 12:04:52 -0300326 elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT));
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300327 assert(elem_sz != 0u);
328
Fabio Utzig12d59162019-11-28 10:01:59 -0300329#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -0300330 align = flash_area_align(BOOT_SCRATCH_AREA(state));
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300331 assert(align != 0u);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800332 if (align > elem_sz) {
333 elem_sz = align;
334 }
Fabio Utzig12d59162019-11-28 10:01:59 -0300335#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800336
337 return elem_sz;
338}
339
Fabio Utzig10ee6482019-08-01 12:04:52 -0300340static int
341boot_initialize_area(struct boot_loader_state *state, int flash_area)
342{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300343 uint32_t num_sectors = BOOT_MAX_IMG_SECTORS;
344 boot_sector_t *out_sectors;
Fabio Utzig10ee6482019-08-01 12:04:52 -0300345 size_t *out_num_sectors;
346 int rc;
347
348 num_sectors = BOOT_MAX_IMG_SECTORS;
349
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300350 if (flash_area == (int) FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
Fabio Utzig10ee6482019-08-01 12:04:52 -0300351 out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors;
352 out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors;
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300353 } else if (flash_area == (int) FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
Fabio Utzig10ee6482019-08-01 12:04:52 -0300354 out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors;
355 out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors;
Fabio Utzig12d59162019-11-28 10:01:59 -0300356#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -0300357 } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
358 out_sectors = state->scratch.sectors;
359 out_num_sectors = &state->scratch.num_sectors;
Fabio Utzig12d59162019-11-28 10:01:59 -0300360#endif
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200361#if MCUBOOT_SWAP_USING_STATUS
362 } else if (flash_area == FLASH_AREA_IMAGE_SWAP_STATUS) {
363 out_sectors = state->status.sectors;
364 out_num_sectors = &state->status.num_sectors;
365#endif
Fabio Utzig10ee6482019-08-01 12:04:52 -0300366 } else {
367 return BOOT_EFLASH;
368 }
369
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300370#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
Fabio Utzig10ee6482019-08-01 12:04:52 -0300371 rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300372#else
373 _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed");
374 rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors);
375#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
Fabio Utzig10ee6482019-08-01 12:04:52 -0300376 if (rc != 0) {
377 return rc;
378 }
379 *out_num_sectors = num_sectors;
380 return 0;
381}
Fabio Utzig10ee6482019-08-01 12:04:52 -0300382
Christopher Collins92ea77f2016-12-12 15:59:26 -0800383/**
384 * Determines the sector layout of both image slots and the scratch area.
385 * This information is necessary for calculating the number of bytes to erase
386 * and copy during an image swap. The information collected during this
Fabio Utzig10ee6482019-08-01 12:04:52 -0300387 * function is used to populate the state.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800388 */
389static int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300390boot_read_sectors(struct boot_loader_state *state)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800391{
Fabio Utzigb0f04732019-07-31 09:49:19 -0300392 uint8_t image_index;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800393 int rc;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800394
Fabio Utzig10ee6482019-08-01 12:04:52 -0300395 image_index = BOOT_CURR_IMG(state);
Fabio Utzigb0f04732019-07-31 09:49:19 -0300396
397 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
Christopher Collins92ea77f2016-12-12 15:59:26 -0800398 if (rc != 0) {
399 return BOOT_EFLASH;
400 }
401
Fabio Utzig10ee6482019-08-01 12:04:52 -0300402 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index));
Christopher Collins92ea77f2016-12-12 15:59:26 -0800403 if (rc != 0) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300404 /* We need to differentiate from the primary image issue */
405 return BOOT_EFLASH_SEC;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800406 }
407
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200408#if MCUBOOT_SWAP_USING_STATUS
409 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SWAP_STATUS);
410 if (rc != 0) {
411 return BOOT_EFLASH;
412 }
413#endif
414
Fabio Utzig12d59162019-11-28 10:01:59 -0300415#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -0300416 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH);
Fabio Utzig2bd980a2018-11-26 10:38:17 -0200417 if (rc != 0) {
418 return BOOT_EFLASH;
419 }
Fabio Utzig12d59162019-11-28 10:01:59 -0300420#endif
Fabio Utzig2bd980a2018-11-26 10:38:17 -0200421
Fabio Utzig10ee6482019-08-01 12:04:52 -0300422 BOOT_WRITE_SZ(state) = boot_write_sz(state);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800423
424 return 0;
425}
426
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200427static void
Fabio Utzig12d59162019-11-28 10:01:59 -0300428boot_status_reset(struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800429{
Fabio Utzig4741c452019-12-19 15:32:41 -0300430#ifdef MCUBOOT_ENC_IMAGES
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300431 (void)memset(&bs->enckey, BOOT_UNINITIALIZED_KEY_FILL,
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300432 BOOT_NUM_SLOTS * BOOT_ENC_KEY_ALIGN_SIZE);
433#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300434 (void)memset(&bs->enctlv, BOOT_UNINITIALIZED_TLV_FILL,
435 BOOT_NUM_SLOTS * BOOT_ENC_TLV_ALIGN_SIZE);
Fabio Utzig4741c452019-12-19 15:32:41 -0300436#endif
437#endif /* MCUBOOT_ENC_IMAGES */
438
439 bs->use_scratch = 0;
440 bs->swap_size = 0;
441 bs->source = 0;
442
Fabio Utzig74aef312019-11-28 11:05:34 -0300443 bs->op = BOOT_STATUS_OP_MOVE;
Fabio Utzig39000012018-07-30 12:40:20 -0300444 bs->idx = BOOT_STATUS_IDX_0;
445 bs->state = BOOT_STATUS_STATE_0;
Christopher Collinsa1c12042019-05-23 14:00:28 -0700446 bs->swap_type = BOOT_SWAP_TYPE_NONE;
Fabio Utzig12d59162019-11-28 10:01:59 -0300447}
Christopher Collins92ea77f2016-12-12 15:59:26 -0800448
Fabio Utzig12d59162019-11-28 10:01:59 -0300449bool
450boot_status_is_reset(const struct boot_status *bs)
451{
Fabio Utzig74aef312019-11-28 11:05:34 -0300452 return (bs->op == BOOT_STATUS_OP_MOVE &&
453 bs->idx == BOOT_STATUS_IDX_0 &&
454 bs->state == BOOT_STATUS_STATE_0);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800455}
456
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200457#ifndef MCUBOOT_SWAP_USING_STATUS
Christopher Collins92ea77f2016-12-12 15:59:26 -0800458/**
459 * Writes the supplied boot status to the flash file system. The boot status
460 * contains the current state of an in-progress image copy operation.
461 *
462 * @param bs The boot status to write.
463 *
464 * @return 0 on success; nonzero on failure.
465 */
466int
Fabio Utzig12d59162019-11-28 10:01:59 -0300467boot_write_status(const struct boot_loader_state *state, struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800468{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300469 const struct flash_area *fap = NULL;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800470 uint32_t off;
471 int area_id;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300472 int rc = 0;
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300473 uint8_t buf[BOOT_MAX_ALIGN];
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300474 uint32_t align;
Fabio Utzig39000012018-07-30 12:40:20 -0300475 uint8_t erased_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800476
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300477 /* NOTE: The first sector copied (that is the last sector on slot) contains
David Vincze2d736ad2019-02-18 11:50:22 +0100478 * the trailer. Since in the last step the primary slot is erased, the
479 * first two status writes go to the scratch which will be copied to
480 * the primary slot!
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300481 */
482
Fabio Utzig12d59162019-11-28 10:01:59 -0300483#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig2473ac02017-05-02 12:45:02 -0300484 if (bs->use_scratch) {
Christopher Collins92ea77f2016-12-12 15:59:26 -0800485 /* Write to scratch. */
486 area_id = FLASH_AREA_IMAGE_SCRATCH;
487 } else {
Fabio Utzig12d59162019-11-28 10:01:59 -0300488#endif
David Vincze2d736ad2019-02-18 11:50:22 +0100489 /* Write to the primary slot. */
Fabio Utzig10ee6482019-08-01 12:04:52 -0300490 area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
Fabio Utzig12d59162019-11-28 10:01:59 -0300491#if MCUBOOT_SWAP_USING_SCRATCH
Christopher Collins92ea77f2016-12-12 15:59:26 -0800492 }
Fabio Utzig12d59162019-11-28 10:01:59 -0300493#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800494
495 rc = flash_area_open(area_id, &fap);
496 if (rc != 0) {
497 rc = BOOT_EFLASH;
498 goto done;
499 }
500
501 off = boot_status_off(fap) +
Fabio Utzig12d59162019-11-28 10:01:59 -0300502 boot_status_internal_off(bs, BOOT_WRITE_SZ(state));
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +0200503 align = flash_area_align(fap);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300504 if (align == 0u) {
505 rc = BOOT_EFLASH;
506 goto done;
507 }
508
Fabio Utzig39000012018-07-30 12:40:20 -0300509 erased_val = flash_area_erased_val(fap);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300510 (void)memset(buf, erased_val, BOOT_MAX_ALIGN);
David Brown9d725462017-01-23 15:50:58 -0700511 buf[0] = bs->state;
512
513 rc = flash_area_write(fap, off, buf, align);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800514 if (rc != 0) {
515 rc = BOOT_EFLASH;
516 goto done;
517 }
518
519 rc = 0;
520
521done:
522 flash_area_close(fap);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300523
Christopher Collins92ea77f2016-12-12 15:59:26 -0800524 return rc;
525}
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200526#endif /* MCUBOOT_SWAP_USING_STATUS */
527
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300528
David Vinczee574f2d2020-07-10 11:42:03 +0200529#endif /* !MCUBOOT_DIRECT_XIP */
Christopher Collins92ea77f2016-12-12 15:59:26 -0800530
531/*
David Vinczec3084132020-02-18 14:50:47 +0100532 * Validate image hash/signature and optionally the security counter in a slot.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800533 */
Raef Colese8fe6cf2020-05-26 13:07:40 +0100534static fih_int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300535boot_image_check(struct boot_loader_state *state, struct image_header *hdr,
536 const struct flash_area *fap, struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800537{
Fabio Utzig10ee6482019-08-01 12:04:52 -0300538 TARGET_STATIC uint8_t tmpbuf[BOOT_TMPBUF_SZ];
Fabio Utzigb0f04732019-07-31 09:49:19 -0300539 uint8_t image_index;
Raef Colese8fe6cf2020-05-26 13:07:40 +0100540 fih_int fih_rc = FIH_FAILURE;
Fabio Utzigba829042018-09-18 08:29:34 -0300541
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200542#ifdef USE_IFX_SE_CRYPTO
543 fih_uint fih_complex_result = FIH_UINT_ZERO;
544 extern fih_uint IFX_FIH_IMG_VALIDATE_COMPLEX_OK;
545#else
546 fih_int fih_complex_result = FIH_FAILURE;
547 extern fih_int FIH_IMG_VALIDATE_COMPLEX_OK;
548#endif /* USE_IFX_SE_CRYPTO */
549
Fabio Utzig10ee6482019-08-01 12:04:52 -0300550#if (BOOT_IMAGE_NUMBER == 1)
551 (void)state;
552#endif
553
Fabio Utzigba829042018-09-18 08:29:34 -0300554 (void)bs;
Fabio Utzigbc077932019-08-26 11:16:34 -0300555
556 image_index = BOOT_CURR_IMG(state);
557
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300558/* In the case of ram loading the image has already been decrypted as it is
559 * decrypted when copied in ram */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300560#if defined(MCUBOOT_ENC_IMAGES)
561 if (MUST_DECRYPT(fap, image_index, hdr) && !IS_RAM_BOOTABLE(hdr)) {
562 int rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Fabio Utzigba829042018-09-18 08:29:34 -0300563 if (rc < 0) {
Raef Colese8fe6cf2020-05-26 13:07:40 +0100564 FIH_RET(fih_rc);
Fabio Utzigba829042018-09-18 08:29:34 -0300565 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300566 else {
567 uint8_t slot = (uint8_t)rc;
568
569 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap, bs);
570 if (rc < 0) {
571 FIH_RET(fih_rc);
572 }
573 if (0 == rc && boot_enc_set_key(BOOT_CURR_ENC(state), slot, bs)) {
574 FIH_RET(fih_rc);
575 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200576#ifdef MCUBOOT_ENC_IMAGES_XIP_MULTI
577 ifx_epb_set_xip_crypto_params((uint32_t *)bs->enckey[slot],
578 (uint32_t *)BOOT_CURR_ENC(state)[slot].aes_iv);
579#endif /* MCUBOOT_ENC_IMAGES_XIP_MULTI */
Fabio Utzigba829042018-09-18 08:29:34 -0300580 }
581 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200582#endif /* MCUBOOT_ENC_IMAGES */
Fabio Utzigbc077932019-08-26 11:16:34 -0300583
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200584#ifdef USE_IFX_SE_CRYPTO
585 FIH_UCALL(bootutil_psa_img_validate, fih_complex_result, \
586 BOOT_CURR_ENC(state), image_index, hdr, fap, \
587 tmpbuf, BOOT_TMPBUF_SZ, NULL, 0);
588
589 BOOT_LOG_DBG(" * bootutil_psa_img_validate expected = 0x%x, " \
590 "returned = 0x%x", \
591 fih_uint_decode(IFX_FIH_IMG_VALIDATE_COMPLEX_OK), \
592 fih_uint_decode(fih_complex_result));
593
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200594 if (fih_uint_eq(fih_complex_result, IFX_FIH_IMG_VALIDATE_COMPLEX_OK)) {
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200595 fih_rc = fih_int_encode_zero_equality(
596 fih_uint_decode(IFX_FIH_IMG_VALIDATE_COMPLEX_OK) &
597 ~fih_uint_decode(fih_complex_result));
598 }
599 else {
600 fih_rc = FIH_FAILURE;
601 }
602#else
603 FIH_CALL(bootutil_img_validate, fih_complex_result, BOOT_CURR_ENC(state), image_index,
Raef Colese8fe6cf2020-05-26 13:07:40 +0100604 hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, NULL);
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200605 BOOT_LOG_DBG(" * bootutil_img_validate expected = 0x%x, " \
606 "returned = 0x%x", \
607 fih_int_decode(FIH_IMG_VALIDATE_COMPLEX_OK), \
608 fih_int_decode(fih_complex_result));
609
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200610 if (fih_eq(fih_complex_result, FIH_IMG_VALIDATE_COMPLEX_OK)) {
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200611 fih_rc = fih_int_encode_zero_equality(
612 fih_int_decode(FIH_IMG_VALIDATE_COMPLEX_OK) &
613 ~fih_int_decode(fih_complex_result));
614 }
615 else {
616 fih_rc = FIH_FAILURE;
617 }
618
619#endif /* USE_IFX_SE_CRYPTO */
Fabio Utzig10ee6482019-08-01 12:04:52 -0300620
Raef Colese8fe6cf2020-05-26 13:07:40 +0100621 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800622}
623
Raef Colese8fe6cf2020-05-26 13:07:40 +0100624static fih_int
Christopher Collins92ea77f2016-12-12 15:59:26 -0800625split_image_check(struct image_header *app_hdr,
626 const struct flash_area *app_fap,
627 struct image_header *loader_hdr,
628 const struct flash_area *loader_fap)
629{
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200630 fih_int fih_rc = FIH_FAILURE;
631#if !defined USE_IFX_SE_CRYPTO
Christopher Collins92ea77f2016-12-12 15:59:26 -0800632 static void *tmpbuf;
633 uint8_t loader_hash[32];
634
635 if (!tmpbuf) {
636 tmpbuf = malloc(BOOT_TMPBUF_SZ);
637 if (!tmpbuf) {
Raef Colese8fe6cf2020-05-26 13:07:40 +0100638 goto out;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800639 }
640 }
641
Raef Colese8fe6cf2020-05-26 13:07:40 +0100642 FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, loader_hdr, loader_fap,
643 tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200644 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
Raef Colese8fe6cf2020-05-26 13:07:40 +0100645 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800646 }
647
Raef Colese8fe6cf2020-05-26 13:07:40 +0100648 FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, app_hdr, app_fap,
649 tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200650#else
651 /* Not implemented for USE_IFX_SE_CRYPTO
652 The code below is just to avoid warnings
653 */
654 (void)app_hdr;
655 (void)app_fap;
656 (void)loader_hdr;
657 (void)loader_fap;
658 goto out;
659#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800660
Raef Colese8fe6cf2020-05-26 13:07:40 +0100661out:
662 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800663}
664
Fabio Utzig338a19f2018-12-03 08:37:08 -0200665/*
David Brown9bf95af2019-10-10 15:36:36 -0600666 * Check that this is a valid header. Valid means that the magic is
667 * correct, and that the sizes/offsets are "sane". Sane means that
668 * there is no overflow on the arithmetic, and that the result fits
669 * within the flash area we are in.
670 */
671static bool
672boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fap)
673{
674 uint32_t size;
675
676 if (hdr->ih_magic != IMAGE_MAGIC) {
677 return false;
678 }
679
680 if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size)) {
681 return false;
682 }
683
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300684 if (size >= flash_area_get_size(fap)) {
David Brown9bf95af2019-10-10 15:36:36 -0600685 return false;
686 }
687
688 return true;
689}
690
691/*
Fabio Utzig338a19f2018-12-03 08:37:08 -0200692 * Check that a memory area consists of a given value.
693 */
694static inline bool
695boot_data_is_set_to(uint8_t val, void *data, size_t len)
Fabio Utzig39000012018-07-30 12:40:20 -0300696{
697 uint8_t i;
Fabio Utzig338a19f2018-12-03 08:37:08 -0200698 uint8_t *p = (uint8_t *)data;
699 for (i = 0; i < len; i++) {
700 if (val != p[i]) {
701 return false;
Fabio Utzig39000012018-07-30 12:40:20 -0300702 }
703 }
Fabio Utzig338a19f2018-12-03 08:37:08 -0200704 return true;
705}
706
707static int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300708boot_check_header_erased(struct boot_loader_state *state, int slot)
Fabio Utzig338a19f2018-12-03 08:37:08 -0200709{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300710 const struct flash_area *fap = NULL;
Fabio Utzig338a19f2018-12-03 08:37:08 -0200711 struct image_header *hdr;
712 uint8_t erased_val;
Fabio Utzigb0f04732019-07-31 09:49:19 -0300713 int area_id;
Fabio Utzig338a19f2018-12-03 08:37:08 -0200714 int rc;
715
Fabio Utzig10ee6482019-08-01 12:04:52 -0300716 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
Fabio Utzigb0f04732019-07-31 09:49:19 -0300717 rc = flash_area_open(area_id, &fap);
Fabio Utzig338a19f2018-12-03 08:37:08 -0200718 if (rc != 0) {
719 return -1;
720 }
721
722 erased_val = flash_area_erased_val(fap);
723 flash_area_close(fap);
724
Fabio Utzig10ee6482019-08-01 12:04:52 -0300725 hdr = boot_img_hdr(state, slot);
Fabio Utzig338a19f2018-12-03 08:37:08 -0200726 if (!boot_data_is_set_to(erased_val, &hdr->ih_magic, sizeof(hdr->ih_magic))) {
727 return -1;
728 }
729
730 return 0;
Fabio Utzig39000012018-07-30 12:40:20 -0300731}
732
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200733#if (BOOT_IMAGE_NUMBER > 1 && defined(MCUBOOT_DEPENDENCY_CHECK)) || \
David Vinczee574f2d2020-07-10 11:42:03 +0200734 defined(MCUBOOT_DIRECT_XIP) || \
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000735 (defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION))
736/**
David Vincze8b0b6372020-05-20 19:54:44 +0200737 * Compare image version numbers not including the build number
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000738 *
David Vincze8b0b6372020-05-20 19:54:44 +0200739 * @param ver1 Pointer to the first image version to compare.
740 * @param ver2 Pointer to the second image version to compare.
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000741 *
David Vincze8b0b6372020-05-20 19:54:44 +0200742 * @retval -1 If ver1 is strictly less than ver2.
743 * @retval 0 If the image version numbers are equal,
744 * (not including the build number).
745 * @retval 1 If ver1 is strictly greater than ver2.
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000746 */
747static int
David Vincze8b0b6372020-05-20 19:54:44 +0200748boot_version_cmp(const struct image_version *ver1,
749 const struct image_version *ver2)
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000750{
David Vincze8b0b6372020-05-20 19:54:44 +0200751 if (ver1->iv_major > ver2->iv_major) {
752 return 1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000753 }
David Vincze8b0b6372020-05-20 19:54:44 +0200754 if (ver1->iv_major < ver2->iv_major) {
755 return -1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000756 }
David Vincze8b0b6372020-05-20 19:54:44 +0200757 /* The major version numbers are equal, continue comparison. */
758 if (ver1->iv_minor > ver2->iv_minor) {
759 return 1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000760 }
David Vincze8b0b6372020-05-20 19:54:44 +0200761 if (ver1->iv_minor < ver2->iv_minor) {
762 return -1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000763 }
David Vincze8b0b6372020-05-20 19:54:44 +0200764 /* The minor version numbers are equal, continue comparison. */
765 if (ver1->iv_revision > ver2->iv_revision) {
766 return 1;
767 }
768 if (ver1->iv_revision < ver2->iv_revision) {
769 return -1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000770 }
771
772 return 0;
773}
774#endif
775
Dominik Ermel0c8c8d52021-02-17 14:45:02 +0000776#if defined(MCUBOOT_DIRECT_XIP)
777/**
778 * Check if image in slot has been set with specific ROM address to run from
779 * and whether the slot starts at that address.
780 *
781 * @returns 0 if IMAGE_F_ROM_FIXED flag is not set;
782 * 0 if IMAGE_F_ROM_FIXED flag is set and ROM address specified in
783 * header matches the slot address;
784 * 1 if IMF_F_ROM_FIXED flag is set but ROM address specified in header
785 * does not match the slot address.
786 */
787static bool
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300788boot_rom_address_check(struct boot_loader_state *state)
Dominik Ermel0c8c8d52021-02-17 14:45:02 +0000789{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300790 uint32_t active_slot;
791 const struct image_header *hdr;
792 uint32_t f_off;
793
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300794 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300795 hdr = boot_img_hdr(state, active_slot);
796 f_off = boot_img_slot_off(state, active_slot);
797
Dominik Ermel0c8c8d52021-02-17 14:45:02 +0000798 if (hdr->ih_flags & IMAGE_F_ROM_FIXED && hdr->ih_load_addr != f_off) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300799 BOOT_LOG_WRN("Image in %s slot at 0x%" PRIx32
800 " has been built for offset 0x%" PRIx32 ", skipping",
801 active_slot == 0 ? "primary" : "secondary", f_off,
Dominik Ermel0c8c8d52021-02-17 14:45:02 +0000802 hdr->ih_load_addr);
803
804 /* If there is address mismatch, the image is not bootable from this
805 * slot.
806 */
807 return 1;
808 }
809 return 0;
810}
811#endif
812
Fabio Utzigb1adb1e2019-09-11 11:42:53 -0300813/*
814 * Check that there is a valid image in a slot
815 *
816 * @returns
Raef Colese8fe6cf2020-05-26 13:07:40 +0100817 * FIH_SUCCESS if image was successfully validated
818 * 1 (or its fih_int encoded form) if no bootloable image was found
819 * FIH_FAILURE on any errors
Fabio Utzigb1adb1e2019-09-11 11:42:53 -0300820 */
Raef Colese8fe6cf2020-05-26 13:07:40 +0100821static fih_int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300822boot_validate_slot(struct boot_loader_state *state, int slot,
823 struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800824{
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300825 const struct flash_area *fap = NULL;
Marti Bolivarf804f622017-06-12 15:41:48 -0400826 struct image_header *hdr;
Fabio Utzigb0f04732019-07-31 09:49:19 -0300827 int area_id;
Raef Colese8fe6cf2020-05-26 13:07:40 +0100828 fih_int fih_rc = FIH_FAILURE;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800829 int rc;
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300830
Fabio Utzig10ee6482019-08-01 12:04:52 -0300831 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
Fabio Utzigb0f04732019-07-31 09:49:19 -0300832 rc = flash_area_open(area_id, &fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800833 if (rc != 0) {
Raef Colese8fe6cf2020-05-26 13:07:40 +0100834 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800835 }
836
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300837 BOOT_LOG_DBG("> boot_validate_slot: fa_id = %u", (unsigned)fap->fa_id);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200838
Fabio Utzig10ee6482019-08-01 12:04:52 -0300839 hdr = boot_img_hdr(state, slot);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300840
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200841#ifdef MCUBOOT_ENC_IMAGES_XIP_MULTI
842/* In the XIP encryption multi image case if XIP encryption is turned on then
843 * the boot_check_header_erased() can't detect erased header correctly for the second and next images
844 * because erased value is not read as 0xFF.
845 * So, the bootloader has one option only to detect correctness of image header: it is
846 * to check header magic */
847 if (hdr->ih_magic != IMAGE_MAGIC) {
848 FIH_RET(fih_rc);
849 }
850#endif /* MCUBOOT_ENC_IMAGES_XIP_MULTI */
851
Fabio Utzig10ee6482019-08-01 12:04:52 -0300852 if (boot_check_header_erased(state, slot) == 0 ||
853 (hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) {
Fabio Utzig260ec452020-07-09 18:40:07 -0300854
855#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
856 /*
857 * This fixes an issue where an image might be erased, but a trailer
858 * be left behind. It can happen if the image is in the secondary slot
859 * and did not pass validation, in which case the whole slot is erased.
860 * If during the erase operation, a reset occurs, parts of the slot
861 * might have been erased while some did not. The concerning part is
862 * the trailer because it might disable a new image from being loaded
863 * through mcumgr; so we just get rid of the trailer here, if the header
864 * is erased.
865 */
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200866 BOOT_LOG_DBG(" * Fix the secondary slot when image is invalid.");
Fabio Utzig260ec452020-07-09 18:40:07 -0300867 if (slot != BOOT_PRIMARY_SLOT) {
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200868 BOOT_LOG_DBG(" * Erase secondary image trailer.");
Fabio Utzig260ec452020-07-09 18:40:07 -0300869 swap_erase_trailer_sectors(state, fap);
870 }
871#endif
872
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200873 BOOT_LOG_DBG(" * No bootable image in slot(%d); continue booting from the primary slot.", slot);
David Vincze2d736ad2019-02-18 11:50:22 +0100874 /* No bootable image in slot; continue booting from the primary slot. */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300875 fih_rc = FIH_SWAP_TYPE_NONE;
Fabio Utzig338a19f2018-12-03 08:37:08 -0200876 goto out;
Fabio Utzig39000012018-07-30 12:40:20 -0300877 }
878
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000879#if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION)
880 if (slot != BOOT_PRIMARY_SLOT) {
881 /* Check if version of secondary slot is sufficient */
David Vincze8b0b6372020-05-20 19:54:44 +0200882 rc = boot_version_cmp(
883 &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver,
884 &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver);
885 if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) {
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000886 BOOT_LOG_ERR("insufficient version in secondary slot");
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300887 flash_area_erase(fap, 0, flash_area_get_size(fap));
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000888 /* Image in the secondary slot does not satisfy version requirement.
889 * Erase the image and continue booting from the primary slot.
890 */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300891 fih_rc = FIH_SWAP_TYPE_NONE;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000892 goto out;
893 }
894 }
895#endif
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200896 BOOT_HOOK_CALL_FIH(boot_image_check_hook, FIH_INT_INIT(BOOT_HOOK_REGULAR),
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300897 fih_rc, BOOT_CURR_IMG(state), slot);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200898 if (fih_eq(fih_rc, FIH_INT_INIT(BOOT_HOOK_REGULAR)))
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300899 {
900 FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs);
901 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200902 if (!boot_is_header_valid(hdr, fap) || !fih_eq(fih_rc, FIH_SUCCESS)) {
Tamas Banfe031092020-09-10 17:32:39 +0200903 if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) {
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200904 BOOT_LOG_DBG(" * Image in the secondary slot is invalid. Erase the image");
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300905 flash_area_erase(fap, 0, flash_area_get_size(fap));
David Vinczee574f2d2020-07-10 11:42:03 +0200906 /* Image is invalid, erase it to prevent further unnecessary
907 * attempts to validate and boot it.
David Brownb38e0442017-02-24 13:57:12 -0700908 */
909 }
David Brown098de832019-12-10 11:58:01 -0700910#if !defined(__BOOTSIM__)
David Vincze2d736ad2019-02-18 11:50:22 +0100911 BOOT_LOG_ERR("Image in the %s slot is not valid!",
912 (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
David Brown098de832019-12-10 11:58:01 -0700913#endif
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300914 fih_rc = FIH_SWAP_TYPE_NONE;
Fabio Utzig338a19f2018-12-03 08:37:08 -0200915 goto out;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800916 }
917
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300918#if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_VERIFY_IMG_ADDRESS)
919 /* Verify that the image in the secondary slot has a reset address
920 * located in the primary slot. This is done to avoid users incorrectly
921 * overwriting an application written to the incorrect slot.
922 * This feature is only supported by ARM platforms.
923 */
924 if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
925 const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
926 struct image_header *secondary_hdr = boot_img_hdr(state, slot);
927 uint32_t reset_value = 0;
928 uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value);
929
930 rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value));
931 if (rc != 0) {
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200932 fih_rc = FIH_INT_INIT(1);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300933 goto out;
934 }
935
936 if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) {
937 BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot");
938 BOOT_LOG_ERR("Erasing image from secondary slot");
939
940 /* The vector table in the image located in the secondary
941 * slot does not target the primary slot. This might
942 * indicate that the image was loaded to the wrong slot.
943 *
944 * Erase the image and continue booting from the primary slot.
945 */
946 flash_area_erase(fap, 0, fap->fa_size);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200947 fih_rc = FIH_INT_INIT(1);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300948 goto out;
949 }
950 }
951#endif
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200952
Fabio Utzig338a19f2018-12-03 08:37:08 -0200953out:
954 flash_area_close(fap);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300955 BOOT_LOG_DBG("< boot_validate_slot: fa_id = %u", (unsigned)fap->fa_id);
Raef Colese8fe6cf2020-05-26 13:07:40 +0100956 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800957}
958
David Vinczec3084132020-02-18 14:50:47 +0100959#ifdef MCUBOOT_HW_ROLLBACK_PROT
960/**
961 * Updates the stored security counter value with the image's security counter
962 * value which resides in the given slot, only if it's greater than the stored
963 * value.
964 *
965 * @param image_index Index of the image to determine which security
966 * counter to update.
967 * @param slot Slot number of the image.
968 * @param hdr Pointer to the image header structure of the image
969 * that is currently stored in the given slot.
970 *
971 * @return 0 on success; nonzero on failure.
972 */
973static int
974boot_update_security_counter(uint8_t image_index, int slot,
975 struct image_header *hdr)
976{
977 const struct flash_area *fap = NULL;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300978 fih_int fih_rc = FIH_FAILURE;
979 fih_uint img_security_cnt = FIH_UINT_ZERO;
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300980 void * custom_data = NULL;
David Vinczec3084132020-02-18 14:50:47 +0100981 int rc;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300982#if defined CYW20829
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300983 uint8_t buff[REPROV_PACK_SIZE];
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300984#endif /* defined CYW20829 */
David Vinczec3084132020-02-18 14:50:47 +0100985
986 rc = flash_area_open(flash_area_id_from_multi_image_slot(image_index, slot),
987 &fap);
988 if (rc != 0) {
989 rc = BOOT_EFLASH;
990 goto done;
991 }
992
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300993 rc = -1;
994 FIH_CALL(bootutil_get_img_security_cnt, fih_rc, hdr, fap, &img_security_cnt);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200995 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
David Vinczec3084132020-02-18 14:50:47 +0100996 goto done;
997 }
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300998 else
999 {
1000 fih_rc = FIH_FAILURE;
1001 }
David Vinczec3084132020-02-18 14:50:47 +01001002
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001003#if defined CYW20829
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001004 rc = bootutil_get_img_reprov_packet(hdr, fap, buff);
1005 if (rc == 0) {
1006 custom_data = (void *)buff;
David Vinczec3084132020-02-18 14:50:47 +01001007 }
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001008#endif /* defined CYW20829 */
David Vinczec3084132020-02-18 14:50:47 +01001009
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001010 rc = boot_nv_security_counter_update(image_index, img_security_cnt, custom_data);
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02001011#ifdef USE_IFX_SE_CRYPTO
1012 fih_uint img_security_check = FIH_UINT_ZERO;
1013 FIH_CALL(boot_nv_security_counter_get, fih_rc, image_index, &img_security_check);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001014 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02001015 goto done;
1016 }
1017 else
1018 {
1019 fih_rc = FIH_FAILURE;
1020 BOOT_LOG_INF("[SUCCESS] security_counter_get called right after security_counter_update" \
1021 "to check if update is successful upd_cnt = %u, read_cnt = %u",
1022 fih_uint_decode(img_security_check), img_security_cnt);
1023 }
1024#endif /* IFX_SE_RT_CRYPTO */
David Vinczec3084132020-02-18 14:50:47 +01001025done:
1026 flash_area_close(fap);
1027 return rc;
1028}
1029#endif /* MCUBOOT_HW_ROLLBACK_PROT */
1030
David Vinczee574f2d2020-07-10 11:42:03 +02001031/**
1032 * Determines which swap operation to perform, if any. If it is determined
1033 * that a swap operation is required, the image in the secondary slot is checked
1034 * for validity. If the image in the secondary slot is invalid, it is erased,
1035 * and a swap type of "none" is indicated.
1036 *
1037 * @return The type of swap to perform (BOOT_SWAP_TYPE...)
1038 */
1039static int
1040boot_validated_swap_type(struct boot_loader_state *state,
1041 struct boot_status *bs)
1042{
1043 int swap_type;
Raef Colese8fe6cf2020-05-26 13:07:40 +01001044 fih_int fih_rc = FIH_FAILURE;
David Vinczee574f2d2020-07-10 11:42:03 +02001045
1046 swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
1047 if (BOOT_IS_UPGRADE(swap_type)) {
1048 /* Boot loader wants to switch to the secondary slot.
1049 * Ensure image is valid.
1050 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01001051 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SECONDARY_SLOT, bs);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001052 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
1053 if (fih_eq(fih_rc, FIH_SWAP_TYPE_NONE)) {
Raef Colese8fe6cf2020-05-26 13:07:40 +01001054 swap_type = BOOT_SWAP_TYPE_NONE;
1055 } else {
1056 swap_type = BOOT_SWAP_TYPE_FAIL;
1057 }
David Vinczee574f2d2020-07-10 11:42:03 +02001058 }
1059 }
1060
1061 return swap_type;
1062}
1063
Christopher Collins92ea77f2016-12-12 15:59:26 -08001064/**
Christopher Collins92ea77f2016-12-12 15:59:26 -08001065 * Erases a region of flash.
1066 *
Fabio Utzigba829042018-09-18 08:29:34 -03001067 * @param flash_area The flash_area containing the region to erase.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001068 * @param off The offset within the flash area to start the
1069 * erase.
1070 * @param sz The number of bytes to erase.
1071 *
1072 * @return 0 on success; nonzero on failure.
1073 */
Fabio Utzig12d59162019-11-28 10:01:59 -03001074int
Fabio Utzigc28005b2019-09-10 12:18:29 -03001075boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz)
Christopher Collins92ea77f2016-12-12 15:59:26 -08001076{
Fabio Utzigba829042018-09-18 08:29:34 -03001077 return flash_area_erase(fap, off, sz);
Christopher Collins92ea77f2016-12-12 15:59:26 -08001078}
1079
1080/**
1081 * Copies the contents of one flash region to another. You must erase the
1082 * destination region prior to calling this function.
1083 *
1084 * @param flash_area_id_src The ID of the source flash area.
1085 * @param flash_area_id_dst The ID of the destination flash area.
1086 * @param off_src The offset within the source flash area to
1087 * copy from.
1088 * @param off_dst The offset within the destination flash area to
1089 * copy to.
1090 * @param sz The number of bytes to copy.
1091 *
1092 * @return 0 on success; nonzero on failure.
1093 */
Fabio Utzig12d59162019-11-28 10:01:59 -03001094int
Fabio Utzigc28005b2019-09-10 12:18:29 -03001095boot_copy_region(struct boot_loader_state *state,
Fabio Utzig10ee6482019-08-01 12:04:52 -03001096 const struct flash_area *fap_src,
Fabio Utzigba829042018-09-18 08:29:34 -03001097 const struct flash_area *fap_dst,
Christopher Collins92ea77f2016-12-12 15:59:26 -08001098 uint32_t off_src, uint32_t off_dst, uint32_t sz)
1099{
Christopher Collins92ea77f2016-12-12 15:59:26 -08001100 uint32_t bytes_copied;
1101 int chunk_sz;
1102 int rc;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001103#if (defined (MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_ENC_IMAGES_XIP)) || \
1104 (defined (MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_ENC_IMAGES_XIP) && defined(MCUBOOT_ENC_IMAGES_XIP_MULTI))
Fabio Utzigba829042018-09-18 08:29:34 -03001105 uint32_t off;
Fabio Utziga87cc7d2019-08-26 11:21:45 -03001106 uint32_t tlv_off;
Fabio Utzigba829042018-09-18 08:29:34 -03001107 size_t blk_off;
1108 struct image_header *hdr;
1109 uint16_t idx;
1110 uint32_t blk_sz;
Fabio Utzigb0f04732019-07-31 09:49:19 -03001111 uint8_t image_index;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001112#endif /* (defined (MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_ENC_IMAGES_XIP)) || \
1113 (defined (MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_ENC_IMAGES_XIP) && defined(MCUBOOT_ENC_IMAGES_XIP_MULTI)) */
Christopher Collins92ea77f2016-12-12 15:59:26 -08001114
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001115/* NOTE:
1116 * Default value 1024 is not suitable for platforms with larger erase size.
1117 * Give user ability to define platform tolerant chunk size. In most cases
1118 * it would be flash erase alignment.
1119 */
1120#ifdef MCUBOOT_PLATFORM_CHUNK_SIZE
1121 #define MCUBOOT_CHUNK_SIZE MCUBOOT_PLATFORM_CHUNK_SIZE
1122#else
1123 #define MCUBOOT_CHUNK_SIZE 1024
1124#endif
Fabio Utzig10ee6482019-08-01 12:04:52 -03001125
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001126 TARGET_STATIC uint8_t buf[MCUBOOT_CHUNK_SIZE] __attribute__((aligned(4)));
1127
1128#if !defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_ENC_IMAGES_XIP)
Fabio Utzig10ee6482019-08-01 12:04:52 -03001129 (void)state;
1130#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -08001131
Christopher Collins92ea77f2016-12-12 15:59:26 -08001132 bytes_copied = 0;
1133 while (bytes_copied < sz) {
1134 if (sz - bytes_copied > sizeof buf) {
1135 chunk_sz = sizeof buf;
1136 } else {
1137 chunk_sz = sz - bytes_copied;
1138 }
1139
1140 rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz);
1141 if (rc != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -03001142 return BOOT_EFLASH;
Christopher Collins92ea77f2016-12-12 15:59:26 -08001143 }
1144
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001145#if (defined (MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_ENC_IMAGES_XIP)) || \
1146 (defined (MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_ENC_IMAGES_XIP) && defined(MCUBOOT_ENC_IMAGES_XIP_MULTI))
Fabio Utzig10ee6482019-08-01 12:04:52 -03001147 image_index = BOOT_CURR_IMG(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001148 if ((flash_area_get_id(fap_src) == FLASH_AREA_IMAGE_PRIMARY(image_index) ||
1149 flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_PRIMARY(image_index)) &&
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001150
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001151 !(flash_area_get_id(fap_src) == FLASH_AREA_IMAGE_PRIMARY(image_index) &&
1152 flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_PRIMARY(image_index)) &&
1153 !(flash_area_get_id(fap_src) == FLASH_AREA_IMAGE_SECONDARY(image_index) &&
1154 flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_SECONDARY(image_index)))
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001155 {
1156 /* assume the primary slot as src, needs encryption */
1157 hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
Fabio Utzig74aef312019-11-28 11:05:34 -03001158#if !defined(MCUBOOT_SWAP_USING_MOVE)
Fabio Utzigba829042018-09-18 08:29:34 -03001159 off = off_src;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001160 if (flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001161 /* might need decryption (metadata from the secondary slot) */
1162 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
Fabio Utzigba829042018-09-18 08:29:34 -03001163 off = off_dst;
1164 }
Fabio Utzig74aef312019-11-28 11:05:34 -03001165#else
1166 off = off_dst;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001167 if (flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_PRIMARY(image_index)) {
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001168 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
Fabio Utzig74aef312019-11-28 11:05:34 -03001169 }
1170#endif
Fabio Utzig2fc80df2018-12-14 06:47:38 -02001171 if (IS_ENCRYPTED(hdr)) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001172 uint32_t abs_off = off + bytes_copied;
1173 if (abs_off < hdr->ih_hdr_size) {
Fabio Utzigba829042018-09-18 08:29:34 -03001174 /* do not decrypt header */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001175 if (abs_off + chunk_sz > hdr->ih_hdr_size) {
1176 /* The lower part of the chunk contains header data */
1177 blk_off = 0;
1178 blk_sz = chunk_sz - (hdr->ih_hdr_size - abs_off);
1179 idx = hdr->ih_hdr_size - abs_off;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001180 } else {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001181 /* The chunk contains exclusively header data */
1182 blk_sz = 0; /* nothing to decrypt */
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001183 }
Fabio Utzigba829042018-09-18 08:29:34 -03001184 } else {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001185 idx = 0;
1186 blk_sz = chunk_sz;
1187 blk_off = (abs_off - hdr->ih_hdr_size) & 0xf;
Fabio Utzigba829042018-09-18 08:29:34 -03001188 }
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001189
1190 if (blk_sz > 0)
1191 {
1192 tlv_off = BOOT_TLV_OFF(hdr);
1193 if (abs_off + chunk_sz > tlv_off) {
1194 /* do not decrypt TLVs */
1195 if (abs_off >= tlv_off) {
1196 blk_sz = 0;
1197 } else {
1198 blk_sz = tlv_off - abs_off;
1199 }
Fabio Utzigba829042018-09-18 08:29:34 -03001200 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001201#ifndef MCUBOOT_ENC_IMAGES_XIP_MULTI
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001202 rc = boot_encrypt(BOOT_CURR_ENC(state), image_index, fap_src,
1203 (abs_off + idx) - hdr->ih_hdr_size, blk_sz,
1204 blk_off, &buf[idx]);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001205#else /* MCUBOOT_ENC_IMAGES_XIP_MULTI */
1206 rc = boot_encrypt_xip(fap_src, fap_dst,
1207 (abs_off + idx), blk_sz, &buf[idx]);
1208#endif
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001209 if (rc != 0) {
1210 return rc;
1211 }
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001212 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001213#ifdef MCUBOOT_ENC_IMAGES_XIP_MULTI
1214 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
1215 }
1216 else {
1217 (void)blk_off;
1218 rc = boot_encrypt_xip(fap_src, fap_dst,
1219 off_dst + bytes_copied,
1220 chunk_sz, buf);
1221
1222 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
1223 SMIF_SET_CRYPTO_MODE(Enable);
Fabio Utzigba829042018-09-18 08:29:34 -03001224 }
1225 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001226#else
1227 }
1228 }
Christopher Collins92ea77f2016-12-12 15:59:26 -08001229 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001230#endif /* MCUBOOT_ENC_IMAGES_XIP_MULTI */
1231#else
1232 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
1233#endif /* (defined (MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_ENC_IMAGES_XIP)) || \
1234 (defined (MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_ENC_IMAGES_XIP) && defined(MCUBOOT_ENC_IMAGES_XIP_MULTI)) */
1235
Christopher Collins92ea77f2016-12-12 15:59:26 -08001236 if (rc != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -03001237 return BOOT_EFLASH;
Christopher Collins92ea77f2016-12-12 15:59:26 -08001238 }
1239
1240 bytes_copied += chunk_sz;
Fabio Utzig853657c2019-05-07 08:06:07 -03001241
1242 MCUBOOT_WATCHDOG_FEED();
Christopher Collins92ea77f2016-12-12 15:59:26 -08001243 }
1244
Fabio Utzigba829042018-09-18 08:29:34 -03001245 return 0;
Christopher Collins92ea77f2016-12-12 15:59:26 -08001246}
1247
Christopher Collins92ea77f2016-12-12 15:59:26 -08001248/**
David Vincze2d736ad2019-02-18 11:50:22 +01001249 * Overwrite primary slot with the image contained in the secondary slot.
1250 * If a prior copy operation was interrupted by a system reset, this function
1251 * redos the copy.
Christopher Collins92ea77f2016-12-12 15:59:26 -08001252 *
1253 * @param bs The current boot status. This function reads
1254 * this struct to determine if it is resuming
1255 * an interrupted swap operation. This
1256 * function writes the updated status to this
1257 * function on return.
1258 *
1259 * @return 0 on success; nonzero on failure.
1260 */
Fabio Utzig338a19f2018-12-03 08:37:08 -02001261#if defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_BOOTSTRAP)
David Brown17609d82017-05-05 09:41:34 -06001262static int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001263boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
David Brown17609d82017-05-05 09:41:34 -06001264{
Marti Bolivard3269fd2017-06-12 16:31:12 -04001265 size_t sect_count;
1266 size_t sect;
David Brown17609d82017-05-05 09:41:34 -06001267 int rc;
Fabio Utzig13d9e352017-10-05 20:32:31 -03001268 size_t size;
Marti Bolivard3269fd2017-06-12 16:31:12 -04001269 size_t this_size;
Fabio Utzig13d9e352017-10-05 20:32:31 -03001270 size_t last_sector;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001271 const struct flash_area *fap_primary_slot = NULL;
1272 const struct flash_area *fap_secondary_slot = NULL;
Fabio Utzigb0f04732019-07-31 09:49:19 -03001273 uint8_t image_index;
David Vincze2d736ad2019-02-18 11:50:22 +01001274
Fabio Utzigb4f88102020-10-04 10:16:24 -03001275#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1276 uint32_t sector;
1277 uint32_t trailer_sz;
1278 uint32_t off;
1279 uint32_t sz;
1280#endif
1281
Fabio Utzigaaf767c2017-12-05 10:22:46 -02001282 (void)bs;
1283
Fabio Utzig13d9e352017-10-05 20:32:31 -03001284#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1285 uint32_t src_size = 0;
Fabio Utzigd638b172019-08-09 10:38:05 -03001286 rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &src_size);
Fabio Utzig13d9e352017-10-05 20:32:31 -03001287 assert(rc == 0);
1288#endif
David Brown17609d82017-05-05 09:41:34 -06001289
David Vincze2d736ad2019-02-18 11:50:22 +01001290 BOOT_LOG_INF("Image upgrade secondary slot -> primary slot");
1291 BOOT_LOG_INF("Erasing the primary slot");
David Brown17609d82017-05-05 09:41:34 -06001292
Fabio Utzigb0f04732019-07-31 09:49:19 -03001293 image_index = BOOT_CURR_IMG(state);
1294
1295 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
1296 &fap_primary_slot);
Fabio Utzigba829042018-09-18 08:29:34 -03001297 assert (rc == 0);
1298
Fabio Utzigb0f04732019-07-31 09:49:19 -03001299 rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index),
1300 &fap_secondary_slot);
Fabio Utzigba829042018-09-18 08:29:34 -03001301 assert (rc == 0);
1302
Fabio Utzig10ee6482019-08-01 12:04:52 -03001303 sect_count = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001304 BOOT_LOG_DBG(" * primary slot sectors: %lu", (unsigned long)sect_count);
Fabio Utzig13d9e352017-10-05 20:32:31 -03001305 for (sect = 0, size = 0; sect < sect_count; sect++) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001306 this_size = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sect);
Fabio Utzigc28005b2019-09-10 12:18:29 -03001307 rc = boot_erase_region(fap_primary_slot, size, this_size);
David Brown17609d82017-05-05 09:41:34 -06001308 assert(rc == 0);
1309
Fabio Utzig13d9e352017-10-05 20:32:31 -03001310#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
Fabio Utzigb4f88102020-10-04 10:16:24 -03001311 if ((size + this_size) >= src_size) {
1312 size += src_size - size;
1313 size += BOOT_WRITE_SZ(state) - (size % BOOT_WRITE_SZ(state));
Fabio Utzig13d9e352017-10-05 20:32:31 -03001314 break;
1315 }
1316#endif
Fabio Utzigb4f88102020-10-04 10:16:24 -03001317
1318 size += this_size;
David Brown17609d82017-05-05 09:41:34 -06001319 }
1320
Fabio Utzigb4f88102020-10-04 10:16:24 -03001321#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1322 trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
1323 sector = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1;
1324 sz = 0;
1325 do {
1326 sz += boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sector);
1327 off = boot_img_sector_off(state, BOOT_PRIMARY_SLOT, sector);
1328 sector--;
1329 } while (sz < trailer_sz);
1330
1331 rc = boot_erase_region(fap_primary_slot, off, sz);
1332 assert(rc == 0);
1333#endif
1334
Fabio Utzigba829042018-09-18 08:29:34 -03001335#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig10ee6482019-08-01 12:04:52 -03001336 if (IS_ENCRYPTED(boot_img_hdr(state, BOOT_SECONDARY_SLOT))) {
Fabio Utzig1e4284b2019-08-23 11:55:27 -03001337 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index,
Fabio Utzig10ee6482019-08-01 12:04:52 -03001338 boot_img_hdr(state, BOOT_SECONDARY_SLOT),
Fabio Utzig4741c452019-12-19 15:32:41 -03001339 fap_secondary_slot, bs);
David Vincze2d736ad2019-02-18 11:50:22 +01001340
Fabio Utzigba829042018-09-18 08:29:34 -03001341 if (rc < 0) {
1342 return BOOT_EBADIMAGE;
1343 }
Fabio Utzig4741c452019-12-19 15:32:41 -03001344 if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) {
Fabio Utzigba829042018-09-18 08:29:34 -03001345 return BOOT_EBADIMAGE;
1346 }
1347 }
1348#endif
1349
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001350 BOOT_LOG_INF("Copying the secondary slot to the primary slot: 0x%lx bytes", (unsigned long)size);
Fabio Utzigc28005b2019-09-10 12:18:29 -03001351 rc = boot_copy_region(state, fap_secondary_slot, fap_primary_slot, 0, 0, size);
Fabio Utzigb4f88102020-10-04 10:16:24 -03001352 if (rc != 0) {
1353 return rc;
1354 }
1355
1356#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1357 rc = boot_write_magic(fap_primary_slot);
1358 if (rc != 0) {
1359 return rc;
1360 }
1361#endif
David Brown17609d82017-05-05 09:41:34 -06001362
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001363 rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state),
1364 BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size);
1365 if (rc != 0) {
1366 return rc;
1367 }
1368
David Vinczec3084132020-02-18 14:50:47 +01001369#ifdef MCUBOOT_HW_ROLLBACK_PROT
1370 /* Update the stored security counter with the new image's security counter
1371 * value. Both slots hold the new image at this point, but the secondary
1372 * slot's image header must be passed since the image headers in the
1373 * boot_data structure have not been updated yet.
1374 */
1375 rc = boot_update_security_counter(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT,
1376 boot_img_hdr(state, BOOT_SECONDARY_SLOT));
1377 if (rc != 0) {
1378 BOOT_LOG_ERR("Security counter update failed after image upgrade.");
1379 return rc;
1380 }
1381#endif /* MCUBOOT_HW_ROLLBACK_PROT */
1382
Fabio Utzig13d9e352017-10-05 20:32:31 -03001383 /*
1384 * Erases header and trailer. The trailer is erased because when a new
1385 * image is written without a trailer as is the case when using newt, the
1386 * trailer that was left might trigger a new upgrade.
1387 */
Christopher Collins2c88e692019-05-22 15:10:14 -07001388 BOOT_LOG_DBG("erasing secondary header");
Fabio Utzigc28005b2019-09-10 12:18:29 -03001389 rc = boot_erase_region(fap_secondary_slot,
Fabio Utzig10ee6482019-08-01 12:04:52 -03001390 boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0),
1391 boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0));
David Brown17609d82017-05-05 09:41:34 -06001392 assert(rc == 0);
Fabio Utzig10ee6482019-08-01 12:04:52 -03001393 last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1;
Christopher Collins2c88e692019-05-22 15:10:14 -07001394 BOOT_LOG_DBG("erasing secondary trailer");
Fabio Utzigc28005b2019-09-10 12:18:29 -03001395 rc = boot_erase_region(fap_secondary_slot,
Fabio Utzig10ee6482019-08-01 12:04:52 -03001396 boot_img_sector_off(state, BOOT_SECONDARY_SLOT,
1397 last_sector),
1398 boot_img_sector_size(state, BOOT_SECONDARY_SLOT,
1399 last_sector));
Fabio Utzig13d9e352017-10-05 20:32:31 -03001400 assert(rc == 0);
1401
David Vincze2d736ad2019-02-18 11:50:22 +01001402 flash_area_close(fap_primary_slot);
1403 flash_area_close(fap_secondary_slot);
Fabio Utzigba829042018-09-18 08:29:34 -03001404
David Vincze2d736ad2019-02-18 11:50:22 +01001405 /* TODO: Perhaps verify the primary slot's signature again? */
David Brown17609d82017-05-05 09:41:34 -06001406
1407 return 0;
1408}
Fabio Utzig338a19f2018-12-03 08:37:08 -02001409#endif
Fabio Utzigba829042018-09-18 08:29:34 -03001410
Christopher Collinsa1c12042019-05-23 14:00:28 -07001411#if !defined(MCUBOOT_OVERWRITE_ONLY)
Fabio Utzigba829042018-09-18 08:29:34 -03001412/**
1413 * Swaps the two images in flash. If a prior copy operation was interrupted
1414 * by a system reset, this function completes that operation.
1415 *
1416 * @param bs The current boot status. This function reads
1417 * this struct to determine if it is resuming
1418 * an interrupted swap operation. This
1419 * function writes the updated status to this
1420 * function on return.
1421 *
1422 * @return 0 on success; nonzero on failure.
1423 */
Christopher Collins92ea77f2016-12-12 15:59:26 -08001424static int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001425boot_swap_image(struct boot_loader_state *state, struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -08001426{
Fabio Utzig2473ac02017-05-02 12:45:02 -03001427 struct image_header *hdr;
Fabio Utzigba829042018-09-18 08:29:34 -03001428#ifdef MCUBOOT_ENC_IMAGES
1429 const struct flash_area *fap;
1430 uint8_t slot;
Fabio Utzigba829042018-09-18 08:29:34 -03001431#endif
Fabio Utzig2473ac02017-05-02 12:45:02 -03001432 uint32_t size;
1433 uint32_t copy_size;
Fabio Utzigb0f04732019-07-31 09:49:19 -03001434 uint8_t image_index;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001435 int rc = -1;
Fabio Utzig2473ac02017-05-02 12:45:02 -03001436
1437 /* FIXME: just do this if asked by user? */
1438
1439 size = copy_size = 0;
Fabio Utzig10ee6482019-08-01 12:04:52 -03001440 image_index = BOOT_CURR_IMG(state);
Fabio Utzig2473ac02017-05-02 12:45:02 -03001441
Fabio Utzig12d59162019-11-28 10:01:59 -03001442 if (boot_status_is_reset(bs)) {
Fabio Utzig46490722017-09-04 15:34:32 -03001443 /*
1444 * No swap ever happened, so need to find the largest image which
1445 * will be used to determine the amount of sectors to swap.
1446 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001447 hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
Fabio Utzig2473ac02017-05-02 12:45:02 -03001448 if (hdr->ih_magic == IMAGE_MAGIC) {
Fabio Utzigd638b172019-08-09 10:38:05 -03001449 rc = boot_read_image_size(state, BOOT_PRIMARY_SLOT, &copy_size);
David Brownf5b33d82017-09-01 10:58:27 -06001450 assert(rc == 0);
Fabio Utzig2473ac02017-05-02 12:45:02 -03001451 }
Fabio Utzig2473ac02017-05-02 12:45:02 -03001452
Fabio Utzigba829042018-09-18 08:29:34 -03001453#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig2fc80df2018-12-14 06:47:38 -02001454 if (IS_ENCRYPTED(hdr)) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001455 fap = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
Fabio Utzig4741c452019-12-19 15:32:41 -03001456 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001457 assert(rc >= 0);
1458
1459 if (rc == 0) {
Fabio Utzig4741c452019-12-19 15:32:41 -03001460 rc = boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001461 assert(rc == 0);
1462 } else {
1463 rc = 0;
1464 }
1465 } else {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001466 (void)memset(bs->enckey[0], BOOT_UNINITIALIZED_KEY_FILL,
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001467 BOOT_ENC_KEY_ALIGN_SIZE);
Fabio Utzigba829042018-09-18 08:29:34 -03001468 }
1469#endif
1470
Fabio Utzig10ee6482019-08-01 12:04:52 -03001471 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
Fabio Utzig46490722017-09-04 15:34:32 -03001472 if (hdr->ih_magic == IMAGE_MAGIC) {
Fabio Utzigd638b172019-08-09 10:38:05 -03001473 rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &size);
Fabio Utzig46490722017-09-04 15:34:32 -03001474 assert(rc == 0);
1475 }
1476
Fabio Utzigba829042018-09-18 08:29:34 -03001477#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig10ee6482019-08-01 12:04:52 -03001478 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
Fabio Utzig2fc80df2018-12-14 06:47:38 -02001479 if (IS_ENCRYPTED(hdr)) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001480 fap = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
Fabio Utzig4741c452019-12-19 15:32:41 -03001481 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001482 assert(rc >= 0);
1483
1484 if (rc == 0) {
Fabio Utzig4741c452019-12-19 15:32:41 -03001485 rc = boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001486 assert(rc == 0);
1487 } else {
1488 rc = 0;
1489 }
1490 } else {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001491 (void)memset(bs->enckey[1], BOOT_UNINITIALIZED_KEY_FILL,
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001492 BOOT_ENC_KEY_ALIGN_SIZE);
Fabio Utzigba829042018-09-18 08:29:34 -03001493 }
1494#endif
1495
Fabio Utzig46490722017-09-04 15:34:32 -03001496 if (size > copy_size) {
1497 copy_size = size;
1498 }
1499
1500 bs->swap_size = copy_size;
1501 } else {
1502 /*
1503 * If a swap was under way, the swap_size should already be present
1504 * in the trailer...
1505 */
Fabio Utzigb0f04732019-07-31 09:49:19 -03001506 rc = boot_read_swap_size(image_index, &bs->swap_size);
Fabio Utzig46490722017-09-04 15:34:32 -03001507 assert(rc == 0);
1508
1509 copy_size = bs->swap_size;
Fabio Utzigba829042018-09-18 08:29:34 -03001510
1511#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig4741c452019-12-19 15:32:41 -03001512 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1513 rc = boot_read_enc_key(image_index, slot, bs);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001514 assert(0 == rc);
Fabio Utzigba829042018-09-18 08:29:34 -03001515
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001516 /* Set only an initialized key */
1517 if (!bootutil_buffer_is_filled(bs->enckey[slot],
1518 BOOT_UNINITIALIZED_KEY_FILL,
1519 BOOT_ENC_KEY_SIZE)) {
1520 rc = boot_enc_set_key(BOOT_CURR_ENC(state), slot, bs);
1521 assert(rc == 0);
Fabio Utzigba829042018-09-18 08:29:34 -03001522 }
1523 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001524#if defined(MCUBOOT_SAVE_ENC_IV)
1525 rc = boot_read_iv(image_index, 1, state->enc[image_index][1].aes_iv);
1526 assert(rc == 0);
1527#endif
Fabio Utzigba829042018-09-18 08:29:34 -03001528#endif
Fabio Utzig2473ac02017-05-02 12:45:02 -03001529 }
1530
Fabio Utzig12d59162019-11-28 10:01:59 -03001531 swap_run(state, bs, copy_size);
Christopher Collins92ea77f2016-12-12 15:59:26 -08001532
David Vincze2d736ad2019-02-18 11:50:22 +01001533#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
Fabio Utzig12d59162019-11-28 10:01:59 -03001534 extern int boot_status_fails;
Fabio Utziga0e1cce2017-11-23 20:04:01 -02001535 if (boot_status_fails > 0) {
Christopher Collins2c88e692019-05-22 15:10:14 -07001536 BOOT_LOG_WRN("%d status write fails performing the swap",
1537 boot_status_fails);
Fabio Utziga0e1cce2017-11-23 20:04:01 -02001538 }
1539#endif
1540
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001541 return rc;
Christopher Collins92ea77f2016-12-12 15:59:26 -08001542}
David Brown17609d82017-05-05 09:41:34 -06001543#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -08001544
David Vinczee32483f2019-06-13 10:46:24 +02001545#if (BOOT_IMAGE_NUMBER > 1)
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001546#if defined(MCUBOOT_DEPENDENCY_CHECK)
David Vinczee32483f2019-06-13 10:46:24 +02001547/**
1548 * Check the image dependency whether it is satisfied and modify
1549 * the swap type if necessary.
1550 *
1551 * @param dep Image dependency which has to be verified.
1552 *
1553 * @return 0 on success; nonzero on failure.
1554 */
1555static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001556boot_verify_slot_dependency_flash(struct boot_loader_state *state, struct image_dependency *dep)
David Vinczee32483f2019-06-13 10:46:24 +02001557{
1558 struct image_version *dep_version;
1559 size_t dep_slot;
1560 int rc;
David Browne6ab34c2019-09-03 12:24:21 -06001561 uint8_t swap_type;
David Vinczee32483f2019-06-13 10:46:24 +02001562
1563 /* Determine the source of the image which is the subject of
1564 * the dependency and get it's version. */
David Browne6ab34c2019-09-03 12:24:21 -06001565 swap_type = state->swap_type[dep->image_id];
Barry Solomon04075532020-03-18 09:33:32 -04001566 dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SECONDARY_SLOT
1567 : BOOT_PRIMARY_SLOT;
Fabio Utzig10ee6482019-08-01 12:04:52 -03001568 dep_version = &state->imgs[dep->image_id][dep_slot].hdr.ih_ver;
David Vinczee32483f2019-06-13 10:46:24 +02001569
David Vincze8b0b6372020-05-20 19:54:44 +02001570 rc = boot_version_cmp(dep_version, &dep->image_min_version);
1571 if (rc < 0) {
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001572#ifndef MCUBOOT_OVERWRITE_ONLY
David Vinczee32483f2019-06-13 10:46:24 +02001573 /* Dependency not satisfied.
1574 * Modify the swap type to decrease the version number of the image
1575 * (which will be located in the primary slot after the boot process),
1576 * consequently the number of unsatisfied dependencies will be
1577 * decreased or remain the same.
1578 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001579 switch (BOOT_SWAP_TYPE(state)) {
David Vinczee32483f2019-06-13 10:46:24 +02001580 case BOOT_SWAP_TYPE_TEST:
1581 case BOOT_SWAP_TYPE_PERM:
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001582 /* BOOT_SWAP_TYPE_NONE has been changed to BOOT_SWAP_TYPE_FAIL to avoid
1583 * reversion again after device reset */
1584 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_FAIL;
David Vinczee32483f2019-06-13 10:46:24 +02001585 break;
1586 case BOOT_SWAP_TYPE_NONE:
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001587 BOOT_LOG_DBG("Dependency is unsatisfied. Slot will be reverted.");
Fabio Utzig10ee6482019-08-01 12:04:52 -03001588 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT;
David Vinczee32483f2019-06-13 10:46:24 +02001589 break;
1590 default:
1591 break;
1592 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001593#else
1594 BOOT_LOG_DBG("Dependency is unsatisfied.");
1595#endif
David Vincze8b0b6372020-05-20 19:54:44 +02001596 } else {
1597 /* Dependency satisfied. */
1598 rc = 0;
David Vinczee32483f2019-06-13 10:46:24 +02001599 }
1600
1601 return rc;
1602}
1603
1604/**
1605 * Read all dependency TLVs of an image from the flash and verify
1606 * one after another to see if they are all satisfied.
1607 *
1608 * @param slot Image slot number.
1609 *
1610 * @return 0 on success; nonzero on failure.
1611 */
1612static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001613boot_verify_slot_dependencies_flash(struct boot_loader_state *state, uint32_t slot)
David Vinczee32483f2019-06-13 10:46:24 +02001614{
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001615 const struct flash_area *fap = NULL;
Fabio Utzig61fd8882019-09-14 20:00:20 -03001616 struct image_tlv_iter it;
David Vinczee32483f2019-06-13 10:46:24 +02001617 struct image_dependency dep;
1618 uint32_t off;
Fabio Utzig61fd8882019-09-14 20:00:20 -03001619 uint16_t len;
Fabio Utzigb0f04732019-07-31 09:49:19 -03001620 int area_id;
David Vinczee32483f2019-06-13 10:46:24 +02001621 int rc;
1622
Fabio Utzig10ee6482019-08-01 12:04:52 -03001623 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
Fabio Utzigb0f04732019-07-31 09:49:19 -03001624 rc = flash_area_open(area_id, &fap);
David Vinczee32483f2019-06-13 10:46:24 +02001625 if (rc != 0) {
1626 rc = BOOT_EFLASH;
1627 goto done;
1628 }
1629
Fabio Utzig61fd8882019-09-14 20:00:20 -03001630 rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, slot), fap,
1631 IMAGE_TLV_DEPENDENCY, true);
David Vinczee32483f2019-06-13 10:46:24 +02001632 if (rc != 0) {
David Vinczee32483f2019-06-13 10:46:24 +02001633 goto done;
1634 }
1635
Fabio Utzig61fd8882019-09-14 20:00:20 -03001636 while (true) {
1637 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
1638 if (rc < 0) {
1639 return -1;
1640 } else if (rc > 0) {
1641 rc = 0;
David Vinczee32483f2019-06-13 10:46:24 +02001642 break;
1643 }
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001644 else
1645 {
1646 /* acc. to MISRA R.15.7 */
1647 }
Fabio Utzig61fd8882019-09-14 20:00:20 -03001648
1649 if (len != sizeof(dep)) {
1650 rc = BOOT_EBADIMAGE;
1651 goto done;
1652 }
1653
1654 rc = flash_area_read(fap, off, &dep, len);
1655 if (rc != 0) {
1656 rc = BOOT_EFLASH;
1657 goto done;
1658 }
1659
1660 if (dep.image_id >= BOOT_IMAGE_NUMBER) {
1661 rc = BOOT_EBADARGS;
1662 goto done;
1663 }
1664
1665 /* Verify dependency and modify the swap type if not satisfied. */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001666 rc = boot_verify_slot_dependency_flash(state, &dep);
Fabio Utzig61fd8882019-09-14 20:00:20 -03001667 if (rc != 0) {
1668 /* Dependency not satisfied. */
1669 goto done;
1670 }
David Vinczee32483f2019-06-13 10:46:24 +02001671 }
1672
1673done:
1674 flash_area_close(fap);
1675 return rc;
1676}
1677
1678/**
David Vinczee32483f2019-06-13 10:46:24 +02001679 * Iterate over all the images and verify whether the image dependencies in the
1680 * TLV area are all satisfied and update the related swap type if necessary.
1681 */
Fabio Utzig298913b2019-08-28 11:22:45 -03001682static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001683boot_verify_dependencies_flash(struct boot_loader_state *state)
David Vinczee32483f2019-06-13 10:46:24 +02001684{
Erik Johnson49063752020-02-06 09:59:31 -06001685 int rc = -1;
Fabio Utzig298913b2019-08-28 11:22:45 -03001686 uint8_t slot;
David Vinczee32483f2019-06-13 10:46:24 +02001687
Fabio Utzig10ee6482019-08-01 12:04:52 -03001688 BOOT_CURR_IMG(state) = 0;
1689 while (BOOT_CURR_IMG(state) < BOOT_IMAGE_NUMBER) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001690 if (state->img_mask[BOOT_CURR_IMG(state)]) {
1691 BOOT_CURR_IMG(state)++;
1692 continue;
1693 }
Fabio Utzig298913b2019-08-28 11:22:45 -03001694 if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE &&
1695 BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_FAIL) {
1696 slot = BOOT_SECONDARY_SLOT;
1697 } else {
1698 slot = BOOT_PRIMARY_SLOT;
1699 }
1700
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03001701 rc = boot_verify_slot_dependencies_flash(state, slot);
Fabio Utzigabec0732019-07-31 08:40:22 -03001702 if (rc == 0) {
David Vinczee32483f2019-06-13 10:46:24 +02001703 /* All dependencies've been satisfied, continue with next image. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001704 BOOT_CURR_IMG(state)++;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001705 } else {
1706#if (USE_SHARED_SLOT == 1)
1707 /* Disable an upgrading of this image.*/
1708 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
1709 BOOT_CURR_IMG(state)++;
1710#else
Fabio Utzig298913b2019-08-28 11:22:45 -03001711 /* Cannot upgrade due to non-met dependencies, so disable all
1712 * image upgrades.
1713 */
1714 for (int idx = 0; idx < BOOT_IMAGE_NUMBER; idx++) {
1715 BOOT_CURR_IMG(state) = idx;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001716 /*When dependency is not satisfied, the boot_verify_slot_dependencies_flash
1717 changes swap type to BOOT_SWAP_TYPE_REVERT to have ability of reversion of a
1718 dependent image. That's why BOOT_SWAP_TYPE_REVERT must not be changed to
1719 BOOT_SWAP_TYPE_NONE */
1720 if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_REVERT) {
1721 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
1722 }
Fabio Utzig298913b2019-08-28 11:22:45 -03001723 }
1724 break;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001725#endif /* (USE_SHARED_SLOT == 1) */
David Vinczee32483f2019-06-13 10:46:24 +02001726 }
1727 }
Fabio Utzig298913b2019-08-28 11:22:45 -03001728 return rc;
David Vinczee32483f2019-06-13 10:46:24 +02001729}
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001730#endif /* (MCUBOOT_DEPENDENCY_CHECK) */
David Vinczee32483f2019-06-13 10:46:24 +02001731#endif /* (BOOT_IMAGE_NUMBER > 1) */
1732
Christopher Collins92ea77f2016-12-12 15:59:26 -08001733/**
David Vinczeba3bd602019-06-17 16:01:43 +02001734 * Performs a clean (not aborted) image update.
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001735 *
David Vinczeba3bd602019-06-17 16:01:43 +02001736 * @param bs The current boot status.
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001737 *
1738 * @return 0 on success; nonzero on failure.
1739 */
1740static int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001741boot_perform_update(struct boot_loader_state *state, struct boot_status *bs)
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001742{
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001743 int rc;
Fabio Utzig10ee6482019-08-01 12:04:52 -03001744#ifndef MCUBOOT_OVERWRITE_ONLY
1745 uint8_t swap_type;
1746#endif
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001747
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001748 BOOT_LOG_DBG("> boot_perform_update: bs->idx = %" PRIu32, bs->idx);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001749
David Vinczeba3bd602019-06-17 16:01:43 +02001750 /* At this point there are no aborted swaps. */
1751#if defined(MCUBOOT_OVERWRITE_ONLY)
Fabio Utzig10ee6482019-08-01 12:04:52 -03001752 rc = boot_copy_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001753#elif defined(MCUBOOT_BOOTSTRAP)
1754 /* Check if the image update was triggered by a bad image in the
1755 * primary slot (the validity of the image in the secondary slot had
1756 * already been checked).
1757 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01001758 fih_int fih_rc = FIH_FAILURE;
1759 rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT);
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02001760
1761#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
Raef Colese8fe6cf2020-05-26 13:07:40 +01001762 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, bs);
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02001763#else
1764 fih_rc = FIH_SUCCESS;
1765#endif
1766
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02001767 if (rc == 0 || !fih_eq(fih_rc, FIH_SUCCESS)) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001768 /* Initialize swap status partition for primary slot, because
1769 * in swap mode it is needed to properly complete copying the image
1770 * to the primary slot.
1771 */
1772 const struct flash_area *fap_primary_slot = NULL;
1773
1774 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state)),
1775 &fap_primary_slot);
1776 assert(rc == 0);
1777
1778 rc = swap_status_init(state, fap_primary_slot, bs);
1779 assert(rc == 0);
1780
1781 flash_area_close(fap_primary_slot);
1782
Fabio Utzig10ee6482019-08-01 12:04:52 -03001783 rc = boot_copy_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001784 } else {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001785 rc = boot_swap_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001786 }
1787#else
Fabio Utzig10ee6482019-08-01 12:04:52 -03001788 rc = boot_swap_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001789#endif
Fabio Utzig7ebb7c22017-04-26 10:59:31 -03001790 assert(rc == 0);
David Vinczeba3bd602019-06-17 16:01:43 +02001791
1792#ifndef MCUBOOT_OVERWRITE_ONLY
1793 /* The following state needs image_ok be explicitly set after the
1794 * swap was finished to avoid a new revert.
1795 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001796 swap_type = BOOT_SWAP_TYPE(state);
1797 if (swap_type == BOOT_SWAP_TYPE_REVERT ||
1798 swap_type == BOOT_SWAP_TYPE_PERM) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001799 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001800 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001801 BOOT_SWAP_TYPE(state) = swap_type = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001802 }
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001803 }
1804
David Vinczec3084132020-02-18 14:50:47 +01001805#ifdef MCUBOOT_HW_ROLLBACK_PROT
1806 if (swap_type == BOOT_SWAP_TYPE_PERM) {
1807 /* Update the stored security counter with the new image's security
1808 * counter value. The primary slot holds the new image at this point,
1809 * but the secondary slot's image header must be passed since image
1810 * headers in the boot_data structure have not been updated yet.
1811 *
1812 * In case of a permanent image swap mcuboot will never attempt to
1813 * revert the images on the next reboot. Therefore, the security
1814 * counter must be increased right after the image upgrade.
1815 */
1816 rc = boot_update_security_counter(
1817 BOOT_CURR_IMG(state),
1818 BOOT_PRIMARY_SLOT,
1819 boot_img_hdr(state, BOOT_SECONDARY_SLOT));
1820 if (rc != 0) {
1821 BOOT_LOG_ERR("Security counter update failed after "
1822 "image upgrade.");
1823 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1824 }
1825 }
1826#endif /* MCUBOOT_HW_ROLLBACK_PROT */
1827
Fabio Utzige575b0b2019-09-11 12:34:23 -03001828 if (BOOT_IS_UPGRADE(swap_type)) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001829 rc = swap_set_copy_done(BOOT_CURR_IMG(state));
INFINEON\DovhalAe54c0a32024-07-31 22:45:38 +03001830#if defined(MCUBOOT_ENC_IMAGES_SMIF)
1831 rc |= swap_clear_magic_upgrade(BOOT_CURR_IMG(state));
1832#endif
David Vinczeba3bd602019-06-17 16:01:43 +02001833 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001834 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
Christopher Collinsa1c12042019-05-23 14:00:28 -07001835 }
David Vinczeba3bd602019-06-17 16:01:43 +02001836 }
1837#endif /* !MCUBOOT_OVERWRITE_ONLY */
Fabio Utzig338a19f2018-12-03 08:37:08 -02001838
David Vinczeba3bd602019-06-17 16:01:43 +02001839 return rc;
1840}
1841
1842/**
1843 * Completes a previously aborted image swap.
1844 *
1845 * @param bs The current boot status.
1846 *
1847 * @return 0 on success; nonzero on failure.
1848 */
1849#if !defined(MCUBOOT_OVERWRITE_ONLY)
1850static int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001851boot_complete_partial_swap(struct boot_loader_state *state,
1852 struct boot_status *bs)
David Vinczeba3bd602019-06-17 16:01:43 +02001853{
1854 int rc;
1855
1856 /* Determine the type of swap operation being resumed from the
1857 * `swap-type` trailer field.
1858 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001859 rc = boot_swap_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001860 assert(rc == 0);
1861
Fabio Utzig10ee6482019-08-01 12:04:52 -03001862 BOOT_SWAP_TYPE(state) = bs->swap_type;
David Vinczeba3bd602019-06-17 16:01:43 +02001863
1864 /* The following states need image_ok be explicitly set after the
1865 * swap was finished to avoid a new revert.
1866 */
1867 if (bs->swap_type == BOOT_SWAP_TYPE_REVERT ||
1868 bs->swap_type == BOOT_SWAP_TYPE_PERM) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001869 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001870 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001871 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001872 }
1873 }
1874
Fabio Utzige575b0b2019-09-11 12:34:23 -03001875 if (BOOT_IS_UPGRADE(bs->swap_type)) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001876 rc = swap_set_copy_done(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001877 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001878 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001879 }
1880 }
1881
Fabio Utzig10ee6482019-08-01 12:04:52 -03001882 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
David Vinczeba3bd602019-06-17 16:01:43 +02001883 BOOT_LOG_ERR("panic!");
1884 assert(0);
1885
1886 /* Loop forever... */
1887 while (1) {}
1888 }
1889
1890 return rc;
1891}
1892#endif /* !MCUBOOT_OVERWRITE_ONLY */
1893
1894#if (BOOT_IMAGE_NUMBER > 1)
1895/**
1896 * Review the validity of previously determined swap types of other images.
1897 *
1898 * @param aborted_swap The current image upgrade is a
1899 * partial/aborted swap.
1900 */
1901static void
Fabio Utzig10ee6482019-08-01 12:04:52 -03001902boot_review_image_swap_types(struct boot_loader_state *state,
1903 bool aborted_swap)
David Vinczeba3bd602019-06-17 16:01:43 +02001904{
1905 /* In that case if we rebooted in the middle of an image upgrade process, we
1906 * must review the validity of swap types, that were previously determined
1907 * for other images. The image_ok flag had not been set before the reboot
1908 * for any of the updated images (only the copy_done flag) and thus falsely
1909 * the REVERT swap type has been determined for the previous images that had
1910 * been updated before the reboot.
1911 *
1912 * There are two separate scenarios that we have to deal with:
1913 *
1914 * 1. The reboot has happened during swapping an image:
1915 * The current image upgrade has been determined as a
1916 * partial/aborted swap.
1917 * 2. The reboot has happened between two separate image upgrades:
1918 * In this scenario we must check the swap type of the current image.
1919 * In those cases if it is NONE or REVERT we cannot certainly determine
1920 * the fact of a reboot. In a consistent state images must move in the
1921 * same direction or stay in place, e.g. in practice REVERT and TEST
1922 * swap types cannot be present at the same time. If the swap type of
1923 * the current image is either TEST, PERM or FAIL we must review the
1924 * already determined swap types of other images and set each false
1925 * REVERT swap types to NONE (these images had been successfully
1926 * updated before the system rebooted between two separate image
1927 * upgrades).
1928 */
1929
Fabio Utzig10ee6482019-08-01 12:04:52 -03001930 if (BOOT_CURR_IMG(state) == 0) {
David Vinczeba3bd602019-06-17 16:01:43 +02001931 /* Nothing to do */
1932 return;
1933 }
1934
1935 if (!aborted_swap) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001936 if ((BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) ||
1937 (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_REVERT)) {
David Vinczeba3bd602019-06-17 16:01:43 +02001938 /* Nothing to do */
1939 return;
1940 }
1941 }
1942
Fabio Utzig10ee6482019-08-01 12:04:52 -03001943 for (uint8_t i = 0; i < BOOT_CURR_IMG(state); i++) {
1944 if (state->swap_type[i] == BOOT_SWAP_TYPE_REVERT) {
1945 state->swap_type[i] = BOOT_SWAP_TYPE_NONE;
David Vinczeba3bd602019-06-17 16:01:43 +02001946 }
1947 }
1948}
1949#endif
1950
1951/**
1952 * Prepare image to be updated if required.
1953 *
1954 * Prepare image to be updated if required with completing an image swap
1955 * operation if one was aborted and/or determining the type of the
1956 * swap operation. In case of any error set the swap type to NONE.
1957 *
Fabio Utzig10ee6482019-08-01 12:04:52 -03001958 * @param state TODO
David Vinczeba3bd602019-06-17 16:01:43 +02001959 * @param bs Pointer where the read and possibly updated
1960 * boot status can be written to.
1961 */
1962static void
Fabio Utzig10ee6482019-08-01 12:04:52 -03001963boot_prepare_image_for_update(struct boot_loader_state *state,
1964 struct boot_status *bs)
David Vinczeba3bd602019-06-17 16:01:43 +02001965{
1966 int rc;
Raef Colese8fe6cf2020-05-26 13:07:40 +01001967 fih_int fih_rc = FIH_FAILURE;
David Vinczeba3bd602019-06-17 16:01:43 +02001968
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001969 BOOT_LOG_DBG("> boot_prepare_image_for_update: image = %u",
1970 (unsigned)BOOT_CURR_IMG(state));
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02001971
David Vinczeba3bd602019-06-17 16:01:43 +02001972 /* Determine the sector layout of the image slots and scratch area. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001973 rc = boot_read_sectors(state);
David Vinczeba3bd602019-06-17 16:01:43 +02001974 if (rc != 0) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001975 BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%u"
1976 " - too small?", (unsigned int) BOOT_MAX_IMG_SECTORS);
David Vinczeba3bd602019-06-17 16:01:43 +02001977 /* Unable to determine sector layout, continue with next image
1978 * if there is one.
1979 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001980 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001981 if (rc == BOOT_EFLASH)
1982 {
1983 /* Only return on error from the primary image flash */
1984 return;
1985 }
David Vinczeba3bd602019-06-17 16:01:43 +02001986 }
1987
1988 /* Attempt to read an image header from each slot. */
Fabio Utzig12d59162019-11-28 10:01:59 -03001989 rc = boot_read_image_headers(state, false, NULL);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001990 BOOT_LOG_DBG(" * Read an image (%u) header from each slot: rc = %d",
1991 (unsigned)BOOT_CURR_IMG(state), rc);
David Vinczeba3bd602019-06-17 16:01:43 +02001992 if (rc != 0) {
1993 /* Continue with next image if there is one. */
Fabio Utzigb0f04732019-07-31 09:49:19 -03001994 BOOT_LOG_WRN("Failed reading image headers; Image=%u",
Roman Okhrimenko977b3752022-03-31 14:40:48 +03001995 (unsigned)BOOT_CURR_IMG(state));
Fabio Utzig10ee6482019-08-01 12:04:52 -03001996 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
David Vinczeba3bd602019-06-17 16:01:43 +02001997 return;
1998 }
1999
2000 /* If the current image's slots aren't compatible, no swap is possible.
2001 * Just boot into primary slot.
2002 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002003 if (boot_slots_compatible(state)) {
Fabio Utzig12d59162019-11-28 10:01:59 -03002004 boot_status_reset(bs);
2005
2006#ifndef MCUBOOT_OVERWRITE_ONLY
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002007#ifdef MCUBOOT_SWAP_USING_STATUS
2008
2009 const struct flash_area *fap;
2010 uint32_t img_size = 0;
2011
2012 /* Check here if image firmware + tlvs in slot do not
2013 * overlap with last sector of slot. Last sector of slot
2014 * contains trailer of the image which needs to be
2015 * manupulated independently of other image parts.
2016 * If firmware overlaps with trailer sector it does not
2017 * make sense to move further since any attemps to perform
2018 * swap upgrade would lead to failure or unexpected behaviour
2019 */
2020
2021 for (uint32_t i = 0; i < BOOT_NUM_SLOTS; i++) {
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002022 if ((&state->imgs[BOOT_CURR_IMG(state)][i].hdr)->ih_magic == IMAGE_MAGIC) {
2023 rc = boot_read_image_size(state, i, &img_size);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002024
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002025 if (rc == 0) {
2026 fap = BOOT_IMG(state, i).area;
2027 if (fap != NULL) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002028
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002029 uint32_t trailer_sector_off = (BOOT_WRITE_SZ(state)) * boot_img_num_sectors(state, i) - BOOT_WRITE_SZ(state);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002030
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002031 BOOT_LOG_DBG("Slot %u firmware + tlvs size = %u, "
2032 "slot size = %u, write_size = %u, "
2033 "img sectors num = %u, "
2034 "write_size * sect_num - write_size = %u",
2035 i , img_size, fap->fa_size, BOOT_WRITE_SZ(state),
2036 (uint32_t)boot_img_num_sectors(state, i), trailer_sector_off);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002037
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002038 if (img_size > trailer_sector_off) {
2039 BOOT_LOG_ERR("Firmware + tlvs in slot %u overlaps with last sector, which contains trailer, erasing this image", i);
2040 rc = flash_area_erase(fap, 0, flash_area_get_size(fap));
2041 }
2042 else {
2043 /* image firmware + tlvs do not overlap with last sector of slot, continue */
2044 }
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002045 }
2046 }
2047 }
2048 }
2049#endif /* MCUBOOT_SWAP_USING_STATUS */
2050
Fabio Utzig12d59162019-11-28 10:01:59 -03002051 rc = swap_read_status(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02002052 if (rc != 0) {
2053 BOOT_LOG_WRN("Failed reading boot status; Image=%u",
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002054 (unsigned)BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02002055 /* Continue with next image if there is one. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002056 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
David Vinczeba3bd602019-06-17 16:01:43 +02002057 return;
2058 }
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002059#endif /* ifndef MCUBOOT_OVERWRITE_ONLY */
David Vinczeba3bd602019-06-17 16:01:43 +02002060
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02002061#if defined (MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH)
Fabio Utzig74aef312019-11-28 11:05:34 -03002062 /*
2063 * Must re-read image headers because the boot status might
2064 * have been updated in the previous function call.
2065 */
2066 rc = boot_read_image_headers(state, !boot_status_is_reset(bs), bs);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002067 BOOT_LOG_DBG(" * re-read image(%u) headers: rc = %d.",
2068 (unsigned)BOOT_CURR_IMG(state), rc);
Fabio Utzig32afe852020-10-04 10:36:02 -03002069#ifdef MCUBOOT_BOOTSTRAP
2070 /* When bootstrapping it's OK to not have image magic in the primary slot */
2071 if (rc != 0 && (BOOT_CURR_IMG(state) != BOOT_PRIMARY_SLOT ||
2072 boot_check_header_erased(state, BOOT_PRIMARY_SLOT) != 0)) {
2073#else
Fabio Utzig74aef312019-11-28 11:05:34 -03002074 if (rc != 0) {
Fabio Utzig32afe852020-10-04 10:36:02 -03002075#endif
Fabio Utzig74aef312019-11-28 11:05:34 -03002076 /* Continue with next image if there is one. */
2077 BOOT_LOG_WRN("Failed reading image headers; Image=%u",
2078 BOOT_CURR_IMG(state));
2079 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2080 return;
2081 }
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002082#endif /* (MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH) */
Fabio Utzig74aef312019-11-28 11:05:34 -03002083
David Vinczeba3bd602019-06-17 16:01:43 +02002084 /* Determine if we rebooted in the middle of an image swap
2085 * operation. If a partial swap was detected, complete it.
2086 */
Fabio Utzig12d59162019-11-28 10:01:59 -03002087 if (!boot_status_is_reset(bs)) {
David Vinczeba3bd602019-06-17 16:01:43 +02002088
2089#if (BOOT_IMAGE_NUMBER > 1)
Fabio Utzig10ee6482019-08-01 12:04:52 -03002090 boot_review_image_swap_types(state, true);
David Vinczeba3bd602019-06-17 16:01:43 +02002091#endif
2092
2093#ifdef MCUBOOT_OVERWRITE_ONLY
2094 /* Should never arrive here, overwrite-only mode has
2095 * no swap state.
2096 */
2097 assert(0);
2098#else
2099 /* Determine the type of swap operation being resumed from the
2100 * `swap-type` trailer field.
2101 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002102 rc = boot_complete_partial_swap(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02002103 assert(rc == 0);
2104#endif
2105 /* Attempt to read an image header from each slot. Ensure that
2106 * image headers in slots are aligned with headers in boot_data.
2107 */
Fabio Utzig12d59162019-11-28 10:01:59 -03002108 rc = boot_read_image_headers(state, false, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02002109 assert(rc == 0);
2110
2111 /* Swap has finished set to NONE */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002112 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
David Vinczeba3bd602019-06-17 16:01:43 +02002113 } else {
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02002114 BOOT_LOG_DBG(" * There was no partial swap, determine swap type.");
2115
David Vinczeba3bd602019-06-17 16:01:43 +02002116 /* There was no partial swap, determine swap type. */
2117 if (bs->swap_type == BOOT_SWAP_TYPE_NONE) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03002118 BOOT_SWAP_TYPE(state) = boot_validated_swap_type(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02002119 } else {
Raef Colese8fe6cf2020-05-26 13:07:40 +01002120 FIH_CALL(boot_validate_slot, fih_rc,
2121 state, BOOT_SECONDARY_SLOT, bs);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002122 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
Raef Colese8fe6cf2020-05-26 13:07:40 +01002123 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_FAIL;
2124 } else {
2125 BOOT_SWAP_TYPE(state) = bs->swap_type;
2126 }
David Vinczeba3bd602019-06-17 16:01:43 +02002127 }
2128
2129#if (BOOT_IMAGE_NUMBER > 1)
Fabio Utzig10ee6482019-08-01 12:04:52 -03002130 boot_review_image_swap_types(state, false);
David Vinczeba3bd602019-06-17 16:01:43 +02002131#endif
2132
2133#ifdef MCUBOOT_BOOTSTRAP
Fabio Utzig10ee6482019-08-01 12:04:52 -03002134 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
David Vinczeba3bd602019-06-17 16:01:43 +02002135 /* Header checks are done first because they are
2136 * inexpensive. Since overwrite-only copies starting from
2137 * offset 0, if interrupted, it might leave a valid header
2138 * magic, so also run validation on the primary slot to be
2139 * sure it's not OK.
2140 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01002141 rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT);
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002142#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
Raef Colese8fe6cf2020-05-26 13:07:40 +01002143 FIH_CALL(boot_validate_slot, fih_rc,
2144 state, BOOT_PRIMARY_SLOT, bs);
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002145#else
2146 fih_rc = FIH_SUCCESS;
2147#endif
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002148 if (rc == 0 || !fih_eq(fih_rc, FIH_SUCCESS)) {
Raef Colese8fe6cf2020-05-26 13:07:40 +01002149
Fabio Utzig3d77c952020-10-04 10:23:17 -03002150 rc = (boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_magic == IMAGE_MAGIC) ? 1: 0;
Raef Colese8fe6cf2020-05-26 13:07:40 +01002151 FIH_CALL(boot_validate_slot, fih_rc,
2152 state, BOOT_SECONDARY_SLOT, bs);
2153
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002154 if (rc == 1 && fih_eq(fih_rc, FIH_SUCCESS)) {
David Vinczeba3bd602019-06-17 16:01:43 +02002155 /* Set swap type to REVERT to overwrite the primary
2156 * slot with the image contained in secondary slot
2157 * and to trigger the explicit setting of the
2158 * image_ok flag.
2159 */
Fabio Utzig59b63e52019-09-10 12:22:35 -03002160 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT;
David Vinczeba3bd602019-06-17 16:01:43 +02002161 }
Fabio Utzig338a19f2018-12-03 08:37:08 -02002162 }
2163 }
Fabio Utzig338a19f2018-12-03 08:37:08 -02002164#endif
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08002165 }
David Vinczeba3bd602019-06-17 16:01:43 +02002166 } else {
2167 /* In that case if slots are not compatible. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002168 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08002169 }
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02002170 BOOT_LOG_DBG("< boot_prepare_image_for_update");
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08002171}
2172
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002173/**
2174 * Updates the security counter for the current image.
2175 *
2176 * @param state Boot loader status information.
2177 *
2178 * @return 0 on success; nonzero on failure.
2179 */
2180static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002181boot_update_hw_rollback_protection_flash(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002182{
2183#ifdef MCUBOOT_HW_ROLLBACK_PROT
2184 int rc;
2185
2186 /* Update the stored security counter with the active image's security
2187 * counter value. It will only be updated if the new security counter is
2188 * greater than the stored value.
2189 *
2190 * In case of a successful image swapping when the swap type is TEST the
2191 * security counter can be increased only after a reset, when the swap
2192 * type is NONE and the image has marked itself "OK" (the image_ok flag
2193 * has been set). This way a "revert" can be performed when it's
2194 * necessary.
2195 */
2196 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
2197 rc = boot_update_security_counter(
2198 BOOT_CURR_IMG(state),
2199 BOOT_PRIMARY_SLOT,
2200 boot_img_hdr(state, BOOT_PRIMARY_SLOT));
2201 if (rc != 0) {
2202 BOOT_LOG_ERR("Security counter update failed after image "
2203 "validation.");
2204 return rc;
2205 }
2206 }
2207
2208 return 0;
2209
2210#else /* MCUBOOT_HW_ROLLBACK_PROT */
2211 (void) (state);
2212
2213 return 0;
2214#endif
2215}
2216
Raef Colese8fe6cf2020-05-26 13:07:40 +01002217fih_int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002218context_boot_go_flash(struct boot_loader_state *state, struct boot_rsp *rsp)
Christopher Collins92ea77f2016-12-12 15:59:26 -08002219{
Marti Bolivar84898652017-06-13 17:20:22 -04002220 size_t slot;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002221 struct boot_status bs = {0};
David Vincze9015a5d2020-05-18 14:43:11 +02002222 int rc = -1;
Raef Colese8fe6cf2020-05-26 13:07:40 +01002223 fih_int fih_rc = FIH_FAILURE;
Marti Bolivarc0b47912017-06-13 17:18:09 -04002224 int fa_id;
Fabio Utzigb0f04732019-07-31 09:49:19 -03002225 int image_index;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002226
2227 /* The array of slot sectors are defined here (as opposed to file scope) so
2228 * that they don't get allocated for non-boot-loader apps. This is
2229 * necessary because the gcc option "-fdata-sections" doesn't seem to have
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08002230 * any effect in older gcc versions (e.g., 4.8.4).
Christopher Collins92ea77f2016-12-12 15:59:26 -08002231 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002232 TARGET_STATIC boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
2233 TARGET_STATIC boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
Fabio Utzig12d59162019-11-28 10:01:59 -03002234#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -03002235 TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS];
Fabio Utzig12d59162019-11-28 10:01:59 -03002236#endif
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02002237#if MCUBOOT_SWAP_USING_STATUS
2238 TARGET_STATIC boot_sector_t status_sectors[BOOT_MAX_SWAP_STATUS_SECTORS];
2239#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -08002240
David Vinczeba3bd602019-06-17 16:01:43 +02002241 /* Iterate over all the images. By the end of the loop the swap type has
2242 * to be determined for each image and all aborted swaps have to be
2243 * completed.
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08002244 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002245 IMAGES_ITER(BOOT_CURR_IMG(state)) {
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002246#if !defined(MCUBOOT_DEPENDENCY_CHECK)
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002247#if BOOT_IMAGE_NUMBER > 1
2248 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2249 continue;
2250 }
2251#endif
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002252#endif
David Vinczeba3bd602019-06-17 16:01:43 +02002253#if defined(MCUBOOT_ENC_IMAGES) && (BOOT_IMAGE_NUMBER > 1)
2254 /* The keys used for encryption may no longer be valid (could belong to
2255 * another images). Therefore, mark them as invalid to force their reload
2256 * by boot_enc_load().
Fabio Utzigdb5bd3c2017-07-13 22:20:22 -03002257 */
Fabio Utzig1e4284b2019-08-23 11:55:27 -03002258 boot_enc_zeroize(BOOT_CURR_ENC(state));
David Brown554c52e2017-06-30 16:01:07 -06002259#endif
2260
Fabio Utzig10ee6482019-08-01 12:04:52 -03002261 image_index = BOOT_CURR_IMG(state);
Fabio Utzigb0f04732019-07-31 09:49:19 -03002262
Fabio Utzig10ee6482019-08-01 12:04:52 -03002263 BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
Fabio Utzigb0f04732019-07-31 09:49:19 -03002264 primary_slot_sectors[image_index];
Fabio Utzig10ee6482019-08-01 12:04:52 -03002265 BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
Fabio Utzigb0f04732019-07-31 09:49:19 -03002266 secondary_slot_sectors[image_index];
Fabio Utzig12d59162019-11-28 10:01:59 -03002267#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -03002268 state->scratch.sectors = scratch_sectors;
Fabio Utzig12d59162019-11-28 10:01:59 -03002269#endif
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02002270#if MCUBOOT_SWAP_USING_STATUS
2271 state->status.sectors = status_sectors;
2272#endif
David Vinczeba3bd602019-06-17 16:01:43 +02002273
2274 /* Open primary and secondary image areas for the duration
2275 * of this call.
2276 */
2277 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
Fabio Utzigb0f04732019-07-31 09:49:19 -03002278 fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
Fabio Utzig10ee6482019-08-01 12:04:52 -03002279 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
David Vinczeba3bd602019-06-17 16:01:43 +02002280 assert(rc == 0);
2281 }
Fabio Utzig12d59162019-11-28 10:01:59 -03002282#if MCUBOOT_SWAP_USING_SCRATCH
David Vinczeba3bd602019-06-17 16:01:43 +02002283 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
Fabio Utzig10ee6482019-08-01 12:04:52 -03002284 &BOOT_SCRATCH_AREA(state));
David Vinczeba3bd602019-06-17 16:01:43 +02002285 assert(rc == 0);
Fabio Utzig12d59162019-11-28 10:01:59 -03002286#endif
David Vinczeba3bd602019-06-17 16:01:43 +02002287
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02002288 BOOT_LOG_DBG(" * boot_prepare_image_for_update...");
David Vinczeba3bd602019-06-17 16:01:43 +02002289 /* Determine swap type and complete swap if it has been aborted. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002290 boot_prepare_image_for_update(state, &bs);
Fabio Utzig298913b2019-08-28 11:22:45 -03002291
David Vinczeba3bd602019-06-17 16:01:43 +02002292 }
2293
David Vinczee32483f2019-06-13 10:46:24 +02002294#if (BOOT_IMAGE_NUMBER > 1)
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002295#if defined(MCUBOOT_DEPENDENCY_CHECK)
Fabio Utzig298913b2019-08-28 11:22:45 -03002296 /* Iterate over all the images and verify whether the image dependencies
2297 * are all satisfied and update swap type if necessary.
2298 */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002299 rc = boot_verify_dependencies_flash(state);
David Vincze8b0b6372020-05-20 19:54:44 +02002300 if (rc != 0) {
Fabio Utzig298913b2019-08-28 11:22:45 -03002301 /*
2302 * It was impossible to upgrade because the expected dependency version
2303 * was not available. Here we already changed the swap_type so that
2304 * instead of asserting the bootloader, we continue and no upgrade is
2305 * performed.
2306 */
2307 rc = 0;
2308 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002309#endif /* (MCUBOOT_DEPENDENCY_CHECK) */
2310#endif /* (BOOT_IMAGE_NUMBER > 1) */
David Vinczee32483f2019-06-13 10:46:24 +02002311
David Vinczeba3bd602019-06-17 16:01:43 +02002312 /* Iterate over all the images. At this point there are no aborted swaps
2313 * and the swap types are determined for each image. By the end of the loop
2314 * all required update operations will have been finished.
2315 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002316 IMAGES_ITER(BOOT_CURR_IMG(state)) {
David Vinczeba3bd602019-06-17 16:01:43 +02002317#if (BOOT_IMAGE_NUMBER > 1)
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002318 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2319 continue;
2320 }
2321
David Vinczeba3bd602019-06-17 16:01:43 +02002322#ifdef MCUBOOT_ENC_IMAGES
2323 /* The keys used for encryption may no longer be valid (could belong to
2324 * another images). Therefore, mark them as invalid to force their reload
2325 * by boot_enc_load().
2326 */
Fabio Utzig1e4284b2019-08-23 11:55:27 -03002327 boot_enc_zeroize(BOOT_CURR_ENC(state));
David Vinczeba3bd602019-06-17 16:01:43 +02002328#endif /* MCUBOOT_ENC_IMAGES */
2329
2330 /* Indicate that swap is not aborted */
Fabio Utzig12d59162019-11-28 10:01:59 -03002331 boot_status_reset(&bs);
David Vinczeba3bd602019-06-17 16:01:43 +02002332#endif /* (BOOT_IMAGE_NUMBER > 1) */
2333
2334 /* Set the previously determined swap type */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002335 bs.swap_type = BOOT_SWAP_TYPE(state);
David Vinczeba3bd602019-06-17 16:01:43 +02002336
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002337 BOOT_LOG_DBG(" * process swap_type = %u", (unsigned)bs.swap_type);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +02002338
Fabio Utzig10ee6482019-08-01 12:04:52 -03002339 switch (BOOT_SWAP_TYPE(state)) {
David Vinczeba3bd602019-06-17 16:01:43 +02002340 case BOOT_SWAP_TYPE_NONE:
2341 break;
2342
2343 case BOOT_SWAP_TYPE_TEST: /* fallthrough */
2344 case BOOT_SWAP_TYPE_PERM: /* fallthrough */
2345 case BOOT_SWAP_TYPE_REVERT:
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002346 BOOT_LOG_DBG(" * perform update, mode %u...", (unsigned)bs.swap_type);
2347 rc = BOOT_HOOK_CALL(boot_perform_update_hook, BOOT_HOOK_REGULAR,
2348 BOOT_CURR_IMG(state), &(BOOT_IMG(state, 1).hdr),
2349 BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT));
2350 if (rc == BOOT_HOOK_REGULAR)
2351 {
2352 rc = boot_perform_update(state, &bs);
2353 }
David Vinczeba3bd602019-06-17 16:01:43 +02002354 assert(rc == 0);
2355 break;
2356
2357 case BOOT_SWAP_TYPE_FAIL:
2358 /* The image in secondary slot was invalid and is now erased. Ensure
2359 * we don't try to boot into it again on the next reboot. Do this by
2360 * pretending we just reverted back to primary slot.
2361 */
2362#ifndef MCUBOOT_OVERWRITE_ONLY
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002363 BOOT_LOG_DBG(" * update failed! Set image_ok manually for image(%u)",
2364 (unsigned)BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02002365 /* image_ok needs to be explicitly set to avoid a new revert. */
Fabio Utzig12d59162019-11-28 10:01:59 -03002366 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02002367 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03002368 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02002369 }
2370#endif /* !MCUBOOT_OVERWRITE_ONLY */
2371 break;
2372
2373 default:
Fabio Utzig10ee6482019-08-01 12:04:52 -03002374 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02002375 }
2376
Fabio Utzig10ee6482019-08-01 12:04:52 -03002377 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
David Vinczeba3bd602019-06-17 16:01:43 +02002378 BOOT_LOG_ERR("panic!");
2379 assert(0);
2380
2381 /* Loop forever... */
Raef Colese8fe6cf2020-05-26 13:07:40 +01002382 FIH_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02002383 }
2384 }
2385
2386 /* Iterate over all the images. At this point all required update operations
2387 * have finished. By the end of the loop each image in the primary slot will
2388 * have been re-validated.
2389 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002390 IMAGES_ITER(BOOT_CURR_IMG(state)) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002391#if BOOT_IMAGE_NUMBER > 1
2392 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2393 continue;
2394 }
2395#endif
Fabio Utzig10ee6482019-08-01 12:04:52 -03002396 if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE) {
David Vinczeba3bd602019-06-17 16:01:43 +02002397 /* Attempt to read an image header from each slot. Ensure that image
2398 * headers in slots are aligned with headers in boot_data.
2399 */
Fabio Utzig12d59162019-11-28 10:01:59 -03002400 rc = boot_read_image_headers(state, false, &bs);
David Vinczeba3bd602019-06-17 16:01:43 +02002401 if (rc != 0) {
2402 goto out;
2403 }
2404 /* Since headers were reloaded, it can be assumed we just performed
2405 * a swap or overwrite. Now the header info that should be used to
2406 * provide the data for the bootstrap, which previously was at
2407 * secondary slot, was updated to primary slot.
2408 */
2409 }
2410
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002411#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
2412#if defined(MCUBOOT_RAM_LOAD) /* to fix Rule 14.3 violation */
2413 if(IS_RAM_BOOTABLE(boot_img_hdr(state, BOOT_PRIMARY_SLOT)) == false) {
2414#endif /* defined(MCUBOOT_RAM_LOAD) */
2415 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, &bs);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002416 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002417 goto out;
2418 }
2419#if defined(MCUBOOT_RAM_LOAD) /* to fix Rule 14.3 violation */
David Vinczeba3bd602019-06-17 16:01:43 +02002420 }
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002421#endif /* defined(MCUBOOT_RAM_LOAD) */
David Vinczeba3bd602019-06-17 16:01:43 +02002422#else
2423 /* Even if we're not re-validating the primary slot, we could be booting
2424 * onto an empty flash chip. At least do a basic sanity check that
2425 * the magic number on the image is OK.
2426 */
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02002427
2428 BOOT_LOG_INF("Since boot image validation was skipped, "\
2429 "at least IMAGE_MAGIC should be checked");
2430
Fabio Utzig10ee6482019-08-01 12:04:52 -03002431 if (BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic != IMAGE_MAGIC) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002432 BOOT_LOG_ERR("bad image magic 0x%" PRIx32 "; Image=%u",
2433 BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic,
2434 (unsigned)BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02002435 rc = BOOT_EBADIMAGE;
2436 goto out;
2437 }
David Vinczec3084132020-02-18 14:50:47 +01002438#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
2439
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002440#ifdef MCUBOOT_ENC_IMAGES_XIP
2441 if (0 == BOOT_CURR_IMG(state)) {
2442 if (IS_ENCRYPTED(boot_img_hdr(state, BOOT_PRIMARY_SLOT)))
2443 {
2444 (void)memcpy((uint8_t*)rsp->xip_iv, BOOT_CURR_ENC(state)->aes_iv, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
2445 (void)memcpy((uint8_t*)rsp->xip_key, bs.enckey[BOOT_CURR_IMG(state)], BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE);
David Vinczec3084132020-02-18 14:50:47 +01002446 }
2447 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002448#endif /* MCUBOOT_ENC_IMAGES_XIP */
David Vincze1cf11b52020-03-24 07:51:09 +01002449
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002450 rc = boot_update_hw_rollback_protection_flash(state);
David Vincze1cf11b52020-03-24 07:51:09 +01002451 if (rc != 0) {
Raef Colese8fe6cf2020-05-26 13:07:40 +01002452 goto out;
David Vincze1cf11b52020-03-24 07:51:09 +01002453 }
David Vincze1cf11b52020-03-24 07:51:09 +01002454
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002455 if(IS_RAM_BOOTABLE(boot_img_hdr(state, BOOT_PRIMARY_SLOT)) == false) {
2456 rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT);
2457 if (rc != 0) {
2458 goto out;
2459 }
David Vincze1cf11b52020-03-24 07:51:09 +01002460 }
David Vinczeba3bd602019-06-17 16:01:43 +02002461 }
2462
Fabio Utzigb0f04732019-07-31 09:49:19 -03002463#if (BOOT_IMAGE_NUMBER > 1)
David Vinczeba3bd602019-06-17 16:01:43 +02002464 /* Always boot from the primary slot of Image 0. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002465 BOOT_CURR_IMG(state) = 0;
Fabio Utzigb0f04732019-07-31 09:49:19 -03002466#endif
Fabio Utzig298913b2019-08-28 11:22:45 -03002467
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002468 rsp->br_flash_dev_id = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT)->fa_device_id;
2469 rsp->br_image_off = boot_img_slot_off(state, BOOT_PRIMARY_SLOT);
2470 rsp->br_hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
Fabio Utzigf616c542019-12-19 15:23:32 -03002471 /*
2472 * Since the boot_status struct stores plaintext encryption keys, reset
2473 * them here to avoid the possibility of jumping into an image that could
2474 * easily recover them.
2475 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002476 (void)memset(&bs, 0, sizeof(struct boot_status));
Fabio Utzigf616c542019-12-19 15:23:32 -03002477
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002478 fill_rsp(state, rsp);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002479
Raef Colese8fe6cf2020-05-26 13:07:40 +01002480 fih_rc = FIH_SUCCESS;
Fabio Utzig298913b2019-08-28 11:22:45 -03002481out:
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002482 close_all_flash_areas(state);
Raef Colese8fe6cf2020-05-26 13:07:40 +01002483
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002484#ifdef MCUBOOT_ENC_IMAGES_XIP_MULTI
2485 SMIF_SET_CRYPTO_MODE(Enable);
2486#endif /* MCUBOOT_ENC_IMAGES_XIP_MULTI */
2487
Raef Colese8fe6cf2020-05-26 13:07:40 +01002488 if (rc) {
2489 fih_rc = fih_int_encode(rc);
2490 }
2491
2492 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002493}
2494
Raef Colese8fe6cf2020-05-26 13:07:40 +01002495fih_int
Christopher Collins92ea77f2016-12-12 15:59:26 -08002496split_go(int loader_slot, int split_slot, void **entry)
2497{
Marti Bolivarc50926f2017-06-14 09:35:40 -04002498 boot_sector_t *sectors;
Christopher Collins034a6202017-01-11 12:19:37 -08002499 uintptr_t entry_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002500 int loader_flash_id;
Marti Bolivarc0b47912017-06-13 17:18:09 -04002501 int split_flash_id;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002502 int rc;
Raef Colese8fe6cf2020-05-26 13:07:40 +01002503 fih_int fih_rc = FIH_FAILURE;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002504
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002505 if ((loader_slot < 0) || (split_slot < 0)) {
2506 FIH_RET(FIH_FAILURE);
2507 }
2508
Christopher Collins92ea77f2016-12-12 15:59:26 -08002509 sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors);
2510 if (sectors == NULL) {
Raef Colese8fe6cf2020-05-26 13:07:40 +01002511 FIH_RET(FIH_FAILURE);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002512 }
David Vinczeba3bd602019-06-17 16:01:43 +02002513 BOOT_IMG(&boot_data, loader_slot).sectors = sectors + 0;
2514 BOOT_IMG(&boot_data, split_slot).sectors = sectors + BOOT_MAX_IMG_SECTORS;
Marti Bolivarc0b47912017-06-13 17:18:09 -04002515
2516 loader_flash_id = flash_area_id_from_image_slot(loader_slot);
2517 rc = flash_area_open(loader_flash_id,
Alvaro Prieto63a2bdb2019-07-04 12:18:49 -07002518 &BOOT_IMG_AREA(&boot_data, loader_slot));
Marti Bolivarc0b47912017-06-13 17:18:09 -04002519 assert(rc == 0);
2520 split_flash_id = flash_area_id_from_image_slot(split_slot);
2521 rc = flash_area_open(split_flash_id,
2522 &BOOT_IMG_AREA(&boot_data, split_slot));
2523 assert(rc == 0);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002524
2525 /* Determine the sector layout of the image slots and scratch area. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002526 rc = boot_read_sectors(&boot_data);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002527 if (rc != 0) {
2528 rc = SPLIT_GO_ERR;
2529 goto done;
2530 }
2531
Fabio Utzig12d59162019-11-28 10:01:59 -03002532 rc = boot_read_image_headers(&boot_data, true, NULL);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002533 if (rc != 0) {
2534 goto done;
2535 }
2536
Christopher Collins92ea77f2016-12-12 15:59:26 -08002537 /* Don't check the bootable image flag because we could really call a
2538 * bootable or non-bootable image. Just validate that the image check
2539 * passes which is distinct from the normal check.
2540 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01002541 FIH_CALL(split_image_check, fih_rc,
2542 boot_img_hdr(&boot_data, split_slot),
2543 BOOT_IMG_AREA(&boot_data, split_slot),
2544 boot_img_hdr(&boot_data, loader_slot),
2545 BOOT_IMG_AREA(&boot_data, loader_slot));
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002546 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
Christopher Collins92ea77f2016-12-12 15:59:26 -08002547 goto done;
2548 }
2549
Marti Bolivarea088872017-06-12 17:10:49 -04002550 entry_val = boot_img_slot_off(&boot_data, split_slot) +
Marti Bolivarf804f622017-06-12 15:41:48 -04002551 boot_img_hdr(&boot_data, split_slot)->ih_hdr_size;
Christopher Collins034a6202017-01-11 12:19:37 -08002552 *entry = (void *) entry_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002553 rc = SPLIT_GO_OK;
2554
2555done:
Marti Bolivarc0b47912017-06-13 17:18:09 -04002556 flash_area_close(BOOT_IMG_AREA(&boot_data, split_slot));
2557 flash_area_close(BOOT_IMG_AREA(&boot_data, loader_slot));
Christopher Collins92ea77f2016-12-12 15:59:26 -08002558 free(sectors);
Raef Colese8fe6cf2020-05-26 13:07:40 +01002559
2560 if (rc) {
2561 fih_rc = fih_int_encode(rc);
2562 }
2563
2564 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002565}
David Vinczee574f2d2020-07-10 11:42:03 +02002566
David Vinczee574f2d2020-07-10 11:42:03 +02002567
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002568#if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002569
David Vinczee574f2d2020-07-10 11:42:03 +02002570/**
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002571 * Opens all flash areas and checks which contain an image with a valid header.
David Vinczee574f2d2020-07-10 11:42:03 +02002572 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002573 * @param state Boot loader status information.
David Vinczee574f2d2020-07-10 11:42:03 +02002574 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002575 * @return 0 on success; nonzero on failure.
2576 */
2577static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002578boot_get_slot_usage(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002579{
2580 uint32_t slot;
2581 int fa_id;
2582 int rc;
2583 struct image_header *hdr = NULL;
2584
2585 IMAGES_ITER(BOOT_CURR_IMG(state)) {
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002586#if !defined(MCUBOOT_DEPENDENCY_CHECK)
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002587#if BOOT_IMAGE_NUMBER > 1
2588 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2589 continue;
2590 }
2591#endif
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002592#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002593 /* Open all the slots */
2594 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2595 fa_id = flash_area_id_from_multi_image_slot(
2596 BOOT_CURR_IMG(state), slot);
2597 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
2598 assert(rc == 0);
2599 }
2600
2601 /* Attempt to read an image header from each slot. */
2602 rc = boot_read_image_headers(state, false, NULL);
2603 if (rc != 0) {
2604 BOOT_LOG_WRN("Failed reading image headers.");
2605 return rc;
2606 }
2607
2608 /* Check headers in all slots */
2609 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2610 hdr = boot_img_hdr(state, slot);
2611
2612 if (boot_is_header_valid(hdr, BOOT_IMG_AREA(state, slot))) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002613 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = true;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002614 BOOT_LOG_IMAGE_INFO(slot, hdr);
2615 } else {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002616 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002617 BOOT_LOG_INF("Image %u %s slot: Image not found",
2618 (unsigned)BOOT_CURR_IMG(state),
2619 (slot == BOOT_PRIMARY_SLOT)
2620 ? "Primary" : "Secondary");
2621 }
2622 }
2623
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002624 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002625 }
2626
2627 return 0;
2628}
2629
2630/**
2631 * Finds the slot containing the image with the highest version number for the
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002632 * current image. Also dependency check feature verifies version of the first
2633 * slot of dependent image and assumes to load from the first slot. In order to
2634 * avoid conflicts dependency ckeck feature is disabled.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002635 *
2636 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002637 *
2638 * @return NO_ACTIVE_SLOT if no available slot found, number of
2639 * the found slot otherwise.
David Vinczee574f2d2020-07-10 11:42:03 +02002640 */
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002641#if !defined(MCUBOOT_DEPENDENCY_CHECK) && !defined(MCUBOOT_RAM_LOAD)
David Vinczee574f2d2020-07-10 11:42:03 +02002642static uint32_t
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002643find_slot_with_highest_version(struct boot_loader_state *state)
David Vinczee574f2d2020-07-10 11:42:03 +02002644{
David Vinczee574f2d2020-07-10 11:42:03 +02002645 uint32_t slot;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002646 uint32_t candidate_slot = NO_ACTIVE_SLOT;
2647 int rc;
David Vinczee574f2d2020-07-10 11:42:03 +02002648
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002649 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002650 if (state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot]) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002651 if (candidate_slot == NO_ACTIVE_SLOT) {
2652 candidate_slot = slot;
2653 } else {
2654 rc = boot_version_cmp(
2655 &boot_img_hdr(state, slot)->ih_ver,
2656 &boot_img_hdr(state, candidate_slot)->ih_ver);
2657 if (rc == 1) {
2658 /* The version of the image being examined is greater than
2659 * the version of the current candidate.
2660 */
2661 candidate_slot = slot;
2662 }
2663 }
David Vinczee574f2d2020-07-10 11:42:03 +02002664 }
2665 }
2666
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002667 return candidate_slot;
David Vinczee574f2d2020-07-10 11:42:03 +02002668}
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02002669#endif /* !defined(MCUBOOT_DEPENDENCY_CHECK) && !defined(MCUBOOT_RAM_LOAD) */
David Vinczee574f2d2020-07-10 11:42:03 +02002670
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002671#ifdef MCUBOOT_HAVE_LOGGING
David Vincze505fba22020-10-22 13:53:29 +02002672/**
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002673 * Prints the state of the loaded images.
David Vincze505fba22020-10-22 13:53:29 +02002674 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002675 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002676 */
2677static void
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002678print_loaded_images(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002679{
2680 uint32_t active_slot;
2681
2682 (void)state;
2683
2684 IMAGES_ITER(BOOT_CURR_IMG(state)) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002685#if BOOT_IMAGE_NUMBER > 1
2686 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2687 continue;
2688 }
2689#endif
2690 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002691
2692 BOOT_LOG_INF("Image %u loaded from the %s slot",
2693 (unsigned)BOOT_CURR_IMG(state),
2694 (active_slot == BOOT_PRIMARY_SLOT) ?
2695 "primary" : "secondary");
2696 }
2697}
2698#endif
2699
2700#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
2701/**
2702 * Checks whether the active slot of the current image was previously selected
2703 * to run. Erases the image if it was selected but its execution failed,
2704 * otherwise marks it as selected if it has not been before.
David Vincze505fba22020-10-22 13:53:29 +02002705 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002706 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002707 *
2708 * @return 0 on success; nonzero on failure.
David Vincze505fba22020-10-22 13:53:29 +02002709 */
2710static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002711boot_select_or_erase(struct boot_loader_state *state)
David Vincze505fba22020-10-22 13:53:29 +02002712{
2713 const struct flash_area *fap;
2714 int fa_id;
2715 int rc;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002716 uint32_t active_slot;
2717 struct boot_swap_state* active_swap_state;
David Vincze505fba22020-10-22 13:53:29 +02002718
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002719 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002720
2721 fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), active_slot);
David Vincze505fba22020-10-22 13:53:29 +02002722 rc = flash_area_open(fa_id, &fap);
2723 assert(rc == 0);
2724
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002725 active_swap_state = &(state->slot_usage[BOOT_CURR_IMG(state)].swap_state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002726
2727 (void)memset(active_swap_state, 0, sizeof(struct boot_swap_state));
2728 rc = boot_read_swap_state(fap, active_swap_state);
David Vincze505fba22020-10-22 13:53:29 +02002729 assert(rc == 0);
2730
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002731 if (active_swap_state->magic != BOOT_MAGIC_GOOD ||
2732 (active_swap_state->copy_done == BOOT_FLAG_SET &&
2733 active_swap_state->image_ok != BOOT_FLAG_SET)) {
David Vincze505fba22020-10-22 13:53:29 +02002734 /*
2735 * A reboot happened without the image being confirmed at
2736 * runtime or its trailer is corrupted/invalid. Erase the image
2737 * to prevent it from being selected again on the next reboot.
2738 */
2739 BOOT_LOG_DBG("Erasing faulty image in the %s slot.",
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002740 (active_slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
2741 rc = flash_area_erase(fap, 0, flash_area_get_size(fap));
David Vincze505fba22020-10-22 13:53:29 +02002742 assert(rc == 0);
2743
2744 flash_area_close(fap);
2745 rc = -1;
2746 } else {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002747 if (active_swap_state->copy_done != BOOT_FLAG_SET) {
2748 if (active_swap_state->copy_done == BOOT_FLAG_BAD) {
David Vincze505fba22020-10-22 13:53:29 +02002749 BOOT_LOG_DBG("The copy_done flag had an unexpected value. Its "
2750 "value was neither 'set' nor 'unset', but 'bad'.");
2751 }
2752 /*
2753 * Set the copy_done flag, indicating that the image has been
2754 * selected to boot. It can be set in advance, before even
2755 * validating the image, because in case the validation fails, the
2756 * entire image slot will be erased (including the trailer).
2757 */
2758 rc = boot_write_copy_done(fap);
2759 if (rc != 0) {
2760 BOOT_LOG_WRN("Failed to set copy_done flag of the image in "
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002761 "the %s slot.", (active_slot == BOOT_PRIMARY_SLOT) ?
David Vincze505fba22020-10-22 13:53:29 +02002762 "primary" : "secondary");
2763 rc = 0;
2764 }
2765 }
2766 flash_area_close(fap);
2767 }
2768
2769 return rc;
2770}
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002771#endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */
David Vincze505fba22020-10-22 13:53:29 +02002772
Tamas Banfe031092020-09-10 17:32:39 +02002773#ifdef MCUBOOT_RAM_LOAD
2774
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002775#ifndef MULTIPLE_EXECUTABLE_RAM_REGIONS
Tamas Banfe031092020-09-10 17:32:39 +02002776#if !defined(IMAGE_EXECUTABLE_RAM_START) || !defined(IMAGE_EXECUTABLE_RAM_SIZE)
2777#error "Platform MUST define executable RAM bounds in case of RAM_LOAD"
2778#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002779#endif
Tamas Banfe031092020-09-10 17:32:39 +02002780
2781/**
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002782 * Verifies that the active slot of the current image can be loaded within the
2783 * predefined bounds that are allowed to be used by executable images.
Tamas Banfe031092020-09-10 17:32:39 +02002784 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002785 * @param state Boot loader status information.
Tamas Banfe031092020-09-10 17:32:39 +02002786 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002787 * @return 0 on success; nonzero on failure.
Tamas Banfe031092020-09-10 17:32:39 +02002788 */
2789static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002790boot_verify_ram_load_address(struct boot_loader_state *state)
Tamas Banfe031092020-09-10 17:32:39 +02002791{
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002792 uint32_t img_dst;
2793 uint32_t img_sz;
Tamas Banfe031092020-09-10 17:32:39 +02002794 uint32_t img_end_addr;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002795 uint32_t exec_ram_start;
2796 uint32_t exec_ram_size;
Tamas Banfe031092020-09-10 17:32:39 +02002797
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002798 (void)state;
2799
2800#ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS
2801 int rc;
2802
2803 rc = boot_get_image_exec_ram_info(BOOT_CURR_IMG(state), &exec_ram_start,
2804 &exec_ram_size);
2805 if (rc != 0) {
2806 return BOOT_EBADSTATUS;
2807 }
2808#else
2809 exec_ram_start = IMAGE_EXECUTABLE_RAM_START;
2810 exec_ram_size = IMAGE_EXECUTABLE_RAM_SIZE;
2811#endif
2812
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03002813 img_dst = state->slot_usage[BOOT_CURR_IMG(state)].img_dst;
2814 img_sz = state->slot_usage[BOOT_CURR_IMG(state)].img_sz;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002815
2816 if (img_dst < exec_ram_start) {
Tamas Banfe031092020-09-10 17:32:39 +02002817 return BOOT_EBADIMAGE;
2818 }
2819
2820 if (!boot_u32_safe_add(&img_end_addr, img_dst, img_sz)) {
2821 return BOOT_EBADIMAGE;
2822 }
2823
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002824 if (img_end_addr > (exec_ram_start + exec_ram_size)) {
Tamas Banfe031092020-09-10 17:32:39 +02002825 return BOOT_EBADIMAGE;
2826 }
2827
2828 return 0;
2829}
2830
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002831#ifdef MCUBOOT_ENC_IMAGES
2832
Tamas Banfe031092020-09-10 17:32:39 +02002833/**
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002834 * Copies and decrypts an image from a slot in the flash to an SRAM address.
Tamas Banfe031092020-09-10 17:32:39 +02002835 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002836 * @param state Boot loader status information.
2837 * @param slot The flash slot of the image to be copied to SRAM.
2838 * @param hdr The image header.
2839 * @param src_sz Size of the image.
2840 * @param img_dst Pointer to the address at which the image needs to be
2841 * copied to SRAM.
2842 *
2843 * @return 0 on success; nonzero on failure.
2844 */
2845static int
2846boot_decrypt_and_copy_image_to_sram(struct boot_loader_state *state,
2847 uint32_t slot, struct image_header *hdr,
2848 uint32_t src_sz, uint32_t img_dst)
2849{
2850 /* The flow for the decryption and copy of the image is as follows :
2851 * 1. The whole image is copied to the RAM (header + payload + TLV).
2852 * 2. The encryption key is loaded from the TLV in flash.
2853 * 3. The image is then decrypted chunk by chunk in RAM (1 chunk
2854 * is 1024 bytes). Only the payload section is decrypted.
2855 * 4. The image is authenticated in RAM.
2856 */
2857 const struct flash_area *fap_src = NULL;
2858 struct boot_status bs;
2859 uint32_t blk_off;
2860 uint32_t tlv_off;
2861 uint32_t blk_sz;
2862 uint32_t bytes_copied = hdr->ih_hdr_size;
2863 uint32_t chunk_sz;
2864 uint32_t max_sz = 1024;
2865 uint16_t idx;
2866 uint8_t image_index;
2867 uint8_t * cur_dst;
2868 int area_id;
2869 int rc;
2870 uint8_t * ram_dst = (void *)(IMAGE_RAM_BASE + img_dst);
2871
2872 image_index = BOOT_CURR_IMG(state);
2873 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
2874 rc = flash_area_open(area_id, &fap_src);
2875 if (rc != 0){
2876 return BOOT_EFLASH;
2877 }
2878
2879 tlv_off = BOOT_TLV_OFF(hdr);
2880
2881 /* Copying the whole image in RAM */
2882 rc = flash_area_read(fap_src, 0, ram_dst, src_sz);
2883 if (rc != 0) {
2884 goto done;
2885 }
2886
2887 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap_src, &bs);
2888 if (rc < 0) {
2889 goto done;
2890 }
2891
2892 /* if rc > 0 then the key has already been loaded */
2893 if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), slot, &bs)) {
2894 goto done;
2895 }
2896
2897 /* Starting at the end of the header as the header section is not encrypted */
2898 while (bytes_copied < tlv_off) { /* TLV section copied previously */
2899 if (src_sz - bytes_copied > max_sz) {
2900 chunk_sz = max_sz;
2901 } else {
2902 chunk_sz = src_sz - bytes_copied;
2903 }
2904
2905 cur_dst = ram_dst + bytes_copied;
2906 blk_sz = chunk_sz;
2907 idx = 0;
2908 if (bytes_copied + chunk_sz > tlv_off) {
2909 /* Going over TLV section
2910 * Part of the chunk is encrypted payload */
2911 blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf;
2912 blk_sz = tlv_off - (bytes_copied);
2913 boot_encrypt(BOOT_CURR_ENC(state), image_index, fap_src,
2914 (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
2915 blk_off, cur_dst);
2916 } else {
2917 /* Image encrypted payload section */
2918 blk_off = ((bytes_copied) - hdr->ih_hdr_size) & 0xf;
2919 boot_encrypt(BOOT_CURR_ENC(state), image_index, fap_src,
2920 (bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
2921 blk_off, cur_dst);
2922 }
2923
2924 bytes_copied += chunk_sz;
2925 }
2926 rc = 0;
2927
2928done:
2929 flash_area_close(fap_src);
2930
2931 return rc;
2932}
2933
2934#endif /* MCUBOOT_ENC_IMAGES */
2935/**
2936 * Copies a slot of the current image into SRAM.
2937 *
2938 * @param state Boot loader status information.
Tamas Banfe031092020-09-10 17:32:39 +02002939 * @param slot The flash slot of the image to be copied to SRAM.
2940 * @param img_dst The address at which the image needs to be copied to
2941 * SRAM.
2942 * @param img_sz The size of the image that needs to be copied to SRAM.
2943 *
2944 * @return 0 on success; nonzero on failure.
2945 */
2946static int
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002947boot_copy_image_to_sram(struct boot_loader_state *state, int slot,
2948 uint32_t img_dst, uint32_t img_sz)
Tamas Banfe031092020-09-10 17:32:39 +02002949{
2950 int rc;
2951 const struct flash_area *fap_src = NULL;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002952 int area_id;
Tamas Banfe031092020-09-10 17:32:39 +02002953
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002954#if (BOOT_IMAGE_NUMBER == 1)
2955 (void)state;
2956#endif
2957
2958 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
2959
2960 rc = flash_area_open(area_id, &fap_src);
Tamas Banfe031092020-09-10 17:32:39 +02002961 if (rc != 0) {
2962 return BOOT_EFLASH;
2963 }
2964
2965 /* Direct copy from flash to its new location in SRAM. */
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002966 rc = flash_area_read(fap_src, 0, (void *)(IMAGE_RAM_BASE + img_dst), img_sz);
Tamas Banfe031092020-09-10 17:32:39 +02002967 if (rc != 0) {
2968 BOOT_LOG_INF("Error whilst copying image from Flash to SRAM: %d", rc);
2969 }
2970
2971 flash_area_close(fap_src);
2972
2973 return rc;
2974}
2975
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002976#if (BOOT_IMAGE_NUMBER > 1)
Tamas Banfe031092020-09-10 17:32:39 +02002977/**
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002978 * Checks if two memory regions (A and B) are overlap or not.
Tamas Banfe031092020-09-10 17:32:39 +02002979 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002980 * @param start_a Start of the A region.
2981 * @param end_a End of the A region.
2982 * @param start_b Start of the B region.
2983 * @param end_b End of the B region.
Tamas Banfe031092020-09-10 17:32:39 +02002984 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03002985 * @return true if there is overlap; false otherwise.
2986 */
2987static bool
2988do_regions_overlap(uint32_t start_a, uint32_t end_a,
2989 uint32_t start_b, uint32_t end_b)
2990{
2991 if (start_b > end_a) {
2992 return false;
2993 } else if (start_b >= start_a) {
2994 return true;
2995 } else if (end_b > start_a) {
2996 return true;
2997 }
2998
2999 return false;
3000}
3001
3002/**
3003 * Checks if the image we want to load to memory overlap with an already
3004 * ramloaded image.
3005 *
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003006 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003007 *
3008 * @return 0 if there is no overlap; nonzero otherwise.
Tamas Banfe031092020-09-10 17:32:39 +02003009 */
3010static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003011boot_check_ram_load_overlapping(struct boot_loader_state *state)
Tamas Banfe031092020-09-10 17:32:39 +02003012{
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003013 uint32_t i;
3014
3015 uint32_t start_a;
3016 uint32_t end_a;
3017 uint32_t start_b;
3018 uint32_t end_b;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003019 uint32_t image_id_to_check = BOOT_CURR_IMG(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003020
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003021 start_a = state->slot_usage[image_id_to_check].img_dst;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003022 /* Safe to add here, values are already verified in
3023 * boot_verify_ram_load_address() */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003024 end_a = start_a + state->slot_usage[image_id_to_check].img_sz;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003025
3026 for (i = 0; i < BOOT_IMAGE_NUMBER; i++) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003027 if (state->slot_usage[i].active_slot == NO_ACTIVE_SLOT
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003028 || i == image_id_to_check) {
3029 continue;
3030 }
3031
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003032 start_b = state->slot_usage[i].img_dst;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003033 /* Safe to add here, values are already verified in
3034 * boot_verify_ram_load_address() */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003035 end_b = start_b + state->slot_usage[i].img_sz;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003036
3037 if (do_regions_overlap(start_a, end_a, start_b, end_b)) {
3038 return -1;
3039 }
3040 }
3041
3042 return 0;
3043}
3044#endif
3045
3046/**
3047 * Loads the active slot of the current image into SRAM. The load address and
3048 * image size is extracted from the image header.
3049 *
3050 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003051 *
3052 * @return 0 on success; nonzero on failure.
3053 */
3054static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003055boot_load_image_to_sram(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003056{
3057 uint32_t active_slot;
3058 struct image_header *hdr = NULL;
3059 uint32_t img_dst;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003060 uint32_t img_sz = 0;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003061 int rc = 0;
Tamas Banfe031092020-09-10 17:32:39 +02003062
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003063 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003064 hdr = boot_img_hdr(state, active_slot);
3065
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003066 if (IS_RAM_BOOTABLE(hdr)) {
Tamas Banfe031092020-09-10 17:32:39 +02003067
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003068 img_dst = hdr->ih_load_addr;
Tamas Banfe031092020-09-10 17:32:39 +02003069
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003070 rc = boot_read_image_size(state, active_slot, &img_sz);
Tamas Banfe031092020-09-10 17:32:39 +02003071 if (rc != 0) {
3072 return rc;
3073 }
3074
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003075 state->slot_usage[BOOT_CURR_IMG(state)].img_dst = img_dst;
3076 state->slot_usage[BOOT_CURR_IMG(state)].img_sz = img_sz;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003077
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003078 rc = boot_verify_ram_load_address(state);
Tamas Banfe031092020-09-10 17:32:39 +02003079 if (rc != 0) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003080 BOOT_LOG_INF("Image RAM load address 0x%" PRIx32 " is invalid.", img_dst);
Tamas Banfe031092020-09-10 17:32:39 +02003081 return rc;
3082 }
3083
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003084#if (BOOT_IMAGE_NUMBER > 1)
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003085 rc = boot_check_ram_load_overlapping(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003086 if (rc != 0) {
3087 BOOT_LOG_INF("Image RAM loading to address 0x%" PRIx32
3088 " would overlap with another image.", img_dst);
3089 return rc;
3090 }
3091#endif
3092#ifdef MCUBOOT_ENC_IMAGES
3093 /* decrypt image if encrypted and copy it to RAM */
3094 if (IS_ENCRYPTED(hdr)) {
3095 rc = boot_decrypt_and_copy_image_to_sram(state, active_slot, hdr, img_sz, img_dst);
3096 } else {
3097 rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
3098 }
3099#else
Tamas Banfe031092020-09-10 17:32:39 +02003100 /* Copy image to the load address from where it currently resides in
3101 * flash.
3102 */
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003103 rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
3104#endif
Tamas Banfe031092020-09-10 17:32:39 +02003105 if (rc != 0) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003106 BOOT_LOG_INF("RAM loading to 0x%" PRIx32 " is failed.", img_dst);
Tamas Banfe031092020-09-10 17:32:39 +02003107 } else {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003108 BOOT_LOG_INF("RAM loading to 0x%" PRIx32 " is succeeded.", img_dst);
Tamas Banfe031092020-09-10 17:32:39 +02003109 }
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003110 }
3111 else {
Tamas Banfe031092020-09-10 17:32:39 +02003112 /* Only images that support IMAGE_F_RAM_LOAD are allowed if
3113 * MCUBOOT_RAM_LOAD is set.
3114 */
3115 rc = BOOT_EBADIMAGE;
3116 }
3117
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003118 if (rc != 0) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003119 state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
3120 state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003121 }
3122
Tamas Banfe031092020-09-10 17:32:39 +02003123 return rc;
3124}
3125
3126/**
3127 * Removes an image from SRAM, by overwriting it with zeros.
3128 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003129 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003130 *
3131 * @return 0 on success; nonzero on failure.
3132 */
3133static inline int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003134boot_remove_image_from_sram(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003135{
3136 (void)state;
3137
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003138 BOOT_LOG_INF("Removing image from SRAM at address 0x%x",
3139 state->slot_usage[BOOT_CURR_IMG(state)].img_dst);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003140
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003141 (void)memset((void*)(IMAGE_RAM_BASE + state->slot_usage[BOOT_CURR_IMG(state)].img_dst),
3142 0, state->slot_usage[BOOT_CURR_IMG(state)].img_sz);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003143
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003144 state->slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
3145 state->slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003146
3147 return 0;
3148}
3149
3150/**
3151 * Removes an image from flash by erasing the corresponding flash area
3152 *
3153 * @param state Boot loader status information.
3154 * @param slot The flash slot of the image to be erased.
Tamas Banfe031092020-09-10 17:32:39 +02003155 *
3156 * @return 0 on success; nonzero on failure.
3157 */
3158static inline int
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003159boot_remove_image_from_flash(struct boot_loader_state *state, uint32_t slot)
Tamas Banfe031092020-09-10 17:32:39 +02003160{
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003161 int area_id;
3162 int rc;
3163 const struct flash_area *fap;
Tamas Banfe031092020-09-10 17:32:39 +02003164
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003165 (void)state;
3166
3167 BOOT_LOG_INF("Removing image %u slot %" PRIu32 " from flash",
3168 (unsigned)BOOT_CURR_IMG(state), slot);
3169 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
3170 rc = flash_area_open(area_id, &fap);
3171 if (rc == 0) {
3172 flash_area_erase(fap, 0, flash_area_get_size(fap));
3173 }
3174
3175 return rc;
Tamas Banfe031092020-09-10 17:32:39 +02003176}
3177#endif /* MCUBOOT_RAM_LOAD */
3178
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003179#if (BOOT_IMAGE_NUMBER > 1)
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003180#if defined(MCUBOOT_DEPENDENCY_CHECK)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003181/**
3182 * Checks the image dependency whether it is satisfied.
3183 *
3184 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003185 * @param dep Image dependency which has to be verified.
3186 *
3187 * @return 0 if dependencies are met; nonzero otherwise.
3188 */
3189static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003190boot_verify_slot_dependency_ram(struct boot_loader_state *state,
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003191 struct image_dependency *dep)
David Vinczee574f2d2020-07-10 11:42:03 +02003192{
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003193 struct image_version *dep_version;
3194 uint32_t dep_slot;
David Vinczee574f2d2020-07-10 11:42:03 +02003195 int rc;
3196
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003197 /* Determine the source of the image which is the subject of
3198 * the dependency and get it's version.
David Vinczee574f2d2020-07-10 11:42:03 +02003199 */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003200 dep_slot = state->slot_usage[dep->image_id].active_slot;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003201 dep_version = &state->imgs[dep->image_id][dep_slot].hdr.ih_ver;
3202
3203 rc = boot_version_cmp(dep_version, &dep->image_min_version);
3204 if (rc >= 0) {
3205 /* Dependency satisfied. */
3206 rc = 0;
David Vinczee574f2d2020-07-10 11:42:03 +02003207 }
3208
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003209 return rc;
3210}
3211
3212/**
3213 * Reads all dependency TLVs of an image and verifies one after another to see
3214 * if they are all satisfied.
3215 *
3216 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003217 *
3218 * @return 0 if dependencies are met; nonzero otherwise.
3219 */
3220static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003221boot_verify_slot_dependencies_ram(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003222{
3223 uint32_t active_slot;
3224 const struct flash_area *fap;
3225 struct image_tlv_iter it;
3226 struct image_dependency dep;
3227 uint32_t off;
3228 uint16_t len;
3229 int area_id;
3230 int rc;
3231
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003232 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003233
3234 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state),
3235 active_slot);
3236 rc = flash_area_open(area_id, &fap);
David Vinczee574f2d2020-07-10 11:42:03 +02003237 if (rc != 0) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003238 rc = BOOT_EFLASH;
3239 goto done;
David Vinczee574f2d2020-07-10 11:42:03 +02003240 }
3241
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003242 rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, active_slot), fap,
3243 IMAGE_TLV_DEPENDENCY, true);
3244 if (rc != 0) {
3245 goto done;
3246 }
David Vinczee574f2d2020-07-10 11:42:03 +02003247
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003248 while (true) {
3249 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
3250 if (rc < 0) {
3251 return -1;
3252 } else if (rc > 0) {
3253 rc = 0;
3254 break;
3255 }
David Vinczee574f2d2020-07-10 11:42:03 +02003256
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003257 if (len != sizeof(dep)) {
3258 rc = BOOT_EBADIMAGE;
3259 goto done;
3260 }
3261
3262 rc = LOAD_IMAGE_DATA(boot_img_hdr(state, active_slot),
3263 fap, off, &dep, len);
3264 if (rc != 0) {
3265 rc = BOOT_EFLASH;
3266 goto done;
3267 }
3268
3269 if (dep.image_id >= BOOT_IMAGE_NUMBER) {
3270 rc = BOOT_EBADARGS;
3271 goto done;
3272 }
3273
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003274 rc = boot_verify_slot_dependency_ram(state, &dep);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003275 if (rc != 0) {
3276 /* Dependency not satisfied. */
3277 goto done;
3278 }
3279 }
3280
3281done:
3282 flash_area_close(fap);
3283 return rc;
3284}
3285
3286/**
3287 * Checks the dependency of all the active slots. If an image found with
3288 * invalid or not satisfied dependencies the image is removed from SRAM (in
3289 * case of MCUBOOT_RAM_LOAD strategy) and its slot is set to unavailable.
3290 *
3291 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003292 *
3293 * @return 0 if dependencies are met; nonzero otherwise.
3294 */
3295static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003296boot_verify_dependencies_ram(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003297{
3298 int rc = -1;
3299 uint32_t active_slot;
3300
3301 IMAGES_ITER(BOOT_CURR_IMG(state)) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003302 if (state->img_mask[BOOT_CURR_IMG(state)]) {
3303 continue;
3304 }
3305 rc = boot_verify_slot_dependencies_ram(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003306 if (rc != 0) {
3307 /* Dependencies not met or invalid dependencies. */
3308
3309#ifdef MCUBOOT_RAM_LOAD
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003310 boot_remove_image_from_sram(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003311#endif /* MCUBOOT_RAM_LOAD */
3312
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003313 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
3314 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3315 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003316
3317 return rc;
3318 }
3319 }
3320
3321 return rc;
3322}
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003323#endif /* (MCUBOOT_DEPENDENCY_CHECK) */
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003324#endif /* (BOOT_IMAGE_NUMBER > 1) */
3325
3326/**
3327 * Tries to load a slot for all the images with validation.
3328 *
3329 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003330 *
3331 * @return 0 on success; nonzero on failure.
3332 */
3333fih_int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003334boot_load_and_validate_images(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003335{
3336 uint32_t active_slot;
3337 int rc;
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02003338#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
3339 fih_int fih_rc = FIH_FAILURE;
3340#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003341
3342 /* Go over all the images and try to load one */
3343 IMAGES_ITER(BOOT_CURR_IMG(state)) {
3344 /* All slots tried until a valid image found. Breaking from this loop
3345 * means that a valid image found or already loaded. If no slot is
3346 * found the function returns with error code. */
3347 while (true) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003348 /* Go over all the slots and try to load one */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003349 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003350 if (active_slot != NO_ACTIVE_SLOT){
3351 /* A slot is already active, go to next image. */
3352 break;
3353 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003354
3355 /* Ram load assumes to find the highest version of available slots
3356 * and load it. Also dependency check feature verifies version
3357 * of first slot of dependent image and assumes to load from the
3358 * first slot. So logic is separated into two cases to avoid conflicts,
3359 * where the first is when dependency check is disabled,
3360 * and the second is when it is enabled.
3361 * Notation: to avoid situations when reverted image with higher version is
3362 * ram-loaded, the current logic is changed to loading 'BOOT_PRIMARY_SLOT'
3363 * on a constant basis.
3364 * */
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003365
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003366#if !defined(MCUBOOT_DEPENDENCY_CHECK) && !defined(MCUBOOT_RAM_LOAD)
3367 /* Go over all slots and find the highest version. */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003368 active_slot = find_slot_with_highest_version(state);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003369#else
3370 /* Dependecy check feature assumes to load from the first slot */
3371 active_slot = BOOT_PRIMARY_SLOT;
3372#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003373 if (active_slot == NO_ACTIVE_SLOT) {
3374 BOOT_LOG_INF("No slot to load for image %u",
3375 (unsigned)BOOT_CURR_IMG(state));
3376 FIH_RET(FIH_FAILURE);
3377 }
3378
3379 /* Save the number of the active slot. */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003380 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot;
3381
3382#if BOOT_IMAGE_NUMBER > 1
3383 if (state->img_mask[BOOT_CURR_IMG(state)]) {
3384 continue;
3385 }
3386#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003387
3388#ifdef MCUBOOT_DIRECT_XIP
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003389 rc = boot_rom_address_check(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003390 if (rc != 0) {
3391 /* The image is placed in an unsuitable slot. */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003392 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3393 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003394 continue;
David Vinczee574f2d2020-07-10 11:42:03 +02003395 }
David Vincze505fba22020-10-22 13:53:29 +02003396
3397#ifdef MCUBOOT_DIRECT_XIP_REVERT
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003398 rc = boot_select_or_erase(state);
David Vincze505fba22020-10-22 13:53:29 +02003399 if (rc != 0) {
3400 /* The selected image slot has been erased. */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003401 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3402 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
David Vincze505fba22020-10-22 13:53:29 +02003403 continue;
3404 }
3405#endif /* MCUBOOT_DIRECT_XIP_REVERT */
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003406#endif /* MCUBOOT_DIRECT_XIP */
David Vincze505fba22020-10-22 13:53:29 +02003407
Tamas Banfe031092020-09-10 17:32:39 +02003408#ifdef MCUBOOT_RAM_LOAD
3409 /* Image is first loaded to RAM and authenticated there in order to
3410 * prevent TOCTOU attack during image copy. This could be applied
3411 * when loading images from external (untrusted) flash to internal
3412 * (trusted) RAM and image is authenticated before copying.
3413 */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003414 rc = boot_load_image_to_sram(state);
Tamas Banfe031092020-09-10 17:32:39 +02003415 if (rc != 0 ) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003416 /* Image cannot be ramloaded. */
3417 boot_remove_image_from_flash(state, active_slot);
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003418 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3419 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003420 /* Since active_slot is set BOOT_PRIMARY_SLOT only, then after its deletion
3421 * no sense to check BOOT_SECONDARY_SLOT. So go outside with an error */
3422 BOOT_LOG_ERR("BOOT slot of image %u has been removed from flash",
3423 (unsigned)BOOT_CURR_IMG(state));
3424 FIH_RET(FIH_FAILURE);
Tamas Banfe031092020-09-10 17:32:39 +02003425 }
3426#endif /* MCUBOOT_RAM_LOAD */
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02003427#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003428 FIH_CALL(boot_validate_slot, fih_rc, state, active_slot, NULL);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003429 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003430 /* Image is invalid. */
Tamas Banfe031092020-09-10 17:32:39 +02003431#ifdef MCUBOOT_RAM_LOAD
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003432 boot_remove_image_from_sram(state);
Tamas Banfe031092020-09-10 17:32:39 +02003433#endif /* MCUBOOT_RAM_LOAD */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003434 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
3435 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003436 /* Since active_slot is set BOOT_PRIMARY_SLOT only, then after its deletion
3437 * no sense to check BOOT_SECONDARY_SLOT. So go outside with an error */
3438 BOOT_LOG_ERR("BOOT slot of image %u has been removed from SRAM",
3439 (unsigned)BOOT_CURR_IMG(state));
3440 FIH_RET(FIH_FAILURE);
David Vincze505fba22020-10-22 13:53:29 +02003441 }
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02003442#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003443 /* Valid image loaded from a slot, go to next image. */
3444 break;
David Vinczee574f2d2020-07-10 11:42:03 +02003445 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003446 }
3447
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003448 (void) rc;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003449 FIH_RET(FIH_SUCCESS);
3450}
3451
3452/**
3453 * Updates the security counter for the current image.
3454 *
3455 * @param state Boot loader status information.
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003456 *
3457 * @return 0 on success; nonzero on failure.
3458 */
3459static int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003460boot_update_hw_rollback_protection_ram(struct boot_loader_state *state)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003461{
3462#ifdef MCUBOOT_HW_ROLLBACK_PROT
3463 int rc;
3464
3465 /* Update the stored security counter with the newer (active) image's
3466 * security counter value.
3467 */
3468#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
3469 /* When the 'revert' mechanism is enabled in direct-xip mode, the
3470 * security counter can be increased only after reboot, if the image
3471 * has been confirmed at runtime (the image_ok flag has been set).
3472 * This way a 'revert' can be performed when it's necessary.
3473 */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003474 if (state->slot_usage[BOOT_CURR_IMG(state)].swap_state.image_ok == BOOT_FLAG_SET) {
David Vincze505fba22020-10-22 13:53:29 +02003475#endif
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003476 rc = boot_update_security_counter(BOOT_CURR_IMG(state),
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003477 state->slot_usage[BOOT_CURR_IMG(state)].active_slot,
3478 boot_img_hdr(state, state->slot_usage[BOOT_CURR_IMG(state)].active_slot));
David Vinczee574f2d2020-07-10 11:42:03 +02003479 if (rc != 0) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003480 BOOT_LOG_ERR("Security counter update failed after image "
3481 "validation.");
3482 return rc;
David Vinczee574f2d2020-07-10 11:42:03 +02003483 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003484#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
3485 }
3486#endif
David Vinczee574f2d2020-07-10 11:42:03 +02003487
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003488 return 0;
David Vinczee574f2d2020-07-10 11:42:03 +02003489
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003490#else /* MCUBOOT_HW_ROLLBACK_PROT */
3491 (void) (state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003492 return 0;
3493#endif
3494}
David Vinczee574f2d2020-07-10 11:42:03 +02003495
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003496fih_int
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003497context_boot_go_ram(struct boot_loader_state *state, struct boot_rsp *rsp)
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003498{
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003499 int rc;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003500 fih_int fih_rc = FIH_FAILURE;
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02003501 boot_ram = true;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003502
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003503 rc = boot_get_slot_usage(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003504 if (rc != 0) {
David Vinczee574f2d2020-07-10 11:42:03 +02003505 goto out;
3506 }
3507
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003508#if (BOOT_IMAGE_NUMBER > 1)
3509 while (true) {
3510#endif
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003511 FIH_CALL(boot_load_and_validate_images, fih_rc, state);
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003512 if (!fih_eq(fih_rc, FIH_SUCCESS)) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003513 goto out;
3514 }
3515
3516#if (BOOT_IMAGE_NUMBER > 1)
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003517#if defined(MCUBOOT_DEPENDENCY_CHECK)
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003518 rc = boot_verify_dependencies_ram(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003519 if (rc != 0) {
3520 /* Dependency check failed for an image, it has been removed from
3521 * SRAM in case of MCUBOOT_RAM_LOAD strategy, and set to
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003522 * unavailable. */
3523 goto out;
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003524 }
3525 /* Dependency check was successful. */
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003526#endif /* defined(MCUBOOT_DEPENDENCY_CHECK) */
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003527 break;
3528 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003529#endif /* (BOOT_IMAGE_NUMBER > 1) */
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003530
3531 IMAGES_ITER(BOOT_CURR_IMG(state)) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003532#if BOOT_IMAGE_NUMBER > 1
3533 if (state->img_mask[BOOT_CURR_IMG(state)]) {
3534 continue;
3535 }
3536#endif
3537 rc = boot_update_hw_rollback_protection_ram(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003538 if (rc != 0) {
3539 goto out;
3540 }
3541
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003542 rc = boot_add_shared_data(state, state->slot_usage[BOOT_CURR_IMG(state)].active_slot);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003543 if (rc != 0) {
3544 goto out;
3545 }
3546 }
3547
3548 /* All image loaded successfully. */
3549#ifdef MCUBOOT_HAVE_LOGGING
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003550 print_loaded_images(state);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003551#endif
3552
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003553 fill_rsp(state, rsp);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003554
David Vinczee574f2d2020-07-10 11:42:03 +02003555out:
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003556 close_all_flash_areas(state);
Raef Colese8fe6cf2020-05-26 13:07:40 +01003557
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +02003558 if (fih_eq(fih_rc, FIH_SUCCESS)) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003559 fih_rc = fih_int_encode_zero_equality(rc);
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003560 }
Raef Colese8fe6cf2020-05-26 13:07:40 +01003561
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +02003562 boot_ram = false;
3563
Roman Okhrimenko977b3752022-03-31 14:40:48 +03003564 FIH_RET(fih_rc);
David Vinczee574f2d2020-07-10 11:42:03 +02003565}
Tamas Banfe031092020-09-10 17:32:39 +02003566#endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
David Vinczee574f2d2020-07-10 11:42:03 +02003567
3568/**
Raef Colese8fe6cf2020-05-26 13:07:40 +01003569 * Prepares the booting process. This function moves images around in flash as
David Vinczee574f2d2020-07-10 11:42:03 +02003570 * appropriate, and tells you what address to boot from.
3571 *
3572 * @param rsp On success, indicates how booting should occur.
3573 *
Raef Colese8fe6cf2020-05-26 13:07:40 +01003574 * @return FIH_SUCCESS on success; nonzero on failure.
David Vinczee574f2d2020-07-10 11:42:03 +02003575 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01003576fih_int
David Vinczee574f2d2020-07-10 11:42:03 +02003577boot_go(struct boot_rsp *rsp)
3578{
Raef Colese8fe6cf2020-05-26 13:07:40 +01003579 fih_int fih_rc = FIH_FAILURE;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003580
3581 boot_state_clear(NULL);
3582
3583 FIH_CALL(context_boot_go_flash, fih_rc, &boot_data, rsp);
Raef Colese8fe6cf2020-05-26 13:07:40 +01003584 FIH_RET(fih_rc);
David Vinczee574f2d2020-07-10 11:42:03 +02003585}
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +03003586
3587/**
3588 * Prepares the booting process, considering only a single image. This function
3589 * moves images around in flash as appropriate, and tells you what address to
3590 * boot from.
3591 *
3592 * @param rsp On success, indicates how booting should occur.
3593 *
3594 * @param image_id The image ID to prepare the boot process for.
3595 *
3596 * @return FIH_SUCCESS on success; nonzero on failure.
3597 */
3598fih_int
3599boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id)
3600{
3601 fih_int fih_rc = FIH_FAILURE;
3602
3603 if (image_id >= BOOT_IMAGE_NUMBER) {
3604 FIH_RET(FIH_FAILURE);
3605 }
3606
3607#if BOOT_IMAGE_NUMBER > 1
3608 (void)memset(&boot_data.img_mask, 1, BOOT_IMAGE_NUMBER);
3609 boot_data.img_mask[image_id] = 0;
3610#endif
3611
3612 FIH_CALL(context_boot_go_flash, fih_rc, &boot_data, rsp);
3613 FIH_RET(fih_rc);
3614}
3615
3616#if defined(MCUBOOT_RAM_LOAD)
3617/**
3618 * Prepares the booting process, considering only a single image. This function
3619 * moves images around in flash as appropriate, and tells you what address to
3620 * boot from.
3621 *
3622 * @param rsp On success, indicates how booting should occur.
3623 *
3624 * @param image_id The image ID to prepare the boot process for.
3625 *
3626 * @return FIH_SUCCESS on success; nonzero on failure.
3627 */
3628fih_int
3629boot_go_for_image_id_ram(struct boot_rsp *rsp, uint32_t image_id)
3630{
3631 fih_int fih_rc = FIH_FAILURE;
3632
3633 if (image_id >= BOOT_IMAGE_NUMBER) {
3634 FIH_RET(FIH_FAILURE);
3635 }
3636
3637#if BOOT_IMAGE_NUMBER > 1
3638 (void)memset(&boot_data.img_mask, 1, BOOT_IMAGE_NUMBER);
3639 boot_data.img_mask[image_id] = 0;
3640#endif
3641
3642 FIH_CALL(context_boot_go_ram, fih_rc, &boot_data, rsp);
3643 FIH_RET(fih_rc);
3644}
3645
3646#endif /* MCUBOOT_RAM_LOAD */
3647
3648/**
3649 * Clears the boot state, so that previous operations have no effect on new
3650 * ones.
3651 *
3652 * @param state The state that should be cleared. If the value
3653 * is NULL, the default bootloader state will be
3654 * cleared.
3655 */
3656void boot_state_clear(struct boot_loader_state *state)
3657{
3658 if (state != NULL) {
3659 (void)memset(state, 0, sizeof(struct boot_loader_state));
3660 } else {
3661 (void)memset(&boot_data, 0, sizeof(struct boot_loader_state));
3662 }
3663}