blob: 9ea1a242e5b6f6476209f31fcc8b82a49ca2430f [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
David Vincze39e78552018-10-10 17:10:01 +020020/*
21 * Original code taken from mcuboot project at:
22 * https://github.com/JuulLabs-OSS/mcuboot
David Vincze401c7422019-06-21 20:44:05 +020023 * Git SHA of the original version: 3c469bc698a9767859ed73cd0201c44161204d5c
David Vincze39e78552018-10-10 17:10:01 +020024 * Modifications are Copyright (c) 2018-2019 Arm Limited.
25 */
26
Tamas Banf70ef8c2017-12-19 15:35:09 +000027#ifndef H_BOOTUTIL_PRIV_
28#define H_BOOTUTIL_PRIV_
29
Tamas Banf70ef8c2017-12-19 15:35:09 +000030#include "flash_map/flash_map.h"
David Vincze401c7422019-06-21 20:44:05 +020031#include "bootutil/bootutil.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000032#include "bootutil/image.h"
Mate Toth-Pala76e2ab2018-05-31 15:43:01 +020033#include "flash_layout.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000034
35#ifdef __cplusplus
36extern "C" {
37#endif
38
David Vincze401c7422019-06-21 20:44:05 +020039#ifdef MCUBOOT_HAVE_ASSERT_H
40#include "mcuboot_config/mcuboot_assert.h"
41#else
42#define ASSERT assert
43#endif
44
Tamas Banf70ef8c2017-12-19 15:35:09 +000045struct flash_area;
46
47#define BOOT_EFLASH 1
48#define BOOT_EFILE 2
49#define BOOT_EBADIMAGE 3
50#define BOOT_EBADVECT 4
51#define BOOT_EBADSTATUS 5
52#define BOOT_ENOMEM 6
53#define BOOT_EBADARGS 7
David Vincze060968d2019-05-23 01:13:14 +020054#define BOOT_EBADMAGIC 8
Tamas Banf70ef8c2017-12-19 15:35:09 +000055
56#define BOOT_TMPBUF_SZ 256
57
58/*
59 * Maintain state of copy progress.
60 */
61struct boot_status {
62 uint32_t idx; /* Which area we're operating on */
63 uint8_t state; /* Which part of the swapping process are we at */
64 uint8_t use_scratch; /* Are status bytes ever written to scratch? */
David Vincze401c7422019-06-21 20:44:05 +020065 uint8_t swap_type; /* The type of swap in effect */
Tamas Banf70ef8c2017-12-19 15:35:09 +000066 uint32_t swap_size; /* Total size of swapped image */
67};
68
David Vincze39e78552018-10-10 17:10:01 +020069#define BOOT_MAGIC_GOOD 1
70#define BOOT_MAGIC_BAD 2
71#define BOOT_MAGIC_UNSET 3
72#define BOOT_MAGIC_ANY 4 /* NOTE: control only, not dependent on sector */
David Vincze401c7422019-06-21 20:44:05 +020073#define BOOT_MAGIC_NOTGOOD 5 /* NOTE: control only, not dependent on sector */
David Vincze39e78552018-10-10 17:10:01 +020074
75/*
76 * NOTE: leave BOOT_FLAG_SET equal to one, this is written to flash!
77 */
78#define BOOT_FLAG_SET 1
79#define BOOT_FLAG_BAD 2
80#define BOOT_FLAG_UNSET 3
81#define BOOT_FLAG_ANY 4 /* NOTE: control only, not dependent on sector */
82
83#define BOOT_STATUS_IDX_0 1
84
85#define BOOT_STATUS_STATE_0 1
86#define BOOT_STATUS_STATE_1 2
87#define BOOT_STATUS_STATE_2 3
Tamas Banf70ef8c2017-12-19 15:35:09 +000088
89/**
90 * End-of-image slot structure.
91 *
David Vincze401c7422019-06-21 20:44:05 +020092 * 0 1 2 3
93 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
94 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
95 * ~ ~
96 * ~ Swap status (BOOT_MAX_IMG_SECTORS * min-write-size * 3) ~
97 * ~ ~
98 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 * | Swap size (4 octets) |
100 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
David Vincze91b71ef2019-06-24 13:06:47 +0200101 * | Swap info | 0xff padding (7 octets) |
David Vincze401c7422019-06-21 20:44:05 +0200102 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
103 * | Copy done | 0xff padding (7 octets) |
104 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
105 * | Image OK | 0xff padding (7 octets) |
106 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
107 * | MAGIC (16 octets) |
108 * | |
109 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Tamas Banf70ef8c2017-12-19 15:35:09 +0000110 */
111
112extern const uint32_t boot_img_magic[4];
113
114struct boot_swap_state {
David Vincze401c7422019-06-21 20:44:05 +0200115 uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */
116 uint8_t swap_type; /* One of the BOOT_SWAP_TYPE_[...] values. */
117 uint8_t copy_done; /* One of the BOOT_FLAG_[...] values. */
118 uint8_t image_ok; /* One of the BOOT_FLAG_[...] values. */
David Vincze91b71ef2019-06-24 13:06:47 +0200119 uint8_t image_num; /* Boot status belongs to this image */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000120};
121
David Vinczebb207982019-08-21 15:13:04 +0200122#ifdef MCUBOOT_IMAGE_NUMBER
123#define BOOT_IMAGE_NUMBER MCUBOOT_IMAGE_NUMBER
124#else
125#define BOOT_IMAGE_NUMBER 1
126#endif
127
David Vincze39e78552018-10-10 17:10:01 +0200128/*
David Vincze91b71ef2019-06-24 13:06:47 +0200129 * Extract the swap type and image number from image trailers's swap_info
130 * field.
131 */
132#define SWAP_INFO_SWAP_TYPE_MASK (0x0Fu)
133#define SWAP_INFO_SWAP_TYPE_POS (0)
134#define SWAP_INFO_IMAGE_NUM_MASK (0xF0u)
135#define SWAP_INFO_IMAGE_NUM_POS (4)
136
137#define BOOT_GET_SWAP_TYPE(swap_info) ((swap_info) & SWAP_INFO_SWAP_TYPE_MASK)
138#define BOOT_GET_IMAGE_NUM(swap_info) ((swap_info) >> SWAP_INFO_IMAGE_NUM_POS)
139
140/* Construct the swap_info field from swap type and image number */
141#define BOOT_SET_SWAP_INFO(swap_info, image, type) { \
142 assert(((image) & (SWAP_INFO_IMAGE_NUM_MASK >> \
143 SWAP_INFO_IMAGE_NUM_POS)) == (image)); \
144 assert(((type) & SWAP_INFO_SWAP_TYPE_MASK) == (type)); \
145 (swap_info) = (image) << SWAP_INFO_IMAGE_NUM_POS \
146 | (type); \
147 }
148
149/*
David Vincze39e78552018-10-10 17:10:01 +0200150 * The current flashmap API does not check the amount of space allocated when
151 * loading sector data from the flash device, allowing for smaller counts here
152 * would most surely incur in overruns.
153 *
154 * TODO: make flashmap API receive the current sector array size.
155 */
156#if BOOT_MAX_IMG_SECTORS < 32
157#error "Too few sectors, please increase BOOT_MAX_IMG_SECTORS to at least 32"
158#endif
159
160/** Number of image slots in flash; currently limited to two. */
David Vincze8bdfc2d2019-03-18 15:49:23 +0100161#define BOOT_NUM_SLOTS 2
David Vincze39e78552018-10-10 17:10:01 +0200162
163/** Maximum number of image sectors supported by the bootloader. */
David Vincze8bdfc2d2019-03-18 15:49:23 +0100164#define BOOT_STATUS_STATE_COUNT 3
Tamas Banf70ef8c2017-12-19 15:35:09 +0000165
David Vincze8bdfc2d2019-03-18 15:49:23 +0100166#define BOOT_PRIMARY_SLOT 0
167#define BOOT_SECONDARY_SLOT 1
Tamas Banf70ef8c2017-12-19 15:35:09 +0000168
David Vincze8bdfc2d2019-03-18 15:49:23 +0100169#define BOOT_STATUS_SOURCE_NONE 0
170#define BOOT_STATUS_SOURCE_SCRATCH 1
171#define BOOT_STATUS_SOURCE_PRIMARY_SLOT 2
172
Tamas Banf70ef8c2017-12-19 15:35:09 +0000173extern const uint32_t BOOT_MAGIC_SZ;
174
Tamas Banf70ef8c2017-12-19 15:35:09 +0000175/**
176 * Compatibility shim for flash sector type.
177 *
178 * This can be deleted when flash_area_to_sectors() is removed.
179 */
180#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
181typedef struct flash_sector boot_sector_t;
182#else
183typedef struct flash_area boot_sector_t;
184#endif
185
186/** Private state maintained during boot. */
187struct boot_loader_state {
188 struct {
189 struct image_header hdr;
190 const struct flash_area *area;
191 boot_sector_t *sectors;
192 size_t num_sectors;
193 } imgs[BOOT_NUM_SLOTS];
194
David Vincze401c7422019-06-21 20:44:05 +0200195 struct {
196 const struct flash_area *area;
197 boot_sector_t *sectors;
198 size_t num_sectors;
199 } scratch;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000200
201 uint8_t write_sz;
202};
203
David Vincze39e78552018-10-10 17:10:01 +0200204int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
205 size_t slen, uint8_t key_id);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000206
David Vincze401c7422019-06-21 20:44:05 +0200207int boot_magic_compatible_check(uint8_t tbl_val, uint8_t val);
208uint32_t boot_trailer_sz(uint8_t min_write_sz);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000209int boot_status_entries(const struct flash_area *fap);
210uint32_t boot_status_off(const struct flash_area *fap);
David Vincze91b71ef2019-06-24 13:06:47 +0200211uint32_t boot_swap_info_off(const struct flash_area *fap);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000212int boot_read_swap_state(const struct flash_area *fap,
213 struct boot_swap_state *state);
214int boot_read_swap_state_by_id(int flash_area_id,
215 struct boot_swap_state *state);
216int boot_write_magic(const struct flash_area *fap);
217int boot_write_status(struct boot_status *bs);
218int boot_schedule_test_swap(void);
219int boot_write_copy_done(const struct flash_area *fap);
220int boot_write_image_ok(const struct flash_area *fap);
David Vincze91b71ef2019-06-24 13:06:47 +0200221int boot_write_swap_info(const struct flash_area *fap, uint8_t swap_type,
222 uint8_t image_num);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000223int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
224int boot_read_swap_size(uint32_t *swap_size);
225
226/*
227 * Accessors for the contents of struct boot_loader_state.
228 */
229
230/* These are macros so they can be used as lvalues. */
231#define BOOT_IMG_AREA(state, slot) ((state)->imgs[(slot)].area)
David Vincze401c7422019-06-21 20:44:05 +0200232#define BOOT_SCRATCH_AREA(state) ((state)->scratch.area)
Tamas Banf70ef8c2017-12-19 15:35:09 +0000233#define BOOT_WRITE_SZ(state) ((state)->write_sz)
234
235static inline struct image_header*
236boot_img_hdr(struct boot_loader_state *state, size_t slot)
237{
238 return &state->imgs[slot].hdr;
239}
240
Tamas Banf70ef8c2017-12-19 15:35:09 +0000241static inline size_t
242boot_img_num_sectors(struct boot_loader_state *state, size_t slot)
243{
244 return state->imgs[slot].num_sectors;
245}
246
David Vincze401c7422019-06-21 20:44:05 +0200247static inline size_t
248boot_scratch_num_sectors(struct boot_loader_state *state)
249{
250 return state->scratch.num_sectors;
251}
252
Tamas Banf70ef8c2017-12-19 15:35:09 +0000253/*
254 * Offset of the slot from the beginning of the flash device.
255 */
256static inline uint32_t
257boot_img_slot_off(struct boot_loader_state *state, size_t slot)
258{
259 return state->imgs[slot].area->fa_off;
260}
261
262static inline size_t boot_scratch_area_size(struct boot_loader_state *state)
263{
David Vincze401c7422019-06-21 20:44:05 +0200264 return BOOT_SCRATCH_AREA(state)->fa_size;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000265}
266
267#ifndef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
268
269static inline size_t
270boot_img_sector_size(struct boot_loader_state *state,
271 size_t slot, size_t sector)
272{
273 return state->imgs[slot].sectors[sector].fa_size;
274}
275
276/*
277 * Offset of the sector from the beginning of the image, NOT the flash
278 * device.
279 */
280static inline uint32_t
281boot_img_sector_off(struct boot_loader_state *state, size_t slot,
282 size_t sector)
283{
284 return state->imgs[slot].sectors[sector].fa_off -
285 state->imgs[slot].sectors[0].fa_off;
286}
287
288static inline int
289boot_initialize_area(struct boot_loader_state *state, int flash_area)
290{
291 int num_sectors = BOOT_MAX_IMG_SECTORS;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000292 int rc;
293
David Vinczebb207982019-08-21 15:13:04 +0200294 if (flash_area == FLASH_AREA_IMAGE_PRIMARY) {
David Vincze401c7422019-06-21 20:44:05 +0200295 rc = flash_area_to_sectors(flash_area, &num_sectors,
296 state->imgs[BOOT_PRIMARY_SLOT].sectors);
297 state->imgs[BOOT_PRIMARY_SLOT].num_sectors = (size_t)num_sectors;
David Vinczebb207982019-08-21 15:13:04 +0200298 } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY) {
David Vincze401c7422019-06-21 20:44:05 +0200299 rc = flash_area_to_sectors(flash_area, &num_sectors,
300 state->imgs[BOOT_SECONDARY_SLOT].sectors);
301 state->imgs[BOOT_SECONDARY_SLOT].num_sectors = (size_t)num_sectors;
David Vinczebb207982019-08-21 15:13:04 +0200302 } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
David Vincze401c7422019-06-21 20:44:05 +0200303 rc = flash_area_to_sectors(flash_area, &num_sectors,
304 state->scratch.sectors);
305 state->scratch.num_sectors = (size_t)num_sectors;
David Vinczebb207982019-08-21 15:13:04 +0200306 } else {
Tamas Banf70ef8c2017-12-19 15:35:09 +0000307 return BOOT_EFLASH;
308 }
309
David Vincze401c7422019-06-21 20:44:05 +0200310 return rc;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000311}
312
313#else /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
314
315static inline size_t
316boot_img_sector_size(struct boot_loader_state *state,
317 size_t slot, size_t sector)
318{
319 return state->imgs[slot].sectors[sector].fs_size;
320}
321
322static inline uint32_t
323boot_img_sector_off(struct boot_loader_state *state, size_t slot,
324 size_t sector)
325{
326 return state->imgs[slot].sectors[sector].fs_off -
327 state->imgs[slot].sectors[0].fs_off;
328}
329
330static inline int
331boot_initialize_area(struct boot_loader_state *state, int flash_area)
332{
333 uint32_t num_sectors;
334 struct flash_sector *out_sectors;
335 size_t *out_num_sectors;
336 int rc;
337
David Vinczebb207982019-08-21 15:13:04 +0200338 num_sectors = BOOT_MAX_IMG_SECTORS;
339
340 if (flash_area == FLASH_AREA_IMAGE_PRIMARY) {
David Vincze8bdfc2d2019-03-18 15:49:23 +0100341 out_sectors = state->imgs[BOOT_PRIMARY_SLOT].sectors;
342 out_num_sectors = &state->imgs[BOOT_PRIMARY_SLOT].num_sectors;
David Vinczebb207982019-08-21 15:13:04 +0200343 } else if (flash_area == FLASH_AREA_IMAGE_SECONDARY) {
David Vincze8bdfc2d2019-03-18 15:49:23 +0100344 out_sectors = state->imgs[BOOT_SECONDARY_SLOT].sectors;
345 out_num_sectors = &state->imgs[BOOT_SECONDARY_SLOT].num_sectors;
David Vinczebb207982019-08-21 15:13:04 +0200346 } else if (flash_area == FLASH_AREA_IMAGE_SCRATCH) {
David Vincze401c7422019-06-21 20:44:05 +0200347 out_sectors = state->scratch.sectors;
348 out_num_sectors = &state->scratch.num_sectors;
David Vinczebb207982019-08-21 15:13:04 +0200349 } else {
350 return BOOT_EFLASH;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000351 }
352
353 rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
354 if (rc != 0) {
355 return rc;
356 }
357 *out_num_sectors = num_sectors;
358 return 0;
359}
360
361#endif /* !defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
362
363#ifdef __cplusplus
364}
365#endif
366
367#endif