blob: 5a38dac02519abead08adeb5e8c8ac5233b741a7 [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 Vincze39e78552018-10-10 17:10:01 +0200122/*
David Vincze91b71ef2019-06-24 13:06:47 +0200123 * Extract the swap type and image number from image trailers's swap_info
124 * field.
125 */
126#define SWAP_INFO_SWAP_TYPE_MASK (0x0Fu)
127#define SWAP_INFO_SWAP_TYPE_POS (0)
128#define SWAP_INFO_IMAGE_NUM_MASK (0xF0u)
129#define SWAP_INFO_IMAGE_NUM_POS (4)
130
131#define BOOT_GET_SWAP_TYPE(swap_info) ((swap_info) & SWAP_INFO_SWAP_TYPE_MASK)
132#define BOOT_GET_IMAGE_NUM(swap_info) ((swap_info) >> SWAP_INFO_IMAGE_NUM_POS)
133
134/* Construct the swap_info field from swap type and image number */
135#define BOOT_SET_SWAP_INFO(swap_info, image, type) { \
136 assert(((image) & (SWAP_INFO_IMAGE_NUM_MASK >> \
137 SWAP_INFO_IMAGE_NUM_POS)) == (image)); \
138 assert(((type) & SWAP_INFO_SWAP_TYPE_MASK) == (type)); \
139 (swap_info) = (image) << SWAP_INFO_IMAGE_NUM_POS \
140 | (type); \
141 }
142
143/*
David Vincze39e78552018-10-10 17:10:01 +0200144 * The current flashmap API does not check the amount of space allocated when
145 * loading sector data from the flash device, allowing for smaller counts here
146 * would most surely incur in overruns.
147 *
148 * TODO: make flashmap API receive the current sector array size.
149 */
150#if BOOT_MAX_IMG_SECTORS < 32
151#error "Too few sectors, please increase BOOT_MAX_IMG_SECTORS to at least 32"
152#endif
153
154/** Number of image slots in flash; currently limited to two. */
David Vincze8bdfc2d2019-03-18 15:49:23 +0100155#define BOOT_NUM_SLOTS 2
David Vincze39e78552018-10-10 17:10:01 +0200156
157/** Maximum number of image sectors supported by the bootloader. */
David Vincze8bdfc2d2019-03-18 15:49:23 +0100158#define BOOT_STATUS_STATE_COUNT 3
Tamas Banf70ef8c2017-12-19 15:35:09 +0000159
David Vincze8bdfc2d2019-03-18 15:49:23 +0100160#define BOOT_PRIMARY_SLOT 0
161#define BOOT_SECONDARY_SLOT 1
Tamas Banf70ef8c2017-12-19 15:35:09 +0000162
David Vincze8bdfc2d2019-03-18 15:49:23 +0100163#define BOOT_STATUS_SOURCE_NONE 0
164#define BOOT_STATUS_SOURCE_SCRATCH 1
165#define BOOT_STATUS_SOURCE_PRIMARY_SLOT 2
166
Tamas Banf70ef8c2017-12-19 15:35:09 +0000167extern const uint32_t BOOT_MAGIC_SZ;
168
Tamas Banf70ef8c2017-12-19 15:35:09 +0000169/**
170 * Compatibility shim for flash sector type.
171 *
172 * This can be deleted when flash_area_to_sectors() is removed.
173 */
174#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
175typedef struct flash_sector boot_sector_t;
176#else
177typedef struct flash_area boot_sector_t;
178#endif
179
180/** Private state maintained during boot. */
181struct boot_loader_state {
182 struct {
183 struct image_header hdr;
184 const struct flash_area *area;
185 boot_sector_t *sectors;
186 size_t num_sectors;
187 } imgs[BOOT_NUM_SLOTS];
188
David Vincze401c7422019-06-21 20:44:05 +0200189 struct {
190 const struct flash_area *area;
191 boot_sector_t *sectors;
192 size_t num_sectors;
193 } scratch;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000194
195 uint8_t write_sz;
196};
197
David Vincze39e78552018-10-10 17:10:01 +0200198int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
199 size_t slen, uint8_t key_id);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000200
David Vincze401c7422019-06-21 20:44:05 +0200201int boot_magic_compatible_check(uint8_t tbl_val, uint8_t val);
202uint32_t boot_trailer_sz(uint8_t min_write_sz);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000203int boot_status_entries(const struct flash_area *fap);
204uint32_t boot_status_off(const struct flash_area *fap);
David Vincze91b71ef2019-06-24 13:06:47 +0200205uint32_t boot_swap_info_off(const struct flash_area *fap);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000206int boot_read_swap_state(const struct flash_area *fap,
207 struct boot_swap_state *state);
208int boot_read_swap_state_by_id(int flash_area_id,
209 struct boot_swap_state *state);
210int boot_write_magic(const struct flash_area *fap);
211int boot_write_status(struct boot_status *bs);
212int boot_schedule_test_swap(void);
213int boot_write_copy_done(const struct flash_area *fap);
214int boot_write_image_ok(const struct flash_area *fap);
David Vincze91b71ef2019-06-24 13:06:47 +0200215int boot_write_swap_info(const struct flash_area *fap, uint8_t swap_type,
216 uint8_t image_num);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000217int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
218int boot_read_swap_size(uint32_t *swap_size);
219
220/*
221 * Accessors for the contents of struct boot_loader_state.
222 */
223
224/* These are macros so they can be used as lvalues. */
225#define BOOT_IMG_AREA(state, slot) ((state)->imgs[(slot)].area)
David Vincze401c7422019-06-21 20:44:05 +0200226#define BOOT_SCRATCH_AREA(state) ((state)->scratch.area)
Tamas Banf70ef8c2017-12-19 15:35:09 +0000227#define BOOT_WRITE_SZ(state) ((state)->write_sz)
228
229static inline struct image_header*
230boot_img_hdr(struct boot_loader_state *state, size_t slot)
231{
232 return &state->imgs[slot].hdr;
233}
234
Tamas Banf70ef8c2017-12-19 15:35:09 +0000235static inline size_t
236boot_img_num_sectors(struct boot_loader_state *state, size_t slot)
237{
238 return state->imgs[slot].num_sectors;
239}
240
David Vincze401c7422019-06-21 20:44:05 +0200241static inline size_t
242boot_scratch_num_sectors(struct boot_loader_state *state)
243{
244 return state->scratch.num_sectors;
245}
246
Tamas Banf70ef8c2017-12-19 15:35:09 +0000247/*
248 * Offset of the slot from the beginning of the flash device.
249 */
250static inline uint32_t
251boot_img_slot_off(struct boot_loader_state *state, size_t slot)
252{
253 return state->imgs[slot].area->fa_off;
254}
255
256static inline size_t boot_scratch_area_size(struct boot_loader_state *state)
257{
David Vincze401c7422019-06-21 20:44:05 +0200258 return BOOT_SCRATCH_AREA(state)->fa_size;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000259}
260
261#ifndef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
262
263static inline size_t
264boot_img_sector_size(struct boot_loader_state *state,
265 size_t slot, size_t sector)
266{
267 return state->imgs[slot].sectors[sector].fa_size;
268}
269
270/*
271 * Offset of the sector from the beginning of the image, NOT the flash
272 * device.
273 */
274static inline uint32_t
275boot_img_sector_off(struct boot_loader_state *state, size_t slot,
276 size_t sector)
277{
278 return state->imgs[slot].sectors[sector].fa_off -
279 state->imgs[slot].sectors[0].fa_off;
280}
281
282static inline int
283boot_initialize_area(struct boot_loader_state *state, int flash_area)
284{
285 int num_sectors = BOOT_MAX_IMG_SECTORS;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000286 int rc;
287
288 switch (flash_area) {
David Vincze8bdfc2d2019-03-18 15:49:23 +0100289 case FLASH_AREA_IMAGE_PRIMARY:
David Vincze401c7422019-06-21 20:44:05 +0200290 rc = flash_area_to_sectors(flash_area, &num_sectors,
291 state->imgs[BOOT_PRIMARY_SLOT].sectors);
292 state->imgs[BOOT_PRIMARY_SLOT].num_sectors = (size_t)num_sectors;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000293 break;
David Vincze8bdfc2d2019-03-18 15:49:23 +0100294 case FLASH_AREA_IMAGE_SECONDARY:
David Vincze401c7422019-06-21 20:44:05 +0200295 rc = flash_area_to_sectors(flash_area, &num_sectors,
296 state->imgs[BOOT_SECONDARY_SLOT].sectors);
297 state->imgs[BOOT_SECONDARY_SLOT].num_sectors = (size_t)num_sectors;
298 break;
299 case FLASH_AREA_IMAGE_SCRATCH:
300 rc = flash_area_to_sectors(flash_area, &num_sectors,
301 state->scratch.sectors);
302 state->scratch.num_sectors = (size_t)num_sectors;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000303 break;
304 default:
305 return BOOT_EFLASH;
306 }
307
David Vincze401c7422019-06-21 20:44:05 +0200308 return rc;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000309}
310
311#else /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
312
313static inline size_t
314boot_img_sector_size(struct boot_loader_state *state,
315 size_t slot, size_t sector)
316{
317 return state->imgs[slot].sectors[sector].fs_size;
318}
319
320static inline uint32_t
321boot_img_sector_off(struct boot_loader_state *state, size_t slot,
322 size_t sector)
323{
324 return state->imgs[slot].sectors[sector].fs_off -
325 state->imgs[slot].sectors[0].fs_off;
326}
327
328static inline int
329boot_initialize_area(struct boot_loader_state *state, int flash_area)
330{
331 uint32_t num_sectors;
332 struct flash_sector *out_sectors;
333 size_t *out_num_sectors;
334 int rc;
335
336 switch (flash_area) {
David Vincze8bdfc2d2019-03-18 15:49:23 +0100337 case FLASH_AREA_IMAGE_PRIMARY:
Tamas Banf70ef8c2017-12-19 15:35:09 +0000338 num_sectors = BOOT_MAX_IMG_SECTORS;
David Vincze8bdfc2d2019-03-18 15:49:23 +0100339 out_sectors = state->imgs[BOOT_PRIMARY_SLOT].sectors;
340 out_num_sectors = &state->imgs[BOOT_PRIMARY_SLOT].num_sectors;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000341 break;
David Vincze8bdfc2d2019-03-18 15:49:23 +0100342 case FLASH_AREA_IMAGE_SECONDARY:
Tamas Banf70ef8c2017-12-19 15:35:09 +0000343 num_sectors = BOOT_MAX_IMG_SECTORS;
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;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000346 break;
David Vincze401c7422019-06-21 20:44:05 +0200347 case FLASH_AREA_IMAGE_SCRATCH:
348 num_sectors = BOOT_MAX_IMG_SECTORS;
349 out_sectors = state->scratch.sectors;
350 out_num_sectors = &state->scratch.num_sectors;
351 break;
Tamas Banf70ef8c2017-12-19 15:35:09 +0000352 default:
353 return -1;
354 }
355
356 rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
357 if (rc != 0) {
358 return rc;
359 }
360 *out_num_sectors = num_sectors;
361 return 0;
362}
363
364#endif /* !defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
365
366#ifdef __cplusplus
367}
368#endif
369
370#endif