blob: e4dfc6159119c13636f3405532058f75c9eb5da6 [file] [log] [blame]
Christopher Collins92ea77f2016-12-12 15:59:26 -08001/*
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
20/**
21 * This file provides an interface to the boot loader. Functions defined in
22 * this file should only be called while the boot loader is running.
23 */
24
25#include <assert.h>
26#include <stddef.h>
27#include <inttypes.h>
28#include <stdlib.h>
29#include <string.h>
30#include "sysflash/sysflash.h"
31#include "flash_map/flash_map.h"
32#include <hal/hal_flash.h>
33#include <os/os_malloc.h>
34#include "bootutil/bootutil.h"
35#include "bootutil/image.h"
36#include "bootutil_priv.h"
37
38#define BOOT_MAX_IMG_SECTORS 120
39
40/** Number of image slots in flash; currently limited to two. */
41#define BOOT_NUM_SLOTS 2
42
43static struct {
44 struct {
45 struct image_header hdr;
46 struct flash_area *sectors;
Christopher Collins0ff3c6c2016-12-21 12:04:17 -080047 int num_sectors;
Christopher Collins92ea77f2016-12-12 15:59:26 -080048 } imgs[BOOT_NUM_SLOTS];
49
Christopher Collins92ea77f2016-12-12 15:59:26 -080050 struct flash_area scratch_sector;
51
52 uint8_t write_sz;
53} boot_data;
54
55struct boot_status_table {
56 /**
57 * For each field, a value of 0 means "any".
58 */
59 uint8_t bst_magic_slot0;
60 uint8_t bst_magic_scratch;
61 uint8_t bst_copy_done_slot0;
62 uint8_t bst_status_source;
63};
64
65/**
66 * This set of tables maps swap state contents to boot status location.
67 * When searching for a match, these tables must be iterated in order.
68 */
69static const struct boot_status_table boot_status_tables[] = {
70 {
71 /* | slot-0 | scratch |
72 * ----------+------------+------------|
73 * magic | Good | Any |
74 * copy-done | 0x01 | N/A |
75 * ----------+------------+------------'
76 * source: none |
77 * ------------------------------------'
78 */
79 .bst_magic_slot0 = BOOT_MAGIC_GOOD,
80 .bst_magic_scratch = 0,
81 .bst_copy_done_slot0 = 0x01,
82 .bst_status_source = BOOT_STATUS_SOURCE_NONE,
83 },
84
85 {
86 /* | slot-0 | scratch |
87 * ----------+------------+------------|
88 * magic | Good | Any |
89 * copy-done | 0xff | N/A |
90 * ----------+------------+------------'
91 * source: slot 0 |
92 * ------------------------------------'
93 */
94 .bst_magic_slot0 = BOOT_MAGIC_GOOD,
95 .bst_magic_scratch = 0,
96 .bst_copy_done_slot0 = 0xff,
97 .bst_status_source = BOOT_STATUS_SOURCE_SLOT0,
98 },
99
100 {
101 /* | slot-0 | scratch |
102 * ----------+------------+------------|
103 * magic | Any | Good |
104 * copy-done | Any | N/A |
105 * ----------+------------+------------'
106 * source: scratch |
107 * ------------------------------------'
108 */
109 .bst_magic_slot0 = 0,
110 .bst_magic_scratch = BOOT_MAGIC_GOOD,
111 .bst_copy_done_slot0 = 0,
112 .bst_status_source = BOOT_STATUS_SOURCE_SCRATCH,
113 },
114
115 {
116 /* | slot-0 | scratch |
117 * ----------+------------+------------|
118 * magic | Unset | Any |
119 * copy-done | 0xff | N/A |
120 * ----------+------------+------------|
121 * source: varies |
122 * ------------------------------------+------------------------------+
123 * This represents one of two cases: |
124 * o No swaps ever (no status to read, so no harm in checking). |
125 * o Mid-revert; status in slot 0. |
126 * -------------------------------------------------------------------'
127 */
128 .bst_magic_slot0 = BOOT_MAGIC_UNSET,
129 .bst_magic_scratch = 0,
130 .bst_copy_done_slot0 = 0xff,
131 .bst_status_source = BOOT_STATUS_SOURCE_SLOT0,
132 },
133};
134
135#define BOOT_STATUS_TABLES_COUNT \
136 (sizeof boot_status_tables / sizeof boot_status_tables[0])
137
138/**
139 * This table indicates the next swap type that should be performed. The first
140 * column contains the current swap type. The second column contains the swap
141 * type that should be effected after the first completes.
142 */
143static const uint8_t boot_swap_trans_table[][2] = {
144 /* From To */
145 { BOOT_SWAP_TYPE_REVERT, BOOT_SWAP_TYPE_NONE },
146 { BOOT_SWAP_TYPE_TEST, BOOT_SWAP_TYPE_REVERT },
147};
148
149#define BOOT_SWAP_TRANS_TABLE_SIZE \
150 (sizeof boot_swap_trans_table / sizeof boot_swap_trans_table[0])
151
152/**
153 * Determines where in flash the most recent boot status is stored. The boot
154 * status is necessary for completing a swap that was interrupted by a boot
155 * loader reset.
156 *
157 * @return A BOOT_STATUS_SOURCE_[...] code indicating where * status should be read from.
158 */
159static int
160boot_status_source(void)
161{
162 const struct boot_status_table *table;
163 struct boot_swap_state state_scratch;
164 struct boot_swap_state state_slot0;
165 struct boot_swap_state state_slot1;
166 int rc;
167 int i;
168
169 rc = boot_read_swap_state_img(0, &state_slot0);
170 assert(rc == 0);
171
172 rc = boot_read_swap_state_img(1, &state_slot1);
173 assert(rc == 0);
174
175 rc = boot_read_swap_state_scratch(&state_scratch);
176 assert(rc == 0);
177
178 for (i = 0; i < BOOT_STATUS_TABLES_COUNT; i++) {
179 table = boot_status_tables + i;
180
181 if ((table->bst_magic_slot0 == 0 ||
182 table->bst_magic_slot0 == state_slot0.magic) &&
183 (table->bst_magic_scratch == 0 ||
184 table->bst_magic_scratch == state_scratch.magic) &&
185 (table->bst_copy_done_slot0 == 0 ||
186 table->bst_copy_done_slot0 == state_slot0.copy_done)) {
187
188 return table->bst_status_source;
189 }
190 }
191
192 return BOOT_STATUS_SOURCE_NONE;
193}
194
195/**
196 * Calculates the type of swap that just completed.
197 */
198static int
199boot_previous_swap_type(void)
200{
201 int post_swap_type;
202 int i;
203
204 post_swap_type = boot_swap_type();
205
206 for (i = 0; i < BOOT_SWAP_TRANS_TABLE_SIZE; i++){
207 if (boot_swap_trans_table[i][1] == post_swap_type) {
208 return boot_swap_trans_table[i][0];
209 }
210 }
211
212 /* XXX: Temporary assert. */
213 assert(0);
214
215 return BOOT_SWAP_TYPE_REVERT;
216}
217
218static int
219boot_read_image_header(int slot, struct image_header *out_hdr)
220{
221 const struct flash_area *fap;
222 int area_id;
223 int rc;
224
225 area_id = flash_area_id_from_image_slot(slot);
226 rc = flash_area_open(area_id, &fap);
227 if (rc != 0) {
228 rc = BOOT_EFLASH;
229 goto done;
230 }
231
232 rc = flash_area_read(fap, 0, out_hdr, sizeof *out_hdr);
233 if (rc != 0) {
234 rc = BOOT_EFLASH;
235 goto done;
236 }
237
238 rc = 0;
239
240done:
241 flash_area_close(fap);
242 return rc;
243}
244
245static int
246boot_read_image_headers(void)
247{
248 int rc;
249 int i;
250
251 for (i = 0; i < BOOT_NUM_SLOTS; i++) {
252 rc = boot_read_image_header(i, &boot_data.imgs[i].hdr);
253 if (rc != 0) {
Christopher Collins0ff3c6c2016-12-21 12:04:17 -0800254 /* If at least one header was read successfully, then the boot
255 * loader can attempt a boot. Failure to read any headers is a
256 * fatal error.
257 */
258 if (i > 0) {
259 return 0;
260 } else {
261 return rc;
262 }
Christopher Collins92ea77f2016-12-12 15:59:26 -0800263 }
264 }
265
266 return 0;
267}
268
269static uint8_t
270boot_write_sz(void)
271{
272 uint8_t elem_sz;
273 uint8_t align;
274
275 /* Figure out what size to write update status update as. The size depends
276 * on what the minimum write size is for scratch area, active image slot.
277 * We need to use the bigger of those 2 values.
278 */
279 elem_sz = hal_flash_align(boot_data.imgs[0].sectors[0].fa_device_id);
280 align = hal_flash_align(boot_data.scratch_sector.fa_device_id);
281 if (align > elem_sz) {
282 elem_sz = align;
283 }
284
285 return elem_sz;
286}
287
Christopher Collins0ff3c6c2016-12-21 12:04:17 -0800288static int
289boot_slots_compatible(void)
290{
291 const struct flash_area *sector0;
292 const struct flash_area *sector1;
293 int i;
294
295 /* Ensure both image slots have identical sector layouts. */
296 if (boot_data.imgs[0].num_sectors != boot_data.imgs[1].num_sectors) {
297 return 0;
298 }
299 for (i = 0; i < boot_data.imgs[0].num_sectors; i++) {
300 sector0 = boot_data.imgs[0].sectors + i;
301 sector1 = boot_data.imgs[1].sectors + i;
302 if (sector0->fa_size != sector1->fa_size) {
303 return 0;
304 }
305 }
306
307 return 1;
308}
309
Christopher Collins92ea77f2016-12-12 15:59:26 -0800310/**
311 * Determines the sector layout of both image slots and the scratch area.
312 * This information is necessary for calculating the number of bytes to erase
313 * and copy during an image swap. The information collected during this
314 * function is used to populate the boot_data global.
315 */
316static int
317boot_read_sectors(void)
318{
Christopher Collins92ea77f2016-12-12 15:59:26 -0800319 const struct flash_area *scratch;
320 int num_sectors_slot0;
321 int num_sectors_slot1;
322 int rc;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800323
324 num_sectors_slot0 = BOOT_MAX_IMG_SECTORS;
325 rc = flash_area_to_sectors(FLASH_AREA_IMAGE_0, &num_sectors_slot0,
326 boot_data.imgs[0].sectors);
327 if (rc != 0) {
328 return BOOT_EFLASH;
329 }
Christopher Collins0ff3c6c2016-12-21 12:04:17 -0800330 boot_data.imgs[0].num_sectors = num_sectors_slot0;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800331
332 num_sectors_slot1 = BOOT_MAX_IMG_SECTORS;
333 rc = flash_area_to_sectors(FLASH_AREA_IMAGE_1, &num_sectors_slot1,
334 boot_data.imgs[1].sectors);
335 if (rc != 0) {
336 return BOOT_EFLASH;
337 }
Christopher Collins0ff3c6c2016-12-21 12:04:17 -0800338 boot_data.imgs[1].num_sectors = num_sectors_slot1;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800339
340 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &scratch);
341 if (rc != 0) {
342 return BOOT_EFLASH;
343 }
344 boot_data.scratch_sector = *scratch;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800345
346 boot_data.write_sz = boot_write_sz();
347
348 return 0;
349}
350
351static uint32_t
352boot_status_internal_off(int idx, int state, int elem_sz)
353{
354 int idx_sz;
355
356 idx_sz = elem_sz * BOOT_STATUS_STATE_COUNT;
357
358 return idx * idx_sz + state * elem_sz;
359}
360
361/**
362 * Reads the status of a partially-completed swap, if any. This is necessary
363 * to recover in case the boot lodaer was reset in the middle of a swap
364 * operation.
365 */
366static int
367boot_read_status_bytes(const struct flash_area *fap, struct boot_status *bs)
368{
369 uint32_t off;
370 uint8_t status;
371 int found;
372 int rc;
373 int i;
374
375 off = boot_status_off(fap);
376
377 found = 0;
378 for (i = 0; i < BOOT_STATUS_MAX_ENTRIES; i++) {
379 rc = flash_area_read(fap, off + i * boot_data.write_sz, &status, 1);
380 if (rc != 0) {
381 return BOOT_EFLASH;
382 }
383
384 if (status == 0xff) {
385 if (found) {
386 break;
387 }
388 } else if (!found) {
389 found = 1;
390 }
391 }
392
393 if (found) {
394 i--;
395 bs->idx = i / BOOT_STATUS_STATE_COUNT;
396 bs->state = i % BOOT_STATUS_STATE_COUNT;
397 }
398
399 return 0;
400}
401
402/**
403 * Reads the boot status from the flash. The boot status contains
404 * the current state of an interrupted image copy operation. If the boot
405 * status is not present, or it indicates that previous copy finished,
406 * there is no operation in progress.
407 */
408static int
409boot_read_status(struct boot_status *bs)
410{
411 const struct flash_area *fap;
412 int status_loc;
413 int area_id;
414 int rc;
415
416 memset(bs, 0, sizeof *bs);
417
418 status_loc = boot_status_source();
419 switch (status_loc) {
420 case BOOT_STATUS_SOURCE_NONE:
421 return 0;
422
423 case BOOT_STATUS_SOURCE_SCRATCH:
424 area_id = FLASH_AREA_IMAGE_SCRATCH;
425 break;
426
427 case BOOT_STATUS_SOURCE_SLOT0:
428 area_id = FLASH_AREA_IMAGE_0;
429 break;
430
431 default:
432 assert(0);
433 return BOOT_EBADARGS;
434 }
435
436 rc = flash_area_open(area_id, &fap);
437 if (rc != 0) {
438 return BOOT_EFLASH;
439 }
440
441 rc = boot_read_status_bytes(fap, bs);
442 if (rc != 0) {
443 return rc;
444 }
445
446 return 0;
447}
448
449/**
450 * Writes the supplied boot status to the flash file system. The boot status
451 * contains the current state of an in-progress image copy operation.
452 *
453 * @param bs The boot status to write.
454 *
455 * @return 0 on success; nonzero on failure.
456 */
457int
458boot_write_status(struct boot_status *bs)
459{
460 const struct flash_area *fap;
461 uint32_t off;
462 int area_id;
463 int rc;
464
465 if (bs->idx == 0) {
466 /* Write to scratch. */
467 area_id = FLASH_AREA_IMAGE_SCRATCH;
468 } else {
469 /* Write to slot 0. */
470 area_id = FLASH_AREA_IMAGE_0;
471 }
472
473 rc = flash_area_open(area_id, &fap);
474 if (rc != 0) {
475 rc = BOOT_EFLASH;
476 goto done;
477 }
478
479 off = boot_status_off(fap) +
480 boot_status_internal_off(bs->idx, bs->state, boot_data.write_sz);
481
482 rc = flash_area_write(fap, off, &bs->state, 1);
483 if (rc != 0) {
484 rc = BOOT_EFLASH;
485 goto done;
486 }
487
488 rc = 0;
489
490done:
491 flash_area_close(fap);
492 return rc;
493}
494
495/*
496 * Validate image hash/signature in a slot.
497 */
498static int
499boot_image_check(struct image_header *hdr, const struct flash_area *fap)
500{
501 static void *tmpbuf;
502
503 if (!tmpbuf) {
504 tmpbuf = malloc(BOOT_TMPBUF_SZ);
505 if (!tmpbuf) {
506 return BOOT_ENOMEM;
507 }
508 }
509 if (bootutil_img_validate(hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
510 NULL, 0, NULL)) {
511 return BOOT_EBADIMAGE;
512 }
513 return 0;
514}
515
516static int
517split_image_check(struct image_header *app_hdr,
518 const struct flash_area *app_fap,
519 struct image_header *loader_hdr,
520 const struct flash_area *loader_fap)
521{
522 static void *tmpbuf;
523 uint8_t loader_hash[32];
524
525 if (!tmpbuf) {
526 tmpbuf = malloc(BOOT_TMPBUF_SZ);
527 if (!tmpbuf) {
528 return BOOT_ENOMEM;
529 }
530 }
531
532 if (bootutil_img_validate(loader_hdr, loader_fap, tmpbuf, BOOT_TMPBUF_SZ,
533 NULL, 0, loader_hash)) {
534 return BOOT_EBADIMAGE;
535 }
536
537 if (bootutil_img_validate(app_hdr, app_fap, tmpbuf, BOOT_TMPBUF_SZ,
538 loader_hash, 32, NULL)) {
539 return BOOT_EBADIMAGE;
540 }
541
542 return 0;
543}
544
545static int
546boot_validate_slot1(void)
547{
548 const struct flash_area *fap;
549 int rc;
550
551 if (boot_data.imgs[1].hdr.ih_magic == 0xffffffff ||
552 boot_data.imgs[1].hdr.ih_flags & IMAGE_F_NON_BOOTABLE) {
553
554 /* No bootable image in slot 1; continue booting from slot 0. */
555 return -1;
556 }
557
558 /* Image in slot 1 is invalid. Erase the image and continue booting
559 * from slot 0.
560 */
561 rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
562 if (rc != 0) {
563 return BOOT_EFLASH;
564 }
565
566 if (boot_data.imgs[1].hdr.ih_magic != IMAGE_MAGIC ||
567 boot_image_check(&boot_data.imgs[1].hdr, fap) != 0) {
568
569 /* Image in slot 1 is invalid. Erase the image and continue booting
570 * from slot 0.
571 */
572 flash_area_erase(fap, 0, fap->fa_size);
573 return -1;
574 }
575
576 flash_area_close(fap);
577
578 /* Image in slot 1 is valid. */
579 return 0;
580}
581
582/**
583 * Determines which swap operation to perform, if any. If it is determined
584 * that a swap operation is required, the image in the second slot is checked
585 * for validity. If the image in the second slot is invalid, it is erased, and
586 * a swap type of "none" is indicated.
587 *
588 * @return The type of swap to perform (BOOT_SWAP_TYPE...)
589 */
590static int
591boot_validated_swap_type(void)
592{
593 int swap_type;
594 int rc;
595
596 swap_type = boot_swap_type();
597 if (swap_type == BOOT_SWAP_TYPE_NONE) {
598 /* Continue using slot 0. */
599 return BOOT_SWAP_TYPE_NONE;
600 }
601
602 /* Boot loader wants to switch to slot 1. Ensure image is valid. */
603 rc = boot_validate_slot1();
604 if (rc != 0) {
605 return BOOT_SWAP_TYPE_FAIL;
606 }
607
608 return swap_type;
609}
610
611/**
612 * Calculates the number of sectors the scratch area can contain. A "last"
613 * source sector is specified because images are copied backwards in flash
614 * (final index to index number 0).
615 *
616 * @param last_sector_idx The index of the last source sector
617 * (inclusive).
618 * @param out_first_sector_idx The index of the first source sector
619 * (inclusive) gets written here.
620 *
621 * @return The number of bytes comprised by the
622 * [first-sector, last-sector] range.
623 */
624static uint32_t
625boot_copy_sz(int last_sector_idx, int *out_first_sector_idx)
626{
627 uint32_t new_sz;
628 uint32_t sz;
629 int i;
630
631 sz = 0;
632
633 for (i = last_sector_idx; i >= 0; i--) {
634 new_sz = sz + boot_data.imgs[0].sectors[i].fa_size;
635 if (new_sz > boot_data.scratch_sector.fa_size) {
636 break;
637 }
638 sz = new_sz;
639 }
640
641 /* i currently refers to a sector that doesn't fit or it is -1 because all
642 * sectors have been processed. In both cases, exclude sector i.
643 */
644 *out_first_sector_idx = i + 1;
645 return sz;
646}
647
648/**
649 * Erases a region of flash.
650 *
651 * @param flash_area_idx The ID of the flash area containing the region
652 * to erase.
653 * @param off The offset within the flash area to start the
654 * erase.
655 * @param sz The number of bytes to erase.
656 *
657 * @return 0 on success; nonzero on failure.
658 */
659static int
660boot_erase_sector(int flash_area_id, uint32_t off, uint32_t sz)
661{
662 const struct flash_area *fap;
663 int rc;
664
665 rc = flash_area_open(flash_area_id, &fap);
666 if (rc != 0) {
667 rc = BOOT_EFLASH;
668 goto done;
669 }
670
671 rc = flash_area_erase(fap, off, sz);
672 if (rc != 0) {
673 rc = BOOT_EFLASH;
674 goto done;
675 }
676
677 rc = 0;
678
679done:
680 flash_area_close(fap);
681 return rc;
682}
683
684/**
685 * Copies the contents of one flash region to another. You must erase the
686 * destination region prior to calling this function.
687 *
688 * @param flash_area_id_src The ID of the source flash area.
689 * @param flash_area_id_dst The ID of the destination flash area.
690 * @param off_src The offset within the source flash area to
691 * copy from.
692 * @param off_dst The offset within the destination flash area to
693 * copy to.
694 * @param sz The number of bytes to copy.
695 *
696 * @return 0 on success; nonzero on failure.
697 */
698static int
699boot_copy_sector(int flash_area_id_src, int flash_area_id_dst,
700 uint32_t off_src, uint32_t off_dst, uint32_t sz)
701{
702 const struct flash_area *fap_src;
703 const struct flash_area *fap_dst;
704 uint32_t bytes_copied;
705 int chunk_sz;
706 int rc;
707
708 static uint8_t buf[1024];
709
710 fap_src = NULL;
711 fap_dst = NULL;
712
713 rc = flash_area_open(flash_area_id_src, &fap_src);
714 if (rc != 0) {
715 rc = BOOT_EFLASH;
716 goto done;
717 }
718
719 rc = flash_area_open(flash_area_id_dst, &fap_dst);
720 if (rc != 0) {
721 rc = BOOT_EFLASH;
722 goto done;
723 }
724
725 bytes_copied = 0;
726 while (bytes_copied < sz) {
727 if (sz - bytes_copied > sizeof buf) {
728 chunk_sz = sizeof buf;
729 } else {
730 chunk_sz = sz - bytes_copied;
731 }
732
733 rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz);
734 if (rc != 0) {
735 rc = BOOT_EFLASH;
736 goto done;
737 }
738
739 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
740 if (rc != 0) {
741 rc = BOOT_EFLASH;
742 goto done;
743 }
744
745 bytes_copied += chunk_sz;
746 }
747
748 rc = 0;
749
750done:
751 flash_area_close(fap_src);
752 flash_area_close(fap_dst);
753 return rc;
754}
755
756/**
757 * Swaps the contents of two flash regions within the two image slots.
758 *
759 * @param idx The index of the first sector in the range of
760 * sectors being swapped.
761 * @param sz The number of bytes to swap.
762 * @param bs The current boot status. This struct gets
763 * updated according to the outcome.
764 *
765 * @return 0 on success; nonzero on failure.
766 */
767static int
768boot_swap_sectors(int idx, uint32_t sz, struct boot_status *bs)
769{
770 uint32_t copy_sz;
771 uint32_t img_off;
772 int rc;
773
774 /* Calculate offset from start of image area. */
775 img_off = boot_data.imgs[0].sectors[idx].fa_off -
776 boot_data.imgs[0].sectors[0].fa_off;
777
778 if (bs->state == 0) {
779 rc = boot_erase_sector(FLASH_AREA_IMAGE_SCRATCH, 0, sz);
780 if (rc != 0) {
781 return rc;
782 }
783
784 rc = boot_copy_sector(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_SCRATCH,
785 img_off, 0, sz);
786 if (rc != 0) {
787 return rc;
788 }
789
790 bs->state = 1;
791 (void)boot_write_status(bs);
792 }
793 if (bs->state == 1) {
794 rc = boot_erase_sector(FLASH_AREA_IMAGE_1, img_off, sz);
795 if (rc != 0) {
796 return rc;
797 }
798
799 copy_sz = sz;
800 if (boot_data.imgs[0].sectors[idx].fa_off + sz >=
801 boot_data.imgs[1].sectors[0].fa_off) {
802
803 /* This is the end of the area. Don't copy the image state into
804 * slot 1.
805 */
806 copy_sz -= boot_trailer_sz(boot_data.write_sz);
807 }
808
809 rc = boot_copy_sector(FLASH_AREA_IMAGE_0, FLASH_AREA_IMAGE_1,
810 img_off, img_off, copy_sz);
811 if (rc != 0) {
812 return rc;
813 }
814
815 bs->state = 2;
816 (void)boot_write_status(bs);
817 }
818 if (bs->state == 2) {
819 rc = boot_erase_sector(FLASH_AREA_IMAGE_0, img_off, sz);
820 if (rc != 0) {
821 return rc;
822 }
823
824 rc = boot_copy_sector(FLASH_AREA_IMAGE_SCRATCH, FLASH_AREA_IMAGE_0,
825 0, img_off, sz);
826 if (rc != 0) {
827 return rc;
828 }
829
830 bs->idx++;
831 bs->state = 0;
832 (void)boot_write_status(bs);
833 }
834
835 return 0;
836}
837
838/**
839 * Swaps the two images in flash. If a prior copy operation was interrupted
840 * by a system reset, this function completes that operation.
841 *
842 * @param bs The current boot status. This function reads
843 * this struct to determine if it is resuming
844 * an interrupted swap operation. This
845 * function writes the updated status to this
846 * function on return.
847 *
848 * @return 0 on success; nonzero on failure.
849 */
850static int
851boot_copy_image(struct boot_status *bs)
852{
853 uint32_t sz;
854 int first_sector_idx;
855 int last_sector_idx;
856 int swap_idx;
857
858 swap_idx = 0;
Christopher Collins0ff3c6c2016-12-21 12:04:17 -0800859 last_sector_idx = boot_data.imgs[0].num_sectors - 1;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800860 while (last_sector_idx >= 0) {
861 sz = boot_copy_sz(last_sector_idx, &first_sector_idx);
862 if (swap_idx >= bs->idx) {
863 boot_swap_sectors(first_sector_idx, sz, bs);
864 }
865
866 last_sector_idx = first_sector_idx - 1;
867 swap_idx++;
868 }
869
870 return 0;
871}
872
873/**
874 * Marks a test image in slot 0 as fully copied.
875 */
876static int
877boot_finalize_test_swap(void)
878{
879 const struct flash_area *fap;
880 int rc;
881
882 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
883 if (rc != 0) {
884 return BOOT_EFLASH;
885 }
886
887 rc = boot_write_copy_done(fap);
888 if (rc != 0) {
889 return rc;
890 }
891
892 return 0;
893}
894
895/**
896 * Marks a reverted image in slot 0 as confirmed. This is necessary to ensure
897 * the status bytes from the image revert operation don't get processed on a
898 * subsequent boot.
899 */
900static int
901boot_finalize_revert_swap(void)
902{
903 const struct flash_area *fap;
904 struct boot_swap_state state_slot0;
905 int rc;
906
907 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
908 if (rc != 0) {
909 return BOOT_EFLASH;
910 }
911
912 rc = boot_read_swap_state(fap, &state_slot0);
913 if (rc != 0) {
914 return BOOT_EFLASH;
915 }
916
917 if (state_slot0.magic == BOOT_MAGIC_UNSET) {
918 rc = boot_write_magic(fap);
919 if (rc != 0) {
920 return rc;
921 }
922 }
923
924 if (state_slot0.copy_done == 0xff) {
925 rc = boot_write_copy_done(fap);
926 if (rc != 0) {
927 return rc;
928 }
929 }
930
931 if (state_slot0.image_ok == 0xff) {
932 rc = boot_write_image_ok(fap);
933 if (rc != 0) {
934 return rc;
935 }
936 }
937
938 return 0;
939}
940
941/**
Christopher Collins0ff3c6c2016-12-21 12:04:17 -0800942 * Performs an image swap if one is required.
943 *
944 * @param out_swap_type On success, the type of swap performed gets
945 * written here.
946 *
947 * @return 0 on success; nonzero on failure.
948 */
949static int
950boot_swap_if_needed(int *out_swap_type)
951{
952 struct boot_status bs;
953 int swap_type;
954 int rc;
955
956 /* Determine if we rebooted in the middle of an image swap
957 * operation.
958 */
959 rc = boot_read_status(&bs);
960 if (rc != 0) {
961 return rc;
962 }
963
964 /* If a partial swap was detected, complete it. */
965 if (bs.idx != 0 || bs.state != 0) {
966 rc = boot_copy_image(&bs);
967 assert(rc == 0);
968
969 /* Extrapolate the type of the partial swap. We need this
970 * information to know how to mark the swap complete in flash.
971 */
972 swap_type = boot_previous_swap_type();
973 } else {
974 swap_type = boot_validated_swap_type();
975 switch (swap_type) {
976 case BOOT_SWAP_TYPE_TEST:
977 case BOOT_SWAP_TYPE_REVERT:
978 rc = boot_copy_image(&bs);
979 assert(rc == 0);
980 break;
981 }
982 }
983
984 *out_swap_type = swap_type;
985 return 0;
986}
987
988/**
Christopher Collins92ea77f2016-12-12 15:59:26 -0800989 * Prepares the booting process. This function moves images around in flash as
990 * appropriate, and tells you what address to boot from.
991 *
992 * @param rsp On success, indicates how booting should occur.
993 *
994 * @return 0 on success; nonzero on failure.
995 */
996int
997boot_go(struct boot_rsp *rsp)
998{
Christopher Collins92ea77f2016-12-12 15:59:26 -0800999 int swap_type;
1000 int slot;
1001 int rc;
1002
1003 /* The array of slot sectors are defined here (as opposed to file scope) so
1004 * that they don't get allocated for non-boot-loader apps. This is
1005 * necessary because the gcc option "-fdata-sections" doesn't seem to have
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001006 * any effect in older gcc versions (e.g., 4.8.4).
Christopher Collins92ea77f2016-12-12 15:59:26 -08001007 */
1008 static struct flash_area slot0_sectors[BOOT_MAX_IMG_SECTORS];
1009 static struct flash_area slot1_sectors[BOOT_MAX_IMG_SECTORS];
1010 boot_data.imgs[0].sectors = slot0_sectors;
1011 boot_data.imgs[1].sectors = slot1_sectors;
1012
1013 /* Determine the sector layout of the image slots and scratch area. */
1014 rc = boot_read_sectors();
1015 if (rc != 0) {
1016 return rc;
1017 }
1018
1019 /* Attempt to read an image header from each slot. */
1020 rc = boot_read_image_headers();
1021 if (rc != 0) {
1022 return rc;
1023 }
1024
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001025 /* If the image slots aren't compatible, no swap is possible. Just boot
1026 * into slot 0.
1027 */
1028 if (boot_slots_compatible()) {
1029 rc = boot_swap_if_needed(&swap_type);
1030 if (rc != 0) {
1031 return rc;
Christopher Collins92ea77f2016-12-12 15:59:26 -08001032 }
Christopher Collins0ff3c6c2016-12-21 12:04:17 -08001033 } else {
1034 swap_type = BOOT_SWAP_TYPE_NONE;
Christopher Collins92ea77f2016-12-12 15:59:26 -08001035 }
1036
1037 switch (swap_type) {
1038 case BOOT_SWAP_TYPE_NONE:
1039 slot = 0;
1040 break;
1041
1042 case BOOT_SWAP_TYPE_TEST:
1043 slot = 1;
1044 boot_finalize_test_swap();
1045 break;
1046
1047 case BOOT_SWAP_TYPE_REVERT:
1048 slot = 1;
1049 boot_finalize_revert_swap();
1050 break;
1051
1052 case BOOT_SWAP_TYPE_FAIL:
1053 /* The image in slot 1 was invalid and is now erased. Ensure we don't
1054 * try to boot into it again on the next reboot. Do this by pretending
1055 * we just reverted back to slot 0.
1056 */
1057 slot = 0;
1058 boot_finalize_revert_swap();
1059 break;
1060
1061 default:
1062 assert(0);
1063 slot = 0;
1064 break;
1065 }
1066
1067 /* Always boot from the primary slot. */
1068 rsp->br_flash_id = boot_data.imgs[0].sectors[0].fa_device_id;
1069 rsp->br_image_addr = boot_data.imgs[0].sectors[0].fa_off;
1070 rsp->br_hdr = &boot_data.imgs[slot].hdr;
1071
1072 return 0;
1073}
1074
1075int
1076split_go(int loader_slot, int split_slot, void **entry)
1077{
1078 const struct flash_area *loader_fap;
1079 const struct flash_area *app_fap;
1080 struct flash_area *sectors;
1081 uint32_t entry_val;
1082 int loader_flash_id;
1083 int app_flash_id;
1084 int rc;
1085
1086 app_fap = NULL;
1087 loader_fap = NULL;
1088
1089 sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors);
1090 if (sectors == NULL) {
1091 rc = SPLIT_GO_ERR;
1092 goto done;
1093 }
1094 boot_data.imgs[0].sectors = sectors + 0;
1095 boot_data.imgs[1].sectors = sectors + BOOT_MAX_IMG_SECTORS;
1096
1097 /* Determine the sector layout of the image slots and scratch area. */
1098 rc = boot_read_sectors();
1099 if (rc != 0) {
1100 rc = SPLIT_GO_ERR;
1101 goto done;
1102 }
1103
1104 rc = boot_read_image_headers();
1105 if (rc != 0) {
1106 goto done;
1107 }
1108
1109 app_flash_id = flash_area_id_from_image_slot(split_slot);
1110 rc = flash_area_open(app_flash_id, &app_fap);
1111 if (rc != 0) {
1112 rc = BOOT_EFLASH;
1113 goto done;
1114 }
1115
1116 loader_flash_id = flash_area_id_from_image_slot(loader_slot);
1117 rc = flash_area_open(loader_flash_id, &loader_fap);
1118 if (rc != 0) {
1119 rc = BOOT_EFLASH;
1120 goto done;
1121 }
1122
1123 /* Don't check the bootable image flag because we could really call a
1124 * bootable or non-bootable image. Just validate that the image check
1125 * passes which is distinct from the normal check.
1126 */
1127 rc = split_image_check(&boot_data.imgs[split_slot].hdr,
1128 app_fap,
1129 &boot_data.imgs[loader_slot].hdr,
1130 loader_fap);
1131 if (rc != 0) {
1132 rc = SPLIT_GO_NON_MATCHING;
1133 goto done;
1134 }
1135
1136 entry_val = boot_data.imgs[split_slot].sectors[0].fa_off +
1137 boot_data.imgs[split_slot].hdr.ih_hdr_size;
1138 *entry = (void*) entry_val;
1139 rc = SPLIT_GO_OK;
1140
1141done:
1142 free(sectors);
1143 flash_area_close(app_fap);
1144 flash_area_close(loader_fap);
1145 return rc;
1146}