blob: f40e1be1c0ede262ec831469d498c496e80937ee [file] [log] [blame]
Andrzej Puzdrowskif573b392020-11-10 14:35:15 +01001/*
2 * SPDX-License-Identifier: Apache-2.0
3 *
4 * Copyright (c) 2017-2019 Linaro LTD
5 * Copyright (c) 2016-2019 JUUL Labs
6 * Copyright (c) 2019-2020 Arm Limited
7 * Copyright (c) 2020 Nordic Semiconductor ASA
8 *
9 * Original license:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one
12 * or more contributor license agreements. See the NOTICE file
13 * distributed with this work for additional information
14 * regarding copyright ownership. The ASF licenses this file
15 * to you under the Apache License, Version 2.0 (the
16 * "License"); you may not use this file except in compliance
17 * with the License. You may obtain a copy of the License at
18 *
19 * http://www.apache.org/licenses/LICENSE-2.0
20 *
21 * Unless required by applicable law or agreed to in writing,
22 * software distributed under the License is distributed on an
23 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
24 * KIND, either express or implied. See the License for the
25 * specific language governing permissions and limitations
26 * under the License.
27 */
28
29#include <string.h>
30#include <inttypes.h>
31#include <stddef.h>
32
33#include "sysflash/sysflash.h"
34#include "flash_map_backend/flash_map_backend.h"
35
36#include "bootutil/image.h"
37#include "bootutil/bootutil_public.h"
38#include "bootutil_priv.h"
39#include "bootutil/bootutil_log.h"
40#ifdef MCUBOOT_ENC_IMAGES
41#include "bootutil/enc_key.h"
42#endif
43
44#ifdef CONFIG_MCUBOOT
45MCUBOOT_LOG_MODULE_DECLARE(mcuboot);
46#else
47MCUBOOT_LOG_MODULE_REGISTER(mcuboot_util);
48#endif
49
50const uint32_t boot_img_magic[] = {
51 0xf395c277,
52 0x7fefd260,
53 0x0f505235,
54 0x8079b62c,
55};
56
57#define BOOT_MAGIC_ARR_SZ \
58 (sizeof boot_img_magic / sizeof boot_img_magic[0])
59
60struct boot_swap_table {
61 uint8_t magic_primary_slot;
62 uint8_t magic_secondary_slot;
63 uint8_t image_ok_primary_slot;
64 uint8_t image_ok_secondary_slot;
65 uint8_t copy_done_primary_slot;
66
67 uint8_t swap_type;
68};
69
70/**
71 * This set of tables maps image trailer contents to swap operation type.
72 * When searching for a match, these tables must be iterated sequentially.
73 *
74 * NOTE: the table order is very important. The settings in the secondary
75 * slot always are priority to the primary slot and should be located
76 * earlier in the table.
77 *
78 * The table lists only states where there is action needs to be taken by
79 * the bootloader, as in starting/finishing a swap operation.
80 */
81static const struct boot_swap_table boot_swap_tables[] = {
82 {
83 .magic_primary_slot = BOOT_MAGIC_ANY,
84 .magic_secondary_slot = BOOT_MAGIC_GOOD,
85 .image_ok_primary_slot = BOOT_FLAG_ANY,
86 .image_ok_secondary_slot = BOOT_FLAG_UNSET,
87 .copy_done_primary_slot = BOOT_FLAG_ANY,
88 .swap_type = BOOT_SWAP_TYPE_TEST,
89 },
90 {
91 .magic_primary_slot = BOOT_MAGIC_ANY,
92 .magic_secondary_slot = BOOT_MAGIC_GOOD,
93 .image_ok_primary_slot = BOOT_FLAG_ANY,
94 .image_ok_secondary_slot = BOOT_FLAG_SET,
95 .copy_done_primary_slot = BOOT_FLAG_ANY,
96 .swap_type = BOOT_SWAP_TYPE_PERM,
97 },
98 {
99 .magic_primary_slot = BOOT_MAGIC_GOOD,
100 .magic_secondary_slot = BOOT_MAGIC_UNSET,
101 .image_ok_primary_slot = BOOT_FLAG_UNSET,
102 .image_ok_secondary_slot = BOOT_FLAG_ANY,
103 .copy_done_primary_slot = BOOT_FLAG_SET,
104 .swap_type = BOOT_SWAP_TYPE_REVERT,
105 },
106};
107
108#define BOOT_SWAP_TABLES_COUNT \
109 (sizeof boot_swap_tables / sizeof boot_swap_tables[0])
110
111static int
112boot_magic_decode(const uint32_t *magic)
113{
114 if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
115 return BOOT_MAGIC_GOOD;
116 }
117 return BOOT_MAGIC_BAD;
118}
119
120static int
121boot_flag_decode(uint8_t flag)
122{
123 if (flag != BOOT_FLAG_SET) {
124 return BOOT_FLAG_BAD;
125 }
126 return BOOT_FLAG_SET;
127}
128
129static inline uint32_t
130boot_magic_off(const struct flash_area *fap)
131{
132 return fap->fa_size - BOOT_MAGIC_SZ;
133}
134
135static inline uint32_t
136boot_image_ok_off(const struct flash_area *fap)
137{
138 return boot_magic_off(fap) - BOOT_MAX_ALIGN;
139}
140
141static inline uint32_t
142boot_copy_done_off(const struct flash_area *fap)
143{
144 return boot_image_ok_off(fap) - BOOT_MAX_ALIGN;
145}
146
147static inline uint32_t
148boot_swap_size_off(const struct flash_area *fap)
149{
150 return boot_swap_info_off(fap) - BOOT_MAX_ALIGN;
151}
152
153uint32_t
154boot_swap_info_off(const struct flash_area *fap)
155{
156 return boot_copy_done_off(fap) - BOOT_MAX_ALIGN;
157}
158
159/**
160 * Determines if a status source table is satisfied by the specified magic
161 * code.
162 *
163 * @param tbl_val A magic field from a status source table.
164 * @param val The magic value in a trailer, encoded as a
165 * BOOT_MAGIC_[...].
166 *
167 * @return 1 if the two values are compatible;
168 * 0 otherwise.
169 */
170int
171boot_magic_compatible_check(uint8_t tbl_val, uint8_t val)
172{
173 switch (tbl_val) {
174 case BOOT_MAGIC_ANY:
175 return 1;
176
177 case BOOT_MAGIC_NOTGOOD:
178 return val != BOOT_MAGIC_GOOD;
179
180 default:
181 return tbl_val == val;
182 }
183}
184
185#ifdef MCUBOOT_ENC_IMAGES
186static inline uint32_t
187boot_enc_key_off(const struct flash_area *fap, uint8_t slot)
188{
189#if MCUBOOT_SWAP_SAVE_ENCTLV
190 return boot_swap_size_off(fap) - ((slot + 1) *
191 ((((BOOT_ENC_TLV_SIZE - 1) / BOOT_MAX_ALIGN) + 1) * BOOT_MAX_ALIGN));
192#else
193 return boot_swap_size_off(fap) - ((slot + 1) * BOOT_ENC_KEY_SIZE);
194#endif
195}
196#endif
197
198bool bootutil_buffer_is_erased(const struct flash_area *area,
199 const void *buffer, size_t len)
200{
201 size_t i;
202 uint8_t *u8b;
203 uint8_t erased_val;
204
205 if (buffer == NULL || len == 0) {
206 return false;
207 }
208
209 erased_val = flash_area_erased_val(area);
210 for (i = 0, u8b = (uint8_t *)buffer; i < len; i++) {
211 if (u8b[i] != erased_val) {
212 return false;
213 }
214 }
215
216 return true;
217}
218
219int
220boot_read_swap_state(const struct flash_area *fap,
221 struct boot_swap_state *state)
222{
223 uint32_t magic[BOOT_MAGIC_ARR_SZ];
224 uint32_t off;
225 uint8_t swap_info;
226 int rc;
227
228 off = boot_magic_off(fap);
229 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
230 if (rc < 0) {
231 return BOOT_EFLASH;
232 }
233 if (bootutil_buffer_is_erased(fap, magic, BOOT_MAGIC_SZ)) {
234 state->magic = BOOT_MAGIC_UNSET;
235 } else {
236 state->magic = boot_magic_decode(magic);
237 }
238
239 off = boot_swap_info_off(fap);
240 rc = flash_area_read(fap, off, &swap_info, sizeof swap_info);
241 if (rc < 0) {
242 return BOOT_EFLASH;
243 }
244
245 /* Extract the swap type and image number */
246 state->swap_type = BOOT_GET_SWAP_TYPE(swap_info);
247 state->image_num = BOOT_GET_IMAGE_NUM(swap_info);
248
249 if (bootutil_buffer_is_erased(fap, &swap_info, sizeof swap_info) ||
250 state->swap_type > BOOT_SWAP_TYPE_REVERT) {
251 state->swap_type = BOOT_SWAP_TYPE_NONE;
252 state->image_num = 0;
253 }
254
255 off = boot_copy_done_off(fap);
256 rc = flash_area_read(fap, off, &state->copy_done, sizeof state->copy_done);
257 if (rc < 0) {
258 return BOOT_EFLASH;
259 }
260 if (bootutil_buffer_is_erased(fap, &state->copy_done,
261 sizeof state->copy_done)) {
262 state->copy_done = BOOT_FLAG_UNSET;
263 } else {
264 state->copy_done = boot_flag_decode(state->copy_done);
265 }
266
267 off = boot_image_ok_off(fap);
268 rc = flash_area_read(fap, off, &state->image_ok, sizeof state->image_ok);
269 if (rc < 0) {
270 return BOOT_EFLASH;
271 }
272 if (bootutil_buffer_is_erased(fap, &state->image_ok,
273 sizeof state->image_ok)) {
274 state->image_ok = BOOT_FLAG_UNSET;
275 } else {
276 state->image_ok = boot_flag_decode(state->image_ok);
277 }
278
279 return 0;
280}
281
282/**
283 * Reads the image trailer from the scratch area.
284 */
285int
286boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
287{
288 const struct flash_area *fap;
289 int rc;
290
291 rc = flash_area_open(flash_area_id, &fap);
292 if (rc != 0) {
293 return BOOT_EFLASH;
294 }
295
296 rc = boot_read_swap_state(fap, state);
297 flash_area_close(fap);
298 return rc;
299}
300
301int
302boot_write_magic(const struct flash_area *fap)
303{
304 uint32_t off;
305 int rc;
306
307 off = boot_magic_off(fap);
308
309 BOOT_LOG_DBG("writing magic; fa_id=%d off=0x%lx (0x%lx)",
310 fap->fa_id, (unsigned long)off,
311 (unsigned long)(fap->fa_off + off));
312 rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
313 if (rc != 0) {
314 return BOOT_EFLASH;
315 }
316
317 return 0;
318}
319
320/**
321 * Write trailer data; status bytes, swap_size, etc
322 *
323 * @returns 0 on success, != 0 on error.
324 */
325static int
326boot_write_trailer(const struct flash_area *fap, uint32_t off,
327 const uint8_t *inbuf, uint8_t inlen)
328{
329 uint8_t buf[BOOT_MAX_ALIGN];
330 uint8_t align;
331 uint8_t erased_val;
332 int rc;
333
334 align = flash_area_align(fap);
335 if (inlen > BOOT_MAX_ALIGN || align > BOOT_MAX_ALIGN) {
336 return -1;
337 }
338 erased_val = flash_area_erased_val(fap);
339 if (align < inlen) {
340 align = inlen;
341 }
342 memcpy(buf, inbuf, inlen);
343 memset(&buf[inlen], erased_val, align - inlen);
344
345 rc = flash_area_write(fap, off, buf, align);
346 if (rc != 0) {
347 return BOOT_EFLASH;
348 }
349
350 return 0;
351}
352
353static int
354boot_write_trailer_flag(const struct flash_area *fap, uint32_t off,
355 uint8_t flag_val)
356{
357 const uint8_t buf[1] = { flag_val };
358 return boot_write_trailer(fap, off, buf, 1);
359}
360
361int
362boot_write_image_ok(const struct flash_area *fap)
363{
364 uint32_t off;
365
366 off = boot_image_ok_off(fap);
367 BOOT_LOG_DBG("writing image_ok; fa_id=%d off=0x%lx (0x%lx)",
368 fap->fa_id, (unsigned long)off,
369 (unsigned long)(fap->fa_off + off));
370 return boot_write_trailer_flag(fap, off, BOOT_FLAG_SET);
371}
372
373/**
374 * Writes the specified value to the `swap-type` field of an image trailer.
375 * This value is persisted so that the boot loader knows what swap operation to
376 * resume in case of an unexpected reset.
377 */
378int
379boot_write_swap_info(const struct flash_area *fap, uint8_t swap_type,
380 uint8_t image_num)
381{
382 uint32_t off;
383 uint8_t swap_info;
384
385 BOOT_SET_SWAP_INFO(swap_info, image_num, swap_type);
386 off = boot_swap_info_off(fap);
387 BOOT_LOG_DBG("writing swap_info; fa_id=%d off=0x%lx (0x%lx), swap_type=0x%x"
388 " image_num=0x%x",
389 fap->fa_id, (unsigned long)off,
390 (unsigned long)(fap->fa_off + off), swap_type, image_num);
391 return boot_write_trailer(fap, off, (const uint8_t *) &swap_info, 1);
392}
393
394int
395boot_swap_type_multi(int image_index)
396{
397 const struct boot_swap_table *table;
398 struct boot_swap_state primary_slot;
399 struct boot_swap_state secondary_slot;
400 int rc;
401 size_t i;
402
403 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(image_index),
404 &primary_slot);
405 if (rc) {
406 return BOOT_SWAP_TYPE_PANIC;
407 }
408
409 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(image_index),
410 &secondary_slot);
411 if (rc) {
412 return BOOT_SWAP_TYPE_PANIC;
413 }
414
415 for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
416 table = boot_swap_tables + i;
417
418 if (boot_magic_compatible_check(table->magic_primary_slot,
419 primary_slot.magic) &&
420 boot_magic_compatible_check(table->magic_secondary_slot,
421 secondary_slot.magic) &&
422 (table->image_ok_primary_slot == BOOT_FLAG_ANY ||
423 table->image_ok_primary_slot == primary_slot.image_ok) &&
424 (table->image_ok_secondary_slot == BOOT_FLAG_ANY ||
425 table->image_ok_secondary_slot == secondary_slot.image_ok) &&
426 (table->copy_done_primary_slot == BOOT_FLAG_ANY ||
427 table->copy_done_primary_slot == primary_slot.copy_done)) {
428 BOOT_LOG_INF("Swap type: %s",
429 table->swap_type == BOOT_SWAP_TYPE_TEST ? "test" :
430 table->swap_type == BOOT_SWAP_TYPE_PERM ? "perm" :
431 table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
432 "BUG; can't happen");
433 if (table->swap_type != BOOT_SWAP_TYPE_TEST &&
434 table->swap_type != BOOT_SWAP_TYPE_PERM &&
435 table->swap_type != BOOT_SWAP_TYPE_REVERT) {
436 return BOOT_SWAP_TYPE_PANIC;
437 }
438 return table->swap_type;
439 }
440 }
441
442 BOOT_LOG_INF("Swap type: none");
443 return BOOT_SWAP_TYPE_NONE;
444}
445
446/*
447 * This function is not used by the bootloader itself, but its required API
448 * by external tooling like mcumgr.
449 */
450int
451boot_swap_type(void)
452{
453 return boot_swap_type_multi(0);
454}
455
456/**
457 * Marks the image in the secondary slot as pending. On the next reboot,
458 * the system will perform a one-time boot of the the secondary slot image.
459 *
460 * @param permanent Whether the image should be used permanently or
461 * only tested once:
462 * 0=run image once, then confirm or revert.
463 * 1=run image forever.
464 *
465 * @return 0 on success; nonzero on failure.
466 */
467int
468boot_set_pending(int permanent)
469{
470 const struct flash_area *fap;
471 struct boot_swap_state state_secondary_slot;
472 uint8_t swap_type;
473 int rc;
474
475 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_SECONDARY(0),
476 &state_secondary_slot);
477 if (rc != 0) {
478 return rc;
479 }
480
481 switch (state_secondary_slot.magic) {
482 case BOOT_MAGIC_GOOD:
483 /* Swap already scheduled. */
484 return 0;
485
486 case BOOT_MAGIC_UNSET:
487 rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &fap);
488 if (rc != 0) {
489 rc = BOOT_EFLASH;
490 } else {
491 rc = boot_write_magic(fap);
492 }
493
494 if (rc == 0 && permanent) {
495 rc = boot_write_image_ok(fap);
496 }
497
498 if (rc == 0) {
499 if (permanent) {
500 swap_type = BOOT_SWAP_TYPE_PERM;
501 } else {
502 swap_type = BOOT_SWAP_TYPE_TEST;
503 }
504 rc = boot_write_swap_info(fap, swap_type, 0);
505 }
506
507 flash_area_close(fap);
508 return rc;
509
510 case BOOT_MAGIC_BAD:
511 /* The image slot is corrupt. There is no way to recover, so erase the
512 * slot to allow future upgrades.
513 */
514 rc = flash_area_open(FLASH_AREA_IMAGE_SECONDARY(0), &fap);
515 if (rc != 0) {
516 return BOOT_EFLASH;
517 }
518
519 flash_area_erase(fap, 0, fap->fa_size);
520 flash_area_close(fap);
521 return BOOT_EBADIMAGE;
522
523 default:
524 assert(0);
525 return BOOT_EBADIMAGE;
526 }
527}
528
529/**
530 * Marks the image in the primary slot as confirmed. The system will continue
531 * booting into the image in the primary slot until told to boot from a
532 * different slot.
533 *
534 * @return 0 on success; nonzero on failure.
535 */
536int
537boot_set_confirmed(void)
538{
539 const struct flash_area *fap;
540 struct boot_swap_state state_primary_slot;
541 int rc;
542
543 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_PRIMARY(0),
544 &state_primary_slot);
545 if (rc != 0) {
546 return rc;
547 }
548
549 switch (state_primary_slot.magic) {
550 case BOOT_MAGIC_GOOD:
551 /* Confirm needed; proceed. */
552 break;
553
554 case BOOT_MAGIC_UNSET:
555 /* Already confirmed. */
556 return 0;
557
558 case BOOT_MAGIC_BAD:
559 /* Unexpected state. */
560 return BOOT_EBADVECT;
561 }
562
563 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY(0), &fap);
564 if (rc) {
565 rc = BOOT_EFLASH;
566 goto done;
567 }
568
569 if (state_primary_slot.copy_done == BOOT_FLAG_UNSET) {
570 /* Swap never completed. This is unexpected. */
571 rc = BOOT_EBADVECT;
572 goto done;
573 }
574
575 if (state_primary_slot.image_ok != BOOT_FLAG_UNSET) {
576 /* Already confirmed. */
577 goto done;
578 }
579
580 rc = boot_write_image_ok(fap);
581
582done:
583 flash_area_close(fap);
584 return rc;
585}