blob: 5d70e0cf4cad200f40ddea4bfd071b341554985e [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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
101 * | Swap type | 0xff padding (7 octets) |
102 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
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. */
Tamas Banf70ef8c2017-12-19 15:35:09 +0000119};
120
David Vincze39e78552018-10-10 17:10:01 +0200121/*
122 * The current flashmap API does not check the amount of space allocated when
123 * loading sector data from the flash device, allowing for smaller counts here
124 * would most surely incur in overruns.
125 *
126 * TODO: make flashmap API receive the current sector array size.
127 */
128#if BOOT_MAX_IMG_SECTORS < 32
129#error "Too few sectors, please increase BOOT_MAX_IMG_SECTORS to at least 32"
130#endif
131
132/** Number of image slots in flash; currently limited to two. */
David Vincze8bdfc2d2019-03-18 15:49:23 +0100133#define BOOT_NUM_SLOTS 2
David Vincze39e78552018-10-10 17:10:01 +0200134
135/** Maximum number of image sectors supported by the bootloader. */
David Vincze8bdfc2d2019-03-18 15:49:23 +0100136#define BOOT_STATUS_STATE_COUNT 3
Tamas Banf70ef8c2017-12-19 15:35:09 +0000137
David Vincze8bdfc2d2019-03-18 15:49:23 +0100138#define BOOT_PRIMARY_SLOT 0
139#define BOOT_SECONDARY_SLOT 1
Tamas Banf70ef8c2017-12-19 15:35:09 +0000140
David Vincze8bdfc2d2019-03-18 15:49:23 +0100141#define BOOT_STATUS_SOURCE_NONE 0
142#define BOOT_STATUS_SOURCE_SCRATCH 1
143#define BOOT_STATUS_SOURCE_PRIMARY_SLOT 2
144
Tamas Banf70ef8c2017-12-19 15:35:09 +0000145extern const uint32_t BOOT_MAGIC_SZ;
146
Tamas Banf70ef8c2017-12-19 15:35:09 +0000147/**
148 * Compatibility shim for flash sector type.
149 *
150 * This can be deleted when flash_area_to_sectors() is removed.
151 */
152#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
153typedef struct flash_sector boot_sector_t;
154#else
155typedef struct flash_area boot_sector_t;
156#endif
157
158/** Private state maintained during boot. */
159struct boot_loader_state {
160 struct {
161 struct image_header hdr;
162 const struct flash_area *area;
163 boot_sector_t *sectors;
164 size_t num_sectors;
165 } imgs[BOOT_NUM_SLOTS];
166
David Vincze401c7422019-06-21 20:44:05 +0200167 struct {
168 const struct flash_area *area;
169 boot_sector_t *sectors;
170 size_t num_sectors;
171 } scratch;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000172
173 uint8_t write_sz;
174};
175
David Vincze39e78552018-10-10 17:10:01 +0200176int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
177 size_t slen, uint8_t key_id);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000178
David Vincze401c7422019-06-21 20:44:05 +0200179int boot_magic_compatible_check(uint8_t tbl_val, uint8_t val);
180uint32_t boot_trailer_sz(uint8_t min_write_sz);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000181int boot_status_entries(const struct flash_area *fap);
182uint32_t boot_status_off(const struct flash_area *fap);
David Vincze401c7422019-06-21 20:44:05 +0200183uint32_t boot_swap_type_off(const struct flash_area *fap);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000184int boot_read_swap_state(const struct flash_area *fap,
185 struct boot_swap_state *state);
186int boot_read_swap_state_by_id(int flash_area_id,
187 struct boot_swap_state *state);
188int boot_write_magic(const struct flash_area *fap);
189int boot_write_status(struct boot_status *bs);
190int boot_schedule_test_swap(void);
191int boot_write_copy_done(const struct flash_area *fap);
192int boot_write_image_ok(const struct flash_area *fap);
David Vincze401c7422019-06-21 20:44:05 +0200193int boot_write_swap_type(const struct flash_area *fap, uint8_t swap_type);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000194int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
195int boot_read_swap_size(uint32_t *swap_size);
196
197/*
198 * Accessors for the contents of struct boot_loader_state.
199 */
200
201/* These are macros so they can be used as lvalues. */
202#define BOOT_IMG_AREA(state, slot) ((state)->imgs[(slot)].area)
David Vincze401c7422019-06-21 20:44:05 +0200203#define BOOT_SCRATCH_AREA(state) ((state)->scratch.area)
Tamas Banf70ef8c2017-12-19 15:35:09 +0000204#define BOOT_WRITE_SZ(state) ((state)->write_sz)
205
206static inline struct image_header*
207boot_img_hdr(struct boot_loader_state *state, size_t slot)
208{
209 return &state->imgs[slot].hdr;
210}
211
Tamas Banf70ef8c2017-12-19 15:35:09 +0000212static inline size_t
213boot_img_num_sectors(struct boot_loader_state *state, size_t slot)
214{
215 return state->imgs[slot].num_sectors;
216}
217
David Vincze401c7422019-06-21 20:44:05 +0200218static inline size_t
219boot_scratch_num_sectors(struct boot_loader_state *state)
220{
221 return state->scratch.num_sectors;
222}
223
Tamas Banf70ef8c2017-12-19 15:35:09 +0000224/*
225 * Offset of the slot from the beginning of the flash device.
226 */
227static inline uint32_t
228boot_img_slot_off(struct boot_loader_state *state, size_t slot)
229{
230 return state->imgs[slot].area->fa_off;
231}
232
233static inline size_t boot_scratch_area_size(struct boot_loader_state *state)
234{
David Vincze401c7422019-06-21 20:44:05 +0200235 return BOOT_SCRATCH_AREA(state)->fa_size;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000236}
237
238#ifndef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
239
240static inline size_t
241boot_img_sector_size(struct boot_loader_state *state,
242 size_t slot, size_t sector)
243{
244 return state->imgs[slot].sectors[sector].fa_size;
245}
246
247/*
248 * Offset of the sector from the beginning of the image, NOT the flash
249 * device.
250 */
251static inline uint32_t
252boot_img_sector_off(struct boot_loader_state *state, size_t slot,
253 size_t sector)
254{
255 return state->imgs[slot].sectors[sector].fa_off -
256 state->imgs[slot].sectors[0].fa_off;
257}
258
259static inline int
260boot_initialize_area(struct boot_loader_state *state, int flash_area)
261{
262 int num_sectors = BOOT_MAX_IMG_SECTORS;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000263 int rc;
264
265 switch (flash_area) {
David Vincze8bdfc2d2019-03-18 15:49:23 +0100266 case FLASH_AREA_IMAGE_PRIMARY:
David Vincze401c7422019-06-21 20:44:05 +0200267 rc = flash_area_to_sectors(flash_area, &num_sectors,
268 state->imgs[BOOT_PRIMARY_SLOT].sectors);
269 state->imgs[BOOT_PRIMARY_SLOT].num_sectors = (size_t)num_sectors;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000270 break;
David Vincze8bdfc2d2019-03-18 15:49:23 +0100271 case FLASH_AREA_IMAGE_SECONDARY:
David Vincze401c7422019-06-21 20:44:05 +0200272 rc = flash_area_to_sectors(flash_area, &num_sectors,
273 state->imgs[BOOT_SECONDARY_SLOT].sectors);
274 state->imgs[BOOT_SECONDARY_SLOT].num_sectors = (size_t)num_sectors;
275 break;
276 case FLASH_AREA_IMAGE_SCRATCH:
277 rc = flash_area_to_sectors(flash_area, &num_sectors,
278 state->scratch.sectors);
279 state->scratch.num_sectors = (size_t)num_sectors;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000280 break;
281 default:
282 return BOOT_EFLASH;
283 }
284
David Vincze401c7422019-06-21 20:44:05 +0200285 return rc;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000286}
287
288#else /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
289
290static inline size_t
291boot_img_sector_size(struct boot_loader_state *state,
292 size_t slot, size_t sector)
293{
294 return state->imgs[slot].sectors[sector].fs_size;
295}
296
297static inline uint32_t
298boot_img_sector_off(struct boot_loader_state *state, size_t slot,
299 size_t sector)
300{
301 return state->imgs[slot].sectors[sector].fs_off -
302 state->imgs[slot].sectors[0].fs_off;
303}
304
305static inline int
306boot_initialize_area(struct boot_loader_state *state, int flash_area)
307{
308 uint32_t num_sectors;
309 struct flash_sector *out_sectors;
310 size_t *out_num_sectors;
311 int rc;
312
313 switch (flash_area) {
David Vincze8bdfc2d2019-03-18 15:49:23 +0100314 case FLASH_AREA_IMAGE_PRIMARY:
Tamas Banf70ef8c2017-12-19 15:35:09 +0000315 num_sectors = BOOT_MAX_IMG_SECTORS;
David Vincze8bdfc2d2019-03-18 15:49:23 +0100316 out_sectors = state->imgs[BOOT_PRIMARY_SLOT].sectors;
317 out_num_sectors = &state->imgs[BOOT_PRIMARY_SLOT].num_sectors;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000318 break;
David Vincze8bdfc2d2019-03-18 15:49:23 +0100319 case FLASH_AREA_IMAGE_SECONDARY:
Tamas Banf70ef8c2017-12-19 15:35:09 +0000320 num_sectors = BOOT_MAX_IMG_SECTORS;
David Vincze8bdfc2d2019-03-18 15:49:23 +0100321 out_sectors = state->imgs[BOOT_SECONDARY_SLOT].sectors;
322 out_num_sectors = &state->imgs[BOOT_SECONDARY_SLOT].num_sectors;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000323 break;
David Vincze401c7422019-06-21 20:44:05 +0200324 case FLASH_AREA_IMAGE_SCRATCH:
325 num_sectors = BOOT_MAX_IMG_SECTORS;
326 out_sectors = state->scratch.sectors;
327 out_num_sectors = &state->scratch.num_sectors;
328 break;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000329 default:
330 return -1;
331 }
332
333 rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
334 if (rc != 0) {
335 return rc;
336 }
337 *out_num_sectors = num_sectors;
338 return 0;
339}
340
341#endif /* !defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
342
343#ifdef __cplusplus
344}
345#endif
346
347#endif