blob: b1bea5d6fcbd12fa95886ca74397ca58073ba24d [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#include <assert.h>
21#include <string.h>
22#include <inttypes.h>
Fabio Utziga0bc9b52017-06-28 09:19:55 -030023#include <stddef.h>
Christopher Collins92ea77f2016-12-12 15:59:26 -080024
Christopher Collins92ea77f2016-12-12 15:59:26 -080025#include "sysflash/sysflash.h"
26#include "hal/hal_bsp.h"
27#include "hal/hal_flash.h"
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +020028
29#include "flash_map_backend/flash_map_backend.h"
30
Christopher Collins92ea77f2016-12-12 15:59:26 -080031#include "os/os.h"
32#include "bootutil/image.h"
33#include "bootutil/bootutil.h"
34#include "bootutil_priv.h"
Fabio Utzig7ebb7c22017-04-26 10:59:31 -030035#include "bootutil/bootutil_log.h"
36
Christopher Collins92ea77f2016-12-12 15:59:26 -080037int boot_current_slot;
38
Fabio Utzig24a273d2017-04-20 08:21:31 -030039const uint32_t boot_img_magic[] = {
Christopher Collins92ea77f2016-12-12 15:59:26 -080040 0xf395c277,
41 0x7fefd260,
42 0x0f505235,
43 0x8079b62c,
44};
45
Fabio Utzig24a273d2017-04-20 08:21:31 -030046const uint32_t BOOT_MAGIC_SZ = sizeof boot_img_magic;
Fabio Utziga0bc9b52017-06-28 09:19:55 -030047const uint32_t BOOT_MAX_ALIGN = MAX_FLASH_ALIGN;
Fabio Utzig24a273d2017-04-20 08:21:31 -030048
Christopher Collins92ea77f2016-12-12 15:59:26 -080049struct boot_swap_table {
Fabio Utzigb5b2f552017-06-30 10:03:47 -030050 uint8_t magic_slot0;
51 uint8_t magic_slot1;
52 uint8_t image_ok_slot0;
53 uint8_t image_ok_slot1;
Fabio Utzigd7d20752017-07-13 16:03:25 -030054 uint8_t copy_done_slot0;
Christopher Collins92ea77f2016-12-12 15:59:26 -080055
Fabio Utzigb5b2f552017-06-30 10:03:47 -030056 uint8_t swap_type;
Christopher Collins92ea77f2016-12-12 15:59:26 -080057};
58
59/**
60 * This set of tables maps image trailer contents to swap operation type.
61 * When searching for a match, these tables must be iterated sequentially.
Fabio Utzigb5b2f552017-06-30 10:03:47 -030062 *
63 * NOTE: the table order is very important. The settings in Slot 1 always
64 * are priority to Slot 0 and should be located earlier in the table.
65 *
66 * The table lists only states where there is action needs to be taken by
67 * the bootloader, as in starting/finishing a swap operation.
Christopher Collins92ea77f2016-12-12 15:59:26 -080068 */
69static const struct boot_swap_table boot_swap_tables[] = {
70 {
Fabio Utzig39000012018-07-30 12:40:20 -030071 .magic_slot0 = BOOT_MAGIC_ANY,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030072 .magic_slot1 = BOOT_MAGIC_GOOD,
Fabio Utzig39000012018-07-30 12:40:20 -030073 .image_ok_slot0 = BOOT_FLAG_ANY,
74 .image_ok_slot1 = BOOT_FLAG_UNSET,
75 .copy_done_slot0 = BOOT_FLAG_ANY,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030076 .swap_type = BOOT_SWAP_TYPE_TEST,
Christopher Collins92ea77f2016-12-12 15:59:26 -080077 },
Christopher Collins92ea77f2016-12-12 15:59:26 -080078 {
Fabio Utzig39000012018-07-30 12:40:20 -030079 .magic_slot0 = BOOT_MAGIC_ANY,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030080 .magic_slot1 = BOOT_MAGIC_GOOD,
Fabio Utzig39000012018-07-30 12:40:20 -030081 .image_ok_slot0 = BOOT_FLAG_ANY,
82 .image_ok_slot1 = BOOT_FLAG_SET,
83 .copy_done_slot0 = BOOT_FLAG_ANY,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030084 .swap_type = BOOT_SWAP_TYPE_PERM,
Christopher Collins92ea77f2016-12-12 15:59:26 -080085 },
Christopher Collins92ea77f2016-12-12 15:59:26 -080086 {
Fabio Utzigb5b2f552017-06-30 10:03:47 -030087 .magic_slot0 = BOOT_MAGIC_GOOD,
88 .magic_slot1 = BOOT_MAGIC_UNSET,
Fabio Utzig39000012018-07-30 12:40:20 -030089 .image_ok_slot0 = BOOT_FLAG_UNSET,
90 .image_ok_slot1 = BOOT_FLAG_ANY,
91 .copy_done_slot0 = BOOT_FLAG_SET,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030092 .swap_type = BOOT_SWAP_TYPE_REVERT,
Christopher Collins92ea77f2016-12-12 15:59:26 -080093 },
94};
95
96#define BOOT_SWAP_TABLES_COUNT \
97 (sizeof boot_swap_tables / sizeof boot_swap_tables[0])
98
Fabio Utzig39000012018-07-30 12:40:20 -030099static int
100boot_magic_decode(const struct flash_area *fap, const uint32_t *magic)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800101{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200102 size_t i;
Fabio Utzig39000012018-07-30 12:40:20 -0300103 uint8_t erased_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800104
Fabio Utzig24a273d2017-04-20 08:21:31 -0300105 if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
Christopher Collins92ea77f2016-12-12 15:59:26 -0800106 return BOOT_MAGIC_GOOD;
107 }
108
Fabio Utzig39000012018-07-30 12:40:20 -0300109 erased_val = flash_area_erased_val(fap);
110 for (i = 0; i < BOOT_MAGIC_SZ; i++) {
111 if (((uint8_t *)magic)[i] != erased_val) {
Fabio Utzig24a273d2017-04-20 08:21:31 -0300112 return BOOT_MAGIC_BAD;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800113 }
114 }
115
Fabio Utzig24a273d2017-04-20 08:21:31 -0300116 return BOOT_MAGIC_UNSET;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800117}
118
Fabio Utzig39000012018-07-30 12:40:20 -0300119static int
120boot_flag_decode(const struct flash_area *fap, uint8_t flag)
121{
122 uint8_t erased_val;
123
124 erased_val = flash_area_erased_val(fap);
125 if (flag == erased_val) {
126 return BOOT_FLAG_UNSET;
127 }
128 if (flag != BOOT_FLAG_SET) {
129 return BOOT_FLAG_BAD;
130 }
131 return BOOT_FLAG_SET;
132}
133
Christopher Collins92ea77f2016-12-12 15:59:26 -0800134uint32_t
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300135boot_slots_trailer_sz(uint8_t min_write_sz)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800136{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300137 return /* state for all sectors */
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300138 BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
Fabio Utzig46490722017-09-04 15:34:32 -0300139 BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */ +
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300140 BOOT_MAGIC_SZ;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800141}
142
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300143static uint32_t
144boot_scratch_trailer_sz(uint8_t min_write_sz)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800145{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300146 return BOOT_STATUS_STATE_COUNT * min_write_sz + /* state for one sector */
Fabio Utzig46490722017-09-04 15:34:32 -0300147 BOOT_MAX_ALIGN * 2 + /* image_ok + swap_size */
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300148 BOOT_MAGIC_SZ;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800149}
150
151static uint32_t
152boot_magic_off(const struct flash_area *fap)
153{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300154 assert(offsetof(struct image_trailer, magic) == 16);
155 return fap->fa_size - BOOT_MAGIC_SZ;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800156}
157
Fabio Utzig4cee4f72017-05-22 10:59:57 -0400158int
159boot_status_entries(const struct flash_area *fap)
160{
161 switch (fap->fa_id) {
162 case FLASH_AREA_IMAGE_0:
163 case FLASH_AREA_IMAGE_1:
164 return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
165 case FLASH_AREA_IMAGE_SCRATCH:
166 return BOOT_STATUS_STATE_COUNT;
167 default:
168 return BOOT_EBADARGS;
169 }
170}
171
Christopher Collins92ea77f2016-12-12 15:59:26 -0800172uint32_t
173boot_status_off(const struct flash_area *fap)
174{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300175 uint32_t off_from_end;
176 uint8_t elem_sz;
177
178 elem_sz = flash_area_align(fap);
179
180 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
181 off_from_end = boot_scratch_trailer_sz(elem_sz);
182 } else {
183 off_from_end = boot_slots_trailer_sz(elem_sz);
184 }
185
186 assert(off_from_end <= fap->fa_size);
187 return fap->fa_size - off_from_end;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800188}
189
190static uint32_t
191boot_copy_done_off(const struct flash_area *fap)
192{
Fabio Utzig2473ac02017-05-02 12:45:02 -0300193 assert(fap->fa_id != FLASH_AREA_IMAGE_SCRATCH);
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300194 assert(offsetof(struct image_trailer, copy_done) == 0);
195 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800196}
197
198static uint32_t
199boot_image_ok_off(const struct flash_area *fap)
200{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300201 assert(offsetof(struct image_trailer, image_ok) == 8);
202 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800203}
204
Fabio Utzig46490722017-09-04 15:34:32 -0300205static uint32_t
206boot_swap_size_off(const struct flash_area *fap)
207{
208 /*
209 * The "swap_size" field if located just before the trailer.
210 * The scratch slot doesn't store "copy_done"...
211 */
212 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
213 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
214 }
215
216 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
217}
218
Christopher Collins92ea77f2016-12-12 15:59:26 -0800219int
220boot_read_swap_state(const struct flash_area *fap,
221 struct boot_swap_state *state)
222{
Fabio Utzig24a273d2017-04-20 08:21:31 -0300223 uint32_t magic[BOOT_MAGIC_SZ];
Christopher Collins92ea77f2016-12-12 15:59:26 -0800224 uint32_t off;
225 int rc;
226
227 off = boot_magic_off(fap);
Fabio Utzig24a273d2017-04-20 08:21:31 -0300228 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800229 if (rc != 0) {
230 return BOOT_EFLASH;
231 }
Fabio Utzig39000012018-07-30 12:40:20 -0300232 state->magic = boot_magic_decode(fap, magic);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800233
Fabio Utzig2473ac02017-05-02 12:45:02 -0300234 if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
235 off = boot_copy_done_off(fap);
Fabio Utzig46490722017-09-04 15:34:32 -0300236 rc = flash_area_read(fap, off, &state->copy_done, sizeof state->copy_done);
Fabio Utzig2473ac02017-05-02 12:45:02 -0300237 if (rc != 0) {
238 return BOOT_EFLASH;
239 }
Fabio Utzig39000012018-07-30 12:40:20 -0300240 state->copy_done = boot_flag_decode(fap, state->copy_done);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800241 }
242
243 off = boot_image_ok_off(fap);
Fabio Utzig46490722017-09-04 15:34:32 -0300244 rc = flash_area_read(fap, off, &state->image_ok, sizeof state->image_ok);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800245 if (rc != 0) {
246 return BOOT_EFLASH;
247 }
Fabio Utzig39000012018-07-30 12:40:20 -0300248 state->image_ok = boot_flag_decode(fap, state->image_ok);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800249
250 return 0;
251}
252
253/**
254 * Reads the image trailer from the scratch area.
255 */
256int
Fabio Utzig2473ac02017-05-02 12:45:02 -0300257boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800258{
259 const struct flash_area *fap;
260 int rc;
261
Fabio Utzig2473ac02017-05-02 12:45:02 -0300262 switch (flash_area_id) {
263 case FLASH_AREA_IMAGE_SCRATCH:
264 case FLASH_AREA_IMAGE_0:
265 case FLASH_AREA_IMAGE_1:
266 rc = flash_area_open(flash_area_id, &fap);
267 if (rc != 0) {
268 return BOOT_EFLASH;
269 }
270 break;
271 default:
Fabio Utzig856f7832017-05-22 11:04:44 -0400272 return BOOT_EBADARGS;
Fabio Utzig2473ac02017-05-02 12:45:02 -0300273 }
274
275 rc = boot_read_swap_state(fap, state);
Fabio Utzigacfba2e2017-05-22 11:06:29 -0400276 flash_area_close(fap);
277 return rc;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800278}
279
280int
Fabio Utzig46490722017-09-04 15:34:32 -0300281boot_read_swap_size(uint32_t *swap_size)
282{
283 uint32_t magic[BOOT_MAGIC_SZ];
284 uint32_t off;
285 const struct flash_area *fap;
286 int rc;
287
288 /*
289 * In the middle a swap, tries to locate the saved swap size. Looks
290 * for a valid magic, first on Slot 0, then on scratch. Both "slots"
291 * can end up being temporary storage for a swap and it is assumed
292 * that if magic is valid then swap size is too, because magic is
293 * always written in the last step.
294 */
295
296 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
297 if (rc != 0) {
298 return BOOT_EFLASH;
299 }
300
301 off = boot_magic_off(fap);
302 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
303 if (rc != 0) {
304 rc = BOOT_EFLASH;
305 goto out;
306 }
307
308 if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
309 /*
310 * If Slot 0 's magic is not valid, try scratch...
311 */
312
313 flash_area_close(fap);
314
315 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
316 if (rc != 0) {
317 return BOOT_EFLASH;
318 }
319
320 off = boot_magic_off(fap);
321 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
322 if (rc != 0) {
323 rc = BOOT_EFLASH;
324 goto out;
325 }
326
327 assert(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
328 }
329
330 off = boot_swap_size_off(fap);
331 rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
332 if (rc != 0) {
333 rc = BOOT_EFLASH;
334 }
335
336out:
337 flash_area_close(fap);
338 return rc;
339}
340
341
342int
Christopher Collins92ea77f2016-12-12 15:59:26 -0800343boot_write_magic(const struct flash_area *fap)
344{
345 uint32_t off;
346 int rc;
347
348 off = boot_magic_off(fap);
349
Fabio Utzig24a273d2017-04-20 08:21:31 -0300350 rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800351 if (rc != 0) {
352 return BOOT_EFLASH;
353 }
354
355 return 0;
356}
357
Fabio Utzig2473ac02017-05-02 12:45:02 -0300358static int
359boot_write_flag(int flag, const struct flash_area *fap)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800360{
361 uint32_t off;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800362 int rc;
Fabio Utzig644b8d42017-04-20 07:56:05 -0300363 uint8_t buf[BOOT_MAX_ALIGN];
David Brown9d725462017-01-23 15:50:58 -0700364 uint8_t align;
Fabio Utzig39000012018-07-30 12:40:20 -0300365 uint8_t erased_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800366
Fabio Utzig2473ac02017-05-02 12:45:02 -0300367 switch (flag) {
368 case BOOT_FLAG_COPY_DONE:
369 off = boot_copy_done_off(fap);
370 break;
371 case BOOT_FLAG_IMAGE_OK:
372 off = boot_image_ok_off(fap);
373 break;
374 default:
Fabio Utzig856f7832017-05-22 11:04:44 -0400375 return BOOT_EBADARGS;
Fabio Utzig2473ac02017-05-02 12:45:02 -0300376 }
Christopher Collins92ea77f2016-12-12 15:59:26 -0800377
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +0200378 align = flash_area_align(fap);
Fabio Utzig644b8d42017-04-20 07:56:05 -0300379 assert(align <= BOOT_MAX_ALIGN);
Fabio Utzig39000012018-07-30 12:40:20 -0300380 erased_val = flash_area_erased_val(fap);
381 memset(buf, erased_val, BOOT_MAX_ALIGN);
Fabio Utzigde8a38a2017-05-23 11:15:01 -0400382 buf[0] = BOOT_FLAG_SET;
David Brown9d725462017-01-23 15:50:58 -0700383
384 rc = flash_area_write(fap, off, buf, align);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800385 if (rc != 0) {
386 return BOOT_EFLASH;
387 }
388
389 return 0;
390}
391
392int
Fabio Utzig2473ac02017-05-02 12:45:02 -0300393boot_write_copy_done(const struct flash_area *fap)
394{
395 return boot_write_flag(BOOT_FLAG_COPY_DONE, fap);
396}
397
398int
Christopher Collins92ea77f2016-12-12 15:59:26 -0800399boot_write_image_ok(const struct flash_area *fap)
400{
Fabio Utzig2473ac02017-05-02 12:45:02 -0300401 return boot_write_flag(BOOT_FLAG_IMAGE_OK, fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800402}
403
404int
Fabio Utzig46490722017-09-04 15:34:32 -0300405boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
406{
407 uint32_t off;
408 int rc;
409 uint8_t buf[BOOT_MAX_ALIGN];
410 uint8_t align;
Fabio Utzig39000012018-07-30 12:40:20 -0300411 uint8_t erased_val;
Fabio Utzig46490722017-09-04 15:34:32 -0300412
413 off = boot_swap_size_off(fap);
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +0200414 align = flash_area_align(fap);
Fabio Utzig46490722017-09-04 15:34:32 -0300415 assert(align <= BOOT_MAX_ALIGN);
416 if (align < sizeof swap_size) {
417 align = sizeof swap_size;
418 }
Fabio Utzig39000012018-07-30 12:40:20 -0300419 erased_val = flash_area_erased_val(fap);
420 memset(buf, erased_val, BOOT_MAX_ALIGN);
Fabio Utzig46490722017-09-04 15:34:32 -0300421 memcpy(buf, (uint8_t *)&swap_size, sizeof swap_size);
422
423 rc = flash_area_write(fap, off, buf, align);
424 if (rc != 0) {
425 return BOOT_EFLASH;
426 }
427
428 return 0;
429}
430
431int
Christopher Collins92ea77f2016-12-12 15:59:26 -0800432boot_swap_type(void)
433{
434 const struct boot_swap_table *table;
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300435 struct boot_swap_state slot0;
436 struct boot_swap_state slot1;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800437 int rc;
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200438 size_t i;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800439
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300440 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &slot0);
441 if (rc) {
442 return BOOT_SWAP_TYPE_PANIC;
443 }
Christopher Collins92ea77f2016-12-12 15:59:26 -0800444
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300445 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &slot1);
446 if (rc) {
447 return BOOT_SWAP_TYPE_PANIC;
448 }
Christopher Collins92ea77f2016-12-12 15:59:26 -0800449
450 for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
451 table = boot_swap_tables + i;
452
Fabio Utzig39000012018-07-30 12:40:20 -0300453 if ((table->magic_slot0 == BOOT_MAGIC_ANY ||
454 table->magic_slot0 == slot0.magic) &&
455 (table->magic_slot1 == BOOT_MAGIC_ANY ||
456 table->magic_slot1 == slot1.magic) &&
457 (table->image_ok_slot0 == BOOT_FLAG_ANY ||
458 table->image_ok_slot0 == slot0.image_ok) &&
459 (table->image_ok_slot1 == BOOT_FLAG_ANY ||
460 table->image_ok_slot1 == slot1.image_ok) &&
461 (table->copy_done_slot0 == BOOT_FLAG_ANY ||
462 table->copy_done_slot0 == slot0.copy_done)) {
Fabio Utzig34e393e2017-05-22 11:07:07 -0400463 BOOT_LOG_INF("Swap type: %s",
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300464 table->swap_type == BOOT_SWAP_TYPE_TEST ? "test" :
465 table->swap_type == BOOT_SWAP_TYPE_PERM ? "perm" :
466 table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
467 "BUG; can't happen");
468 assert(table->swap_type == BOOT_SWAP_TYPE_TEST ||
469 table->swap_type == BOOT_SWAP_TYPE_PERM ||
470 table->swap_type == BOOT_SWAP_TYPE_REVERT);
471 return table->swap_type;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800472 }
473 }
474
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300475 BOOT_LOG_INF("Swap type: none");
Christopher Collins92ea77f2016-12-12 15:59:26 -0800476 return BOOT_SWAP_TYPE_NONE;
477}
478
479/**
480 * Marks the image in slot 1 as pending. On the next reboot, the system will
481 * perform a one-time boot of the slot 1 image.
482 *
Christopher Collins7835c1e2016-12-21 10:10:51 -0800483 * @param permanent Whether the image should be used permanently or
484 * only tested once:
485 * 0=run image once, then confirm or revert.
486 * 1=run image forever.
487 *
Christopher Collins92ea77f2016-12-12 15:59:26 -0800488 * @return 0 on success; nonzero on failure.
489 */
490int
Christopher Collins7835c1e2016-12-21 10:10:51 -0800491boot_set_pending(int permanent)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800492{
493 const struct flash_area *fap;
494 struct boot_swap_state state_slot1;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800495 int rc;
496
Fabio Utzig2473ac02017-05-02 12:45:02 -0300497 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &state_slot1);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800498 if (rc != 0) {
499 return rc;
500 }
501
502 switch (state_slot1.magic) {
503 case BOOT_MAGIC_GOOD:
504 /* Swap already scheduled. */
505 return 0;
506
507 case BOOT_MAGIC_UNSET:
Fabio Utzig2473ac02017-05-02 12:45:02 -0300508 rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800509 if (rc != 0) {
510 rc = BOOT_EFLASH;
511 } else {
512 rc = boot_write_magic(fap);
513 }
514
Christopher Collins7835c1e2016-12-21 10:10:51 -0800515 if (rc == 0 && permanent) {
516 rc = boot_write_image_ok(fap);
517 }
518
Christopher Collins92ea77f2016-12-12 15:59:26 -0800519 flash_area_close(fap);
520 return rc;
521
522 default:
523 /* XXX: Temporary assert. */
524 assert(0);
525 return -1;
526 }
527}
528
529/**
530 * Marks the image in slot 0 as confirmed. The system will continue booting into the image in slot 0 until told to boot from a different slot.
531 *
532 * @return 0 on success; nonzero on failure.
533 */
534int
535boot_set_confirmed(void)
536{
537 const struct flash_area *fap;
538 struct boot_swap_state state_slot0;
Fabio Utzig39000012018-07-30 12:40:20 -0300539 uint8_t erased_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800540 int rc;
541
Fabio Utzig2473ac02017-05-02 12:45:02 -0300542 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800543 if (rc != 0) {
544 return rc;
545 }
546
547 switch (state_slot0.magic) {
548 case BOOT_MAGIC_GOOD:
549 /* Confirm needed; proceed. */
550 break;
551
552 case BOOT_MAGIC_UNSET:
553 /* Already confirmed. */
554 return 0;
555
556 case BOOT_MAGIC_BAD:
557 /* Unexpected state. */
558 return BOOT_EBADVECT;
559 }
560
Christopher Collins92ea77f2016-12-12 15:59:26 -0800561 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
562 if (rc) {
563 rc = BOOT_EFLASH;
564 goto done;
565 }
566
Fabio Utzig39000012018-07-30 12:40:20 -0300567 erased_val = flash_area_erased_val(fap);
568 if (state_slot0.copy_done == erased_val) {
569 /* Swap never completed. This is unexpected. */
570 rc = BOOT_EBADVECT;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800571 goto done;
572 }
573
Fabio Utzig39000012018-07-30 12:40:20 -0300574 if (state_slot0.image_ok != erased_val) {
575 /* Already confirmed. */
576 goto done;
577 }
578
579 rc = boot_write_image_ok(fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800580
581done:
582 flash_area_close(fap);
583 return rc;
584}