blob: d2ee6fc73d3e307d8ad1ca4cacefa1b7b5be3816 [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#ifndef H_BOOTUTIL_PRIV_
21#define H_BOOTUTIL_PRIV_
22
Marti Bolivarcca28a92017-06-12 16:52:22 -040023#include "sysflash/sysflash.h"
Marti Bolivar9b1f8bb2017-06-12 15:24:13 -040024#include "flash_map/flash_map.h"
Christopher Collins92ea77f2016-12-12 15:59:26 -080025#include "bootutil/image.h"
Marti Bolivarf91bca52018-04-12 12:40:46 -040026#include "mcuboot_config/mcuboot_config.h"
Christopher Collins92ea77f2016-12-12 15:59:26 -080027
28#ifdef __cplusplus
29extern "C" {
30#endif
31
Marti Bolivar248da082018-04-24 15:11:39 -040032#ifdef MCUBOOT_HAVE_ASSERT_H
33#include "mcuboot_config/mcuboot_assert.h"
Fabio Utzig57c40f72017-12-12 21:48:30 -020034#else
35#define ASSERT assert
36#endif
37
Christopher Collins92ea77f2016-12-12 15:59:26 -080038struct 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
Christopher Collins92ea77f2016-12-12 15:59:26 -080050/*
51 * Maintain state of copy progress.
52 */
53struct boot_status {
Fabio Utzig2473ac02017-05-02 12:45:02 -030054 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? */
Fabio Utzig46490722017-09-04 15:34:32 -030057 uint32_t swap_size; /* Total size of swapped image */
Christopher Collins92ea77f2016-12-12 15:59:26 -080058};
59
60#define BOOT_MAGIC_GOOD 1
61#define BOOT_MAGIC_BAD 2
62#define BOOT_MAGIC_UNSET 3
63
64/**
65 * End-of-image slot structure.
66 *
67 * 0 1 2 3
68 * 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
69 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Christopher Collins92ea77f2016-12-12 15:59:26 -080070 * ~ ~
71 * ~ Swap status (variable, aligned) ~
72 * ~ ~
73 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Fabio Utzig46490722017-09-04 15:34:32 -030074 * | Swap size |
Christopher Collins92ea77f2016-12-12 15:59:26 -080075 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Fabio Utzig46490722017-09-04 15:34:32 -030076 * ~ 0xff padding (MAX ALIGN - 4) ~
77 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
78 * | Copy done | 0xff padding (MAX ALIGN - 1) ~
79 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
80 * | Image OK | 0xff padding (MAX ALIGN - 1) ~
81 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
82 * ~ MAGIC (16 octets) ~
Christopher Collins92ea77f2016-12-12 15:59:26 -080083 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
84 */
85
86extern const uint32_t boot_img_magic[4];
87
88struct boot_swap_state {
89 uint8_t magic; /* One of the BOOT_MAGIC_[...] values. */
90 uint8_t copy_done;
91 uint8_t image_ok;
92};
93
Marti Bolivarf9bfddd2018-04-24 14:28:33 -040094#define BOOT_MAX_IMG_SECTORS MCUBOOT_MAX_IMG_SECTORS
Fabio Utziga1fae672018-03-30 10:52:38 -030095
96/*
97 * The current flashmap API does not check the amount of space allocated when
98 * loading sector data from the flash device, allowing for smaller counts here
99 * would most surely incur in overruns.
100 *
101 * TODO: make flashmap API receive the current sector array size.
102 */
103#if BOOT_MAX_IMG_SECTORS < 32
104#error "Too few sectors, please increase BOOT_MAX_IMG_SECTORS to at least 32"
105#endif
106
107/** Number of image slots in flash; currently limited to two. */
108#define BOOT_NUM_SLOTS 2
109
110/** Maximum number of image sectors supported by the bootloader. */
111#define BOOT_STATUS_STATE_COUNT 3
112#define BOOT_STATUS_MAX_ENTRIES BOOT_MAX_IMG_SECTORS
Christopher Collins92ea77f2016-12-12 15:59:26 -0800113
114#define BOOT_STATUS_SOURCE_NONE 0
115#define BOOT_STATUS_SOURCE_SCRATCH 1
116#define BOOT_STATUS_SOURCE_SLOT0 2
117
Fabio Utzig2473ac02017-05-02 12:45:02 -0300118#define BOOT_FLAG_IMAGE_OK 0
119#define BOOT_FLAG_COPY_DONE 1
120
Fabio Utzigde8a38a2017-05-23 11:15:01 -0400121#define BOOT_FLAG_SET 0x01
122#define BOOT_FLAG_UNSET 0xff
Fabio Utzigba49f842017-05-22 10:52:38 -0400123
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300124extern const uint32_t BOOT_MAGIC_SZ;
125
Marti Bolivarc50926f2017-06-14 09:35:40 -0400126/**
127 * Compatibility shim for flash sector type.
128 *
129 * This can be deleted when flash_area_to_sectors() is removed.
130 */
131#ifdef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
132typedef struct flash_sector boot_sector_t;
133#else
134typedef struct flash_area boot_sector_t;
135#endif
136
Marti Bolivar9b1f8bb2017-06-12 15:24:13 -0400137/** Private state maintained during boot. */
138struct boot_loader_state {
139 struct {
140 struct image_header hdr;
Marti Bolivarc0b47912017-06-13 17:18:09 -0400141 const struct flash_area *area;
Marti Bolivarc50926f2017-06-14 09:35:40 -0400142 boot_sector_t *sectors;
Marti Bolivar84898652017-06-13 17:20:22 -0400143 size_t num_sectors;
Marti Bolivar9b1f8bb2017-06-12 15:24:13 -0400144 } imgs[BOOT_NUM_SLOTS];
145
Marti Bolivarc0b47912017-06-13 17:18:09 -0400146 const struct flash_area *scratch_area;
Marti Bolivar9b1f8bb2017-06-12 15:24:13 -0400147
148 uint8_t write_sz;
149};
150
Fabio Utzig1a927dd2017-12-05 10:30:26 -0200151int bootutil_verify_sig(uint8_t *hash, uint32_t hlen, uint8_t *sig,
152 size_t slen, uint8_t key_id);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800153
Fabio Utzig7ebb7c22017-04-26 10:59:31 -0300154uint32_t boot_slots_trailer_sz(uint8_t min_write_sz);
Fabio Utzig4cee4f72017-05-22 10:59:57 -0400155int boot_status_entries(const struct flash_area *fap);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800156uint32_t boot_status_off(const struct flash_area *fap);
157int boot_read_swap_state(const struct flash_area *fap,
158 struct boot_swap_state *state);
Fabio Utzig2473ac02017-05-02 12:45:02 -0300159int boot_read_swap_state_by_id(int flash_area_id,
160 struct boot_swap_state *state);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800161int boot_write_magic(const struct flash_area *fap);
162int boot_write_status(struct boot_status *bs);
163int boot_schedule_test_swap(void);
164int boot_write_copy_done(const struct flash_area *fap);
165int boot_write_image_ok(const struct flash_area *fap);
Fabio Utzig46490722017-09-04 15:34:32 -0300166int boot_write_swap_size(const struct flash_area *fap, uint32_t swap_size);
167int boot_read_swap_size(uint32_t *swap_size);
Christopher Collins92ea77f2016-12-12 15:59:26 -0800168
Marti Bolivarf804f622017-06-12 15:41:48 -0400169/*
170 * Accessors for the contents of struct boot_loader_state.
171 */
172
Marti Bolivarc0b47912017-06-13 17:18:09 -0400173/* These are macros so they can be used as lvalues. */
174#define BOOT_IMG_AREA(state, slot) ((state)->imgs[(slot)].area)
175#define BOOT_SCRATCH_AREA(state) ((state)->scratch_area)
Marti Bolivare10a7392017-06-14 16:20:07 -0400176#define BOOT_WRITE_SZ(state) ((state)->write_sz)
Marti Bolivarc0b47912017-06-13 17:18:09 -0400177
Marti Bolivarf804f622017-06-12 15:41:48 -0400178static inline struct image_header*
179boot_img_hdr(struct boot_loader_state *state, size_t slot)
180{
181 return &state->imgs[slot].hdr;
182}
183
Marti Bolivare2587152017-06-12 15:52:05 -0400184static inline uint8_t
185boot_img_fa_device_id(struct boot_loader_state *state, size_t slot)
186{
Marti Bolivarc0b47912017-06-13 17:18:09 -0400187 return state->imgs[slot].area->fa_device_id;
Marti Bolivare2587152017-06-12 15:52:05 -0400188}
189
190static inline uint8_t
191boot_scratch_fa_device_id(struct boot_loader_state *state)
192{
Marti Bolivarc0b47912017-06-13 17:18:09 -0400193 return state->scratch_area->fa_device_id;
Marti Bolivare2587152017-06-12 15:52:05 -0400194}
195
Marti Bolivard3269fd2017-06-12 16:31:12 -0400196static inline size_t
197boot_img_num_sectors(struct boot_loader_state *state, size_t slot)
198{
199 return state->imgs[slot].num_sectors;
200}
201
Marti Bolivar135b8f62017-06-13 17:22:13 -0400202/*
203 * Offset of the slot from the beginning of the flash device.
204 */
205static inline uint32_t
206boot_img_slot_off(struct boot_loader_state *state, size_t slot)
207{
208 return state->imgs[slot].area->fa_off;
209}
210
211static inline size_t boot_scratch_area_size(struct boot_loader_state *state)
212{
213 return state->scratch_area->fa_size;
214}
215
Marti Bolivarc50926f2017-06-14 09:35:40 -0400216#ifndef MCUBOOT_USE_FLASH_AREA_GET_SECTORS
217
Marti Bolivard3269fd2017-06-12 16:31:12 -0400218static inline size_t
219boot_img_sector_size(struct boot_loader_state *state,
220 size_t slot, size_t sector)
221{
222 return state->imgs[slot].sectors[sector].fa_size;
223}
224
Marti Bolivarea088872017-06-12 17:10:49 -0400225/*
226 * Offset of the sector from the beginning of the image, NOT the flash
227 * device.
228 */
229static inline uint32_t
230boot_img_sector_off(struct boot_loader_state *state, size_t slot,
231 size_t sector)
232{
233 return state->imgs[slot].sectors[sector].fa_off -
234 state->imgs[slot].sectors[0].fa_off;
235}
236
Marti Bolivarcca28a92017-06-12 16:52:22 -0400237static inline int
238boot_initialize_area(struct boot_loader_state *state, int flash_area)
239{
Marti Bolivarcca28a92017-06-12 16:52:22 -0400240 int num_sectors = BOOT_MAX_IMG_SECTORS;
241 size_t slot;
242 int rc;
243
244 switch (flash_area) {
245 case FLASH_AREA_IMAGE_0:
246 slot = 0;
247 break;
248 case FLASH_AREA_IMAGE_1:
249 slot = 1;
250 break;
Marti Bolivarcca28a92017-06-12 16:52:22 -0400251 default:
252 return BOOT_EFLASH;
253 }
254
255 rc = flash_area_to_sectors(flash_area, &num_sectors,
256 state->imgs[slot].sectors);
257 if (rc != 0) {
258 return rc;
259 }
Marti Bolivar84898652017-06-13 17:20:22 -0400260 state->imgs[slot].num_sectors = (size_t)num_sectors;
Marti Bolivarcca28a92017-06-12 16:52:22 -0400261 return 0;
262}
263
Marti Bolivarc50926f2017-06-14 09:35:40 -0400264#else /* defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
265
266static inline size_t
267boot_img_sector_size(struct boot_loader_state *state,
268 size_t slot, size_t sector)
269{
270 return state->imgs[slot].sectors[sector].fs_size;
271}
272
273static inline uint32_t
274boot_img_sector_off(struct boot_loader_state *state, size_t slot,
275 size_t sector)
276{
277 return state->imgs[slot].sectors[sector].fs_off -
278 state->imgs[slot].sectors[0].fs_off;
279}
280
281static inline int
282boot_initialize_area(struct boot_loader_state *state, int flash_area)
283{
284 uint32_t num_sectors;
285 struct flash_sector *out_sectors;
286 size_t *out_num_sectors;
287 int rc;
288
289 switch (flash_area) {
290 case FLASH_AREA_IMAGE_0:
291 num_sectors = BOOT_MAX_IMG_SECTORS;
292 out_sectors = state->imgs[0].sectors;
293 out_num_sectors = &state->imgs[0].num_sectors;
294 break;
295 case FLASH_AREA_IMAGE_1:
296 num_sectors = BOOT_MAX_IMG_SECTORS;
297 out_sectors = state->imgs[1].sectors;
298 out_num_sectors = &state->imgs[1].num_sectors;
299 break;
300 default:
301 return -1;
302 }
303
304 rc = flash_area_get_sectors(flash_area, &num_sectors, out_sectors);
305 if (rc != 0) {
306 return rc;
307 }
308 *out_num_sectors = num_sectors;
309 return 0;
310}
311
312#endif /* !defined(MCUBOOT_USE_FLASH_AREA_GET_SECTORS) */
313
Christopher Collins92ea77f2016-12-12 15:59:26 -0800314#ifdef __cplusplus
315}
316#endif
317
318#endif