blob: a22e6c1fbff545e7650ed341ef623d08ee4d7c0c [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
20#include <assert.h>
21#include <string.h>
22#include <inttypes.h>
23#include <stddef.h>
24
Tamas Banf70ef8c2017-12-19 15:35:09 +000025#include "flash_map/flash_map.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000026#include "bootutil/image.h"
27#include "bootutil/bootutil.h"
28#include "bootutil_priv.h"
29
30#define BOOT_LOG_LEVEL BOOT_LOG_LEVEL_INFO
31#include "bootutil/bootutil_log.h"
32
33int boot_current_slot;
34
35const uint32_t boot_img_magic[] = {
36 0xf395c277,
37 0x7fefd260,
38 0x0f505235,
39 0x8079b62c,
40};
41
Tamas Ban581034a2017-12-19 19:54:37 +000042const uint32_t BOOT_MAGIC_SZ = sizeof(boot_img_magic);
Tamas Banf70ef8c2017-12-19 15:35:09 +000043const uint32_t BOOT_MAX_ALIGN = MAX_FLASH_ALIGN;
44
45struct boot_swap_table {
46 /** * For each field, a value of 0 means "any". */
47 uint8_t magic_slot0;
48 uint8_t magic_slot1;
49 uint8_t image_ok_slot0;
50 uint8_t image_ok_slot1;
51 uint8_t copy_done_slot0;
52
53 uint8_t swap_type;
54};
55
56/**
57 * This set of tables maps image trailer contents to swap operation type.
58 * When searching for a match, these tables must be iterated sequentially.
59 *
60 * NOTE: the table order is very important. The settings in Slot 1 always
61 * are priority to Slot 0 and should be located earlier in the table.
62 *
63 * The table lists only states where there is action needs to be taken by
64 * the bootloader, as in starting/finishing a swap operation.
65 */
66static const struct boot_swap_table boot_swap_tables[] = {
67 {
68 .magic_slot0 = 0,
69 .magic_slot1 = BOOT_MAGIC_GOOD,
70 .image_ok_slot0 = 0,
71 .image_ok_slot1 = 0xff,
72 .copy_done_slot0 = 0,
73 .swap_type = BOOT_SWAP_TYPE_TEST,
74 },
75 {
76 .magic_slot0 = 0,
77 .magic_slot1 = BOOT_MAGIC_GOOD,
78 .image_ok_slot0 = 0,
79 .image_ok_slot1 = 0x01,
80 .copy_done_slot0 = 0,
81 .swap_type = BOOT_SWAP_TYPE_PERM,
82 },
83 {
84 .magic_slot0 = BOOT_MAGIC_GOOD,
85 .magic_slot1 = BOOT_MAGIC_UNSET,
86 .image_ok_slot0 = 0xff,
87 .image_ok_slot1 = 0,
88 .copy_done_slot0 = 0x01,
89 .swap_type = BOOT_SWAP_TYPE_REVERT,
90 },
91};
92
93#define BOOT_SWAP_TABLES_COUNT \
Tamas Ban581034a2017-12-19 19:54:37 +000094 (sizeof(boot_swap_tables) / sizeof(boot_swap_tables[0]))
Tamas Banf70ef8c2017-12-19 15:35:09 +000095
96int
97boot_magic_code(const uint32_t *magic)
98{
99 int i;
100
101 if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
102 return BOOT_MAGIC_GOOD;
103 }
104
Tamas Ban581034a2017-12-19 19:54:37 +0000105 for (i = 0; i < BOOT_MAGIC_SZ / sizeof(*magic); i++) {
Tamas Banf70ef8c2017-12-19 15:35:09 +0000106 if (magic[i] != 0xffffffff) {
107 return BOOT_MAGIC_BAD;
108 }
109 }
110
111 return BOOT_MAGIC_UNSET;
112}
113
114uint32_t
115boot_slots_trailer_sz(uint8_t min_write_sz)
116{
117 return /* state for all sectors */
118 BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
119 BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */ +
120 BOOT_MAGIC_SZ;
121}
122
123static uint32_t
124boot_scratch_trailer_sz(uint8_t min_write_sz)
125{
126 return BOOT_STATUS_STATE_COUNT * min_write_sz + /* state for one sector */
127 BOOT_MAX_ALIGN * 2 + /* image_ok + swap_size */
128 BOOT_MAGIC_SZ;
129}
130
131static uint32_t
132boot_magic_off(const struct flash_area *fap)
133{
134 assert(offsetof(struct image_trailer, magic) == 16);
135 return fap->fa_size - BOOT_MAGIC_SZ;
136}
137
138int
139boot_status_entries(const struct flash_area *fap)
140{
141 switch (fap->fa_id) {
142 case FLASH_AREA_IMAGE_0:
143 case FLASH_AREA_IMAGE_1:
144 return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
145 case FLASH_AREA_IMAGE_SCRATCH:
146 return BOOT_STATUS_STATE_COUNT;
147 default:
148 return BOOT_EBADARGS;
149 }
150}
151
152uint32_t
153boot_status_off(const struct flash_area *fap)
154{
155 uint32_t off_from_end;
156 uint8_t elem_sz;
157
158 elem_sz = flash_area_align(fap);
159
160 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
161 off_from_end = boot_scratch_trailer_sz(elem_sz);
162 } else {
163 off_from_end = boot_slots_trailer_sz(elem_sz);
164 }
165
166 assert(off_from_end <= fap->fa_size);
167 return fap->fa_size - off_from_end;
168}
169
170static uint32_t
171boot_copy_done_off(const struct flash_area *fap)
172{
173 assert(fap->fa_id != FLASH_AREA_IMAGE_SCRATCH);
174 assert(offsetof(struct image_trailer, copy_done) == 0);
175 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
176}
177
178static uint32_t
179boot_image_ok_off(const struct flash_area *fap)
180{
181 assert(offsetof(struct image_trailer, image_ok) == 8);
182 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
183}
184
185static uint32_t
186boot_swap_size_off(const struct flash_area *fap)
187{
188 /*
189 * The "swap_size" field if located just before the trailer.
190 * The scratch slot doesn't store "copy_done"...
191 */
192 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
193 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
194 }
195
196 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
197}
198
199int
200boot_read_swap_state(const struct flash_area *fap,
201 struct boot_swap_state *state)
202{
203 uint32_t magic[BOOT_MAGIC_SZ];
204 uint32_t off;
205 int rc;
206
207 off = boot_magic_off(fap);
208 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
209 if (rc != 0) {
210 return BOOT_EFLASH;
211 }
212 state->magic = boot_magic_code(magic);
213
214 if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
215 off = boot_copy_done_off(fap);
Tamas Ban581034a2017-12-19 19:54:37 +0000216 rc = flash_area_read(fap, off, &state->copy_done,
217 sizeof(state->copy_done));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000218 if (rc != 0) {
219 return BOOT_EFLASH;
220 }
221 }
222
223 off = boot_image_ok_off(fap);
Tamas Ban581034a2017-12-19 19:54:37 +0000224 rc = flash_area_read(fap, off, &state->image_ok, sizeof(state->image_ok));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000225 if (rc != 0) {
226 return BOOT_EFLASH;
227 }
228
229 return 0;
230}
231
232/**
233 * Reads the image trailer from the scratch area.
234 */
235int
236boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
237{
238 const struct flash_area *fap;
239 int rc;
240
241 switch (flash_area_id) {
242 case FLASH_AREA_IMAGE_SCRATCH:
243 case FLASH_AREA_IMAGE_0:
244 case FLASH_AREA_IMAGE_1:
245 rc = flash_area_open(flash_area_id, &fap);
246 if (rc != 0) {
247 return BOOT_EFLASH;
248 }
249 break;
250 default:
251 return BOOT_EBADARGS;
252 }
253
254 rc = boot_read_swap_state(fap, state);
255 flash_area_close(fap);
256 return rc;
257}
258
259int
260boot_read_swap_size(uint32_t *swap_size)
261{
262 uint32_t magic[BOOT_MAGIC_SZ];
263 uint32_t off;
264 const struct flash_area *fap;
265 int rc;
266
267 /*
268 * In the middle a swap, tries to locate the saved swap size. Looks
269 * for a valid magic, first on Slot 0, then on scratch. Both "slots"
270 * can end up being temporary storage for a swap and it is assumed
271 * that if magic is valid then swap size is too, because magic is
272 * always written in the last step.
273 */
274
275 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
276 if (rc != 0) {
277 return BOOT_EFLASH;
278 }
279
280 off = boot_magic_off(fap);
281 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
282 if (rc != 0) {
283 rc = BOOT_EFLASH;
284 goto out;
285 }
286
287 if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
288 /*
289 * If Slot 0 's magic is not valid, try scratch...
290 */
291
292 flash_area_close(fap);
293
294 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
295 if (rc != 0) {
296 return BOOT_EFLASH;
297 }
298
299 off = boot_magic_off(fap);
300 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
301 if (rc != 0) {
302 rc = BOOT_EFLASH;
303 goto out;
304 }
305
306 assert(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
307 }
308
309 off = boot_swap_size_off(fap);
Tamas Ban581034a2017-12-19 19:54:37 +0000310 rc = flash_area_read(fap, off, swap_size, sizeof(*swap_size));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000311 if (rc != 0) {
312 rc = BOOT_EFLASH;
313 }
314
315out:
316 flash_area_close(fap);
317 return rc;
318}
319
320
321int
322boot_write_magic(const struct flash_area *fap)
323{
324 uint32_t off;
325 int rc;
326
327 off = boot_magic_off(fap);
328
329 rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
330 if (rc != 0) {
331 return BOOT_EFLASH;
332 }
333
334 return 0;
335}
336
337static int
338boot_write_flag(int flag, const struct flash_area *fap)
339{
340 uint32_t off;
341 int rc;
342 uint8_t buf[BOOT_MAX_ALIGN];
343 uint8_t align;
344
345 switch (flag) {
346 case BOOT_FLAG_COPY_DONE:
347 off = boot_copy_done_off(fap);
348 break;
349 case BOOT_FLAG_IMAGE_OK:
350 off = boot_image_ok_off(fap);
351 break;
352 default:
353 return BOOT_EBADARGS;
354 }
355
Tamas Banc3828852018-02-01 12:24:16 +0000356 align = flash_area_align(fap);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000357 assert(align <= BOOT_MAX_ALIGN);
358 memset(buf, 0xFF, BOOT_MAX_ALIGN);
359 buf[0] = BOOT_FLAG_SET;
360
361 rc = flash_area_write(fap, off, buf, align);
362 if (rc != 0) {
363 return BOOT_EFLASH;
364 }
365
366 return 0;
367}
368
369int
370boot_write_copy_done(const struct flash_area *fap)
371{
372 return boot_write_flag(BOOT_FLAG_COPY_DONE, fap);
373}
374
375int
376boot_write_image_ok(const struct flash_area *fap)
377{
378 return boot_write_flag(BOOT_FLAG_IMAGE_OK, fap);
379}
380
381int
382boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
383{
384 uint32_t off;
385 int rc;
386 uint8_t buf[BOOT_MAX_ALIGN];
387 uint8_t align;
388
389 off = boot_swap_size_off(fap);
Tamas Banc3828852018-02-01 12:24:16 +0000390 align = flash_area_align(fap);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000391 assert(align <= BOOT_MAX_ALIGN);
Tamas Ban581034a2017-12-19 19:54:37 +0000392 if (align < sizeof(swap_size)) {
393 align = sizeof(swap_size);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000394 }
395 memset(buf, 0xFF, BOOT_MAX_ALIGN);
Tamas Ban581034a2017-12-19 19:54:37 +0000396 memcpy(buf, (uint8_t *)&swap_size, sizeof(swap_size));
Tamas Banf70ef8c2017-12-19 15:35:09 +0000397
398 rc = flash_area_write(fap, off, buf, align);
399 if (rc != 0) {
400 return BOOT_EFLASH;
401 }
402
403 return 0;
404}
405
406int
407boot_swap_type(void)
408{
409 const struct boot_swap_table *table;
410 struct boot_swap_state slot0;
411 struct boot_swap_state slot1;
412 int rc;
413 int i;
414
415 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &slot0);
416 if (rc) {
417 return BOOT_SWAP_TYPE_PANIC;
418 }
419
420 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &slot1);
421 if (rc) {
422 return BOOT_SWAP_TYPE_PANIC;
423 }
424
425 for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
426 table = boot_swap_tables + i;
427
428 if ((!table->magic_slot0 || table->magic_slot0 == slot0.magic ) &&
429 (!table->magic_slot1 || table->magic_slot1 == slot1.magic ) &&
430 (!table->image_ok_slot0 || table->image_ok_slot0 == slot0.image_ok ) &&
431 (!table->image_ok_slot1 || table->image_ok_slot1 == slot1.image_ok ) &&
432 (!table->copy_done_slot0 || table->copy_done_slot0 == slot0.copy_done)) {
433 BOOT_LOG_INF("Swap type: %s",
434 table->swap_type == BOOT_SWAP_TYPE_TEST ? "test" :
435 table->swap_type == BOOT_SWAP_TYPE_PERM ? "perm" :
436 table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
437 "BUG; can't happen");
438 assert(table->swap_type == BOOT_SWAP_TYPE_TEST ||
439 table->swap_type == BOOT_SWAP_TYPE_PERM ||
440 table->swap_type == BOOT_SWAP_TYPE_REVERT);
441 return table->swap_type;
442 }
443 }
444
445 BOOT_LOG_INF("Swap type: none");
446 return BOOT_SWAP_TYPE_NONE;
447}
448
449/**
450 * Marks the image in slot 1 as pending. On the next reboot, the system will
451 * perform a one-time boot of the slot 1 image.
452 *
453 * @param permanent Whether the image should be used permanently or
454 * only tested once:
455 * 0=run image once, then confirm or revert.
456 * 1=run image forever.
457 *
458 * @return 0 on success; nonzero on failure.
459 */
460int
461boot_set_pending(int permanent)
462{
Tamas Ban581034a2017-12-19 19:54:37 +0000463 const struct flash_area *fap = NULL;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000464 struct boot_swap_state state_slot1;
465 int rc;
466
467 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &state_slot1);
468 if (rc != 0) {
469 return rc;
470 }
471
472 switch (state_slot1.magic) {
473 case BOOT_MAGIC_GOOD:
474 /* Swap already scheduled. */
475 return 0;
476
477 case BOOT_MAGIC_UNSET:
478 rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
479 if (rc != 0) {
480 rc = BOOT_EFLASH;
481 } else {
482 rc = boot_write_magic(fap);
483 }
484
485 if (rc == 0 && permanent) {
486 rc = boot_write_image_ok(fap);
487 }
488
489 flash_area_close(fap);
490 return rc;
491
492 default:
493 /* XXX: Temporary assert. */
494 assert(0);
495 return -1;
496 }
497}
498
499/**
Tamas Ban581034a2017-12-19 19:54:37 +0000500 * Marks the image in slot 0 as confirmed. The system will continue booting
501 * into the image in slot 0 until told to boot from a different slot.
Tamas Banf70ef8c2017-12-19 15:35:09 +0000502 *
Tamas Ban581034a2017-12-19 19:54:37 +0000503 * @return 0 on success; non-zero on failure.
Tamas Banf70ef8c2017-12-19 15:35:09 +0000504 */
505int
506boot_set_confirmed(void)
507{
Tamas Ban581034a2017-12-19 19:54:37 +0000508 const struct flash_area *fap = NULL;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000509 struct boot_swap_state state_slot0;
510 int rc;
511
512 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
513 if (rc != 0) {
514 return rc;
515 }
516
517 switch (state_slot0.magic) {
518 case BOOT_MAGIC_GOOD:
519 /* Confirm needed; proceed. */
520 break;
521
522 case BOOT_MAGIC_UNSET:
523 /* Already confirmed. */
524 return 0;
525
526 case BOOT_MAGIC_BAD:
527 /* Unexpected state. */
528 return BOOT_EBADVECT;
529 }
530
531 if (state_slot0.copy_done == BOOT_FLAG_UNSET) {
532 /* Swap never completed. This is unexpected. */
533 return BOOT_EBADVECT;
534 }
535
536 if (state_slot0.image_ok != BOOT_FLAG_UNSET) {
537 /* Already confirmed. */
538 return 0;
539 }
540
541 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
542 if (rc) {
543 rc = BOOT_EFLASH;
544 goto done;
545 }
546
547 rc = boot_write_image_ok(fap);
548 if (rc != 0) {
549 goto done;
550 }
551
552 rc = 0;
553
554done:
555 flash_area_close(fap);
556 return rc;
557}