blob: 9d85511801a5d4030d6bf75c08462d1960fe88b9 [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;
47 } imgs[BOOT_NUM_SLOTS];
48
49 int num_img_sectors;
50 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) {
254 return rc;
255 }
256 }
257
258 return 0;
259}
260
261static uint8_t
262boot_write_sz(void)
263{
264 uint8_t elem_sz;
265 uint8_t align;
266
267 /* Figure out what size to write update status update as. The size depends
268 * on what the minimum write size is for scratch area, active image slot.
269 * We need to use the bigger of those 2 values.
270 */
271 elem_sz = hal_flash_align(boot_data.imgs[0].sectors[0].fa_device_id);
272 align = hal_flash_align(boot_data.scratch_sector.fa_device_id);
273 if (align > elem_sz) {
274 elem_sz = align;
275 }
276
277 return elem_sz;
278}
279
280/**
281 * Determines the sector layout of both image slots and the scratch area.
282 * This information is necessary for calculating the number of bytes to erase
283 * and copy during an image swap. The information collected during this
284 * function is used to populate the boot_data global.
285 */
286static int
287boot_read_sectors(void)
288{
289 const struct flash_area *sector0;
290 const struct flash_area *sector1;
291 const struct flash_area *scratch;
292 int num_sectors_slot0;
293 int num_sectors_slot1;
294 int rc;
295 int i;
296
297 num_sectors_slot0 = BOOT_MAX_IMG_SECTORS;
298 rc = flash_area_to_sectors(FLASH_AREA_IMAGE_0, &num_sectors_slot0,
299 boot_data.imgs[0].sectors);
300 if (rc != 0) {
301 return BOOT_EFLASH;
302 }
303
304 num_sectors_slot1 = BOOT_MAX_IMG_SECTORS;
305 rc = flash_area_to_sectors(FLASH_AREA_IMAGE_1, &num_sectors_slot1,
306 boot_data.imgs[1].sectors);
307 if (rc != 0) {
308 return BOOT_EFLASH;
309 }
310
311 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &scratch);
312 if (rc != 0) {
313 return BOOT_EFLASH;
314 }
315 boot_data.scratch_sector = *scratch;
316 boot_data.write_sz = hal_flash_align(scratch->fa_device_id);
317
318 /* Ensure both image slots have identical sector layouts. */
319 if (num_sectors_slot0 != num_sectors_slot1) {
320 return BOOT_EFLASH;
321 }
322 for (i = 0; i < num_sectors_slot0; i++) {
323 sector0 = boot_data.imgs[0].sectors + i;
324 sector1 = boot_data.imgs[1].sectors + i;
325 if (sector0->fa_size != sector1->fa_size) {
326 return BOOT_EFLASH;
327 }
328 }
329
330 boot_data.num_img_sectors = num_sectors_slot0;
331
332 boot_data.write_sz = boot_write_sz();
333
334 return 0;
335}
336
337static uint32_t
338boot_status_internal_off(int idx, int state, int elem_sz)
339{
340 int idx_sz;
341
342 idx_sz = elem_sz * BOOT_STATUS_STATE_COUNT;
343
344 return idx * idx_sz + state * elem_sz;
345}
346
347/**
348 * Reads the status of a partially-completed swap, if any. This is necessary
349 * to recover in case the boot lodaer was reset in the middle of a swap
350 * operation.
351 */
352static int
353boot_read_status_bytes(const struct flash_area *fap, struct boot_status *bs)
354{
355 uint32_t off;
356 uint8_t status;
357 int found;
358 int rc;
359 int i;
360
361 off = boot_status_off(fap);
362
363 found = 0;
364 for (i = 0; i < BOOT_STATUS_MAX_ENTRIES; i++) {
365 rc = flash_area_read(fap, off + i * boot_data.write_sz, &status, 1);
366 if (rc != 0) {
367 return BOOT_EFLASH;
368 }
369
370 if (status == 0xff) {
371 if (found) {
372 break;
373 }
374 } else if (!found) {
375 found = 1;
376 }
377 }
378
379 if (found) {
380 i--;
381 bs->idx = i / BOOT_STATUS_STATE_COUNT;
382 bs->state = i % BOOT_STATUS_STATE_COUNT;
383 }
384
385 return 0;
386}
387
388/**
389 * Reads the boot status from the flash. The boot status contains
390 * the current state of an interrupted image copy operation. If the boot
391 * status is not present, or it indicates that previous copy finished,
392 * there is no operation in progress.
393 */
394static int
395boot_read_status(struct boot_status *bs)
396{
397 const struct flash_area *fap;
398 int status_loc;
399 int area_id;
400 int rc;
401
402 memset(bs, 0, sizeof *bs);
403
404 status_loc = boot_status_source();
405 switch (status_loc) {
406 case BOOT_STATUS_SOURCE_NONE:
407 return 0;
408
409 case BOOT_STATUS_SOURCE_SCRATCH:
410 area_id = FLASH_AREA_IMAGE_SCRATCH;
411 break;
412
413 case BOOT_STATUS_SOURCE_SLOT0:
414 area_id = FLASH_AREA_IMAGE_0;
415 break;
416
417 default:
418 assert(0);
419 return BOOT_EBADARGS;
420 }
421
422 rc = flash_area_open(area_id, &fap);
423 if (rc != 0) {
424 return BOOT_EFLASH;
425 }
426
427 rc = boot_read_status_bytes(fap, bs);
428 if (rc != 0) {
429 return rc;
430 }
431
432 return 0;
433}
434
435/**
436 * Writes the supplied boot status to the flash file system. The boot status
437 * contains the current state of an in-progress image copy operation.
438 *
439 * @param bs The boot status to write.
440 *
441 * @return 0 on success; nonzero on failure.
442 */
443int
444boot_write_status(struct boot_status *bs)
445{
446 const struct flash_area *fap;
447 uint32_t off;
448 int area_id;
449 int rc;
450
451 if (bs->idx == 0) {
452 /* Write to scratch. */
453 area_id = FLASH_AREA_IMAGE_SCRATCH;
454 } else {
455 /* Write to slot 0. */
456 area_id = FLASH_AREA_IMAGE_0;
457 }
458
459 rc = flash_area_open(area_id, &fap);
460 if (rc != 0) {
461 rc = BOOT_EFLASH;
462 goto done;
463 }
464
465 off = boot_status_off(fap) +
466 boot_status_internal_off(bs->idx, bs->state, boot_data.write_sz);
467
468 rc = flash_area_write(fap, off, &bs->state, 1);
469 if (rc != 0) {
470 rc = BOOT_EFLASH;
471 goto done;
472 }
473
474 rc = 0;
475
476done:
477 flash_area_close(fap);
478 return rc;
479}
480
481/*
482 * Validate image hash/signature in a slot.
483 */
484static int
485boot_image_check(struct image_header *hdr, const struct flash_area *fap)
486{
David Browndb1d9d32017-01-06 11:07:54 -0700487 static uint8_t tmpbuf[BOOT_TMPBUF_SZ];
Christopher Collins92ea77f2016-12-12 15:59:26 -0800488
Christopher Collins92ea77f2016-12-12 15:59:26 -0800489 if (bootutil_img_validate(hdr, fap, tmpbuf, BOOT_TMPBUF_SZ,
490 NULL, 0, NULL)) {
491 return BOOT_EBADIMAGE;
492 }
493 return 0;
494}
495
496static int
497split_image_check(struct image_header *app_hdr,
498 const struct flash_area *app_fap,
499 struct image_header *loader_hdr,
500 const struct flash_area *loader_fap)
501{
502 static void *tmpbuf;
503 uint8_t loader_hash[32];
504
505 if (!tmpbuf) {
506 tmpbuf = malloc(BOOT_TMPBUF_SZ);
507 if (!tmpbuf) {
508 return BOOT_ENOMEM;
509 }
510 }
511
512 if (bootutil_img_validate(loader_hdr, loader_fap, tmpbuf, BOOT_TMPBUF_SZ,
513 NULL, 0, loader_hash)) {
514 return BOOT_EBADIMAGE;
515 }
516
517 if (bootutil_img_validate(app_hdr, app_fap, tmpbuf, BOOT_TMPBUF_SZ,
518 loader_hash, 32, NULL)) {
519 return BOOT_EBADIMAGE;
520 }
521
522 return 0;
523}
524
525static int
526boot_validate_slot1(void)
527{
528 const struct flash_area *fap;
529 int rc;
530
531 if (boot_data.imgs[1].hdr.ih_magic == 0xffffffff ||
532 boot_data.imgs[1].hdr.ih_flags & IMAGE_F_NON_BOOTABLE) {
533
534 /* No bootable image in slot 1; continue booting from slot 0. */
535 return -1;
536 }
537
538 /* Image in slot 1 is invalid. Erase the image and continue booting
539 * from slot 0.
540 */
541 rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
542 if (rc != 0) {
543 return BOOT_EFLASH;
544 }
545
546 if (boot_data.imgs[1].hdr.ih_magic != IMAGE_MAGIC ||
547 boot_image_check(&boot_data.imgs[1].hdr, fap) != 0) {
548
549 /* Image in slot 1 is invalid. Erase the image and continue booting
550 * from slot 0.
551 */
552 flash_area_erase(fap, 0, fap->fa_size);
553 return -1;
554 }
555
556 flash_area_close(fap);
557
558 /* Image in slot 1 is valid. */
559 return 0;
560}
561
562/**
563 * Determines which swap operation to perform, if any. If it is determined
564 * that a swap operation is required, the image in the second slot is checked
565 * for validity. If the image in the second slot is invalid, it is erased, and
566 * a swap type of "none" is indicated.
567 *
568 * @return The type of swap to perform (BOOT_SWAP_TYPE...)
569 */
570static int
571boot_validated_swap_type(void)
572{
573 int swap_type;
574 int rc;
575
576 swap_type = boot_swap_type();
577 if (swap_type == BOOT_SWAP_TYPE_NONE) {
578 /* Continue using slot 0. */
579 return BOOT_SWAP_TYPE_NONE;
580 }
581
582 /* Boot loader wants to switch to slot 1. Ensure image is valid. */
583 rc = boot_validate_slot1();
584 if (rc != 0) {
585 return BOOT_SWAP_TYPE_FAIL;
586 }
587
588 return swap_type;
589}
590
591/**
592 * Calculates the number of sectors the scratch area can contain. A "last"
593 * source sector is specified because images are copied backwards in flash
594 * (final index to index number 0).
595 *
596 * @param last_sector_idx The index of the last source sector
597 * (inclusive).
598 * @param out_first_sector_idx The index of the first source sector
599 * (inclusive) gets written here.
600 *
601 * @return The number of bytes comprised by the
602 * [first-sector, last-sector] range.
603 */
604static uint32_t
605boot_copy_sz(int last_sector_idx, int *out_first_sector_idx)
606{
607 uint32_t new_sz;
608 uint32_t sz;
609 int i;
610
611 sz = 0;
612
613 for (i = last_sector_idx; i >= 0; i--) {
614 new_sz = sz + boot_data.imgs[0].sectors[i].fa_size;
615 if (new_sz > boot_data.scratch_sector.fa_size) {
616 break;
617 }
618 sz = new_sz;
619 }
620
621 /* i currently refers to a sector that doesn't fit or it is -1 because all
622 * sectors have been processed. In both cases, exclude sector i.
623 */
624 *out_first_sector_idx = i + 1;
625 return sz;
626}
627
628/**
629 * Erases a region of flash.
630 *
631 * @param flash_area_idx The ID of the flash area containing the region
632 * to erase.
633 * @param off The offset within the flash area to start the
634 * erase.
635 * @param sz The number of bytes to erase.
636 *
637 * @return 0 on success; nonzero on failure.
638 */
639static int
640boot_erase_sector(int flash_area_id, uint32_t off, uint32_t sz)
641{
642 const struct flash_area *fap;
643 int rc;
644
645 rc = flash_area_open(flash_area_id, &fap);
646 if (rc != 0) {
647 rc = BOOT_EFLASH;
648 goto done;
649 }
650
651 rc = flash_area_erase(fap, off, sz);
652 if (rc != 0) {
653 rc = BOOT_EFLASH;
654 goto done;
655 }
656
657 rc = 0;
658
659done:
660 flash_area_close(fap);
661 return rc;
662}
663
664/**
665 * Copies the contents of one flash region to another. You must erase the
666 * destination region prior to calling this function.
667 *
668 * @param flash_area_id_src The ID of the source flash area.
669 * @param flash_area_id_dst The ID of the destination flash area.
670 * @param off_src The offset within the source flash area to
671 * copy from.
672 * @param off_dst The offset within the destination flash area to
673 * copy to.
674 * @param sz The number of bytes to copy.
675 *
676 * @return 0 on success; nonzero on failure.
677 */
678static int
679boot_copy_sector(int flash_area_id_src, int flash_area_id_dst,
680 uint32_t off_src, uint32_t off_dst, uint32_t sz)
681{
682 const struct flash_area *fap_src;
683 const struct flash_area *fap_dst;
684 uint32_t bytes_copied;
685 int chunk_sz;
686 int rc;
687
688 static uint8_t buf[1024];
689
690 fap_src = NULL;
691 fap_dst = NULL;
692
693 rc = flash_area_open(flash_area_id_src, &fap_src);
694 if (rc != 0) {
695 rc = BOOT_EFLASH;
696 goto done;
697 }
698
699 rc = flash_area_open(flash_area_id_dst, &fap_dst);
700 if (rc != 0) {
701 rc = BOOT_EFLASH;
702 goto done;
703 }
704
705 bytes_copied = 0;
706 while (bytes_copied < sz) {
707 if (sz - bytes_copied > sizeof buf) {
708 chunk_sz = sizeof buf;
709 } else {
710 chunk_sz = sz - bytes_copied;
711 }
712
713 rc = flash_area_read(fap_src, off_src + bytes_copied, buf, chunk_sz);
714 if (rc != 0) {
715 rc = BOOT_EFLASH;
716 goto done;
717 }
718
719 rc = flash_area_write(fap_dst, off_dst + bytes_copied, buf, chunk_sz);
720 if (rc != 0) {
721 rc = BOOT_EFLASH;
722 goto done;
723 }
724
725 bytes_copied += chunk_sz;
726 }
727
728 rc = 0;
729
730done:
731 flash_area_close(fap_src);
732 flash_area_close(fap_dst);
733 return rc;
734}
735
736/**
737 * Swaps the contents of two flash regions within the two image slots.
738 *
739 * @param idx The index of the first sector in the range of
740 * sectors being swapped.
741 * @param sz The number of bytes to swap.
742 * @param bs The current boot status. This struct gets
743 * updated according to the outcome.
744 *
745 * @return 0 on success; nonzero on failure.
746 */
747static int
748boot_swap_sectors(int idx, uint32_t sz, struct boot_status *bs)
749{
750 uint32_t copy_sz;
751 uint32_t img_off;
752 int rc;
753
754 /* Calculate offset from start of image area. */
755 img_off = boot_data.imgs[0].sectors[idx].fa_off -
756 boot_data.imgs[0].sectors[0].fa_off;
757
758 if (bs->state == 0) {
759 rc = boot_erase_sector(FLASH_AREA_IMAGE_SCRATCH, 0, sz);
760 if (rc != 0) {
761 return rc;
762 }
763
764 rc = boot_copy_sector(FLASH_AREA_IMAGE_1, FLASH_AREA_IMAGE_SCRATCH,
765 img_off, 0, sz);
766 if (rc != 0) {
767 return rc;
768 }
769
770 bs->state = 1;
771 (void)boot_write_status(bs);
772 }
773 if (bs->state == 1) {
774 rc = boot_erase_sector(FLASH_AREA_IMAGE_1, img_off, sz);
775 if (rc != 0) {
776 return rc;
777 }
778
779 copy_sz = sz;
780 if (boot_data.imgs[0].sectors[idx].fa_off + sz >=
781 boot_data.imgs[1].sectors[0].fa_off) {
782
783 /* This is the end of the area. Don't copy the image state into
784 * slot 1.
785 */
786 copy_sz -= boot_trailer_sz(boot_data.write_sz);
787 }
788
789 rc = boot_copy_sector(FLASH_AREA_IMAGE_0, FLASH_AREA_IMAGE_1,
790 img_off, img_off, copy_sz);
791 if (rc != 0) {
792 return rc;
793 }
794
795 bs->state = 2;
796 (void)boot_write_status(bs);
797 }
798 if (bs->state == 2) {
799 rc = boot_erase_sector(FLASH_AREA_IMAGE_0, img_off, sz);
800 if (rc != 0) {
801 return rc;
802 }
803
804 rc = boot_copy_sector(FLASH_AREA_IMAGE_SCRATCH, FLASH_AREA_IMAGE_0,
805 0, img_off, sz);
806 if (rc != 0) {
807 return rc;
808 }
809
810 bs->idx++;
811 bs->state = 0;
812 (void)boot_write_status(bs);
813 }
814
815 return 0;
816}
817
818/**
819 * Swaps the two images in flash. If a prior copy operation was interrupted
820 * by a system reset, this function completes that operation.
821 *
822 * @param bs The current boot status. This function reads
823 * this struct to determine if it is resuming
824 * an interrupted swap operation. This
825 * function writes the updated status to this
826 * function on return.
827 *
828 * @return 0 on success; nonzero on failure.
829 */
830static int
831boot_copy_image(struct boot_status *bs)
832{
833 uint32_t sz;
834 int first_sector_idx;
835 int last_sector_idx;
836 int swap_idx;
837
838 swap_idx = 0;
839 last_sector_idx = boot_data.num_img_sectors - 1;
840 while (last_sector_idx >= 0) {
841 sz = boot_copy_sz(last_sector_idx, &first_sector_idx);
842 if (swap_idx >= bs->idx) {
843 boot_swap_sectors(first_sector_idx, sz, bs);
844 }
845
846 last_sector_idx = first_sector_idx - 1;
847 swap_idx++;
848 }
849
850 return 0;
851}
852
853/**
854 * Marks a test image in slot 0 as fully copied.
855 */
856static int
857boot_finalize_test_swap(void)
858{
859 const struct flash_area *fap;
860 int rc;
861
862 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
863 if (rc != 0) {
864 return BOOT_EFLASH;
865 }
866
867 rc = boot_write_copy_done(fap);
868 if (rc != 0) {
869 return rc;
870 }
871
872 return 0;
873}
874
875/**
876 * Marks a reverted image in slot 0 as confirmed. This is necessary to ensure
877 * the status bytes from the image revert operation don't get processed on a
878 * subsequent boot.
879 */
880static int
881boot_finalize_revert_swap(void)
882{
883 const struct flash_area *fap;
884 struct boot_swap_state state_slot0;
885 int rc;
886
887 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
888 if (rc != 0) {
889 return BOOT_EFLASH;
890 }
891
892 rc = boot_read_swap_state(fap, &state_slot0);
893 if (rc != 0) {
894 return BOOT_EFLASH;
895 }
896
897 if (state_slot0.magic == BOOT_MAGIC_UNSET) {
898 rc = boot_write_magic(fap);
899 if (rc != 0) {
900 return rc;
901 }
902 }
903
904 if (state_slot0.copy_done == 0xff) {
905 rc = boot_write_copy_done(fap);
906 if (rc != 0) {
907 return rc;
908 }
909 }
910
911 if (state_slot0.image_ok == 0xff) {
912 rc = boot_write_image_ok(fap);
913 if (rc != 0) {
914 return rc;
915 }
916 }
917
918 return 0;
919}
920
921/**
922 * Prepares the booting process. This function moves images around in flash as
923 * appropriate, and tells you what address to boot from.
924 *
925 * @param rsp On success, indicates how booting should occur.
926 *
927 * @return 0 on success; nonzero on failure.
928 */
929int
930boot_go(struct boot_rsp *rsp)
931{
932 struct boot_status bs;
933 int swap_type;
934 int slot;
935 int rc;
936
937 /* The array of slot sectors are defined here (as opposed to file scope) so
938 * that they don't get allocated for non-boot-loader apps. This is
939 * necessary because the gcc option "-fdata-sections" doesn't seem to have
940 * any effect for some reason.
941 */
942 static struct flash_area slot0_sectors[BOOT_MAX_IMG_SECTORS];
943 static struct flash_area slot1_sectors[BOOT_MAX_IMG_SECTORS];
944 boot_data.imgs[0].sectors = slot0_sectors;
945 boot_data.imgs[1].sectors = slot1_sectors;
946
947 /* Determine the sector layout of the image slots and scratch area. */
948 rc = boot_read_sectors();
949 if (rc != 0) {
950 return rc;
951 }
952
953 /* Attempt to read an image header from each slot. */
954 rc = boot_read_image_headers();
955 if (rc != 0) {
956 return rc;
957 }
958
959 /* Determine if we rebooted in the middle of an image swap operation. */
960 rc = boot_read_status(&bs);
961 if (rc != 0) {
962 return rc;
963 }
964
965 /* If a partial swap was detected, complete it. */
966 if (bs.idx != 0 || bs.state != 0) {
967 rc = boot_copy_image(&bs);
968 assert(rc == 0);
969
970 /* Extrapolate the type of the partial swap. We need this information
971 * to know how to mark the swap complete in flash.
972 */
973 swap_type = boot_previous_swap_type();
974 } else {
975 swap_type = boot_validated_swap_type();
976 switch (swap_type) {
977 case BOOT_SWAP_TYPE_TEST:
978 case BOOT_SWAP_TYPE_REVERT:
979 rc = boot_copy_image(&bs);
980 assert(rc == 0);
981 break;
982 }
983 }
984
985 switch (swap_type) {
986 case BOOT_SWAP_TYPE_NONE:
987 slot = 0;
988 break;
989
990 case BOOT_SWAP_TYPE_TEST:
991 slot = 1;
992 boot_finalize_test_swap();
993 break;
994
995 case BOOT_SWAP_TYPE_REVERT:
996 slot = 1;
997 boot_finalize_revert_swap();
998 break;
999
1000 case BOOT_SWAP_TYPE_FAIL:
1001 /* The image in slot 1 was invalid and is now erased. Ensure we don't
1002 * try to boot into it again on the next reboot. Do this by pretending
1003 * we just reverted back to slot 0.
1004 */
1005 slot = 0;
1006 boot_finalize_revert_swap();
1007 break;
1008
1009 default:
1010 assert(0);
1011 slot = 0;
1012 break;
1013 }
1014
1015 /* Always boot from the primary slot. */
1016 rsp->br_flash_id = boot_data.imgs[0].sectors[0].fa_device_id;
1017 rsp->br_image_addr = boot_data.imgs[0].sectors[0].fa_off;
1018 rsp->br_hdr = &boot_data.imgs[slot].hdr;
1019
1020 return 0;
1021}
1022
1023int
1024split_go(int loader_slot, int split_slot, void **entry)
1025{
1026 const struct flash_area *loader_fap;
1027 const struct flash_area *app_fap;
1028 struct flash_area *sectors;
1029 uint32_t entry_val;
1030 int loader_flash_id;
1031 int app_flash_id;
1032 int rc;
1033
1034 app_fap = NULL;
1035 loader_fap = NULL;
1036
1037 sectors = malloc(BOOT_MAX_IMG_SECTORS * 2 * sizeof *sectors);
1038 if (sectors == NULL) {
1039 rc = SPLIT_GO_ERR;
1040 goto done;
1041 }
1042 boot_data.imgs[0].sectors = sectors + 0;
1043 boot_data.imgs[1].sectors = sectors + BOOT_MAX_IMG_SECTORS;
1044
1045 /* Determine the sector layout of the image slots and scratch area. */
1046 rc = boot_read_sectors();
1047 if (rc != 0) {
1048 rc = SPLIT_GO_ERR;
1049 goto done;
1050 }
1051
1052 rc = boot_read_image_headers();
1053 if (rc != 0) {
1054 goto done;
1055 }
1056
1057 app_flash_id = flash_area_id_from_image_slot(split_slot);
1058 rc = flash_area_open(app_flash_id, &app_fap);
1059 if (rc != 0) {
1060 rc = BOOT_EFLASH;
1061 goto done;
1062 }
1063
1064 loader_flash_id = flash_area_id_from_image_slot(loader_slot);
1065 rc = flash_area_open(loader_flash_id, &loader_fap);
1066 if (rc != 0) {
1067 rc = BOOT_EFLASH;
1068 goto done;
1069 }
1070
1071 /* Don't check the bootable image flag because we could really call a
1072 * bootable or non-bootable image. Just validate that the image check
1073 * passes which is distinct from the normal check.
1074 */
1075 rc = split_image_check(&boot_data.imgs[split_slot].hdr,
1076 app_fap,
1077 &boot_data.imgs[loader_slot].hdr,
1078 loader_fap);
1079 if (rc != 0) {
1080 rc = SPLIT_GO_NON_MATCHING;
1081 goto done;
1082 }
1083
1084 entry_val = boot_data.imgs[split_slot].sectors[0].fa_off +
1085 boot_data.imgs[split_slot].hdr.ih_hdr_size;
1086 *entry = (void*) entry_val;
1087 rc = SPLIT_GO_OK;
1088
1089done:
1090 free(sectors);
1091 flash_area_close(app_fap);
1092 flash_area_close(loader_fap);
1093 return rc;
1094}