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