blob: 888118efb5bde2629451ccb125b457eaf96bff5a [file] [log] [blame]
Tamas Banf70ef8c2017-12-19 15:35:09 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
Tamas Ban581034a2017-12-19 19:54:37 +000020/*
Tamas Ban4fb8e9d2018-02-23 14:22:03 +000021 * Original code taken from mcuboot project at:
22 * https://github.com/runtimeco/mcuboot
23 * Modifications are Copyright (c) 2018 Arm Limited.
Tamas Ban581034a2017-12-19 19:54:37 +000024 */
25
Tamas Banf70ef8c2017-12-19 15:35:09 +000026/**
27 * This file provides an interface to the boot loader. Functions defined in
28 * this file should only be called while the boot loader is running.
29 */
30
31#include <assert.h>
32#include <stddef.h>
33#include <stdbool.h>
34#include <inttypes.h>
35#include <stdlib.h>
36#include <string.h>
Tamas Banc3828852018-02-01 12:24:16 +000037#include "flash_map/flash_map.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000038#include "bootutil/bootutil.h"
39#include "bootutil/image.h"
40#include "bootutil_priv.h"
Tamas Bana9de4a62018-09-18 08:09:45 +010041#include "bl2/include/tfm_boot_status.h"
42#include "bl2/include/boot_record.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000043
44#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
45#include "bootutil/bootutil_log.h"
46
Tamas Banf70ef8c2017-12-19 15:35:09 +000047static struct boot_loader_state boot_data;
48
Oliver Swedef9982442018-08-24 18:37:44 +010049#if !defined(MCUBOOT_NO_SWAP) && !defined(MCUBOOT_RAM_LOADING)
Tamas Banf70ef8c2017-12-19 15:35:09 +000050struct boot_status_table {
51 /**
52 * For each field, a value of 0 means "any".
53 */
54 uint8_t bst_magic_slot0;
55 uint8_t bst_magic_scratch;
56 uint8_t bst_copy_done_slot0;
57 uint8_t bst_status_source;
58};
59
60/**
61 * This set of tables maps swap state contents to boot status location.
62 * When searching for a match, these tables must be iterated in order.
63 */
64static const struct boot_status_table boot_status_tables[] = {
65 {
66 /* | slot-0 | scratch |
67 * ----------+------------+------------|
68 * magic | Good | Any |
69 * copy-done | 0x01 | N/A |
70 * ----------+------------+------------'
71 * source: none |
72 * ------------------------------------'
73 */
74 .bst_magic_slot0 = BOOT_MAGIC_GOOD,
75 .bst_magic_scratch = 0,
76 .bst_copy_done_slot0 = 0x01,
77 .bst_status_source = BOOT_STATUS_SOURCE_NONE,
78 },
79
80 {
81 /* | slot-0 | scratch |
82 * ----------+------------+------------|
83 * magic | Good | Any |
84 * copy-done | 0xff | N/A |
85 * ----------+------------+------------'
86 * source: slot 0 |
87 * ------------------------------------'
88 */
89 .bst_magic_slot0 = BOOT_MAGIC_GOOD,
90 .bst_magic_scratch = 0,
91 .bst_copy_done_slot0 = 0xff,
92 .bst_status_source = BOOT_STATUS_SOURCE_SLOT0,
93 },
94
95 {
96 /* | slot-0 | scratch |
97 * ----------+------------+------------|
98 * magic | Any | Good |
99 * copy-done | Any | N/A |
100 * ----------+------------+------------'
101 * source: scratch |
102 * ------------------------------------'
103 */
104 .bst_magic_slot0 = 0,
105 .bst_magic_scratch = BOOT_MAGIC_GOOD,
106 .bst_copy_done_slot0 = 0,
107 .bst_status_source = BOOT_STATUS_SOURCE_SCRATCH,
108 },
109
110 {
111 /* | slot-0 | scratch |
112 * ----------+------------+------------|
113 * magic | Unset | Any |
114 * copy-done | 0xff | N/A |
115 * ----------+------------+------------|
116 * source: varies |
117 * ------------------------------------+------------------------------+
118 * This represents one of two cases: |
119 * o No swaps ever (no status to read, so no harm in checking). |
120 * o Mid-revert; status in slot 0. |
121 * -------------------------------------------------------------------'
122 */
123 .bst_magic_slot0 = BOOT_MAGIC_UNSET,
124 .bst_magic_scratch = 0,
125 .bst_copy_done_slot0 = 0xff,
126 .bst_status_source = BOOT_STATUS_SOURCE_SLOT0,
127 },
128};
129
130#define BOOT_STATUS_TABLES_COUNT \
Tamas Ban581034a2017-12-19 19:54:37 +0000131 (sizeof(boot_status_tables) / sizeof(boot_status_tables[0]))
Tamas Banf70ef8c2017-12-19 15:35:09 +0000132
133#define BOOT_LOG_SWAP_STATE(area, state) \
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000134 BOOT_LOG_INF("%s: magic=%5s, copy_done=0x%x, image_ok=0x%x", \
Tamas Banf70ef8c2017-12-19 15:35:09 +0000135 (area), \
136 ((state)->magic == BOOT_MAGIC_GOOD ? "good" : \
137 (state)->magic == BOOT_MAGIC_UNSET ? "unset" : \
138 "bad"), \
139 (state)->copy_done, \
140 (state)->image_ok)
Oliver Swedef9982442018-08-24 18:37:44 +0100141#endif /* !MCUBOOT_NO_SWAP && !MCUBOOT_RAM_LOADING */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000142
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000143
144static int
145boot_read_image_header(int slot, struct image_header *out_hdr)
146{
147 const struct flash_area *fap = NULL;
148 int area_id;
149 int rc;
150
151 area_id = flash_area_id_from_image_slot(slot);
152 rc = flash_area_open(area_id, &fap);
153 if (rc != 0) {
154 rc = BOOT_EFLASH;
155 goto done;
156 }
157
158 rc = flash_area_read(fap, 0, out_hdr, sizeof(*out_hdr));
159 if (rc != 0) {
160 rc = BOOT_EFLASH;
161 goto done;
162 }
163
164 rc = 0;
165
166done:
167 flash_area_close(fap);
168 return rc;
169}
170
171static int
172boot_read_image_headers(void)
173{
174 int rc;
175 int i;
176
177 for (i = 0; i < BOOT_NUM_SLOTS; i++) {
178 rc = boot_read_image_header(i, boot_img_hdr(&boot_data, i));
179 if (rc != 0) {
180 /* If at least the first slot's header was read successfully, then
181 * the boot loader can attempt a boot. Failure to read any headers
182 * is a fatal error.
183 */
184 if (i > 0) {
185 return 0;
186 } else {
187 return rc;
188 }
189 }
190 }
191
192 return 0;
193}
194
195static uint8_t
196boot_write_sz(void)
197{
198 const struct flash_area *fap;
199 uint8_t elem_sz;
200 uint8_t align;
201 int rc;
202
203 /* Figure out what size to write update status update as. The size depends
204 * on what the minimum write size is for scratch area, active image slot.
205 * We need to use the bigger of those 2 values.
206 */
207 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
208 assert(rc == 0);
209 elem_sz = flash_area_align(fap);
210 flash_area_close(fap);
211
212 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
213 assert(rc == 0);
214 align = flash_area_align(fap);
215 flash_area_close(fap);
216
217 if (align > elem_sz) {
218 elem_sz = align;
219 }
220
221 return elem_sz;
222}
223
224/**
225 * Determines the sector layout of both image slots and the scratch area.
226 * This information is necessary for calculating the number of bytes to erase
227 * and copy during an image swap. The information collected during this
228 * function is used to populate the boot_data global.
229 */
230static int
231boot_read_sectors(void)
232{
233 int rc;
234
235 rc = boot_initialize_area(&boot_data, FLASH_AREA_IMAGE_0);
236 if (rc != 0) {
237 return BOOT_EFLASH;
238 }
239
240 rc = boot_initialize_area(&boot_data, FLASH_AREA_IMAGE_1);
241 if (rc != 0) {
242 return BOOT_EFLASH;
243 }
244
245 BOOT_WRITE_SZ(&boot_data) = boot_write_sz();
246
247 return 0;
248}
249
250/*
251 * Validate image hash/signature in a slot.
252 */
253static int
Tamas Bana9de4a62018-09-18 08:09:45 +0100254boot_image_check(struct image_header *hdr, const struct flash_area *fap, uint8_t *out_hash)
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000255{
256 static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
257
258 if (bootutil_img_validate(hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
Tamas Bana9de4a62018-09-18 08:09:45 +0100259 NULL, 0, out_hash)) {
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000260 return BOOT_EBADIMAGE;
261 }
262 return 0;
263}
264
265static int
266boot_validate_slot(int slot)
267{
268 const struct flash_area *fap;
269 struct image_header *hdr;
Tamas Bana9de4a62018-09-18 08:09:45 +0100270 uint8_t hash[32];
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000271 int rc;
272
273 hdr = boot_img_hdr(&boot_data, slot);
274 if (hdr->ih_magic == 0xffffffff || hdr->ih_flags & IMAGE_F_NON_BOOTABLE) {
275 /* No bootable image in slot; continue booting from slot 0. */
276 return -1;
277 }
278
279 rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap);
280 if (rc != 0) {
281 return BOOT_EFLASH;
282 }
283
Tamas Bana9de4a62018-09-18 08:09:45 +0100284 if ((hdr->ih_magic != IMAGE_MAGIC ||
285 boot_image_check(hdr, fap, hash) != 0)) {
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000286 if (slot != 0) {
David Vincze26e8c8a2018-08-28 16:59:41 +0200287 rc = flash_area_erase(fap, 0, fap->fa_size);
288 if(rc != 0) {
289 flash_area_close(fap);
290 return BOOT_EFLASH;
291 }
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000292 /* Image in slot 1 is invalid. Erase the image and
293 * continue booting from slot 0.
294 */
295 }
296 BOOT_LOG_ERR("Authentication failed! Image in slot %d is not valid.",
297 slot);
298 return -1;
Tamas Bana9de4a62018-09-18 08:09:45 +0100299 } else {
300 if (0 != boot_add_data_to_shared_area(TLV_MAJOR_IAS,
301 TLV_MINOR_IAS_S_NS_SHA256,
302 sizeof(hash),
303 hash)) {
304 BOOT_LOG_ERR("Failed to add data to shared area");
305 }
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000306 }
307
308 flash_area_close(fap);
309
310 /* Image in slot 1 is valid. */
311 return 0;
312}
313
Oliver Swedef9982442018-08-24 18:37:44 +0100314#if !defined(MCUBOOT_NO_SWAP) && !defined(MCUBOOT_OVERWRITE_ONLY)
315/*
316 * Compute the total size of the given image. Includes the size of
317 * the TLVs.
318 */
319static int
320boot_read_image_size(int slot, struct image_header *hdr, uint32_t *size)
321{
322 const struct flash_area *fap = NULL;
323 struct image_tlv_info info;
324 int area_id;
325 int rc;
326
327 area_id = flash_area_id_from_image_slot(slot);
328 rc = flash_area_open(area_id, &fap);
329 if (rc != 0) {
330 rc = BOOT_EFLASH;
331 goto done;
332 }
333
334 rc = flash_area_read(fap, hdr->ih_hdr_size + hdr->ih_img_size,
335 &info, sizeof(info));
336 if (rc != 0) {
337 rc = BOOT_EFLASH;
338 goto done;
339 }
340 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
341 rc = BOOT_EBADIMAGE;
342 goto done;
343 }
344 *size = hdr->ih_hdr_size + hdr->ih_img_size + info.it_tlv_tot;
345 rc = 0;
346
347done:
348 flash_area_close(fap);
349 return rc;
350}
351#endif /* !MCUBOOT_NO_SWAP && !MCUBOOT_OVERWRITE_ONLY */
352
353#if !defined(MCUBOOT_NO_SWAP) && !defined(MCUBOOT_RAM_LOADING)
Tamas Banf70ef8c2017-12-19 15:35:09 +0000354/**
Tamas Ban581034a2017-12-19 19:54:37 +0000355 * Determines where in flash the most recent boot status is stored. The boot
Tamas Banf70ef8c2017-12-19 15:35:09 +0000356 * status is necessary for completing a swap that was interrupted by a boot
357 * loader reset.
358 *
Tamas Ban581034a2017-12-19 19:54:37 +0000359 * @return BOOT_STATUS_SOURCE_[...] code indicating where
360 * status should be read from.
Tamas Banf70ef8c2017-12-19 15:35:09 +0000361 */
362static int
363boot_status_source(void)
364{
365 const struct boot_status_table *table;
366 struct boot_swap_state state_scratch;
367 struct boot_swap_state state_slot0;
368 int rc;
369 int i;
370 uint8_t source;
371
372 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
373 assert(rc == 0);
374
375 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SCRATCH, &state_scratch);
376 assert(rc == 0);
377
378 BOOT_LOG_SWAP_STATE("Image 0", &state_slot0);
379 BOOT_LOG_SWAP_STATE("Scratch", &state_scratch);
380
381 for (i = 0; i < BOOT_STATUS_TABLES_COUNT; i++) {
382 table = &boot_status_tables[i];
383
384 if ((table->bst_magic_slot0 == 0 ||
385 table->bst_magic_slot0 == state_slot0.magic) &&
386 (table->bst_magic_scratch == 0 ||
387 table->bst_magic_scratch == state_scratch.magic) &&
388 (table->bst_copy_done_slot0 == 0 ||
389 table->bst_copy_done_slot0 == state_slot0.copy_done)) {
390 source = table->bst_status_source;
391 BOOT_LOG_INF("Boot source: %s",
392 source == BOOT_STATUS_SOURCE_NONE ? "none" :
393 source == BOOT_STATUS_SOURCE_SCRATCH ? "scratch" :
394 source == BOOT_STATUS_SOURCE_SLOT0 ? "slot 0" :
395 "BUG; can't happen");
396 return source;
397 }
398 }
399
400 BOOT_LOG_INF("Boot source: none");
401 return BOOT_STATUS_SOURCE_NONE;
402}
403
404/**
405 * Calculates the type of swap that just completed.
406 *
407 * This is used when a swap is interrupted by an external event. After
408 * finishing the swap operation determines what the initial request was.
409 */
410static int
411boot_previous_swap_type(void)
412{
413 int post_swap_type;
414
415 post_swap_type = boot_swap_type();
416
417 switch (post_swap_type) {
Tamas Ban581034a2017-12-19 19:54:37 +0000418 case BOOT_SWAP_TYPE_NONE: return BOOT_SWAP_TYPE_PERM;
419 case BOOT_SWAP_TYPE_REVERT: return BOOT_SWAP_TYPE_TEST;
420 case BOOT_SWAP_TYPE_PANIC: return BOOT_SWAP_TYPE_PANIC;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000421 }
422
423 return BOOT_SWAP_TYPE_FAIL;
424}
425
Tamas Banf70ef8c2017-12-19 15:35:09 +0000426static int
Tamas Banf70ef8c2017-12-19 15:35:09 +0000427boot_slots_compatible(void)
428{
429 size_t num_sectors_0 = boot_img_num_sectors(&boot_data, 0);
430 size_t num_sectors_1 = boot_img_num_sectors(&boot_data, 1);
431 size_t size_0, size_1;
432 size_t i;
433
434 /* Ensure both image slots have identical sector layouts. */
435 if (num_sectors_0 != num_sectors_1) {
436 return 0;
437 }
438 for (i = 0; i < num_sectors_0; i++) {
439 size_0 = boot_img_sector_size(&boot_data, 0, i);
440 size_1 = boot_img_sector_size(&boot_data, 1, i);
441 if (size_0 != size_1) {
442 return 0;
443 }
444 }
445
446 return 1;
447}
448
Tamas Banf70ef8c2017-12-19 15:35:09 +0000449
450static uint32_t
451boot_status_internal_off(int idx, int state, int elem_sz)
452{
453 int idx_sz;
454
455 idx_sz = elem_sz * BOOT_STATUS_STATE_COUNT;
456
457 return idx * idx_sz + state * elem_sz;
458}
459
460/**
461 * Reads the status of a partially-completed swap, if any. This is necessary
462 * to recover in case the boot lodaer was reset in the middle of a swap
463 * operation.
464 */
465static int
466boot_read_status_bytes(const struct flash_area *fap, struct boot_status *bs)
467{
468 uint32_t off;
469 uint8_t status;
470 int max_entries;
471 int found;
472 int rc;
473 int i;
474
475 off = boot_status_off(fap);
476 max_entries = boot_status_entries(fap);
477
478 found = 0;
479 for (i = 0; i < max_entries; i++) {
480 rc = flash_area_read(fap, off + i * BOOT_WRITE_SZ(&boot_data),
481 &status, 1);
482 if (rc != 0) {
483 return BOOT_EFLASH;
484 }
485
486 if (status == 0xff) {
487 if (found) {
488 break;
489 }
490 } else if (!found) {
491 found = 1;
492 }
493 }
494
495 if (found) {
496 i--;
497 bs->idx = i / BOOT_STATUS_STATE_COUNT;
498 bs->state = i % BOOT_STATUS_STATE_COUNT;
499 }
500
501 return 0;
502}
503
504/**
505 * Reads the boot status from the flash. The boot status contains
506 * the current state of an interrupted image copy operation. If the boot
507 * status is not present, or it indicates that previous copy finished,
508 * there is no operation in progress.
509 */
510static int
511boot_read_status(struct boot_status *bs)
512{
513 const struct flash_area *fap;
514 int status_loc;
515 int area_id;
516 int rc;
517
Tamas Ban581034a2017-12-19 19:54:37 +0000518 memset(bs, 0, sizeof(*bs));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000519
520 status_loc = boot_status_source();
521 switch (status_loc) {
522 case BOOT_STATUS_SOURCE_NONE:
523 return 0;
524
525 case BOOT_STATUS_SOURCE_SCRATCH:
526 area_id = FLASH_AREA_IMAGE_SCRATCH;
527 break;
528
529 case BOOT_STATUS_SOURCE_SLOT0:
530 area_id = FLASH_AREA_IMAGE_0;
531 break;
532
533 default:
534 assert(0);
535 return BOOT_EBADARGS;
536 }
537
538 rc = flash_area_open(area_id, &fap);
539 if (rc != 0) {
540 return BOOT_EFLASH;
541 }
542
543 rc = boot_read_status_bytes(fap, bs);
544
545 flash_area_close(fap);
546 return rc;
547}
548
549/**
550 * Writes the supplied boot status to the flash file system. The boot status
551 * contains the current state of an in-progress image copy operation.
552 *
553 * @param bs The boot status to write.
554 *
555 * @return 0 on success; nonzero on failure.
556 */
557int
558boot_write_status(struct boot_status *bs)
559{
Tamas Ban581034a2017-12-19 19:54:37 +0000560 const struct flash_area *fap = NULL;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000561 uint32_t off;
562 int area_id;
563 int rc;
564 uint8_t buf[BOOT_MAX_ALIGN];
565 uint8_t align;
566
567 /* NOTE: The first sector copied (that is the last sector on slot) contains
568 * the trailer. Since in the last step SLOT 0 is erased, the first
569 * two status writes go to the scratch which will be copied to SLOT 0!
570 */
571
572 if (bs->use_scratch) {
573 /* Write to scratch. */
574 area_id = FLASH_AREA_IMAGE_SCRATCH;
575 } else {
576 /* Write to slot 0. */
577 area_id = FLASH_AREA_IMAGE_0;
578 }
579
580 rc = flash_area_open(area_id, &fap);
581 if (rc != 0) {
582 rc = BOOT_EFLASH;
583 goto done;
584 }
585
586 off = boot_status_off(fap) +
587 boot_status_internal_off(bs->idx, bs->state,
588 BOOT_WRITE_SZ(&boot_data));
589
Tamas Banc3828852018-02-01 12:24:16 +0000590 align = flash_area_align(fap);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000591 memset(buf, 0xFF, BOOT_MAX_ALIGN);
592 buf[0] = bs->state;
593
594 rc = flash_area_write(fap, off, buf, align);
595 if (rc != 0) {
596 rc = BOOT_EFLASH;
597 goto done;
598 }
599
600 rc = 0;
601
602done:
603 flash_area_close(fap);
604 return rc;
605}
606
Tamas Banf70ef8c2017-12-19 15:35:09 +0000607/**
608 * Determines which swap operation to perform, if any. If it is determined
609 * that a swap operation is required, the image in the second slot is checked
610 * for validity. If the image in the second slot is invalid, it is erased, and
611 * a swap type of "none" is indicated.
612 *
613 * @return The type of swap to perform (BOOT_SWAP_TYPE...)
614 */
615static int
616boot_validated_swap_type(void)
617{
618 int swap_type;
619
620 swap_type = boot_swap_type();
621 switch (swap_type) {
622 case BOOT_SWAP_TYPE_TEST:
623 case BOOT_SWAP_TYPE_PERM:
624 case BOOT_SWAP_TYPE_REVERT:
625 /* Boot loader wants to switch to slot 1. Ensure image is valid. */
626 if (boot_validate_slot(1) != 0) {
627 swap_type = BOOT_SWAP_TYPE_FAIL;
628 }
629 }
630
631 return swap_type;
632}
633
634/**
635 * Calculates the number of sectors the scratch area can contain. A "last"
636 * source sector is specified because images are copied backwards in flash
637 * (final index to index number 0).
638 *
639 * @param last_sector_idx The index of the last source sector
640 * (inclusive).
641 * @param out_first_sector_idx The index of the first source sector
642 * (inclusive) gets written here.
643 *
644 * @return The number of bytes comprised by the
645 * [first-sector, last-sector] range.
646 */
647#ifndef MCUBOOT_OVERWRITE_ONLY
648static uint32_t
649boot_copy_sz(int last_sector_idx, int *out_first_sector_idx)
650{
651 size_t scratch_sz;
652 uint32_t new_sz;
653 uint32_t sz;
654 int i;
655
656 sz = 0;
657
658 scratch_sz = boot_scratch_area_size(&boot_data);
659 for (i = last_sector_idx; i >= 0; i--) {
660 new_sz = sz + boot_img_sector_size(&boot_data, 0, i);
661 if (new_sz > scratch_sz) {
662 break;
663 }
664 sz = new_sz;
665 }
666
667 /* i currently refers to a sector that doesn't fit or it is -1 because all
668 * sectors have been processed. In both cases, exclude sector i.
669 */
670 *out_first_sector_idx = i + 1;
671 return sz;
672}
673#endif /* !MCUBOOT_OVERWRITE_ONLY */
674
675/**
David Vinczef7641fa2018-09-04 18:29:46 +0200676 * Erases a region of flash.
677 *
678 * @param flash_area_idx The ID of the flash area containing the region
679 * to erase.
680 * @param off The offset within the flash area to start the
681 * erase.
682 * @param sz The number of bytes to erase.
683 *
684 * @return 0 on success; nonzero on failure.
685 */
686static int
687boot_erase_sector(int flash_area_id, uint32_t off, uint32_t sz)
688{
689 const struct flash_area *fap = NULL;
690 int rc;
691
692 rc = flash_area_open(flash_area_id, &fap);
693 if (rc != 0) {
694 rc = BOOT_EFLASH;
695 goto done;
696 }
697
698 rc = flash_area_erase(fap, off, sz);
699 if (rc != 0) {
700 rc = BOOT_EFLASH;
701 goto done;
702 }
703
704 rc = 0;
705
706done:
707 flash_area_close(fap);
708 return rc;
709}
710
711/**
Tamas Banf70ef8c2017-12-19 15:35:09 +0000712 * Copies the contents of one flash region to another. You must erase the
713 * destination region prior to calling this function.
714 *
715 * @param flash_area_id_src The ID of the source flash area.
716 * @param flash_area_id_dst The ID of the destination flash area.
717 * @param off_src The offset within the source flash area to
718 * copy from.
719 * @param off_dst The offset within the destination flash area to
720 * copy to.
721 * @param sz The number of bytes to copy.
722 *
723 * @return 0 on success; nonzero on failure.
724 */
725static int
726boot_copy_sector(int flash_area_id_src, int flash_area_id_dst,
727 uint32_t off_src, uint32_t off_dst, uint32_t sz)
728{
729 const struct flash_area *fap_src;
730 const struct flash_area *fap_dst;
731 uint32_t bytes_copied;
732 int chunk_sz;
733 int rc;
734
735 static uint8_t buf[1024];
736
737 fap_src = NULL;
738 fap_dst = NULL;
739
740 rc = flash_area_open(flash_area_id_src, &fap_src);
741 if (rc != 0) {
742 rc = BOOT_EFLASH;
743 goto done;
744 }
745
746 rc = flash_area_open(flash_area_id_dst, &fap_dst);
747 if (rc != 0) {
748 rc = BOOT_EFLASH;
749 goto done;
750 }
751
752 bytes_copied = 0;
753 while (bytes_copied < sz) {
Tamas Ban581034a2017-12-19 19:54:37 +0000754 if (sz - bytes_copied > sizeof(buf)) {
755 chunk_sz = sizeof(buf);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000756 } else {
757 chunk_sz = sz - bytes_copied;
758 }
759
760 rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz);
761 if (rc != 0) {
762 rc = BOOT_EFLASH;
763 goto done;
764 }
765
766 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
767 if (rc != 0) {
768 rc = BOOT_EFLASH;
769 goto done;
770 }
771
772 bytes_copied += chunk_sz;
773 }
774
775 rc = 0;
776
777done:
778 if (fap_src) {
779 flash_area_close(fap_src);
780 }
781 if (fap_dst) {
782 flash_area_close(fap_dst);
783 }
784 return rc;
785}
786
787#ifndef MCUBOOT_OVERWRITE_ONLY
788static inline int
789boot_status_init_by_id(int flash_area_id, const struct boot_status *bs)
790{
791 const struct flash_area *fap;
792 struct boot_swap_state swap_state;
793 int rc;
794
795 rc = flash_area_open(flash_area_id, &fap);
796 assert(rc == 0);
797
798 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &swap_state);
799 assert(rc == 0);
800
801 if (swap_state.image_ok == BOOT_FLAG_SET) {
802 rc = boot_write_image_ok(fap);
803 assert(rc == 0);
804 }
805
806 rc = boot_write_swap_size(fap, bs->swap_size);
807 assert(rc == 0);
808
809 rc = boot_write_magic(fap);
810 assert(rc == 0);
811
812 flash_area_close(fap);
813
814 return 0;
815}
David Vinczef7641fa2018-09-04 18:29:46 +0200816
817static int
818boot_erase_last_sector_by_id(int flash_area_id)
819{
820 uint8_t slot;
821 uint32_t last_sector;
822 int rc;
823
824 switch (flash_area_id) {
825 case FLASH_AREA_IMAGE_0:
826 slot = 0;
827 break;
828 case FLASH_AREA_IMAGE_1:
829 slot = 1;
830 break;
831 default:
832 return BOOT_EFLASH;
833 }
834
835 last_sector = boot_img_num_sectors(&boot_data, slot) - 1;
836 rc = boot_erase_sector(flash_area_id,
837 boot_img_sector_off(&boot_data, slot, last_sector),
838 boot_img_sector_size(&boot_data, slot, last_sector));
839 assert(rc == 0);
840
841 return rc;
842}
843#endif /* !MCUBOOT_OVERWRITE_ONLY */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000844
Tamas Banf70ef8c2017-12-19 15:35:09 +0000845/**
846 * Swaps the contents of two flash regions within the two image slots.
847 *
848 * @param idx The index of the first sector in the range of
849 * sectors being swapped.
850 * @param sz The number of bytes to swap.
851 * @param bs The current boot status. This struct gets
852 * updated according to the outcome.
853 *
854 * @return 0 on success; nonzero on failure.
855 */
856#ifndef MCUBOOT_OVERWRITE_ONLY
857static void
858boot_swap_sectors(int idx, uint32_t sz, struct boot_status *bs)
859{
860 const struct flash_area *fap;
861 uint32_t copy_sz;
862 uint32_t trailer_sz;
863 uint32_t img_off;
864 uint32_t scratch_trailer_off;
865 struct boot_swap_state swap_state;
866 size_t last_sector;
867 int rc;
868
869 /* Calculate offset from start of image area. */
870 img_off = boot_img_sector_off(&boot_data, 0, idx);
871
872 copy_sz = sz;
873 trailer_sz = boot_slots_trailer_sz(BOOT_WRITE_SZ(&boot_data));
874
875 /* sz in this function is always is always sized on a multiple of the
876 * sector size. The check against the start offset of the last sector
877 * is to determine if we're swapping the last sector. The last sector
878 * needs special handling because it's where the trailer lives. If we're
879 * copying it, we need to use scratch to write the trailer temporarily.
880 *
881 * NOTE: `use_scratch` is a temporary flag (never written to flash) which
882 * controls if special handling is needed (swapping last sector).
883 */
884 last_sector = boot_img_num_sectors(&boot_data, 0) - 1;
885 if (img_off + sz > boot_img_sector_off(&boot_data, 0, last_sector)) {
886 copy_sz -= trailer_sz;
887 }
888
889 bs->use_scratch = (bs->idx == 0 && copy_sz != sz);
890
891 if (bs->state == 0) {
892 rc = boot_erase_sector(FLASH_AREA_IMAGE_SCRATCH, 0, sz);
893 assert(rc == 0);
894
895 rc = boot_copy_sector(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_SCRATCH,
896 img_off, 0, copy_sz);
897 assert(rc == 0);
898
899 if (bs->idx == 0) {
900 if (bs->use_scratch) {
901 boot_status_init_by_id(FLASH_AREA_IMAGE_SCRATCH, bs);
902 } else {
903 /* Prepare the status area... here it is known that the
904 * last sector is not being used by the image data so it's
905 * safe to erase.
906 */
907 rc = boot_erase_last_sector_by_id(FLASH_AREA_IMAGE_0);
908 assert(rc == 0);
909
910 boot_status_init_by_id(FLASH_AREA_IMAGE_0, bs);
911 }
912 }
913
914 bs->state = 1;
915 rc = boot_write_status(bs);
916 assert(rc == 0);
917 }
918
919 if (bs->state == 1) {
920 rc = boot_erase_sector(FLASH_AREA_IMAGE_1, img_off, sz);
921 assert(rc == 0);
922
923 rc = boot_copy_sector(FLASH_AREA_IMAGE_0, FLASH_AREA_IMAGE_1,
924 img_off, img_off, copy_sz);
925 assert(rc == 0);
926
927 if (bs->idx == 0 && !bs->use_scratch) {
928 /* If not all sectors of the slot are being swapped,
929 * guarantee here that only slot0 will have the state.
930 */
931 rc = boot_erase_last_sector_by_id(FLASH_AREA_IMAGE_1);
932 assert(rc == 0);
933 }
934
935 bs->state = 2;
936 rc = boot_write_status(bs);
937 assert(rc == 0);
938 }
939
940 if (bs->state == 2) {
941 rc = boot_erase_sector(FLASH_AREA_IMAGE_0, img_off, sz);
942 assert(rc == 0);
943
944 /* NOTE: also copy trailer from scratch (has status info) */
945 rc = boot_copy_sector(FLASH_AREA_IMAGE_SCRATCH, FLASH_AREA_IMAGE_0,
946 0, img_off, copy_sz);
947 assert(rc == 0);
948
949 if (bs->use_scratch) {
950 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
951 assert(rc == 0);
952
953 scratch_trailer_off = boot_status_off(fap);
954
955 flash_area_close(fap);
956
957 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
958 assert(rc == 0);
959
960 /* copy current status that is being maintained in scratch */
961 rc = boot_copy_sector(FLASH_AREA_IMAGE_SCRATCH, FLASH_AREA_IMAGE_0,
962 scratch_trailer_off,
963 img_off + copy_sz,
964 BOOT_STATUS_STATE_COUNT * BOOT_WRITE_SZ(&boot_data));
965 assert(rc == 0);
966
967 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SCRATCH,
968 &swap_state);
969 assert(rc == 0);
970
971 if (swap_state.image_ok == BOOT_FLAG_SET) {
972 rc = boot_write_image_ok(fap);
973 assert(rc == 0);
974 }
975
976 rc = boot_write_swap_size(fap, bs->swap_size);
977 assert(rc == 0);
978
979 rc = boot_write_magic(fap);
980 assert(rc == 0);
981
982 flash_area_close(fap);
983 }
984
985 bs->idx++;
986 bs->state = 0;
987 bs->use_scratch = 0;
988 rc = boot_write_status(bs);
989 assert(rc == 0);
990 }
991}
992#endif /* !MCUBOOT_OVERWRITE_ONLY */
993
994/**
995 * Swaps the two images in flash. If a prior copy operation was interrupted
996 * by a system reset, this function completes that operation.
997 *
998 * @param bs The current boot status. This function reads
999 * this struct to determine if it is resuming
1000 * an interrupted swap operation. This
1001 * function writes the updated status to this
1002 * function on return.
1003 *
1004 * @return 0 on success; nonzero on failure.
1005 */
1006#ifdef MCUBOOT_OVERWRITE_ONLY
1007static int
1008boot_copy_image(struct boot_status *bs)
1009{
1010 size_t sect_count;
1011 size_t sect;
1012 int rc;
1013 size_t size = 0;
1014 size_t this_size;
1015
1016 BOOT_LOG_INF("Image upgrade slot1 -> slot0");
1017 BOOT_LOG_INF("Erasing slot0");
1018
1019 sect_count = boot_img_num_sectors(&boot_data, 0);
1020 for (sect = 0; sect < sect_count; sect++) {
1021 this_size = boot_img_sector_size(&boot_data, 0, sect);
1022 rc = boot_erase_sector(FLASH_AREA_IMAGE_0,
1023 size,
1024 this_size);
1025 assert(rc == 0);
1026
1027 size += this_size;
1028 }
1029
1030 BOOT_LOG_INF("Copying slot 1 to slot 0: 0x%lx bytes", size);
1031 rc = boot_copy_sector(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_0,
1032 0, 0, size);
1033
1034 /* Erase slot 1 so that we don't do the upgrade on every boot.
1035 * TODO: Perhaps verify slot 0's signature again? */
1036 rc = boot_erase_sector(FLASH_AREA_IMAGE_1,
1037 0, boot_img_sector_size(&boot_data, 1, 0));
1038 assert(rc == 0);
1039
1040 return 0;
1041}
1042#else
1043static int
1044boot_copy_image(struct boot_status *bs)
1045{
1046 uint32_t sz;
1047 int first_sector_idx;
1048 int last_sector_idx;
1049 int swap_idx;
1050 struct image_header *hdr;
1051 uint32_t size;
1052 uint32_t copy_size;
1053 int rc;
1054
1055 /* FIXME: just do this if asked by user? */
1056
1057 size = copy_size = 0;
1058
1059 if (bs->idx == 0 && bs->state == 0) {
1060 /*
1061 * No swap ever happened, so need to find the largest image which
1062 * will be used to determine the amount of sectors to swap.
1063 */
1064 hdr = boot_img_hdr(&boot_data, 0);
1065 if (hdr->ih_magic == IMAGE_MAGIC) {
1066 rc = boot_read_image_size(0, hdr, &copy_size);
1067 assert(rc == 0);
1068 }
1069
1070 hdr = boot_img_hdr(&boot_data, 1);
1071 if (hdr->ih_magic == IMAGE_MAGIC) {
1072 rc = boot_read_image_size(1, hdr, &size);
1073 assert(rc == 0);
1074 }
1075
1076 if (size > copy_size) {
1077 copy_size = size;
1078 }
1079
1080 bs->swap_size = copy_size;
1081 } else {
1082 /*
1083 * If a swap was under way, the swap_size should already be present
1084 * in the trailer...
1085 */
1086 rc = boot_read_swap_size(&bs->swap_size);
1087 assert(rc == 0);
1088
1089 copy_size = bs->swap_size;
1090 }
1091
1092 size = 0;
1093 last_sector_idx = 0;
1094 while (1) {
1095 size += boot_img_sector_size(&boot_data, 0, last_sector_idx);
1096 if (size >= copy_size) {
1097 break;
1098 }
1099 last_sector_idx++;
1100 }
1101
1102 swap_idx = 0;
1103 while (last_sector_idx >= 0) {
1104 sz = boot_copy_sz(last_sector_idx, &first_sector_idx);
1105 if (swap_idx >= bs->idx) {
1106 boot_swap_sectors(first_sector_idx, sz, bs);
1107 }
1108
1109 last_sector_idx = first_sector_idx - 1;
1110 swap_idx++;
1111 }
1112
1113 return 0;
1114}
1115#endif
1116
1117/**
1118 * Marks the image in slot 0 as fully copied.
1119 */
1120#ifndef MCUBOOT_OVERWRITE_ONLY
1121static int
1122boot_set_copy_done(void)
1123{
1124 const struct flash_area *fap;
1125 int rc;
1126
1127 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
1128 if (rc != 0) {
1129 return BOOT_EFLASH;
1130 }
1131
1132 rc = boot_write_copy_done(fap);
1133 flash_area_close(fap);
1134 return rc;
1135}
1136#endif /* !MCUBOOT_OVERWRITE_ONLY */
1137
1138/**
1139 * Marks a reverted image in slot 0 as confirmed. This is necessary to ensure
1140 * the status bytes from the image revert operation don't get processed on a
1141 * subsequent boot.
1142 *
1143 * NOTE: image_ok is tested before writing because if there's a valid permanent
1144 * image installed on slot0 and the new image to be upgrade to has a bad sig,
1145 * image_ok would be overwritten.
1146 */
1147#ifndef MCUBOOT_OVERWRITE_ONLY
1148static int
1149boot_set_image_ok(void)
1150{
1151 const struct flash_area *fap;
1152 struct boot_swap_state state;
1153 int rc;
1154
1155 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
1156 if (rc != 0) {
1157 return BOOT_EFLASH;
1158 }
1159
1160 rc = boot_read_swap_state(fap, &state);
1161 if (rc != 0) {
1162 rc = BOOT_EFLASH;
1163 goto out;
1164 }
1165
1166 if (state.image_ok == BOOT_FLAG_UNSET) {
1167 rc = boot_write_image_ok(fap);
1168 }
1169
1170out:
1171 flash_area_close(fap);
1172 return rc;
1173}
1174#endif /* !MCUBOOT_OVERWRITE_ONLY */
1175
1176/**
1177 * Performs an image swap if one is required.
1178 *
1179 * @param out_swap_type On success, the type of swap performed gets
1180 * written here.
1181 *
1182 * @return 0 on success; nonzero on failure.
1183 */
1184static int
1185boot_swap_if_needed(int *out_swap_type)
1186{
1187 struct boot_status bs;
1188 int swap_type;
1189 int rc;
1190
1191 /* Determine if we rebooted in the middle of an image swap
1192 * operation.
1193 */
1194 rc = boot_read_status(&bs);
1195 assert(rc == 0);
1196 if (rc != 0) {
1197 return rc;
1198 }
1199
1200 /* If a partial swap was detected, complete it. */
1201 if (bs.idx != 0 || bs.state != 0) {
1202 rc = boot_copy_image(&bs);
1203 assert(rc == 0);
1204
1205 /* NOTE: here we have finished a swap resume. The initial request
1206 * was either a TEST or PERM swap, which now after the completed
1207 * swap will be determined to be respectively REVERT (was TEST)
1208 * or NONE (was PERM).
1209 */
1210
1211 /* Extrapolate the type of the partial swap. We need this
1212 * information to know how to mark the swap complete in flash.
1213 */
1214 swap_type = boot_previous_swap_type();
1215 } else {
1216 swap_type = boot_validated_swap_type();
1217 switch (swap_type) {
1218 case BOOT_SWAP_TYPE_TEST:
1219 case BOOT_SWAP_TYPE_PERM:
1220 case BOOT_SWAP_TYPE_REVERT:
1221 rc = boot_copy_image(&bs);
1222 assert(rc == 0);
1223 break;
1224 }
1225 }
1226
1227 *out_swap_type = swap_type;
1228 return 0;
1229}
1230
1231/**
1232 * Prepares the booting process. This function moves images around in flash as
1233 * appropriate, and tells you what address to boot from.
1234 *
1235 * @param rsp On success, indicates how booting should occur.
1236 *
1237 * @return 0 on success; nonzero on failure.
1238 */
1239int
1240boot_go(struct boot_rsp *rsp)
1241{
1242 int swap_type;
1243 size_t slot;
1244 int rc;
1245 int fa_id;
1246 bool reload_headers = false;
1247
1248 /* The array of slot sectors are defined here (as opposed to file scope) so
1249 * that they don't get allocated for non-boot-loader apps. This is
1250 * necessary because the gcc option "-fdata-sections" doesn't seem to have
1251 * any effect in older gcc versions (e.g., 4.8.4).
1252 */
1253 static boot_sector_t slot0_sectors[BOOT_MAX_IMG_SECTORS];
1254 static boot_sector_t slot1_sectors[BOOT_MAX_IMG_SECTORS];
Tamas Ban581034a2017-12-19 19:54:37 +00001255
Tamas Banf70ef8c2017-12-19 15:35:09 +00001256 boot_data.imgs[0].sectors = slot0_sectors;
1257 boot_data.imgs[1].sectors = slot1_sectors;
1258
1259 /* Open boot_data image areas for the duration of this call. */
1260 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1261 fa_id = flash_area_id_from_image_slot(slot);
1262 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot));
1263 assert(rc == 0);
1264 }
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001265
Tamas Banf70ef8c2017-12-19 15:35:09 +00001266 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
1267 &BOOT_SCRATCH_AREA(&boot_data));
1268 assert(rc == 0);
1269
1270 /* Determine the sector layout of the image slots and scratch area. */
1271 rc = boot_read_sectors();
1272 if (rc != 0) {
1273 goto out;
1274 }
1275
1276 /* Attempt to read an image header from each slot. */
1277 rc = boot_read_image_headers();
1278 if (rc != 0) {
1279 goto out;
1280 }
1281
1282 /* If the image slots aren't compatible, no swap is possible. Just boot
1283 * into slot 0.
1284 */
1285 if (boot_slots_compatible()) {
1286 rc = boot_swap_if_needed(&swap_type);
1287 assert(rc == 0);
1288 if (rc != 0) {
1289 goto out;
1290 }
1291
1292 /*
1293 * The following states need image_ok be explicitly set after the
1294 * swap was finished to avoid a new revert.
1295 */
Tamas Ban581034a2017-12-19 19:54:37 +00001296 if (swap_type == BOOT_SWAP_TYPE_REVERT ||
1297 swap_type == BOOT_SWAP_TYPE_FAIL) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001298#ifndef MCUBOOT_OVERWRITE_ONLY
1299 rc = boot_set_image_ok();
1300 if (rc != 0) {
1301 swap_type = BOOT_SWAP_TYPE_PANIC;
1302 }
1303#endif /* !MCUBOOT_OVERWRITE_ONLY */
1304 }
1305 } else {
1306 swap_type = BOOT_SWAP_TYPE_NONE;
1307 }
1308
1309 switch (swap_type) {
1310 case BOOT_SWAP_TYPE_NONE:
1311 slot = 0;
1312 break;
1313
1314 case BOOT_SWAP_TYPE_TEST: /* fallthrough */
1315 case BOOT_SWAP_TYPE_PERM: /* fallthrough */
1316 case BOOT_SWAP_TYPE_REVERT:
1317 slot = 1;
1318 reload_headers = true;
1319#ifndef MCUBOOT_OVERWRITE_ONLY
1320 rc = boot_set_copy_done();
1321 if (rc != 0) {
1322 swap_type = BOOT_SWAP_TYPE_PANIC;
1323 }
1324#endif /* !MCUBOOT_OVERWRITE_ONLY */
1325 break;
1326
1327 case BOOT_SWAP_TYPE_FAIL:
1328 /* The image in slot 1 was invalid and is now erased. Ensure we don't
1329 * try to boot into it again on the next reboot. Do this by pretending
1330 * we just reverted back to slot 0.
1331 */
1332 slot = 0;
1333 reload_headers = true;
1334 break;
1335
1336 default:
1337 swap_type = BOOT_SWAP_TYPE_PANIC;
1338 }
1339
1340 if (swap_type == BOOT_SWAP_TYPE_PANIC) {
1341 BOOT_LOG_ERR("panic!");
1342 assert(0);
1343
1344 /* Loop forever... */
Tamas Ban581034a2017-12-19 19:54:37 +00001345 while (1)
1346 ;
Tamas Banf70ef8c2017-12-19 15:35:09 +00001347 }
1348
1349#ifdef MCUBOOT_VALIDATE_SLOT0
1350 if (reload_headers) {
1351 rc = boot_read_image_headers();
1352 if (rc != 0) {
1353 goto out;
1354 }
1355 /* Since headers were reloaded, it can be assumed we just performed a
1356 * swap or overwrite. Now the header info that should be used to
1357 * provide the data for the bootstrap, which previously was at Slot 1,
1358 * was updated to Slot 0.
1359 */
1360 slot = 0;
1361 }
1362
1363 rc = boot_validate_slot(0);
1364 assert(rc == 0);
1365 if (rc != 0) {
1366 rc = BOOT_EBADIMAGE;
1367 goto out;
1368 }
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001369#else /* MCUBOOT_VALIDATE_SLOT0 */
Tamas Banf70ef8c2017-12-19 15:35:09 +00001370 (void)reload_headers;
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001371#endif /* MCUBOOT_VALIDATE_SLOT0 */
Tamas Banf70ef8c2017-12-19 15:35:09 +00001372
1373 /* Always boot from the primary slot. */
1374 rsp->br_flash_dev_id = boot_img_fa_device_id(&boot_data, 0);
1375 rsp->br_image_off = boot_img_slot_off(&boot_data, 0);
1376 rsp->br_hdr = boot_img_hdr(&boot_data, slot);
1377
1378 out:
1379 flash_area_close(BOOT_SCRATCH_AREA(&boot_data));
1380 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1381 flash_area_close(BOOT_IMG_AREA(&boot_data, BOOT_NUM_SLOTS - 1 - slot));
1382 }
1383 return rc;
1384}
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001385
Oliver Swedef9982442018-08-24 18:37:44 +01001386#else /* MCUBOOT_NO_SWAP || MCUBOOT_RAM_LOADING */
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001387
1388#define BOOT_LOG_IMAGE_INFO(area, hdr, state) \
1389 BOOT_LOG_INF("Image %"PRIu32": version=%"PRIu8".%"PRIu8".%"PRIu16"" \
1390 ".%"PRIu32", magic=%5s, image_ok=0x%x", \
1391 (area), \
1392 (hdr)->ih_ver.iv_major, \
1393 (hdr)->ih_ver.iv_minor, \
1394 (hdr)->ih_ver.iv_revision, \
1395 (hdr)->ih_ver.iv_build_num, \
1396 ((state)->magic == BOOT_MAGIC_GOOD ? "good" : \
1397 (state)->magic == BOOT_MAGIC_UNSET ? "unset" : \
1398 "bad"), \
1399 (state)->image_ok)
1400
1401struct image_slot_version {
1402 uint64_t version;
1403 uint32_t slot_number;
1404};
1405
1406/**
1407 * Extract the version number from the image header. This function must be
1408 * ported if version number format has changed in the image header.
1409 *
1410 * @param hdr Pointer to an image header structure
1411 *
Oliver Swedef9982442018-08-24 18:37:44 +01001412 * @return Version number casted to uint64_t
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001413 */
1414static uint64_t
1415boot_get_version_number(struct image_header *hdr)
1416{
Oliver Swedef9982442018-08-24 18:37:44 +01001417 uint64_t version = 0;
1418 version |= (uint64_t)hdr->ih_ver.iv_major << (IMAGE_VER_MINOR_LENGTH
1419 + IMAGE_VER_REVISION_LENGTH
1420 + IMAGE_VER_BUILD_NUM_LENGTH);
1421 version |= (uint64_t)hdr->ih_ver.iv_minor << (IMAGE_VER_REVISION_LENGTH
1422 + IMAGE_VER_BUILD_NUM_LENGTH);
1423 version |= (uint64_t)hdr->ih_ver.iv_revision << IMAGE_VER_BUILD_NUM_LENGTH;
1424 version |= hdr->ih_ver.iv_build_num;
1425 return version;
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001426}
1427
1428/**
1429 * Comparator function for `qsort` to compare version numbers. This function
1430 * must be ported if version number format has changed in the image header.
1431 *
1432 * @param ver1 Pointer to an array element which holds the version number
1433 * @param ver2 Pointer to another array element which holds the version
1434 * number
1435 *
1436 * @return if version1 > version2 -1
1437 * if version1 == version2 0
1438 * if version1 < version2 1
1439 */
1440static int
1441boot_compare_version_numbers(const void *ver1, const void *ver2)
1442{
1443 if (((struct image_slot_version *)ver1)->version <
1444 ((struct image_slot_version *)ver2)->version) {
1445 return 1;
1446 }
1447
1448 if (((struct image_slot_version *)ver1)->version ==
1449 ((struct image_slot_version *)ver2)->version) {
1450 return 0;
1451 }
1452
1453 return -1;
1454}
1455
1456/**
1457 * Sort the available images based on the version number and puts them in
1458 * a list.
1459 *
1460 * @param boot_sequence A pointer to an array, whose aim is to carry
1461 * the boot order of candidate images.
1462 * @param slot_cnt The number of flash areas, which can contains firmware
1463 * images.
1464 *
1465 * @return The number of valid images.
1466 */
1467uint32_t
1468boot_get_boot_sequence(uint32_t *boot_sequence, uint32_t slot_cnt)
1469{
1470 struct boot_swap_state slot_state;
1471 struct image_header *hdr;
1472 struct image_slot_version image_versions[BOOT_NUM_SLOTS] = {{0}};
1473 uint32_t image_cnt = 0;
1474 uint32_t slot;
1475 int32_t rc;
1476 int32_t fa_id;
1477
1478 for (slot = 0; slot < slot_cnt; slot++) {
1479 hdr = boot_img_hdr(&boot_data, slot);
1480 fa_id = flash_area_id_from_image_slot(slot);
1481 rc = boot_read_swap_state_by_id(fa_id, &slot_state);
1482 if (rc != 0) {
1483 BOOT_LOG_ERR("Error during reading image trailer from slot:"
1484 " %"PRIu32"", slot);
1485 continue;
1486 }
1487
1488 if (hdr->ih_magic == IMAGE_MAGIC) {
1489 if (slot_state.magic == BOOT_MAGIC_GOOD ||
1490 slot_state.image_ok == 0x01) {
1491 /* Valid cases:
1492 * - Test mode: magic is OK in image trailer
1493 * - Permanent mode: image_ok flag has previously set
1494 */
1495 image_versions[slot].slot_number = slot;
1496 image_versions[slot].version = boot_get_version_number(hdr);
1497 image_cnt++;
1498 }
1499
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001500 BOOT_LOG_IMAGE_INFO(slot, hdr, &slot_state);
1501 } else {
Oliver Swedef9982442018-08-24 18:37:44 +01001502 BOOT_LOG_INF("Image %"PRIu32": No valid image", slot);
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001503 }
1504 }
1505
1506 /* Sort the images based on version number */
1507 qsort(&image_versions[0],
1508 slot_cnt,
1509 sizeof(struct image_slot_version),
1510 boot_compare_version_numbers);
1511
1512 /* Copy the calculated boot sequence to boot_sequence array */
1513 for (slot = 0; slot < slot_cnt; slot++) {
1514 boot_sequence[slot] = image_versions[slot].slot_number;
1515 }
1516
1517 return image_cnt;
1518}
1519
Oliver Swedef9982442018-08-24 18:37:44 +01001520#ifdef MCUBOOT_RAM_LOADING
1521/**
1522 * Copies an image from a slot in the flash to an SRAM address, where the load
1523 * address has already been inserted into the image header by this point and is
1524 * extracted from it within this method. The copying is done sector-by-sector.
1525 *
1526 * @param slot The flash slot of the image to be copied to SRAM.
1527 *
1528 * @param hdr Pointer to the image header structure of the image
1529 * that needs to be copid to SRAM
1530 *
1531 * @return 0 on success; nonzero on failure.
1532 */
1533static int
1534boot_copy_image_to_sram(int slot, struct image_header *hdr)
1535{
1536 int rc;
1537 uint32_t sect_sz;
1538 uint32_t sect = 0;
1539 uint32_t bytes_copied = 0;
1540 const struct flash_area *fap_src = NULL;
1541 uint32_t dst = (uint32_t) hdr->ih_load_addr;
1542 uint32_t img_sz;
1543
1544 if (dst % 4 != 0) {
1545 BOOT_LOG_INF("Cannot copy the image to the SRAM address 0x%"PRIx32" "
1546 "- the load address must be aligned with 4 bytes due to SRAM "
1547 "restrictions", dst);
1548 return BOOT_EBADARGS;
1549 }
1550
1551 rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap_src);
1552 if (rc != 0) {
1553 return BOOT_EFLASH;
1554 }
1555
1556 rc = boot_read_image_size(slot, hdr, &img_sz);
1557 if (rc != 0) {
1558 return BOOT_EFLASH;
1559 }
1560
1561 while (bytes_copied < img_sz) {
1562 sect_sz = boot_img_sector_size(&boot_data, slot, sect);
1563 /*
1564 * Direct copy from where the image sector resides in flash to its new
1565 * location in SRAM
1566 */
1567 rc = flash_area_read(fap_src,
1568 bytes_copied,
1569 (void *)(dst + bytes_copied),
1570 sect_sz);
1571 if (rc != 0) {
1572 BOOT_LOG_INF("Error whilst copying image from Flash to SRAM");
1573 break;
1574 } else {
1575 bytes_copied += sect_sz;
1576 }
1577 sect++;
1578 }
1579
1580 if (fap_src) {
1581 flash_area_close(fap_src);
1582 }
1583 return rc;
1584}
1585#endif /* MCUBOOT_RAM_LOADING */
1586
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001587/**
1588 * Prepares the booting process. This function choose the newer image in flash
1589 * as appropriate, and returns the address to boot from.
1590 *
1591 * @param rsp On success, indicates how booting should occur.
1592 *
1593 * @return 0 on success; nonzero on failure.
1594 */
1595int
1596boot_go(struct boot_rsp *rsp)
1597{
1598 size_t slot = 0;
1599 int32_t i;
1600 int rc;
1601 int fa_id;
1602 uint32_t boot_sequence[BOOT_NUM_SLOTS];
1603 uint32_t img_cnt;
Oliver Swedef9982442018-08-24 18:37:44 +01001604 struct image_header *newest_image_header;
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001605
1606 static boot_sector_t slot0_sectors[BOOT_MAX_IMG_SECTORS];
1607 static boot_sector_t slot1_sectors[BOOT_MAX_IMG_SECTORS];
1608
1609 boot_data.imgs[0].sectors = &slot0_sectors[0];
1610 boot_data.imgs[1].sectors = &slot1_sectors[0];
1611
1612 /* Open boot_data image areas for the duration of this call. */
1613 for (i = 0; i < BOOT_NUM_SLOTS; i++) {
1614 fa_id = flash_area_id_from_image_slot(i);
1615 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, i));
1616 assert(rc == 0);
1617 }
1618
1619 /* Determine the sector layout of the image slots. */
1620 rc = boot_read_sectors();
1621 if (rc != 0) {
1622 goto out;
1623 }
1624
1625 /* Attempt to read an image header from each slot. */
1626 rc = boot_read_image_headers();
1627 if (rc != 0) {
1628 goto out;
1629 }
1630
1631 img_cnt = boot_get_boot_sequence(boot_sequence, BOOT_NUM_SLOTS);
1632 if (img_cnt) {
1633 /* Authenticate images */
1634 for (i = 0; i < img_cnt; i++) {
1635 rc = boot_validate_slot(boot_sequence[i]);
1636 if (rc == 0) {
1637 slot = boot_sequence[i];
1638 break;
1639 }
1640 }
1641 if (rc) {
1642 /* If there was no valid image at all */
1643 rc = BOOT_EBADIMAGE;
1644 goto out;
1645 }
1646
Oliver Swedef9982442018-08-24 18:37:44 +01001647 /* The slot variable now refers to the newest image's slot in flash */
1648 newest_image_header = boot_img_hdr(&boot_data, slot);
1649
1650 #ifdef MCUBOOT_RAM_LOADING
1651 if (newest_image_header->ih_flags & IMAGE_F_RAM_LOAD) {
1652 /* Copy image to the load address from where it
1653 * currently resides in flash */
1654 rc = boot_copy_image_to_sram(slot, newest_image_header);
1655 if (rc != 0) {
1656 rc = BOOT_EBADIMAGE;
1657 BOOT_LOG_INF("Could not copy image from slot 0x%"PRIx32" in "
1658 "the Flash to load address 0x%"PRIx32" in SRAM, "
1659 "aborting..",
1660 slot,
1661 newest_image_header->ih_load_addr);
1662 goto out;
1663 } else {
1664 BOOT_LOG_INF("Image has been copied from slot %d in flash to "
1665 "SRAM address 0x%"PRIx32"",
1666 slot,
1667 newest_image_header->ih_load_addr);
1668 }
1669
1670 /* Validate the image hash in SRAM after the copy was successful */
1671 rc = bootutil_check_hash_after_loading(newest_image_header);
1672 if (rc != 0) {
1673 rc = BOOT_EBADIMAGE;
1674 BOOT_LOG_INF("Cannot validate the hash of the image that was "
1675 "copied to SRAM, aborting..");
1676 goto out;
1677 }
1678
1679 BOOT_LOG_INF("Booting image from SRAM at address 0x%"PRIx32"",
1680 newest_image_header->ih_load_addr);
1681 } else {
1682 BOOT_LOG_INF("Booting image from slot %d", slot);
1683 }
1684 #endif /* MCUBOOT_RAM_LOADING */
1685
1686 rsp->br_hdr = newest_image_header;
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001687 rsp->br_image_off = boot_img_slot_off(&boot_data, slot);
Oliver Swedef9982442018-08-24 18:37:44 +01001688 rsp->br_flash_dev_id = boot_img_fa_device_id(&boot_data, slot);
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001689 } else {
1690 /* No candidate image available */
1691 rc = BOOT_EBADIMAGE;
1692 }
1693
1694out:
1695 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1696 flash_area_close(BOOT_IMG_AREA(&boot_data, BOOT_NUM_SLOTS - 1 - slot));
1697 }
1698 return rc;
1699}
Oliver Swedef9982442018-08-24 18:37:44 +01001700#endif /* MCUBOOT_NO_SWAP || MCUBOOT_RAM_LOADING */