1 /*
2 * SPDX-License-Identifier: Apache-2.0
3 *
4 * Copyright (c) 2016-2020 Linaro LTD
5 * Copyright (c) 2016-2019 JUUL Labs
6 * Copyright (c) 2019-2023 Arm Limited
7 * Copyright (c) 2024-2025 Nordic Semiconductor ASA
8 *
9 * Original license:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one
12 * or more contributor license agreements. See the NOTICE file
13 * distributed with this work for additional information
14 * regarding copyright ownership. The ASF licenses this file
15 * to you under the Apache License, Version 2.0 (the
16 * "License"); you may not use this file except in compliance
17 * with the License. You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing,
22 * software distributed under the License is distributed on an
23 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
24 * KIND, either express or implied. See the License for the
25 * specific language governing permissions and limitations
26 * under the License.
27 */
28
29 /**
30 * This file provides an interface to the boot loader. Functions defined in
31 * this file should only be called while the boot loader is running.
32 */
33
34 #include <stddef.h>
35 #include <stdbool.h>
36 #include <inttypes.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include "bootutil/bootutil.h"
40 #include "bootutil/bootutil_public.h"
41 #include "bootutil/image.h"
42 #include "bootutil_priv.h"
43 #include "swap_priv.h"
44 #include "bootutil/bootutil_log.h"
45 #include "bootutil/security_cnt.h"
46 #include "bootutil/boot_record.h"
47 #include "bootutil/fault_injection_hardening.h"
48 #include "bootutil/ramload.h"
49 #include "bootutil/boot_hooks.h"
50 #include "bootutil/mcuboot_status.h"
51
52 #ifdef MCUBOOT_ENC_IMAGES
53 #include "bootutil/enc_key.h"
54 #endif
55
56 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
57 #include <os/os_malloc.h>
58 #endif
59
60 #include "mcuboot_config/mcuboot_config.h"
61
62 BOOT_LOG_MODULE_DECLARE(mcuboot);
63
64 static struct boot_loader_state boot_data;
65
66 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
67 static struct image_max_size image_max_sizes[BOOT_IMAGE_NUMBER] = {0};
68 #endif
69
70 #if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \
71 defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
72 #if !defined(__BOOTSIM__)
73 /* Used for holding static buffers in multiple functions to work around issues
74 * in older versions of gcc (e.g. 4.8.4)
75 */
76 struct sector_buffer_t {
77 boot_sector_t primary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
78 boot_sector_t secondary[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
79 #if MCUBOOT_SWAP_USING_SCRATCH
80 boot_sector_t scratch[BOOT_MAX_IMG_SECTORS];
81 #endif
82 };
83
84 static struct sector_buffer_t sector_buffers;
85 #endif
86 #endif
87
88 #if (BOOT_IMAGE_NUMBER > 1)
89 #define IMAGES_ITER(x) for ((x) = 0; (x) < BOOT_IMAGE_NUMBER; ++(x))
90 #else
91 #define IMAGES_ITER(x)
92 #endif
93
94 /*
95 * This macro allows some control on the allocation of local variables.
96 * When running natively on a target, we don't want to allocated huge
97 * variables on the stack, so make them global instead. For the simulator
98 * we want to run as many threads as there are tests, and it's safer
99 * to just make those variables stack allocated.
100 */
101 #if !defined(__BOOTSIM__)
102 #define TARGET_STATIC static
103 #else
104 #define TARGET_STATIC
105 #endif
106
107 #if BOOT_MAX_ALIGN > 1024
108 #define BUF_SZ BOOT_MAX_ALIGN
109 #else
110 #define BUF_SZ 1024
111 #endif
112
113 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_ENC_IMAGES)
114 #define BOOT_COPY_REGION(state, fap_pri, fap_sec, pri_off, sec_off, sz, sector_off) \
115 boot_copy_region(state, fap_pri, fap_sec, pri_off, sec_off, sz, sector_off)
116 #else
117 #define BOOT_COPY_REGION(state, fap_pri, fap_sec, pri_off, sec_off, sz, sector_off) \
118 boot_copy_region(state, fap_pri, fap_sec, pri_off, sec_off, sz)
119 #endif
120
boot_get_loader_state(void)121 struct boot_loader_state *boot_get_loader_state(void)
122 {
123 return &boot_data;
124 }
125
126 static int
boot_read_image_headers(struct boot_loader_state * state,bool require_all,struct boot_status * bs)127 boot_read_image_headers(struct boot_loader_state *state, bool require_all,
128 struct boot_status *bs)
129 {
130 int rc;
131 int i;
132
133 for (i = 0; i < BOOT_NUM_SLOTS; i++) {
134 rc = BOOT_HOOK_CALL(boot_read_image_header_hook, BOOT_HOOK_REGULAR,
135 BOOT_CURR_IMG(state), i, boot_img_hdr(state, i));
136 if (rc == BOOT_HOOK_REGULAR)
137 {
138 rc = boot_read_image_header(state, i, boot_img_hdr(state, i), bs);
139 }
140 if (rc != 0) {
141 /* If `require_all` is set, fail on any single fail, otherwise
142 * if at least the first slot's header was read successfully,
143 * then the boot loader can attempt a boot.
144 *
145 * Failure to read any headers is a fatal error.
146 */
147 if (i > 0 && !require_all) {
148 return 0;
149 } else {
150 return rc;
151 }
152 }
153 }
154
155 return 0;
156 }
157
158 /**
159 * Saves boot status and shared data for current image.
160 *
161 * @param state Boot loader status information.
162 * @param active_slot Index of the slot will be loaded for current image.
163 *
164 * @return 0 on success; nonzero on failure.
165 */
166 static int
boot_add_shared_data(struct boot_loader_state * state,uint8_t active_slot)167 boot_add_shared_data(struct boot_loader_state *state,
168 uint8_t active_slot)
169 {
170 #if defined(MCUBOOT_MEASURED_BOOT) || defined(MCUBOOT_DATA_SHARING)
171 int rc;
172
173 #ifdef MCUBOOT_MEASURED_BOOT
174 rc = boot_save_boot_status(BOOT_CURR_IMG(state),
175 boot_img_hdr(state, active_slot),
176 BOOT_IMG_AREA(state, active_slot));
177 if (rc != 0) {
178 BOOT_LOG_ERR("Failed to add image data to shared area");
179 return rc;
180 }
181 #endif /* MCUBOOT_MEASURED_BOOT */
182
183 #ifdef MCUBOOT_DATA_SHARING
184 rc = boot_save_shared_data(boot_img_hdr(state, active_slot),
185 BOOT_IMG_AREA(state, active_slot),
186 active_slot, image_max_sizes);
187 if (rc != 0) {
188 BOOT_LOG_ERR("Failed to add data to shared memory area.");
189 return rc;
190 }
191 #endif /* MCUBOOT_DATA_SHARING */
192
193 return 0;
194
195 #else /* MCUBOOT_MEASURED_BOOT || MCUBOOT_DATA_SHARING */
196 (void) (state);
197 (void) (active_slot);
198
199 return 0;
200 #endif
201 }
202
203 /**
204 * Fills rsp to indicate how booting should occur.
205 *
206 * @param state Boot loader status information.
207 * @param rsp boot_rsp struct to fill.
208 */
209 static void
fill_rsp(struct boot_loader_state * state,struct boot_rsp * rsp)210 fill_rsp(struct boot_loader_state *state, struct boot_rsp *rsp)
211 {
212 uint32_t active_slot;
213
214 #if (BOOT_IMAGE_NUMBER > 1)
215 /* Always boot from the first enabled image. */
216 BOOT_CURR_IMG(state) = 0;
217 IMAGES_ITER(BOOT_CURR_IMG(state)) {
218 if (!state->img_mask[BOOT_CURR_IMG(state)]) {
219 break;
220 }
221 }
222 /* At least one image must be active, otherwise skip the execution */
223 if (BOOT_CURR_IMG(state) >= BOOT_IMAGE_NUMBER) {
224 return;
225 }
226 #endif
227
228 #if defined(MCUBOOT_DIRECT_XIP) || defined(MCUBOOT_RAM_LOAD)
229 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
230 #else
231 active_slot = BOOT_PRIMARY_SLOT;
232 #endif
233
234 rsp->br_flash_dev_id = flash_area_get_device_id(BOOT_IMG_AREA(state, active_slot));
235 rsp->br_image_off = boot_img_slot_off(state, active_slot);
236 rsp->br_hdr = boot_img_hdr(state, active_slot);
237 }
238
239 /**
240 * Closes all flash areas.
241 *
242 * @param state Boot loader status information.
243 */
244 static void
close_all_flash_areas(struct boot_loader_state * state)245 close_all_flash_areas(struct boot_loader_state *state)
246 {
247 uint32_t slot;
248
249 IMAGES_ITER(BOOT_CURR_IMG(state)) {
250 #if BOOT_IMAGE_NUMBER > 1
251 if (state->img_mask[BOOT_CURR_IMG(state)]) {
252 continue;
253 }
254 #endif
255 #if MCUBOOT_SWAP_USING_SCRATCH
256 flash_area_close(BOOT_SCRATCH_AREA(state));
257 #endif
258 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
259 flash_area_close(BOOT_IMG_AREA(state, BOOT_NUM_SLOTS - 1 - slot));
260 }
261 }
262 }
263
264 #if (BOOT_IMAGE_NUMBER > 1) || \
265 defined(MCUBOOT_DIRECT_XIP) || \
266 defined(MCUBOOT_RAM_LOAD) || \
267 defined(MCUBOOT_DOWNGRADE_PREVENTION)
268 /**
269 * Compare image version numbers
270 *
271 * By default, the comparison does not take build number into account.
272 * Enable MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER to take the build number into account.
273 *
274 * @param ver1 Pointer to the first image version to compare.
275 * @param ver2 Pointer to the second image version to compare.
276 *
277 * @retval -1 If ver1 is less than ver2.
278 * @retval 0 If the image version numbers are equal.
279 * @retval 1 If ver1 is greater than ver2.
280 */
281 static int
boot_version_cmp(const struct image_version * ver1,const struct image_version * ver2)282 boot_version_cmp(const struct image_version *ver1,
283 const struct image_version *ver2)
284 {
285 if (ver1->iv_major > ver2->iv_major) {
286 return 1;
287 }
288 if (ver1->iv_major < ver2->iv_major) {
289 return -1;
290 }
291 /* The major version numbers are equal, continue comparison. */
292 if (ver1->iv_minor > ver2->iv_minor) {
293 return 1;
294 }
295 if (ver1->iv_minor < ver2->iv_minor) {
296 return -1;
297 }
298 /* The minor version numbers are equal, continue comparison. */
299 if (ver1->iv_revision > ver2->iv_revision) {
300 return 1;
301 }
302 if (ver1->iv_revision < ver2->iv_revision) {
303 return -1;
304 }
305
306 #if defined(MCUBOOT_VERSION_CMP_USE_BUILD_NUMBER)
307 /* The revisions are equal, continue comparison. */
308 if (ver1->iv_build_num > ver2->iv_build_num) {
309 return 1;
310 }
311 if (ver1->iv_build_num < ver2->iv_build_num) {
312 return -1;
313 }
314 #endif
315
316 return 0;
317 }
318 #endif
319
320 #if (!defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)) || \
321 defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
322 static int
boot_initialize_area(struct boot_loader_state * state,int flash_area)323 boot_initialize_area(struct boot_loader_state *state, int flash_area)
324 {
325 uint32_t num_sectors = BOOT_MAX_IMG_SECTORS;
326 boot_sector_t *out_sectors;
327 uint32_t *out_num_sectors;
328 int rc;
329
330 num_sectors = BOOT_MAX_IMG_SECTORS;
331
332 if (flash_area == FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state))) {
333 out_sectors = BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors;
334 out_num_sectors = &BOOT_IMG(state, BOOT_PRIMARY_SLOT).num_sectors;
335 } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
336 out_sectors = BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors;
337 out_num_sectors = &BOOT_IMG(state, BOOT_SECONDARY_SLOT).num_sectors;
338 #if MCUBOOT_SWAP_USING_SCRATCH
339 } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
340 out_sectors = state->scratch.sectors;
341 out_num_sectors = &state->scratch.num_sectors;
342 #endif
343 } else {
344 return BOOT_EFLASH;
345 }
346
347 #ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
348 rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
349 #else
350 _Static_assert(sizeof(int) <= sizeof(uint32_t), "Fix needed");
351 rc = flash_area_to_sectors(flash_area, (int *)&num_sectors, out_sectors);
352 #endif /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
353 if (rc != 0) {
354 return rc;
355 }
356 *out_num_sectors = num_sectors;
357 return 0;
358 }
359 #endif
360
361 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
362 static int
boot_read_sectors_recovery(struct boot_loader_state * state)363 boot_read_sectors_recovery(struct boot_loader_state *state)
364 {
365 uint8_t image_index;
366 int rc;
367
368 image_index = BOOT_CURR_IMG(state);
369
370 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
371 if (rc != 0) {
372 return BOOT_EFLASH;
373 }
374
375 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index));
376 if (rc != 0) {
377 /* We need to differentiate from the primary image issue */
378 return BOOT_EFLASH_SEC;
379 }
380
381 return 0;
382 }
383 #endif
384
385
386 #if (BOOT_IMAGE_NUMBER > 1)
387
388 static int
389 boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot);
390
391 /**
392 * Check the image dependency whether it is satisfied and modify
393 * the swap type if necessary.
394 *
395 * @param dep Image dependency which has to be verified.
396 *
397 * @return 0 on success; nonzero on failure.
398 */
399 static int
boot_verify_slot_dependency(struct boot_loader_state * state,struct image_dependency * dep)400 boot_verify_slot_dependency(struct boot_loader_state *state,
401 struct image_dependency *dep)
402 {
403 struct image_version *dep_version;
404 size_t dep_slot;
405 int rc;
406
407 /* Determine the source of the image which is the subject of
408 * the dependency and get it's version. */
409 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
410 uint8_t swap_type = state->swap_type[dep->image_id];
411 dep_slot = BOOT_IS_UPGRADE(swap_type) ? BOOT_SECONDARY_SLOT
412 : BOOT_PRIMARY_SLOT;
413 #else
414 dep_slot = state->slot_usage[dep->image_id].active_slot;
415 #endif
416
417 dep_version = &state->imgs[dep->image_id][dep_slot].hdr.ih_ver;
418
419 rc = boot_version_cmp(dep_version, &dep->image_min_version);
420 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
421 if (rc < 0) {
422 /* Dependency not satisfied.
423 * Modify the swap type to decrease the version number of the image
424 * (which will be located in the primary slot after the boot process),
425 * consequently the number of unsatisfied dependencies will be
426 * decreased or remain the same.
427 */
428 switch (BOOT_SWAP_TYPE(state)) {
429 case BOOT_SWAP_TYPE_TEST:
430 case BOOT_SWAP_TYPE_PERM:
431 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
432 break;
433 case BOOT_SWAP_TYPE_NONE:
434 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT;
435 break;
436 default:
437 break;
438 }
439 } else {
440 /* Dependency satisfied. */
441 rc = 0;
442 }
443 #else
444 if (rc >= 0) {
445 /* Dependency satisfied. */
446 rc = 0;
447 }
448 #endif
449
450 return rc;
451 }
452
453 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
454 /**
455 * Iterate over all the images and verify whether the image dependencies in the
456 * TLV area are all satisfied and update the related swap type if necessary.
457 */
458 static int
boot_verify_dependencies(struct boot_loader_state * state)459 boot_verify_dependencies(struct boot_loader_state *state)
460 {
461 int rc = -1;
462 uint8_t slot;
463
464 BOOT_CURR_IMG(state) = 0;
465 while (BOOT_CURR_IMG(state) < BOOT_IMAGE_NUMBER) {
466 if (state->img_mask[BOOT_CURR_IMG(state)]) {
467 BOOT_CURR_IMG(state)++;
468 continue;
469 }
470 if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE &&
471 BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_FAIL) {
472 slot = BOOT_SECONDARY_SLOT;
473 } else {
474 slot = BOOT_PRIMARY_SLOT;
475 }
476
477 rc = boot_verify_slot_dependencies(state, slot);
478 if (rc == 0) {
479 /* All dependencies've been satisfied, continue with next image. */
480 BOOT_CURR_IMG(state)++;
481 } else {
482 /* Cannot upgrade due to non-met dependencies, so disable all
483 * image upgrades.
484 */
485 for (int idx = 0; idx < BOOT_IMAGE_NUMBER; idx++) {
486 BOOT_CURR_IMG(state) = idx;
487 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
488 }
489 break;
490 }
491 }
492 return rc;
493 }
494 #else
495
496 /**
497 * Checks the dependency of all the active slots. If an image found with
498 * invalid or not satisfied dependencies the image is removed from SRAM (in
499 * case of MCUBOOT_RAM_LOAD strategy) and its slot is set to unavailable.
500 *
501 * @param state Boot loader status information.
502 *
503 * @return 0 if dependencies are met; nonzero otherwise.
504 */
505 static int
boot_verify_dependencies(struct boot_loader_state * state)506 boot_verify_dependencies(struct boot_loader_state *state)
507 {
508 int rc = -1;
509 uint32_t active_slot;
510
511 IMAGES_ITER(BOOT_CURR_IMG(state)) {
512 if (state->img_mask[BOOT_CURR_IMG(state)]) {
513 continue;
514 }
515 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
516 rc = boot_verify_slot_dependencies(state, active_slot);
517 if (rc != 0) {
518 /* Dependencies not met or invalid dependencies. */
519
520 #ifdef MCUBOOT_RAM_LOAD
521 boot_remove_image_from_sram(state);
522 #endif /* MCUBOOT_RAM_LOAD */
523
524 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
525 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
526
527 return rc;
528 }
529 }
530
531 return rc;
532 }
533 #endif
534
535 /**
536 * Read all dependency TLVs of an image from the flash and verify
537 * one after another to see if they are all satisfied.
538 *
539 * @param slot Image slot number.
540 *
541 * @return 0 on success; nonzero on failure.
542 */
543 static int
boot_verify_slot_dependencies(struct boot_loader_state * state,uint32_t slot)544 boot_verify_slot_dependencies(struct boot_loader_state *state, uint32_t slot)
545 {
546 const struct flash_area *fap;
547 struct image_tlv_iter it;
548 struct image_dependency dep;
549 uint32_t off;
550 uint16_t len;
551 int area_id;
552 int rc;
553
554 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
555 rc = flash_area_open(area_id, &fap);
556 if (rc != 0) {
557 rc = BOOT_EFLASH;
558 goto done;
559 }
560
561 #if defined(MCUBOOT_SWAP_USING_OFFSET)
562 it.start_off = boot_get_state_secondary_offset(state, fap);
563 #endif
564
565 rc = bootutil_tlv_iter_begin(&it, boot_img_hdr(state, slot), fap,
566 IMAGE_TLV_DEPENDENCY, true);
567 if (rc != 0) {
568 goto done;
569 }
570
571 while (true) {
572 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
573 if (rc < 0) {
574 return -1;
575 } else if (rc > 0) {
576 rc = 0;
577 break;
578 }
579
580 if (len != sizeof(dep)) {
581 rc = BOOT_EBADIMAGE;
582 goto done;
583 }
584
585 rc = LOAD_IMAGE_DATA(boot_img_hdr(state, slot),
586 fap, off, &dep, len);
587 if (rc != 0) {
588 rc = BOOT_EFLASH;
589 goto done;
590 }
591
592 if (dep.image_id >= BOOT_IMAGE_NUMBER) {
593 rc = BOOT_EBADARGS;
594 goto done;
595 }
596
597 /* Verify dependency and modify the swap type if not satisfied. */
598 rc = boot_verify_slot_dependency(state, &dep);
599 if (rc != 0) {
600 /* Dependency not satisfied */
601 goto done;
602 }
603 }
604
605 done:
606 flash_area_close(fap);
607 return rc;
608 }
609
610 #endif /* (BOOT_IMAGE_NUMBER > 1) */
611
612 #if !defined(MCUBOOT_DIRECT_XIP)
613
614 #if !defined(MCUBOOT_RAM_LOAD)
615 static uint32_t
boot_write_sz(struct boot_loader_state * state)616 boot_write_sz(struct boot_loader_state *state)
617 {
618 uint32_t elem_sz;
619 #if MCUBOOT_SWAP_USING_SCRATCH
620 uint32_t align;
621 #endif
622
623 /* Figure out what size to write update status update as. The size depends
624 * on what the minimum write size is for scratch area, active image slot.
625 * We need to use the bigger of those 2 values.
626 */
627 elem_sz = flash_area_align(BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT));
628 #if MCUBOOT_SWAP_USING_SCRATCH
629 align = flash_area_align(BOOT_SCRATCH_AREA(state));
630 if (align > elem_sz) {
631 elem_sz = align;
632 }
633 #endif
634
635 return elem_sz;
636 }
637
638 /**
639 * Determines the sector layout of both image slots and the scratch area.
640 * This information is necessary for calculating the number of bytes to erase
641 * and copy during an image swap. The information collected during this
642 * function is used to populate the state.
643 */
644 static int
boot_read_sectors(struct boot_loader_state * state)645 boot_read_sectors(struct boot_loader_state *state)
646 {
647 uint8_t image_index;
648 int rc;
649
650 image_index = BOOT_CURR_IMG(state);
651
652 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_PRIMARY(image_index));
653 if (rc != 0) {
654 return BOOT_EFLASH;
655 }
656
657 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SECONDARY(image_index));
658 if (rc != 0) {
659 /* We need to differentiate from the primary image issue */
660 return BOOT_EFLASH_SEC;
661 }
662
663 #if MCUBOOT_SWAP_USING_SCRATCH
664 rc = boot_initialize_area(state, FLASH_AREA_IMAGE_SCRATCH);
665 if (rc != 0) {
666 return BOOT_EFLASH;
667 }
668 #endif
669
670 BOOT_WRITE_SZ(state) = boot_write_sz(state);
671
672 return 0;
673 }
674
675 void
boot_status_reset(struct boot_status * bs)676 boot_status_reset(struct boot_status *bs)
677 {
678 #ifdef MCUBOOT_ENC_IMAGES
679 memset(&bs->enckey, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_KEY_ALIGN_SIZE);
680 #if MCUBOOT_SWAP_SAVE_ENCTLV
681 memset(&bs->enctlv, 0xff, BOOT_NUM_SLOTS * BOOT_ENC_TLV_ALIGN_SIZE);
682 #endif
683 #endif /* MCUBOOT_ENC_IMAGES */
684
685 bs->use_scratch = 0;
686 bs->swap_size = 0;
687 bs->source = 0;
688
689 #if defined(MCUBOOT_SWAP_USING_OFFSET)
690 bs->op = BOOT_STATUS_OP_SWAP;
691 #else
692 bs->op = BOOT_STATUS_OP_MOVE;
693 #endif
694 bs->idx = BOOT_STATUS_IDX_0;
695 bs->state = BOOT_STATUS_STATE_0;
696 bs->swap_type = BOOT_SWAP_TYPE_NONE;
697 }
698
699 bool
boot_status_is_reset(const struct boot_status * bs)700 boot_status_is_reset(const struct boot_status *bs)
701 {
702 return (
703 #if defined(MCUBOOT_SWAP_USING_OFFSET)
704 bs->op == BOOT_STATUS_OP_SWAP &&
705 #else
706 bs->op == BOOT_STATUS_OP_MOVE &&
707 #endif
708 bs->idx == BOOT_STATUS_IDX_0 &&
709 bs->state == BOOT_STATUS_STATE_0);
710 }
711
712 /**
713 * Writes the supplied boot status to the flash file system. The boot status
714 * contains the current state of an in-progress image copy operation.
715 *
716 * @param bs The boot status to write.
717 *
718 * @return 0 on success; nonzero on failure.
719 */
720 int
boot_write_status(const struct boot_loader_state * state,struct boot_status * bs)721 boot_write_status(const struct boot_loader_state *state, struct boot_status *bs)
722 {
723 const struct flash_area *fap;
724 uint32_t off;
725 int area_id;
726 int rc = 0;
727 uint8_t buf[BOOT_MAX_ALIGN];
728 uint32_t align;
729 uint8_t erased_val;
730
731 /* NOTE: The first sector copied (that is the last sector on slot) contains
732 * the trailer. Since in the last step the primary slot is erased, the
733 * first two status writes go to the scratch which will be copied to
734 * the primary slot!
735 */
736
737 #if MCUBOOT_SWAP_USING_SCRATCH
738 if (bs->use_scratch) {
739 /* Write to scratch. */
740 area_id = FLASH_AREA_IMAGE_SCRATCH;
741 } else {
742 #endif
743 /* Write to the primary slot. */
744 area_id = FLASH_AREA_IMAGE_PRIMARY(BOOT_CURR_IMG(state));
745 #if MCUBOOT_SWAP_USING_SCRATCH
746 }
747 #endif
748
749 rc = flash_area_open(area_id, &fap);
750 if (rc != 0) {
751 return BOOT_EFLASH;
752 }
753
754 off = boot_status_off(fap) +
755 boot_status_internal_off(bs, BOOT_WRITE_SZ(state));
756 align = flash_area_align(fap);
757 erased_val = flash_area_erased_val(fap);
758 memset(buf, erased_val, BOOT_MAX_ALIGN);
759 buf[0] = bs->state;
760
761 BOOT_LOG_DBG("writing swap status; fa_id=%d off=0x%lx (0x%lx)",
762 flash_area_get_id(fap), (unsigned long)off,
763 (unsigned long)flash_area_get_off(fap) + off);
764
765 rc = flash_area_write(fap, off, buf, align);
766 if (rc != 0) {
767 rc = BOOT_EFLASH;
768 }
769
770 flash_area_close(fap);
771
772 return rc;
773 }
774 #endif /* !MCUBOOT_RAM_LOAD */
775 #endif /* !MCUBOOT_DIRECT_XIP */
776
777 /*
778 * Validate image hash/signature and optionally the security counter in a slot.
779 */
780 static fih_ret
boot_image_check(struct boot_loader_state * state,struct image_header * hdr,const struct flash_area * fap,struct boot_status * bs)781 boot_image_check(struct boot_loader_state *state, struct image_header *hdr,
782 const struct flash_area *fap, struct boot_status *bs)
783 {
784 TARGET_STATIC uint8_t tmpbuf[BOOT_TMPBUF_SZ];
785 int rc;
786 FIH_DECLARE(fih_rc, FIH_FAILURE);
787
788 #if (BOOT_IMAGE_NUMBER == 1)
789 (void)state;
790 #endif
791
792 (void)bs;
793 (void)rc;
794
795 /* In the case of ram loading the image has already been decrypted as it is
796 * decrypted when copied in ram
797 */
798 #if defined(MCUBOOT_ENC_IMAGES) && !defined(MCUBOOT_RAM_LOAD)
799 if (MUST_DECRYPT(fap, BOOT_CURR_IMG(state), hdr)) {
800 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
801 rc = boot_enc_load(state, 1, hdr, fap, bs, 0);
802 #else
803 rc = boot_enc_load(state, 1, hdr, fap, bs);
804 #endif
805 if (rc < 0) {
806 FIH_RET(fih_rc);
807 }
808 if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) {
809 FIH_RET(fih_rc);
810 }
811 }
812 #endif
813
814 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
815 FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
816 NULL, 0, NULL, 0);
817 #else
818 FIH_CALL(bootutil_img_validate, fih_rc, state, hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
819 NULL, 0, NULL);
820 #endif
821
822 FIH_RET(fih_rc);
823 }
824
825 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
826 static fih_ret
split_image_check(struct image_header * app_hdr,const struct flash_area * app_fap,struct image_header * loader_hdr,const struct flash_area * loader_fap)827 split_image_check(struct image_header *app_hdr,
828 const struct flash_area *app_fap,
829 struct image_header *loader_hdr,
830 const struct flash_area *loader_fap)
831 {
832 static void *tmpbuf;
833 uint8_t loader_hash[32];
834 FIH_DECLARE(fih_rc, FIH_FAILURE);
835
836 if (!tmpbuf) {
837 tmpbuf = malloc(BOOT_TMPBUF_SZ);
838 if (!tmpbuf) {
839 goto out;
840 }
841 }
842
843 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
844 FIH_CALL(bootutil_img_validate, fih_rc, NULL, loader_hdr, loader_fap,
845 tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash, 0);
846 #else
847 FIH_CALL(bootutil_img_validate, fih_rc, NULL, loader_hdr, loader_fap,
848 tmpbuf, BOOT_TMPBUF_SZ, NULL, 0, loader_hash);
849 #endif
850 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
851 FIH_RET(fih_rc);
852 }
853
854 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
855 FIH_CALL(bootutil_img_validate, fih_rc, NULL, app_hdr, app_fap,
856 tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL, 0);
857 #else
858 FIH_CALL(bootutil_img_validate, fih_rc, NULL, app_hdr, app_fap,
859 tmpbuf, BOOT_TMPBUF_SZ, loader_hash, 32, NULL);
860 #endif
861
862 out:
863 FIH_RET(fih_rc);
864 }
865 #endif /* !MCUBOOT_DIRECT_XIP && !MCUBOOT_RAM_LOAD */
866
867 /*
868 * Check that this is a valid header. Valid means that the magic is
869 * correct, and that the sizes/offsets are "sane". Sane means that
870 * there is no overflow on the arithmetic, and that the result fits
871 * within the flash area we are in. Also check the flags in the image
872 * and class the image as invalid if flags for encryption/compression
873 * are present but these features are not enabled.
874 */
875 static bool
boot_is_header_valid(const struct image_header * hdr,const struct flash_area * fap,struct boot_loader_state * state)876 boot_is_header_valid(const struct image_header *hdr, const struct flash_area *fap,
877 struct boot_loader_state *state)
878 {
879 uint32_t size;
880
881 (void)state;
882
883 if (hdr->ih_magic != IMAGE_MAGIC) {
884 return false;
885 }
886
887 if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size)) {
888 return false;
889 }
890
891 #ifdef MCUBOOT_DECOMPRESS_IMAGES
892 if (!MUST_DECOMPRESS(fap, BOOT_CURR_IMG(state), hdr)) {
893 #else
894 if (1) {
895 #endif
896 if (!boot_u32_safe_add(&size, size, hdr->ih_protect_tlv_size)) {
897 return false;
898 }
899 }
900
901 if (size >= flash_area_get_size(fap)) {
902 return false;
903 }
904
905 #if !defined(MCUBOOT_ENC_IMAGES)
906 if (IS_ENCRYPTED(hdr)) {
907 return false;
908 }
909 #else
910 if ((hdr->ih_flags & IMAGE_F_ENCRYPTED_AES128) &&
911 (hdr->ih_flags & IMAGE_F_ENCRYPTED_AES256))
912 {
913 return false;
914 }
915 #endif
916
917 #if !defined(MCUBOOT_DECOMPRESS_IMAGES)
918 if (IS_COMPRESSED(hdr)) {
919 return false;
920 }
921 #else
922 if ((hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA1) &&
923 (hdr->ih_flags & IMAGE_F_COMPRESSED_LZMA2))
924 {
925 return false;
926 }
927 #endif
928
929 return true;
930 }
931
932 /*
933 * Check that a memory area consists of a given value.
934 */
935 static inline bool
936 boot_data_is_set_to(uint8_t val, void *data, size_t len)
937 {
938 uint8_t i;
939 uint8_t *p = (uint8_t *)data;
940 for (i = 0; i < len; i++) {
941 if (val != p[i]) {
942 return false;
943 }
944 }
945 return true;
946 }
947
948 static int
949 boot_check_header_erased(struct boot_loader_state *state, int slot)
950 {
951 const struct flash_area *fap;
952 struct image_header *hdr;
953 uint8_t erased_val;
954 int area_id;
955 int rc;
956
957 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
958 rc = flash_area_open(area_id, &fap);
959 if (rc != 0) {
960 return -1;
961 }
962
963 erased_val = flash_area_erased_val(fap);
964 flash_area_close(fap);
965
966 hdr = boot_img_hdr(state, slot);
967 if (!boot_data_is_set_to(erased_val, &hdr->ih_magic, sizeof(hdr->ih_magic))) {
968 return -1;
969 }
970
971 return 0;
972 }
973
974 #if defined(MCUBOOT_DIRECT_XIP)
975 /**
976 * Check if image in slot has been set with specific ROM address to run from
977 * and whether the slot starts at that address.
978 *
979 * @returns 0 if IMAGE_F_ROM_FIXED flag is not set;
980 * 0 if IMAGE_F_ROM_FIXED flag is set and ROM address specified in
981 * header matches the slot address;
982 * 1 if IMF_F_ROM_FIXED flag is set but ROM address specified in header
983 * does not match the slot address.
984 */
985 static bool
986 boot_rom_address_check(struct boot_loader_state *state)
987 {
988 uint32_t active_slot;
989 const struct image_header *hdr;
990 uint32_t f_off;
991
992 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
993 hdr = boot_img_hdr(state, active_slot);
994 f_off = boot_img_slot_off(state, active_slot);
995
996 if (hdr->ih_flags & IMAGE_F_ROM_FIXED && hdr->ih_load_addr != f_off) {
997 BOOT_LOG_WRN("Image in %s slot at 0x%x has been built for offset 0x%x"\
998 ", skipping",
999 active_slot == 0 ? "primary" : "secondary", f_off,
1000 hdr->ih_load_addr);
1001
1002 /* If there is address mismatch, the image is not bootable from this
1003 * slot.
1004 */
1005 return 1;
1006 }
1007 return 0;
1008 }
1009 #endif
1010
1011 /*
1012 * Check that there is a valid image in a slot
1013 *
1014 * @returns
1015 * FIH_SUCCESS if image was successfully validated
1016 * FIH_NO_BOOTABLE_IMAGE if no bootloable image was found
1017 * FIH_FAILURE on any errors
1018 */
1019 static fih_ret
1020 boot_validate_slot(struct boot_loader_state *state, int slot,
1021 struct boot_status *bs, int expected_swap_type)
1022 {
1023 const struct flash_area *fap;
1024 struct image_header *hdr;
1025 int area_id;
1026 FIH_DECLARE(fih_rc, FIH_FAILURE);
1027 int rc;
1028
1029 #if !defined(MCUBOOT_SWAP_USING_OFFSET)
1030 (void)expected_swap_type;
1031 #endif
1032
1033 area_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot);
1034 rc = flash_area_open(area_id, &fap);
1035 if (rc != 0) {
1036 FIH_RET(fih_rc);
1037 }
1038
1039 hdr = boot_img_hdr(state, slot);
1040 if (boot_check_header_erased(state, slot) == 0 ||
1041 (hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) {
1042 #if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET)
1043 /*
1044 * This fixes an issue where an image might be erased, but a trailer
1045 * be left behind. It can happen if the image is in the secondary slot
1046 * and did not pass validation, in which case the whole slot is erased.
1047 * If during the erase operation, a reset occurs, parts of the slot
1048 * might have been erased while some did not. The concerning part is
1049 * the trailer because it might disable a new image from being loaded
1050 * through mcumgr; so we just get rid of the trailer here, if the header
1051 * is erased.
1052 */
1053 if (slot != BOOT_PRIMARY_SLOT) {
1054 swap_erase_trailer_sectors(state, fap);
1055
1056 #if defined(MCUBOOT_SWAP_USING_MOVE)
1057 if (bs->swap_type == BOOT_SWAP_TYPE_REVERT ||
1058 boot_swap_type_multi(BOOT_CURR_IMG(state)) == BOOT_SWAP_TYPE_REVERT) {
1059 const struct flash_area *fap_pri;
1060
1061 rc = flash_area_open(flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state),
1062 BOOT_PRIMARY_SLOT),
1063 &fap_pri);
1064
1065 if (rc == 0) {
1066 rc = swap_erase_trailer_sectors(state, fap_pri);
1067 flash_area_close(fap_pri);
1068
1069 if (rc == 0) {
1070 BOOT_LOG_INF("Cleared image %d primary slot trailer due to stuck revert",
1071 BOOT_CURR_IMG(state));
1072 }
1073 }
1074 }
1075 #endif
1076 }
1077 #endif
1078
1079 /* No bootable image in slot; continue booting from the primary slot. */
1080 fih_rc = FIH_NO_BOOTABLE_IMAGE;
1081 goto out;
1082 }
1083
1084 #if defined(MCUBOOT_SWAP_USING_OFFSET)
1085 if (slot != BOOT_PRIMARY_SLOT && boot_status_is_reset(bs) &&
1086 (expected_swap_type == BOOT_SWAP_TYPE_TEST || expected_swap_type == BOOT_SWAP_TYPE_PERM)) {
1087 /* Check first sector to see if there is a magic header here, if so the update has likely
1088 * been loaded to the wrong sector and cannot be used
1089 */
1090 struct image_header first_sector_hdr;
1091
1092 if (flash_area_read(fap, 0, &first_sector_hdr, sizeof(first_sector_hdr))) {
1093 FIH_RET(fih_rc);
1094 }
1095
1096 if (first_sector_hdr.ih_magic == IMAGE_MAGIC) {
1097 BOOT_LOG_ERR("Secondary header magic detected in first sector, wrong upload address?");
1098 fih_rc = FIH_NO_BOOTABLE_IMAGE;
1099 goto check_validity;
1100 }
1101 }
1102 #endif
1103
1104 #if defined(MCUBOOT_OVERWRITE_ONLY) && defined(MCUBOOT_DOWNGRADE_PREVENTION)
1105 if (slot != BOOT_PRIMARY_SLOT) {
1106 /* Check if version of secondary slot is sufficient */
1107 rc = boot_version_cmp(
1108 &boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver,
1109 &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver);
1110 if (rc < 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT)) {
1111 BOOT_LOG_ERR("insufficient version in secondary slot");
1112 flash_area_erase(fap, 0, flash_area_get_size(fap));
1113 /* Image in the secondary slot does not satisfy version requirement.
1114 * Erase the image and continue booting from the primary slot.
1115 */
1116 fih_rc = FIH_NO_BOOTABLE_IMAGE;
1117 goto out;
1118 }
1119 }
1120 #endif
1121 if (!boot_is_header_valid(hdr, fap, state)) {
1122 fih_rc = FIH_FAILURE;
1123 } else {
1124 BOOT_HOOK_CALL_FIH(boot_image_check_hook, FIH_BOOT_HOOK_REGULAR,
1125 fih_rc, BOOT_CURR_IMG(state), slot);
1126 if (FIH_EQ(fih_rc, FIH_BOOT_HOOK_REGULAR)) {
1127 FIH_CALL(boot_image_check, fih_rc, state, hdr, fap, bs);
1128 }
1129 }
1130 #if defined(MCUBOOT_SWAP_USING_OFFSET)
1131 check_validity:
1132 #endif
1133 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
1134 if ((slot != BOOT_PRIMARY_SLOT) || ARE_SLOTS_EQUIVALENT()) {
1135 flash_area_erase(fap, 0, flash_area_get_size(fap));
1136 /* Image is invalid, erase it to prevent further unnecessary
1137 * attempts to validate and boot it.
1138 */
1139 }
1140 #if !defined(__BOOTSIM__)
1141 BOOT_LOG_ERR("Image in the %s slot is not valid!",
1142 (slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
1143 #endif
1144 fih_rc = FIH_NO_BOOTABLE_IMAGE;
1145 goto out;
1146 }
1147
1148 #if MCUBOOT_IMAGE_NUMBER > 1 && !defined(MCUBOOT_ENC_IMAGES) && defined(MCUBOOT_VERIFY_IMG_ADDRESS)
1149 /* Verify that the image in the secondary slot has a reset address
1150 * located in the primary slot. This is done to avoid users incorrectly
1151 * overwriting an application written to the incorrect slot.
1152 * This feature is only supported by ARM platforms.
1153 */
1154 if (area_id == FLASH_AREA_IMAGE_SECONDARY(BOOT_CURR_IMG(state))) {
1155 const struct flash_area *pri_fa = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
1156 struct image_header *secondary_hdr = boot_img_hdr(state, slot);
1157 uint32_t reset_value = 0;
1158 uint32_t reset_addr = secondary_hdr->ih_hdr_size + sizeof(reset_value);
1159
1160 rc = flash_area_read(fap, reset_addr, &reset_value, sizeof(reset_value));
1161 if (rc != 0) {
1162 fih_rc = FIH_NO_BOOTABLE_IMAGE;
1163 goto out;
1164 }
1165
1166 if (reset_value < pri_fa->fa_off || reset_value> (pri_fa->fa_off + pri_fa->fa_size)) {
1167 BOOT_LOG_ERR("Reset address of image in secondary slot is not in the primary slot");
1168 BOOT_LOG_ERR("Erasing image from secondary slot");
1169
1170 /* The vector table in the image located in the secondary
1171 * slot does not target the primary slot. This might
1172 * indicate that the image was loaded to the wrong slot.
1173 *
1174 * Erase the image and continue booting from the primary slot.
1175 */
1176 flash_area_erase(fap, 0, fap->fa_size);
1177 fih_rc = FIH_NO_BOOTABLE_IMAGE;
1178 goto out;
1179 }
1180 }
1181 #endif
1182
1183 out:
1184 flash_area_close(fap);
1185
1186 FIH_RET(fih_rc);
1187 }
1188
1189 #ifdef MCUBOOT_HW_ROLLBACK_PROT
1190 /**
1191 * Updates the stored security counter value with the image's security counter
1192 * value which resides in the given slot, only if it's greater than the stored
1193 * value.
1194 *
1195 * @param state Boot state where the current image's security counter will
1196 * be updated.
1197 * @param slot Slot number of the image.
1198 * @param hdr_slot_idx Index of the header in the state current image variable
1199 * containing the pointer to the image header structure of the
1200 * image that is currently stored in the given slot.
1201 *
1202 * @return 0 on success; nonzero on failure.
1203 */
1204 static int
1205 boot_update_security_counter(struct boot_loader_state *state, int slot, int hdr_slot_idx)
1206 {
1207 const struct flash_area *fap = NULL;
1208 uint32_t img_security_cnt;
1209 int rc;
1210
1211 rc = flash_area_open(flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), slot),
1212 &fap);
1213 if (rc != 0) {
1214 rc = BOOT_EFLASH;
1215 goto done;
1216 }
1217
1218 rc = bootutil_get_img_security_cnt(state, hdr_slot_idx, fap, &img_security_cnt);
1219 if (rc != 0) {
1220 goto done;
1221 }
1222
1223 rc = boot_nv_security_counter_update(BOOT_CURR_IMG(state), img_security_cnt);
1224 if (rc != 0) {
1225 goto done;
1226 }
1227
1228 done:
1229 flash_area_close(fap);
1230 return rc;
1231 }
1232 #endif /* MCUBOOT_HW_ROLLBACK_PROT */
1233
1234 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
1235 /**
1236 * Determines which swap operation to perform, if any. If it is determined
1237 * that a swap operation is required, the image in the secondary slot is checked
1238 * for validity. If the image in the secondary slot is invalid, it is erased,
1239 * and a swap type of "none" is indicated.
1240 *
1241 * @return The type of swap to perform (BOOT_SWAP_TYPE...)
1242 */
1243 static int
1244 boot_validated_swap_type(struct boot_loader_state *state,
1245 struct boot_status *bs)
1246 {
1247 int swap_type;
1248 FIH_DECLARE(fih_rc, FIH_FAILURE);
1249
1250 swap_type = boot_swap_type_multi(BOOT_CURR_IMG(state));
1251 if (BOOT_IS_UPGRADE(swap_type)) {
1252 /* Boot loader wants to switch to the secondary slot.
1253 * Ensure image is valid.
1254 */
1255 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_SECONDARY_SLOT, bs, swap_type);
1256 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
1257 if (FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) {
1258 swap_type = BOOT_SWAP_TYPE_NONE;
1259 } else {
1260 swap_type = BOOT_SWAP_TYPE_FAIL;
1261 }
1262 }
1263 }
1264
1265 return swap_type;
1266 }
1267 #endif
1268
1269 /**
1270 * Erases a region of flash.
1271 *
1272 * @param flash_area The flash_area containing the region to erase.
1273 * @param off The offset within the flash area to start the
1274 * erase.
1275 * @param sz The number of bytes to erase.
1276 *
1277 * @return 0 on success; nonzero on failure.
1278 */
1279 int
1280 boot_erase_region(const struct flash_area *fap, uint32_t off, uint32_t sz)
1281 {
1282 return flash_area_erase(fap, off, sz);
1283 }
1284
1285 #if !defined(MCUBOOT_DIRECT_XIP) && !defined(MCUBOOT_RAM_LOAD)
1286
1287 #if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SWAP_SAVE_ENCTLV)
1288 /* Replacement for memset(p, 0, sizeof(*p) that does not get
1289 * optimized out.
1290 */
1291 static void like_mbedtls_zeroize(void *p, size_t n)
1292 {
1293 volatile unsigned char *v = (unsigned char *)p;
1294
1295 for (size_t i = 0; i < n; i++) {
1296 v[i] = 0;
1297 }
1298 }
1299 #endif
1300
1301 /**
1302 * Copies the contents of one flash region to another. You must erase the
1303 * destination region prior to calling this function.
1304 *
1305 * @param flash_area_id_src The ID of the source flash area.
1306 * @param flash_area_id_dst The ID of the destination flash area.
1307 * @param off_src The offset within the source flash area to
1308 * copy from.
1309 * @param off_dst The offset within the destination flash area to
1310 * copy to.
1311 * @param sz The number of bytes to copy.
1312 * @param sector_off (Swap using offset with encryption only) the
1313 * sector offset for encryption/decryption
1314 *
1315 * @return 0 on success; nonzero on failure.
1316 */
1317 int
1318 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_ENC_IMAGES)
1319 boot_copy_region(struct boot_loader_state *state,
1320 const struct flash_area *fap_src,
1321 const struct flash_area *fap_dst,
1322 uint32_t off_src, uint32_t off_dst, uint32_t sz, uint32_t sector_off)
1323 #else
1324 boot_copy_region(struct boot_loader_state *state,
1325 const struct flash_area *fap_src,
1326 const struct flash_area *fap_dst,
1327 uint32_t off_src, uint32_t off_dst, uint32_t sz)
1328 #endif
1329 {
1330 uint32_t bytes_copied;
1331 int chunk_sz;
1332 int rc;
1333 #ifdef MCUBOOT_ENC_IMAGES
1334 uint32_t off = off_dst;
1335 uint32_t tlv_off;
1336 size_t blk_off;
1337 struct image_header *hdr;
1338 uint16_t idx;
1339 uint32_t blk_sz;
1340 uint8_t image_index = BOOT_CURR_IMG(state);
1341 bool encrypted_src;
1342 bool encrypted_dst;
1343 /* Assuming the secondary slot is source; note that 0 here not only
1344 * means that primary slot is source, but also that there will be
1345 * encryption happening, if it is 1 then there is decryption from
1346 * secondary slot.
1347 */
1348 int source_slot = 1;
1349 /* In case of encryption enabled, we may have to do more work than
1350 * just copy bytes */
1351 bool only_copy = false;
1352 #else
1353 (void)state;
1354 #endif
1355
1356 TARGET_STATIC uint8_t buf[BUF_SZ] __attribute__((aligned(4)));
1357
1358 #ifdef MCUBOOT_ENC_IMAGES
1359 encrypted_src = (flash_area_get_id(fap_src) != FLASH_AREA_IMAGE_PRIMARY(image_index));
1360 encrypted_dst = (flash_area_get_id(fap_dst) != FLASH_AREA_IMAGE_PRIMARY(image_index));
1361
1362 if (encrypted_src != encrypted_dst) {
1363 if (encrypted_dst) {
1364 /* Need encryption, metadata from the primary slot */
1365 hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
1366 source_slot = 0;
1367 } else {
1368 /* Need decryption, metadata from the secondary slot */
1369 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
1370 source_slot = 1;
1371 }
1372 } else {
1373 /* In case when source and targe is the same area, this means that we
1374 * only have to copy bytes, no encryption or decryption.
1375 */
1376 only_copy = true;
1377 }
1378 #endif
1379
1380 bytes_copied = 0;
1381 while (bytes_copied < sz) {
1382 if (sz - bytes_copied > sizeof buf) {
1383 chunk_sz = sizeof buf;
1384 } else {
1385 chunk_sz = sz - bytes_copied;
1386 }
1387
1388 rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz);
1389 if (rc != 0) {
1390 return BOOT_EFLASH;
1391 }
1392
1393 #ifdef MCUBOOT_ENC_IMAGES
1394 /* If only copy, then does not matter if header indicates need for
1395 * encryption/decryption, we just copy data. */
1396 if (!only_copy && IS_ENCRYPTED(hdr)) {
1397 #if defined(MCUBOOT_SWAP_USING_OFFSET)
1398 uint32_t abs_off = off - sector_off + bytes_copied;
1399 #else
1400 uint32_t abs_off = off + bytes_copied;
1401 #endif
1402 if (abs_off < hdr->ih_hdr_size) {
1403 /* do not decrypt header */
1404 if (abs_off + chunk_sz > hdr->ih_hdr_size) {
1405 /* The lower part of the chunk contains header data */
1406 blk_off = 0;
1407 blk_sz = chunk_sz - (hdr->ih_hdr_size - abs_off);
1408 idx = hdr->ih_hdr_size - abs_off;
1409 } else {
1410 /* The chunk contains exclusively header data */
1411 blk_sz = 0; /* nothing to decrypt */
1412 }
1413 } else {
1414 idx = 0;
1415 blk_sz = chunk_sz;
1416 blk_off = (abs_off - hdr->ih_hdr_size) & 0xf;
1417 }
1418
1419 if (blk_sz > 0)
1420 {
1421 tlv_off = BOOT_TLV_OFF(hdr);
1422 if (abs_off + chunk_sz > tlv_off) {
1423 /* do not decrypt TLVs */
1424 if (abs_off >= tlv_off) {
1425 blk_sz = 0;
1426 } else {
1427 blk_sz = tlv_off - abs_off;
1428 }
1429 }
1430 if (source_slot == 0) {
1431 boot_enc_encrypt(BOOT_CURR_ENC(state), source_slot,
1432 (abs_off + idx) - hdr->ih_hdr_size, blk_sz,
1433 blk_off, &buf[idx]);
1434 } else {
1435 boot_enc_decrypt(BOOT_CURR_ENC(state), source_slot,
1436 (abs_off + idx) - hdr->ih_hdr_size, blk_sz,
1437 blk_off, &buf[idx]);
1438 }
1439 }
1440 }
1441 #endif
1442
1443 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
1444 if (rc != 0) {
1445 return BOOT_EFLASH;
1446 }
1447
1448 bytes_copied += chunk_sz;
1449
1450 MCUBOOT_WATCHDOG_FEED();
1451 }
1452
1453 return 0;
1454 }
1455
1456 /**
1457 * Overwrite primary slot with the image contained in the secondary slot.
1458 * If a prior copy operation was interrupted by a system reset, this function
1459 * redos the copy.
1460 *
1461 * @param bs The current boot status. This function reads
1462 * this struct to determine if it is resuming
1463 * an interrupted swap operation. This
1464 * function writes the updated status to this
1465 * function on return.
1466 *
1467 * @return 0 on success; nonzero on failure.
1468 */
1469 #if defined(MCUBOOT_OVERWRITE_ONLY) || defined(MCUBOOT_BOOTSTRAP)
1470 static int
1471 boot_copy_image(struct boot_loader_state *state, struct boot_status *bs)
1472 {
1473 size_t sect_count;
1474 size_t sect;
1475 int rc;
1476 size_t size;
1477 size_t this_size;
1478 size_t last_sector;
1479 const struct flash_area *fap_primary_slot;
1480 const struct flash_area *fap_secondary_slot;
1481 uint8_t image_index;
1482
1483 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1484 uint32_t sector;
1485 uint32_t trailer_sz;
1486 uint32_t off;
1487 uint32_t sz;
1488 #endif
1489
1490 (void)bs;
1491
1492 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1493 uint32_t src_size = 0;
1494 rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &src_size);
1495 assert(rc == 0);
1496 #endif
1497
1498 image_index = BOOT_CURR_IMG(state);
1499
1500 BOOT_LOG_INF("Image %d upgrade secondary slot -> primary slot", image_index);
1501 BOOT_LOG_INF("Erasing the primary slot");
1502
1503 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index),
1504 &fap_primary_slot);
1505 assert (rc == 0);
1506
1507 rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index),
1508 &fap_secondary_slot);
1509 assert (rc == 0);
1510
1511 sect_count = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT);
1512 for (sect = 0, size = 0; sect < sect_count; sect++) {
1513 this_size = boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sect);
1514 rc = boot_erase_region(fap_primary_slot, size, this_size);
1515 assert(rc == 0);
1516
1517 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1518 if ((size + this_size) >= src_size) {
1519 size += src_size - size;
1520 size += BOOT_WRITE_SZ(state) - (size % BOOT_WRITE_SZ(state));
1521 break;
1522 }
1523 #endif
1524
1525 size += this_size;
1526 }
1527
1528 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1529 trailer_sz = boot_trailer_sz(BOOT_WRITE_SZ(state));
1530 sector = boot_img_num_sectors(state, BOOT_PRIMARY_SLOT) - 1;
1531 sz = 0;
1532 do {
1533 sz += boot_img_sector_size(state, BOOT_PRIMARY_SLOT, sector);
1534 off = boot_img_sector_off(state, BOOT_PRIMARY_SLOT, sector);
1535 sector--;
1536 } while (sz < trailer_sz);
1537
1538 rc = boot_erase_region(fap_primary_slot, off, sz);
1539 assert(rc == 0);
1540 #endif
1541
1542 #ifdef MCUBOOT_ENC_IMAGES
1543 if (IS_ENCRYPTED(boot_img_hdr(state, BOOT_SECONDARY_SLOT))) {
1544 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
1545 rc = boot_enc_load(state, BOOT_SECONDARY_SLOT,
1546 boot_img_hdr(state, BOOT_SECONDARY_SLOT),
1547 fap_secondary_slot, bs, 0);
1548 #else
1549 rc = boot_enc_load(state, BOOT_SECONDARY_SLOT,
1550 boot_img_hdr(state, BOOT_SECONDARY_SLOT),
1551 fap_secondary_slot, bs);
1552 #endif
1553
1554 if (rc < 0) {
1555 return BOOT_EBADIMAGE;
1556 }
1557 if (rc == 0 && boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs)) {
1558 return BOOT_EBADIMAGE;
1559 }
1560 }
1561 #endif
1562
1563 BOOT_LOG_INF("Image %d copying the secondary slot to the primary slot: 0x%zx bytes",
1564 image_index, size);
1565 #if defined(MCUBOOT_SWAP_USING_OFFSET)
1566 rc = BOOT_COPY_REGION(state, fap_secondary_slot, fap_primary_slot,
1567 boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0), 0, size, 0);
1568 #else
1569 rc = boot_copy_region(state, fap_secondary_slot, fap_primary_slot, 0, 0, size);
1570 #endif
1571 if (rc != 0) {
1572 return rc;
1573 }
1574
1575 #if defined(MCUBOOT_OVERWRITE_ONLY_FAST)
1576 rc = boot_write_magic(fap_primary_slot);
1577 if (rc != 0) {
1578 return rc;
1579 }
1580 #endif
1581
1582 rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state),
1583 BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size);
1584 if (rc != 0) {
1585 return rc;
1586 }
1587
1588 #ifdef MCUBOOT_HW_ROLLBACK_PROT
1589 /* Update the stored security counter with the new image's security counter
1590 * value. Both slots hold the new image at this point, but the secondary
1591 * slot's image header must be passed since the image headers in the
1592 * boot_data structure have not been updated yet.
1593 */
1594 rc = boot_update_security_counter(state, BOOT_PRIMARY_SLOT, BOOT_SECONDARY_SLOT);
1595 if (rc != 0) {
1596 BOOT_LOG_ERR("Security counter update failed after image upgrade.");
1597 return rc;
1598 }
1599 #endif /* MCUBOOT_HW_ROLLBACK_PROT */
1600
1601 #ifndef MCUBOOT_OVERWRITE_ONLY_KEEP_BACKUP
1602 /*
1603 * Erases header and trailer. The trailer is erased because when a new
1604 * image is written without a trailer as is the case when using newt, the
1605 * trailer that was left might trigger a new upgrade.
1606 */
1607 BOOT_LOG_DBG("erasing secondary header");
1608 rc = boot_erase_region(fap_secondary_slot,
1609 boot_img_sector_off(state, BOOT_SECONDARY_SLOT, 0),
1610 boot_img_sector_size(state, BOOT_SECONDARY_SLOT, 0));
1611 assert(rc == 0);
1612 #endif
1613
1614 last_sector = boot_img_num_sectors(state, BOOT_SECONDARY_SLOT) - 1;
1615 BOOT_LOG_DBG("erasing secondary trailer");
1616 rc = boot_erase_region(fap_secondary_slot,
1617 boot_img_sector_off(state, BOOT_SECONDARY_SLOT,
1618 last_sector),
1619 boot_img_sector_size(state, BOOT_SECONDARY_SLOT,
1620 last_sector));
1621 assert(rc == 0);
1622
1623 flash_area_close(fap_primary_slot);
1624 flash_area_close(fap_secondary_slot);
1625
1626 /* TODO: Perhaps verify the primary slot's signature again? */
1627
1628 return 0;
1629 }
1630 #endif
1631
1632 #if !defined(MCUBOOT_OVERWRITE_ONLY)
1633 /**
1634 * Swaps the two images in flash. If a prior copy operation was interrupted
1635 * by a system reset, this function completes that operation.
1636 *
1637 * @param bs The current boot status. This function reads
1638 * this struct to determine if it is resuming
1639 * an interrupted swap operation. This
1640 * function writes the updated status to this
1641 * function on return.
1642 *
1643 * @return 0 on success; nonzero on failure.
1644 */
1645 static int
1646 boot_swap_image(struct boot_loader_state *state, struct boot_status *bs)
1647 {
1648 struct image_header *hdr;
1649 const struct flash_area *fap;
1650 #ifdef MCUBOOT_ENC_IMAGES
1651 uint8_t slot;
1652 uint8_t i;
1653 #endif
1654 uint32_t size;
1655 uint32_t copy_size;
1656 uint8_t image_index;
1657 int rc;
1658
1659 /* FIXME: just do this if asked by user? */
1660
1661 size = copy_size = 0;
1662 image_index = BOOT_CURR_IMG(state);
1663
1664 if (boot_status_is_reset(bs)) {
1665 /*
1666 * No swap ever happened, so need to find the largest image which
1667 * will be used to determine the amount of sectors to swap.
1668 */
1669 hdr = boot_img_hdr(state, BOOT_PRIMARY_SLOT);
1670 if (hdr->ih_magic == IMAGE_MAGIC) {
1671 rc = boot_read_image_size(state, BOOT_PRIMARY_SLOT, ©_size);
1672 assert(rc == 0);
1673 }
1674
1675 #ifdef MCUBOOT_ENC_IMAGES
1676 if (IS_ENCRYPTED(hdr)) {
1677 fap = BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT);
1678 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
1679 rc = boot_enc_load(state, 0, hdr, fap, bs, 0);
1680 #else
1681 rc = boot_enc_load(state, 0, hdr, fap, bs);
1682 #endif
1683 assert(rc >= 0);
1684
1685 if (rc == 0) {
1686 rc = boot_enc_set_key(BOOT_CURR_ENC(state), 0, bs);
1687 assert(rc == 0);
1688 } else {
1689 rc = 0;
1690 }
1691 } else {
1692 memset(bs->enckey[0], 0xff, BOOT_ENC_KEY_ALIGN_SIZE);
1693 }
1694 #endif
1695
1696 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
1697 if (hdr->ih_magic == IMAGE_MAGIC) {
1698 rc = boot_read_image_size(state, BOOT_SECONDARY_SLOT, &size);
1699 assert(rc == 0);
1700 }
1701
1702 #ifdef MCUBOOT_ENC_IMAGES
1703 hdr = boot_img_hdr(state, BOOT_SECONDARY_SLOT);
1704 if (IS_ENCRYPTED(hdr)) {
1705 fap = BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT);
1706 #if defined(MCUBOOT_SWAP_USING_OFFSET) && defined(MCUBOOT_SERIAL_RECOVERY)
1707 rc = boot_enc_load(state, 1, hdr, fap, bs, 0);
1708 #else
1709 rc = boot_enc_load(state, 1, hdr, fap, bs);
1710 #endif
1711 assert(rc >= 0);
1712
1713 if (rc == 0) {
1714 rc = boot_enc_set_key(BOOT_CURR_ENC(state), 1, bs);
1715 assert(rc == 0);
1716 } else {
1717 rc = 0;
1718 }
1719 } else {
1720 memset(bs->enckey[1], 0xff, BOOT_ENC_KEY_ALIGN_SIZE);
1721 }
1722 #endif
1723
1724 if (size > copy_size) {
1725 copy_size = size;
1726 }
1727
1728 bs->swap_size = copy_size;
1729 } else {
1730 /*
1731 * If a swap was under way, the swap_size should already be present
1732 * in the trailer...
1733 */
1734
1735 rc = boot_find_status(image_index, &fap);
1736 assert(fap != NULL);
1737 rc = boot_read_swap_size(fap, &bs->swap_size);
1738 assert(rc == 0);
1739
1740 copy_size = bs->swap_size;
1741
1742 #ifdef MCUBOOT_ENC_IMAGES
1743 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1744 rc = boot_read_enc_key(fap, slot, bs);
1745 assert(rc == 0);
1746
1747 for (i = 0; i < BOOT_ENC_KEY_SIZE; i++) {
1748 if (bs->enckey[slot][i] != 0xff) {
1749 break;
1750 }
1751 }
1752
1753 boot_enc_init(BOOT_CURR_ENC(state), slot);
1754
1755 if (i != BOOT_ENC_KEY_SIZE) {
1756 boot_enc_set_key(BOOT_CURR_ENC(state), slot, bs);
1757 }
1758 }
1759 #endif
1760 flash_area_close(fap);
1761 }
1762
1763 swap_run(state, bs, copy_size);
1764
1765 #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
1766 extern int boot_status_fails;
1767 if (boot_status_fails > 0) {
1768 BOOT_LOG_WRN("%d status write fails performing the swap",
1769 boot_status_fails);
1770 }
1771 #endif
1772 rc = BOOT_HOOK_CALL(boot_copy_region_post_hook, 0, BOOT_CURR_IMG(state),
1773 BOOT_IMG_AREA(state, BOOT_PRIMARY_SLOT), size);
1774
1775 return 0;
1776 }
1777 #endif
1778
1779
1780 /**
1781 * Performs a clean (not aborted) image update.
1782 *
1783 * @param bs The current boot status.
1784 *
1785 * @return 0 on success; nonzero on failure.
1786 */
1787 static int
1788 boot_perform_update(struct boot_loader_state *state, struct boot_status *bs)
1789 {
1790 int rc;
1791 #ifndef MCUBOOT_OVERWRITE_ONLY
1792 uint8_t swap_type;
1793 #endif
1794
1795 /* At this point there are no aborted swaps. */
1796 #if defined(MCUBOOT_OVERWRITE_ONLY)
1797 rc = boot_copy_image(state, bs);
1798 #elif defined(MCUBOOT_BOOTSTRAP)
1799 /* Check if the image update was triggered by a bad image in the
1800 * primary slot (the validity of the image in the secondary slot had
1801 * already been checked).
1802 */
1803 FIH_DECLARE(fih_rc, FIH_FAILURE);
1804 rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT);
1805 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, bs, 0);
1806 if (rc == 0 || FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
1807 rc = boot_copy_image(state, bs);
1808 } else {
1809 rc = boot_swap_image(state, bs);
1810 }
1811 #else
1812 rc = boot_swap_image(state, bs);
1813 #endif
1814 assert(rc == 0);
1815
1816 #ifndef MCUBOOT_OVERWRITE_ONLY
1817 /* The following state needs image_ok be explicitly set after the
1818 * swap was finished to avoid a new revert.
1819 */
1820 swap_type = BOOT_SWAP_TYPE(state);
1821 if (swap_type == BOOT_SWAP_TYPE_REVERT ||
1822 swap_type == BOOT_SWAP_TYPE_PERM) {
1823 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
1824 if (rc != 0) {
1825 BOOT_SWAP_TYPE(state) = swap_type = BOOT_SWAP_TYPE_PANIC;
1826 }
1827 }
1828
1829 #ifdef MCUBOOT_HW_ROLLBACK_PROT
1830 if (swap_type == BOOT_SWAP_TYPE_PERM) {
1831 /* Update the stored security counter with the new image's security
1832 * counter value. The primary slot holds the new image at this point,
1833 * but the secondary slot's image header must be passed since image
1834 * headers in the boot_data structure have not been updated yet.
1835 *
1836 * In case of a permanent image swap mcuboot will never attempt to
1837 * revert the images on the next reboot. Therefore, the security
1838 * counter must be increased right after the image upgrade.
1839 */
1840 rc = boot_update_security_counter(state, BOOT_PRIMARY_SLOT, BOOT_SECONDARY_SLOT);
1841 if (rc != 0) {
1842 BOOT_LOG_ERR("Security counter update failed after "
1843 "image upgrade.");
1844 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1845 }
1846 }
1847 #endif /* MCUBOOT_HW_ROLLBACK_PROT */
1848
1849 if (BOOT_IS_UPGRADE(swap_type)) {
1850 rc = swap_set_copy_done(BOOT_CURR_IMG(state));
1851 if (rc != 0) {
1852 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1853 }
1854 }
1855 #endif /* !MCUBOOT_OVERWRITE_ONLY */
1856
1857 return rc;
1858 }
1859
1860 /**
1861 * Completes a previously aborted image swap.
1862 *
1863 * @param bs The current boot status.
1864 *
1865 * @return 0 on success; nonzero on failure.
1866 */
1867 #if !defined(MCUBOOT_OVERWRITE_ONLY)
1868 static int
1869 boot_complete_partial_swap(struct boot_loader_state *state,
1870 struct boot_status *bs)
1871 {
1872 int rc;
1873
1874 /* Determine the type of swap operation being resumed from the
1875 * `swap-type` trailer field.
1876 */
1877 rc = boot_swap_image(state, bs);
1878 assert(rc == 0);
1879
1880 BOOT_SWAP_TYPE(state) = bs->swap_type;
1881
1882 /* The following states need image_ok be explicitly set after the
1883 * swap was finished to avoid a new revert.
1884 */
1885 if (bs->swap_type == BOOT_SWAP_TYPE_REVERT ||
1886 bs->swap_type == BOOT_SWAP_TYPE_PERM) {
1887 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
1888 if (rc != 0) {
1889 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1890 }
1891 }
1892
1893 if (BOOT_IS_UPGRADE(bs->swap_type)) {
1894 rc = swap_set_copy_done(BOOT_CURR_IMG(state));
1895 if (rc != 0) {
1896 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
1897 }
1898 }
1899
1900 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
1901 BOOT_LOG_ERR("panic!");
1902 assert(0);
1903
1904 /* Loop forever... */
1905 while (1) {}
1906 }
1907
1908 return rc;
1909 }
1910 #endif /* !MCUBOOT_OVERWRITE_ONLY */
1911
1912 #if (BOOT_IMAGE_NUMBER > 1)
1913 /**
1914 * Review the validity of previously determined swap types of other images.
1915 *
1916 * @param aborted_swap The current image upgrade is a
1917 * partial/aborted swap.
1918 */
1919 static void
1920 boot_review_image_swap_types(struct boot_loader_state *state,
1921 bool aborted_swap)
1922 {
1923 /* In that case if we rebooted in the middle of an image upgrade process, we
1924 * must review the validity of swap types, that were previously determined
1925 * for other images. The image_ok flag had not been set before the reboot
1926 * for any of the updated images (only the copy_done flag) and thus falsely
1927 * the REVERT swap type has been determined for the previous images that had
1928 * been updated before the reboot.
1929 *
1930 * There are two separate scenarios that we have to deal with:
1931 *
1932 * 1. The reboot has happened during swapping an image:
1933 * The current image upgrade has been determined as a
1934 * partial/aborted swap.
1935 * 2. The reboot has happened between two separate image upgrades:
1936 * In this scenario we must check the swap type of the current image.
1937 * In those cases if it is NONE or REVERT we cannot certainly determine
1938 * the fact of a reboot. In a consistent state images must move in the
1939 * same direction or stay in place, e.g. in practice REVERT and TEST
1940 * swap types cannot be present at the same time. If the swap type of
1941 * the current image is either TEST, PERM or FAIL we must review the
1942 * already determined swap types of other images and set each false
1943 * REVERT swap types to NONE (these images had been successfully
1944 * updated before the system rebooted between two separate image
1945 * upgrades).
1946 */
1947
1948 if (BOOT_CURR_IMG(state) == 0) {
1949 /* Nothing to do */
1950 return;
1951 }
1952
1953 if (!aborted_swap) {
1954 if ((BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) ||
1955 (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_REVERT)) {
1956 /* Nothing to do */
1957 return;
1958 }
1959 }
1960
1961 for (uint8_t i = 0; i < BOOT_CURR_IMG(state); i++) {
1962 if (state->swap_type[i] == BOOT_SWAP_TYPE_REVERT) {
1963 state->swap_type[i] = BOOT_SWAP_TYPE_NONE;
1964 }
1965 }
1966 }
1967 #endif
1968
1969 /**
1970 * Prepare image to be updated if required.
1971 *
1972 * Prepare image to be updated if required with completing an image swap
1973 * operation if one was aborted and/or determining the type of the
1974 * swap operation. In case of any error set the swap type to NONE.
1975 *
1976 * @param state TODO
1977 * @param bs Pointer where the read and possibly updated
1978 * boot status can be written to.
1979 */
1980 static void
1981 boot_prepare_image_for_update(struct boot_loader_state *state,
1982 struct boot_status *bs)
1983 {
1984 int rc;
1985 FIH_DECLARE(fih_rc, FIH_FAILURE);
1986
1987 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
1988 int max_size;
1989 #endif
1990
1991 /* Determine the sector layout of the image slots and scratch area. */
1992 rc = boot_read_sectors(state);
1993 if (rc != 0) {
1994 BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d"
1995 " - too small?", BOOT_MAX_IMG_SECTORS);
1996 /* Unable to determine sector layout, continue with next image
1997 * if there is one.
1998 */
1999 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2000 if (rc == BOOT_EFLASH)
2001 {
2002 /* Only return on error from the primary image flash */
2003 return;
2004 }
2005 }
2006
2007 /* Attempt to read an image header from each slot. */
2008 rc = boot_read_image_headers(state, false, NULL);
2009 if (rc != 0) {
2010 /* Continue with next image if there is one. */
2011 BOOT_LOG_WRN("Failed reading image headers; Image=%u",
2012 BOOT_CURR_IMG(state));
2013 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2014 return;
2015 }
2016
2017 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
2018 /* Fetch information on maximum sizes for later usage, if needed */
2019 max_size = app_max_size(state);
2020
2021 if (max_size > 0) {
2022 image_max_sizes[BOOT_CURR_IMG(state)].calculated = true;
2023 image_max_sizes[BOOT_CURR_IMG(state)].max_size = max_size;
2024 }
2025 #endif
2026
2027 /* If the current image's slots aren't compatible, no swap is possible.
2028 * Just boot into primary slot.
2029 */
2030 if (boot_slots_compatible(state)) {
2031 boot_status_reset(bs);
2032
2033 #ifndef MCUBOOT_OVERWRITE_ONLY
2034 rc = swap_read_status(state, bs);
2035 if (rc != 0) {
2036 BOOT_LOG_WRN("Failed reading boot status; Image=%u",
2037 BOOT_CURR_IMG(state));
2038 /* Continue with next image if there is one. */
2039 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2040 return;
2041 }
2042 #endif
2043
2044 #if defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_OFFSET)
2045 /*
2046 * Must re-read image headers because the boot status might
2047 * have been updated in the previous function call.
2048 */
2049 rc = boot_read_image_headers(state, !boot_status_is_reset(bs), bs);
2050 #ifdef MCUBOOT_BOOTSTRAP
2051 /* When bootstrapping it's OK to not have image magic in the primary slot */
2052 if (rc != 0 && boot_check_header_erased(state, BOOT_PRIMARY_SLOT) != 0) {
2053 #else
2054 if (rc != 0) {
2055 #endif
2056
2057 /* Continue with next image if there is one. */
2058 BOOT_LOG_WRN("Failed reading image headers; Image=%u",
2059 BOOT_CURR_IMG(state));
2060 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2061 return;
2062 }
2063 #endif
2064
2065 /* Determine if we rebooted in the middle of an image swap
2066 * operation. If a partial swap was detected, complete it.
2067 */
2068 if (!boot_status_is_reset(bs)) {
2069
2070 #if (BOOT_IMAGE_NUMBER > 1)
2071 boot_review_image_swap_types(state, true);
2072 #endif
2073
2074 #ifdef MCUBOOT_OVERWRITE_ONLY
2075 /* Should never arrive here, overwrite-only mode has
2076 * no swap state.
2077 */
2078 assert(0);
2079 #else
2080 /* Determine the type of swap operation being resumed from the
2081 * `swap-type` trailer field.
2082 */
2083 rc = boot_complete_partial_swap(state, bs);
2084 assert(rc == 0);
2085 #endif
2086 /* Attempt to read an image header from each slot. Ensure that image headers in slots
2087 * are aligned with headers in boot_data.
2088 *
2089 * The boot status (last param) is used to figure out in which slot the header of each
2090 * image is currently located. This is useful as in the middle of an upgrade process,
2091 * the header of a given image could have already been moved to the other slot. However,
2092 * providing it at the end of the upgrade, as it is the case here, would cause the
2093 * reading of the header of the primary image from the secondary slot and the secondary
2094 * image from the primary slot, since the images have been swapped. That's not what we
2095 * want here, since the goal is to upgrade the bootloader state to reflect the new state
2096 * of the slots: the image headers in the primary and secondary slots must now
2097 * respectively be the headers of the new and previous active image. So NULL is provided
2098 * as boot status.
2099 */
2100 rc = boot_read_image_headers(state, false, NULL);
2101 assert(rc == 0);
2102
2103 /* Swap has finished set to NONE */
2104 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2105 } else {
2106 /* There was no partial swap, determine swap type. */
2107 if (bs->swap_type == BOOT_SWAP_TYPE_NONE) {
2108 BOOT_SWAP_TYPE(state) = boot_validated_swap_type(state, bs);
2109 } else {
2110 FIH_CALL(boot_validate_slot, fih_rc,
2111 state, BOOT_SECONDARY_SLOT, bs, 0);
2112 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
2113 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_FAIL;
2114 } else {
2115 BOOT_SWAP_TYPE(state) = bs->swap_type;
2116 }
2117 }
2118
2119 #if (BOOT_IMAGE_NUMBER > 1)
2120 boot_review_image_swap_types(state, false);
2121 #endif
2122
2123 #ifdef MCUBOOT_BOOTSTRAP
2124 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
2125 /* Header checks are done first because they are
2126 * inexpensive. Since overwrite-only copies starting from
2127 * offset 0, if interrupted, it might leave a valid header
2128 * magic, so also run validation on the primary slot to be
2129 * sure it's not OK.
2130 */
2131 rc = boot_check_header_erased(state, BOOT_PRIMARY_SLOT);
2132 FIH_CALL(boot_validate_slot, fih_rc,
2133 state, BOOT_PRIMARY_SLOT, bs, 0);
2134
2135 if (rc == 0 || FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
2136
2137 rc = (boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_magic == IMAGE_MAGIC) ? 1: 0;
2138 FIH_CALL(boot_validate_slot, fih_rc,
2139 state, BOOT_SECONDARY_SLOT, bs, 0);
2140
2141 if (rc == 1 && FIH_EQ(fih_rc, FIH_SUCCESS)) {
2142 /* Set swap type to REVERT to overwrite the primary
2143 * slot with the image contained in secondary slot
2144 * and to trigger the explicit setting of the
2145 * image_ok flag.
2146 */
2147 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_REVERT;
2148 }
2149 }
2150 }
2151 #endif
2152 }
2153 } else {
2154 /* In that case if slots are not compatible. */
2155 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2156 }
2157 }
2158
2159 /**
2160 * Updates the security counter for the current image.
2161 *
2162 * @param state Boot loader status information.
2163 *
2164 * @return 0 on success; nonzero on failure.
2165 */
2166 static int
2167 boot_update_hw_rollback_protection(struct boot_loader_state *state)
2168 {
2169 #ifdef MCUBOOT_HW_ROLLBACK_PROT
2170 int rc;
2171
2172 /* Update the stored security counter with the active image's security
2173 * counter value. It will only be updated if the new security counter is
2174 * greater than the stored value.
2175 *
2176 * In case of a successful image swapping when the swap type is TEST the
2177 * security counter can be increased only after a reset, when the swap
2178 * type is NONE and the image has marked itself "OK" (the image_ok flag
2179 * has been set). This way a "revert" can be performed when it's
2180 * necessary.
2181 */
2182 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_NONE) {
2183 rc = boot_update_security_counter(state, BOOT_PRIMARY_SLOT, BOOT_PRIMARY_SLOT);
2184 if (rc != 0) {
2185 BOOT_LOG_ERR("Security counter update failed after image "
2186 "validation.");
2187 return rc;
2188 }
2189 }
2190
2191 return 0;
2192
2193 #else /* MCUBOOT_HW_ROLLBACK_PROT */
2194 (void) (state);
2195
2196 return 0;
2197 #endif
2198 }
2199
2200 /**
2201 * Checks test swap downgrade prevention conditions.
2202 *
2203 * Function called only for swap upgrades test run. It may prevent
2204 * swap if slot 1 image has <= version number or < security counter
2205 *
2206 * @param state Boot loader status information.
2207 *
2208 * @return 0 - image can be swapped, -1 downgrade prevention
2209 */
2210 static int
2211 check_downgrade_prevention(struct boot_loader_state *state)
2212 {
2213 #if defined(MCUBOOT_DOWNGRADE_PREVENTION) && \
2214 (defined(MCUBOOT_SWAP_USING_MOVE) || defined(MCUBOOT_SWAP_USING_SCRATCH) || defined(MCUBOOT_SWAP_USING_OFFSET))
2215 uint32_t security_counter[2];
2216 int rc;
2217
2218 if (MCUBOOT_DOWNGRADE_PREVENTION_SECURITY_COUNTER) {
2219 /* If there was security no counter in slot 0, allow swap */
2220 rc = bootutil_get_img_security_cnt(state, BOOT_PRIMARY_SLOT,
2221 BOOT_IMG_AREA(state, 0),
2222 &security_counter[0]);
2223 if (rc != 0) {
2224 return 0;
2225 }
2226 /* If there is no security counter in slot 1, or it's lower than
2227 * that of slot 0, prevent downgrade */
2228 rc = bootutil_get_img_security_cnt(state, BOOT_SECONDARY_SLOT,
2229 BOOT_IMG_AREA(state, 1),
2230 &security_counter[1]);
2231 if (rc != 0 || security_counter[0] > security_counter[1]) {
2232 rc = -1;
2233 }
2234 }
2235 else {
2236 rc = boot_version_cmp(&boot_img_hdr(state, BOOT_SECONDARY_SLOT)->ih_ver,
2237 &boot_img_hdr(state, BOOT_PRIMARY_SLOT)->ih_ver);
2238 }
2239 if (rc < 0) {
2240 /* Image in slot 0 prevents downgrade, delete image in slot 1 */
2241 BOOT_LOG_INF("Image %d in slot 1 erased due to downgrade prevention", BOOT_CURR_IMG(state));
2242 flash_area_erase(BOOT_IMG_AREA(state, 1), 0,
2243 flash_area_get_size(BOOT_IMG_AREA(state, 1)));
2244 } else {
2245 rc = 0;
2246 }
2247 return rc;
2248 #else
2249 (void)state;
2250 return 0;
2251 #endif
2252 }
2253
2254 fih_ret
2255 context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
2256 {
2257 size_t slot;
2258 struct boot_status bs;
2259 int rc = -1;
2260 FIH_DECLARE(fih_rc, FIH_FAILURE);
2261 int fa_id;
2262 int image_index;
2263 bool has_upgrade;
2264 volatile int fih_cnt;
2265
2266 #if defined(__BOOTSIM__)
2267 /* The array of slot sectors are defined here (as opposed to file scope) so
2268 * that they don't get allocated for non-boot-loader apps. This is
2269 * necessary because the gcc option "-fdata-sections" doesn't seem to have
2270 * any effect in older gcc versions (e.g., 4.8.4).
2271 */
2272 TARGET_STATIC boot_sector_t primary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
2273 TARGET_STATIC boot_sector_t secondary_slot_sectors[BOOT_IMAGE_NUMBER][BOOT_MAX_IMG_SECTORS];
2274 #if MCUBOOT_SWAP_USING_SCRATCH
2275 TARGET_STATIC boot_sector_t scratch_sectors[BOOT_MAX_IMG_SECTORS];
2276 #endif
2277 #endif
2278
2279 has_upgrade = false;
2280
2281 #if (BOOT_IMAGE_NUMBER == 1)
2282 (void)has_upgrade;
2283 #endif
2284
2285 /* Iterate over all the images. By the end of the loop the swap type has
2286 * to be determined for each image and all aborted swaps have to be
2287 * completed.
2288 */
2289 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2290 #if BOOT_IMAGE_NUMBER > 1
2291 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2292 continue;
2293 }
2294 #endif
2295 #if defined(MCUBOOT_ENC_IMAGES) && (BOOT_IMAGE_NUMBER > 1)
2296 /* The keys used for encryption may no longer be valid (could belong to
2297 * another images). Therefore, mark them as invalid to force their reload
2298 * by boot_enc_load().
2299 */
2300 boot_enc_zeroize(BOOT_CURR_ENC(state));
2301 #endif
2302
2303 image_index = BOOT_CURR_IMG(state);
2304
2305 #if !defined(__BOOTSIM__)
2306 BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
2307 sector_buffers.primary[image_index];
2308 BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
2309 sector_buffers.secondary[image_index];
2310 #if MCUBOOT_SWAP_USING_SCRATCH
2311 state->scratch.sectors = sector_buffers.scratch;
2312 #endif
2313 #else
2314 BOOT_IMG(state, BOOT_PRIMARY_SLOT).sectors =
2315 primary_slot_sectors[image_index];
2316 BOOT_IMG(state, BOOT_SECONDARY_SLOT).sectors =
2317 secondary_slot_sectors[image_index];
2318 #if MCUBOOT_SWAP_USING_SCRATCH
2319 state->scratch.sectors = scratch_sectors;
2320 #endif
2321 #endif
2322
2323 /* Open primary and secondary image areas for the duration
2324 * of this call.
2325 */
2326 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2327 fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
2328 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
2329 assert(rc == 0);
2330
2331 if (rc != 0) {
2332 BOOT_LOG_ERR("Failed to open flash area ID %d (image %d slot %d): %d, "
2333 "cannot continue", fa_id, image_index, (int8_t)slot, rc);
2334 FIH_PANIC;
2335 }
2336 }
2337 #if MCUBOOT_SWAP_USING_SCRATCH
2338 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
2339 &BOOT_SCRATCH_AREA(state));
2340 assert(rc == 0);
2341
2342 if (rc != 0) {
2343 BOOT_LOG_ERR("Failed to open scratch flash area: %d, cannot continue", rc);
2344 FIH_PANIC;
2345 }
2346 #endif
2347
2348 /* Determine swap type and complete swap if it has been aborted. */
2349 boot_prepare_image_for_update(state, &bs);
2350
2351 if (BOOT_IS_UPGRADE(BOOT_SWAP_TYPE(state))) {
2352 has_upgrade = true;
2353 }
2354 }
2355
2356 #if (BOOT_IMAGE_NUMBER > 1)
2357 if (has_upgrade) {
2358 /* Iterate over all the images and verify whether the image dependencies
2359 * are all satisfied and update swap type if necessary.
2360 */
2361 rc = boot_verify_dependencies(state);
2362 if (rc != 0) {
2363 /*
2364 * It was impossible to upgrade because the expected dependency version
2365 * was not available. Here we already changed the swap_type so that
2366 * instead of asserting the bootloader, we continue and no upgrade is
2367 * performed.
2368 */
2369 rc = 0;
2370 }
2371 }
2372 #endif
2373
2374 /* Trigger status change callback with upgrading status */
2375 if (has_upgrade) {
2376 mcuboot_status_change(MCUBOOT_STATUS_UPGRADING);
2377 }
2378
2379 /* Iterate over all the images. At this point there are no aborted swaps
2380 * and the swap types are determined for each image. By the end of the loop
2381 * all required update operations will have been finished.
2382 */
2383 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2384 #if (BOOT_IMAGE_NUMBER > 1)
2385 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2386 continue;
2387 }
2388
2389 #ifdef MCUBOOT_ENC_IMAGES
2390 /* The keys used for encryption may no longer be valid (could belong to
2391 * another images). Therefore, mark them as invalid to force their reload
2392 * by boot_enc_load().
2393 */
2394 boot_enc_zeroize(BOOT_CURR_ENC(state));
2395 #endif /* MCUBOOT_ENC_IMAGES */
2396
2397 /* Indicate that swap is not aborted */
2398 boot_status_reset(&bs);
2399 #endif /* (BOOT_IMAGE_NUMBER > 1) */
2400
2401 /* Set the previously determined swap type */
2402 bs.swap_type = BOOT_SWAP_TYPE(state);
2403
2404 switch (BOOT_SWAP_TYPE(state)) {
2405 case BOOT_SWAP_TYPE_NONE:
2406 break;
2407
2408 case BOOT_SWAP_TYPE_TEST:
2409 /* fallthrough */
2410 case BOOT_SWAP_TYPE_PERM:
2411 if (check_downgrade_prevention(state) != 0) {
2412 /* Downgrade prevented */
2413 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_NONE;
2414 break;
2415 }
2416 /* fallthrough */
2417 case BOOT_SWAP_TYPE_REVERT:
2418 rc = BOOT_HOOK_CALL(boot_perform_update_hook, BOOT_HOOK_REGULAR,
2419 BOOT_CURR_IMG(state), &(BOOT_IMG(state, 1).hdr),
2420 BOOT_IMG_AREA(state, BOOT_SECONDARY_SLOT));
2421 if (rc == BOOT_HOOK_REGULAR)
2422 {
2423 rc = boot_perform_update(state, &bs);
2424 }
2425 assert(rc == 0);
2426 break;
2427
2428 case BOOT_SWAP_TYPE_FAIL:
2429 /* The image in secondary slot was invalid and is now erased. Ensure
2430 * we don't try to boot into it again on the next reboot. Do this by
2431 * pretending we just reverted back to primary slot.
2432 */
2433 #ifndef MCUBOOT_OVERWRITE_ONLY
2434 /* image_ok needs to be explicitly set to avoid a new revert. */
2435 rc = swap_set_image_ok(BOOT_CURR_IMG(state));
2436 if (rc != 0) {
2437 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
2438 }
2439 #endif /* !MCUBOOT_OVERWRITE_ONLY */
2440 break;
2441
2442 default:
2443 BOOT_SWAP_TYPE(state) = BOOT_SWAP_TYPE_PANIC;
2444 }
2445
2446 if (BOOT_SWAP_TYPE(state) == BOOT_SWAP_TYPE_PANIC) {
2447 BOOT_LOG_ERR("panic!");
2448 assert(0);
2449
2450 /* Loop forever... */
2451 FIH_PANIC;
2452 }
2453 }
2454
2455 /* Iterate over all the images. At this point all required update operations
2456 * have finished. By the end of the loop each image in the primary slot will
2457 * have been re-validated.
2458 */
2459 FIH_SET(fih_cnt, 0);
2460 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2461 #if BOOT_IMAGE_NUMBER > 1
2462 /* Hardenned to prevent from skipping check of a given image,
2463 * tmp_img_mask is declared volatile
2464 */
2465 volatile bool tmp_img_mask;
2466 FIH_SET(tmp_img_mask, state->img_mask[BOOT_CURR_IMG(state)]);
2467 if (FIH_EQ(tmp_img_mask, true)) {
2468 ++fih_cnt;
2469 continue;
2470 }
2471 #endif
2472 if (BOOT_SWAP_TYPE(state) != BOOT_SWAP_TYPE_NONE) {
2473 /* Attempt to read an image header from each slot. Ensure that image
2474 * headers in slots are aligned with headers in boot_data.
2475 * Note: Quite complicated internal logic of boot_read_image_headers
2476 * uses boot state, the last parm, to figure out in which slot which
2477 * header is located; when boot state is not provided, then it
2478 * is assumed that headers are at proper slots (we are not in
2479 * the middle of moving images, etc).
2480 */
2481 rc = boot_read_image_headers(state, false, NULL);
2482 if (rc != 0) {
2483 FIH_SET(fih_rc, FIH_FAILURE);
2484 goto out;
2485 }
2486 /* Since headers were reloaded, it can be assumed we just performed
2487 * a swap or overwrite. Now the header info that should be used to
2488 * provide the data for the bootstrap, which previously was at
2489 * secondary slot, was updated to primary slot.
2490 */
2491 }
2492
2493 #ifdef MCUBOOT_VALIDATE_PRIMARY_SLOT
2494 FIH_CALL(boot_validate_slot, fih_rc, state, BOOT_PRIMARY_SLOT, NULL, 0);
2495 /* Check for all possible values is redundant in normal operation it
2496 * is meant to prevent FI attack.
2497 */
2498 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS) ||
2499 FIH_EQ(fih_rc, FIH_FAILURE) ||
2500 FIH_EQ(fih_rc, FIH_NO_BOOTABLE_IMAGE)) {
2501 FIH_SET(fih_rc, FIH_FAILURE);
2502 goto out;
2503 }
2504 #else
2505 /* Even if we're not re-validating the primary slot, we could be booting
2506 * onto an empty flash chip. At least do a basic sanity check that
2507 * the magic number on the image is OK.
2508 */
2509 if (BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic != IMAGE_MAGIC) {
2510 BOOT_LOG_ERR("bad image magic 0x%lx; Image=%u", (unsigned long)
2511 BOOT_IMG(state, BOOT_PRIMARY_SLOT).hdr.ih_magic,
2512 BOOT_CURR_IMG(state));
2513 rc = BOOT_EBADIMAGE;
2514 FIH_SET(fih_rc, FIH_FAILURE);
2515 goto out;
2516 }
2517 #endif /* MCUBOOT_VALIDATE_PRIMARY_SLOT */
2518
2519 rc = boot_update_hw_rollback_protection(state);
2520 if (rc != 0) {
2521 FIH_SET(fih_rc, FIH_FAILURE);
2522 goto out;
2523 }
2524
2525 rc = boot_add_shared_data(state, BOOT_PRIMARY_SLOT);
2526 if (rc != 0) {
2527 FIH_SET(fih_rc, FIH_FAILURE);
2528 goto out;
2529 }
2530 ++fih_cnt;
2531 }
2532 /*
2533 * fih_cnt should be equal to BOOT_IMAGE_NUMBER now.
2534 * If this is not the case, at least one iteration of the loop
2535 * has been skipped.
2536 */
2537 if(FIH_NOT_EQ(fih_cnt, BOOT_IMAGE_NUMBER)) {
2538 FIH_PANIC;
2539 }
2540
2541 fill_rsp(state, rsp);
2542
2543 fih_rc = FIH_SUCCESS;
2544 out:
2545 /*
2546 * Since the boot_status struct stores plaintext encryption keys, reset
2547 * them here to avoid the possibility of jumping into an image that could
2548 * easily recover them.
2549 */
2550 #if defined(MCUBOOT_ENC_IMAGES) || defined(MCUBOOT_SWAP_SAVE_ENCTLV)
2551 like_mbedtls_zeroize(&bs, sizeof(bs));
2552 #else
2553 memset(&bs, 0, sizeof(struct boot_status));
2554 #endif
2555
2556 close_all_flash_areas(state);
2557 FIH_RET(fih_rc);
2558 }
2559
2560 fih_ret
2561 split_go(int loader_slot, int split_slot, void **entry)
2562 {
2563 boot_sector_t *sectors;
2564 uintptr_t entry_val;
2565 int loader_flash_id;
2566 int split_flash_id;
2567 int rc;
2568 FIH_DECLARE(fih_rc, FIH_FAILURE);
2569
2570 sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors);
2571 if (sectors == NULL) {
2572 FIH_RET(FIH_FAILURE);
2573 }
2574 BOOT_IMG(&boot_data, loader_slot).sectors = sectors + 0;
2575 BOOT_IMG(&boot_data, split_slot).sectors = sectors + BOOT_MAX_IMG_SECTORS;
2576
2577 loader_flash_id = flash_area_id_from_image_slot(loader_slot);
2578 rc = flash_area_open(loader_flash_id,
2579 &BOOT_IMG_AREA(&boot_data, loader_slot));
2580 assert(rc == 0);
2581 split_flash_id = flash_area_id_from_image_slot(split_slot);
2582 rc = flash_area_open(split_flash_id,
2583 &BOOT_IMG_AREA(&boot_data, split_slot));
2584 assert(rc == 0);
2585
2586 /* Determine the sector layout of the image slots and scratch area. */
2587 rc = boot_read_sectors(&boot_data);
2588 if (rc != 0) {
2589 rc = SPLIT_GO_ERR;
2590 goto done;
2591 }
2592
2593 rc = boot_read_image_headers(&boot_data, true, NULL);
2594 if (rc != 0) {
2595 goto done;
2596 }
2597
2598 /* Don't check the bootable image flag because we could really call a
2599 * bootable or non-bootable image. Just validate that the image check
2600 * passes which is distinct from the normal check.
2601 */
2602 FIH_CALL(split_image_check, fih_rc,
2603 boot_img_hdr(&boot_data, split_slot),
2604 BOOT_IMG_AREA(&boot_data, split_slot),
2605 boot_img_hdr(&boot_data, loader_slot),
2606 BOOT_IMG_AREA(&boot_data, loader_slot));
2607 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
2608 goto done;
2609 }
2610
2611 entry_val = boot_img_slot_off(&boot_data, split_slot) +
2612 boot_img_hdr(&boot_data, split_slot)->ih_hdr_size;
2613 *entry = (void *) entry_val;
2614 rc = SPLIT_GO_OK;
2615
2616 done:
2617 flash_area_close(BOOT_IMG_AREA(&boot_data, split_slot));
2618 flash_area_close(BOOT_IMG_AREA(&boot_data, loader_slot));
2619 free(sectors);
2620
2621 if (rc) {
2622 FIH_SET(fih_rc, FIH_FAILURE);
2623 }
2624
2625 FIH_RET(fih_rc);
2626 }
2627
2628 #else /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
2629
2630 /**
2631 * Opens all flash areas and checks which contain an image with a valid header.
2632 *
2633 * @param state Boot loader status information.
2634 *
2635 * @return 0 on success; nonzero on failure.
2636 */
2637 static int
2638 boot_get_slot_usage(struct boot_loader_state *state)
2639 {
2640 uint32_t slot;
2641 int fa_id;
2642 int rc;
2643 struct image_header *hdr = NULL;
2644
2645 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2646 #if BOOT_IMAGE_NUMBER > 1
2647 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2648 continue;
2649 }
2650 #endif
2651 /* Open all the slots */
2652 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2653 fa_id = flash_area_id_from_multi_image_slot(
2654 BOOT_CURR_IMG(state), slot);
2655 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(state, slot));
2656 assert(rc == 0);
2657 }
2658
2659 /* Attempt to read an image header from each slot. */
2660 rc = boot_read_image_headers(state, false, NULL);
2661 if (rc != 0) {
2662 BOOT_LOG_WRN("Failed reading image headers.");
2663 return rc;
2664 }
2665
2666 /* Check headers in all slots */
2667 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2668 hdr = boot_img_hdr(state, slot);
2669
2670 if (boot_is_header_valid(hdr, BOOT_IMG_AREA(state, slot), state)) {
2671 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = true;
2672 BOOT_LOG_IMAGE_INFO(slot, hdr);
2673 } else {
2674 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot] = false;
2675 BOOT_LOG_INF("Image %d %s slot: Image not found",
2676 BOOT_CURR_IMG(state),
2677 (slot == BOOT_PRIMARY_SLOT)
2678 ? "Primary" : "Secondary");
2679 }
2680 }
2681
2682 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2683 }
2684
2685 return 0;
2686 }
2687
2688 /**
2689 * Finds the slot containing the image with the highest version number for the
2690 * current image.
2691 *
2692 * @param state Boot loader status information.
2693 *
2694 * @return NO_ACTIVE_SLOT if no available slot found, number of
2695 * the found slot otherwise.
2696 */
2697 static uint32_t
2698 find_slot_with_highest_version(struct boot_loader_state *state)
2699 {
2700 uint32_t slot;
2701 uint32_t candidate_slot = NO_ACTIVE_SLOT;
2702 int rc;
2703
2704 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
2705 if (state->slot_usage[BOOT_CURR_IMG(state)].slot_available[slot]) {
2706 if (candidate_slot == NO_ACTIVE_SLOT) {
2707 candidate_slot = slot;
2708 } else {
2709 rc = boot_version_cmp(
2710 &boot_img_hdr(state, slot)->ih_ver,
2711 &boot_img_hdr(state, candidate_slot)->ih_ver);
2712 if (rc == 1) {
2713 /* The version of the image being examined is greater than
2714 * the version of the current candidate.
2715 */
2716 candidate_slot = slot;
2717 }
2718 }
2719 }
2720 }
2721
2722 return candidate_slot;
2723 }
2724
2725 #ifdef MCUBOOT_HAVE_LOGGING
2726 /**
2727 * Prints the state of the loaded images.
2728 *
2729 * @param state Boot loader status information.
2730 */
2731 static void
2732 print_loaded_images(struct boot_loader_state *state)
2733 {
2734 uint32_t active_slot;
2735
2736 (void)state;
2737
2738 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2739 #if BOOT_IMAGE_NUMBER > 1
2740 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2741 continue;
2742 }
2743 #endif
2744 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
2745
2746 BOOT_LOG_INF("Image %d loaded from the %s slot",
2747 BOOT_CURR_IMG(state),
2748 (active_slot == BOOT_PRIMARY_SLOT) ?
2749 "primary" : "secondary");
2750 }
2751 }
2752 #endif
2753
2754 #if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
2755 /**
2756 * Checks whether the active slot of the current image was previously selected
2757 * to run. Erases the image if it was selected but its execution failed,
2758 * otherwise marks it as selected if it has not been before.
2759 *
2760 * @param state Boot loader status information.
2761 *
2762 * @return 0 on success; nonzero on failure.
2763 */
2764 static int
2765 boot_select_or_erase(struct boot_loader_state *state)
2766 {
2767 const struct flash_area *fap;
2768 int fa_id;
2769 int rc;
2770 uint32_t active_slot;
2771 struct boot_swap_state* active_swap_state;
2772
2773 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
2774
2775 fa_id = flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state), active_slot);
2776 rc = flash_area_open(fa_id, &fap);
2777 assert(rc == 0);
2778
2779 active_swap_state = &(state->slot_usage[BOOT_CURR_IMG(state)].swap_state);
2780
2781 memset(active_swap_state, 0, sizeof(struct boot_swap_state));
2782 rc = boot_read_swap_state(fap, active_swap_state);
2783 assert(rc == 0);
2784
2785 if (active_swap_state->magic != BOOT_MAGIC_GOOD ||
2786 (active_swap_state->copy_done == BOOT_FLAG_SET &&
2787 active_swap_state->image_ok != BOOT_FLAG_SET)) {
2788 /*
2789 * A reboot happened without the image being confirmed at
2790 * runtime or its trailer is corrupted/invalid. Erase the image
2791 * to prevent it from being selected again on the next reboot.
2792 */
2793 BOOT_LOG_DBG("Erasing faulty image in the %s slot.",
2794 (active_slot == BOOT_PRIMARY_SLOT) ? "primary" : "secondary");
2795 rc = flash_area_erase(fap, 0, flash_area_get_size(fap));
2796 assert(rc == 0);
2797
2798 flash_area_close(fap);
2799 rc = -1;
2800 } else {
2801 if (active_swap_state->copy_done != BOOT_FLAG_SET) {
2802 if (active_swap_state->copy_done == BOOT_FLAG_BAD) {
2803 BOOT_LOG_DBG("The copy_done flag had an unexpected value. Its "
2804 "value was neither 'set' nor 'unset', but 'bad'.");
2805 }
2806 /*
2807 * Set the copy_done flag, indicating that the image has been
2808 * selected to boot. It can be set in advance, before even
2809 * validating the image, because in case the validation fails, the
2810 * entire image slot will be erased (including the trailer).
2811 */
2812 rc = boot_write_copy_done(fap);
2813 if (rc != 0) {
2814 BOOT_LOG_WRN("Failed to set copy_done flag of the image in "
2815 "the %s slot.", (active_slot == BOOT_PRIMARY_SLOT) ?
2816 "primary" : "secondary");
2817 rc = 0;
2818 }
2819 }
2820 flash_area_close(fap);
2821 }
2822
2823 return rc;
2824 }
2825 #endif /* MCUBOOT_DIRECT_XIP && MCUBOOT_DIRECT_XIP_REVERT */
2826
2827 /**
2828 * Tries to load a slot for all the images with validation.
2829 *
2830 * @param state Boot loader status information.
2831 *
2832 * @return 0 on success; nonzero on failure.
2833 */
2834 fih_ret
2835 boot_load_and_validate_images(struct boot_loader_state *state)
2836 {
2837 uint32_t active_slot;
2838 int rc;
2839 fih_ret fih_rc;
2840
2841 /* Go over all the images and try to load one */
2842 IMAGES_ITER(BOOT_CURR_IMG(state)) {
2843 /* All slots tried until a valid image found. Breaking from this loop
2844 * means that a valid image found or already loaded. If no slot is
2845 * found the function returns with error code. */
2846 while (true) {
2847 /* Go over all the slots and try to load one */
2848 active_slot = state->slot_usage[BOOT_CURR_IMG(state)].active_slot;
2849 if (active_slot != NO_ACTIVE_SLOT){
2850 /* A slot is already active, go to next image. */
2851 break;
2852 }
2853
2854 active_slot = find_slot_with_highest_version(state);
2855 if (active_slot == NO_ACTIVE_SLOT) {
2856 BOOT_LOG_INF("No slot to load for image %d",
2857 BOOT_CURR_IMG(state));
2858 FIH_RET(FIH_FAILURE);
2859 }
2860
2861 /* Save the number of the active slot. */
2862 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = active_slot;
2863
2864 #if BOOT_IMAGE_NUMBER > 1
2865 if (state->img_mask[BOOT_CURR_IMG(state)]) {
2866 continue;
2867 }
2868 #endif
2869
2870 #ifdef MCUBOOT_DIRECT_XIP
2871 rc = boot_rom_address_check(state);
2872 if (rc != 0) {
2873 /* The image is placed in an unsuitable slot. */
2874 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2875 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2876 continue;
2877 }
2878
2879 #ifdef MCUBOOT_DIRECT_XIP_REVERT
2880 rc = boot_select_or_erase(state);
2881 if (rc != 0) {
2882 /* The selected image slot has been erased. */
2883 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2884 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2885 continue;
2886 }
2887 #endif /* MCUBOOT_DIRECT_XIP_REVERT */
2888 #endif /* MCUBOOT_DIRECT_XIP */
2889
2890 #ifdef MCUBOOT_RAM_LOAD
2891 /* Image is first loaded to RAM and authenticated there in order to
2892 * prevent TOCTOU attack during image copy. This could be applied
2893 * when loading images from external (untrusted) flash to internal
2894 * (trusted) RAM and image is authenticated before copying.
2895 */
2896 rc = boot_load_image_to_sram(state);
2897 if (rc != 0 ) {
2898 /* Image cannot be ramloaded. */
2899 boot_remove_image_from_flash(state, active_slot);
2900 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2901 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2902 continue;
2903 }
2904 #endif /* MCUBOOT_RAM_LOAD */
2905
2906 FIH_CALL(boot_validate_slot, fih_rc, state, active_slot, NULL, 0);
2907 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
2908 /* Image is invalid. */
2909 #ifdef MCUBOOT_RAM_LOAD
2910 boot_remove_image_from_sram(state);
2911 #endif /* MCUBOOT_RAM_LOAD */
2912 state->slot_usage[BOOT_CURR_IMG(state)].slot_available[active_slot] = false;
2913 state->slot_usage[BOOT_CURR_IMG(state)].active_slot = NO_ACTIVE_SLOT;
2914 continue;
2915 }
2916
2917 /* Valid image loaded from a slot, go to next image. */
2918 break;
2919 }
2920 }
2921
2922 FIH_RET(FIH_SUCCESS);
2923 }
2924
2925 /**
2926 * Updates the security counter for the current image.
2927 *
2928 * @param state Boot loader status information.
2929 *
2930 * @return 0 on success; nonzero on failure.
2931 */
2932 static int
2933 boot_update_hw_rollback_protection(struct boot_loader_state *state)
2934 {
2935 #ifdef MCUBOOT_HW_ROLLBACK_PROT
2936 int rc;
2937
2938 /* Update the stored security counter with the newer (active) image's
2939 * security counter value.
2940 */
2941 #if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
2942 /* When the 'revert' mechanism is enabled in direct-xip mode, the
2943 * security counter can be increased only after reboot, if the image
2944 * has been confirmed at runtime (the image_ok flag has been set).
2945 * This way a 'revert' can be performed when it's necessary.
2946 */
2947 if (state->slot_usage[BOOT_CURR_IMG(state)].swap_state.image_ok == BOOT_FLAG_SET) {
2948 #endif
2949 rc = boot_update_security_counter(state,
2950 state->slot_usage[BOOT_CURR_IMG(state)].active_slot,
2951 state->slot_usage[BOOT_CURR_IMG(state)].active_slot);
2952 if (rc != 0) {
2953 BOOT_LOG_ERR("Security counter update failed after image %d validation.", BOOT_CURR_IMG(state));
2954 return rc;
2955 }
2956 #if defined(MCUBOOT_DIRECT_XIP) && defined(MCUBOOT_DIRECT_XIP_REVERT)
2957 }
2958 #endif
2959
2960 return 0;
2961
2962 #else /* MCUBOOT_HW_ROLLBACK_PROT */
2963 (void) (state);
2964 return 0;
2965 #endif
2966 }
2967
2968 fih_ret
2969 context_boot_go(struct boot_loader_state *state, struct boot_rsp *rsp)
2970 {
2971 int rc;
2972 FIH_DECLARE(fih_rc, FIH_FAILURE);
2973
2974 rc = boot_get_slot_usage(state);
2975 if (rc != 0) {
2976 goto out;
2977 }
2978
2979 #if (BOOT_IMAGE_NUMBER > 1)
2980 while (true) {
2981 #endif
2982 FIH_CALL(boot_load_and_validate_images, fih_rc, state);
2983 if (FIH_NOT_EQ(fih_rc, FIH_SUCCESS)) {
2984 FIH_SET(fih_rc, FIH_FAILURE);
2985 goto out;
2986 }
2987
2988 #if (BOOT_IMAGE_NUMBER > 1)
2989 rc = boot_verify_dependencies(state);
2990 if (rc != 0) {
2991 /* Dependency check failed for an image, it has been removed from
2992 * SRAM in case of MCUBOOT_RAM_LOAD strategy, and set to
2993 * unavailable. Try to load an image from another slot.
2994 */
2995 continue;
2996 }
2997 /* Dependency check was successful. */
2998 break;
2999 }
3000 #endif
3001
3002 IMAGES_ITER(BOOT_CURR_IMG(state)) {
3003 #if BOOT_IMAGE_NUMBER > 1
3004 if (state->img_mask[BOOT_CURR_IMG(state)]) {
3005 continue;
3006 }
3007 #endif
3008 rc = boot_update_hw_rollback_protection(state);
3009 if (rc != 0) {
3010 FIH_SET(fih_rc, FIH_FAILURE);
3011 goto out;
3012 }
3013
3014 rc = boot_add_shared_data(state, (uint8_t)state->slot_usage[BOOT_CURR_IMG(state)].active_slot);
3015 if (rc != 0) {
3016 FIH_SET(fih_rc, FIH_FAILURE);
3017 goto out;
3018 }
3019 }
3020
3021 /* All image loaded successfully. */
3022 #ifdef MCUBOOT_HAVE_LOGGING
3023 print_loaded_images(state);
3024 #endif
3025
3026 fill_rsp(state, rsp);
3027
3028 out:
3029 close_all_flash_areas(state);
3030
3031 if (rc != 0) {
3032 FIH_SET(fih_rc, FIH_FAILURE);
3033 }
3034
3035 FIH_RET(fih_rc);
3036 }
3037 #endif /* MCUBOOT_DIRECT_XIP || MCUBOOT_RAM_LOAD */
3038
3039 /**
3040 * Prepares the booting process. This function moves images around in flash as
3041 * appropriate, and tells you what address to boot from.
3042 *
3043 * @param rsp On success, indicates how booting should occur.
3044 *
3045 * @return FIH_SUCCESS on success; nonzero on failure.
3046 */
3047 fih_ret
3048 boot_go(struct boot_rsp *rsp)
3049 {
3050 FIH_DECLARE(fih_rc, FIH_FAILURE);
3051
3052 boot_state_clear(NULL);
3053
3054 FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp);
3055 FIH_RET(fih_rc);
3056 }
3057
3058 /**
3059 * Prepares the booting process, considering only a single image. This function
3060 * moves images around in flash as appropriate, and tells you what address to
3061 * boot from.
3062 *
3063 * @param rsp On success, indicates how booting should occur.
3064 *
3065 * @param image_id The image ID to prepare the boot process for.
3066 *
3067 * @return FIH_SUCCESS on success; nonzero on failure.
3068 */
3069 fih_ret
3070 boot_go_for_image_id(struct boot_rsp *rsp, uint32_t image_id)
3071 {
3072 FIH_DECLARE(fih_rc, FIH_FAILURE);
3073
3074 if (image_id >= BOOT_IMAGE_NUMBER) {
3075 FIH_RET(FIH_FAILURE);
3076 }
3077
3078 #if BOOT_IMAGE_NUMBER > 1
3079 memset(&boot_data.img_mask, 1, BOOT_IMAGE_NUMBER);
3080 boot_data.img_mask[image_id] = 0;
3081 #endif
3082
3083 FIH_CALL(context_boot_go, fih_rc, &boot_data, rsp);
3084 FIH_RET(fih_rc);
3085 }
3086
3087 /**
3088 * Clears the boot state, so that previous operations have no effect on new
3089 * ones.
3090 *
3091 * @param state The state that should be cleared. If the value
3092 * is NULL, the default bootloader state will be
3093 * cleared.
3094 */
3095 void boot_state_clear(struct boot_loader_state *state)
3096 {
3097 if (state != NULL) {
3098 memset(state, 0, sizeof(struct boot_loader_state));
3099 } else {
3100 memset(&boot_data, 0, sizeof(struct boot_loader_state));
3101 }
3102 }
3103
3104 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
3105 /**
3106 * Reads image data to find out the maximum application sizes. Only needs to
3107 * be called in serial recovery mode, as the state information is unpopulated
3108 * at that time
3109 */
3110 static void boot_fetch_slot_state_sizes(void)
3111 {
3112 size_t slot;
3113 int rc = -1;
3114 int fa_id;
3115 int image_index;
3116
3117 IMAGES_ITER(BOOT_CURR_IMG(&boot_data)) {
3118 int max_size = 0;
3119
3120 image_index = BOOT_CURR_IMG(&boot_data);
3121
3122 BOOT_IMG(&boot_data, BOOT_PRIMARY_SLOT).sectors =
3123 sector_buffers.primary[image_index];
3124 BOOT_IMG(&boot_data, BOOT_SECONDARY_SLOT).sectors =
3125 sector_buffers.secondary[image_index];
3126 #if MCUBOOT_SWAP_USING_SCRATCH
3127 boot_data.scratch.sectors = sector_buffers.scratch;
3128 #endif
3129
3130 /* Open primary and secondary image areas for the duration
3131 * of this call.
3132 */
3133 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
3134 fa_id = flash_area_id_from_multi_image_slot(image_index, slot);
3135 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot));
3136 assert(rc == 0);
3137
3138 if (rc != 0) {
3139 goto finish;
3140 }
3141 }
3142
3143 #if MCUBOOT_SWAP_USING_SCRATCH
3144 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
3145 &BOOT_SCRATCH_AREA(&boot_data));
3146 assert(rc == 0);
3147
3148 if (rc != 0) {
3149 goto finish;
3150 }
3151 #endif
3152
3153 /* Determine the sector layout of the image slots and scratch area. */
3154 rc = boot_read_sectors_recovery(&boot_data);
3155
3156 if (rc == 0) {
3157 max_size = app_max_size(&boot_data);
3158
3159 if (max_size > 0) {
3160 image_max_sizes[image_index].calculated = true;
3161 image_max_sizes[image_index].max_size = max_size;
3162 }
3163 }
3164 }
3165
3166 finish:
3167 close_all_flash_areas(&boot_data);
3168 memset(&boot_data, 0x00, sizeof(boot_data));
3169 }
3170 #endif
3171
3172 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO) || defined(MCUBOOT_DATA_SHARING)
3173 /**
3174 * Fetches the maximum allowed size of the image
3175 */
3176 const struct image_max_size *boot_get_max_app_size(void)
3177 {
3178 #if defined(MCUBOOT_SERIAL_IMG_GRP_SLOT_INFO)
3179 uint8_t i = 0;
3180
3181 while (i < BOOT_IMAGE_NUMBER) {
3182 if (image_max_sizes[i].calculated == true) {
3183 break;
3184 }
3185
3186 ++i;
3187 }
3188
3189 if (i == BOOT_IMAGE_NUMBER) {
3190 /* Information not available, need to fetch it */
3191 boot_fetch_slot_state_sizes();
3192 }
3193 #endif
3194
3195 return image_max_sizes;
3196 }
3197 #endif
3198
3199 #if defined(MCUBOOT_SWAP_USING_OFFSET)
3200 uint32_t boot_get_state_secondary_offset(struct boot_loader_state *state,
3201 const struct flash_area *fap)
3202 {
3203 if (state != NULL && flash_area_id_from_multi_image_slot(BOOT_CURR_IMG(state),
3204 BOOT_SECONDARY_SLOT) == fap->fa_id) {
3205 return state->secondary_offset[BOOT_CURR_IMG(state)];
3206 }
3207
3208 return 0;
3209 }
3210 #endif
3211