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