blob: 918d2d1ee31ff3302e6fb9d086f0f2c64c7ca245 [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
23 * Git SHA of the original version: 178be54bd6e5f035cc60e98205535682acd26e64
24 * 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"
31#include "bootutil/image.h"
Mate Toth-Pala76e2ab2018-05-31 15:43:01 +020032#include "flash_layout.h"
Tamas Banf70ef8c2017-12-19 15:35:09 +000033
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38struct flash_area;
39
40#define BOOT_EFLASH 1
41#define BOOT_EFILE 2
42#define BOOT_EBADIMAGE 3
43#define BOOT_EBADVECT 4
44#define BOOT_EBADSTATUS 5
45#define BOOT_ENOMEM 6
46#define BOOT_EBADARGS 7
47
48#define BOOT_TMPBUF_SZ 256
49
50/*
51 * Maintain state of copy progress.
52 */
53struct boot_status {
54 uint32_t idx; /* Which area we're operating on */
55 uint8_t state; /* Which part of the swapping process are we at */
56 uint8_t use_scratch; /* Are status bytes ever written to scratch? */
57 uint32_t swap_size; /* Total size of swapped image */
58};
59
David Vincze39e78552018-10-10 17:10:01 +020060#define BOOT_MAGIC_GOOD 1
61#define BOOT_MAGIC_BAD 2
62#define BOOT_MAGIC_UNSET 3
63#define BOOT_MAGIC_ANY 4 /* NOTE: control only, not dependent on sector */
64
65/*
66 * NOTE: leave BOOT_FLAG_SET equal to one, this is written to flash!
67 */
68#define BOOT_FLAG_SET 1
69#define BOOT_FLAG_BAD 2
70#define BOOT_FLAG_UNSET 3
71#define BOOT_FLAG_ANY 4 /* NOTE: control only, not dependent on sector */
72
73#define BOOT_STATUS_IDX_0 1
74
75#define BOOT_STATUS_STATE_0 1
76#define BOOT_STATUS_STATE_1 2
77#define BOOT_STATUS_STATE_2 3
Tamas Banf70ef8c2017-12-19 15:35:09 +000078
79/**
80 * End-of-image slot structure.
81 *
82 * 0 1 2 3
83 * 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
84 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
85 * ~ ~
86 * ~ Swap status (variable, aligned) ~
87 * ~ ~
88 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
89 * | Swap size |
90 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
David Vincze39e78552018-10-10 17:10:01 +020091 * ~ padding with erased val (MAX ALIGN - 4) ~
Tamas Banf70ef8c2017-12-19 15:35:09 +000092 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
David Vincze39e78552018-10-10 17:10:01 +020093 * | Copy done | padding with erased val (MAX ALIGN - 1) ~
Tamas Banf70ef8c2017-12-19 15:35:09 +000094 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
David Vincze39e78552018-10-10 17:10:01 +020095 * | Image OK | padding with erased val (MAX ALIGN - 1) ~
Tamas Banf70ef8c2017-12-19 15:35:09 +000096 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
97 * ~ MAGIC (16 octets) ~
98 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
99 */
100
101extern const uint32_t boot_img_magic[4];
102
103struct boot_swap_state {
104 uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */
105 uint8_t copy_done;
106 uint8_t image_ok;
107};
108
David Vincze39e78552018-10-10 17:10:01 +0200109/*
110 * The current flashmap API does not check the amount of space allocated when
111 * loading sector data from the flash device, allowing for smaller counts here
112 * would most surely incur in overruns.
113 *
114 * TODO: make flashmap API receive the current sector array size.
115 */
116#if BOOT_MAX_IMG_SECTORS < 32
117#error "Too few sectors, please increase BOOT_MAX_IMG_SECTORS to at least 32"
118#endif
119
120/** Number of image slots in flash; currently limited to two. */
121#define BOOT_NUM_SLOTS 2
122
123/** Maximum number of image sectors supported by the bootloader. */
124#define BOOT_STATUS_STATE_COUNT 3
Tamas Banf70ef8c2017-12-19 15:35:09 +0000125
126#define BOOT_STATUS_SOURCE_NONE 0
127#define BOOT_STATUS_SOURCE_SCRATCH 1
128#define BOOT_STATUS_SOURCE_SLOT0 2
129
130#define BOOT_FLAG_IMAGE_OK 0
131#define BOOT_FLAG_COPY_DONE 1
132
Tamas Banf70ef8c2017-12-19 15:35:09 +0000133extern const uint32_t BOOT_MAGIC_SZ;
134
Tamas Banf70ef8c2017-12-19 15:35:09 +0000135/**
136 * Compatibility shim for flash sector type.
137 *
138 * This can be deleted when flash_area_to_sectors() is removed.
139 */
140#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
141typedef struct flash_sector boot_sector_t;
142#else
143typedef struct flash_area boot_sector_t;
144#endif
145
146/** Private state maintained during boot. */
147struct boot_loader_state {
148 struct {
149 struct image_header hdr;
150 const struct flash_area *area;
151 boot_sector_t *sectors;
152 size_t num_sectors;
153 } imgs[BOOT_NUM_SLOTS];
154
155 const struct flash_area *scratch_area;
156
157 uint8_t write_sz;
158};
159
David Vincze39e78552018-10-10 17:10:01 +0200160int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
161 size_t slen, uint8_t key_id);
Tamas Banf70ef8c2017-12-19 15:35:09 +0000162
163uint32_t boot_slots_trailer_sz(uint8_t min_write_sz);
164int boot_status_entries(const struct flash_area *fap);
165uint32_t boot_status_off(const struct flash_area *fap);
166int boot_read_swap_state(const struct flash_area *fap,
167 struct boot_swap_state *state);
168int boot_read_swap_state_by_id(int flash_area_id,
169 struct boot_swap_state *state);
170int boot_write_magic(const struct flash_area *fap);
171int boot_write_status(struct boot_status *bs);
172int boot_schedule_test_swap(void);
173int boot_write_copy_done(const struct flash_area *fap);
174int boot_write_image_ok(const struct flash_area *fap);
175int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
176int boot_read_swap_size(uint32_t *swap_size);
177
178/*
179 * Accessors for the contents of struct boot_loader_state.
180 */
181
182/* These are macros so they can be used as lvalues. */
183#define BOOT_IMG_AREA(state, slot) ((state)->imgs[(slot)].area)
184#define BOOT_SCRATCH_AREA(state) ((state)->scratch_area)
185#define BOOT_WRITE_SZ(state) ((state)->write_sz)
186
187static inline struct image_header*
188boot_img_hdr(struct boot_loader_state *state, size_t slot)
189{
190 return &state->imgs[slot].hdr;
191}
192
193static inline uint8_t
194boot_img_fa_device_id(struct boot_loader_state *state, size_t slot)
195{
196 return state->imgs[slot].area->fa_device_id;
197}
198
199static inline uint8_t
200boot_scratch_fa_device_id(struct boot_loader_state *state)
201{
202 return state->scratch_area->fa_device_id;
203}
204
205static inline size_t
206boot_img_num_sectors(struct boot_loader_state *state, size_t slot)
207{
208 return state->imgs[slot].num_sectors;
209}
210
211/*
212 * Offset of the slot from the beginning of the flash device.
213 */
214static inline uint32_t
215boot_img_slot_off(struct boot_loader_state *state, size_t slot)
216{
217 return state->imgs[slot].area->fa_off;
218}
219
220static inline size_t boot_scratch_area_size(struct boot_loader_state *state)
221{
222 return state->scratch_area->fa_size;
223}
224
225#ifndef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
226
227static inline size_t
228boot_img_sector_size(struct boot_loader_state *state,
229 size_t slot, size_t sector)
230{
231 return state->imgs[slot].sectors[sector].fa_size;
232}
233
234/*
235 * Offset of the sector from the beginning of the image, NOT the flash
236 * device.
237 */
238static inline uint32_t
239boot_img_sector_off(struct boot_loader_state *state, size_t slot,
240 size_t sector)
241{
242 return state->imgs[slot].sectors[sector].fa_off -
243 state->imgs[slot].sectors[0].fa_off;
244}
245
246static inline int
247boot_initialize_area(struct boot_loader_state *state, int flash_area)
248{
249 int num_sectors = BOOT_MAX_IMG_SECTORS;
250 size_t slot;
251 int rc;
252
253 switch (flash_area) {
254 case FLASH_AREA_IMAGE_0:
255 slot = 0;
256 break;
257 case FLASH_AREA_IMAGE_1:
258 slot = 1;
259 break;
260 default:
261 return BOOT_EFLASH;
262 }
263
264 rc = flash_area_to_sectors(flash_area, &num_sectors,
265 state->imgs[slot].sectors);
266 if (rc != 0) {
267 return rc;
268 }
269 state->imgs[slot].num_sectors = (size_t)num_sectors;
270 return 0;
271}
272
273#else /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
274
275static inline size_t
276boot_img_sector_size(struct boot_loader_state *state,
277 size_t slot, size_t sector)
278{
279 return state->imgs[slot].sectors[sector].fs_size;
280}
281
282static inline uint32_t
283boot_img_sector_off(struct boot_loader_state *state, size_t slot,
284 size_t sector)
285{
286 return state->imgs[slot].sectors[sector].fs_off -
287 state->imgs[slot].sectors[0].fs_off;
288}
289
290static inline int
291boot_initialize_area(struct boot_loader_state *state, int flash_area)
292{
293 uint32_t num_sectors;
294 struct flash_sector *out_sectors;
295 size_t *out_num_sectors;
296 int rc;
297
298 switch (flash_area) {
299 case FLASH_AREA_IMAGE_0:
300 num_sectors = BOOT_MAX_IMG_SECTORS;
301 out_sectors = state->imgs[0].sectors;
302 out_num_sectors = &state->imgs[0].num_sectors;
303 break;
304 case FLASH_AREA_IMAGE_1:
305 num_sectors = BOOT_MAX_IMG_SECTORS;
306 out_sectors = state->imgs[1].sectors;
307 out_num_sectors = &state->imgs[1].num_sectors;
308 break;
309 default:
310 return -1;
311 }
312
313 rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
314 if (rc != 0) {
315 return rc;
316 }
317 *out_num_sectors = num_sectors;
318 return 0;
319}
320
321#endif /* !defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
322
323#ifdef __cplusplus
324}
325#endif
326
327#endif