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