1 /*
2 * Copyright (c) 2017 Nordic Semiconductor ASA
3 * Copyright (c) 2016-2017 Linaro Limited
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <stddef.h>
9 #include <errno.h>
10 #include <string.h>
11 #include <zephyr/drivers/flash.h>
12 #include <zephyr/storage/flash_map.h>
13 #include <zephyr/kernel.h>
14 #include <zephyr/init.h>
15
16 #include <zephyr/sys/__assert.h>
17 #include <zephyr/sys/byteorder.h>
18
19 #include "bootutil/bootutil_public.h"
20 #include <zephyr/dfu/mcuboot.h>
21
22 #include "mcuboot_priv.h"
23
24 /*
25 * Helpers for image headers and trailers, as defined by mcuboot.
26 */
27
28 /*
29 * Strict defines: the definitions in the following block contain
30 * values which are MCUboot implementation requirements.
31 */
32
33 /* Header: */
34 #define BOOT_HEADER_MAGIC_V1 0x96f3b83d
35 #define BOOT_HEADER_SIZE_V1 32
36
37 /* Get active partition. zephyr,code-partition chosen node must be defined */
38 #define ACTIVE_SLOT_FLASH_AREA_ID DT_FIXED_PARTITION_ID(DT_CHOSEN(zephyr_code_partition))
39
40 /*
41 * Raw (on-flash) representation of the v1 image header.
42 */
43 struct mcuboot_v1_raw_header {
44 uint32_t header_magic;
45 uint32_t image_load_address;
46 uint16_t header_size;
47 uint16_t pad;
48 uint32_t image_size;
49 uint32_t image_flags;
50 struct {
51 uint8_t major;
52 uint8_t minor;
53 uint16_t revision;
54 uint32_t build_num;
55 } version;
56 uint32_t pad2;
57 } __packed;
58
59 /*
60 * End of strict defines
61 */
62
boot_read_v1_header(uint8_t area_id,struct mcuboot_v1_raw_header * v1_raw)63 static int boot_read_v1_header(uint8_t area_id,
64 struct mcuboot_v1_raw_header *v1_raw)
65 {
66 const struct flash_area *fa;
67 int rc;
68
69 rc = flash_area_open(area_id, &fa);
70 if (rc) {
71 return rc;
72 }
73
74 /*
75 * Read and sanity-check the raw header.
76 */
77 rc = flash_area_read(fa, 0, v1_raw, sizeof(*v1_raw));
78 flash_area_close(fa);
79 if (rc) {
80 return rc;
81 }
82
83 v1_raw->header_magic = sys_le32_to_cpu(v1_raw->header_magic);
84 v1_raw->image_load_address =
85 sys_le32_to_cpu(v1_raw->image_load_address);
86 v1_raw->header_size = sys_le16_to_cpu(v1_raw->header_size);
87 v1_raw->image_size = sys_le32_to_cpu(v1_raw->image_size);
88 v1_raw->image_flags = sys_le32_to_cpu(v1_raw->image_flags);
89 v1_raw->version.revision =
90 sys_le16_to_cpu(v1_raw->version.revision);
91 v1_raw->version.build_num =
92 sys_le32_to_cpu(v1_raw->version.build_num);
93
94 /*
95 * Sanity checks.
96 *
97 * Larger values in header_size than BOOT_HEADER_SIZE_V1 are
98 * possible, e.g. if Zephyr was linked with
99 * CONFIG_ROM_START_OFFSET > BOOT_HEADER_SIZE_V1.
100 */
101 if ((v1_raw->header_magic != BOOT_HEADER_MAGIC_V1) ||
102 (v1_raw->header_size < BOOT_HEADER_SIZE_V1)) {
103 return -EIO;
104 }
105
106 return 0;
107 }
108
boot_read_bank_header(uint8_t area_id,struct mcuboot_img_header * header,size_t header_size)109 int boot_read_bank_header(uint8_t area_id,
110 struct mcuboot_img_header *header,
111 size_t header_size)
112 {
113 int rc;
114 struct mcuboot_v1_raw_header v1_raw;
115 struct mcuboot_img_sem_ver *sem_ver;
116 size_t v1_min_size = (sizeof(uint32_t) +
117 sizeof(struct mcuboot_img_header_v1));
118
119 /*
120 * Only version 1 image headers are supported.
121 */
122 if (header_size < v1_min_size) {
123 return -ENOMEM;
124 }
125 rc = boot_read_v1_header(area_id, &v1_raw);
126 if (rc) {
127 return rc;
128 }
129
130 /*
131 * Copy just the fields we care about into the return parameter.
132 *
133 * - header_magic: skip (only used to check format)
134 * - image_load_address: skip (only matters for PIC code)
135 * - header_size: skip (only used to check format)
136 * - image_size: include
137 * - image_flags: skip (all unsupported or not relevant)
138 * - version: include
139 */
140 header->mcuboot_version = 1U;
141 header->h.v1.image_size = v1_raw.image_size;
142 sem_ver = &header->h.v1.sem_ver;
143 sem_ver->major = v1_raw.version.major;
144 sem_ver->minor = v1_raw.version.minor;
145 sem_ver->revision = v1_raw.version.revision;
146 sem_ver->build_num = v1_raw.version.build_num;
147 return 0;
148 }
149
mcuboot_swap_type_multi(int image_index)150 int mcuboot_swap_type_multi(int image_index)
151 {
152 return boot_swap_type_multi(image_index);
153 }
154
mcuboot_swap_type(void)155 int mcuboot_swap_type(void)
156 {
157 #ifdef FLASH_AREA_IMAGE_SECONDARY
158 return boot_swap_type();
159 #else
160 return BOOT_SWAP_TYPE_NONE;
161 #endif
162
163 }
164
boot_request_upgrade(int permanent)165 int boot_request_upgrade(int permanent)
166 {
167 #ifdef FLASH_AREA_IMAGE_SECONDARY
168 int rc;
169
170 rc = boot_set_pending(permanent);
171 if (rc) {
172 return -EFAULT;
173 }
174 #endif /* FLASH_AREA_IMAGE_SECONDARY */
175 return 0;
176 }
177
boot_request_upgrade_multi(int image_index,int permanent)178 int boot_request_upgrade_multi(int image_index, int permanent)
179 {
180 int rc;
181
182 rc = boot_set_pending_multi(image_index, permanent);
183 if (rc) {
184 return -EFAULT;
185 }
186 return 0;
187 }
188
boot_is_img_confirmed(void)189 bool boot_is_img_confirmed(void)
190 {
191 struct boot_swap_state state;
192 const struct flash_area *fa;
193 int rc;
194
195 rc = flash_area_open(FLASH_AREA_IMAGE_PRIMARY, &fa);
196 if (rc) {
197 return false;
198 }
199
200 rc = boot_read_swap_state(fa, &state);
201 if (rc != 0) {
202 return false;
203 }
204
205 if (state.magic == BOOT_MAGIC_UNSET) {
206 /* This is initial/preprogramed image.
207 * Such image can neither be reverted nor physically confirmed.
208 * Treat this image as confirmed which ensures consistency
209 * with `boot_write_img_confirmed...()` procedures.
210 */
211 return true;
212 }
213
214 return state.image_ok == BOOT_FLAG_SET;
215 }
216
boot_write_img_confirmed(void)217 int boot_write_img_confirmed(void)
218 {
219 const struct flash_area *fa;
220 int rc = 0;
221
222 if (flash_area_open(ACTIVE_SLOT_FLASH_AREA_ID, &fa) != 0) {
223 return -EIO;
224 }
225
226 rc = boot_set_next(fa, true, true);
227
228 flash_area_close(fa);
229
230 return rc;
231 }
232
boot_write_img_confirmed_multi(int image_index)233 int boot_write_img_confirmed_multi(int image_index)
234 {
235 int rc;
236
237 rc = boot_set_confirmed_multi(image_index);
238 if (rc) {
239 return -EIO;
240 }
241
242 return 0;
243 }
244
boot_erase_img_bank(uint8_t area_id)245 int boot_erase_img_bank(uint8_t area_id)
246 {
247 const struct flash_area *fa;
248 int rc;
249
250 rc = flash_area_open(area_id, &fa);
251 if (rc) {
252 return rc;
253 }
254
255 rc = flash_area_erase(fa, 0, fa->fa_size);
256
257 flash_area_close(fa);
258
259 return rc;
260 }
261
boot_get_trailer_status_offset(size_t area_size)262 ssize_t boot_get_trailer_status_offset(size_t area_size)
263 {
264 return (ssize_t)area_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
265 }
266
boot_get_area_trailer_status_offset(uint8_t area_id)267 ssize_t boot_get_area_trailer_status_offset(uint8_t area_id)
268 {
269 int rc;
270 const struct flash_area *fa;
271 ssize_t offset;
272
273 rc = flash_area_open(area_id, &fa);
274 if (rc) {
275 return rc;
276 }
277
278 offset = boot_get_trailer_status_offset(fa->fa_size);
279
280 flash_area_close(fa);
281
282 if (offset < 0) {
283 return -EFAULT;
284 }
285
286 return offset;
287 }
288