blob: 9fcea4eda0f673d6b853ee32e30010fa1f8e24f4 [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
Hovland, Sigvart1d96f362018-09-25 13:23:42 +020046#define BOOT_MAGIC_ARR_SZ \
47 (sizeof boot_img_magic / sizeof boot_img_magic[0])
48
Fabio Utzig24a273d2017-04-20 08:21:31 -030049const uint32_t BOOT_MAGIC_SZ = sizeof boot_img_magic;
Fabio Utziga0bc9b52017-06-28 09:19:55 -030050const uint32_t BOOT_MAX_ALIGN = MAX_FLASH_ALIGN;
Fabio Utzig24a273d2017-04-20 08:21:31 -030051
Christopher Collins92ea77f2016-12-12 15:59:26 -080052struct boot_swap_table {
Fabio Utzigb5b2f552017-06-30 10:03:47 -030053 uint8_t magic_slot0;
54 uint8_t magic_slot1;
55 uint8_t image_ok_slot0;
56 uint8_t image_ok_slot1;
Fabio Utzigd7d20752017-07-13 16:03:25 -030057 uint8_t copy_done_slot0;
Christopher Collins92ea77f2016-12-12 15:59:26 -080058
Fabio Utzigb5b2f552017-06-30 10:03:47 -030059 uint8_t swap_type;
Christopher Collins92ea77f2016-12-12 15:59:26 -080060};
61
62/**
63 * This set of tables maps image trailer contents to swap operation type.
64 * When searching for a match, these tables must be iterated sequentially.
Fabio Utzigb5b2f552017-06-30 10:03:47 -030065 *
66 * NOTE: the table order is very important. The settings in Slot 1 always
67 * are priority to Slot 0 and should be located earlier in the table.
68 *
69 * The table lists only states where there is action needs to be taken by
70 * the bootloader, as in starting/finishing a swap operation.
Christopher Collins92ea77f2016-12-12 15:59:26 -080071 */
72static const struct boot_swap_table boot_swap_tables[] = {
73 {
Fabio Utzig39000012018-07-30 12:40:20 -030074 .magic_slot0 = BOOT_MAGIC_ANY,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030075 .magic_slot1 = BOOT_MAGIC_GOOD,
Fabio Utzig39000012018-07-30 12:40:20 -030076 .image_ok_slot0 = BOOT_FLAG_ANY,
77 .image_ok_slot1 = BOOT_FLAG_UNSET,
78 .copy_done_slot0 = BOOT_FLAG_ANY,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030079 .swap_type = BOOT_SWAP_TYPE_TEST,
Christopher Collins92ea77f2016-12-12 15:59:26 -080080 },
Christopher Collins92ea77f2016-12-12 15:59:26 -080081 {
Fabio Utzig39000012018-07-30 12:40:20 -030082 .magic_slot0 = BOOT_MAGIC_ANY,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030083 .magic_slot1 = BOOT_MAGIC_GOOD,
Fabio Utzig39000012018-07-30 12:40:20 -030084 .image_ok_slot0 = BOOT_FLAG_ANY,
85 .image_ok_slot1 = BOOT_FLAG_SET,
86 .copy_done_slot0 = BOOT_FLAG_ANY,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030087 .swap_type = BOOT_SWAP_TYPE_PERM,
Christopher Collins92ea77f2016-12-12 15:59:26 -080088 },
Christopher Collins92ea77f2016-12-12 15:59:26 -080089 {
Fabio Utzigb5b2f552017-06-30 10:03:47 -030090 .magic_slot0 = BOOT_MAGIC_GOOD,
91 .magic_slot1 = BOOT_MAGIC_UNSET,
Fabio Utzig39000012018-07-30 12:40:20 -030092 .image_ok_slot0 = BOOT_FLAG_UNSET,
93 .image_ok_slot1 = BOOT_FLAG_ANY,
94 .copy_done_slot0 = BOOT_FLAG_SET,
Fabio Utzigb5b2f552017-06-30 10:03:47 -030095 .swap_type = BOOT_SWAP_TYPE_REVERT,
Christopher Collins92ea77f2016-12-12 15:59:26 -080096 },
97};
98
99#define BOOT_SWAP_TABLES_COUNT \
100 (sizeof boot_swap_tables / sizeof boot_swap_tables[0])
101
Fabio Utzig39000012018-07-30 12:40:20 -0300102static int
103boot_magic_decode(const struct flash_area *fap, const uint32_t *magic)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800104{
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200105 size_t i;
Fabio Utzig39000012018-07-30 12:40:20 -0300106 uint8_t erased_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800107
Fabio Utzig24a273d2017-04-20 08:21:31 -0300108 if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0) {
Christopher Collins92ea77f2016-12-12 15:59:26 -0800109 return BOOT_MAGIC_GOOD;
110 }
111
Fabio Utzig39000012018-07-30 12:40:20 -0300112 erased_val = flash_area_erased_val(fap);
113 for (i = 0; i < BOOT_MAGIC_SZ; i++) {
114 if (((uint8_t *)magic)[i] != erased_val) {
Fabio Utzig24a273d2017-04-20 08:21:31 -0300115 return BOOT_MAGIC_BAD;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800116 }
117 }
118
Fabio Utzig24a273d2017-04-20 08:21:31 -0300119 return BOOT_MAGIC_UNSET;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800120}
121
Fabio Utzig39000012018-07-30 12:40:20 -0300122static int
123boot_flag_decode(const struct flash_area *fap, uint8_t flag)
124{
125 uint8_t erased_val;
126
127 erased_val = flash_area_erased_val(fap);
128 if (flag == erased_val) {
129 return BOOT_FLAG_UNSET;
130 }
131 if (flag != BOOT_FLAG_SET) {
132 return BOOT_FLAG_BAD;
133 }
134 return BOOT_FLAG_SET;
135}
136
Christopher Collins92ea77f2016-12-12 15:59:26 -0800137uint32_t
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300138boot_slots_trailer_sz(uint8_t min_write_sz)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800139{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300140 return /* state for all sectors */
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300141 BOOT_STATUS_MAX_ENTRIES * BOOT_STATUS_STATE_COUNT * min_write_sz +
Fabio Utzig46490722017-09-04 15:34:32 -0300142 BOOT_MAX_ALIGN * 3 /* copy_done + image_ok + swap_size */ +
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300143 BOOT_MAGIC_SZ;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800144}
145
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300146static uint32_t
147boot_scratch_trailer_sz(uint8_t min_write_sz)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800148{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300149 return BOOT_STATUS_STATE_COUNT * min_write_sz + /* state for one sector */
Fabio Utzig46490722017-09-04 15:34:32 -0300150 BOOT_MAX_ALIGN * 2 + /* image_ok + swap_size */
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300151 BOOT_MAGIC_SZ;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800152}
153
154static uint32_t
155boot_magic_off(const struct flash_area *fap)
156{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300157 assert(offsetof(struct image_trailer, magic) == 16);
158 return fap->fa_size - BOOT_MAGIC_SZ;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800159}
160
Fabio Utzig4cee4f72017-05-22 10:59:57 -0400161int
162boot_status_entries(const struct flash_area *fap)
163{
164 switch (fap->fa_id) {
165 case FLASH_AREA_IMAGE_0:
166 case FLASH_AREA_IMAGE_1:
167 return BOOT_STATUS_STATE_COUNT * BOOT_STATUS_MAX_ENTRIES;
168 case FLASH_AREA_IMAGE_SCRATCH:
169 return BOOT_STATUS_STATE_COUNT;
170 default:
171 return BOOT_EBADARGS;
172 }
173}
174
Christopher Collins92ea77f2016-12-12 15:59:26 -0800175uint32_t
176boot_status_off(const struct flash_area *fap)
177{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300178 uint32_t off_from_end;
179 uint8_t elem_sz;
180
181 elem_sz = flash_area_align(fap);
182
183 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
184 off_from_end = boot_scratch_trailer_sz(elem_sz);
185 } else {
186 off_from_end = boot_slots_trailer_sz(elem_sz);
187 }
188
189 assert(off_from_end <= fap->fa_size);
190 return fap->fa_size - off_from_end;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800191}
192
193static uint32_t
194boot_copy_done_off(const struct flash_area *fap)
195{
Fabio Utzig2473ac02017-05-02 12:45:02 -0300196 assert(fap->fa_id != FLASH_AREA_IMAGE_SCRATCH);
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300197 assert(offsetof(struct image_trailer, copy_done) == 0);
198 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800199}
200
201static uint32_t
202boot_image_ok_off(const struct flash_area *fap)
203{
Fabio Utziga0bc9b52017-06-28 09:19:55 -0300204 assert(offsetof(struct image_trailer, image_ok) == 8);
205 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800206}
207
Fabio Utzig46490722017-09-04 15:34:32 -0300208static uint32_t
209boot_swap_size_off(const struct flash_area *fap)
210{
211 /*
212 * The "swap_size" field if located just before the trailer.
213 * The scratch slot doesn't store "copy_done"...
214 */
215 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
216 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
217 }
218
219 return fap->fa_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 3;
220}
221
Christopher Collins92ea77f2016-12-12 15:59:26 -0800222int
223boot_read_swap_state(const struct flash_area *fap,
224 struct boot_swap_state *state)
225{
Hovland, Sigvart1d96f362018-09-25 13:23:42 +0200226 uint32_t magic[BOOT_MAGIC_ARR_SZ];
Christopher Collins92ea77f2016-12-12 15:59:26 -0800227 uint32_t off;
228 int rc;
229
230 off = boot_magic_off(fap);
Fabio Utzig24a273d2017-04-20 08:21:31 -0300231 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800232 if (rc != 0) {
233 return BOOT_EFLASH;
234 }
Fabio Utzig39000012018-07-30 12:40:20 -0300235 state->magic = boot_magic_decode(fap, magic);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800236
Fabio Utzig2473ac02017-05-02 12:45:02 -0300237 if (fap->fa_id != FLASH_AREA_IMAGE_SCRATCH) {
238 off = boot_copy_done_off(fap);
Fabio Utzig46490722017-09-04 15:34:32 -0300239 rc = flash_area_read(fap, off, &state->copy_done, sizeof state->copy_done);
Fabio Utzig2473ac02017-05-02 12:45:02 -0300240 if (rc != 0) {
241 return BOOT_EFLASH;
242 }
Fabio Utzig39000012018-07-30 12:40:20 -0300243 state->copy_done = boot_flag_decode(fap, state->copy_done);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800244 }
245
246 off = boot_image_ok_off(fap);
Fabio Utzig46490722017-09-04 15:34:32 -0300247 rc = flash_area_read(fap, off, &state->image_ok, sizeof state->image_ok);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800248 if (rc != 0) {
249 return BOOT_EFLASH;
250 }
Fabio Utzig39000012018-07-30 12:40:20 -0300251 state->image_ok = boot_flag_decode(fap, state->image_ok);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800252
253 return 0;
254}
255
256/**
257 * Reads the image trailer from the scratch area.
258 */
259int
Fabio Utzig2473ac02017-05-02 12:45:02 -0300260boot_read_swap_state_by_id(int flash_area_id, struct boot_swap_state *state)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800261{
262 const struct flash_area *fap;
263 int rc;
264
Fabio Utzig2473ac02017-05-02 12:45:02 -0300265 switch (flash_area_id) {
266 case FLASH_AREA_IMAGE_SCRATCH:
267 case FLASH_AREA_IMAGE_0:
268 case FLASH_AREA_IMAGE_1:
269 rc = flash_area_open(flash_area_id, &fap);
270 if (rc != 0) {
271 return BOOT_EFLASH;
272 }
273 break;
274 default:
Fabio Utzig856f7832017-05-22 11:04:44 -0400275 return BOOT_EBADARGS;
Fabio Utzig2473ac02017-05-02 12:45:02 -0300276 }
277
278 rc = boot_read_swap_state(fap, state);
Fabio Utzigacfba2e2017-05-22 11:06:29 -0400279 flash_area_close(fap);
280 return rc;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800281}
282
283int
Fabio Utzig46490722017-09-04 15:34:32 -0300284boot_read_swap_size(uint32_t *swap_size)
285{
Hovland, Sigvart1d96f362018-09-25 13:23:42 +0200286 uint32_t magic[BOOT_MAGIC_ARR_SZ];
Fabio Utzig46490722017-09-04 15:34:32 -0300287 uint32_t off;
288 const struct flash_area *fap;
289 int rc;
290
291 /*
292 * In the middle a swap, tries to locate the saved swap size. Looks
293 * for a valid magic, first on Slot 0, then on scratch. Both "slots"
294 * can end up being temporary storage for a swap and it is assumed
295 * that if magic is valid then swap size is too, because magic is
296 * always written in the last step.
297 */
298
299 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
300 if (rc != 0) {
301 return BOOT_EFLASH;
302 }
303
304 off = boot_magic_off(fap);
305 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
306 if (rc != 0) {
307 rc = BOOT_EFLASH;
308 goto out;
309 }
310
311 if (memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) != 0) {
312 /*
313 * If Slot 0 's magic is not valid, try scratch...
314 */
315
316 flash_area_close(fap);
317
318 rc = flash_area_open(FLASH_AREA_IMAGE_SCRATCH, &fap);
319 if (rc != 0) {
320 return BOOT_EFLASH;
321 }
322
323 off = boot_magic_off(fap);
324 rc = flash_area_read(fap, off, magic, BOOT_MAGIC_SZ);
325 if (rc != 0) {
326 rc = BOOT_EFLASH;
327 goto out;
328 }
329
330 assert(memcmp(magic, boot_img_magic, BOOT_MAGIC_SZ) == 0);
331 }
332
333 off = boot_swap_size_off(fap);
334 rc = flash_area_read(fap, off, swap_size, sizeof *swap_size);
335 if (rc != 0) {
336 rc = BOOT_EFLASH;
337 }
338
339out:
340 flash_area_close(fap);
341 return rc;
342}
343
344
345int
Christopher Collins92ea77f2016-12-12 15:59:26 -0800346boot_write_magic(const struct flash_area *fap)
347{
348 uint32_t off;
349 int rc;
350
351 off = boot_magic_off(fap);
352
Fabio Utzig24a273d2017-04-20 08:21:31 -0300353 rc = flash_area_write(fap, off, boot_img_magic, BOOT_MAGIC_SZ);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800354 if (rc != 0) {
355 return BOOT_EFLASH;
356 }
357
358 return 0;
359}
360
Fabio Utzig2473ac02017-05-02 12:45:02 -0300361static int
362boot_write_flag(int flag, const struct flash_area *fap)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800363{
364 uint32_t off;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800365 int rc;
Fabio Utzig644b8d42017-04-20 07:56:05 -0300366 uint8_t buf[BOOT_MAX_ALIGN];
David Brown9d725462017-01-23 15:50:58 -0700367 uint8_t align;
Fabio Utzig39000012018-07-30 12:40:20 -0300368 uint8_t erased_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800369
Fabio Utzig2473ac02017-05-02 12:45:02 -0300370 switch (flag) {
371 case BOOT_FLAG_COPY_DONE:
372 off = boot_copy_done_off(fap);
373 break;
374 case BOOT_FLAG_IMAGE_OK:
375 off = boot_image_ok_off(fap);
376 break;
377 default:
Fabio Utzig856f7832017-05-22 11:04:44 -0400378 return BOOT_EBADARGS;
Fabio Utzig2473ac02017-05-02 12:45:02 -0300379 }
Christopher Collins92ea77f2016-12-12 15:59:26 -0800380
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +0200381 align = flash_area_align(fap);
Fabio Utzig644b8d42017-04-20 07:56:05 -0300382 assert(align <= BOOT_MAX_ALIGN);
Fabio Utzig39000012018-07-30 12:40:20 -0300383 erased_val = flash_area_erased_val(fap);
384 memset(buf, erased_val, BOOT_MAX_ALIGN);
Fabio Utzigde8a38a2017-05-23 11:15:01 -0400385 buf[0] = BOOT_FLAG_SET;
David Brown9d725462017-01-23 15:50:58 -0700386
387 rc = flash_area_write(fap, off, buf, align);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800388 if (rc != 0) {
389 return BOOT_EFLASH;
390 }
391
392 return 0;
393}
394
395int
Fabio Utzig2473ac02017-05-02 12:45:02 -0300396boot_write_copy_done(const struct flash_area *fap)
397{
398 return boot_write_flag(BOOT_FLAG_COPY_DONE, fap);
399}
400
401int
Christopher Collins92ea77f2016-12-12 15:59:26 -0800402boot_write_image_ok(const struct flash_area *fap)
403{
Fabio Utzig2473ac02017-05-02 12:45:02 -0300404 return boot_write_flag(BOOT_FLAG_IMAGE_OK, fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800405}
406
407int
Fabio Utzig46490722017-09-04 15:34:32 -0300408boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size)
409{
410 uint32_t off;
411 int rc;
412 uint8_t buf[BOOT_MAX_ALIGN];
413 uint8_t align;
Fabio Utzig39000012018-07-30 12:40:20 -0300414 uint8_t erased_val;
Fabio Utzig46490722017-09-04 15:34:32 -0300415
416 off = boot_swap_size_off(fap);
Andrzej Puzdrowskib788c712018-04-12 12:42:49 +0200417 align = flash_area_align(fap);
Fabio Utzig46490722017-09-04 15:34:32 -0300418 assert(align <= BOOT_MAX_ALIGN);
419 if (align < sizeof swap_size) {
420 align = sizeof swap_size;
421 }
Fabio Utzig39000012018-07-30 12:40:20 -0300422 erased_val = flash_area_erased_val(fap);
423 memset(buf, erased_val, BOOT_MAX_ALIGN);
Fabio Utzig46490722017-09-04 15:34:32 -0300424 memcpy(buf, (uint8_t *)&swap_size, sizeof swap_size);
425
426 rc = flash_area_write(fap, off, buf, align);
427 if (rc != 0) {
428 return BOOT_EFLASH;
429 }
430
431 return 0;
432}
433
434int
Christopher Collins92ea77f2016-12-12 15:59:26 -0800435boot_swap_type(void)
436{
437 const struct boot_swap_table *table;
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300438 struct boot_swap_state slot0;
439 struct boot_swap_state slot1;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800440 int rc;
Fabio Utzigcd5774b2017-11-29 10:18:26 -0200441 size_t i;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800442
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300443 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &slot0);
444 if (rc) {
445 return BOOT_SWAP_TYPE_PANIC;
446 }
Christopher Collins92ea77f2016-12-12 15:59:26 -0800447
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300448 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &slot1);
449 if (rc) {
450 return BOOT_SWAP_TYPE_PANIC;
451 }
Christopher Collins92ea77f2016-12-12 15:59:26 -0800452
453 for (i = 0; i < BOOT_SWAP_TABLES_COUNT; i++) {
454 table = boot_swap_tables + i;
455
Fabio Utzig39000012018-07-30 12:40:20 -0300456 if ((table->magic_slot0 == BOOT_MAGIC_ANY ||
457 table->magic_slot0 == slot0.magic) &&
458 (table->magic_slot1 == BOOT_MAGIC_ANY ||
459 table->magic_slot1 == slot1.magic) &&
460 (table->image_ok_slot0 == BOOT_FLAG_ANY ||
461 table->image_ok_slot0 == slot0.image_ok) &&
462 (table->image_ok_slot1 == BOOT_FLAG_ANY ||
463 table->image_ok_slot1 == slot1.image_ok) &&
464 (table->copy_done_slot0 == BOOT_FLAG_ANY ||
465 table->copy_done_slot0 == slot0.copy_done)) {
Fabio Utzig34e393e2017-05-22 11:07:07 -0400466 BOOT_LOG_INF("Swap type: %s",
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300467 table->swap_type == BOOT_SWAP_TYPE_TEST ? "test" :
468 table->swap_type == BOOT_SWAP_TYPE_PERM ? "perm" :
469 table->swap_type == BOOT_SWAP_TYPE_REVERT ? "revert" :
470 "BUG; can't happen");
471 assert(table->swap_type == BOOT_SWAP_TYPE_TEST ||
472 table->swap_type == BOOT_SWAP_TYPE_PERM ||
473 table->swap_type == BOOT_SWAP_TYPE_REVERT);
474 return table->swap_type;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800475 }
476 }
477
Fabio Utzigb5b2f552017-06-30 10:03:47 -0300478 BOOT_LOG_INF("Swap type: none");
Christopher Collins92ea77f2016-12-12 15:59:26 -0800479 return BOOT_SWAP_TYPE_NONE;
480}
481
482/**
483 * Marks the image in slot 1 as pending. On the next reboot, the system will
484 * perform a one-time boot of the slot 1 image.
485 *
Christopher Collins7835c1e2016-12-21 10:10:51 -0800486 * @param permanent Whether the image should be used permanently or
487 * only tested once:
488 * 0=run image once, then confirm or revert.
489 * 1=run image forever.
490 *
Christopher Collins92ea77f2016-12-12 15:59:26 -0800491 * @return 0 on success; nonzero on failure.
492 */
493int
Christopher Collins7835c1e2016-12-21 10:10:51 -0800494boot_set_pending(int permanent)
Christopher Collins92ea77f2016-12-12 15:59:26 -0800495{
496 const struct flash_area *fap;
497 struct boot_swap_state state_slot1;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800498 int rc;
499
Fabio Utzig2473ac02017-05-02 12:45:02 -0300500 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_1, &state_slot1);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800501 if (rc != 0) {
502 return rc;
503 }
504
505 switch (state_slot1.magic) {
506 case BOOT_MAGIC_GOOD:
507 /* Swap already scheduled. */
508 return 0;
509
510 case BOOT_MAGIC_UNSET:
Fabio Utzig2473ac02017-05-02 12:45:02 -0300511 rc = flash_area_open(FLASH_AREA_IMAGE_1, &fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800512 if (rc != 0) {
513 rc = BOOT_EFLASH;
514 } else {
515 rc = boot_write_magic(fap);
516 }
517
Christopher Collins7835c1e2016-12-21 10:10:51 -0800518 if (rc == 0 && permanent) {
519 rc = boot_write_image_ok(fap);
520 }
521
Christopher Collins92ea77f2016-12-12 15:59:26 -0800522 flash_area_close(fap);
523 return rc;
524
525 default:
526 /* XXX: Temporary assert. */
527 assert(0);
528 return -1;
529 }
530}
531
532/**
533 * 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.
534 *
535 * @return 0 on success; nonzero on failure.
536 */
537int
538boot_set_confirmed(void)
539{
540 const struct flash_area *fap;
541 struct boot_swap_state state_slot0;
Fabio Utzig39000012018-07-30 12:40:20 -0300542 uint8_t erased_val;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800543 int rc;
544
Fabio Utzig2473ac02017-05-02 12:45:02 -0300545 rc = boot_read_swap_state_by_id(FLASH_AREA_IMAGE_0, &state_slot0);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800546 if (rc != 0) {
547 return rc;
548 }
549
550 switch (state_slot0.magic) {
551 case BOOT_MAGIC_GOOD:
552 /* Confirm needed; proceed. */
553 break;
554
555 case BOOT_MAGIC_UNSET:
556 /* Already confirmed. */
557 return 0;
558
559 case BOOT_MAGIC_BAD:
560 /* Unexpected state. */
561 return BOOT_EBADVECT;
562 }
563
Christopher Collins92ea77f2016-12-12 15:59:26 -0800564 rc = flash_area_open(FLASH_AREA_IMAGE_0, &fap);
565 if (rc) {
566 rc = BOOT_EFLASH;
567 goto done;
568 }
569
Fabio Utzig39000012018-07-30 12:40:20 -0300570 erased_val = flash_area_erased_val(fap);
571 if (state_slot0.copy_done == erased_val) {
572 /* Swap never completed. This is unexpected. */
573 rc = BOOT_EBADVECT;
Christopher Collins92ea77f2016-12-12 15:59:26 -0800574 goto done;
575 }
576
Ɓukasz Rymanowskia1927f42018-09-26 15:31:50 +0200577 if (state_slot0.image_ok != BOOT_FLAG_UNSET) {
Fabio Utzig39000012018-07-30 12:40:20 -0300578 /* Already confirmed. */
579 goto done;
580 }
581
582 rc = boot_write_image_ok(fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800583
584done:
585 flash_area_close(fap);
586 return rc;
587}