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 enum IMAGE_INDEXES {
46 	IMAGE_INDEX_INVALID = -1,
47 	IMAGE_INDEX_0,
48 	IMAGE_INDEX_1,
49 	IMAGE_INDEX_2
50 };
51 
52 #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
53 /* For RAM LOAD mode, the active image must be fetched from the bootloader */
54 #define ACTIVE_SLOT_FLASH_AREA_ID boot_fetch_active_slot()
55 #define INVALID_SLOT_ID 255
56 #else
57 /* Get active partition. zephyr,code-partition chosen node must be defined */
58 #define ACTIVE_SLOT_FLASH_AREA_ID DT_FIXED_PARTITION_ID(DT_CHOSEN(zephyr_code_partition))
59 #endif
60 
61 /*
62  * Raw (on-flash) representation of the v1 image header.
63  */
64 struct mcuboot_v1_raw_header {
65 	uint32_t header_magic;
66 	uint32_t image_load_address;
67 	uint16_t header_size;
68 	uint16_t pad;
69 	uint32_t image_size;
70 	uint32_t image_flags;
71 	struct {
72 		uint8_t major;
73 		uint8_t minor;
74 		uint16_t revision;
75 		uint32_t build_num;
76 	} version;
77 	uint32_t pad2;
78 } __packed;
79 
80 /*
81  * End of strict defines
82  */
83 
84 #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD)
boot_fetch_active_slot(void)85 uint8_t boot_fetch_active_slot(void)
86 {
87 	int rc;
88 	uint8_t slot;
89 
90 	rc = blinfo_lookup(BLINFO_RUNNING_SLOT, &slot, sizeof(slot));
91 
92 	if (rc <= 0) {
93 		LOG_ERR("Failed to fetch active slot: %d", rc);
94 
95 		return INVALID_SLOT_ID;
96 	}
97 
98 	LOG_DBG("Active slot: %d", slot);
99 
100 	return slot;
101 }
102 #else  /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD */
boot_fetch_active_slot(void)103 uint8_t boot_fetch_active_slot(void)
104 {
105 	return ACTIVE_SLOT_FLASH_AREA_ID;
106 }
107 #endif /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD */
108 
109 #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET)
boot_get_image_start_offset(uint8_t area_id)110 size_t boot_get_image_start_offset(uint8_t area_id)
111 {
112 	size_t off = 0;
113 	int image = IMAGE_INDEX_INVALID;
114 
115 	if (area_id == FIXED_PARTITION_ID(slot1_partition)) {
116 		image = IMAGE_INDEX_0;
117 #if FIXED_PARTITION_EXISTS(slot3_partition)
118 	} else if (area_id == FIXED_PARTITION_ID(slot3_partition)) {
119 		image = IMAGE_INDEX_1;
120 #endif
121 #if FIXED_PARTITION_EXISTS(slot5_partition)
122 	} else if (area_id == FIXED_PARTITION_ID(slot5_partition)) {
123 		image = IMAGE_INDEX_2;
124 #endif
125 	}
126 
127 	if (image != IMAGE_INDEX_INVALID) {
128 		/* Need to check status from primary slot to get correct offset for secondary
129 		 * slot image header
130 		 */
131 		const struct flash_area *fa;
132 		uint32_t num_sectors = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN;
133 		struct flash_sector sector_data;
134 		int rc;
135 
136 		rc = flash_area_open(area_id, &fa);
137 		if (rc) {
138 			LOG_ERR("Flash open area %u failed: %d", area_id, rc);
139 			goto done;
140 		}
141 
142 		if (mcuboot_swap_type_multi(image) != BOOT_SWAP_TYPE_REVERT) {
143 			/* For swap using offset mode, the image starts in the second sector of
144 			 * the upgrade slot, so apply the offset when this is needed, do this by
145 			 * getting information on first sector only, this is expected to return an
146 			 * error as there are more slots, so allow the not enough memory error
147 			 */
148 			rc = flash_area_get_sectors(area_id, &num_sectors, &sector_data);
149 			if ((rc != 0 && rc != -ENOMEM) ||
150 			    num_sectors != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) {
151 				LOG_ERR("Failed to get sector details: %d", rc);
152 			} else {
153 				off = sector_data.fs_size;
154 			}
155 		}
156 
157 		flash_area_close(fa);
158 	}
159 
160 done:
161 	LOG_DBG("Start offset for area %u: 0x%x", area_id, off);
162 	return off;
163 }
164 #endif /* CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET */
165 
boot_read_v1_header(uint8_t area_id,struct mcuboot_v1_raw_header * v1_raw)166 static int boot_read_v1_header(uint8_t area_id,
167 			       struct mcuboot_v1_raw_header *v1_raw)
168 {
169 	const struct flash_area *fa;
170 	int rc;
171 	size_t off = boot_get_image_start_offset(area_id);
172 
173 	rc = flash_area_open(area_id, &fa);
174 	if (rc) {
175 		return rc;
176 	}
177 
178 	/*
179 	 * Read and validty-check the raw header.
180 	 */
181 	rc = flash_area_read(fa, off, v1_raw, sizeof(*v1_raw));
182 	flash_area_close(fa);
183 	if (rc) {
184 		return rc;
185 	}
186 
187 	v1_raw->header_magic = sys_le32_to_cpu(v1_raw->header_magic);
188 	v1_raw->header_size = sys_le16_to_cpu(v1_raw->header_size);
189 
190 	/*
191 	 * Validity checks.
192 	 *
193 	 * Larger values in header_size than BOOT_HEADER_SIZE_V1 are
194 	 * possible, e.g. if Zephyr was linked with
195 	 * CONFIG_ROM_START_OFFSET > BOOT_HEADER_SIZE_V1.
196 	 */
197 	if ((v1_raw->header_magic != BOOT_HEADER_MAGIC_V1) ||
198 	    (v1_raw->header_size < BOOT_HEADER_SIZE_V1)) {
199 		return -EIO;
200 	}
201 
202 	v1_raw->image_load_address =
203 		sys_le32_to_cpu(v1_raw->image_load_address);
204 	v1_raw->header_size = sys_le16_to_cpu(v1_raw->header_size);
205 	v1_raw->image_size = sys_le32_to_cpu(v1_raw->image_size);
206 	v1_raw->image_flags = sys_le32_to_cpu(v1_raw->image_flags);
207 	v1_raw->version.revision =
208 		sys_le16_to_cpu(v1_raw->version.revision);
209 	v1_raw->version.build_num =
210 		sys_le32_to_cpu(v1_raw->version.build_num);
211 
212 	return 0;
213 }
214 
boot_read_bank_header(uint8_t area_id,struct mcuboot_img_header * header,size_t header_size)215 int boot_read_bank_header(uint8_t area_id,
216 			  struct mcuboot_img_header *header,
217 			  size_t header_size)
218 {
219 	int rc;
220 	struct mcuboot_v1_raw_header v1_raw;
221 	struct mcuboot_img_sem_ver *sem_ver;
222 	size_t v1_min_size = (sizeof(uint32_t) +
223 			      sizeof(struct mcuboot_img_header_v1));
224 
225 	/*
226 	 * Only version 1 image headers are supported.
227 	 */
228 	if (header_size < v1_min_size) {
229 		return -ENOMEM;
230 	}
231 	rc = boot_read_v1_header(area_id, &v1_raw);
232 	if (rc) {
233 		return rc;
234 	}
235 
236 	/*
237 	 * Copy just the fields we care about into the return parameter.
238 	 *
239 	 * - header_magic:       skip (only used to check format)
240 	 * - image_load_address: skip (only matters for PIC code)
241 	 * - header_size:        skip (only used to check format)
242 	 * - image_size:         include
243 	 * - image_flags:        skip (all unsupported or not relevant)
244 	 * - version:            include
245 	 */
246 	header->mcuboot_version = 1U;
247 	header->h.v1.image_size = v1_raw.image_size;
248 	sem_ver = &header->h.v1.sem_ver;
249 	sem_ver->major = v1_raw.version.major;
250 	sem_ver->minor = v1_raw.version.minor;
251 	sem_ver->revision = v1_raw.version.revision;
252 	sem_ver->build_num = v1_raw.version.build_num;
253 	return 0;
254 }
255 
mcuboot_swap_type_multi(int image_index)256 int mcuboot_swap_type_multi(int image_index)
257 {
258 	return boot_swap_type_multi(image_index);
259 }
260 
mcuboot_swap_type(void)261 int mcuboot_swap_type(void)
262 {
263 #ifdef FLASH_AREA_IMAGE_SECONDARY
264 	return boot_swap_type();
265 #else
266 	return BOOT_SWAP_TYPE_NONE;
267 #endif
268 
269 }
270 
boot_request_upgrade(int permanent)271 int boot_request_upgrade(int permanent)
272 {
273 #ifdef FLASH_AREA_IMAGE_SECONDARY
274 	int rc;
275 
276 	rc = boot_set_pending(permanent);
277 	if (rc) {
278 		return -EFAULT;
279 	}
280 #endif /* FLASH_AREA_IMAGE_SECONDARY */
281 	return 0;
282 }
283 
boot_request_upgrade_multi(int image_index,int permanent)284 int boot_request_upgrade_multi(int image_index, int permanent)
285 {
286 	int rc;
287 
288 	rc = boot_set_pending_multi(image_index, permanent);
289 	if (rc) {
290 		return -EFAULT;
291 	}
292 	return 0;
293 }
294 
boot_is_img_confirmed(void)295 bool boot_is_img_confirmed(void)
296 {
297 	struct boot_swap_state state;
298 	const struct flash_area *fa;
299 	int rc;
300 
301 	rc = flash_area_open(ACTIVE_SLOT_FLASH_AREA_ID, &fa);
302 	if (rc) {
303 		return false;
304 	}
305 
306 	rc = boot_read_swap_state(fa, &state);
307 	if (rc != 0) {
308 		return false;
309 	}
310 
311 	if (state.magic == BOOT_MAGIC_UNSET) {
312 		/* This is initial/preprogramed image.
313 		 * Such image can neither be reverted nor physically confirmed.
314 		 * Treat this image as confirmed which ensures consistency
315 		 * with `boot_write_img_confirmed...()` procedures.
316 		 */
317 		return true;
318 	}
319 
320 	return state.image_ok == BOOT_FLAG_SET;
321 }
322 
boot_write_img_confirmed(void)323 int boot_write_img_confirmed(void)
324 {
325 	const struct flash_area *fa;
326 	int rc = 0;
327 
328 	if (flash_area_open(ACTIVE_SLOT_FLASH_AREA_ID, &fa) != 0) {
329 		return -EIO;
330 	}
331 
332 	rc = boot_set_next(fa, true, true);
333 
334 	flash_area_close(fa);
335 
336 	return rc;
337 }
338 
boot_write_img_confirmed_multi(int image_index)339 int boot_write_img_confirmed_multi(int image_index)
340 {
341 	int rc;
342 
343 	rc = boot_set_confirmed_multi(image_index);
344 	if (rc) {
345 		return -EIO;
346 	}
347 
348 	return 0;
349 }
350 
boot_erase_img_bank(uint8_t area_id)351 int boot_erase_img_bank(uint8_t area_id)
352 {
353 	const struct flash_area *fa;
354 	int rc;
355 
356 	rc = flash_area_open(area_id, &fa);
357 	if (rc) {
358 		return rc;
359 	}
360 
361 	rc = flash_area_flatten(fa, 0, fa->fa_size);
362 
363 	flash_area_close(fa);
364 
365 	return rc;
366 }
367 
boot_get_trailer_status_offset(size_t area_size)368 ssize_t boot_get_trailer_status_offset(size_t area_size)
369 {
370 	return (ssize_t)area_size - BOOT_MAGIC_SZ - BOOT_MAX_ALIGN * 2;
371 }
372 
boot_get_area_trailer_status_offset(uint8_t area_id)373 ssize_t boot_get_area_trailer_status_offset(uint8_t area_id)
374 {
375 	int rc;
376 	const struct flash_area *fa;
377 	ssize_t offset;
378 
379 	rc = flash_area_open(area_id, &fa);
380 	if (rc) {
381 		return rc;
382 	}
383 
384 	offset = boot_get_trailer_status_offset(fa->fa_size);
385 
386 	flash_area_close(fa);
387 
388 	if (offset < 0) {
389 		return -EFAULT;
390 	}
391 
392 	return offset;
393 }
394