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, &copy_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