blob: 0a4034291db28af3dc50c30b44edfcfc0e1c6b98 [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:
David Vincze39e78552018-10-10 17:10:01 +020022 * https://github.com/JuulLabs-OSS/mcuboot
23 * Git SHA of the original version: 178be54bd6e5f035cc60e98205535682acd26e64
Tamas Ban5b647472019-01-05 08:59:30 +000024 * Modifications are Copyright (c) 2018-2019 Arm Limited.
Tamas Ban581034a2017-12-19 19:54:37 +000025 */
26
Tamas Banf70ef8c2017-12-19 15:35:09 +000027/**
28 * This file provides an interface to the boot loader. Functions defined in
29 * this file should only be called while the boot loader is running.
30 */
31
32#include <assert.h>
33#include <stddef.h>
34#include <stdbool.h>
35#include <inttypes.h>
36#include <stdlib.h>
37#include <string.h>
Tamas Banc3828852018-02-01 12:24:16 +000038#include "flash_map/flash_map.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000039#include "bootutil/bootutil.h"
40#include "bootutil/image.h"
41#include "bootutil_priv.h"
Tamas Bana9de4a62018-09-18 08:09:45 +010042#include "bl2/include/tfm_boot_status.h"
43#include "bl2/include/boot_record.h"
David Vincze060968d2019-05-23 01:13:14 +020044#include "security_cnt.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000045
46#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
47#include "bootutil/bootutil_log.h"
48
Tamas Banf70ef8c2017-12-19 15:35:09 +000049static struct boot_loader_state boot_data;
50
Oliver Swedef9982442018-08-24 18:37:44 +010051#if !defined(MCUBOOT_NO_SWAP) && !defined(MCUBOOT_RAM_LOADING)
David Vincze39e78552018-10-10 17:10:01 +020052
53#if defined(MCUBOOT_VALIDATE_SLOT0) && !defined(MCUBOOT_OVERWRITE_ONLY)
54static int boot_status_fails = 0;
55#define BOOT_STATUS_ASSERT(x) \
56 do { \
57 if (!(x)) { \
58 boot_status_fails++; \
59 } \
60 } while (0)
61#else
62#define BOOT_STATUS_ASSERT(x) assert(x)
63#endif
64
Tamas Banf70ef8c2017-12-19 15:35:09 +000065struct boot_status_table {
Tamas Banf70ef8c2017-12-19 15:35:09 +000066 uint8_t bst_magic_slot0;
67 uint8_t bst_magic_scratch;
68 uint8_t bst_copy_done_slot0;
69 uint8_t bst_status_source;
70};
71
72/**
73 * This set of tables maps swap state contents to boot status location.
74 * When searching for a match, these tables must be iterated in order.
75 */
76static const struct boot_status_table boot_status_tables[] = {
77 {
78 /* | slot-0 | scratch |
79 * ----------+------------+------------|
80 * magic | Good | Any |
David Vincze39e78552018-10-10 17:10:01 +020081 * copy-done | Set | N/A |
Tamas Banf70ef8c2017-12-19 15:35:09 +000082 * ----------+------------+------------'
83 * source: none |
84 * ------------------------------------'
85 */
86 .bst_magic_slot0 = BOOT_MAGIC_GOOD,
David Vincze39e78552018-10-10 17:10:01 +020087 .bst_magic_scratch = BOOT_MAGIC_ANY,
88 .bst_copy_done_slot0 = BOOT_FLAG_SET,
Tamas Banf70ef8c2017-12-19 15:35:09 +000089 .bst_status_source = BOOT_STATUS_SOURCE_NONE,
90 },
91
92 {
93 /* | slot-0 | scratch |
94 * ----------+------------+------------|
95 * magic | Good | Any |
David Vincze39e78552018-10-10 17:10:01 +020096 * copy-done | Unset | N/A |
Tamas Banf70ef8c2017-12-19 15:35:09 +000097 * ----------+------------+------------'
98 * source: slot 0 |
99 * ------------------------------------'
100 */
101 .bst_magic_slot0 = BOOT_MAGIC_GOOD,
David Vincze39e78552018-10-10 17:10:01 +0200102 .bst_magic_scratch = BOOT_MAGIC_ANY,
103 .bst_copy_done_slot0 = BOOT_FLAG_UNSET,
Tamas Banf70ef8c2017-12-19 15:35:09 +0000104 .bst_status_source = BOOT_STATUS_SOURCE_SLOT0,
105 },
106
107 {
108 /* | slot-0 | scratch |
109 * ----------+------------+------------|
110 * magic | Any | Good |
111 * copy-done | Any | N/A |
112 * ----------+------------+------------'
113 * source: scratch |
114 * ------------------------------------'
115 */
David Vincze39e78552018-10-10 17:10:01 +0200116 .bst_magic_slot0 = BOOT_MAGIC_ANY,
Tamas Banf70ef8c2017-12-19 15:35:09 +0000117 .bst_magic_scratch = BOOT_MAGIC_GOOD,
David Vincze39e78552018-10-10 17:10:01 +0200118 .bst_copy_done_slot0 = BOOT_FLAG_ANY,
Tamas Banf70ef8c2017-12-19 15:35:09 +0000119 .bst_status_source = BOOT_STATUS_SOURCE_SCRATCH,
120 },
121
122 {
123 /* | slot-0 | scratch |
124 * ----------+------------+------------|
125 * magic | Unset | Any |
David Vincze39e78552018-10-10 17:10:01 +0200126 * copy-done | Unset | N/A |
Tamas Banf70ef8c2017-12-19 15:35:09 +0000127 * ----------+------------+------------|
128 * source: varies |
129 * ------------------------------------+------------------------------+
130 * This represents one of two cases: |
131 * o No swaps ever (no status to read, so no harm in checking). |
132 * o Mid-revert; status in slot 0. |
133 * -------------------------------------------------------------------'
134 */
135 .bst_magic_slot0 = BOOT_MAGIC_UNSET,
David Vincze39e78552018-10-10 17:10:01 +0200136 .bst_magic_scratch = BOOT_MAGIC_ANY,
137 .bst_copy_done_slot0 = BOOT_FLAG_UNSET,
Tamas Banf70ef8c2017-12-19 15:35:09 +0000138 .bst_status_source = BOOT_STATUS_SOURCE_SLOT0,
139 },
140};
141
142#define BOOT_STATUS_TABLES_COUNT \
Tamas Ban581034a2017-12-19 19:54:37 +0000143 (sizeof(boot_status_tables) / sizeof(boot_status_tables[0]))
Tamas Banf70ef8c2017-12-19 15:35:09 +0000144
145#define BOOT_LOG_SWAP_STATE(area, state) \
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000146 BOOT_LOG_INF("%s: magic=%5s, copy_done=0x%x, image_ok=0x%x", \
Tamas Banf70ef8c2017-12-19 15:35:09 +0000147 (area), \
148 ((state)->magic == BOOT_MAGIC_GOOD ? "good" : \
149 (state)->magic == BOOT_MAGIC_UNSET ? "unset" : \
150 "bad"), \
151 (state)->copy_done, \
152 (state)->image_ok)
Oliver Swedef9982442018-08-24 18:37:44 +0100153#endif /* !MCUBOOT_NO_SWAP && !MCUBOOT_RAM_LOADING */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000154
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000155
156static int
157boot_read_image_header(int slot, struct image_header *out_hdr)
158{
159 const struct flash_area *fap = NULL;
160 int area_id;
161 int rc;
162
163 area_id = flash_area_id_from_image_slot(slot);
164 rc = flash_area_open(area_id, &fap);
165 if (rc != 0) {
166 rc = BOOT_EFLASH;
167 goto done;
168 }
169
170 rc = flash_area_read(fap, 0, out_hdr, sizeof(*out_hdr));
171 if (rc != 0) {
172 rc = BOOT_EFLASH;
173 goto done;
174 }
175
176 rc = 0;
177
178done:
179 flash_area_close(fap);
180 return rc;
181}
182
183static int
David Vincze39e78552018-10-10 17:10:01 +0200184boot_read_image_headers(bool require_all)
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000185{
186 int rc;
187 int i;
188
189 for (i = 0; i < BOOT_NUM_SLOTS; i++) {
190 rc = boot_read_image_header(i, boot_img_hdr(&boot_data, i));
191 if (rc != 0) {
David Vincze39e78552018-10-10 17:10:01 +0200192 /* If `require_all` is set, fail on any single fail, otherwise
193 * if at least the first slot's header was read successfully,
194 * then the boot loader can attempt a boot.
195 *
196 * Failure to read any headers is a fatal error.
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000197 */
David Vincze39e78552018-10-10 17:10:01 +0200198 if (i > 0 && !require_all) {
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000199 return 0;
200 } else {
201 return rc;
202 }
203 }
204 }
205
206 return 0;
207}
208
209static uint8_t
210boot_write_sz(void)
211{
212 const struct flash_area *fap;
213 uint8_t elem_sz;
214 uint8_t align;
215 int rc;
216
217 /* Figure out what size to write update status update as. The size depends
218 * on what the minimum write size is for scratch area, active image slot.
219 * We need to use the bigger of those 2 values.
220 */
221 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
222 assert(rc == 0);
223 elem_sz = flash_area_align(fap);
224 flash_area_close(fap);
225
226 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
227 assert(rc == 0);
228 align = flash_area_align(fap);
229 flash_area_close(fap);
230
231 if (align > elem_sz) {
232 elem_sz = align;
233 }
234
235 return elem_sz;
236}
237
238/**
239 * Determines the sector layout of both image slots and the scratch area.
240 * This information is necessary for calculating the number of bytes to erase
241 * and copy during an image swap. The information collected during this
242 * function is used to populate the boot_data global.
243 */
244static int
245boot_read_sectors(void)
246{
247 int rc;
248
249 rc = boot_initialize_area(&boot_data, FLASH_AREA_IMAGE_0);
250 if (rc != 0) {
251 return BOOT_EFLASH;
252 }
253
254 rc = boot_initialize_area(&boot_data, FLASH_AREA_IMAGE_1);
255 if (rc != 0) {
256 return BOOT_EFLASH;
257 }
258
259 BOOT_WRITE_SZ(&boot_data) = boot_write_sz();
260
261 return 0;
262}
263
David Vincze060968d2019-05-23 01:13:14 +0200264/**
265 * Validate image hash/signature and security counter in a slot.
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000266 */
267static int
Tamas Ban0e8ab302019-01-17 11:45:31 +0000268boot_image_check(struct image_header *hdr, const struct flash_area *fap)
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000269{
270 static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
271
272 if (bootutil_img_validate(hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
Tamas Ban0e8ab302019-01-17 11:45:31 +0000273 NULL, 0, NULL)) {
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000274 return BOOT_EBADIMAGE;
275 }
276 return 0;
277}
278
David Vincze39e78552018-10-10 17:10:01 +0200279static inline int
280boot_magic_is_erased(uint8_t erased_val, uint32_t magic)
281{
282 uint8_t i;
283 for (i = 0; i < sizeof(magic); i++) {
284 if (erased_val != *(((uint8_t *)&magic) + i)) {
285 return 0;
286 }
287 }
288 return 1;
289}
290
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000291static int
292boot_validate_slot(int slot)
293{
294 const struct flash_area *fap;
295 struct image_header *hdr;
296 int rc;
297
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000298 rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap);
299 if (rc != 0) {
300 return BOOT_EFLASH;
301 }
302
David Vincze39e78552018-10-10 17:10:01 +0200303 hdr = boot_img_hdr(&boot_data, slot);
304 if (boot_magic_is_erased(flash_area_erased_val(fap), hdr->ih_magic) ||
305 (hdr->ih_flags & IMAGE_F_NON_BOOTABLE)) {
306 /* No bootable image in slot; continue booting from slot 0. */
307 return -1;
308 }
309
Tamas Bana9de4a62018-09-18 08:09:45 +0100310 if ((hdr->ih_magic != IMAGE_MAGIC ||
Tamas Ban0e8ab302019-01-17 11:45:31 +0000311 boot_image_check(hdr, fap) != 0)) {
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000312 if (slot != 0) {
David Vincze26e8c8a2018-08-28 16:59:41 +0200313 rc = flash_area_erase(fap, 0, fap->fa_size);
314 if(rc != 0) {
315 flash_area_close(fap);
316 return BOOT_EFLASH;
317 }
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000318 /* Image in slot 1 is invalid. Erase the image and
319 * continue booting from slot 0.
320 */
321 }
322 BOOT_LOG_ERR("Authentication failed! Image in slot %d is not valid.",
323 slot);
David Vincze060968d2019-05-23 01:13:14 +0200324
325 flash_area_close(fap);
Tamas Ban4fb8e9d2018-02-23 14:22:03 +0000326 return -1;
327 }
328
329 flash_area_close(fap);
330
331 /* Image in slot 1 is valid. */
332 return 0;
333}
334
David Vincze060968d2019-05-23 01:13:14 +0200335/**
336 * Updates the stored security counter value with the image's security counter
337 * value which resides in the given slot if it's greater than the stored value.
338 *
339 * @param slot Slot number of the image.
340 * @param hdr Pointer to the image header structure of the image that is
341 * currently stored in the given slot.
342 *
343 * @return 0 on success; nonzero on failure.
344 */
345static int
346boot_update_security_counter(int slot, struct image_header *hdr)
347{
348 const struct flash_area *fap = NULL;
349 uint32_t img_security_cnt;
350 int rc;
351
352 rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap);
353 if (rc != 0) {
354 rc = BOOT_EFLASH;
355 goto done;
356 }
357
358 rc = bootutil_get_img_security_cnt(hdr, fap, &img_security_cnt);
359 if (rc != 0) {
360 goto done;
361 }
362
363 rc = boot_nv_security_counter_update(0, img_security_cnt);
364 if (rc != 0) {
365 goto done;
366 }
367
368done:
369 flash_area_close(fap);
370 return rc;
371}
372
Oliver Swedef9982442018-08-24 18:37:44 +0100373#if !defined(MCUBOOT_NO_SWAP) && !defined(MCUBOOT_OVERWRITE_ONLY)
374/*
375 * Compute the total size of the given image. Includes the size of
376 * the TLVs.
377 */
378static int
379boot_read_image_size(int slot, struct image_header *hdr, uint32_t *size)
380{
381 const struct flash_area *fap = NULL;
382 struct image_tlv_info info;
383 int area_id;
384 int rc;
385
386 area_id = flash_area_id_from_image_slot(slot);
387 rc = flash_area_open(area_id, &fap);
388 if (rc != 0) {
389 rc = BOOT_EFLASH;
390 goto done;
391 }
392
393 rc = flash_area_read(fap, hdr->ih_hdr_size + hdr->ih_img_size,
394 &info, sizeof(info));
395 if (rc != 0) {
396 rc = BOOT_EFLASH;
397 goto done;
398 }
399 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
400 rc = BOOT_EBADIMAGE;
401 goto done;
402 }
403 *size = hdr->ih_hdr_size + hdr->ih_img_size + info.it_tlv_tot;
404 rc = 0;
405
406done:
407 flash_area_close(fap);
408 return rc;
409}
410#endif /* !MCUBOOT_NO_SWAP && !MCUBOOT_OVERWRITE_ONLY */
411
412#if !defined(MCUBOOT_NO_SWAP) && !defined(MCUBOOT_RAM_LOADING)
Tamas Banf70ef8c2017-12-19 15:35:09 +0000413/**
Tamas Ban581034a2017-12-19 19:54:37 +0000414 * Determines where in flash the most recent boot status is stored. The boot
Tamas Banf70ef8c2017-12-19 15:35:09 +0000415 * status is necessary for completing a swap that was interrupted by a boot
416 * loader reset.
417 *
Tamas Ban581034a2017-12-19 19:54:37 +0000418 * @return BOOT_STATUS_SOURCE_[...] code indicating where
419 * status should be read from.
Tamas Banf70ef8c2017-12-19 15:35:09 +0000420 */
421static int
422boot_status_source(void)
423{
424 const struct boot_status_table *table;
425 struct boot_swap_state state_scratch;
426 struct boot_swap_state state_slot0;
427 int rc;
David Vincze39e78552018-10-10 17:10:01 +0200428 size_t i;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000429 uint8_t source;
430
431 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
432 assert(rc == 0);
433
434 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SCRATCH, &state_scratch);
435 assert(rc == 0);
436
437 BOOT_LOG_SWAP_STATE("Image 0", &state_slot0);
438 BOOT_LOG_SWAP_STATE("Scratch", &state_scratch);
439
440 for (i = 0; i < BOOT_STATUS_TABLES_COUNT; i++) {
441 table = &boot_status_tables[i];
442
David Vincze39e78552018-10-10 17:10:01 +0200443 if ((table->bst_magic_slot0 == BOOT_MAGIC_ANY ||
Tamas Banf70ef8c2017-12-19 15:35:09 +0000444 table->bst_magic_slot0 == state_slot0.magic) &&
David Vincze39e78552018-10-10 17:10:01 +0200445 (table->bst_magic_scratch == BOOT_MAGIC_ANY ||
Tamas Banf70ef8c2017-12-19 15:35:09 +0000446 table->bst_magic_scratch == state_scratch.magic) &&
David Vincze39e78552018-10-10 17:10:01 +0200447 (table->bst_copy_done_slot0 == BOOT_FLAG_ANY ||
Tamas Banf70ef8c2017-12-19 15:35:09 +0000448 table->bst_copy_done_slot0 == state_slot0.copy_done)) {
449 source = table->bst_status_source;
450 BOOT_LOG_INF("Boot source: %s",
451 source == BOOT_STATUS_SOURCE_NONE ? "none" :
452 source == BOOT_STATUS_SOURCE_SCRATCH ? "scratch" :
453 source == BOOT_STATUS_SOURCE_SLOT0 ? "slot 0" :
454 "BUG; can't happen");
455 return source;
456 }
457 }
458
459 BOOT_LOG_INF("Boot source: none");
460 return BOOT_STATUS_SOURCE_NONE;
461}
462
463/**
464 * Calculates the type of swap that just completed.
465 *
466 * This is used when a swap is interrupted by an external event. After
467 * finishing the swap operation determines what the initial request was.
468 */
469static int
470boot_previous_swap_type(void)
471{
472 int post_swap_type;
473
474 post_swap_type = boot_swap_type();
475
476 switch (post_swap_type) {
David Vincze39e78552018-10-10 17:10:01 +0200477 case BOOT_SWAP_TYPE_NONE : return BOOT_SWAP_TYPE_PERM;
478 case BOOT_SWAP_TYPE_REVERT : return BOOT_SWAP_TYPE_TEST;
479 case BOOT_SWAP_TYPE_PANIC : return BOOT_SWAP_TYPE_PANIC;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000480 }
481
482 return BOOT_SWAP_TYPE_FAIL;
483}
484
Tamas Banf70ef8c2017-12-19 15:35:09 +0000485static int
Tamas Banf70ef8c2017-12-19 15:35:09 +0000486boot_slots_compatible(void)
487{
488 size_t num_sectors_0 = boot_img_num_sectors(&boot_data, 0);
489 size_t num_sectors_1 = boot_img_num_sectors(&boot_data, 1);
490 size_t size_0, size_1;
491 size_t i;
492
David Vincze39e78552018-10-10 17:10:01 +0200493 if (num_sectors_0 > BOOT_MAX_IMG_SECTORS || num_sectors_1 > BOOT_MAX_IMG_SECTORS) {
494 BOOT_LOG_WRN("Cannot upgrade: more sectors than allowed");
Tamas Banf70ef8c2017-12-19 15:35:09 +0000495 return 0;
496 }
David Vincze39e78552018-10-10 17:10:01 +0200497
498 /* Ensure both image slots have identical sector layouts. */
499 if (num_sectors_0 != num_sectors_1) {
500 BOOT_LOG_WRN("Cannot upgrade: number of sectors differ between slots");
501 return 0;
502 }
503
Tamas Banf70ef8c2017-12-19 15:35:09 +0000504 for (i = 0; i < num_sectors_0; i++) {
505 size_0 = boot_img_sector_size(&boot_data, 0, i);
506 size_1 = boot_img_sector_size(&boot_data, 1, i);
507 if (size_0 != size_1) {
David Vincze39e78552018-10-10 17:10:01 +0200508 BOOT_LOG_WRN("Cannot upgrade: an incompatible sector was found");
Tamas Banf70ef8c2017-12-19 15:35:09 +0000509 return 0;
510 }
511 }
512
513 return 1;
514}
515
Tamas Banf70ef8c2017-12-19 15:35:09 +0000516static uint32_t
517boot_status_internal_off(int idx, int state, int elem_sz)
518{
519 int idx_sz;
520
521 idx_sz = elem_sz * BOOT_STATUS_STATE_COUNT;
522
David Vincze39e78552018-10-10 17:10:01 +0200523 return (idx - BOOT_STATUS_IDX_0) * idx_sz +
524 (state - BOOT_STATUS_STATE_0) * elem_sz;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000525}
526
527/**
528 * Reads the status of a partially-completed swap, if any. This is necessary
529 * to recover in case the boot lodaer was reset in the middle of a swap
530 * operation.
531 */
532static int
533boot_read_status_bytes(const struct flash_area *fap, struct boot_status *bs)
534{
535 uint32_t off;
536 uint8_t status;
537 int max_entries;
538 int found;
David Vincze39e78552018-10-10 17:10:01 +0200539 int found_idx;
540 int invalid;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000541 int rc;
542 int i;
543
544 off = boot_status_off(fap);
545 max_entries = boot_status_entries(fap);
546
547 found = 0;
David Vincze39e78552018-10-10 17:10:01 +0200548 found_idx = 0;
549 invalid = 0;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000550 for (i = 0; i < max_entries; i++) {
David Vincze39e78552018-10-10 17:10:01 +0200551 rc = flash_area_read_is_empty(fap, off + i * BOOT_WRITE_SZ(&boot_data),
552 &status, 1);
553 if (rc < 0) {
Tamas Banf70ef8c2017-12-19 15:35:09 +0000554 return BOOT_EFLASH;
555 }
556
David Vincze39e78552018-10-10 17:10:01 +0200557 if (rc == 1) {
558 if (found && !found_idx) {
559 found_idx = i;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000560 }
561 } else if (!found) {
562 found = 1;
David Vincze39e78552018-10-10 17:10:01 +0200563 } else if (found_idx) {
564 invalid = 1;
565 break;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000566 }
567 }
568
David Vincze39e78552018-10-10 17:10:01 +0200569 if (invalid) {
570 /* This means there was an error writing status on the last
571 * swap. Tell user and move on to validation!
572 */
573 BOOT_LOG_ERR("Detected inconsistent status!");
574
575#if !defined(MCUBOOT_VALIDATE_SLOT0)
576 /* With validation of slot0 disabled, there is no way to be sure the
577 * swapped slot0 is OK, so abort!
578 */
579 assert(0);
580#endif
581 }
582
Tamas Banf70ef8c2017-12-19 15:35:09 +0000583 if (found) {
David Vincze39e78552018-10-10 17:10:01 +0200584 if (!found_idx) {
585 found_idx = i;
586 }
587 found_idx--;
588 bs->idx = (found_idx / BOOT_STATUS_STATE_COUNT) + 1;
589 bs->state = (found_idx % BOOT_STATUS_STATE_COUNT) + 1;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000590 }
591
592 return 0;
593}
594
595/**
596 * Reads the boot status from the flash. The boot status contains
597 * the current state of an interrupted image copy operation. If the boot
598 * status is not present, or it indicates that previous copy finished,
599 * there is no operation in progress.
600 */
601static int
602boot_read_status(struct boot_status *bs)
603{
604 const struct flash_area *fap;
605 int status_loc;
606 int area_id;
607 int rc;
608
David Vincze39e78552018-10-10 17:10:01 +0200609 memset(bs, 0, sizeof *bs);
610 bs->idx = BOOT_STATUS_IDX_0;
611 bs->state = BOOT_STATUS_STATE_0;
612
613#ifdef MCUBOOT_OVERWRITE_ONLY
614 /* Overwrite-only doesn't make use of the swap status area. */
615 return 0;
616#endif
Tamas Banf70ef8c2017-12-19 15:35:09 +0000617
618 status_loc = boot_status_source();
619 switch (status_loc) {
620 case BOOT_STATUS_SOURCE_NONE:
621 return 0;
622
623 case BOOT_STATUS_SOURCE_SCRATCH:
624 area_id = FLASH_AREA_IMAGE_SCRATCH;
625 break;
626
627 case BOOT_STATUS_SOURCE_SLOT0:
628 area_id = FLASH_AREA_IMAGE_0;
629 break;
630
631 default:
632 assert(0);
633 return BOOT_EBADARGS;
634 }
635
636 rc = flash_area_open(area_id, &fap);
637 if (rc != 0) {
638 return BOOT_EFLASH;
639 }
640
641 rc = boot_read_status_bytes(fap, bs);
642
643 flash_area_close(fap);
David Vincze39e78552018-10-10 17:10:01 +0200644
Tamas Banf70ef8c2017-12-19 15:35:09 +0000645 return rc;
646}
647
648/**
649 * Writes the supplied boot status to the flash file system. The boot status
650 * contains the current state of an in-progress image copy operation.
651 *
652 * @param bs The boot status to write.
653 *
654 * @return 0 on success; nonzero on failure.
655 */
656int
657boot_write_status(struct boot_status *bs)
658{
Tamas Ban581034a2017-12-19 19:54:37 +0000659 const struct flash_area *fap = NULL;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000660 uint32_t off;
661 int area_id;
662 int rc;
663 uint8_t buf[BOOT_MAX_ALIGN];
664 uint8_t align;
David Vincze39e78552018-10-10 17:10:01 +0200665 uint8_t erased_val;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000666
667 /* NOTE: The first sector copied (that is the last sector on slot) contains
668 * the trailer. Since in the last step SLOT 0 is erased, the first
669 * two status writes go to the scratch which will be copied to SLOT 0!
670 */
671
672 if (bs->use_scratch) {
673 /* Write to scratch. */
674 area_id = FLASH_AREA_IMAGE_SCRATCH;
675 } else {
676 /* Write to slot 0. */
677 area_id = FLASH_AREA_IMAGE_0;
678 }
679
680 rc = flash_area_open(area_id, &fap);
681 if (rc != 0) {
682 rc = BOOT_EFLASH;
683 goto done;
684 }
685
686 off = boot_status_off(fap) +
687 boot_status_internal_off(bs->idx, bs->state,
688 BOOT_WRITE_SZ(&boot_data));
689
Tamas Banc3828852018-02-01 12:24:16 +0000690 align = flash_area_align(fap);
David Vincze39e78552018-10-10 17:10:01 +0200691 erased_val = flash_area_erased_val(fap);
692 memset(buf, erased_val, BOOT_MAX_ALIGN);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000693 buf[0] = bs->state;
694
695 rc = flash_area_write(fap, off, buf, align);
696 if (rc != 0) {
697 rc = BOOT_EFLASH;
698 goto done;
699 }
700
701 rc = 0;
702
703done:
704 flash_area_close(fap);
705 return rc;
706}
707
Tamas Banf70ef8c2017-12-19 15:35:09 +0000708/**
709 * Determines which swap operation to perform, if any. If it is determined
710 * that a swap operation is required, the image in the second slot is checked
711 * for validity. If the image in the second slot is invalid, it is erased, and
712 * a swap type of "none" is indicated.
713 *
714 * @return The type of swap to perform (BOOT_SWAP_TYPE...)
715 */
716static int
717boot_validated_swap_type(void)
718{
719 int swap_type;
720
721 swap_type = boot_swap_type();
722 switch (swap_type) {
723 case BOOT_SWAP_TYPE_TEST:
724 case BOOT_SWAP_TYPE_PERM:
725 case BOOT_SWAP_TYPE_REVERT:
726 /* Boot loader wants to switch to slot 1. Ensure image is valid. */
727 if (boot_validate_slot(1) != 0) {
728 swap_type = BOOT_SWAP_TYPE_FAIL;
729 }
730 }
731
732 return swap_type;
733}
734
735/**
736 * Calculates the number of sectors the scratch area can contain. A "last"
737 * source sector is specified because images are copied backwards in flash
738 * (final index to index number 0).
739 *
740 * @param last_sector_idx The index of the last source sector
741 * (inclusive).
742 * @param out_first_sector_idx The index of the first source sector
743 * (inclusive) gets written here.
744 *
745 * @return The number of bytes comprised by the
746 * [first-sector, last-sector] range.
747 */
748#ifndef MCUBOOT_OVERWRITE_ONLY
749static uint32_t
750boot_copy_sz(int last_sector_idx, int *out_first_sector_idx)
751{
752 size_t scratch_sz;
753 uint32_t new_sz;
754 uint32_t sz;
755 int i;
756
757 sz = 0;
758
759 scratch_sz = boot_scratch_area_size(&boot_data);
760 for (i = last_sector_idx; i >= 0; i--) {
761 new_sz = sz + boot_img_sector_size(&boot_data, 0, i);
762 if (new_sz > scratch_sz) {
763 break;
764 }
765 sz = new_sz;
766 }
767
768 /* i currently refers to a sector that doesn't fit or it is -1 because all
769 * sectors have been processed. In both cases, exclude sector i.
770 */
771 *out_first_sector_idx = i + 1;
772 return sz;
773}
774#endif /* !MCUBOOT_OVERWRITE_ONLY */
775
776/**
David Vinczef7641fa2018-09-04 18:29:46 +0200777 * Erases a region of flash.
778 *
779 * @param flash_area_idx The ID of the flash area containing the region
780 * to erase.
781 * @param off The offset within the flash area to start the
782 * erase.
783 * @param sz The number of bytes to erase.
784 *
785 * @return 0 on success; nonzero on failure.
786 */
787static int
788boot_erase_sector(int flash_area_id, uint32_t off, uint32_t sz)
789{
790 const struct flash_area *fap = NULL;
791 int rc;
792
793 rc = flash_area_open(flash_area_id, &fap);
794 if (rc != 0) {
795 rc = BOOT_EFLASH;
796 goto done;
797 }
798
799 rc = flash_area_erase(fap, off, sz);
800 if (rc != 0) {
801 rc = BOOT_EFLASH;
802 goto done;
803 }
804
805 rc = 0;
806
807done:
808 flash_area_close(fap);
809 return rc;
810}
811
812/**
Tamas Banf70ef8c2017-12-19 15:35:09 +0000813 * Copies the contents of one flash region to another. You must erase the
814 * destination region prior to calling this function.
815 *
816 * @param flash_area_id_src The ID of the source flash area.
817 * @param flash_area_id_dst The ID of the destination flash area.
818 * @param off_src The offset within the source flash area to
819 * copy from.
820 * @param off_dst The offset within the destination flash area to
821 * copy to.
822 * @param sz The number of bytes to copy.
823 *
824 * @return 0 on success; nonzero on failure.
825 */
826static int
827boot_copy_sector(int flash_area_id_src, int flash_area_id_dst,
828 uint32_t off_src, uint32_t off_dst, uint32_t sz)
829{
830 const struct flash_area *fap_src;
831 const struct flash_area *fap_dst;
832 uint32_t bytes_copied;
833 int chunk_sz;
834 int rc;
835
836 static uint8_t buf[1024];
837
838 fap_src = NULL;
839 fap_dst = NULL;
840
841 rc = flash_area_open(flash_area_id_src, &fap_src);
842 if (rc != 0) {
843 rc = BOOT_EFLASH;
844 goto done;
845 }
846
847 rc = flash_area_open(flash_area_id_dst, &fap_dst);
848 if (rc != 0) {
849 rc = BOOT_EFLASH;
850 goto done;
851 }
852
853 bytes_copied = 0;
854 while (bytes_copied < sz) {
Tamas Ban581034a2017-12-19 19:54:37 +0000855 if (sz - bytes_copied > sizeof(buf)) {
856 chunk_sz = sizeof(buf);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000857 } else {
858 chunk_sz = sz - bytes_copied;
859 }
860
861 rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz);
862 if (rc != 0) {
863 rc = BOOT_EFLASH;
864 goto done;
865 }
866
867 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
868 if (rc != 0) {
869 rc = BOOT_EFLASH;
870 goto done;
871 }
872
873 bytes_copied += chunk_sz;
874 }
875
876 rc = 0;
877
878done:
879 if (fap_src) {
880 flash_area_close(fap_src);
881 }
882 if (fap_dst) {
883 flash_area_close(fap_dst);
884 }
885 return rc;
886}
887
888#ifndef MCUBOOT_OVERWRITE_ONLY
889static inline int
890boot_status_init_by_id(int flash_area_id, const struct boot_status *bs)
891{
892 const struct flash_area *fap;
893 struct boot_swap_state swap_state;
894 int rc;
895
896 rc = flash_area_open(flash_area_id, &fap);
897 assert(rc == 0);
898
899 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &swap_state);
900 assert(rc == 0);
901
902 if (swap_state.image_ok == BOOT_FLAG_SET) {
903 rc = boot_write_image_ok(fap);
904 assert(rc == 0);
905 }
906
907 rc = boot_write_swap_size(fap, bs->swap_size);
908 assert(rc == 0);
909
910 rc = boot_write_magic(fap);
911 assert(rc == 0);
912
913 flash_area_close(fap);
914
915 return 0;
916}
David Vinczef7641fa2018-09-04 18:29:46 +0200917
918static int
919boot_erase_last_sector_by_id(int flash_area_id)
920{
921 uint8_t slot;
922 uint32_t last_sector;
923 int rc;
924
925 switch (flash_area_id) {
926 case FLASH_AREA_IMAGE_0:
927 slot = 0;
928 break;
929 case FLASH_AREA_IMAGE_1:
930 slot = 1;
931 break;
932 default:
933 return BOOT_EFLASH;
934 }
935
936 last_sector = boot_img_num_sectors(&boot_data, slot) - 1;
937 rc = boot_erase_sector(flash_area_id,
938 boot_img_sector_off(&boot_data, slot, last_sector),
939 boot_img_sector_size(&boot_data, slot, last_sector));
940 assert(rc == 0);
941
942 return rc;
943}
944#endif /* !MCUBOOT_OVERWRITE_ONLY */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000945
Tamas Banf70ef8c2017-12-19 15:35:09 +0000946/**
947 * Swaps the contents of two flash regions within the two image slots.
948 *
949 * @param idx The index of the first sector in the range of
950 * sectors being swapped.
951 * @param sz The number of bytes to swap.
952 * @param bs The current boot status. This struct gets
953 * updated according to the outcome.
954 *
955 * @return 0 on success; nonzero on failure.
956 */
957#ifndef MCUBOOT_OVERWRITE_ONLY
958static void
959boot_swap_sectors(int idx, uint32_t sz, struct boot_status *bs)
960{
961 const struct flash_area *fap;
962 uint32_t copy_sz;
963 uint32_t trailer_sz;
964 uint32_t img_off;
965 uint32_t scratch_trailer_off;
966 struct boot_swap_state swap_state;
967 size_t last_sector;
968 int rc;
969
970 /* Calculate offset from start of image area. */
971 img_off = boot_img_sector_off(&boot_data, 0, idx);
972
973 copy_sz = sz;
974 trailer_sz = boot_slots_trailer_sz(BOOT_WRITE_SZ(&boot_data));
975
976 /* sz in this function is always is always sized on a multiple of the
977 * sector size. The check against the start offset of the last sector
978 * is to determine if we're swapping the last sector. The last sector
979 * needs special handling because it's where the trailer lives. If we're
980 * copying it, we need to use scratch to write the trailer temporarily.
981 *
982 * NOTE: `use_scratch` is a temporary flag (never written to flash) which
983 * controls if special handling is needed (swapping last sector).
984 */
985 last_sector = boot_img_num_sectors(&boot_data, 0) - 1;
986 if (img_off + sz > boot_img_sector_off(&boot_data, 0, last_sector)) {
987 copy_sz -= trailer_sz;
988 }
989
David Vincze39e78552018-10-10 17:10:01 +0200990 bs->use_scratch = (bs->idx == BOOT_STATUS_IDX_0 && copy_sz != sz);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000991
David Vincze39e78552018-10-10 17:10:01 +0200992 if (bs->state == BOOT_STATUS_STATE_0) {
Tamas Banf70ef8c2017-12-19 15:35:09 +0000993 rc = boot_erase_sector(FLASH_AREA_IMAGE_SCRATCH, 0, sz);
994 assert(rc == 0);
995
996 rc = boot_copy_sector(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_SCRATCH,
997 img_off, 0, copy_sz);
998 assert(rc == 0);
999
David Vincze39e78552018-10-10 17:10:01 +02001000 if (bs->idx == BOOT_STATUS_IDX_0) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001001 if (bs->use_scratch) {
1002 boot_status_init_by_id(FLASH_AREA_IMAGE_SCRATCH, bs);
1003 } else {
1004 /* Prepare the status area... here it is known that the
1005 * last sector is not being used by the image data so it's
1006 * safe to erase.
1007 */
1008 rc = boot_erase_last_sector_by_id(FLASH_AREA_IMAGE_0);
1009 assert(rc == 0);
1010
1011 boot_status_init_by_id(FLASH_AREA_IMAGE_0, bs);
1012 }
1013 }
1014
David Vincze39e78552018-10-10 17:10:01 +02001015 bs->state = BOOT_STATUS_STATE_1;
Tamas Banf70ef8c2017-12-19 15:35:09 +00001016 rc = boot_write_status(bs);
David Vincze39e78552018-10-10 17:10:01 +02001017 BOOT_STATUS_ASSERT(rc == 0);
Tamas Banf70ef8c2017-12-19 15:35:09 +00001018 }
1019
David Vincze39e78552018-10-10 17:10:01 +02001020 if (bs->state == BOOT_STATUS_STATE_1) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001021 rc = boot_erase_sector(FLASH_AREA_IMAGE_1, img_off, sz);
1022 assert(rc == 0);
1023
1024 rc = boot_copy_sector(FLASH_AREA_IMAGE_0, FLASH_AREA_IMAGE_1,
1025 img_off, img_off, copy_sz);
1026 assert(rc == 0);
1027
David Vincze39e78552018-10-10 17:10:01 +02001028 if (bs->idx == BOOT_STATUS_IDX_0 && !bs->use_scratch) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001029 /* If not all sectors of the slot are being swapped,
1030 * guarantee here that only slot0 will have the state.
1031 */
1032 rc = boot_erase_last_sector_by_id(FLASH_AREA_IMAGE_1);
1033 assert(rc == 0);
1034 }
1035
David Vincze39e78552018-10-10 17:10:01 +02001036 bs->state = BOOT_STATUS_STATE_2;
Tamas Banf70ef8c2017-12-19 15:35:09 +00001037 rc = boot_write_status(bs);
David Vincze39e78552018-10-10 17:10:01 +02001038 BOOT_STATUS_ASSERT(rc == 0);
Tamas Banf70ef8c2017-12-19 15:35:09 +00001039 }
1040
David Vincze39e78552018-10-10 17:10:01 +02001041 if (bs->state == BOOT_STATUS_STATE_2) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001042 rc = boot_erase_sector(FLASH_AREA_IMAGE_0, img_off, sz);
1043 assert(rc == 0);
1044
1045 /* NOTE: also copy trailer from scratch (has status info) */
1046 rc = boot_copy_sector(FLASH_AREA_IMAGE_SCRATCH, FLASH_AREA_IMAGE_0,
1047 0, img_off, copy_sz);
1048 assert(rc == 0);
1049
1050 if (bs->use_scratch) {
1051 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
1052 assert(rc == 0);
1053
1054 scratch_trailer_off = boot_status_off(fap);
1055
1056 flash_area_close(fap);
1057
1058 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
1059 assert(rc == 0);
1060
1061 /* copy current status that is being maintained in scratch */
1062 rc = boot_copy_sector(FLASH_AREA_IMAGE_SCRATCH, FLASH_AREA_IMAGE_0,
1063 scratch_trailer_off,
1064 img_off + copy_sz,
1065 BOOT_STATUS_STATE_COUNT * BOOT_WRITE_SZ(&boot_data));
David Vincze39e78552018-10-10 17:10:01 +02001066 BOOT_STATUS_ASSERT(rc == 0);
Tamas Banf70ef8c2017-12-19 15:35:09 +00001067
1068 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SCRATCH,
1069 &swap_state);
1070 assert(rc == 0);
1071
1072 if (swap_state.image_ok == BOOT_FLAG_SET) {
1073 rc = boot_write_image_ok(fap);
1074 assert(rc == 0);
1075 }
1076
1077 rc = boot_write_swap_size(fap, bs->swap_size);
1078 assert(rc == 0);
1079
1080 rc = boot_write_magic(fap);
1081 assert(rc == 0);
1082
1083 flash_area_close(fap);
1084 }
1085
1086 bs->idx++;
David Vincze39e78552018-10-10 17:10:01 +02001087 bs->state = BOOT_STATUS_STATE_0;
Tamas Banf70ef8c2017-12-19 15:35:09 +00001088 bs->use_scratch = 0;
1089 rc = boot_write_status(bs);
David Vincze39e78552018-10-10 17:10:01 +02001090 BOOT_STATUS_ASSERT(rc == 0);
Tamas Banf70ef8c2017-12-19 15:35:09 +00001091 }
1092}
1093#endif /* !MCUBOOT_OVERWRITE_ONLY */
1094
1095/**
1096 * Swaps the two images in flash. If a prior copy operation was interrupted
1097 * by a system reset, this function completes that operation.
1098 *
1099 * @param bs The current boot status. This function reads
1100 * this struct to determine if it is resuming
1101 * an interrupted swap operation. This
1102 * function writes the updated status to this
1103 * function on return.
1104 *
1105 * @return 0 on success; nonzero on failure.
1106 */
1107#ifdef MCUBOOT_OVERWRITE_ONLY
1108static int
1109boot_copy_image(struct boot_status *bs)
1110{
1111 size_t sect_count;
1112 size_t sect;
1113 int rc;
1114 size_t size = 0;
1115 size_t this_size;
David Vincze39e78552018-10-10 17:10:01 +02001116 size_t last_sector;
1117
1118 (void)bs;
Tamas Banf70ef8c2017-12-19 15:35:09 +00001119
1120 BOOT_LOG_INF("Image upgrade slot1 -> slot0");
1121 BOOT_LOG_INF("Erasing slot0");
1122
1123 sect_count = boot_img_num_sectors(&boot_data, 0);
1124 for (sect = 0; sect < sect_count; sect++) {
1125 this_size = boot_img_sector_size(&boot_data, 0, sect);
1126 rc = boot_erase_sector(FLASH_AREA_IMAGE_0,
1127 size,
1128 this_size);
1129 assert(rc == 0);
1130
1131 size += this_size;
1132 }
1133
David Vincze8a2a4e22019-05-24 10:14:23 +02001134 BOOT_LOG_INF("Copying slot 1 to slot 0: 0x%zx bytes", size);
Tamas Banf70ef8c2017-12-19 15:35:09 +00001135 rc = boot_copy_sector(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_0,
1136 0, 0, size);
1137
David Vincze060968d2019-05-23 01:13:14 +02001138 /* Update the stored security counter with the new image's security counter
1139 * value. Both slots hold the new image at this point, but slot 1's image
1140 * header must be passed because the read image headers in the boot_data
1141 * structure have not been updated yet.
1142 */
1143 rc = boot_update_security_counter(0, boot_img_hdr(&boot_data, 1));
1144 if (rc != 0) {
1145 BOOT_LOG_ERR("Security counter update failed after image upgrade.");
1146 return rc;
1147 }
1148
David Vincze39e78552018-10-10 17:10:01 +02001149 /*
1150 * Erases header and trailer. The trailer is erased because when a new
1151 * image is written without a trailer as is the case when using newt, the
1152 * trailer that was left might trigger a new upgrade.
1153 */
Tamas Banf70ef8c2017-12-19 15:35:09 +00001154 rc = boot_erase_sector(FLASH_AREA_IMAGE_1,
David Vincze39e78552018-10-10 17:10:01 +02001155 boot_img_sector_off(&boot_data, 1, 0),
1156 boot_img_sector_size(&boot_data, 1, 0));
Tamas Banf70ef8c2017-12-19 15:35:09 +00001157 assert(rc == 0);
David Vincze39e78552018-10-10 17:10:01 +02001158 last_sector = boot_img_num_sectors(&boot_data, 1) - 1;
1159 rc = boot_erase_sector(FLASH_AREA_IMAGE_1,
1160 boot_img_sector_off(&boot_data, 1, last_sector),
1161 boot_img_sector_size(&boot_data, 1, last_sector));
1162 assert(rc == 0);
1163
1164 /* TODO: Perhaps verify slot 0's signature again? */
Tamas Banf70ef8c2017-12-19 15:35:09 +00001165
1166 return 0;
1167}
1168#else
1169static int
1170boot_copy_image(struct boot_status *bs)
1171{
1172 uint32_t sz;
1173 int first_sector_idx;
1174 int last_sector_idx;
David Vincze39e78552018-10-10 17:10:01 +02001175 uint32_t swap_idx;
Tamas Banf70ef8c2017-12-19 15:35:09 +00001176 struct image_header *hdr;
1177 uint32_t size;
1178 uint32_t copy_size;
1179 int rc;
1180
1181 /* FIXME: just do this if asked by user? */
1182
1183 size = copy_size = 0;
1184
David Vincze39e78552018-10-10 17:10:01 +02001185 if (bs->idx == BOOT_STATUS_IDX_0 && bs->state == BOOT_STATUS_STATE_0) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001186 /*
1187 * No swap ever happened, so need to find the largest image which
1188 * will be used to determine the amount of sectors to swap.
1189 */
1190 hdr = boot_img_hdr(&boot_data, 0);
1191 if (hdr->ih_magic == IMAGE_MAGIC) {
1192 rc = boot_read_image_size(0, hdr, &copy_size);
1193 assert(rc == 0);
1194 }
1195
1196 hdr = boot_img_hdr(&boot_data, 1);
1197 if (hdr->ih_magic == IMAGE_MAGIC) {
1198 rc = boot_read_image_size(1, hdr, &size);
1199 assert(rc == 0);
1200 }
1201
1202 if (size > copy_size) {
1203 copy_size = size;
1204 }
1205
1206 bs->swap_size = copy_size;
1207 } else {
1208 /*
1209 * If a swap was under way, the swap_size should already be present
1210 * in the trailer...
1211 */
1212 rc = boot_read_swap_size(&bs->swap_size);
1213 assert(rc == 0);
1214
1215 copy_size = bs->swap_size;
1216 }
1217
1218 size = 0;
1219 last_sector_idx = 0;
1220 while (1) {
1221 size += boot_img_sector_size(&boot_data, 0, last_sector_idx);
1222 if (size >= copy_size) {
1223 break;
1224 }
1225 last_sector_idx++;
1226 }
1227
1228 swap_idx = 0;
1229 while (last_sector_idx >= 0) {
1230 sz = boot_copy_sz(last_sector_idx, &first_sector_idx);
David Vincze39e78552018-10-10 17:10:01 +02001231 if (swap_idx >= (bs->idx - BOOT_STATUS_IDX_0)) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001232 boot_swap_sectors(first_sector_idx, sz, bs);
1233 }
1234
1235 last_sector_idx = first_sector_idx - 1;
1236 swap_idx++;
1237 }
1238
David Vincze39e78552018-10-10 17:10:01 +02001239#ifdef MCUBOOT_VALIDATE_SLOT0
1240 if (boot_status_fails > 0) {
1241 BOOT_LOG_WRN("%d status write fails performing the swap", boot_status_fails);
1242 }
1243#endif
1244
Tamas Banf70ef8c2017-12-19 15:35:09 +00001245 return 0;
1246}
1247#endif
1248
1249/**
1250 * Marks the image in slot 0 as fully copied.
1251 */
1252#ifndef MCUBOOT_OVERWRITE_ONLY
1253static int
1254boot_set_copy_done(void)
1255{
1256 const struct flash_area *fap;
1257 int rc;
1258
1259 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
1260 if (rc != 0) {
1261 return BOOT_EFLASH;
1262 }
1263
1264 rc = boot_write_copy_done(fap);
1265 flash_area_close(fap);
1266 return rc;
1267}
1268#endif /* !MCUBOOT_OVERWRITE_ONLY */
1269
1270/**
1271 * Marks a reverted image in slot 0 as confirmed. This is necessary to ensure
1272 * the status bytes from the image revert operation don't get processed on a
1273 * subsequent boot.
1274 *
1275 * NOTE: image_ok is tested before writing because if there's a valid permanent
1276 * image installed on slot0 and the new image to be upgrade to has a bad sig,
1277 * image_ok would be overwritten.
1278 */
1279#ifndef MCUBOOT_OVERWRITE_ONLY
1280static int
1281boot_set_image_ok(void)
1282{
1283 const struct flash_area *fap;
1284 struct boot_swap_state state;
1285 int rc;
1286
1287 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
1288 if (rc != 0) {
1289 return BOOT_EFLASH;
1290 }
1291
1292 rc = boot_read_swap_state(fap, &state);
1293 if (rc != 0) {
1294 rc = BOOT_EFLASH;
1295 goto out;
1296 }
1297
1298 if (state.image_ok == BOOT_FLAG_UNSET) {
1299 rc = boot_write_image_ok(fap);
1300 }
1301
1302out:
1303 flash_area_close(fap);
1304 return rc;
1305}
1306#endif /* !MCUBOOT_OVERWRITE_ONLY */
1307
1308/**
1309 * Performs an image swap if one is required.
1310 *
1311 * @param out_swap_type On success, the type of swap performed gets
1312 * written here.
1313 *
1314 * @return 0 on success; nonzero on failure.
1315 */
1316static int
1317boot_swap_if_needed(int *out_swap_type)
1318{
1319 struct boot_status bs;
1320 int swap_type;
1321 int rc;
1322
1323 /* Determine if we rebooted in the middle of an image swap
1324 * operation.
1325 */
1326 rc = boot_read_status(&bs);
1327 assert(rc == 0);
1328 if (rc != 0) {
1329 return rc;
1330 }
1331
1332 /* If a partial swap was detected, complete it. */
David Vincze39e78552018-10-10 17:10:01 +02001333 if (bs.idx != BOOT_STATUS_IDX_0 || bs.state != BOOT_STATUS_STATE_0) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001334 rc = boot_copy_image(&bs);
1335 assert(rc == 0);
1336
1337 /* NOTE: here we have finished a swap resume. The initial request
1338 * was either a TEST or PERM swap, which now after the completed
1339 * swap will be determined to be respectively REVERT (was TEST)
1340 * or NONE (was PERM).
1341 */
1342
1343 /* Extrapolate the type of the partial swap. We need this
1344 * information to know how to mark the swap complete in flash.
1345 */
1346 swap_type = boot_previous_swap_type();
1347 } else {
1348 swap_type = boot_validated_swap_type();
1349 switch (swap_type) {
1350 case BOOT_SWAP_TYPE_TEST:
1351 case BOOT_SWAP_TYPE_PERM:
1352 case BOOT_SWAP_TYPE_REVERT:
1353 rc = boot_copy_image(&bs);
1354 assert(rc == 0);
1355 break;
1356 }
1357 }
1358
1359 *out_swap_type = swap_type;
1360 return 0;
1361}
1362
1363/**
1364 * Prepares the booting process. This function moves images around in flash as
1365 * appropriate, and tells you what address to boot from.
1366 *
1367 * @param rsp On success, indicates how booting should occur.
1368 *
1369 * @return 0 on success; nonzero on failure.
1370 */
1371int
1372boot_go(struct boot_rsp *rsp)
1373{
1374 int swap_type;
1375 size_t slot;
1376 int rc;
1377 int fa_id;
1378 bool reload_headers = false;
1379
1380 /* The array of slot sectors are defined here (as opposed to file scope) so
1381 * that they don't get allocated for non-boot-loader apps. This is
1382 * necessary because the gcc option "-fdata-sections" doesn't seem to have
1383 * any effect in older gcc versions (e.g., 4.8.4).
1384 */
1385 static boot_sector_t slot0_sectors[BOOT_MAX_IMG_SECTORS];
1386 static boot_sector_t slot1_sectors[BOOT_MAX_IMG_SECTORS];
Tamas Ban581034a2017-12-19 19:54:37 +00001387
Tamas Banf70ef8c2017-12-19 15:35:09 +00001388 boot_data.imgs[0].sectors = slot0_sectors;
1389 boot_data.imgs[1].sectors = slot1_sectors;
1390
1391 /* Open boot_data image areas for the duration of this call. */
1392 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1393 fa_id = flash_area_id_from_image_slot(slot);
1394 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, slot));
1395 assert(rc == 0);
1396 }
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001397
Tamas Banf70ef8c2017-12-19 15:35:09 +00001398 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH,
1399 &BOOT_SCRATCH_AREA(&boot_data));
1400 assert(rc == 0);
1401
1402 /* Determine the sector layout of the image slots and scratch area. */
1403 rc = boot_read_sectors();
1404 if (rc != 0) {
David Vincze39e78552018-10-10 17:10:01 +02001405 BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d - too small?",
1406 BOOT_MAX_IMG_SECTORS);
Tamas Banf70ef8c2017-12-19 15:35:09 +00001407 goto out;
1408 }
1409
1410 /* Attempt to read an image header from each slot. */
David Vincze39e78552018-10-10 17:10:01 +02001411 rc = boot_read_image_headers(false);
Tamas Banf70ef8c2017-12-19 15:35:09 +00001412 if (rc != 0) {
1413 goto out;
1414 }
1415
1416 /* If the image slots aren't compatible, no swap is possible. Just boot
1417 * into slot 0.
1418 */
1419 if (boot_slots_compatible()) {
1420 rc = boot_swap_if_needed(&swap_type);
1421 assert(rc == 0);
1422 if (rc != 0) {
1423 goto out;
1424 }
1425
1426 /*
1427 * The following states need image_ok be explicitly set after the
1428 * swap was finished to avoid a new revert.
1429 */
Tamas Ban581034a2017-12-19 19:54:37 +00001430 if (swap_type == BOOT_SWAP_TYPE_REVERT ||
1431 swap_type == BOOT_SWAP_TYPE_FAIL) {
Tamas Banf70ef8c2017-12-19 15:35:09 +00001432#ifndef MCUBOOT_OVERWRITE_ONLY
1433 rc = boot_set_image_ok();
1434 if (rc != 0) {
1435 swap_type = BOOT_SWAP_TYPE_PANIC;
1436 }
1437#endif /* !MCUBOOT_OVERWRITE_ONLY */
1438 }
1439 } else {
1440 swap_type = BOOT_SWAP_TYPE_NONE;
1441 }
1442
1443 switch (swap_type) {
1444 case BOOT_SWAP_TYPE_NONE:
1445 slot = 0;
1446 break;
1447
1448 case BOOT_SWAP_TYPE_TEST: /* fallthrough */
1449 case BOOT_SWAP_TYPE_PERM: /* fallthrough */
1450 case BOOT_SWAP_TYPE_REVERT:
1451 slot = 1;
1452 reload_headers = true;
1453#ifndef MCUBOOT_OVERWRITE_ONLY
David Vincze060968d2019-05-23 01:13:14 +02001454 if (swap_type == BOOT_SWAP_TYPE_PERM) {
1455 /* Update the stored security counter with the new image's security
1456 * counter value (the one in the primary slot). Slot 0 holds the
1457 * new image at this point, but slot 1's image header must be
1458 * passed because the read image headers in the boot_data structure
1459 * have not been updated yet.
1460 *
1461 * In case of a permanent image swap mcuboot will never attempt to
1462 * revert the images on the next reboot. Therefore, the security
1463 * counter must be increased right after the image upgrade.
1464 */
1465 rc = boot_update_security_counter(0, boot_img_hdr(&boot_data, 1));
1466 if (rc != 0) {
1467 BOOT_LOG_ERR("Security counter update failed after "
1468 "image upgrade.");
1469 goto out;
1470 }
1471 }
1472
Tamas Banf70ef8c2017-12-19 15:35:09 +00001473 rc = boot_set_copy_done();
1474 if (rc != 0) {
1475 swap_type = BOOT_SWAP_TYPE_PANIC;
1476 }
1477#endif /* !MCUBOOT_OVERWRITE_ONLY */
1478 break;
1479
1480 case BOOT_SWAP_TYPE_FAIL:
1481 /* The image in slot 1 was invalid and is now erased. Ensure we don't
1482 * try to boot into it again on the next reboot. Do this by pretending
1483 * we just reverted back to slot 0.
1484 */
1485 slot = 0;
1486 reload_headers = true;
1487 break;
1488
1489 default:
1490 swap_type = BOOT_SWAP_TYPE_PANIC;
1491 }
1492
1493 if (swap_type == BOOT_SWAP_TYPE_PANIC) {
1494 BOOT_LOG_ERR("panic!");
1495 assert(0);
1496
1497 /* Loop forever... */
David Vincze39e78552018-10-10 17:10:01 +02001498 while (1) {}
Tamas Banf70ef8c2017-12-19 15:35:09 +00001499 }
1500
Tamas Banf70ef8c2017-12-19 15:35:09 +00001501 if (reload_headers) {
David Vincze39e78552018-10-10 17:10:01 +02001502 rc = boot_read_image_headers(false);
Tamas Banf70ef8c2017-12-19 15:35:09 +00001503 if (rc != 0) {
1504 goto out;
1505 }
1506 /* Since headers were reloaded, it can be assumed we just performed a
1507 * swap or overwrite. Now the header info that should be used to
1508 * provide the data for the bootstrap, which previously was at Slot 1,
1509 * was updated to Slot 0.
1510 */
1511 slot = 0;
1512 }
1513
David Vincze39e78552018-10-10 17:10:01 +02001514#ifdef MCUBOOT_VALIDATE_SLOT0
Tamas Banf70ef8c2017-12-19 15:35:09 +00001515 rc = boot_validate_slot(0);
1516 assert(rc == 0);
1517 if (rc != 0) {
1518 rc = BOOT_EBADIMAGE;
1519 goto out;
1520 }
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001521#else /* MCUBOOT_VALIDATE_SLOT0 */
David Vincze39e78552018-10-10 17:10:01 +02001522 /* Even if we're not re-validating slot 0, we could be booting
1523 * onto an empty flash chip. At least do a basic sanity check that
1524 * the magic number on the image is OK.
1525 */
1526 if (boot_data.imgs[0].hdr.ih_magic != IMAGE_MAGIC) {
1527 BOOT_LOG_ERR("bad image magic 0x%lx", (unsigned long)boot_data.imgs[0].hdr.ih_magic);
1528 rc = BOOT_EBADIMAGE;
1529 goto out;
1530 }
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001531#endif /* MCUBOOT_VALIDATE_SLOT0 */
Tamas Banf70ef8c2017-12-19 15:35:09 +00001532
David Vincze060968d2019-05-23 01:13:14 +02001533 /* Update the stored security counter with the active image's security
1534 * counter value. It will be updated only if the new security counter is
1535 * greater than the stored value.
1536 *
1537 * In case of a successful image swapping when the swap type is TEST the
1538 * security counter can be increased only after a reset, when the swap type
1539 * is NONE and the image has marked itself "OK" (the image_ok flag has been
1540 * set). This way a "revert" swap can be performed if it's necessary.
1541 */
1542 if (swap_type == BOOT_SWAP_TYPE_NONE) {
1543 rc = boot_update_security_counter(0, boot_img_hdr(&boot_data, 0));
1544 if (rc != 0) {
1545 BOOT_LOG_ERR("Security counter update failed after image "
1546 "validation.");
1547 goto out;
1548 }
1549 }
1550
Tamas Banf70ef8c2017-12-19 15:35:09 +00001551 /* Always boot from the primary slot. */
1552 rsp->br_flash_dev_id = boot_img_fa_device_id(&boot_data, 0);
1553 rsp->br_image_off = boot_img_slot_off(&boot_data, 0);
1554 rsp->br_hdr = boot_img_hdr(&boot_data, slot);
1555
Tamas Ban0e8ab302019-01-17 11:45:31 +00001556 /* Save boot status to shared memory area */
1557 rc = boot_save_boot_status(SW_S_NS,
1558 rsp->br_hdr,
1559 BOOT_IMG_AREA(&boot_data, slot));
1560 if (rc) {
1561 BOOT_LOG_ERR("Failed to add data to shared area");
1562 }
1563
Tamas Banf70ef8c2017-12-19 15:35:09 +00001564 out:
1565 flash_area_close(BOOT_SCRATCH_AREA(&boot_data));
1566 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1567 flash_area_close(BOOT_IMG_AREA(&boot_data, BOOT_NUM_SLOTS - 1 - slot));
1568 }
1569 return rc;
1570}
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001571
Oliver Swedef9982442018-08-24 18:37:44 +01001572#else /* MCUBOOT_NO_SWAP || MCUBOOT_RAM_LOADING */
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001573
1574#define BOOT_LOG_IMAGE_INFO(area, hdr, state) \
1575 BOOT_LOG_INF("Image %"PRIu32": version=%"PRIu8".%"PRIu8".%"PRIu16"" \
1576 ".%"PRIu32", magic=%5s, image_ok=0x%x", \
1577 (area), \
1578 (hdr)->ih_ver.iv_major, \
1579 (hdr)->ih_ver.iv_minor, \
1580 (hdr)->ih_ver.iv_revision, \
1581 (hdr)->ih_ver.iv_build_num, \
1582 ((state)->magic == BOOT_MAGIC_GOOD ? "good" : \
1583 (state)->magic == BOOT_MAGIC_UNSET ? "unset" : \
1584 "bad"), \
1585 (state)->image_ok)
1586
1587struct image_slot_version {
1588 uint64_t version;
1589 uint32_t slot_number;
1590};
1591
1592/**
1593 * Extract the version number from the image header. This function must be
1594 * ported if version number format has changed in the image header.
1595 *
1596 * @param hdr Pointer to an image header structure
1597 *
Oliver Swedef9982442018-08-24 18:37:44 +01001598 * @return Version number casted to uint64_t
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001599 */
1600static uint64_t
1601boot_get_version_number(struct image_header *hdr)
1602{
Oliver Swedef9982442018-08-24 18:37:44 +01001603 uint64_t version = 0;
1604 version |= (uint64_t)hdr->ih_ver.iv_major << (IMAGE_VER_MINOR_LENGTH
1605 + IMAGE_VER_REVISION_LENGTH
1606 + IMAGE_VER_BUILD_NUM_LENGTH);
1607 version |= (uint64_t)hdr->ih_ver.iv_minor << (IMAGE_VER_REVISION_LENGTH
1608 + IMAGE_VER_BUILD_NUM_LENGTH);
1609 version |= (uint64_t)hdr->ih_ver.iv_revision << IMAGE_VER_BUILD_NUM_LENGTH;
1610 version |= hdr->ih_ver.iv_build_num;
1611 return version;
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001612}
1613
1614/**
1615 * Comparator function for `qsort` to compare version numbers. This function
1616 * must be ported if version number format has changed in the image header.
1617 *
1618 * @param ver1 Pointer to an array element which holds the version number
1619 * @param ver2 Pointer to another array element which holds the version
1620 * number
1621 *
1622 * @return if version1 > version2 -1
1623 * if version1 == version2 0
1624 * if version1 < version2 1
1625 */
1626static int
1627boot_compare_version_numbers(const void *ver1, const void *ver2)
1628{
1629 if (((struct image_slot_version *)ver1)->version <
1630 ((struct image_slot_version *)ver2)->version) {
1631 return 1;
1632 }
1633
1634 if (((struct image_slot_version *)ver1)->version ==
1635 ((struct image_slot_version *)ver2)->version) {
1636 return 0;
1637 }
1638
1639 return -1;
1640}
1641
1642/**
1643 * Sort the available images based on the version number and puts them in
1644 * a list.
1645 *
1646 * @param boot_sequence A pointer to an array, whose aim is to carry
1647 * the boot order of candidate images.
1648 * @param slot_cnt The number of flash areas, which can contains firmware
1649 * images.
1650 *
1651 * @return The number of valid images.
1652 */
1653uint32_t
1654boot_get_boot_sequence(uint32_t *boot_sequence, uint32_t slot_cnt)
1655{
1656 struct boot_swap_state slot_state;
1657 struct image_header *hdr;
1658 struct image_slot_version image_versions[BOOT_NUM_SLOTS] = {{0}};
1659 uint32_t image_cnt = 0;
1660 uint32_t slot;
1661 int32_t rc;
1662 int32_t fa_id;
1663
1664 for (slot = 0; slot < slot_cnt; slot++) {
1665 hdr = boot_img_hdr(&boot_data, slot);
1666 fa_id = flash_area_id_from_image_slot(slot);
1667 rc = boot_read_swap_state_by_id(fa_id, &slot_state);
1668 if (rc != 0) {
1669 BOOT_LOG_ERR("Error during reading image trailer from slot:"
1670 " %"PRIu32"", slot);
1671 continue;
1672 }
1673
1674 if (hdr->ih_magic == IMAGE_MAGIC) {
1675 if (slot_state.magic == BOOT_MAGIC_GOOD ||
David Vincze39e78552018-10-10 17:10:01 +02001676 slot_state.image_ok == BOOT_FLAG_SET) {
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001677 /* Valid cases:
1678 * - Test mode: magic is OK in image trailer
1679 * - Permanent mode: image_ok flag has previously set
1680 */
1681 image_versions[slot].slot_number = slot;
1682 image_versions[slot].version = boot_get_version_number(hdr);
1683 image_cnt++;
1684 }
1685
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001686 BOOT_LOG_IMAGE_INFO(slot, hdr, &slot_state);
1687 } else {
Oliver Swedef9982442018-08-24 18:37:44 +01001688 BOOT_LOG_INF("Image %"PRIu32": No valid image", slot);
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001689 }
1690 }
1691
1692 /* Sort the images based on version number */
1693 qsort(&image_versions[0],
1694 slot_cnt,
1695 sizeof(struct image_slot_version),
1696 boot_compare_version_numbers);
1697
1698 /* Copy the calculated boot sequence to boot_sequence array */
1699 for (slot = 0; slot < slot_cnt; slot++) {
1700 boot_sequence[slot] = image_versions[slot].slot_number;
1701 }
1702
1703 return image_cnt;
1704}
1705
Oliver Swedef9982442018-08-24 18:37:44 +01001706#ifdef MCUBOOT_RAM_LOADING
1707/**
1708 * Copies an image from a slot in the flash to an SRAM address, where the load
1709 * address has already been inserted into the image header by this point and is
1710 * extracted from it within this method. The copying is done sector-by-sector.
1711 *
1712 * @param slot The flash slot of the image to be copied to SRAM.
1713 *
1714 * @param hdr Pointer to the image header structure of the image
1715 * that needs to be copid to SRAM
1716 *
1717 * @return 0 on success; nonzero on failure.
1718 */
1719static int
1720boot_copy_image_to_sram(int slot, struct image_header *hdr)
1721{
1722 int rc;
1723 uint32_t sect_sz;
1724 uint32_t sect = 0;
1725 uint32_t bytes_copied = 0;
1726 const struct flash_area *fap_src = NULL;
1727 uint32_t dst = (uint32_t) hdr->ih_load_addr;
1728 uint32_t img_sz;
1729
1730 if (dst % 4 != 0) {
1731 BOOT_LOG_INF("Cannot copy the image to the SRAM address 0x%"PRIx32" "
1732 "- the load address must be aligned with 4 bytes due to SRAM "
1733 "restrictions", dst);
1734 return BOOT_EBADARGS;
1735 }
1736
1737 rc = flash_area_open(flash_area_id_from_image_slot(slot), &fap_src);
1738 if (rc != 0) {
1739 return BOOT_EFLASH;
1740 }
1741
1742 rc = boot_read_image_size(slot, hdr, &img_sz);
1743 if (rc != 0) {
1744 return BOOT_EFLASH;
1745 }
1746
1747 while (bytes_copied < img_sz) {
1748 sect_sz = boot_img_sector_size(&boot_data, slot, sect);
1749 /*
1750 * Direct copy from where the image sector resides in flash to its new
1751 * location in SRAM
1752 */
1753 rc = flash_area_read(fap_src,
1754 bytes_copied,
1755 (void *)(dst + bytes_copied),
1756 sect_sz);
1757 if (rc != 0) {
1758 BOOT_LOG_INF("Error whilst copying image from Flash to SRAM");
1759 break;
1760 } else {
1761 bytes_copied += sect_sz;
1762 }
1763 sect++;
1764 }
1765
1766 if (fap_src) {
1767 flash_area_close(fap_src);
1768 }
1769 return rc;
1770}
1771#endif /* MCUBOOT_RAM_LOADING */
1772
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001773/**
1774 * Prepares the booting process. This function choose the newer image in flash
1775 * as appropriate, and returns the address to boot from.
1776 *
1777 * @param rsp On success, indicates how booting should occur.
1778 *
1779 * @return 0 on success; nonzero on failure.
1780 */
1781int
1782boot_go(struct boot_rsp *rsp)
1783{
1784 size_t slot = 0;
1785 int32_t i;
1786 int rc;
1787 int fa_id;
1788 uint32_t boot_sequence[BOOT_NUM_SLOTS];
1789 uint32_t img_cnt;
Oliver Swedef9982442018-08-24 18:37:44 +01001790 struct image_header *newest_image_header;
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001791
1792 static boot_sector_t slot0_sectors[BOOT_MAX_IMG_SECTORS];
1793 static boot_sector_t slot1_sectors[BOOT_MAX_IMG_SECTORS];
1794
1795 boot_data.imgs[0].sectors = &slot0_sectors[0];
1796 boot_data.imgs[1].sectors = &slot1_sectors[0];
1797
1798 /* Open boot_data image areas for the duration of this call. */
1799 for (i = 0; i < BOOT_NUM_SLOTS; i++) {
1800 fa_id = flash_area_id_from_image_slot(i);
1801 rc = flash_area_open(fa_id, &BOOT_IMG_AREA(&boot_data, i));
1802 assert(rc == 0);
1803 }
1804
1805 /* Determine the sector layout of the image slots. */
1806 rc = boot_read_sectors();
1807 if (rc != 0) {
David Vincze39e78552018-10-10 17:10:01 +02001808 BOOT_LOG_WRN("Failed reading sectors; BOOT_MAX_IMG_SECTORS=%d - too small?",
1809 BOOT_MAX_IMG_SECTORS);
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001810 goto out;
1811 }
1812
1813 /* Attempt to read an image header from each slot. */
David Vincze39e78552018-10-10 17:10:01 +02001814 rc = boot_read_image_headers(false);
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001815 if (rc != 0) {
1816 goto out;
1817 }
1818
1819 img_cnt = boot_get_boot_sequence(boot_sequence, BOOT_NUM_SLOTS);
1820 if (img_cnt) {
1821 /* Authenticate images */
1822 for (i = 0; i < img_cnt; i++) {
1823 rc = boot_validate_slot(boot_sequence[i]);
1824 if (rc == 0) {
1825 slot = boot_sequence[i];
1826 break;
1827 }
1828 }
1829 if (rc) {
1830 /* If there was no valid image at all */
1831 rc = BOOT_EBADIMAGE;
1832 goto out;
1833 }
1834
Oliver Swedef9982442018-08-24 18:37:44 +01001835 /* The slot variable now refers to the newest image's slot in flash */
1836 newest_image_header = boot_img_hdr(&boot_data, slot);
1837
David Vincze060968d2019-05-23 01:13:14 +02001838 /* Update the security counter with the newest image's security
1839 * counter value.
1840 */
1841 rc = boot_update_security_counter(slot, newest_image_header);
1842 if (rc != 0) {
1843 BOOT_LOG_ERR("Security counter update failed after image "
1844 "validation.");
1845 goto out;
1846 }
1847
Oliver Swedef9982442018-08-24 18:37:44 +01001848 #ifdef MCUBOOT_RAM_LOADING
1849 if (newest_image_header->ih_flags & IMAGE_F_RAM_LOAD) {
1850 /* Copy image to the load address from where it
1851 * currently resides in flash */
1852 rc = boot_copy_image_to_sram(slot, newest_image_header);
1853 if (rc != 0) {
1854 rc = BOOT_EBADIMAGE;
1855 BOOT_LOG_INF("Could not copy image from slot 0x%"PRIx32" in "
1856 "the Flash to load address 0x%"PRIx32" in SRAM, "
1857 "aborting..",
1858 slot,
1859 newest_image_header->ih_load_addr);
1860 goto out;
1861 } else {
1862 BOOT_LOG_INF("Image has been copied from slot %d in flash to "
1863 "SRAM address 0x%"PRIx32"",
1864 slot,
1865 newest_image_header->ih_load_addr);
1866 }
1867
1868 /* Validate the image hash in SRAM after the copy was successful */
1869 rc = bootutil_check_hash_after_loading(newest_image_header);
1870 if (rc != 0) {
1871 rc = BOOT_EBADIMAGE;
1872 BOOT_LOG_INF("Cannot validate the hash of the image that was "
1873 "copied to SRAM, aborting..");
1874 goto out;
1875 }
1876
1877 BOOT_LOG_INF("Booting image from SRAM at address 0x%"PRIx32"",
1878 newest_image_header->ih_load_addr);
1879 } else {
David Vincze8a2a4e22019-05-24 10:14:23 +02001880#endif /* MCUBOOT_RAM_LOADING */
Oliver Swedef9982442018-08-24 18:37:44 +01001881 BOOT_LOG_INF("Booting image from slot %d", slot);
David Vincze8a2a4e22019-05-24 10:14:23 +02001882#ifdef MCUBOOT_RAM_LOADING
Oliver Swedef9982442018-08-24 18:37:44 +01001883 }
David Vincze8a2a4e22019-05-24 10:14:23 +02001884#endif
Oliver Swedef9982442018-08-24 18:37:44 +01001885
1886 rsp->br_hdr = newest_image_header;
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001887 rsp->br_image_off = boot_img_slot_off(&boot_data, slot);
Oliver Swedef9982442018-08-24 18:37:44 +01001888 rsp->br_flash_dev_id = boot_img_fa_device_id(&boot_data, slot);
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001889 } else {
1890 /* No candidate image available */
1891 rc = BOOT_EBADIMAGE;
David Vincze060968d2019-05-23 01:13:14 +02001892 goto out;
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001893 }
1894
Tamas Ban0e8ab302019-01-17 11:45:31 +00001895 /* Save boot status to shared memory area */
1896 rc = boot_save_boot_status(SW_S_NS,
1897 rsp->br_hdr,
1898 BOOT_IMG_AREA(&boot_data, slot));
1899 if (rc) {
1900 BOOT_LOG_ERR("Failed to add data to shared area");
1901 }
1902
Tamas Ban4fb8e9d2018-02-23 14:22:03 +00001903out:
1904 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
1905 flash_area_close(BOOT_IMG_AREA(&boot_data, BOOT_NUM_SLOTS - 1 - slot));
1906 }
1907 return rc;
1908}
Oliver Swedef9982442018-08-24 18:37:44 +01001909#endif /* MCUBOOT_NO_SWAP || MCUBOOT_RAM_LOADING */