blob: 28cb65eb56d38418672881162267800c2d514d0f [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
Mark Horvathccaf7f82021-01-04 18:16:42 +01006 * 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 <os/os_malloc.h>
39#include "bootutil/bootutil.h"
40#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"
Mark Horvathccaf7f82021-01-04 18:16:42 +010047#include "bootutil/ramload.h"
Marti Bolivarfd20c762017-02-07 16:52:50 -050048
Fabio Utzigba829042018-09-18 08:29:34 -030049#ifdef MCUBOOT_ENC_IMAGES
50#include "bootutil/enc_key.h"
51#endif
52
Fabio Utzigba1fbe62017-07-21 14:01:20 -030053#include "mcuboot_config/mcuboot_config.h"
Fabio Utzigeed80b62017-06-10 08:03:05 -030054
Carlos Falgueras Garcíaa4b4b0f2021-06-22 10:00:22 +020055BOOT_LOG_MODULE_DECLARE(mcuboot);
Emanuele Di Santo9f1933d2018-11-20 10:59:59 +010056
Marti Bolivar9b1f8bb2017-06-12 15:24:13 -040057static struct boot_loader_state boot_data;
Christopher Collins92ea77f2016-12-12 15:59:26 -080058
Fabio Utzigabec0732019-07-31 08:40:22 -030059#if (BOOT_IMAGE_NUMBER > 1)
60#define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x))
61#else
62#define IMAGES_ITER(x)
63#endif
64
Mark Horvathccaf7f82021-01-04 18:16:42 +010065#if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
66struct slot_usage_t {
67 /* Index of the slot chosen to be loaded */
68 uint32_t active_slot;
69 bool slot_available[BOOT_NUM_SLOTS];
David Vincze1c456242021-06-29 15:25:24 +020070#if defined(MCUBOOT_RAM_LOAD)
Mark Horvathccaf7f82021-01-04 18:16:42 +010071 /* Image destination and size for the active slot */
72 uint32_t img_dst;
73 uint32_t img_sz;
David Vincze1c456242021-06-29 15:25:24 +020074#elif defined(MCUBOOT_DIRECT_XIP_REVERT)
Mark Horvathccaf7f82021-01-04 18:16:42 +010075 /* Swap status for the active slot */
Carlos Falgueras Garcíaafb424d2021-06-21 17:05:44 +020076 struct boot_swap_state swap_state;
Mark Horvathccaf7f82021-01-04 18:16:42 +010077#endif
David Vincze1c456242021-06-29 15:25:24 +020078};
79#endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
Mark Horvathccaf7f82021-01-04 18:16:42 +010080
Fabio Utzig10ee6482019-08-01 12:04:52 -030081/*
82 * This macro allows some control on the allocation of local variables.
83 * When running natively on a target, we don't want to allocated huge
84 * variables on the stack, so make them global instead. For the simulator
85 * we want to run as many threads as there are tests, and it's safer
86 * to just make those variables stack allocated.
87 */
88#if !defined(__BOOTSIM__)
89#define TARGET_STATIC static
90#else
91#define TARGET_STATIC
92#endif
93
David Vinczee574f2d2020-07-10 11:42:03 +020094static int
95boot_read_image_headers(struct boot_loader_state *state, bool require_all,
96 struct boot_status *bs)
97{
98 int rc;
99 int i;
100
101 for (i = 0; i < BOOT_NUM_SLOTS; i++) {
102 rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs);
103 if (rc != 0) {
104 /* If `require_all` is set, fail on any single fail, otherwise
105 * if at least the first slot's header was read successfully,
106 * then the boot loader can attempt a boot.
107 *
108 * Failure to read any headers is a fatal error.
109 */
110 if (i > 0 && !require_all) {
111 return 0;
112 } else {
113 return rc;
114 }
115 }
116 }
117
118 return 0;
119}
120
Mark Horvathccaf7f82021-01-04 18:16:42 +0100121/**
122 * Saves boot status and shared data for current image.
123 *
124 * @param state Boot loader status information.
125 * @param active_slot Index of the slot will be loaded for current image.
126 *
127 * @return 0 on success; nonzero on failure.
128 */
129static int
130boot_add_shared_data(struct boot_loader_state *state,
131 uint32_t active_slot)
132{
133#if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING)
134 int rc;
135
136#ifdef MCUBOOT_MEASURED_BOOT
137 rc = boot_save_boot_status(BOOT_CURR_IMG(state),
138 boot_img_hdr(state, active_slot),
139 BOOT_IMG_AREA(state, active_slot));
140 if (rc != 0) {
141 BOOT_LOG_ERR("Failed to add image data to shared area");
142 return rc;
143 }
144#endif /* MCUBOOT_MEASURED_BOOT */
145
146#ifdef MCUBOOT_DATA_SHARING
147 rc = boot_save_shared_data(boot_img_hdr(state, active_slot),
148 BOOT_IMG_AREA(state, active_slot));
149 if (rc != 0) {
150 BOOT_LOG_ERR("Failed to add data to shared memory area.");
151 return rc;
152 }
153#endif /* MCUBOOT_DATA_SHARING */
154
155 return 0;
156
157#else /* MCUBOOT_MEASURED_BOOT || MCUBOOT_DATA_SHARING */
158 (void) (state);
159 (void) (active_slot);
160
161 return 0;
162#endif
163}
164
165/**
166 * Fills rsp to indicate how booting should occur.
167 *
168 * @param state Boot loader status information.
169 * @param slot_usage Information about the active and available slots.
170 * Only used in MCUBOOT_DIRECT_XIP and MCUBOOT_RAM_LOAD
171 * @param rsp boot_rsp struct to fill.
172 */
173static void
174fill_rsp(struct boot_loader_state *state, void *slot_usage,
175 struct boot_rsp *rsp)
176{
177 uint32_t active_slot;
178
179#if (BOOT_IMAGE_NUMBER > 1)
180 /* Always boot from Image 0. */
181 BOOT_CURR_IMG(state) = 0;
182#endif
183
184#if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
185 active_slot = ((struct slot_usage_t *)slot_usage)[BOOT_CURR_IMG(state)].active_slot;
186#else
187 (void) (slot_usage);
188 active_slot = BOOT_PRIMARY_SLOT;
189#endif
190
Dominik Ermel260ae092021-04-23 05:38:45 +0000191 rsp->br_flash_dev_id = flash_area_get_device_id(BOOT_IMG_AREA(state, active_slot));
Mark Horvathccaf7f82021-01-04 18:16:42 +0100192 rsp->br_image_off = boot_img_slot_off(state, active_slot);
193 rsp->br_hdr = boot_img_hdr(state, active_slot);
194}
195
196/**
197 * Closes all flash areas.
198 *
199 * @param state Boot loader status information.
200 */
201static void
202close_all_flash_areas(struct boot_loader_state *state)
203{
204 uint32_t slot;
205
206 IMAGES_ITER(BOOT_CURR_IMG(state)) {
207#if MCUBOOT_SWAP_USING_SCRATCH
208 flash_area_close(BOOT_SCRATCH_AREA(state));
209#endif
210 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
211 flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot));
212 }
213 }
214}
215
Tamas Banfe031092020-09-10 17:32:39 +0200216#if !defined(MCUBOOT_DIRECT_XIP)
David Brownf5b33d82017-09-01 10:58:27 -0600217/*
218 * Compute the total size of the given image. Includes the size of
219 * the TLVs.
220 */
Tamas Banfe031092020-09-10 17:32:39 +0200221#if !defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_OVERWRITE_ONLY_FAST)
David Brownf5b33d82017-09-01 10:58:27 -0600222static int
Fabio Utzigd638b172019-08-09 10:38:05 -0300223boot_read_image_size(struct boot_loader_state *state, int slot, uint32_t *size)
David Brownf5b33d82017-09-01 10:58:27 -0600224{
225 const struct flash_area *fap;
Fabio Utzig61fd8882019-09-14 20:00:20 -0300226 struct image_tlv_info info;
Fabio Utzig233af7d2019-08-26 12:06:16 -0300227 uint32_t off;
Fabio Utzige52c08e2019-09-11 19:32:00 -0300228 uint32_t protect_tlv_size;
David Brownf5b33d82017-09-01 10:58:27 -0600229 int area_id;
230 int rc;
231
Fabio Utzig10ee6482019-08-01 12:04:52 -0300232#if (BOOT_IMAGE_NUMBER == 1)
233 (void)state;
234#endif
235
236 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
David Brownf5b33d82017-09-01 10:58:27 -0600237 rc = flash_area_open(area_id, &fap);
238 if (rc != 0) {
239 rc = BOOT_EFLASH;
240 goto done;
241 }
242
Fabio Utzig61fd8882019-09-14 20:00:20 -0300243 off = BOOT_TLV_OFF(boot_img_hdr(state, slot));
244
245 if (flash_area_read(fap, off, &info, sizeof(info))) {
246 rc = BOOT_EFLASH;
David Brownf5b33d82017-09-01 10:58:27 -0600247 goto done;
248 }
Fabio Utzig61fd8882019-09-14 20:00:20 -0300249
Fabio Utzige52c08e2019-09-11 19:32:00 -0300250 protect_tlv_size = boot_img_hdr(state, slot)->ih_protect_tlv_size;
251 if (info.it_magic == IMAGE_TLV_PROT_INFO_MAGIC) {
252 if (protect_tlv_size != info.it_tlv_tot) {
253 rc = BOOT_EBADIMAGE;
254 goto done;
255 }
256
257 if (flash_area_read(fap, off + info.it_tlv_tot, &info, sizeof(info))) {
258 rc = BOOT_EFLASH;
259 goto done;
260 }
261 } else if (protect_tlv_size != 0) {
262 rc = BOOT_EBADIMAGE;
263 goto done;
264 }
265
Fabio Utzig61fd8882019-09-14 20:00:20 -0300266 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
267 rc = BOOT_EBADIMAGE;
268 goto done;
269 }
270
Fabio Utzige52c08e2019-09-11 19:32:00 -0300271 *size = off + protect_tlv_size + info.it_tlv_tot;
David Brownf5b33d82017-09-01 10:58:27 -0600272 rc = 0;
273
274done:
275 flash_area_close(fap);
Fabio Utzig2eebf112017-09-04 15:25:08 -0300276 return rc;
David Brownf5b33d82017-09-01 10:58:27 -0600277}
Fabio Utzig36ec0e72017-09-05 08:10:33 -0300278#endif /* !MCUBOOT_OVERWRITE_ONLY */
David Brownf5b33d82017-09-01 10:58:27 -0600279
Tamas Banfe031092020-09-10 17:32:39 +0200280#if !defined(MCUBOOT_RAM_LOAD)
David Brownab449182019-11-15 09:32:52 -0700281static uint32_t
Fabio Utzig10ee6482019-08-01 12:04:52 -0300282boot_write_sz(struct boot_loader_state *state)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800283{
David Brownab449182019-11-15 09:32:52 -0700284 uint32_t elem_sz;
Fabio Utzig12d59162019-11-28 10:01:59 -0300285#if MCUBOOT_SWAP_USING_SCRATCH
David Brownab449182019-11-15 09:32:52 -0700286 uint32_t align;
Fabio Utzig12d59162019-11-28 10:01:59 -0300287#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800288
289 /* Figure out what size to write update status update as. The size depends
290 * on what the minimum write size is for scratch area, active image slot.
291 * We need to use the bigger of those 2 values.
292 */
Fabio Utzig10ee6482019-08-01 12:04:52 -0300293 elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT));
Fabio Utzig12d59162019-11-28 10:01:59 -0300294#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -0300295 align = flash_area_align(BOOT_SCRATCH_AREA(state));
Christopher Collins92ea77f2016-12-12 15:59:26 -0800296 if (align > elem_sz) {
297 elem_sz = align;
298 }
Fabio Utzig12d59162019-11-28 10:01:59 -0300299#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800300
301 return elem_sz;
302}
303
Fabio Utzig10ee6482019-08-01 12:04:52 -0300304static int
305boot_initialize_area(struct boot_loader_state *state, int flash_area)
306{
Dominik Ermel51c8d762021-05-24 15:34:01 +0000307 uint32_t num_sectors = BOOT_MAX_IMG_SECTORS;
308 boot_sector_t *out_sectors;
309 uint32_t *out_num_sectors;
Fabio Utzig10ee6482019-08-01 12:04:52 -0300310 int rc;
311
312 num_sectors = BOOT_MAX_IMG_SECTORS;
313
314 if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
315 out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors;
316 out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors;
317 } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
318 out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors;
319 out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors;
Fabio Utzig12d59162019-11-28 10:01:59 -0300320#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -0300321 } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
322 out_sectors = state->scratch.sectors;
323 out_num_sectors = &state->scratch.num_sectors;
Fabio Utzig12d59162019-11-28 10:01:59 -0300324#endif
Fabio Utzig10ee6482019-08-01 12:04:52 -0300325 } else {
326 return BOOT_EFLASH;
327 }
328
Dominik Ermel51c8d762021-05-24 15:34:01 +0000329#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
Fabio Utzig10ee6482019-08-01 12:04:52 -0300330 rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
Dominik Ermel51c8d762021-05-24 15:34:01 +0000331#else
332 _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed");
333 rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors);
334#endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
Fabio Utzig10ee6482019-08-01 12:04:52 -0300335 if (rc != 0) {
336 return rc;
337 }
338 *out_num_sectors = num_sectors;
339 return 0;
340}
Fabio Utzig10ee6482019-08-01 12:04:52 -0300341
Christopher Collins92ea77f2016-12-12 15:59:26 -0800342/**
343 * Determines the sector layout of both image slots and the scratch area.
344 * This information is necessary for calculating the number of bytes to erase
345 * and copy during an image swap. The information collected during this
Fabio Utzig10ee6482019-08-01 12:04:52 -0300346 * function is used to populate the state.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800347 */
348static int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300349boot_read_sectors(struct boot_loader_state *state)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800350{
Fabio Utzigb0f04732019-07-31 09:49:19 -0300351 uint8_t image_index;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800352 int rc;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800353
Fabio Utzig10ee6482019-08-01 12:04:52 -0300354 image_index = BOOT_CURR_IMG(state);
Fabio Utzigb0f04732019-07-31 09:49:19 -0300355
356 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
Christopher Collins92ea77f2016-12-12 15:59:26 -0800357 if (rc != 0) {
358 return BOOT_EFLASH;
359 }
360
Fabio Utzig10ee6482019-08-01 12:04:52 -0300361 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index));
Christopher Collins92ea77f2016-12-12 15:59:26 -0800362 if (rc != 0) {
Andrzej Puzdrowski54b4ad92021-06-22 13:21:22 +0200363 /* We need to differentiate from the primary image issue */
364 return BOOT_EFLASH_SEC;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800365 }
366
Fabio Utzig12d59162019-11-28 10:01:59 -0300367#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -0300368 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH);
Fabio Utzig2bd980a2018-11-26 10:38:17 -0200369 if (rc != 0) {
370 return BOOT_EFLASH;
371 }
Fabio Utzig12d59162019-11-28 10:01:59 -0300372#endif
Fabio Utzig2bd980a2018-11-26 10:38:17 -0200373
Fabio Utzig10ee6482019-08-01 12:04:52 -0300374 BOOT_WRITE_SZ(state) = boot_write_sz(state);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800375
376 return 0;
377}
378
Fabio Utzig12d59162019-11-28 10:01:59 -0300379void
380boot_status_reset(struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800381{
Fabio Utzig4741c452019-12-19 15:32:41 -0300382#ifdef MCUBOOT_ENC_IMAGES
383 memset(&bs->enckey, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_KEY_SIZE);
384#if MCUBOOT_SWAP_SAVE_ENCTLV
385 memset(&bs->enctlv, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_TLV_ALIGN_SIZE);
386#endif
387#endif /* MCUBOOT_ENC_IMAGES */
388
389 bs->use_scratch = 0;
390 bs->swap_size = 0;
391 bs->source = 0;
392
Fabio Utzig74aef312019-11-28 11:05:34 -0300393 bs->op = BOOT_STATUS_OP_MOVE;
Fabio Utzig39000012018-07-30 12:40:20 -0300394 bs->idx = BOOT_STATUS_IDX_0;
395 bs->state = BOOT_STATUS_STATE_0;
Christopher Collinsa1c12042019-05-23 14:00:28 -0700396 bs->swap_type = BOOT_SWAP_TYPE_NONE;
Fabio Utzig12d59162019-11-28 10:01:59 -0300397}
Christopher Collins92ea77f2016-12-12 15:59:26 -0800398
Fabio Utzig12d59162019-11-28 10:01:59 -0300399bool
400boot_status_is_reset(const struct boot_status *bs)
401{
Fabio Utzig74aef312019-11-28 11:05:34 -0300402 return (bs->op == BOOT_STATUS_OP_MOVE &&
403 bs->idx == BOOT_STATUS_IDX_0 &&
404 bs->state == BOOT_STATUS_STATE_0);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800405}
406
407/**
408 * Writes the supplied boot status to the flash file system. The boot status
409 * contains the current state of an in-progress image copy operation.
410 *
411 * @param bs The boot status to write.
412 *
413 * @return 0 on success; nonzero on failure.
414 */
415int
Fabio Utzig12d59162019-11-28 10:01:59 -0300416boot_write_status(const struct boot_loader_state *state, struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800417{
418 const struct flash_area *fap;
419 uint32_t off;
420 int area_id;
421 int rc;
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300422 uint8_t buf[BOOT_MAX_ALIGN];
David Brown9d725462017-01-23 15:50:58 -0700423 uint8_t align;
Fabio Utzig39000012018-07-30 12:40:20 -0300424 uint8_t erased_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800425
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300426 /* NOTE: The first sector copied (that is the last sector on slot) contains
David Vincze2d736ad2019-02-18 11:50:22 +0100427 * the trailer. Since in the last step the primary slot is erased, the
428 * first two status writes go to the scratch which will be copied to
429 * the primary slot!
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300430 */
431
Fabio Utzig12d59162019-11-28 10:01:59 -0300432#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig2473ac02017-05-02 12:45:02 -0300433 if (bs->use_scratch) {
Christopher Collins92ea77f2016-12-12 15:59:26 -0800434 /* Write to scratch. */
435 area_id = FLASH_AREA_IMAGE_SCRATCH;
436 } else {
Fabio Utzig12d59162019-11-28 10:01:59 -0300437#endif
David Vincze2d736ad2019-02-18 11:50:22 +0100438 /* Write to the primary slot. */
Fabio Utzig10ee6482019-08-01 12:04:52 -0300439 area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
Fabio Utzig12d59162019-11-28 10:01:59 -0300440#if MCUBOOT_SWAP_USING_SCRATCH
Christopher Collins92ea77f2016-12-12 15:59:26 -0800441 }
Fabio Utzig12d59162019-11-28 10:01:59 -0300442#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800443
444 rc = flash_area_open(area_id, &fap);
445 if (rc != 0) {
446 rc = BOOT_EFLASH;
447 goto done;
448 }
449
450 off = boot_status_off(fap) +
Fabio Utzig12d59162019-11-28 10:01:59 -0300451 boot_status_internal_off(bs, BOOT_WRITE_SZ(state));
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +0200452 align = flash_area_align(fap);
Fabio Utzig39000012018-07-30 12:40:20 -0300453 erased_val = flash_area_erased_val(fap);
454 memset(buf, erased_val, BOOT_MAX_ALIGN);
David Brown9d725462017-01-23 15:50:58 -0700455 buf[0] = bs->state;
456
457 rc = flash_area_write(fap, off, buf, align);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800458 if (rc != 0) {
459 rc = BOOT_EFLASH;
460 goto done;
461 }
462
463 rc = 0;
464
465done:
466 flash_area_close(fap);
467 return rc;
468}
Tamas Banfe031092020-09-10 17:32:39 +0200469#endif /* !MCUBOOT_RAM_LOAD */
David Vinczee574f2d2020-07-10 11:42:03 +0200470#endif /* !MCUBOOT_DIRECT_XIP */
Christopher Collins92ea77f2016-12-12 15:59:26 -0800471
472/*
David Vinczec3084132020-02-18 14:50:47 +0100473 * Validate image hash/signature and optionally the security counter in a slot.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800474 */
Raef Colese8fe6cf2020-05-26 13:07:40 +0100475static fih_int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300476boot_image_check(struct boot_loader_state *state, struct image_header *hdr,
477 const struct flash_area *fap, struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800478{
Fabio Utzig10ee6482019-08-01 12:04:52 -0300479 TARGET_STATIC uint8_t tmpbuf[BOOT_TMPBUF_SZ];
Fabio Utzigb0f04732019-07-31 09:49:19 -0300480 uint8_t image_index;
Fabio Utzigba829042018-09-18 08:29:34 -0300481 int rc;
Raef Colese8fe6cf2020-05-26 13:07:40 +0100482 fih_int fih_rc = FIH_FAILURE;
Fabio Utzigba829042018-09-18 08:29:34 -0300483
Fabio Utzig10ee6482019-08-01 12:04:52 -0300484#if (BOOT_IMAGE_NUMBER == 1)
485 (void)state;
486#endif
487
Fabio Utzigba829042018-09-18 08:29:34 -0300488 (void)bs;
489 (void)rc;
Fabio Utzigbc077932019-08-26 11:16:34 -0300490
491 image_index = BOOT_CURR_IMG(state);
492
493#ifdef MCUBOOT_ENC_IMAGES
494 if (MUST_DECRYPT(fap, image_index, hdr)) {
Fabio Utzig4741c452019-12-19 15:32:41 -0300495 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap, bs);
Fabio Utzigba829042018-09-18 08:29:34 -0300496 if (rc < 0) {
Raef Colese8fe6cf2020-05-26 13:07:40 +0100497 FIH_RET(fih_rc);
Fabio Utzigba829042018-09-18 08:29:34 -0300498 }
Fabio Utzig4741c452019-12-19 15:32:41 -0300499 if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) {
Raef Colese8fe6cf2020-05-26 13:07:40 +0100500 FIH_RET(fih_rc);
Fabio Utzigba829042018-09-18 08:29:34 -0300501 }
502 }
Fabio Utzigbc077932019-08-26 11:16:34 -0300503#endif
504
Raef Colese8fe6cf2020-05-26 13:07:40 +0100505 FIH_CALL(bootutil_img_validate, fih_rc, BOOT_CURR_ENC(state), image_index,
506 hdr, fap, tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, NULL);
Fabio Utzig10ee6482019-08-01 12:04:52 -0300507
Raef Colese8fe6cf2020-05-26 13:07:40 +0100508 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800509}
510
Tamas Banfe031092020-09-10 17:32:39 +0200511#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
Raef Colese8fe6cf2020-05-26 13:07:40 +0100512static fih_int
Christopher Collins92ea77f2016-12-12 15:59:26 -0800513split_image_check(struct image_header *app_hdr,
514 const struct flash_area *app_fap,
515 struct image_header *loader_hdr,
516 const struct flash_area *loader_fap)
517{
518 static void *tmpbuf;
519 uint8_t loader_hash[32];
Raef Colese8fe6cf2020-05-26 13:07:40 +0100520 fih_int fih_rc = FIH_FAILURE;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800521
522 if (!tmpbuf) {
523 tmpbuf = malloc(BOOT_TMPBUF_SZ);
524 if (!tmpbuf) {
Raef Colese8fe6cf2020-05-26 13:07:40 +0100525 goto out;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800526 }
527 }
528
Raef Colese8fe6cf2020-05-26 13:07:40 +0100529 FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, loader_hdr, loader_fap,
530 tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash);
531 if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
532 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800533 }
534
Raef Colese8fe6cf2020-05-26 13:07:40 +0100535 FIH_CALL(bootutil_img_validate, fih_rc, NULL, 0, app_hdr, app_fap,
536 tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800537
Raef Colese8fe6cf2020-05-26 13:07:40 +0100538out:
539 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800540}
Tamas Banfe031092020-09-10 17:32:39 +0200541#endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */
Christopher Collins92ea77f2016-12-12 15:59:26 -0800542
Fabio Utzig338a19f2018-12-03 08:37:08 -0200543/*
David Brown9bf95af2019-10-10 15:36:36 -0600544 * Check that this is a valid header. Valid means that the magic is
545 * correct, and that the sizes/offsets are "sane". Sane means that
546 * there is no overflow on the arithmetic, and that the result fits
547 * within the flash area we are in.
548 */
549static bool
550boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fap)
551{
552 uint32_t size;
553
554 if (hdr->ih_magic != IMAGE_MAGIC) {
555 return false;
556 }
557
558 if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size)) {
559 return false;
560 }
561
Dominik Ermel260ae092021-04-23 05:38:45 +0000562 if (size >= flash_area_get_size(fap)) {
David Brown9bf95af2019-10-10 15:36:36 -0600563 return false;
564 }
565
566 return true;
567}
568
569/*
Fabio Utzig338a19f2018-12-03 08:37:08 -0200570 * Check that a memory area consists of a given value.
571 */
572static inline bool
573boot_data_is_set_to(uint8_t val, void *data, size_t len)
Fabio Utzig39000012018-07-30 12:40:20 -0300574{
575 uint8_t i;
Fabio Utzig338a19f2018-12-03 08:37:08 -0200576 uint8_t *p = (uint8_t *)data;
577 for (i = 0; i < len; i++) {
578 if (val != p[i]) {
579 return false;
Fabio Utzig39000012018-07-30 12:40:20 -0300580 }
581 }
Fabio Utzig338a19f2018-12-03 08:37:08 -0200582 return true;
583}
584
585static int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300586boot_check_header_erased(struct boot_loader_state *state, int slot)
Fabio Utzig338a19f2018-12-03 08:37:08 -0200587{
588 const struct flash_area *fap;
589 struct image_header *hdr;
590 uint8_t erased_val;
Fabio Utzigb0f04732019-07-31 09:49:19 -0300591 int area_id;
Fabio Utzig338a19f2018-12-03 08:37:08 -0200592 int rc;
593
Fabio Utzig10ee6482019-08-01 12:04:52 -0300594 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
Fabio Utzigb0f04732019-07-31 09:49:19 -0300595 rc = flash_area_open(area_id, &fap);
Fabio Utzig338a19f2018-12-03 08:37:08 -0200596 if (rc != 0) {
597 return -1;
598 }
599
600 erased_val = flash_area_erased_val(fap);
601 flash_area_close(fap);
602
Fabio Utzig10ee6482019-08-01 12:04:52 -0300603 hdr = boot_img_hdr(state, slot);
Fabio Utzig338a19f2018-12-03 08:37:08 -0200604 if (!boot_data_is_set_to(erased_val, &hdr->ih_magic, sizeof(hdr->ih_magic))) {
605 return -1;
606 }
607
608 return 0;
Fabio Utzig39000012018-07-30 12:40:20 -0300609}
610
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000611#if (BOOT_IMAGE_NUMBER > 1) || \
David Vinczee574f2d2020-07-10 11:42:03 +0200612 defined(MCUBOOT_DIRECT_XIP) || \
Tamas Banfe031092020-09-10 17:32:39 +0200613 defined(MCUBOOT_RAM_LOAD) || \
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000614 (defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION))
615/**
David Vincze8b0b6372020-05-20 19:54:44 +0200616 * Compare image version numbers not including the build number
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000617 *
David Vincze8b0b6372020-05-20 19:54:44 +0200618 * @param ver1 Pointer to the first image version to compare.
619 * @param ver2 Pointer to the second image version to compare.
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000620 *
David Vincze8b0b6372020-05-20 19:54:44 +0200621 * @retval -1 If ver1 is strictly less than ver2.
622 * @retval 0 If the image version numbers are equal,
623 * (not including the build number).
624 * @retval 1 If ver1 is strictly greater than ver2.
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000625 */
626static int
David Vincze8b0b6372020-05-20 19:54:44 +0200627boot_version_cmp(const struct image_version *ver1,
628 const struct image_version *ver2)
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000629{
David Vincze8b0b6372020-05-20 19:54:44 +0200630 if (ver1->iv_major > ver2->iv_major) {
631 return 1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000632 }
David Vincze8b0b6372020-05-20 19:54:44 +0200633 if (ver1->iv_major < ver2->iv_major) {
634 return -1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000635 }
David Vincze8b0b6372020-05-20 19:54:44 +0200636 /* The major version numbers are equal, continue comparison. */
637 if (ver1->iv_minor > ver2->iv_minor) {
638 return 1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000639 }
David Vincze8b0b6372020-05-20 19:54:44 +0200640 if (ver1->iv_minor < ver2->iv_minor) {
641 return -1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000642 }
David Vincze8b0b6372020-05-20 19:54:44 +0200643 /* The minor version numbers are equal, continue comparison. */
644 if (ver1->iv_revision > ver2->iv_revision) {
645 return 1;
646 }
647 if (ver1->iv_revision < ver2->iv_revision) {
648 return -1;
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000649 }
650
651 return 0;
652}
653#endif
654
Dominik Ermel0c8c8d52021-02-17 14:45:02 +0000655#if defined(MCUBOOT_DIRECT_XIP)
656/**
657 * Check if image in slot has been set with specific ROM address to run from
658 * and whether the slot starts at that address.
659 *
660 * @returns 0 if IMAGE_F_ROM_FIXED flag is not set;
661 * 0 if IMAGE_F_ROM_FIXED flag is set and ROM address specified in
662 * header matches the slot address;
663 * 1 if IMF_F_ROM_FIXED flag is set but ROM address specified in header
664 * does not match the slot address.
665 */
666static bool
Mark Horvathccaf7f82021-01-04 18:16:42 +0100667boot_rom_address_check(struct boot_loader_state *state,
668 struct slot_usage_t slot_usage[])
Dominik Ermel0c8c8d52021-02-17 14:45:02 +0000669{
Mark Horvathccaf7f82021-01-04 18:16:42 +0100670 uint32_t active_slot;
671 const struct image_header *hdr;
672 uint32_t f_off;
673
674 active_slot = slot_usage[BOOT_CURR_IMG(state)].active_slot;
675 hdr = boot_img_hdr(state, active_slot);
676 f_off = boot_img_slot_off(state, active_slot);
677
Dominik Ermel0c8c8d52021-02-17 14:45:02 +0000678 if (hdr->ih_flags & IMAGE_F_ROM_FIXED && hdr->ih_load_addr != f_off) {
679 BOOT_LOG_WRN("Image in %s slot at 0x%x has been built for offset 0x%x"\
Mark Horvathccaf7f82021-01-04 18:16:42 +0100680 ", skipping",
681 active_slot == 0 ? "primary" : "secondary", f_off,
Dominik Ermel0c8c8d52021-02-17 14:45:02 +0000682 hdr->ih_load_addr);
683
684 /* If there is address mismatch, the image is not bootable from this
685 * slot.
686 */
687 return 1;
688 }
689 return 0;
690}
691#endif
692
Fabio Utzigb1adb1e2019-09-11 11:42:53 -0300693/*
694 * Check that there is a valid image in a slot
695 *
696 * @returns
Raef Colese8fe6cf2020-05-26 13:07:40 +0100697 * FIH_SUCCESS if image was successfully validated
698 * 1 (or its fih_int encoded form) if no bootloable image was found
699 * FIH_FAILURE on any errors
Fabio Utzigb1adb1e2019-09-11 11:42:53 -0300700 */
Raef Colese8fe6cf2020-05-26 13:07:40 +0100701static fih_int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300702boot_validate_slot(struct boot_loader_state *state, int slot,
703 struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800704{
705 const struct flash_area *fap;
Marti Bolivarf804f622017-06-12 15:41:48 -0400706 struct image_header *hdr;
Fabio Utzigb0f04732019-07-31 09:49:19 -0300707 int area_id;
Raef Colese8fe6cf2020-05-26 13:07:40 +0100708 fih_int fih_rc = FIH_FAILURE;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800709 int rc;
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300710
Fabio Utzig10ee6482019-08-01 12:04:52 -0300711 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
Fabio Utzigb0f04732019-07-31 09:49:19 -0300712 rc = flash_area_open(area_id, &fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800713 if (rc != 0) {
Raef Colese8fe6cf2020-05-26 13:07:40 +0100714 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800715 }
716
Fabio Utzig10ee6482019-08-01 12:04:52 -0300717 hdr = boot_img_hdr(state, slot);
718 if (boot_check_header_erased(state, slot) == 0 ||
719 (hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) {
Fabio Utzig260ec452020-07-09 18:40:07 -0300720
721#if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE)
722 /*
723 * This fixes an issue where an image might be erased, but a trailer
724 * be left behind. It can happen if the image is in the secondary slot
725 * and did not pass validation, in which case the whole slot is erased.
726 * If during the erase operation, a reset occurs, parts of the slot
727 * might have been erased while some did not. The concerning part is
728 * the trailer because it might disable a new image from being loaded
729 * through mcumgr; so we just get rid of the trailer here, if the header
730 * is erased.
731 */
732 if (slot != BOOT_PRIMARY_SLOT) {
733 swap_erase_trailer_sectors(state, fap);
734 }
735#endif
736
David Vincze2d736ad2019-02-18 11:50:22 +0100737 /* No bootable image in slot; continue booting from the primary slot. */
Raef Colese8fe6cf2020-05-26 13:07:40 +0100738 fih_rc = fih_int_encode(1);
Fabio Utzig338a19f2018-12-03 08:37:08 -0200739 goto out;
Fabio Utzig39000012018-07-30 12:40:20 -0300740 }
741
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000742#if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION)
743 if (slot != BOOT_PRIMARY_SLOT) {
744 /* Check if version of secondary slot is sufficient */
David Vincze8b0b6372020-05-20 19:54:44 +0200745 rc = boot_version_cmp(
746 &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver,
747 &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver);
748 if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) {
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000749 BOOT_LOG_ERR("insufficient version in secondary slot");
Dominik Ermel260ae092021-04-23 05:38:45 +0000750 flash_area_erase(fap, 0, flash_area_get_size(fap));
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000751 /* Image in the secondary slot does not satisfy version requirement.
752 * Erase the image and continue booting from the primary slot.
753 */
Raef Colese8fe6cf2020-05-26 13:07:40 +0100754 fih_rc = fih_int_encode(1);
Håkon Øye Amundsen2d1bac12020-01-03 13:08:09 +0000755 goto out;
756 }
757 }
758#endif
759
Raef Colese8fe6cf2020-05-26 13:07:40 +0100760 FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs);
761 if (!boot_is_header_valid(hdr, fap) || fih_not_eq(fih_rc, FIH_SUCCESS)) {
Tamas Banfe031092020-09-10 17:32:39 +0200762 if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) {
Dominik Ermel260ae092021-04-23 05:38:45 +0000763 flash_area_erase(fap, 0, flash_area_get_size(fap));
David Vinczee574f2d2020-07-10 11:42:03 +0200764 /* Image is invalid, erase it to prevent further unnecessary
765 * attempts to validate and boot it.
David Brownb38e0442017-02-24 13:57:12 -0700766 */
767 }
David Brown098de832019-12-10 11:58:01 -0700768#if !defined(__BOOTSIM__)
David Vincze2d736ad2019-02-18 11:50:22 +0100769 BOOT_LOG_ERR("Image in the %s slot is not valid!",
770 (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
David Brown098de832019-12-10 11:58:01 -0700771#endif
Raef Colese8fe6cf2020-05-26 13:07:40 +0100772 fih_rc = fih_int_encode(1);
Fabio Utzig338a19f2018-12-03 08:37:08 -0200773 goto out;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800774 }
775
Fabio Utzig338a19f2018-12-03 08:37:08 -0200776out:
777 flash_area_close(fap);
Raef Colese8fe6cf2020-05-26 13:07:40 +0100778
779 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800780}
781
David Vinczec3084132020-02-18 14:50:47 +0100782#ifdef MCUBOOT_HW_ROLLBACK_PROT
783/**
784 * Updates the stored security counter value with the image's security counter
785 * value which resides in the given slot, only if it's greater than the stored
786 * value.
787 *
788 * @param image_index Index of the image to determine which security
789 * counter to update.
790 * @param slot Slot number of the image.
791 * @param hdr Pointer to the image header structure of the image
792 * that is currently stored in the given slot.
793 *
794 * @return 0 on success; nonzero on failure.
795 */
796static int
797boot_update_security_counter(uint8_t image_index, int slot,
798 struct image_header *hdr)
799{
800 const struct flash_area *fap = NULL;
801 uint32_t img_security_cnt;
802 int rc;
803
804 rc = flash_area_open(flash_area_id_from_multi_image_slot(image_index, slot),
805 &fap);
806 if (rc != 0) {
807 rc = BOOT_EFLASH;
808 goto done;
809 }
810
811 rc = bootutil_get_img_security_cnt(hdr, fap, &img_security_cnt);
812 if (rc != 0) {
813 goto done;
814 }
815
816 rc = boot_nv_security_counter_update(image_index, img_security_cnt);
817 if (rc != 0) {
818 goto done;
819 }
820
821done:
822 flash_area_close(fap);
823 return rc;
824}
825#endif /* MCUBOOT_HW_ROLLBACK_PROT */
826
Tamas Banfe031092020-09-10 17:32:39 +0200827#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
David Vinczee574f2d2020-07-10 11:42:03 +0200828/**
829 * Determines which swap operation to perform, if any. If it is determined
830 * that a swap operation is required, the image in the secondary slot is checked
831 * for validity. If the image in the secondary slot is invalid, it is erased,
832 * and a swap type of "none" is indicated.
833 *
834 * @return The type of swap to perform (BOOT_SWAP_TYPE...)
835 */
836static int
837boot_validated_swap_type(struct boot_loader_state *state,
838 struct boot_status *bs)
839{
840 int swap_type;
Raef Colese8fe6cf2020-05-26 13:07:40 +0100841 fih_int fih_rc = FIH_FAILURE;
David Vinczee574f2d2020-07-10 11:42:03 +0200842
843 swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
844 if (BOOT_IS_UPGRADE(swap_type)) {
845 /* Boot loader wants to switch to the secondary slot.
846 * Ensure image is valid.
847 */
Raef Colese8fe6cf2020-05-26 13:07:40 +0100848 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SECONDARY_SLOT, bs);
849 if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
850 if (fih_eq(fih_rc, fih_int_encode(1))) {
851 swap_type = BOOT_SWAP_TYPE_NONE;
852 } else {
853 swap_type = BOOT_SWAP_TYPE_FAIL;
854 }
David Vinczee574f2d2020-07-10 11:42:03 +0200855 }
856 }
857
858 return swap_type;
859}
David Brown94ed12c2021-05-26 16:28:14 -0600860#endif
David Vinczee574f2d2020-07-10 11:42:03 +0200861
Christopher Collins92ea77f2016-12-12 15:59:26 -0800862/**
Christopher Collins92ea77f2016-12-12 15:59:26 -0800863 * Erases a region of flash.
864 *
Fabio Utzigba829042018-09-18 08:29:34 -0300865 * @param flash_area The flash_area containing the region to erase.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800866 * @param off The offset within the flash area to start the
867 * erase.
868 * @param sz The number of bytes to erase.
869 *
870 * @return 0 on success; nonzero on failure.
871 */
Fabio Utzig12d59162019-11-28 10:01:59 -0300872int
Fabio Utzigc28005b2019-09-10 12:18:29 -0300873boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800874{
Fabio Utzigba829042018-09-18 08:29:34 -0300875 return flash_area_erase(fap, off, sz);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800876}
877
David Brown94ed12c2021-05-26 16:28:14 -0600878#if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800879/**
880 * Copies the contents of one flash region to another. You must erase the
881 * destination region prior to calling this function.
882 *
883 * @param flash_area_id_src The ID of the source flash area.
884 * @param flash_area_id_dst The ID of the destination flash area.
885 * @param off_src The offset within the source flash area to
886 * copy from.
887 * @param off_dst The offset within the destination flash area to
888 * copy to.
889 * @param sz The number of bytes to copy.
890 *
891 * @return 0 on success; nonzero on failure.
892 */
Fabio Utzig12d59162019-11-28 10:01:59 -0300893int
Fabio Utzigc28005b2019-09-10 12:18:29 -0300894boot_copy_region(struct boot_loader_state *state,
Fabio Utzig10ee6482019-08-01 12:04:52 -0300895 const struct flash_area *fap_src,
Fabio Utzigba829042018-09-18 08:29:34 -0300896 const struct flash_area *fap_dst,
Christopher Collins92ea77f2016-12-12 15:59:26 -0800897 uint32_t off_src, uint32_t off_dst, uint32_t sz)
898{
Christopher Collins92ea77f2016-12-12 15:59:26 -0800899 uint32_t bytes_copied;
900 int chunk_sz;
901 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300902#ifdef MCUBOOT_ENC_IMAGES
903 uint32_t off;
Fabio Utziga87cc7d2019-08-26 11:21:45 -0300904 uint32_t tlv_off;
Fabio Utzigba829042018-09-18 08:29:34 -0300905 size_t blk_off;
906 struct image_header *hdr;
907 uint16_t idx;
908 uint32_t blk_sz;
Fabio Utzigb0f04732019-07-31 09:49:19 -0300909 uint8_t image_index;
Fabio Utzigba829042018-09-18 08:29:34 -0300910#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800911
Marek Pietae51ec072021-07-15 14:53:10 +0200912 TARGET_STATIC uint8_t buf[1024] __attribute__((aligned(4)));
Fabio Utzig10ee6482019-08-01 12:04:52 -0300913
914#if !defined(MCUBOOT_ENC_IMAGES)
915 (void)state;
916#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -0800917
Christopher Collins92ea77f2016-12-12 15:59:26 -0800918 bytes_copied = 0;
919 while (bytes_copied < sz) {
920 if (sz - bytes_copied > sizeof buf) {
921 chunk_sz = sizeof buf;
922 } else {
923 chunk_sz = sz - bytes_copied;
924 }
925
926 rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz);
927 if (rc != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -0300928 return BOOT_EFLASH;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800929 }
930
Fabio Utzigba829042018-09-18 08:29:34 -0300931#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig10ee6482019-08-01 12:04:52 -0300932 image_index = BOOT_CURR_IMG(state);
Dominik Ermel260ae092021-04-23 05:38:45 +0000933 if ((flash_area_get_id(fap_src) == FLASH_AREA_IMAGE_SECONDARY(image_index) ||
934 flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_SECONDARY(image_index)) &&
935 !(flash_area_get_id(fap_src) == FLASH_AREA_IMAGE_SECONDARY(image_index) &&
936 flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_SECONDARY(image_index))) {
David Vincze2d736ad2019-02-18 11:50:22 +0100937 /* assume the secondary slot as src, needs decryption */
Fabio Utzig10ee6482019-08-01 12:04:52 -0300938 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
Fabio Utzig74aef312019-11-28 11:05:34 -0300939#if !defined(MCUBOOT_SWAP_USING_MOVE)
Fabio Utzigba829042018-09-18 08:29:34 -0300940 off = off_src;
Dominik Ermel260ae092021-04-23 05:38:45 +0000941 if (flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
David Vincze2d736ad2019-02-18 11:50:22 +0100942 /* might need encryption (metadata from the primary slot) */
Fabio Utzig10ee6482019-08-01 12:04:52 -0300943 hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
Fabio Utzigba829042018-09-18 08:29:34 -0300944 off = off_dst;
945 }
Fabio Utzig74aef312019-11-28 11:05:34 -0300946#else
947 off = off_dst;
Dominik Ermel260ae092021-04-23 05:38:45 +0000948 if (flash_area_get_id(fap_dst) == FLASH_AREA_IMAGE_SECONDARY(image_index)) {
Fabio Utzig74aef312019-11-28 11:05:34 -0300949 hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
950 }
951#endif
Fabio Utzig2fc80df2018-12-14 06:47:38 -0200952 if (IS_ENCRYPTED(hdr)) {
Fabio Utzigba829042018-09-18 08:29:34 -0300953 blk_sz = chunk_sz;
954 idx = 0;
955 if (off + bytes_copied < hdr->ih_hdr_size) {
956 /* do not decrypt header */
957 blk_off = 0;
958 blk_sz = chunk_sz - hdr->ih_hdr_size;
959 idx = hdr->ih_hdr_size;
960 } else {
961 blk_off = ((off + bytes_copied) - hdr->ih_hdr_size) & 0xf;
962 }
Fabio Utziga87cc7d2019-08-26 11:21:45 -0300963 tlv_off = BOOT_TLV_OFF(hdr);
964 if (off + bytes_copied + chunk_sz > tlv_off) {
Fabio Utzigba829042018-09-18 08:29:34 -0300965 /* do not decrypt TLVs */
Fabio Utziga87cc7d2019-08-26 11:21:45 -0300966 if (off + bytes_copied >= tlv_off) {
Fabio Utzigba829042018-09-18 08:29:34 -0300967 blk_sz = 0;
968 } else {
Fabio Utziga87cc7d2019-08-26 11:21:45 -0300969 blk_sz = tlv_off - (off + bytes_copied);
Fabio Utzigba829042018-09-18 08:29:34 -0300970 }
971 }
Fabio Utzig1e4284b2019-08-23 11:55:27 -0300972 boot_encrypt(BOOT_CURR_ENC(state), image_index, fap_src,
Fabio Utzigb0f04732019-07-31 09:49:19 -0300973 (off + bytes_copied + idx) - hdr->ih_hdr_size, blk_sz,
974 blk_off, &buf[idx]);
Fabio Utzigba829042018-09-18 08:29:34 -0300975 }
976 }
977#endif
978
Christopher Collins92ea77f2016-12-12 15:59:26 -0800979 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
980 if (rc != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -0300981 return BOOT_EFLASH;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800982 }
983
984 bytes_copied += chunk_sz;
Fabio Utzig853657c2019-05-07 08:06:07 -0300985
986 MCUBOOT_WATCHDOG_FEED();
Christopher Collins92ea77f2016-12-12 15:59:26 -0800987 }
988
Fabio Utzigba829042018-09-18 08:29:34 -0300989 return 0;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800990}
991
Christopher Collins92ea77f2016-12-12 15:59:26 -0800992/**
David Vincze2d736ad2019-02-18 11:50:22 +0100993 * Overwrite primary slot with the image contained in the secondary slot.
994 * If a prior copy operation was interrupted by a system reset, this function
995 * redos the copy.
Christopher Collins92ea77f2016-12-12 15:59:26 -0800996 *
997 * @param bs The current boot status. This function reads
998 * this struct to determine if it is resuming
999 * an interrupted swap operation. This
1000 * function writes the updated status to this
1001 * function on return.
1002 *
1003 * @return 0 on success; nonzero on failure.
1004 */
Fabio Utzig338a19f2018-12-03 08:37:08 -02001005#if defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_BOOTSTRAP)
David Brown17609d82017-05-05 09:41:34 -06001006static int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001007boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
David Brown17609d82017-05-05 09:41:34 -06001008{
Marti Bolivard3269fd2017-06-12 16:31:12 -04001009 size_t sect_count;
1010 size_t sect;
David Brown17609d82017-05-05 09:41:34 -06001011 int rc;
Fabio Utzig13d9e352017-10-05 20:32:31 -03001012 size_t size;
Marti Bolivard3269fd2017-06-12 16:31:12 -04001013 size_t this_size;
Fabio Utzig13d9e352017-10-05 20:32:31 -03001014 size_t last_sector;
David Vincze2d736ad2019-02-18 11:50:22 +01001015 const struct flash_area *fap_primary_slot;
1016 const struct flash_area *fap_secondary_slot;
Fabio Utzigb0f04732019-07-31 09:49:19 -03001017 uint8_t image_index;
David Vincze2d736ad2019-02-18 11:50:22 +01001018
Fabio Utzigb4f88102020-10-04 10:16:24 -03001019#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1020 uint32_t sector;
1021 uint32_t trailer_sz;
1022 uint32_t off;
1023 uint32_t sz;
1024#endif
1025
Fabio Utzigaaf767c2017-12-05 10:22:46 -02001026 (void)bs;
1027
Fabio Utzig13d9e352017-10-05 20:32:31 -03001028#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1029 uint32_t src_size = 0;
Fabio Utzigd638b172019-08-09 10:38:05 -03001030 rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &src_size);
Fabio Utzig13d9e352017-10-05 20:32:31 -03001031 assert(rc == 0);
1032#endif
David Brown17609d82017-05-05 09:41:34 -06001033
David Vincze2d736ad2019-02-18 11:50:22 +01001034 BOOT_LOG_INF("Image upgrade secondary slot -> primary slot");
1035 BOOT_LOG_INF("Erasing the primary slot");
David Brown17609d82017-05-05 09:41:34 -06001036
Fabio Utzigb0f04732019-07-31 09:49:19 -03001037 image_index = BOOT_CURR_IMG(state);
1038
1039 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
1040 &fap_primary_slot);
Fabio Utzigba829042018-09-18 08:29:34 -03001041 assert (rc == 0);
1042
Fabio Utzigb0f04732019-07-31 09:49:19 -03001043 rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index),
1044 &fap_secondary_slot);
Fabio Utzigba829042018-09-18 08:29:34 -03001045 assert (rc == 0);
1046
Fabio Utzig10ee6482019-08-01 12:04:52 -03001047 sect_count = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
Fabio Utzig13d9e352017-10-05 20:32:31 -03001048 for (sect = 0, size = 0; sect < sect_count; sect++) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001049 this_size = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sect);
Fabio Utzigc28005b2019-09-10 12:18:29 -03001050 rc = boot_erase_region(fap_primary_slot, size, this_size);
David Brown17609d82017-05-05 09:41:34 -06001051 assert(rc == 0);
1052
Fabio Utzig13d9e352017-10-05 20:32:31 -03001053#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
Fabio Utzigb4f88102020-10-04 10:16:24 -03001054 if ((size + this_size) >= src_size) {
1055 size += src_size - size;
1056 size += BOOT_WRITE_SZ(state) - (size % BOOT_WRITE_SZ(state));
Fabio Utzig13d9e352017-10-05 20:32:31 -03001057 break;
1058 }
1059#endif
Fabio Utzigb4f88102020-10-04 10:16:24 -03001060
1061 size += this_size;
David Brown17609d82017-05-05 09:41:34 -06001062 }
1063
Fabio Utzigb4f88102020-10-04 10:16:24 -03001064#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1065 trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
1066 sector = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1;
1067 sz = 0;
1068 do {
1069 sz += boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sector);
1070 off = boot_img_sector_off(state, BOOT_PRIMARY_SLOT, sector);
1071 sector--;
1072 } while (sz < trailer_sz);
1073
1074 rc = boot_erase_region(fap_primary_slot, off, sz);
1075 assert(rc == 0);
1076#endif
1077
Fabio Utzigba829042018-09-18 08:29:34 -03001078#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig10ee6482019-08-01 12:04:52 -03001079 if (IS_ENCRYPTED(boot_img_hdr(state, BOOT_SECONDARY_SLOT))) {
Fabio Utzig1e4284b2019-08-23 11:55:27 -03001080 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index,
Fabio Utzig10ee6482019-08-01 12:04:52 -03001081 boot_img_hdr(state, BOOT_SECONDARY_SLOT),
Fabio Utzig4741c452019-12-19 15:32:41 -03001082 fap_secondary_slot, bs);
David Vincze2d736ad2019-02-18 11:50:22 +01001083
Fabio Utzigba829042018-09-18 08:29:34 -03001084 if (rc < 0) {
1085 return BOOT_EBADIMAGE;
1086 }
Fabio Utzig4741c452019-12-19 15:32:41 -03001087 if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) {
Fabio Utzigba829042018-09-18 08:29:34 -03001088 return BOOT_EBADIMAGE;
1089 }
1090 }
1091#endif
1092
David Vincze2d736ad2019-02-18 11:50:22 +01001093 BOOT_LOG_INF("Copying the secondary slot to the primary slot: 0x%zx bytes",
1094 size);
Fabio Utzigc28005b2019-09-10 12:18:29 -03001095 rc = boot_copy_region(state, fap_secondary_slot, fap_primary_slot, 0, 0, size);
Fabio Utzigb4f88102020-10-04 10:16:24 -03001096 if (rc != 0) {
1097 return rc;
1098 }
1099
1100#if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1101 rc = boot_write_magic(fap_primary_slot);
1102 if (rc != 0) {
1103 return rc;
1104 }
1105#endif
David Brown17609d82017-05-05 09:41:34 -06001106
David Vinczec3084132020-02-18 14:50:47 +01001107#ifdef MCUBOOT_HW_ROLLBACK_PROT
1108 /* Update the stored security counter with the new image's security counter
1109 * value. Both slots hold the new image at this point, but the secondary
1110 * slot's image header must be passed since the image headers in the
1111 * boot_data structure have not been updated yet.
1112 */
1113 rc = boot_update_security_counter(BOOT_CURR_IMG(state), BOOT_PRIMARY_SLOT,
1114 boot_img_hdr(state, BOOT_SECONDARY_SLOT));
1115 if (rc != 0) {
1116 BOOT_LOG_ERR("Security counter update failed after image upgrade.");
1117 return rc;
1118 }
1119#endif /* MCUBOOT_HW_ROLLBACK_PROT */
1120
Fabio Utzig13d9e352017-10-05 20:32:31 -03001121 /*
1122 * Erases header and trailer. The trailer is erased because when a new
1123 * image is written without a trailer as is the case when using newt, the
1124 * trailer that was left might trigger a new upgrade.
1125 */
Christopher Collins2c88e692019-05-22 15:10:14 -07001126 BOOT_LOG_DBG("erasing secondary header");
Fabio Utzigc28005b2019-09-10 12:18:29 -03001127 rc = boot_erase_region(fap_secondary_slot,
Fabio Utzig10ee6482019-08-01 12:04:52 -03001128 boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0),
1129 boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0));
David Brown17609d82017-05-05 09:41:34 -06001130 assert(rc == 0);
Fabio Utzig10ee6482019-08-01 12:04:52 -03001131 last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1;
Christopher Collins2c88e692019-05-22 15:10:14 -07001132 BOOT_LOG_DBG("erasing secondary trailer");
Fabio Utzigc28005b2019-09-10 12:18:29 -03001133 rc = boot_erase_region(fap_secondary_slot,
Fabio Utzig10ee6482019-08-01 12:04:52 -03001134 boot_img_sector_off(state, BOOT_SECONDARY_SLOT,
1135 last_sector),
1136 boot_img_sector_size(state, BOOT_SECONDARY_SLOT,
1137 last_sector));
Fabio Utzig13d9e352017-10-05 20:32:31 -03001138 assert(rc == 0);
1139
David Vincze2d736ad2019-02-18 11:50:22 +01001140 flash_area_close(fap_primary_slot);
1141 flash_area_close(fap_secondary_slot);
Fabio Utzigba829042018-09-18 08:29:34 -03001142
David Vincze2d736ad2019-02-18 11:50:22 +01001143 /* TODO: Perhaps verify the primary slot's signature again? */
David Brown17609d82017-05-05 09:41:34 -06001144
1145 return 0;
1146}
Fabio Utzig338a19f2018-12-03 08:37:08 -02001147#endif
Fabio Utzigba829042018-09-18 08:29:34 -03001148
Christopher Collinsa1c12042019-05-23 14:00:28 -07001149#if !defined(MCUBOOT_OVERWRITE_ONLY)
Fabio Utzigba829042018-09-18 08:29:34 -03001150/**
1151 * Swaps the two images in flash. If a prior copy operation was interrupted
1152 * by a system reset, this function completes that operation.
1153 *
1154 * @param bs The current boot status. This function reads
1155 * this struct to determine if it is resuming
1156 * an interrupted swap operation. This
1157 * function writes the updated status to this
1158 * function on return.
1159 *
1160 * @return 0 on success; nonzero on failure.
1161 */
Christopher Collins92ea77f2016-12-12 15:59:26 -08001162static int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001163boot_swap_image(struct boot_loader_state *state, struct boot_status *bs)
Christopher Collins92ea77f2016-12-12 15:59:26 -08001164{
Fabio Utzig2473ac02017-05-02 12:45:02 -03001165 struct image_header *hdr;
Fabio Utzigba829042018-09-18 08:29:34 -03001166#ifdef MCUBOOT_ENC_IMAGES
1167 const struct flash_area *fap;
1168 uint8_t slot;
1169 uint8_t i;
Fabio Utzigba829042018-09-18 08:29:34 -03001170#endif
Fabio Utzig2473ac02017-05-02 12:45:02 -03001171 uint32_t size;
1172 uint32_t copy_size;
Fabio Utzigb0f04732019-07-31 09:49:19 -03001173 uint8_t image_index;
Fabio Utzig2473ac02017-05-02 12:45:02 -03001174 int rc;
1175
1176 /* FIXME: just do this if asked by user? */
1177
1178 size = copy_size = 0;
Fabio Utzig10ee6482019-08-01 12:04:52 -03001179 image_index = BOOT_CURR_IMG(state);
Fabio Utzig2473ac02017-05-02 12:45:02 -03001180
Fabio Utzig12d59162019-11-28 10:01:59 -03001181 if (boot_status_is_reset(bs)) {
Fabio Utzig46490722017-09-04 15:34:32 -03001182 /*
1183 * No swap ever happened, so need to find the largest image which
1184 * will be used to determine the amount of sectors to swap.
1185 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001186 hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
Fabio Utzig2473ac02017-05-02 12:45:02 -03001187 if (hdr->ih_magic == IMAGE_MAGIC) {
Fabio Utzigd638b172019-08-09 10:38:05 -03001188 rc = boot_read_image_size(state, BOOT_PRIMARY_SLOT, &copy_size);
David Brownf5b33d82017-09-01 10:58:27 -06001189 assert(rc == 0);
Fabio Utzig2473ac02017-05-02 12:45:02 -03001190 }
Fabio Utzig2473ac02017-05-02 12:45:02 -03001191
Fabio Utzigba829042018-09-18 08:29:34 -03001192#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig2fc80df2018-12-14 06:47:38 -02001193 if (IS_ENCRYPTED(hdr)) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001194 fap = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
Fabio Utzig4741c452019-12-19 15:32:41 -03001195 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001196 assert(rc >= 0);
1197
1198 if (rc == 0) {
Fabio Utzig4741c452019-12-19 15:32:41 -03001199 rc = boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001200 assert(rc == 0);
1201 } else {
1202 rc = 0;
1203 }
1204 } else {
1205 memset(bs->enckey[0], 0xff, BOOT_ENC_KEY_SIZE);
1206 }
1207#endif
1208
Fabio Utzig10ee6482019-08-01 12:04:52 -03001209 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
Fabio Utzig46490722017-09-04 15:34:32 -03001210 if (hdr->ih_magic == IMAGE_MAGIC) {
Fabio Utzigd638b172019-08-09 10:38:05 -03001211 rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &size);
Fabio Utzig46490722017-09-04 15:34:32 -03001212 assert(rc == 0);
1213 }
1214
Fabio Utzigba829042018-09-18 08:29:34 -03001215#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig10ee6482019-08-01 12:04:52 -03001216 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
Fabio Utzig2fc80df2018-12-14 06:47:38 -02001217 if (IS_ENCRYPTED(hdr)) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001218 fap = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
Fabio Utzig4741c452019-12-19 15:32:41 -03001219 rc = boot_enc_load(BOOT_CURR_ENC(state), image_index, hdr, fap, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001220 assert(rc >= 0);
1221
1222 if (rc == 0) {
Fabio Utzig4741c452019-12-19 15:32:41 -03001223 rc = boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001224 assert(rc == 0);
1225 } else {
1226 rc = 0;
1227 }
1228 } else {
1229 memset(bs->enckey[1], 0xff, BOOT_ENC_KEY_SIZE);
1230 }
1231#endif
1232
Fabio Utzig46490722017-09-04 15:34:32 -03001233 if (size > copy_size) {
1234 copy_size = size;
1235 }
1236
1237 bs->swap_size = copy_size;
1238 } else {
1239 /*
1240 * If a swap was under way, the swap_size should already be present
1241 * in the trailer...
1242 */
Fabio Utzigb0f04732019-07-31 09:49:19 -03001243 rc = boot_read_swap_size(image_index, &bs->swap_size);
Fabio Utzig46490722017-09-04 15:34:32 -03001244 assert(rc == 0);
1245
1246 copy_size = bs->swap_size;
Fabio Utzigba829042018-09-18 08:29:34 -03001247
1248#ifdef MCUBOOT_ENC_IMAGES
Fabio Utzig4741c452019-12-19 15:32:41 -03001249 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1250 rc = boot_read_enc_key(image_index, slot, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001251 assert(rc == 0);
1252
1253 for (i = 0; i < BOOT_ENC_KEY_SIZE; i++) {
Fabio Utzig1c7d9592018-12-03 10:35:56 -02001254 if (bs->enckey[slot][i] != 0xff) {
Fabio Utzigba829042018-09-18 08:29:34 -03001255 break;
1256 }
1257 }
1258
1259 if (i != BOOT_ENC_KEY_SIZE) {
Fabio Utzig4741c452019-12-19 15:32:41 -03001260 boot_enc_set_key(BOOT_CURR_ENC(state), slot, bs);
Fabio Utzigba829042018-09-18 08:29:34 -03001261 }
1262 }
1263#endif
Fabio Utzig2473ac02017-05-02 12:45:02 -03001264 }
1265
Fabio Utzig12d59162019-11-28 10:01:59 -03001266 swap_run(state, bs, copy_size);
Christopher Collins92ea77f2016-12-12 15:59:26 -08001267
David Vincze2d736ad2019-02-18 11:50:22 +01001268#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
Fabio Utzig12d59162019-11-28 10:01:59 -03001269 extern int boot_status_fails;
Fabio Utziga0e1cce2017-11-23 20:04:01 -02001270 if (boot_status_fails > 0) {
Christopher Collins2c88e692019-05-22 15:10:14 -07001271 BOOT_LOG_WRN("%d status write fails performing the swap",
1272 boot_status_fails);
Fabio Utziga0e1cce2017-11-23 20:04:01 -02001273 }
1274#endif
1275
Christopher Collins92ea77f2016-12-12 15:59:26 -08001276 return 0;
1277}
David Brown17609d82017-05-05 09:41:34 -06001278#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -08001279
David Vinczee32483f2019-06-13 10:46:24 +02001280#if (BOOT_IMAGE_NUMBER > 1)
1281/**
1282 * Check the image dependency whether it is satisfied and modify
1283 * the swap type if necessary.
1284 *
1285 * @param dep Image dependency which has to be verified.
1286 *
1287 * @return 0 on success; nonzero on failure.
1288 */
1289static int
Fabio Utzig298913b2019-08-28 11:22:45 -03001290boot_verify_slot_dependency(struct boot_loader_state *state,
1291 struct image_dependency *dep)
David Vinczee32483f2019-06-13 10:46:24 +02001292{
1293 struct image_version *dep_version;
1294 size_t dep_slot;
1295 int rc;
David Browne6ab34c2019-09-03 12:24:21 -06001296 uint8_t swap_type;
David Vinczee32483f2019-06-13 10:46:24 +02001297
1298 /* Determine the source of the image which is the subject of
1299 * the dependency and get it's version. */
David Browne6ab34c2019-09-03 12:24:21 -06001300 swap_type = state->swap_type[dep->image_id];
Barry Solomon04075532020-03-18 09:33:32 -04001301 dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SECONDARY_SLOT
1302 : BOOT_PRIMARY_SLOT;
Fabio Utzig10ee6482019-08-01 12:04:52 -03001303 dep_version = &state->imgs[dep->image_id][dep_slot].hdr.ih_ver;
David Vinczee32483f2019-06-13 10:46:24 +02001304
David Vincze8b0b6372020-05-20 19:54:44 +02001305 rc = boot_version_cmp(dep_version, &dep->image_min_version);
1306 if (rc < 0) {
David Vinczee32483f2019-06-13 10:46:24 +02001307 /* Dependency not satisfied.
1308 * Modify the swap type to decrease the version number of the image
1309 * (which will be located in the primary slot after the boot process),
1310 * consequently the number of unsatisfied dependencies will be
1311 * decreased or remain the same.
1312 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001313 switch (BOOT_SWAP_TYPE(state)) {
David Vinczee32483f2019-06-13 10:46:24 +02001314 case BOOT_SWAP_TYPE_TEST:
1315 case BOOT_SWAP_TYPE_PERM:
Fabio Utzig10ee6482019-08-01 12:04:52 -03001316 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
David Vinczee32483f2019-06-13 10:46:24 +02001317 break;
1318 case BOOT_SWAP_TYPE_NONE:
Fabio Utzig10ee6482019-08-01 12:04:52 -03001319 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT;
David Vinczee32483f2019-06-13 10:46:24 +02001320 break;
1321 default:
1322 break;
1323 }
David Vincze8b0b6372020-05-20 19:54:44 +02001324 } else {
1325 /* Dependency satisfied. */
1326 rc = 0;
David Vinczee32483f2019-06-13 10:46:24 +02001327 }
1328
1329 return rc;
1330}
1331
1332/**
1333 * Read all dependency TLVs of an image from the flash and verify
1334 * one after another to see if they are all satisfied.
1335 *
1336 * @param slot Image slot number.
1337 *
1338 * @return 0 on success; nonzero on failure.
1339 */
1340static int
Fabio Utzig298913b2019-08-28 11:22:45 -03001341boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot)
David Vinczee32483f2019-06-13 10:46:24 +02001342{
1343 const struct flash_area *fap;
Fabio Utzig61fd8882019-09-14 20:00:20 -03001344 struct image_tlv_iter it;
David Vinczee32483f2019-06-13 10:46:24 +02001345 struct image_dependency dep;
1346 uint32_t off;
Fabio Utzig61fd8882019-09-14 20:00:20 -03001347 uint16_t len;
Fabio Utzigb0f04732019-07-31 09:49:19 -03001348 int area_id;
David Vinczee32483f2019-06-13 10:46:24 +02001349 int rc;
1350
Fabio Utzig10ee6482019-08-01 12:04:52 -03001351 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
Fabio Utzigb0f04732019-07-31 09:49:19 -03001352 rc = flash_area_open(area_id, &fap);
David Vinczee32483f2019-06-13 10:46:24 +02001353 if (rc != 0) {
1354 rc = BOOT_EFLASH;
1355 goto done;
1356 }
1357
Fabio Utzig61fd8882019-09-14 20:00:20 -03001358 rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, slot), fap,
1359 IMAGE_TLV_DEPENDENCY, true);
David Vinczee32483f2019-06-13 10:46:24 +02001360 if (rc != 0) {
David Vinczee32483f2019-06-13 10:46:24 +02001361 goto done;
1362 }
1363
Fabio Utzig61fd8882019-09-14 20:00:20 -03001364 while (true) {
1365 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
1366 if (rc < 0) {
1367 return -1;
1368 } else if (rc > 0) {
1369 rc = 0;
David Vinczee32483f2019-06-13 10:46:24 +02001370 break;
1371 }
Fabio Utzig61fd8882019-09-14 20:00:20 -03001372
1373 if (len != sizeof(dep)) {
1374 rc = BOOT_EBADIMAGE;
1375 goto done;
1376 }
1377
1378 rc = flash_area_read(fap, off, &dep, len);
1379 if (rc != 0) {
1380 rc = BOOT_EFLASH;
1381 goto done;
1382 }
1383
1384 if (dep.image_id >= BOOT_IMAGE_NUMBER) {
1385 rc = BOOT_EBADARGS;
1386 goto done;
1387 }
1388
1389 /* Verify dependency and modify the swap type if not satisfied. */
1390 rc = boot_verify_slot_dependency(state, &dep);
1391 if (rc != 0) {
1392 /* Dependency not satisfied. */
1393 goto done;
1394 }
David Vinczee32483f2019-06-13 10:46:24 +02001395 }
1396
1397done:
1398 flash_area_close(fap);
1399 return rc;
1400}
1401
1402/**
David Vinczee32483f2019-06-13 10:46:24 +02001403 * Iterate over all the images and verify whether the image dependencies in the
1404 * TLV area are all satisfied and update the related swap type if necessary.
1405 */
Fabio Utzig298913b2019-08-28 11:22:45 -03001406static int
1407boot_verify_dependencies(struct boot_loader_state *state)
David Vinczee32483f2019-06-13 10:46:24 +02001408{
Erik Johnson49063752020-02-06 09:59:31 -06001409 int rc = -1;
Fabio Utzig298913b2019-08-28 11:22:45 -03001410 uint8_t slot;
David Vinczee32483f2019-06-13 10:46:24 +02001411
Fabio Utzig10ee6482019-08-01 12:04:52 -03001412 BOOT_CURR_IMG(state) = 0;
1413 while (BOOT_CURR_IMG(state) < BOOT_IMAGE_NUMBER) {
Fabio Utzig298913b2019-08-28 11:22:45 -03001414 if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE &&
1415 BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_FAIL) {
1416 slot = BOOT_SECONDARY_SLOT;
1417 } else {
1418 slot = BOOT_PRIMARY_SLOT;
1419 }
1420
1421 rc = boot_verify_slot_dependencies(state, slot);
Fabio Utzigabec0732019-07-31 08:40:22 -03001422 if (rc == 0) {
David Vinczee32483f2019-06-13 10:46:24 +02001423 /* All dependencies've been satisfied, continue with next image. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001424 BOOT_CURR_IMG(state)++;
David Vincze8b0b6372020-05-20 19:54:44 +02001425 } else {
Fabio Utzig298913b2019-08-28 11:22:45 -03001426 /* Cannot upgrade due to non-met dependencies, so disable all
1427 * image upgrades.
1428 */
1429 for (int idx = 0; idx < BOOT_IMAGE_NUMBER; idx++) {
1430 BOOT_CURR_IMG(state) = idx;
1431 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
1432 }
1433 break;
David Vinczee32483f2019-06-13 10:46:24 +02001434 }
1435 }
Fabio Utzig298913b2019-08-28 11:22:45 -03001436 return rc;
David Vinczee32483f2019-06-13 10:46:24 +02001437}
1438#endif /* (BOOT_IMAGE_NUMBER > 1) */
1439
Christopher Collins92ea77f2016-12-12 15:59:26 -08001440/**
David Vinczeba3bd602019-06-17 16:01:43 +02001441 * Performs a clean (not aborted) image update.
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001442 *
David Vinczeba3bd602019-06-17 16:01:43 +02001443 * @param bs The current boot status.
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001444 *
1445 * @return 0 on success; nonzero on failure.
1446 */
1447static int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001448boot_perform_update(struct boot_loader_state *state, struct boot_status *bs)
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001449{
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001450 int rc;
Fabio Utzig10ee6482019-08-01 12:04:52 -03001451#ifndef MCUBOOT_OVERWRITE_ONLY
1452 uint8_t swap_type;
1453#endif
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001454
David Vinczeba3bd602019-06-17 16:01:43 +02001455 /* At this point there are no aborted swaps. */
1456#if defined(MCUBOOT_OVERWRITE_ONLY)
Fabio Utzig10ee6482019-08-01 12:04:52 -03001457 rc = boot_copy_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001458#elif defined(MCUBOOT_BOOTSTRAP)
1459 /* Check if the image update was triggered by a bad image in the
1460 * primary slot (the validity of the image in the secondary slot had
1461 * already been checked).
1462 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01001463 fih_int fih_rc = FIH_FAILURE;
1464 rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT);
1465 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, bs);
1466 if (rc == 0 || fih_not_eq(fih_rc, FIH_SUCCESS)) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001467 rc = boot_copy_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001468 } else {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001469 rc = boot_swap_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001470 }
1471#else
Fabio Utzig10ee6482019-08-01 12:04:52 -03001472 rc = boot_swap_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001473#endif
Fabio Utzig7ebb7c22017-04-26 10:59:31 -03001474 assert(rc == 0);
David Vinczeba3bd602019-06-17 16:01:43 +02001475
1476#ifndef MCUBOOT_OVERWRITE_ONLY
1477 /* The following state needs image_ok be explicitly set after the
1478 * swap was finished to avoid a new revert.
1479 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001480 swap_type = BOOT_SWAP_TYPE(state);
1481 if (swap_type == BOOT_SWAP_TYPE_REVERT ||
1482 swap_type == BOOT_SWAP_TYPE_PERM) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001483 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001484 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001485 BOOT_SWAP_TYPE(state) = swap_type = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001486 }
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001487 }
1488
David Vinczec3084132020-02-18 14:50:47 +01001489#ifdef MCUBOOT_HW_ROLLBACK_PROT
1490 if (swap_type == BOOT_SWAP_TYPE_PERM) {
1491 /* Update the stored security counter with the new image's security
1492 * counter value. The primary slot holds the new image at this point,
1493 * but the secondary slot's image header must be passed since image
1494 * headers in the boot_data structure have not been updated yet.
1495 *
1496 * In case of a permanent image swap mcuboot will never attempt to
1497 * revert the images on the next reboot. Therefore, the security
1498 * counter must be increased right after the image upgrade.
1499 */
1500 rc = boot_update_security_counter(
1501 BOOT_CURR_IMG(state),
1502 BOOT_PRIMARY_SLOT,
1503 boot_img_hdr(state, BOOT_SECONDARY_SLOT));
1504 if (rc != 0) {
1505 BOOT_LOG_ERR("Security counter update failed after "
1506 "image upgrade.");
1507 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1508 }
1509 }
1510#endif /* MCUBOOT_HW_ROLLBACK_PROT */
1511
Fabio Utzige575b0b2019-09-11 12:34:23 -03001512 if (BOOT_IS_UPGRADE(swap_type)) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001513 rc = swap_set_copy_done(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001514 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001515 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
Christopher Collinsa1c12042019-05-23 14:00:28 -07001516 }
David Vinczeba3bd602019-06-17 16:01:43 +02001517 }
1518#endif /* !MCUBOOT_OVERWRITE_ONLY */
Fabio Utzig338a19f2018-12-03 08:37:08 -02001519
David Vinczeba3bd602019-06-17 16:01:43 +02001520 return rc;
1521}
1522
1523/**
1524 * Completes a previously aborted image swap.
1525 *
1526 * @param bs The current boot status.
1527 *
1528 * @return 0 on success; nonzero on failure.
1529 */
1530#if !defined(MCUBOOT_OVERWRITE_ONLY)
1531static int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001532boot_complete_partial_swap(struct boot_loader_state *state,
1533 struct boot_status *bs)
David Vinczeba3bd602019-06-17 16:01:43 +02001534{
1535 int rc;
1536
1537 /* Determine the type of swap operation being resumed from the
1538 * `swap-type` trailer field.
1539 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001540 rc = boot_swap_image(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001541 assert(rc == 0);
1542
Fabio Utzig10ee6482019-08-01 12:04:52 -03001543 BOOT_SWAP_TYPE(state) = bs->swap_type;
David Vinczeba3bd602019-06-17 16:01:43 +02001544
1545 /* The following states need image_ok be explicitly set after the
1546 * swap was finished to avoid a new revert.
1547 */
1548 if (bs->swap_type == BOOT_SWAP_TYPE_REVERT ||
1549 bs->swap_type == BOOT_SWAP_TYPE_PERM) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001550 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001551 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001552 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001553 }
1554 }
1555
Fabio Utzige575b0b2019-09-11 12:34:23 -03001556 if (BOOT_IS_UPGRADE(bs->swap_type)) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001557 rc = swap_set_copy_done(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001558 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001559 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001560 }
1561 }
1562
Fabio Utzig10ee6482019-08-01 12:04:52 -03001563 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
David Vinczeba3bd602019-06-17 16:01:43 +02001564 BOOT_LOG_ERR("panic!");
1565 assert(0);
1566
1567 /* Loop forever... */
1568 while (1) {}
1569 }
1570
1571 return rc;
1572}
1573#endif /* !MCUBOOT_OVERWRITE_ONLY */
1574
1575#if (BOOT_IMAGE_NUMBER > 1)
1576/**
1577 * Review the validity of previously determined swap types of other images.
1578 *
1579 * @param aborted_swap The current image upgrade is a
1580 * partial/aborted swap.
1581 */
1582static void
Fabio Utzig10ee6482019-08-01 12:04:52 -03001583boot_review_image_swap_types(struct boot_loader_state *state,
1584 bool aborted_swap)
David Vinczeba3bd602019-06-17 16:01:43 +02001585{
1586 /* In that case if we rebooted in the middle of an image upgrade process, we
1587 * must review the validity of swap types, that were previously determined
1588 * for other images. The image_ok flag had not been set before the reboot
1589 * for any of the updated images (only the copy_done flag) and thus falsely
1590 * the REVERT swap type has been determined for the previous images that had
1591 * been updated before the reboot.
1592 *
1593 * There are two separate scenarios that we have to deal with:
1594 *
1595 * 1. The reboot has happened during swapping an image:
1596 * The current image upgrade has been determined as a
1597 * partial/aborted swap.
1598 * 2. The reboot has happened between two separate image upgrades:
1599 * In this scenario we must check the swap type of the current image.
1600 * In those cases if it is NONE or REVERT we cannot certainly determine
1601 * the fact of a reboot. In a consistent state images must move in the
1602 * same direction or stay in place, e.g. in practice REVERT and TEST
1603 * swap types cannot be present at the same time. If the swap type of
1604 * the current image is either TEST, PERM or FAIL we must review the
1605 * already determined swap types of other images and set each false
1606 * REVERT swap types to NONE (these images had been successfully
1607 * updated before the system rebooted between two separate image
1608 * upgrades).
1609 */
1610
Fabio Utzig10ee6482019-08-01 12:04:52 -03001611 if (BOOT_CURR_IMG(state) == 0) {
David Vinczeba3bd602019-06-17 16:01:43 +02001612 /* Nothing to do */
1613 return;
1614 }
1615
1616 if (!aborted_swap) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001617 if ((BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) ||
1618 (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_REVERT)) {
David Vinczeba3bd602019-06-17 16:01:43 +02001619 /* Nothing to do */
1620 return;
1621 }
1622 }
1623
Fabio Utzig10ee6482019-08-01 12:04:52 -03001624 for (uint8_t i = 0; i < BOOT_CURR_IMG(state); i++) {
1625 if (state->swap_type[i] == BOOT_SWAP_TYPE_REVERT) {
1626 state->swap_type[i] = BOOT_SWAP_TYPE_NONE;
David Vinczeba3bd602019-06-17 16:01:43 +02001627 }
1628 }
1629}
1630#endif
1631
1632/**
1633 * Prepare image to be updated if required.
1634 *
1635 * Prepare image to be updated if required with completing an image swap
1636 * operation if one was aborted and/or determining the type of the
1637 * swap operation. In case of any error set the swap type to NONE.
1638 *
Fabio Utzig10ee6482019-08-01 12:04:52 -03001639 * @param state TODO
David Vinczeba3bd602019-06-17 16:01:43 +02001640 * @param bs Pointer where the read and possibly updated
1641 * boot status can be written to.
1642 */
1643static void
Fabio Utzig10ee6482019-08-01 12:04:52 -03001644boot_prepare_image_for_update(struct boot_loader_state *state,
1645 struct boot_status *bs)
David Vinczeba3bd602019-06-17 16:01:43 +02001646{
1647 int rc;
Raef Colese8fe6cf2020-05-26 13:07:40 +01001648 fih_int fih_rc = FIH_FAILURE;
David Vinczeba3bd602019-06-17 16:01:43 +02001649
1650 /* Determine the sector layout of the image slots and scratch area. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001651 rc = boot_read_sectors(state);
David Vinczeba3bd602019-06-17 16:01:43 +02001652 if (rc != 0) {
1653 BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d"
1654 " - too small?", BOOT_MAX_IMG_SECTORS);
1655 /* Unable to determine sector layout, continue with next image
1656 * if there is one.
1657 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001658 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
Andrzej Puzdrowski54b4ad92021-06-22 13:21:22 +02001659 if (rc == BOOT_EFLASH)
1660 {
1661 /* Only return on error from the primary image flash */
1662 return;
1663 }
David Vinczeba3bd602019-06-17 16:01:43 +02001664 }
1665
1666 /* Attempt to read an image header from each slot. */
Fabio Utzig12d59162019-11-28 10:01:59 -03001667 rc = boot_read_image_headers(state, false, NULL);
David Vinczeba3bd602019-06-17 16:01:43 +02001668 if (rc != 0) {
1669 /* Continue with next image if there is one. */
Fabio Utzigb0f04732019-07-31 09:49:19 -03001670 BOOT_LOG_WRN("Failed reading image headers; Image=%u",
Fabio Utzig10ee6482019-08-01 12:04:52 -03001671 BOOT_CURR_IMG(state));
1672 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
David Vinczeba3bd602019-06-17 16:01:43 +02001673 return;
1674 }
1675
1676 /* If the current image's slots aren't compatible, no swap is possible.
1677 * Just boot into primary slot.
1678 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001679 if (boot_slots_compatible(state)) {
Fabio Utzig12d59162019-11-28 10:01:59 -03001680 boot_status_reset(bs);
1681
1682#ifndef MCUBOOT_OVERWRITE_ONLY
1683 rc = swap_read_status(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001684 if (rc != 0) {
1685 BOOT_LOG_WRN("Failed reading boot status; Image=%u",
Fabio Utzig10ee6482019-08-01 12:04:52 -03001686 BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001687 /* Continue with next image if there is one. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001688 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
David Vinczeba3bd602019-06-17 16:01:43 +02001689 return;
1690 }
Fabio Utzig12d59162019-11-28 10:01:59 -03001691#endif
David Vinczeba3bd602019-06-17 16:01:43 +02001692
Fabio Utzig74aef312019-11-28 11:05:34 -03001693#ifdef MCUBOOT_SWAP_USING_MOVE
1694 /*
1695 * Must re-read image headers because the boot status might
1696 * have been updated in the previous function call.
1697 */
1698 rc = boot_read_image_headers(state, !boot_status_is_reset(bs), bs);
Fabio Utzig32afe852020-10-04 10:36:02 -03001699#ifdef MCUBOOT_BOOTSTRAP
1700 /* When bootstrapping it's OK to not have image magic in the primary slot */
1701 if (rc != 0 && (BOOT_CURR_IMG(state) != BOOT_PRIMARY_SLOT ||
1702 boot_check_header_erased(state, BOOT_PRIMARY_SLOT) != 0)) {
1703#else
Fabio Utzig74aef312019-11-28 11:05:34 -03001704 if (rc != 0) {
Fabio Utzig32afe852020-10-04 10:36:02 -03001705#endif
1706
Fabio Utzig74aef312019-11-28 11:05:34 -03001707 /* Continue with next image if there is one. */
1708 BOOT_LOG_WRN("Failed reading image headers; Image=%u",
1709 BOOT_CURR_IMG(state));
1710 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
1711 return;
1712 }
1713#endif
1714
David Vinczeba3bd602019-06-17 16:01:43 +02001715 /* Determine if we rebooted in the middle of an image swap
1716 * operation. If a partial swap was detected, complete it.
1717 */
Fabio Utzig12d59162019-11-28 10:01:59 -03001718 if (!boot_status_is_reset(bs)) {
David Vinczeba3bd602019-06-17 16:01:43 +02001719
1720#if (BOOT_IMAGE_NUMBER > 1)
Fabio Utzig10ee6482019-08-01 12:04:52 -03001721 boot_review_image_swap_types(state, true);
David Vinczeba3bd602019-06-17 16:01:43 +02001722#endif
1723
1724#ifdef MCUBOOT_OVERWRITE_ONLY
1725 /* Should never arrive here, overwrite-only mode has
1726 * no swap state.
1727 */
1728 assert(0);
1729#else
1730 /* Determine the type of swap operation being resumed from the
1731 * `swap-type` trailer field.
1732 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001733 rc = boot_complete_partial_swap(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001734 assert(rc == 0);
1735#endif
1736 /* Attempt to read an image header from each slot. Ensure that
1737 * image headers in slots are aligned with headers in boot_data.
1738 */
Fabio Utzig12d59162019-11-28 10:01:59 -03001739 rc = boot_read_image_headers(state, false, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001740 assert(rc == 0);
1741
1742 /* Swap has finished set to NONE */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001743 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
David Vinczeba3bd602019-06-17 16:01:43 +02001744 } else {
1745 /* There was no partial swap, determine swap type. */
1746 if (bs->swap_type == BOOT_SWAP_TYPE_NONE) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001747 BOOT_SWAP_TYPE(state) = boot_validated_swap_type(state, bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001748 } else {
Raef Colese8fe6cf2020-05-26 13:07:40 +01001749 FIH_CALL(boot_validate_slot, fih_rc,
1750 state, BOOT_SECONDARY_SLOT, bs);
1751 if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
1752 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_FAIL;
1753 } else {
1754 BOOT_SWAP_TYPE(state) = bs->swap_type;
1755 }
David Vinczeba3bd602019-06-17 16:01:43 +02001756 }
1757
1758#if (BOOT_IMAGE_NUMBER > 1)
Fabio Utzig10ee6482019-08-01 12:04:52 -03001759 boot_review_image_swap_types(state, false);
David Vinczeba3bd602019-06-17 16:01:43 +02001760#endif
1761
1762#ifdef MCUBOOT_BOOTSTRAP
Fabio Utzig10ee6482019-08-01 12:04:52 -03001763 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
David Vinczeba3bd602019-06-17 16:01:43 +02001764 /* Header checks are done first because they are
1765 * inexpensive. Since overwrite-only copies starting from
1766 * offset 0, if interrupted, it might leave a valid header
1767 * magic, so also run validation on the primary slot to be
1768 * sure it's not OK.
1769 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01001770 rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT);
1771 FIH_CALL(boot_validate_slot, fih_rc,
1772 state, BOOT_PRIMARY_SLOT, bs);
1773
1774 if (rc == 0 || fih_not_eq(fih_rc, FIH_SUCCESS)) {
1775
Fabio Utzig3d77c952020-10-04 10:23:17 -03001776 rc = (boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_magic == IMAGE_MAGIC) ? 1: 0;
Raef Colese8fe6cf2020-05-26 13:07:40 +01001777 FIH_CALL(boot_validate_slot, fih_rc,
1778 state, BOOT_SECONDARY_SLOT, bs);
1779
Fabio Utzig3d77c952020-10-04 10:23:17 -03001780 if (rc == 1 && fih_eq(fih_rc, FIH_SUCCESS)) {
David Vinczeba3bd602019-06-17 16:01:43 +02001781 /* Set swap type to REVERT to overwrite the primary
1782 * slot with the image contained in secondary slot
1783 * and to trigger the explicit setting of the
1784 * image_ok flag.
1785 */
Fabio Utzig59b63e52019-09-10 12:22:35 -03001786 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT;
David Vinczeba3bd602019-06-17 16:01:43 +02001787 }
Fabio Utzig338a19f2018-12-03 08:37:08 -02001788 }
1789 }
Fabio Utzig338a19f2018-12-03 08:37:08 -02001790#endif
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001791 }
David Vinczeba3bd602019-06-17 16:01:43 +02001792 } else {
1793 /* In that case if slots are not compatible. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001794 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001795 }
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001796}
1797
Mark Horvathccaf7f82021-01-04 18:16:42 +01001798/**
1799 * Updates the security counter for the current image.
1800 *
1801 * @param state Boot loader status information.
1802 *
1803 * @return 0 on success; nonzero on failure.
1804 */
1805static int
1806boot_update_hw_rollback_protection(struct boot_loader_state *state)
1807{
1808#ifdef MCUBOOT_HW_ROLLBACK_PROT
1809 int rc;
1810
1811 /* Update the stored security counter with the active image's security
1812 * counter value. It will only be updated if the new security counter is
1813 * greater than the stored value.
1814 *
1815 * In case of a successful image swapping when the swap type is TEST the
1816 * security counter can be increased only after a reset, when the swap
1817 * type is NONE and the image has marked itself "OK" (the image_ok flag
1818 * has been set). This way a "revert" can be performed when it's
1819 * necessary.
1820 */
1821 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
1822 rc = boot_update_security_counter(
1823 BOOT_CURR_IMG(state),
1824 BOOT_PRIMARY_SLOT,
1825 boot_img_hdr(state, BOOT_PRIMARY_SLOT));
1826 if (rc != 0) {
1827 BOOT_LOG_ERR("Security counter update failed after image "
1828 "validation.");
1829 return rc;
1830 }
1831 }
1832
1833 return 0;
1834
1835#else /* MCUBOOT_HW_ROLLBACK_PROT */
1836 (void) (state);
1837
1838 return 0;
1839#endif
1840}
1841
Raef Colese8fe6cf2020-05-26 13:07:40 +01001842fih_int
Fabio Utzig10ee6482019-08-01 12:04:52 -03001843context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
Christopher Collins92ea77f2016-12-12 15:59:26 -08001844{
Marti Bolivar84898652017-06-13 17:20:22 -04001845 size_t slot;
David Vinczeba3bd602019-06-17 16:01:43 +02001846 struct boot_status bs;
David Vincze9015a5d2020-05-18 14:43:11 +02001847 int rc = -1;
Raef Colese8fe6cf2020-05-26 13:07:40 +01001848 fih_int fih_rc = FIH_FAILURE;
Marti Bolivarc0b47912017-06-13 17:18:09 -04001849 int fa_id;
Fabio Utzigb0f04732019-07-31 09:49:19 -03001850 int image_index;
Fabio Utzig298913b2019-08-28 11:22:45 -03001851 bool has_upgrade;
Christopher Collins92ea77f2016-12-12 15:59:26 -08001852
1853 /* The array of slot sectors are defined here (as opposed to file scope) so
1854 * that they don't get allocated for non-boot-loader apps. This is
1855 * necessary because the gcc option "-fdata-sections" doesn't seem to have
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001856 * any effect in older gcc versions (e.g., 4.8.4).
Christopher Collins92ea77f2016-12-12 15:59:26 -08001857 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001858 TARGET_STATIC boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
1859 TARGET_STATIC boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
Fabio Utzig12d59162019-11-28 10:01:59 -03001860#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -03001861 TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS];
Fabio Utzig12d59162019-11-28 10:01:59 -03001862#endif
Christopher Collins92ea77f2016-12-12 15:59:26 -08001863
Fabio Utzig10ee6482019-08-01 12:04:52 -03001864 memset(state, 0, sizeof(struct boot_loader_state));
Fabio Utzig298913b2019-08-28 11:22:45 -03001865 has_upgrade = false;
1866
1867#if (BOOT_IMAGE_NUMBER == 1)
1868 (void)has_upgrade;
1869#endif
Fabio Utzigba829042018-09-18 08:29:34 -03001870
David Vinczeba3bd602019-06-17 16:01:43 +02001871 /* Iterate over all the images. By the end of the loop the swap type has
1872 * to be determined for each image and all aborted swaps have to be
1873 * completed.
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001874 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001875 IMAGES_ITER(BOOT_CURR_IMG(state)) {
Fabio Utzigdb5bd3c2017-07-13 22:20:22 -03001876
David Vinczeba3bd602019-06-17 16:01:43 +02001877#if defined(MCUBOOT_ENC_IMAGES) && (BOOT_IMAGE_NUMBER > 1)
1878 /* The keys used for encryption may no longer be valid (could belong to
1879 * another images). Therefore, mark them as invalid to force their reload
1880 * by boot_enc_load().
Fabio Utzigdb5bd3c2017-07-13 22:20:22 -03001881 */
Fabio Utzig1e4284b2019-08-23 11:55:27 -03001882 boot_enc_zeroize(BOOT_CURR_ENC(state));
David Brown554c52e2017-06-30 16:01:07 -06001883#endif
1884
Fabio Utzig10ee6482019-08-01 12:04:52 -03001885 image_index = BOOT_CURR_IMG(state);
Fabio Utzigb0f04732019-07-31 09:49:19 -03001886
Fabio Utzig10ee6482019-08-01 12:04:52 -03001887 BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
Fabio Utzigb0f04732019-07-31 09:49:19 -03001888 primary_slot_sectors[image_index];
Fabio Utzig10ee6482019-08-01 12:04:52 -03001889 BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
Fabio Utzigb0f04732019-07-31 09:49:19 -03001890 secondary_slot_sectors[image_index];
Fabio Utzig12d59162019-11-28 10:01:59 -03001891#if MCUBOOT_SWAP_USING_SCRATCH
Fabio Utzig10ee6482019-08-01 12:04:52 -03001892 state->scratch.sectors = scratch_sectors;
Fabio Utzig12d59162019-11-28 10:01:59 -03001893#endif
David Vinczeba3bd602019-06-17 16:01:43 +02001894
1895 /* Open primary and secondary image areas for the duration
1896 * of this call.
1897 */
1898 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
Fabio Utzigb0f04732019-07-31 09:49:19 -03001899 fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
Fabio Utzig10ee6482019-08-01 12:04:52 -03001900 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
David Vinczeba3bd602019-06-17 16:01:43 +02001901 assert(rc == 0);
1902 }
Fabio Utzig12d59162019-11-28 10:01:59 -03001903#if MCUBOOT_SWAP_USING_SCRATCH
David Vinczeba3bd602019-06-17 16:01:43 +02001904 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
Fabio Utzig10ee6482019-08-01 12:04:52 -03001905 &BOOT_SCRATCH_AREA(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001906 assert(rc == 0);
Fabio Utzig12d59162019-11-28 10:01:59 -03001907#endif
David Vinczeba3bd602019-06-17 16:01:43 +02001908
1909 /* Determine swap type and complete swap if it has been aborted. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001910 boot_prepare_image_for_update(state, &bs);
Fabio Utzig298913b2019-08-28 11:22:45 -03001911
Fabio Utzige575b0b2019-09-11 12:34:23 -03001912 if (BOOT_IS_UPGRADE(BOOT_SWAP_TYPE(state))) {
Fabio Utzig298913b2019-08-28 11:22:45 -03001913 has_upgrade = true;
1914 }
David Vinczeba3bd602019-06-17 16:01:43 +02001915 }
1916
David Vinczee32483f2019-06-13 10:46:24 +02001917#if (BOOT_IMAGE_NUMBER > 1)
Fabio Utzig298913b2019-08-28 11:22:45 -03001918 if (has_upgrade) {
1919 /* Iterate over all the images and verify whether the image dependencies
1920 * are all satisfied and update swap type if necessary.
1921 */
1922 rc = boot_verify_dependencies(state);
David Vincze8b0b6372020-05-20 19:54:44 +02001923 if (rc != 0) {
Fabio Utzig298913b2019-08-28 11:22:45 -03001924 /*
1925 * It was impossible to upgrade because the expected dependency version
1926 * was not available. Here we already changed the swap_type so that
1927 * instead of asserting the bootloader, we continue and no upgrade is
1928 * performed.
1929 */
1930 rc = 0;
1931 }
1932 }
David Vinczee32483f2019-06-13 10:46:24 +02001933#endif
1934
David Vinczeba3bd602019-06-17 16:01:43 +02001935 /* Iterate over all the images. At this point there are no aborted swaps
1936 * and the swap types are determined for each image. By the end of the loop
1937 * all required update operations will have been finished.
1938 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001939 IMAGES_ITER(BOOT_CURR_IMG(state)) {
David Vinczeba3bd602019-06-17 16:01:43 +02001940
1941#if (BOOT_IMAGE_NUMBER > 1)
1942#ifdef MCUBOOT_ENC_IMAGES
1943 /* The keys used for encryption may no longer be valid (could belong to
1944 * another images). Therefore, mark them as invalid to force their reload
1945 * by boot_enc_load().
1946 */
Fabio Utzig1e4284b2019-08-23 11:55:27 -03001947 boot_enc_zeroize(BOOT_CURR_ENC(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001948#endif /* MCUBOOT_ENC_IMAGES */
1949
1950 /* Indicate that swap is not aborted */
Fabio Utzig12d59162019-11-28 10:01:59 -03001951 boot_status_reset(&bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001952#endif /* (BOOT_IMAGE_NUMBER > 1) */
1953
1954 /* Set the previously determined swap type */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001955 bs.swap_type = BOOT_SWAP_TYPE(state);
David Vinczeba3bd602019-06-17 16:01:43 +02001956
Fabio Utzig10ee6482019-08-01 12:04:52 -03001957 switch (BOOT_SWAP_TYPE(state)) {
David Vinczeba3bd602019-06-17 16:01:43 +02001958 case BOOT_SWAP_TYPE_NONE:
1959 break;
1960
1961 case BOOT_SWAP_TYPE_TEST: /* fallthrough */
1962 case BOOT_SWAP_TYPE_PERM: /* fallthrough */
1963 case BOOT_SWAP_TYPE_REVERT:
Fabio Utzig10ee6482019-08-01 12:04:52 -03001964 rc = boot_perform_update(state, &bs);
David Vinczeba3bd602019-06-17 16:01:43 +02001965 assert(rc == 0);
1966 break;
1967
1968 case BOOT_SWAP_TYPE_FAIL:
1969 /* The image in secondary slot was invalid and is now erased. Ensure
1970 * we don't try to boot into it again on the next reboot. Do this by
1971 * pretending we just reverted back to primary slot.
1972 */
1973#ifndef MCUBOOT_OVERWRITE_ONLY
1974 /* image_ok needs to be explicitly set to avoid a new revert. */
Fabio Utzig12d59162019-11-28 10:01:59 -03001975 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02001976 if (rc != 0) {
Fabio Utzig10ee6482019-08-01 12:04:52 -03001977 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001978 }
1979#endif /* !MCUBOOT_OVERWRITE_ONLY */
1980 break;
1981
1982 default:
Fabio Utzig10ee6482019-08-01 12:04:52 -03001983 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001984 }
1985
Fabio Utzig10ee6482019-08-01 12:04:52 -03001986 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
David Vinczeba3bd602019-06-17 16:01:43 +02001987 BOOT_LOG_ERR("panic!");
1988 assert(0);
1989
1990 /* Loop forever... */
Raef Colese8fe6cf2020-05-26 13:07:40 +01001991 FIH_PANIC;
David Vinczeba3bd602019-06-17 16:01:43 +02001992 }
1993 }
1994
1995 /* Iterate over all the images. At this point all required update operations
1996 * have finished. By the end of the loop each image in the primary slot will
1997 * have been re-validated.
1998 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03001999 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2000 if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE) {
David Vinczeba3bd602019-06-17 16:01:43 +02002001 /* Attempt to read an image header from each slot. Ensure that image
2002 * headers in slots are aligned with headers in boot_data.
2003 */
Fabio Utzig12d59162019-11-28 10:01:59 -03002004 rc = boot_read_image_headers(state, false, &bs);
David Vinczeba3bd602019-06-17 16:01:43 +02002005 if (rc != 0) {
2006 goto out;
2007 }
2008 /* Since headers were reloaded, it can be assumed we just performed
2009 * a swap or overwrite. Now the header info that should be used to
2010 * provide the data for the bootstrap, which previously was at
2011 * secondary slot, was updated to primary slot.
2012 */
2013 }
2014
2015#ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
Raef Colese8fe6cf2020-05-26 13:07:40 +01002016 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL);
2017 if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
David Vinczeba3bd602019-06-17 16:01:43 +02002018 goto out;
2019 }
2020#else
2021 /* Even if we're not re-validating the primary slot, we could be booting
2022 * onto an empty flash chip. At least do a basic sanity check that
2023 * the magic number on the image is OK.
2024 */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002025 if (BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic != IMAGE_MAGIC) {
David Vinczeba3bd602019-06-17 16:01:43 +02002026 BOOT_LOG_ERR("bad image magic 0x%lx; Image=%u", (unsigned long)
Fabio Utzig10ee6482019-08-01 12:04:52 -03002027 &boot_img_hdr(state,BOOT_PRIMARY_SLOT)->ih_magic,
2028 BOOT_CURR_IMG(state));
David Vinczeba3bd602019-06-17 16:01:43 +02002029 rc = BOOT_EBADIMAGE;
2030 goto out;
2031 }
David Vinczec3084132020-02-18 14:50:47 +01002032#endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
2033
Mark Horvathccaf7f82021-01-04 18:16:42 +01002034 rc = boot_update_hw_rollback_protection(state);
David Vincze1cf11b52020-03-24 07:51:09 +01002035 if (rc != 0) {
Raef Colese8fe6cf2020-05-26 13:07:40 +01002036 goto out;
David Vincze1cf11b52020-03-24 07:51:09 +01002037 }
David Vincze1cf11b52020-03-24 07:51:09 +01002038
Mark Horvathccaf7f82021-01-04 18:16:42 +01002039 rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT);
David Vincze1cf11b52020-03-24 07:51:09 +01002040 if (rc != 0) {
Raef Colese8fe6cf2020-05-26 13:07:40 +01002041 goto out;
David Vincze1cf11b52020-03-24 07:51:09 +01002042 }
David Vinczeba3bd602019-06-17 16:01:43 +02002043 }
2044
Fabio Utzigf616c542019-12-19 15:23:32 -03002045 /*
2046 * Since the boot_status struct stores plaintext encryption keys, reset
2047 * them here to avoid the possibility of jumping into an image that could
2048 * easily recover them.
2049 */
2050 memset(&bs, 0, sizeof(struct boot_status));
2051
Mark Horvathccaf7f82021-01-04 18:16:42 +01002052 fill_rsp(state, NULL, rsp);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002053
Raef Colese8fe6cf2020-05-26 13:07:40 +01002054 fih_rc = FIH_SUCCESS;
Fabio Utzig298913b2019-08-28 11:22:45 -03002055out:
Mark Horvathccaf7f82021-01-04 18:16:42 +01002056 close_all_flash_areas(state);
Raef Colese8fe6cf2020-05-26 13:07:40 +01002057
2058 if (rc) {
2059 fih_rc = fih_int_encode(rc);
2060 }
2061
2062 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002063}
2064
Raef Colese8fe6cf2020-05-26 13:07:40 +01002065fih_int
Christopher Collins92ea77f2016-12-12 15:59:26 -08002066split_go(int loader_slot, int split_slot, void **entry)
2067{
Marti Bolivarc50926f2017-06-14 09:35:40 -04002068 boot_sector_t *sectors;
Christopher Collins034a6202017-01-11 12:19:37 -08002069 uintptr_t entry_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002070 int loader_flash_id;
Marti Bolivarc0b47912017-06-13 17:18:09 -04002071 int split_flash_id;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002072 int rc;
Raef Colese8fe6cf2020-05-26 13:07:40 +01002073 fih_int fih_rc = FIH_FAILURE;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002074
Christopher Collins92ea77f2016-12-12 15:59:26 -08002075 sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors);
2076 if (sectors == NULL) {
Raef Colese8fe6cf2020-05-26 13:07:40 +01002077 FIH_RET(FIH_FAILURE);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002078 }
David Vinczeba3bd602019-06-17 16:01:43 +02002079 BOOT_IMG(&boot_data, loader_slot).sectors = sectors + 0;
2080 BOOT_IMG(&boot_data, split_slot).sectors = sectors + BOOT_MAX_IMG_SECTORS;
Marti Bolivarc0b47912017-06-13 17:18:09 -04002081
2082 loader_flash_id = flash_area_id_from_image_slot(loader_slot);
2083 rc = flash_area_open(loader_flash_id,
Alvaro Prieto63a2bdb2019-07-04 12:18:49 -07002084 &BOOT_IMG_AREA(&boot_data, loader_slot));
Marti Bolivarc0b47912017-06-13 17:18:09 -04002085 assert(rc == 0);
2086 split_flash_id = flash_area_id_from_image_slot(split_slot);
2087 rc = flash_area_open(split_flash_id,
2088 &BOOT_IMG_AREA(&boot_data, split_slot));
2089 assert(rc == 0);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002090
2091 /* Determine the sector layout of the image slots and scratch area. */
Fabio Utzig10ee6482019-08-01 12:04:52 -03002092 rc = boot_read_sectors(&boot_data);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002093 if (rc != 0) {
2094 rc = SPLIT_GO_ERR;
2095 goto done;
2096 }
2097
Fabio Utzig12d59162019-11-28 10:01:59 -03002098 rc = boot_read_image_headers(&boot_data, true, NULL);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002099 if (rc != 0) {
2100 goto done;
2101 }
2102
Christopher Collins92ea77f2016-12-12 15:59:26 -08002103 /* Don't check the bootable image flag because we could really call a
2104 * bootable or non-bootable image. Just validate that the image check
2105 * passes which is distinct from the normal check.
2106 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01002107 FIH_CALL(split_image_check, fih_rc,
2108 boot_img_hdr(&boot_data, split_slot),
2109 BOOT_IMG_AREA(&boot_data, split_slot),
2110 boot_img_hdr(&boot_data, loader_slot),
2111 BOOT_IMG_AREA(&boot_data, loader_slot));
2112 if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
Christopher Collins92ea77f2016-12-12 15:59:26 -08002113 goto done;
2114 }
2115
Marti Bolivarea088872017-06-12 17:10:49 -04002116 entry_val = boot_img_slot_off(&boot_data, split_slot) +
Marti Bolivarf804f622017-06-12 15:41:48 -04002117 boot_img_hdr(&boot_data, split_slot)->ih_hdr_size;
Christopher Collins034a6202017-01-11 12:19:37 -08002118 *entry = (void *) entry_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -08002119 rc = SPLIT_GO_OK;
2120
2121done:
Marti Bolivarc0b47912017-06-13 17:18:09 -04002122 flash_area_close(BOOT_IMG_AREA(&boot_data, split_slot));
2123 flash_area_close(BOOT_IMG_AREA(&boot_data, loader_slot));
Christopher Collins92ea77f2016-12-12 15:59:26 -08002124 free(sectors);
Raef Colese8fe6cf2020-05-26 13:07:40 +01002125
2126 if (rc) {
2127 fih_rc = fih_int_encode(rc);
2128 }
2129
2130 FIH_RET(fih_rc);
Christopher Collins92ea77f2016-12-12 15:59:26 -08002131}
David Vinczee574f2d2020-07-10 11:42:03 +02002132
Tamas Banfe031092020-09-10 17:32:39 +02002133#else /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
David Vinczee574f2d2020-07-10 11:42:03 +02002134
Mark Horvathccaf7f82021-01-04 18:16:42 +01002135#define NO_ACTIVE_SLOT UINT32_MAX
2136
David Vinczee574f2d2020-07-10 11:42:03 +02002137/**
Mark Horvathccaf7f82021-01-04 18:16:42 +01002138 * Opens all flash areas and checks which contain an image with a valid header.
David Vinczee574f2d2020-07-10 11:42:03 +02002139 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002140 * @param state Boot loader status information.
2141 * @param slot_usage Structure to fill with information about the available
2142 * slots.
David Vinczee574f2d2020-07-10 11:42:03 +02002143 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002144 * @return 0 on success; nonzero on failure.
2145 */
2146static int
2147boot_get_slot_usage(struct boot_loader_state *state,
2148 struct slot_usage_t slot_usage[])
2149{
2150 uint32_t slot;
2151 int fa_id;
2152 int rc;
2153 struct image_header *hdr = NULL;
2154
2155 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2156 /* Open all the slots */
2157 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2158 fa_id = flash_area_id_from_multi_image_slot(
2159 BOOT_CURR_IMG(state), slot);
2160 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
2161 assert(rc == 0);
2162 }
2163
2164 /* Attempt to read an image header from each slot. */
2165 rc = boot_read_image_headers(state, false, NULL);
2166 if (rc != 0) {
2167 BOOT_LOG_WRN("Failed reading image headers.");
2168 return rc;
2169 }
2170
2171 /* Check headers in all slots */
2172 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2173 hdr = boot_img_hdr(state, slot);
2174
2175 if (boot_is_header_valid(hdr, BOOT_IMG_AREA(state, slot))) {
2176 slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = true;
2177 BOOT_LOG_IMAGE_INFO(slot, hdr);
2178 } else {
2179 slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false;
2180 BOOT_LOG_INF("Image %d %s slot: Image not found",
2181 BOOT_CURR_IMG(state),
2182 (slot == BOOT_PRIMARY_SLOT)
2183 ? "Primary" : "Secondary");
2184 }
2185 }
2186
2187 slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2188 }
2189
2190 return 0;
2191}
2192
2193/**
2194 * Finds the slot containing the image with the highest version number for the
2195 * current image.
2196 *
2197 * @param state Boot loader status information.
2198 * @param slot_usage Information about the active and available slots.
2199 *
2200 * @return NO_ACTIVE_SLOT if no available slot found, number of
2201 * the found slot otherwise.
David Vinczee574f2d2020-07-10 11:42:03 +02002202 */
2203static uint32_t
Mark Horvathccaf7f82021-01-04 18:16:42 +01002204find_slot_with_highest_version(struct boot_loader_state *state,
2205 struct slot_usage_t slot_usage[])
David Vinczee574f2d2020-07-10 11:42:03 +02002206{
David Vinczee574f2d2020-07-10 11:42:03 +02002207 uint32_t slot;
Mark Horvathccaf7f82021-01-04 18:16:42 +01002208 uint32_t candidate_slot = NO_ACTIVE_SLOT;
2209 int rc;
David Vinczee574f2d2020-07-10 11:42:03 +02002210
Mark Horvathccaf7f82021-01-04 18:16:42 +01002211 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2212 if (slot_usage[BOOT_CURR_IMG(state)].slot_available[slot]) {
2213 if (candidate_slot == NO_ACTIVE_SLOT) {
2214 candidate_slot = slot;
2215 } else {
2216 rc = boot_version_cmp(
2217 &boot_img_hdr(state, slot)->ih_ver,
2218 &boot_img_hdr(state, candidate_slot)->ih_ver);
2219 if (rc == 1) {
2220 /* The version of the image being examined is greater than
2221 * the version of the current candidate.
2222 */
2223 candidate_slot = slot;
2224 }
2225 }
David Vinczee574f2d2020-07-10 11:42:03 +02002226 }
2227 }
2228
Mark Horvathccaf7f82021-01-04 18:16:42 +01002229 return candidate_slot;
David Vinczee574f2d2020-07-10 11:42:03 +02002230}
2231
Mark Horvathccaf7f82021-01-04 18:16:42 +01002232#ifdef MCUBOOT_HAVE_LOGGING
2233/**
2234 * Prints the state of the loaded images.
2235 *
2236 * @param state Boot loader status information.
2237 * @param slot_usage Information about the active and available slots.
2238 */
2239static void
2240print_loaded_images(struct boot_loader_state *state,
2241 struct slot_usage_t slot_usage[])
2242{
2243 uint32_t active_slot;
2244
David Brown695e5912021-05-24 16:58:01 -06002245 (void)state;
2246
Mark Horvathccaf7f82021-01-04 18:16:42 +01002247 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2248 active_slot = slot_usage[BOOT_CURR_IMG(state)].active_slot;
2249
2250 BOOT_LOG_INF("Image %d loaded from the %s slot",
2251 BOOT_CURR_IMG(state),
2252 (active_slot == BOOT_PRIMARY_SLOT) ?
2253 "primary" : "secondary");
2254 }
2255}
2256#endif
2257
David Vincze1c456242021-06-29 15:25:24 +02002258#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
David Vincze505fba22020-10-22 13:53:29 +02002259/**
Mark Horvathccaf7f82021-01-04 18:16:42 +01002260 * Checks whether the active slot of the current image was previously selected
2261 * to run. Erases the image if it was selected but its execution failed,
2262 * otherwise marks it as selected if it has not been before.
David Vincze505fba22020-10-22 13:53:29 +02002263 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002264 * @param state Boot loader status information.
2265 * @param slot_usage Information about the active and available slots.
David Vincze505fba22020-10-22 13:53:29 +02002266 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002267 * @return 0 on success; nonzero on failure.
David Vincze505fba22020-10-22 13:53:29 +02002268 */
2269static int
Mark Horvathccaf7f82021-01-04 18:16:42 +01002270boot_select_or_erase(struct boot_loader_state *state,
2271 struct slot_usage_t slot_usage[])
David Vincze505fba22020-10-22 13:53:29 +02002272{
2273 const struct flash_area *fap;
2274 int fa_id;
2275 int rc;
Mark Horvathccaf7f82021-01-04 18:16:42 +01002276 uint32_t active_slot;
2277 struct boot_swap_state* active_swap_state;
David Vincze505fba22020-10-22 13:53:29 +02002278
Mark Horvathccaf7f82021-01-04 18:16:42 +01002279 active_slot = slot_usage[BOOT_CURR_IMG(state)].active_slot;
2280
2281 fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), active_slot);
David Vincze505fba22020-10-22 13:53:29 +02002282 rc = flash_area_open(fa_id, &fap);
2283 assert(rc == 0);
2284
Mark Horvathccaf7f82021-01-04 18:16:42 +01002285 active_swap_state = &(slot_usage[BOOT_CURR_IMG(state)].swap_state);
2286
2287 memset(active_swap_state, 0, sizeof(struct boot_swap_state));
2288 rc = boot_read_swap_state(fap, active_swap_state);
David Vincze505fba22020-10-22 13:53:29 +02002289 assert(rc == 0);
2290
Mark Horvathccaf7f82021-01-04 18:16:42 +01002291 if (active_swap_state->magic != BOOT_MAGIC_GOOD ||
2292 (active_swap_state->copy_done == BOOT_FLAG_SET &&
2293 active_swap_state->image_ok != BOOT_FLAG_SET)) {
David Vincze505fba22020-10-22 13:53:29 +02002294 /*
2295 * A reboot happened without the image being confirmed at
2296 * runtime or its trailer is corrupted/invalid. Erase the image
2297 * to prevent it from being selected again on the next reboot.
2298 */
2299 BOOT_LOG_DBG("Erasing faulty image in the %s slot.",
Carlos Falgueras Garcíaae13c3c2021-06-21 17:20:31 +02002300 (active_slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
Dominik Ermel260ae092021-04-23 05:38:45 +00002301 rc = flash_area_erase(fap, 0, flash_area_get_size(fap));
David Vincze505fba22020-10-22 13:53:29 +02002302 assert(rc == 0);
2303
2304 flash_area_close(fap);
2305 rc = -1;
2306 } else {
Mark Horvathccaf7f82021-01-04 18:16:42 +01002307 if (active_swap_state->copy_done != BOOT_FLAG_SET) {
2308 if (active_swap_state->copy_done == BOOT_FLAG_BAD) {
David Vincze505fba22020-10-22 13:53:29 +02002309 BOOT_LOG_DBG("The copy_done flag had an unexpected value. Its "
2310 "value was neither 'set' nor 'unset', but 'bad'.");
2311 }
2312 /*
2313 * Set the copy_done flag, indicating that the image has been
2314 * selected to boot. It can be set in advance, before even
2315 * validating the image, because in case the validation fails, the
2316 * entire image slot will be erased (including the trailer).
2317 */
2318 rc = boot_write_copy_done(fap);
2319 if (rc != 0) {
2320 BOOT_LOG_WRN("Failed to set copy_done flag of the image in "
Carlos Falgueras Garcíaae13c3c2021-06-21 17:20:31 +02002321 "the %s slot.", (active_slot == BOOT_PRIMARY_SLOT) ?
David Vincze505fba22020-10-22 13:53:29 +02002322 "primary" : "secondary");
2323 rc = 0;
2324 }
2325 }
2326 flash_area_close(fap);
2327 }
2328
2329 return rc;
2330}
David Vincze1c456242021-06-29 15:25:24 +02002331#endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */
David Vincze505fba22020-10-22 13:53:29 +02002332
Tamas Banfe031092020-09-10 17:32:39 +02002333#ifdef MCUBOOT_RAM_LOAD
2334
Mark Horvathccaf7f82021-01-04 18:16:42 +01002335#ifndef MULTIPLE_EXECUTABLE_RAM_REGIONS
Tamas Banfe031092020-09-10 17:32:39 +02002336#if !defined(IMAGE_EXECUTABLE_RAM_START) || !defined(IMAGE_EXECUTABLE_RAM_SIZE)
2337#error "Platform MUST define executable RAM bounds in case of RAM_LOAD"
2338#endif
Mark Horvathccaf7f82021-01-04 18:16:42 +01002339#endif
Tamas Banfe031092020-09-10 17:32:39 +02002340
2341/**
Mark Horvathccaf7f82021-01-04 18:16:42 +01002342 * Verifies that the active slot of the current image can be loaded within the
2343 * predefined bounds that are allowed to be used by executable images.
Tamas Banfe031092020-09-10 17:32:39 +02002344 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002345 * @param state Boot loader status information.
2346 * @param slot_usage Information about the active and available slots.
Tamas Banfe031092020-09-10 17:32:39 +02002347 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002348 * @return 0 on success; nonzero on failure.
Tamas Banfe031092020-09-10 17:32:39 +02002349 */
2350static int
Mark Horvathccaf7f82021-01-04 18:16:42 +01002351boot_verify_ram_load_address(struct boot_loader_state *state,
2352 struct slot_usage_t slot_usage[])
Tamas Banfe031092020-09-10 17:32:39 +02002353{
Mark Horvathccaf7f82021-01-04 18:16:42 +01002354 uint32_t img_dst;
2355 uint32_t img_sz;
Tamas Banfe031092020-09-10 17:32:39 +02002356 uint32_t img_end_addr;
Mark Horvathccaf7f82021-01-04 18:16:42 +01002357 uint32_t exec_ram_start;
2358 uint32_t exec_ram_size;
David Brown695e5912021-05-24 16:58:01 -06002359
2360 (void)state;
2361
Mark Horvathccaf7f82021-01-04 18:16:42 +01002362#ifdef MULTIPLE_EXECUTABLE_RAM_REGIONS
2363 int rc;
Tamas Banfe031092020-09-10 17:32:39 +02002364
Mark Horvathccaf7f82021-01-04 18:16:42 +01002365 rc = boot_get_image_exec_ram_info(BOOT_CURR_IMG(state), &exec_ram_start,
2366 &exec_ram_size);
2367 if (rc != 0) {
2368 return BOOT_EBADSTATUS;
2369 }
2370#else
2371 exec_ram_start = IMAGE_EXECUTABLE_RAM_START;
2372 exec_ram_size = IMAGE_EXECUTABLE_RAM_SIZE;
2373#endif
2374
2375 img_dst = slot_usage[BOOT_CURR_IMG(state)].img_dst;
2376 img_sz = slot_usage[BOOT_CURR_IMG(state)].img_sz;
2377
2378 if (img_dst < exec_ram_start) {
Tamas Banfe031092020-09-10 17:32:39 +02002379 return BOOT_EBADIMAGE;
2380 }
2381
2382 if (!boot_u32_safe_add(&img_end_addr, img_dst, img_sz)) {
2383 return BOOT_EBADIMAGE;
2384 }
2385
Mark Horvathccaf7f82021-01-04 18:16:42 +01002386 if (img_end_addr > (exec_ram_start + exec_ram_size)) {
Tamas Banfe031092020-09-10 17:32:39 +02002387 return BOOT_EBADIMAGE;
2388 }
2389
2390 return 0;
2391}
2392
2393/**
Mark Horvathccaf7f82021-01-04 18:16:42 +01002394 * Copies a slot of the current image into SRAM.
Tamas Banfe031092020-09-10 17:32:39 +02002395 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002396 * @param state Boot loader status information.
Tamas Banfe031092020-09-10 17:32:39 +02002397 * @param slot The flash slot of the image to be copied to SRAM.
2398 * @param img_dst The address at which the image needs to be copied to
2399 * SRAM.
2400 * @param img_sz The size of the image that needs to be copied to SRAM.
2401 *
2402 * @return 0 on success; nonzero on failure.
2403 */
2404static int
Mark Horvathccaf7f82021-01-04 18:16:42 +01002405boot_copy_image_to_sram(struct boot_loader_state *state, int slot,
2406 uint32_t img_dst, uint32_t img_sz)
Tamas Banfe031092020-09-10 17:32:39 +02002407{
2408 int rc;
2409 const struct flash_area *fap_src = NULL;
Mark Horvathccaf7f82021-01-04 18:16:42 +01002410 int area_id;
Tamas Banfe031092020-09-10 17:32:39 +02002411
Mark Horvathccaf7f82021-01-04 18:16:42 +01002412#if (BOOT_IMAGE_NUMBER == 1)
2413 (void)state;
2414#endif
2415
2416 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
2417
2418 rc = flash_area_open(area_id, &fap_src);
Tamas Banfe031092020-09-10 17:32:39 +02002419 if (rc != 0) {
2420 return BOOT_EFLASH;
2421 }
2422
2423 /* Direct copy from flash to its new location in SRAM. */
David Brown9bd7f902021-05-26 16:31:14 -06002424 rc = flash_area_read(fap_src, 0, (void *)(IMAGE_RAM_BASE + img_dst), img_sz);
Tamas Banfe031092020-09-10 17:32:39 +02002425 if (rc != 0) {
2426 BOOT_LOG_INF("Error whilst copying image from Flash to SRAM: %d", rc);
2427 }
2428
2429 flash_area_close(fap_src);
2430
2431 return rc;
2432}
2433
Mark Horvathccaf7f82021-01-04 18:16:42 +01002434#if (BOOT_IMAGE_NUMBER > 1)
Tamas Banfe031092020-09-10 17:32:39 +02002435/**
Mark Horvathccaf7f82021-01-04 18:16:42 +01002436 * Checks if two memory regions (A and B) are overlap or not.
Tamas Banfe031092020-09-10 17:32:39 +02002437 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002438 * @param start_a Start of the A region.
2439 * @param end_a End of the A region.
2440 * @param start_b Start of the B region.
2441 * @param end_b End of the B region.
Tamas Banfe031092020-09-10 17:32:39 +02002442 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002443 * @return true if there is overlap; false otherwise.
2444 */
2445static bool
2446do_regions_overlap(uint32_t start_a, uint32_t end_a,
2447 uint32_t start_b, uint32_t end_b)
2448{
2449 if (start_b > end_a) {
2450 return false;
2451 } else if (start_b >= start_a) {
2452 return true;
2453 } else if (end_b > start_a) {
2454 return true;
2455 }
2456
2457 return false;
2458}
2459
2460/**
2461 * Checks if the image we want to load to memory overlap with an already
2462 * ramloaded image.
2463 *
2464 * @param slot_usage Information about the active and available slots.
2465 * @param image_id_to_check The ID of the image we would like to load.
2466 *
2467 * @return 0 if there is no overlap; nonzero otherwise.
Tamas Banfe031092020-09-10 17:32:39 +02002468 */
2469static int
Mark Horvathccaf7f82021-01-04 18:16:42 +01002470boot_check_ram_load_overlapping(struct slot_usage_t slot_usage[],
2471 uint32_t image_id_to_check)
Tamas Banfe031092020-09-10 17:32:39 +02002472{
Mark Horvathccaf7f82021-01-04 18:16:42 +01002473 uint32_t i;
2474
2475 uint32_t start_a;
2476 uint32_t end_a;
2477 uint32_t start_b;
2478 uint32_t end_b;
2479
2480 start_a = slot_usage[image_id_to_check].img_dst;
2481 /* Safe to add here, values are already verified in
2482 * boot_verify_ram_load_address() */
2483 end_a = start_a + slot_usage[image_id_to_check].img_sz;
2484
2485 for (i = 0; i < BOOT_IMAGE_NUMBER; i++) {
2486 if (slot_usage[i].active_slot == NO_ACTIVE_SLOT
2487 || i == image_id_to_check) {
2488 continue;
2489 }
2490
2491 start_b = slot_usage[i].img_dst;
2492 /* Safe to add here, values are already verified in
2493 * boot_verify_ram_load_address() */
2494 end_b = start_b + slot_usage[i].img_sz;
2495
2496 if (do_regions_overlap(start_a, end_a, start_b, end_b)) {
2497 return -1;
2498 }
2499 }
2500
2501 return 0;
2502}
2503#endif
2504
2505/**
2506 * Loads the active slot of the current image into SRAM. The load address and
2507 * image size is extracted from the image header.
2508 *
2509 * @param state Boot loader status information.
2510 * @param slot_usage Information about the active and available slots.
2511 *
2512 * @return 0 on success; nonzero on failure.
2513 */
2514static int
2515boot_load_image_to_sram(struct boot_loader_state *state,
2516 struct slot_usage_t slot_usage[])
2517{
2518 uint32_t active_slot;
2519 struct image_header *hdr = NULL;
2520 uint32_t img_dst;
2521 uint32_t img_sz;
Tamas Banfe031092020-09-10 17:32:39 +02002522 int rc;
2523
Mark Horvathccaf7f82021-01-04 18:16:42 +01002524 active_slot = slot_usage[BOOT_CURR_IMG(state)].active_slot;
2525 hdr = boot_img_hdr(state, active_slot);
2526
Tamas Banfe031092020-09-10 17:32:39 +02002527 if (hdr->ih_flags & IMAGE_F_RAM_LOAD) {
2528
Mark Horvathccaf7f82021-01-04 18:16:42 +01002529 img_dst = hdr->ih_load_addr;
Tamas Banfe031092020-09-10 17:32:39 +02002530
Mark Horvathccaf7f82021-01-04 18:16:42 +01002531 rc = boot_read_image_size(state, active_slot, &img_sz);
Tamas Banfe031092020-09-10 17:32:39 +02002532 if (rc != 0) {
2533 return rc;
2534 }
2535
Mark Horvathccaf7f82021-01-04 18:16:42 +01002536 slot_usage[BOOT_CURR_IMG(state)].img_dst = img_dst;
2537 slot_usage[BOOT_CURR_IMG(state)].img_sz = img_sz;
2538
2539 rc = boot_verify_ram_load_address(state, slot_usage);
Tamas Banfe031092020-09-10 17:32:39 +02002540 if (rc != 0) {
Mark Horvathccaf7f82021-01-04 18:16:42 +01002541 BOOT_LOG_INF("Image RAM load address 0x%x is invalid.", img_dst);
Tamas Banfe031092020-09-10 17:32:39 +02002542 return rc;
2543 }
2544
Mark Horvathccaf7f82021-01-04 18:16:42 +01002545#if (BOOT_IMAGE_NUMBER > 1)
2546 rc = boot_check_ram_load_overlapping(slot_usage, BOOT_CURR_IMG(state));
2547 if (rc != 0) {
2548 BOOT_LOG_INF("Image RAM loading to address 0x%x would overlap with\
2549 another image.", img_dst);
2550 return rc;
2551 }
2552#endif
2553
Tamas Banfe031092020-09-10 17:32:39 +02002554 /* Copy image to the load address from where it currently resides in
2555 * flash.
2556 */
Mark Horvathccaf7f82021-01-04 18:16:42 +01002557 rc = boot_copy_image_to_sram(state, active_slot, img_dst, img_sz);
Tamas Banfe031092020-09-10 17:32:39 +02002558 if (rc != 0) {
Mark Horvathccaf7f82021-01-04 18:16:42 +01002559 BOOT_LOG_INF("RAM loading to 0x%x is failed.", img_dst);
Tamas Banfe031092020-09-10 17:32:39 +02002560 } else {
Mark Horvathccaf7f82021-01-04 18:16:42 +01002561 BOOT_LOG_INF("RAM loading to 0x%x is succeeded.", img_dst);
Tamas Banfe031092020-09-10 17:32:39 +02002562 }
2563 } else {
2564 /* Only images that support IMAGE_F_RAM_LOAD are allowed if
2565 * MCUBOOT_RAM_LOAD is set.
2566 */
2567 rc = BOOT_EBADIMAGE;
2568 }
2569
Mark Horvathccaf7f82021-01-04 18:16:42 +01002570 if (rc != 0) {
2571 slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
2572 slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
2573 }
2574
Tamas Banfe031092020-09-10 17:32:39 +02002575 return rc;
2576}
2577
2578/**
2579 * Removes an image from SRAM, by overwriting it with zeros.
2580 *
Mark Horvathccaf7f82021-01-04 18:16:42 +01002581 * @param state Boot loader status information.
2582 * @param slot_usage Information about the active and available slots.
2583 *
2584 * @return 0 on success; nonzero on failure.
2585 */
2586static inline int
2587boot_remove_image_from_sram(struct boot_loader_state *state,
2588 struct slot_usage_t slot_usage[])
2589{
David Brown695e5912021-05-24 16:58:01 -06002590 (void)state;
2591
Mark Horvathccaf7f82021-01-04 18:16:42 +01002592 BOOT_LOG_INF("Removing image from SRAM at address 0x%x",
2593 slot_usage[BOOT_CURR_IMG(state)].img_dst);
2594
David Brown695e5912021-05-24 16:58:01 -06002595 memset((void*)(IMAGE_RAM_BASE + slot_usage[BOOT_CURR_IMG(state)].img_dst),
2596 0, slot_usage[BOOT_CURR_IMG(state)].img_sz);
Mark Horvathccaf7f82021-01-04 18:16:42 +01002597
2598 slot_usage[BOOT_CURR_IMG(state)].img_dst = 0;
2599 slot_usage[BOOT_CURR_IMG(state)].img_sz = 0;
2600
2601 return 0;
2602}
2603
2604/**
2605 * Removes an image from flash by erasing the corresponding flash area
2606 *
2607 * @param state Boot loader status information.
2608 * @param slot The flash slot of the image to be erased.
Tamas Banfe031092020-09-10 17:32:39 +02002609 *
2610 * @return 0 on success; nonzero on failure.
2611 */
2612static inline int
Mark Horvathccaf7f82021-01-04 18:16:42 +01002613boot_remove_image_from_flash(struct boot_loader_state *state, uint32_t slot)
Tamas Banfe031092020-09-10 17:32:39 +02002614{
Mark Horvathccaf7f82021-01-04 18:16:42 +01002615 int area_id;
2616 int rc;
2617 const struct flash_area *fap;
Tamas Banfe031092020-09-10 17:32:39 +02002618
David Brown695e5912021-05-24 16:58:01 -06002619 (void)state;
2620
Mark Horvathccaf7f82021-01-04 18:16:42 +01002621 BOOT_LOG_INF("Removing image %d slot %d from flash", BOOT_CURR_IMG(state),
2622 slot);
2623 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
2624 rc = flash_area_open(area_id, &fap);
2625 if (rc == 0) {
Dominik Ermel260ae092021-04-23 05:38:45 +00002626 flash_area_erase(fap, 0, flash_area_get_size(fap));
Mark Horvathccaf7f82021-01-04 18:16:42 +01002627 }
2628
2629 return rc;
Tamas Banfe031092020-09-10 17:32:39 +02002630}
2631#endif /* MCUBOOT_RAM_LOAD */
2632
Mark Horvathccaf7f82021-01-04 18:16:42 +01002633#if (BOOT_IMAGE_NUMBER > 1)
2634/**
2635 * Checks the image dependency whether it is satisfied.
2636 *
2637 * @param state Boot loader status information.
2638 * @param slot_usage Information about the active and available slots.
2639 * @param dep Image dependency which has to be verified.
2640 *
2641 * @return 0 if dependencies are met; nonzero otherwise.
2642 */
2643static int
2644boot_verify_slot_dependency(struct boot_loader_state *state,
2645 struct slot_usage_t slot_usage[],
2646 struct image_dependency *dep)
David Vinczee574f2d2020-07-10 11:42:03 +02002647{
Mark Horvathccaf7f82021-01-04 18:16:42 +01002648 struct image_version *dep_version;
2649 uint32_t dep_slot;
David Vinczee574f2d2020-07-10 11:42:03 +02002650 int rc;
2651
Mark Horvathccaf7f82021-01-04 18:16:42 +01002652 /* Determine the source of the image which is the subject of
2653 * the dependency and get it's version.
David Vinczee574f2d2020-07-10 11:42:03 +02002654 */
Mark Horvathccaf7f82021-01-04 18:16:42 +01002655 dep_slot = slot_usage[dep->image_id].active_slot;
2656 dep_version = &state->imgs[dep->image_id][dep_slot].hdr.ih_ver;
2657
2658 rc = boot_version_cmp(dep_version, &dep->image_min_version);
2659 if (rc >= 0) {
2660 /* Dependency satisfied. */
2661 rc = 0;
David Vinczee574f2d2020-07-10 11:42:03 +02002662 }
2663
Mark Horvathccaf7f82021-01-04 18:16:42 +01002664 return rc;
2665}
2666
2667/**
2668 * Reads all dependency TLVs of an image and verifies one after another to see
2669 * if they are all satisfied.
2670 *
2671 * @param state Boot loader status information.
2672 * @param slot_usage Information about the active and available slots.
2673 *
2674 * @return 0 if dependencies are met; nonzero otherwise.
2675 */
2676static int
2677boot_verify_slot_dependencies(struct boot_loader_state *state,
2678 struct slot_usage_t slot_usage[])
2679{
2680 uint32_t active_slot;
2681 const struct flash_area *fap;
2682 struct image_tlv_iter it;
2683 struct image_dependency dep;
2684 uint32_t off;
2685 uint16_t len;
2686 int area_id;
2687 int rc;
2688
2689 active_slot = slot_usage[BOOT_CURR_IMG(state)].active_slot;
2690
2691 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state),
2692 active_slot);
2693 rc = flash_area_open(area_id, &fap);
David Vinczee574f2d2020-07-10 11:42:03 +02002694 if (rc != 0) {
Mark Horvathccaf7f82021-01-04 18:16:42 +01002695 rc = BOOT_EFLASH;
2696 goto done;
David Vinczee574f2d2020-07-10 11:42:03 +02002697 }
2698
Mark Horvathccaf7f82021-01-04 18:16:42 +01002699 rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, active_slot), fap,
2700 IMAGE_TLV_DEPENDENCY, true);
2701 if (rc != 0) {
2702 goto done;
2703 }
David Vinczee574f2d2020-07-10 11:42:03 +02002704
Mark Horvathccaf7f82021-01-04 18:16:42 +01002705 while (true) {
2706 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
2707 if (rc < 0) {
2708 return -1;
2709 } else if (rc > 0) {
2710 rc = 0;
2711 break;
2712 }
David Vinczee574f2d2020-07-10 11:42:03 +02002713
Mark Horvathccaf7f82021-01-04 18:16:42 +01002714 if (len != sizeof(dep)) {
2715 rc = BOOT_EBADIMAGE;
2716 goto done;
2717 }
2718
2719 rc = LOAD_IMAGE_DATA(boot_img_hdr(state, active_slot),
2720 fap, off, &dep, len);
2721 if (rc != 0) {
2722 rc = BOOT_EFLASH;
2723 goto done;
2724 }
2725
2726 if (dep.image_id >= BOOT_IMAGE_NUMBER) {
2727 rc = BOOT_EBADARGS;
2728 goto done;
2729 }
2730
2731 rc = boot_verify_slot_dependency(state, slot_usage, &dep);
2732 if (rc != 0) {
2733 /* Dependency not satisfied. */
2734 goto done;
2735 }
2736 }
2737
2738done:
2739 flash_area_close(fap);
2740 return rc;
2741}
2742
2743/**
2744 * Checks the dependency of all the active slots. If an image found with
2745 * invalid or not satisfied dependencies the image is removed from SRAM (in
2746 * case of MCUBOOT_RAM_LOAD strategy) and its slot is set to unavailable.
2747 *
2748 * @param state Boot loader status information.
2749 * @param slot_usage Information about the active and available slots.
2750 *
2751 * @return 0 if dependencies are met; nonzero otherwise.
2752 */
2753static int
2754boot_verify_dependencies(struct boot_loader_state *state,
2755 struct slot_usage_t slot_usage[])
2756{
2757 int rc = -1;
2758 uint32_t active_slot;
2759
2760 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2761 rc = boot_verify_slot_dependencies(state, slot_usage);
2762 if (rc != 0) {
2763 /* Dependencies not met or invalid dependencies. */
2764
2765#ifdef MCUBOOT_RAM_LOAD
2766 boot_remove_image_from_sram(state, slot_usage);
2767#endif /* MCUBOOT_RAM_LOAD */
2768
2769 active_slot = slot_usage[BOOT_CURR_IMG(state)].active_slot;
2770 slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2771 slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2772
2773 return rc;
2774 }
2775 }
2776
2777 return rc;
2778}
2779#endif /* (BOOT_IMAGE_NUMBER > 1) */
2780
2781/**
2782 * Tries to load a slot for all the images with validation.
2783 *
2784 * @param state Boot loader status information.
2785 * @param slot_usage Information about the active and available slots.
2786 *
2787 * @return 0 on success; nonzero on failure.
2788 */
2789fih_int
2790boot_load_and_validate_images(struct boot_loader_state *state,
2791 struct slot_usage_t slot_usage[])
2792{
2793 uint32_t active_slot;
2794 int rc;
2795 fih_int fih_rc;
2796
2797 /* Go over all the images and try to load one */
2798 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2799 /* All slots tried until a valid image found. Breaking from this loop
2800 * means that a valid image found or already loaded. If no slot is
2801 * found the function returns with error code. */
2802 while (true) {
2803
2804 /* Go over all the slots and try to load one */
2805 active_slot = slot_usage[BOOT_CURR_IMG(state)].active_slot;
2806 if (active_slot != NO_ACTIVE_SLOT){
2807 /* A slot is already active, go to next image. */
2808 break;
David Vinczee574f2d2020-07-10 11:42:03 +02002809 }
David Vincze505fba22020-10-22 13:53:29 +02002810
Mark Horvathccaf7f82021-01-04 18:16:42 +01002811 active_slot = find_slot_with_highest_version(state,
2812 slot_usage);
2813 if (active_slot == NO_ACTIVE_SLOT) {
2814 BOOT_LOG_INF("No slot to load for image %d",
2815 BOOT_CURR_IMG(state));
2816 FIH_RET(FIH_FAILURE);
2817 }
2818
2819 /* Save the number of the active slot. */
2820 slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot;
2821
2822#ifdef MCUBOOT_DIRECT_XIP
2823 rc = boot_rom_address_check(state, slot_usage);
2824 if (rc != 0) {
2825 /* The image is placed in an unsuitable slot. */
2826 slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2827 slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2828 continue;
2829 }
George Becksteind4d90f82021-05-11 02:00:00 -04002830
David Vincze505fba22020-10-22 13:53:29 +02002831#ifdef MCUBOOT_DIRECT_XIP_REVERT
Mark Horvathccaf7f82021-01-04 18:16:42 +01002832 rc = boot_select_or_erase(state, slot_usage);
David Vincze505fba22020-10-22 13:53:29 +02002833 if (rc != 0) {
2834 /* The selected image slot has been erased. */
Mark Horvathccaf7f82021-01-04 18:16:42 +01002835 slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2836 slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
David Vincze505fba22020-10-22 13:53:29 +02002837 continue;
2838 }
2839#endif /* MCUBOOT_DIRECT_XIP_REVERT */
David Vincze1c456242021-06-29 15:25:24 +02002840#endif /* MCUBOOT_DIRECT_XIP */
David Vincze505fba22020-10-22 13:53:29 +02002841
Tamas Banfe031092020-09-10 17:32:39 +02002842#ifdef MCUBOOT_RAM_LOAD
2843 /* Image is first loaded to RAM and authenticated there in order to
2844 * prevent TOCTOU attack during image copy. This could be applied
2845 * when loading images from external (untrusted) flash to internal
2846 * (trusted) RAM and image is authenticated before copying.
2847 */
Mark Horvathccaf7f82021-01-04 18:16:42 +01002848 rc = boot_load_image_to_sram(state, slot_usage);
Tamas Banfe031092020-09-10 17:32:39 +02002849 if (rc != 0 ) {
Mark Horvathccaf7f82021-01-04 18:16:42 +01002850 /* Image cannot be ramloaded. */
2851 boot_remove_image_from_flash(state, active_slot);
2852 slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2853 slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
Tamas Banfe031092020-09-10 17:32:39 +02002854 continue;
Tamas Banfe031092020-09-10 17:32:39 +02002855 }
2856#endif /* MCUBOOT_RAM_LOAD */
Mark Horvathccaf7f82021-01-04 18:16:42 +01002857
2858 FIH_CALL(boot_validate_slot, fih_rc, state, active_slot, NULL);
2859 if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
2860 /* Image is invalid. */
Tamas Banfe031092020-09-10 17:32:39 +02002861#ifdef MCUBOOT_RAM_LOAD
Mark Horvathccaf7f82021-01-04 18:16:42 +01002862 boot_remove_image_from_sram(state, slot_usage);
Tamas Banfe031092020-09-10 17:32:39 +02002863#endif /* MCUBOOT_RAM_LOAD */
Mark Horvathccaf7f82021-01-04 18:16:42 +01002864 slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2865 slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2866 continue;
David Vincze505fba22020-10-22 13:53:29 +02002867 }
Mark Horvathccaf7f82021-01-04 18:16:42 +01002868
2869 /* Valid image loaded from a slot, go to next image. */
2870 break;
2871 }
2872 }
2873
2874 FIH_RET(FIH_SUCCESS);
2875}
2876
2877/**
2878 * Updates the security counter for the current image.
2879 *
2880 * @param state Boot loader status information.
Sherry Zhang50b06ae2021-07-09 15:22:51 +08002881 * @param slot_usage Information about the active and available slots.
Mark Horvathccaf7f82021-01-04 18:16:42 +01002882 *
2883 * @return 0 on success; nonzero on failure.
2884 */
2885static int
2886boot_update_hw_rollback_protection(struct boot_loader_state *state,
Sherry Zhang50b06ae2021-07-09 15:22:51 +08002887 const struct slot_usage_t slot_usage[])
Mark Horvathccaf7f82021-01-04 18:16:42 +01002888{
2889#ifdef MCUBOOT_HW_ROLLBACK_PROT
2890 int rc;
2891
2892 /* Update the stored security counter with the newer (active) image's
2893 * security counter value.
2894 */
David Vincze1c456242021-06-29 15:25:24 +02002895#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
Mark Horvathccaf7f82021-01-04 18:16:42 +01002896 /* When the 'revert' mechanism is enabled in direct-xip mode, the
2897 * security counter can be increased only after reboot, if the image
2898 * has been confirmed at runtime (the image_ok flag has been set).
2899 * This way a 'revert' can be performed when it's necessary.
2900 */
2901 if (slot_usage[BOOT_CURR_IMG(state)].swap_state.image_ok == BOOT_FLAG_SET) {
David Vincze505fba22020-10-22 13:53:29 +02002902#endif
Sherry Zhang50b06ae2021-07-09 15:22:51 +08002903 rc = boot_update_security_counter(BOOT_CURR_IMG(state),
2904 slot_usage[BOOT_CURR_IMG(state)].active_slot,
2905 boot_img_hdr(state, slot_usage[BOOT_CURR_IMG(state)].active_slot));
David Vinczee574f2d2020-07-10 11:42:03 +02002906 if (rc != 0) {
Mark Horvathccaf7f82021-01-04 18:16:42 +01002907 BOOT_LOG_ERR("Security counter update failed after image "
2908 "validation.");
2909 return rc;
David Vinczee574f2d2020-07-10 11:42:03 +02002910 }
David Vincze1c456242021-06-29 15:25:24 +02002911#if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
Mark Horvathccaf7f82021-01-04 18:16:42 +01002912 }
2913#endif
David Vinczee574f2d2020-07-10 11:42:03 +02002914
Mark Horvathccaf7f82021-01-04 18:16:42 +01002915 return 0;
David Vinczee574f2d2020-07-10 11:42:03 +02002916
Mark Horvathccaf7f82021-01-04 18:16:42 +01002917#else /* MCUBOOT_HW_ROLLBACK_PROT */
2918 (void) (state);
Sherry Zhang50b06ae2021-07-09 15:22:51 +08002919 (void) (slot_usage);
Mark Horvathccaf7f82021-01-04 18:16:42 +01002920 return 0;
2921#endif
2922}
2923
2924fih_int
2925context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
2926{
2927 struct slot_usage_t slot_usage[BOOT_IMAGE_NUMBER];
2928 int rc;
David Brown695e5912021-05-24 16:58:01 -06002929 fih_int fih_rc = fih_int_encode(0);
Mark Horvathccaf7f82021-01-04 18:16:42 +01002930
2931 memset(state, 0, sizeof(struct boot_loader_state));
2932 memset(slot_usage, 0, sizeof(struct slot_usage_t) * BOOT_IMAGE_NUMBER);
2933
2934 rc = boot_get_slot_usage(state, slot_usage);
2935 if (rc != 0) {
David Vinczee574f2d2020-07-10 11:42:03 +02002936 goto out;
2937 }
2938
Mark Horvathccaf7f82021-01-04 18:16:42 +01002939#if (BOOT_IMAGE_NUMBER > 1)
2940 while (true) {
2941#endif
2942 FIH_CALL(boot_load_and_validate_images, fih_rc, state, slot_usage);
2943 if (fih_not_eq(fih_rc, FIH_SUCCESS)) {
2944 goto out;
2945 }
2946
2947#if (BOOT_IMAGE_NUMBER > 1)
2948 rc = boot_verify_dependencies(state, slot_usage);
2949 if (rc != 0) {
2950 /* Dependency check failed for an image, it has been removed from
2951 * SRAM in case of MCUBOOT_RAM_LOAD strategy, and set to
2952 * unavailable. Try to load an image from another slot.
2953 */
2954 continue;
2955 }
2956 /* Dependency check was successful. */
2957 break;
2958 }
2959#endif
2960
2961 IMAGES_ITER(BOOT_CURR_IMG(state)) {
Sherry Zhang50b06ae2021-07-09 15:22:51 +08002962 rc = boot_update_hw_rollback_protection(state, slot_usage);
Mark Horvathccaf7f82021-01-04 18:16:42 +01002963 if (rc != 0) {
2964 goto out;
2965 }
2966
Sherry Zhang50b06ae2021-07-09 15:22:51 +08002967 rc = boot_add_shared_data(state, slot_usage[BOOT_CURR_IMG(state)].active_slot);
Mark Horvathccaf7f82021-01-04 18:16:42 +01002968 if (rc != 0) {
2969 goto out;
2970 }
2971 }
2972
2973 /* All image loaded successfully. */
2974#ifdef MCUBOOT_HAVE_LOGGING
2975 print_loaded_images(state, slot_usage);
2976#endif
2977
2978 fill_rsp(state, slot_usage, rsp);
2979
David Vinczee574f2d2020-07-10 11:42:03 +02002980out:
Mark Horvathccaf7f82021-01-04 18:16:42 +01002981 close_all_flash_areas(state);
Raef Colese8fe6cf2020-05-26 13:07:40 +01002982
Mark Horvathccaf7f82021-01-04 18:16:42 +01002983 if (fih_eq(fih_rc, FIH_SUCCESS)) {
2984 fih_rc = fih_int_encode(rc);
2985 }
Raef Colese8fe6cf2020-05-26 13:07:40 +01002986
Mark Horvathccaf7f82021-01-04 18:16:42 +01002987 FIH_RET(fih_rc);
David Vinczee574f2d2020-07-10 11:42:03 +02002988}
Tamas Banfe031092020-09-10 17:32:39 +02002989#endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
David Vinczee574f2d2020-07-10 11:42:03 +02002990
2991/**
Raef Colese8fe6cf2020-05-26 13:07:40 +01002992 * Prepares the booting process. This function moves images around in flash as
David Vinczee574f2d2020-07-10 11:42:03 +02002993 * appropriate, and tells you what address to boot from.
2994 *
2995 * @param rsp On success, indicates how booting should occur.
2996 *
Raef Colese8fe6cf2020-05-26 13:07:40 +01002997 * @return FIH_SUCCESS on success; nonzero on failure.
David Vinczee574f2d2020-07-10 11:42:03 +02002998 */
Raef Colese8fe6cf2020-05-26 13:07:40 +01002999fih_int
David Vinczee574f2d2020-07-10 11:42:03 +02003000boot_go(struct boot_rsp *rsp)
3001{
Raef Colese8fe6cf2020-05-26 13:07:40 +01003002 fih_int fih_rc = FIH_FAILURE;
3003 FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp);
3004 FIH_RET(fih_rc);
David Vinczee574f2d2020-07-10 11:42:03 +02003005}