1 /*
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  * Copyright (c) 2017-2019 Linaro LTD
5  * Copyright (c) 2016-2019 JUUL Labs
6  * Copyright (c) 2019-2023 Arm Limited
7  * Copyright (c) 2020-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  * @file
31  * @brief Public MCUBoot interface API implementation
32  *
33  * This file contains API implementation which can be combined with
34  * the application in order to interact with the MCUBoot bootloader.
35  * This file contains shared code-base betwen MCUBoot and the application
36  * which controls DFU process.
37  */
38 
39 #include <string.h>
40 #include <inttypes.h>
41 #include <stddef.h>
42 
43 #include "sysflash/sysflash.h"
44 #include "flash_map_backend/flash_map_backend.h"
45 
46 #include "bootutil/image.h"
47 #include "bootutil/bootutil_public.h"
48 #include "bootutil/bootutil_log.h"
49 
50 #include "bootutil/boot_public_hooks.h"
51 #include "bootutil_priv.h"
52 #include "bootutil_misc.h"
53 
54 #ifdef CONFIG_MCUBOOT
55 BOOT_LOG_MODULE_DECLARE(mcuboot);
56 #else
57 BOOT_LOG_MODULE_REGISTER(mcuboot_util);
58 #endif
59 
60 #if BOOT_MAX_ALIGN == 8
61 const union boot_img_magic_t boot_img_magic = {
62     .val = {
63         0x77, 0xc2, 0x95, 0xf3,
64         0x60, 0xd2, 0xef, 0x7f,
65         0x35, 0x52, 0x50, 0x0f,
66         0x2c, 0xb6, 0x79, 0x80
67     }
68 };
69 #else
70 const union boot_img_magic_t boot_img_magic = {
71     .align = BOOT_MAX_ALIGN,
72     .magic = {
73         0x2d, 0xe1,
74         0x5d, 0x29, 0x41, 0x0b,
75         0x8d, 0x77, 0x67, 0x9c,
76         0x11, 0x0f, 0x1f, 0x8a
77     }
78 };
79 #endif
80 
81 struct boot_swap_table {
82     uint8_t magic_primary_slot;
83     uint8_t magic_secondary_slot;
84     uint8_t image_ok_primary_slot;
85     uint8_t image_ok_secondary_slot;
86     uint8_t copy_done_primary_slot;
87 #if defined(MCUBOOT_SWAP_USING_OFFSET)
88     uint8_t copy_done_secondary_slot;
89 #endif
90 
91     uint8_t swap_type;
92 };
93 
94 /**
95  * This set of tables maps image trailer contents to swap operation type.
96  * When searching for a match, these tables must be iterated sequentially.
97  *
98  * NOTE: the table order is very important. The settings in the secondary
99  * slot always are priority to the primary slot and should be located
100  * earlier in the table.
101  *
102  * The table lists only states where there is action needs to be taken by
103  * the bootloader, as in starting/finishing a swap operation.
104  */
105 static const struct boot_swap_table boot_swap_tables[] = {
106 #if defined(MCUBOOT_SWAP_USING_OFFSET)
107     {
108         .magic_primary_slot =       BOOT_MAGIC_ANY,
109         .magic_secondary_slot =     BOOT_MAGIC_GOOD,
110         .image_ok_primary_slot =    BOOT_FLAG_ANY,
111         .image_ok_secondary_slot =  BOOT_FLAG_UNSET,
112         .copy_done_primary_slot =   BOOT_FLAG_ANY,
113         .copy_done_secondary_slot = BOOT_FLAG_SET,
114         .swap_type =                BOOT_SWAP_TYPE_REVERT,
115     },
116 #endif
117     {
118         .magic_primary_slot =       BOOT_MAGIC_ANY,
119         .magic_secondary_slot =     BOOT_MAGIC_GOOD,
120         .image_ok_primary_slot =    BOOT_FLAG_ANY,
121         .image_ok_secondary_slot =  BOOT_FLAG_UNSET,
122         .copy_done_primary_slot =   BOOT_FLAG_ANY,
123 #if defined(MCUBOOT_SWAP_USING_OFFSET)
124         .copy_done_secondary_slot = BOOT_FLAG_ANY,
125 #endif
126         .swap_type =                BOOT_SWAP_TYPE_TEST,
127     },
128     {
129         .magic_primary_slot =       BOOT_MAGIC_ANY,
130         .magic_secondary_slot =     BOOT_MAGIC_GOOD,
131         .image_ok_primary_slot =    BOOT_FLAG_ANY,
132         .image_ok_secondary_slot =  BOOT_FLAG_SET,
133         .copy_done_primary_slot =   BOOT_FLAG_ANY,
134 #if defined(MCUBOOT_SWAP_USING_OFFSET)
135         .copy_done_secondary_slot = BOOT_FLAG_ANY,
136 #endif
137         .swap_type =                BOOT_SWAP_TYPE_PERM,
138     },
139     {
140         .magic_primary_slot =       BOOT_MAGIC_GOOD,
141         .magic_secondary_slot =     BOOT_MAGIC_ANY,
142         .image_ok_primary_slot =    BOOT_FLAG_UNSET,
143         .image_ok_secondary_slot =  BOOT_FLAG_ANY,
144         .copy_done_primary_slot =   BOOT_FLAG_SET,
145 #if defined(MCUBOOT_SWAP_USING_OFFSET)
146         .copy_done_secondary_slot = BOOT_FLAG_ANY,
147 #endif
148         .swap_type =                BOOT_SWAP_TYPE_REVERT,
149     },
150 };
151 
152 #define BOOT_SWAP_TABLES_COUNT \
153     (sizeof boot_swap_tables / sizeof boot_swap_tables[0])
154 
155 static int
boot_flag_decode(uint8_t flag)156 boot_flag_decode(uint8_t flag)
157 {
158     if (flag != BOOT_FLAG_SET) {
159         return BOOT_FLAG_BAD;
160     }
161     return BOOT_FLAG_SET;
162 }
163 
164 uint32_t
boot_swap_info_off(const struct flash_area * fap)165 boot_swap_info_off(const struct flash_area *fap)
166 {
167     return boot_copy_done_off(fap) - BOOT_MAX_ALIGN;
168 }
169 
170 /**
171  * Determines if a status source table is satisfied by the specified magic
172  * code.
173  *
174  * @param tbl_val               A magic field from a status source table.
175  * @param val                   The magic value in a trailer, encoded as a
176  *                                  BOOT_MAGIC_[...].
177  *
178  * @return                      1 if the two values are compatible;
179  *                              0 otherwise.
180  */
181 int
boot_magic_compatible_check(uint8_t tbl_val,uint8_t val)182 boot_magic_compatible_check(uint8_t tbl_val, uint8_t val)
183 {
184     switch (tbl_val) {
185     case BOOT_MAGIC_ANY:
186         return 1;
187 
188     case BOOT_MAGIC_NOTGOOD:
189         return val != BOOT_MAGIC_GOOD;
190 
191     default:
192         return tbl_val == val;
193     }
194 }
195 
bootutil_buffer_is_erased(const struct flash_area * area,const void * buffer,size_t len)196 bool bootutil_buffer_is_erased(const struct flash_area *area,
197                                const void *buffer, size_t len)
198 {
199     size_t i;
200     uint8_t *u8b;
201     uint8_t erased_val;
202 
203     if (buffer == NULL || len == 0) {
204         return false;
205     }
206 
207     erased_val = flash_area_erased_val(area);
208     for (i = 0, u8b = (uint8_t *)buffer; i < len; i++) {
209         if (u8b[i] != erased_val) {
210             return false;
211         }
212     }
213 
214     return true;
215 }
216 
217 static int
boot_read_flag(const struct flash_area * fap,uint8_t * flag,uint32_t off)218 boot_read_flag(const struct flash_area *fap, uint8_t *flag, uint32_t off)
219 {
220     int rc;
221 
222     rc = flash_area_read(fap, off, flag, sizeof *flag);
223     if (rc < 0) {
224         return BOOT_EFLASH;
225     }
226     if (bootutil_buffer_is_erased(fap, flag, sizeof *flag)) {
227         *flag = BOOT_FLAG_UNSET;
228     } else {
229         *flag = boot_flag_decode(*flag);
230     }
231 
232     return 0;
233 }
234 
235 static inline int
boot_read_copy_done(const struct flash_area * fap,uint8_t * copy_done)236 boot_read_copy_done(const struct flash_area *fap, uint8_t *copy_done)
237 {
238     return boot_read_flag(fap, copy_done, boot_copy_done_off(fap));
239 }
240 
241 
242 int
boot_read_swap_state(const struct flash_area * fap,struct boot_swap_state * state)243 boot_read_swap_state(const struct flash_area *fap,
244                      struct boot_swap_state *state)
245 {
246     uint8_t magic[BOOT_MAGIC_SZ];
247     uint32_t off;
248     uint8_t swap_info;
249     int rc;
250 
251     off = boot_magic_off(fap);
252     rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
253     if (rc < 0) {
254         return BOOT_EFLASH;
255     }
256     if (bootutil_buffer_is_erased(fap, magic, BOOT_MAGIC_SZ)) {
257         state->magic = BOOT_MAGIC_UNSET;
258     } else {
259         state->magic = boot_magic_decode(magic);
260     }
261 
262     off = boot_swap_info_off(fap);
263     rc = flash_area_read(fap, off, &swap_info, sizeof swap_info);
264     if (rc < 0) {
265         return BOOT_EFLASH;
266     }
267 
268     /* Extract the swap type and image number */
269     state->swap_type = BOOT_GET_SWAP_TYPE(swap_info);
270     state->image_num = BOOT_GET_IMAGE_NUM(swap_info);
271 
272     if (bootutil_buffer_is_erased(fap, &swap_info, sizeof swap_info) ||
273             state->swap_type > BOOT_SWAP_TYPE_REVERT) {
274         state->swap_type = BOOT_SWAP_TYPE_NONE;
275         state->image_num = 0;
276     }
277 
278     rc = boot_read_copy_done(fap, &state->copy_done);
279     if (rc) {
280         return BOOT_EFLASH;
281     }
282 
283     return boot_read_image_ok(fap, &state->image_ok);
284 }
285 
286 int
boot_read_swap_state_by_id(int flash_area_id,struct boot_swap_state * state)287 boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
288 {
289     const struct flash_area *fap;
290     int rc;
291 
292     rc = flash_area_open(flash_area_id, &fap);
293     if (rc != 0) {
294         return BOOT_EFLASH;
295     }
296 
297     rc = boot_read_swap_state(fap, state);
298     flash_area_close(fap);
299     return rc;
300 }
301 
302 int
boot_write_magic(const struct flash_area * fap)303 boot_write_magic(const struct flash_area *fap)
304 {
305     uint32_t off;
306     uint32_t pad_off;
307     int rc;
308     uint8_t magic[BOOT_MAGIC_ALIGN_SIZE];
309     uint8_t erased_val;
310 
311     off = boot_magic_off(fap);
312 
313     /* image_trailer structure was modified with additional padding such that
314      * the pad+magic ends up in a flash minimum write region. The address
315      * returned by boot_magic_off() is the start of magic which is not the
316      * start of the flash write boundary and thus writes to the magic will fail.
317      * To account for this change, write to magic is first padded with 0xFF
318      * before writing to the trailer.
319      */
320     pad_off = ALIGN_DOWN(off, BOOT_MAX_ALIGN);
321 
322     erased_val = flash_area_erased_val(fap);
323 
324     memset(&magic[0], erased_val, sizeof(magic));
325     memcpy(&magic[BOOT_MAGIC_ALIGN_SIZE - BOOT_MAGIC_SZ], BOOT_IMG_MAGIC, BOOT_MAGIC_SZ);
326 
327     BOOT_LOG_DBG("writing magic; fa_id=%d off=0x%lx (0x%lx)",
328                  flash_area_get_id(fap), (unsigned long)off,
329                  (unsigned long)(flash_area_get_off(fap) + off));
330     rc = flash_area_write(fap, pad_off, &magic[0], BOOT_MAGIC_ALIGN_SIZE);
331 
332     if (rc != 0) {
333         return BOOT_EFLASH;
334     }
335 
336     return 0;
337 }
338 
339 /**
340  * Write trailer data; status bytes, swap_size, etc
341  *
342  * @returns 0 on success, != 0 on error.
343  */
344 int
boot_write_trailer(const struct flash_area * fap,uint32_t off,const uint8_t * inbuf,uint8_t inlen)345 boot_write_trailer(const struct flash_area *fap, uint32_t off,
346         const uint8_t *inbuf, uint8_t inlen)
347 {
348     uint8_t buf[BOOT_MAX_ALIGN];
349     uint8_t erased_val;
350     uint32_t align;
351     int rc;
352 
353     align = flash_area_align(fap);
354     align = ALIGN_UP(inlen, align);
355     if (align > BOOT_MAX_ALIGN) {
356         return -1;
357     }
358     erased_val = flash_area_erased_val(fap);
359 
360     memcpy(buf, inbuf, inlen);
361     memset(&buf[inlen], erased_val, align - inlen);
362 
363     rc = flash_area_write(fap, off, buf, align);
364     if (rc != 0) {
365         return BOOT_EFLASH;
366     }
367 
368     return 0;
369 }
370 
371 int
boot_write_trailer_flag(const struct flash_area * fap,uint32_t off,uint8_t flag_val)372 boot_write_trailer_flag(const struct flash_area *fap, uint32_t off,
373         uint8_t flag_val)
374 {
375     const uint8_t buf[1] = { flag_val };
376     return boot_write_trailer(fap, off, buf, 1);
377 }
378 
379 int
boot_write_image_ok(const struct flash_area * fap)380 boot_write_image_ok(const struct flash_area *fap)
381 {
382     uint32_t off;
383 
384     off = boot_image_ok_off(fap);
385     BOOT_LOG_DBG("writing image_ok; fa_id=%d off=0x%lx (0x%lx)",
386                  flash_area_get_id(fap), (unsigned long)off,
387                  (unsigned long)(flash_area_get_off(fap) + off));
388     return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET);
389 }
390 
391 int
boot_read_image_ok(const struct flash_area * fap,uint8_t * image_ok)392 boot_read_image_ok(const struct flash_area *fap, uint8_t *image_ok)
393 {
394     return boot_read_flag(fap, image_ok, boot_image_ok_off(fap));
395 }
396 
397 /**
398  * Writes the specified value to the `swap-type` field of an image trailer.
399  * This value is persisted so that the boot loader knows what swap operation to
400  * resume in case of an unexpected reset.
401  */
402 int
boot_write_swap_info(const struct flash_area * fap,uint8_t swap_type,uint8_t image_num)403 boot_write_swap_info(const struct flash_area *fap, uint8_t swap_type,
404                      uint8_t image_num)
405 {
406     uint32_t off;
407     uint8_t swap_info;
408 
409     BOOT_SET_SWAP_INFO(swap_info, image_num, swap_type);
410     off = boot_swap_info_off(fap);
411     BOOT_LOG_DBG("writing swap_info; fa_id=%d off=0x%lx (0x%lx), swap_type=0x%x"
412                  " image_num=0x%x",
413                  flash_area_get_id(fap), (unsigned long)off,
414                  (unsigned long)(flash_area_get_off(fap) + off),
415                  swap_type, image_num);
416     return boot_write_trailer(fap, off, (const uint8_t *) &swap_info, 1);
417 }
418 
419 int
boot_swap_type_multi(int image_index)420 boot_swap_type_multi(int image_index)
421 {
422     const struct boot_swap_table *table;
423     struct boot_swap_state primary_slot;
424     struct boot_swap_state secondary_slot;
425     int rc;
426     size_t i;
427 
428     rc = BOOT_HOOK_CALL(boot_read_swap_state_primary_slot_hook,
429                         BOOT_HOOK_REGULAR, image_index, &primary_slot);
430     if (rc == BOOT_HOOK_REGULAR)
431     {
432         rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(image_index),
433                                         &primary_slot);
434     }
435     if (rc) {
436         return BOOT_SWAP_TYPE_PANIC;
437     }
438 
439     rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(image_index),
440                                     &secondary_slot);
441     if (rc == BOOT_EFLASH) {
442         BOOT_LOG_INF("Secondary image of image pair (%d.) "
443                      "is unreachable. Treat it as empty", image_index);
444         secondary_slot.magic = BOOT_MAGIC_UNSET;
445         secondary_slot.swap_type = BOOT_SWAP_TYPE_NONE;
446         secondary_slot.copy_done = BOOT_FLAG_UNSET;
447         secondary_slot.image_ok = BOOT_FLAG_UNSET;
448         secondary_slot.image_num = 0;
449     } else if (rc) {
450         return BOOT_SWAP_TYPE_PANIC;
451     }
452 
453     for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
454         table = boot_swap_tables + i;
455 
456         if (boot_magic_compatible_check(table->magic_primary_slot,
457                                         primary_slot.magic) &&
458             boot_magic_compatible_check(table->magic_secondary_slot,
459                                         secondary_slot.magic) &&
460             (table->image_ok_primary_slot == BOOT_FLAG_ANY   ||
461                 table->image_ok_primary_slot == primary_slot.image_ok) &&
462             (table->image_ok_secondary_slot == BOOT_FLAG_ANY ||
463                 table->image_ok_secondary_slot == secondary_slot.image_ok) &&
464             (table->copy_done_primary_slot == BOOT_FLAG_ANY  ||
465                 table->copy_done_primary_slot == primary_slot.copy_done)
466 #if defined(MCUBOOT_SWAP_USING_OFFSET)
467             && (table->copy_done_secondary_slot == BOOT_FLAG_ANY  ||
468                 table->copy_done_secondary_slot == secondary_slot.copy_done)
469 #endif
470             ) {
471             BOOT_LOG_INF("Image index: %d, Swap type: %s", image_index,
472                          table->swap_type == BOOT_SWAP_TYPE_TEST   ? "test"   :
473                          table->swap_type == BOOT_SWAP_TYPE_PERM   ? "perm"   :
474                          table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
475                          "BUG; can't happen");
476             if (table->swap_type != BOOT_SWAP_TYPE_TEST &&
477                     table->swap_type != BOOT_SWAP_TYPE_PERM &&
478                     table->swap_type != BOOT_SWAP_TYPE_REVERT) {
479                 return BOOT_SWAP_TYPE_PANIC;
480             }
481             return table->swap_type;
482         }
483     }
484 
485     BOOT_LOG_INF("Image index: %d, Swap type: none", image_index);
486     return BOOT_SWAP_TYPE_NONE;
487 }
488 
489 int
boot_write_copy_done(const struct flash_area * fap)490 boot_write_copy_done(const struct flash_area *fap)
491 {
492     uint32_t off;
493 
494     off = boot_copy_done_off(fap);
495     BOOT_LOG_DBG("writing copy_done; fa_id=%d off=0x%lx (0x%lx)",
496                  flash_area_get_id(fap), (unsigned long)off,
497                  (unsigned long)(flash_area_get_off(fap) + off));
498     return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET);
499 }
500 
501 #ifndef MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP
502 
flash_area_to_image(const struct flash_area * fa)503 static int flash_area_to_image(const struct flash_area *fa)
504 {
505 #if BOOT_IMAGE_NUMBER > 1
506     uint8_t i = 0;
507     int id = flash_area_get_id(fa);
508 
509     while (i < BOOT_IMAGE_NUMBER) {
510         if (FLASH_AREA_IMAGE_PRIMARY(i) == id || (FLASH_AREA_IMAGE_SECONDARY(i) == id)) {
511             return i;
512         }
513 
514         ++i;
515     }
516 #else
517     (void)fa;
518 #endif
519     return 0;
520 }
521 
522 int
boot_set_next(const struct flash_area * fa,bool active,bool confirm)523 boot_set_next(const struct flash_area *fa, bool active, bool confirm)
524 {
525     struct boot_swap_state slot_state;
526     int rc;
527 
528     if (active) {
529         confirm = true;
530     }
531 
532     rc = boot_read_swap_state(fa, &slot_state);
533     if (rc != 0) {
534         return rc;
535     }
536 
537     switch (slot_state.magic) {
538     case BOOT_MAGIC_GOOD:
539         /* If non-active then swap already scheduled, else confirm needed.*/
540 
541         if (active && slot_state.image_ok == BOOT_FLAG_UNSET) {
542             /* Intentionally do not check copy_done flag to be able to
543              * confirm a padded image which has been programmed using
544              * a programming interface.
545              */
546             rc = boot_write_image_ok(fa);
547         }
548 
549         break;
550 
551     case BOOT_MAGIC_UNSET:
552         if (!active) {
553             rc = boot_write_magic(fa);
554 
555             if (rc == 0 && confirm) {
556                 rc = boot_write_image_ok(fa);
557             }
558 
559             if (rc == 0) {
560                 uint8_t swap_type;
561 
562                 if (confirm) {
563                     swap_type = BOOT_SWAP_TYPE_PERM;
564                 } else {
565                     swap_type = BOOT_SWAP_TYPE_TEST;
566                 }
567                 rc = boot_write_swap_info(fa, swap_type, flash_area_to_image(fa));
568             }
569         }
570         break;
571 
572     case BOOT_MAGIC_BAD:
573         if (active) {
574             rc = BOOT_EBADVECT;
575         } else {
576             /* The image slot is corrupt.  There is no way to recover, so erase the
577              * slot to allow future upgrades.
578              */
579             flash_area_erase(fa, 0, flash_area_get_size(fa));
580             rc = BOOT_EBADIMAGE;
581         }
582         break;
583 
584     default:
585         /* Something is not OK, this should never happen */
586         assert(0);
587         rc = BOOT_EBADIMAGE;
588     }
589 
590     return rc;
591 }
592 #else
593 int
boot_set_next(const struct flash_area * fa,bool active,bool confirm)594 boot_set_next(const struct flash_area *fa, bool active, bool confirm)
595 {
596     struct boot_swap_state slot_state;
597     int rc;
598 
599     if (active) {
600         /* The only way to set active slot for next boot is to confirm it,
601          * as DirectXIP will conclude that, since slot has not been confirmed
602          * last boot, it is bad and will remove it.
603          */
604         confirm = true;
605     }
606 
607     rc = boot_read_swap_state(fa, &slot_state);
608     if (rc != 0) {
609         return rc;
610     }
611 
612     switch (slot_state.magic) {
613     case BOOT_MAGIC_UNSET:
614         /* Magic is needed for MCUboot to even consider booting an image */
615         rc = boot_write_magic(fa);
616         if (rc != 0) {
617             break;
618         }
619         /* Pass */
620 
621     case BOOT_MAGIC_GOOD:
622         if (confirm) {
623             if (slot_state.copy_done == BOOT_FLAG_UNSET) {
624                 /* Magic is needed for DirectXIP to even try to boot application.
625                  * DirectXIP will set copy-done flag before attempting to boot
626                  * application. Next boot, application that has copy-done flag
627                  * is expected to already have ok flag, otherwise it will be removed.
628                  */
629                 rc = boot_write_copy_done(fa);
630                 if (rc != 0) {
631                     break;
632                 }
633             }
634 
635             if (slot_state.image_ok == BOOT_FLAG_UNSET) {
636                 rc = boot_write_image_ok(fa);
637                 if (rc != 0) {
638                     break;
639                 }
640             }
641         }
642         break;
643 
644     case BOOT_MAGIC_BAD:
645         /* This image will not be boot next time anyway */
646         rc = BOOT_EBADIMAGE;
647         break;
648 
649     default:
650         /* Something is not OK, this should never happen */
651         assert(0);
652         rc = BOOT_EBADSTATUS;
653     }
654 
655     return rc;
656 }
657 #endif
658 
659 /*
660  * This function is not used by the bootloader itself, but its required API
661  * by external tooling like mcumgr.
662  */
663 int
boot_swap_type(void)664 boot_swap_type(void)
665 {
666     return boot_swap_type_multi(0);
667 }
668 
669 /**
670  * Marks the image with the given index in the secondary slot as pending. On the
671  * next reboot, the system will perform a one-time boot of the the secondary
672  * slot image.
673  *
674  * @param image_index       Image pair index.
675  *
676  * @param permanent         Whether the image should be used permanently or
677  *                          only tested once:
678  *                               0=run image once, then confirm or revert.
679  *                               1=run image forever.
680  *
681  * @return                  0 on success; nonzero on failure.
682  */
683 int
boot_set_pending_multi(int image_index,int permanent)684 boot_set_pending_multi(int image_index, int permanent)
685 {
686     const struct flash_area *fap;
687     int rc;
688 
689     rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(image_index), &fap);
690     if (rc != 0) {
691         return BOOT_EFLASH;
692     }
693 
694     rc = boot_set_next(fap, false, !(permanent == 0));
695 
696     flash_area_close(fap);
697     return rc;
698 }
699 
700 /**
701  * Marks the image with index 0 in the secondary slot as pending. On the next
702  * reboot, the system will perform a one-time boot of the the secondary slot
703  * image. Note that this API is kept for compatibility. The
704  * boot_set_pending_multi() API is recommended.
705  *
706  * @param permanent         Whether the image should be used permanently or
707  *                          only tested once:
708  *                               0=run image once, then confirm or revert.
709  *                               1=run image forever.
710  *
711  * @return                  0 on success; nonzero on failure.
712  */
713 int
boot_set_pending(int permanent)714 boot_set_pending(int permanent)
715 {
716     return boot_set_pending_multi(0, permanent);
717 }
718 
719 /**
720  * Marks the image with the given index in the primary slot as confirmed.  The
721  * system will continue booting into the image in the primary slot until told to
722  * boot from a different slot.
723  *
724  * @param image_index       Image pair index.
725  *
726  * @return                  0 on success; nonzero on failure.
727  */
728 int
boot_set_confirmed_multi(int image_index)729 boot_set_confirmed_multi(int image_index)
730 {
731     const struct flash_area *fap = NULL;
732     int rc;
733 
734     rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(image_index), &fap);
735     if (rc != 0) {
736         return BOOT_EFLASH;
737     }
738 
739     rc = boot_set_next(fap, true, true);
740 
741     flash_area_close(fap);
742     return rc;
743 }
744 
745 /**
746  * Marks the image with index 0 in the primary slot as confirmed.  The system
747  * will continue booting into the image in the primary slot until told to boot
748  * from a different slot.  Note that this API is kept for compatibility. The
749  * boot_set_confirmed_multi() API is recommended.
750  *
751  * @return                  0 on success; nonzero on failure.
752  */
753 int
boot_set_confirmed(void)754 boot_set_confirmed(void)
755 {
756     return boot_set_confirmed_multi(0);
757 }
758 
759 int
boot_image_load_header(const struct flash_area * fa_p,struct image_header * hdr)760 boot_image_load_header(const struct flash_area *fa_p,
761                        struct image_header *hdr)
762 {
763     uint32_t size;
764     int rc = flash_area_read(fa_p, 0, hdr, sizeof *hdr);
765 
766     if (rc != 0) {
767         rc = BOOT_EFLASH;
768         BOOT_LOG_ERR("Failed reading image header");
769 	return BOOT_EFLASH;
770     }
771 
772     if (hdr->ih_magic != IMAGE_MAGIC) {
773         BOOT_LOG_ERR("Bad image magic 0x%lx", (unsigned long)hdr->ih_magic);
774 
775         return BOOT_EBADIMAGE;
776     }
777 
778     if (hdr->ih_flags & IMAGE_F_NON_BOOTABLE) {
779         BOOT_LOG_ERR("Image not bootable");
780 
781         return BOOT_EBADIMAGE;
782     }
783 
784     if (!boot_u32_safe_add(&size, hdr->ih_img_size, hdr->ih_hdr_size) ||
785         size >= flash_area_get_size(fa_p)) {
786         return BOOT_EBADIMAGE;
787     }
788 
789     return 0;
790 }
791