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