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