1 /*
2  * Copyright (c) 2017-2025 Nordic Semiconductor ASA
3  * Copyright (c) 2017 Linaro Limited
4  * Copyright (c) 2020 Gerson Fernando Budke <nandojve@gmail.com>
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 #include <zephyr/types.h>
9 #include <assert.h>
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <zephyr/logging/log.h>
14 #include <zephyr/dfu/mcuboot.h>
15 #include <zephyr/dfu/flash_img.h>
16 #include <zephyr/dfu/mcuboot.h>
17 #include <zephyr/storage/flash_map.h>
18 #include <zephyr/storage/stream_flash.h>
19 
20 LOG_MODULE_REGISTER(flash_img, CONFIG_IMG_MANAGER_LOG_LEVEL);
21 
22 #ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
23 #include <bootutil/bootutil_public.h>
24 #endif
25 
26 #define FIXED_PARTITION_IS_RUNNING_APP_PARTITION(label) \
27 	(FIXED_PARTITION_OFFSET(label) == CONFIG_FLASH_LOAD_OFFSET)
28 
29 #include <zephyr/devicetree.h>
30 #ifdef CONFIG_TRUSTED_EXECUTION_NONSECURE
31 #define UPLOAD_FLASH_AREA_LABEL slot1_ns_partition
32 #else
33 #if FIXED_PARTITION_EXISTS(slot1_partition) && \
34 	FIXED_PARTITION_IS_RUNNING_APP_PARTITION(slot0_partition)
35 #define UPLOAD_FLASH_AREA_LABEL slot1_partition
36 #else
37 #define UPLOAD_FLASH_AREA_LABEL slot0_partition
38 #endif
39 #endif
40 
41 #ifdef CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD
42 /* For RAM LOAD mode, the active image must be fetched from the bootloader */
43 #define UPLOAD_FLASH_AREA_ID flash_img_get_upload_slot()
44 #else
45 /* FIXED_PARTITION_ID() values used below are auto-generated by DT */
46 #define UPLOAD_FLASH_AREA_ID FIXED_PARTITION_ID(UPLOAD_FLASH_AREA_LABEL)
47 #endif /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD */
48 #define UPLOAD_FLASH_AREA_CONTROLLER \
49 	DT_GPARENT(DT_NODELABEL(UPLOAD_FLASH_AREA_LABEL))
50 
51 #if DT_NODE_HAS_PROP(UPLOAD_FLASH_AREA_CONTROLLER, write_block_size)
52 #define FLASH_WRITE_BLOCK_SIZE \
53 	DT_PROP(UPLOAD_FLASH_AREA_CONTROLLER, write_block_size)
54 
55 BUILD_ASSERT((CONFIG_IMG_BLOCK_BUF_SIZE % FLASH_WRITE_BLOCK_SIZE == 0),
56 	     "CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of "
57 	     "FLASH_WRITE_BLOCK_SIZE");
58 #endif
59 
60 #define FLASH_CHECK_ERASED_BUFFER_SIZE 16
61 #define ERASED_VAL_32(x) (((x) << 24) | ((x) << 16) | ((x) << 8) | (x))
62 
scramble_mcuboot_trailer(struct flash_img_context * ctx)63 static int scramble_mcuboot_trailer(struct flash_img_context *ctx)
64 {
65 	int rc = 0;
66 
67 #ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
68 	if (stream_flash_bytes_written(&ctx->stream) == 0) {
69 		off_t toff = boot_get_trailer_status_offset(ctx->flash_area->fa_size);
70 		off_t offset;
71 		size_t size;
72 		const struct flash_parameters *fparams =
73 			flash_get_parameters(flash_area_get_device(ctx->flash_area));
74 #ifdef CONFIG_STREAM_FLASH_ERASE
75 		/* for erasable devices prgressive-erase works only along with
76 		 * CONFIG_STREAM_FLASH_ERASE option.
77 		 */
78 		if (flash_params_get_erase_cap(fparams) & FLASH_ERASE_C_EXPLICIT) {
79 			/* On devices with explicit erase we are aligning to page
80 			 * layout.
81 			 */
82 			struct flash_pages_info info;
83 
84 			rc = flash_get_page_info_by_offs(flash_area_get_device(ctx->flash_area),
85 							 toff, &info);
86 			if (rc != 0) {
87 				return rc;
88 			}
89 			offset = info.start_offset;
90 			size = info.size;
91 
92 		} else
93 #endif
94 		{
95 			/* On devices with no erase, we are aligning to write block
96 			 * size.
97 			 */
98 			offset = (toff + fparams->write_block_size - 1) &
99 				 ~(fparams->write_block_size - 1);
100 			/* No alignment correction needed here, offset is corrected already
101 			 * and, size should be aligned.
102 			 */
103 			size = ctx->flash_area->fa_size - offset;
104 		}
105 
106 		rc = flash_area_flatten(ctx->flash_area, offset, size);
107 	}
108 #endif
109 
110 	return rc;
111 }
112 
113 
flash_img_buffered_write(struct flash_img_context * ctx,const uint8_t * data,size_t len,bool flush)114 int flash_img_buffered_write(struct flash_img_context *ctx, const uint8_t *data,
115 			     size_t len, bool flush)
116 {
117 	int rc;
118 
119 	/* If there is a need to erase the trailer, that should happen before any
120 	 * write is done to partition.
121 	 */
122 	rc = scramble_mcuboot_trailer(ctx);
123 	if (rc != 0) {
124 		return rc;
125 	}
126 
127 
128 	/* if CONFIG_IMG_ERASE_PROGRESSIVELY is enabled the enabled CONFIG_STREAM_FLASH_ERASE
129 	 * ensures that stream_flash erases flash progresively.
130 	 */
131 	rc = stream_flash_buffered_write(&ctx->stream, data, len, flush);
132 	if (!flush) {
133 		return rc;
134 	}
135 
136 	flash_area_close(ctx->flash_area);
137 	ctx->flash_area = NULL;
138 
139 	return rc;
140 }
141 
flash_img_bytes_written(struct flash_img_context * ctx)142 size_t flash_img_bytes_written(struct flash_img_context *ctx)
143 {
144 	return stream_flash_bytes_written(&ctx->stream);
145 }
146 
147 #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET)
148 /**
149  * Determines if the specified area of flash is completely unwritten.
150  *
151  * @param	fa	pointer to flash area to scan
152  *
153  * @return	0	when not empty, 1 when empty, negative errno code on error.
154  */
flash_check_erased(const struct flash_area * fa)155 static int flash_check_erased(const struct flash_area *fa)
156 {
157 	uint32_t data[FLASH_CHECK_ERASED_BUFFER_SIZE];
158 	off_t addr;
159 	off_t end;
160 	int bytes_to_read;
161 	int rc;
162 	int i;
163 	uint8_t erased_val;
164 	uint32_t erased_val_32;
165 
166 	assert(fa->fa_size % sizeof(erased_val_32) == 0);
167 
168 	erased_val = flash_area_erased_val(fa);
169 	erased_val_32 = ERASED_VAL_32(erased_val);
170 
171 	end = fa->fa_size;
172 	for (addr = 0; addr < end; addr += sizeof(data)) {
173 		if (end - addr < sizeof(data)) {
174 			bytes_to_read = end - addr;
175 		} else {
176 			bytes_to_read = sizeof(data);
177 		}
178 
179 		rc = flash_area_read(fa, addr, data, bytes_to_read);
180 
181 		if (rc < 0) {
182 			LOG_ERR("Failed to read data from flash area: %d", rc);
183 			return rc;
184 		}
185 
186 		for (i = 0; i < bytes_to_read / sizeof(erased_val_32); i++) {
187 			if (data[i] != erased_val_32) {
188 				return 0;
189 			}
190 		}
191 	}
192 
193 	return 1;
194 }
195 #endif
196 
flash_img_init_id(struct flash_img_context * ctx,uint8_t area_id)197 int flash_img_init_id(struct flash_img_context *ctx, uint8_t area_id)
198 {
199 	int rc;
200 	const struct device *flash_dev;
201 #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET)
202 	uint32_t sector_count = SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN;
203 	struct flash_sector sector_data;
204 #endif
205 
206 	rc = flash_area_open(area_id,
207 			       (const struct flash_area **)&(ctx->flash_area));
208 	if (rc) {
209 		return rc;
210 	}
211 
212 	flash_dev = flash_area_get_device(ctx->flash_area);
213 
214 #if defined(CONFIG_MCUBOOT_BOOTLOADER_MODE_SWAP_USING_OFFSET)
215 	/* Query size of first sector in flash for upgrade slot, so it can be erased, and begin
216 	 * upload started at the second sector
217 	 */
218 	rc = flash_area_sectors((const struct flash_area *)ctx->flash_area, &sector_count,
219 				&sector_data);
220 
221 	if (rc && rc != -ENOMEM) {
222 		flash_area_close(ctx->flash_area);
223 		ctx->flash_area = NULL;
224 		return rc;
225 	} else if (sector_count != SWAP_USING_OFFSET_SECTOR_UPDATE_BEGIN) {
226 		flash_area_close(ctx->flash_area);
227 		ctx->flash_area = NULL;
228 		return -ENOENT;
229 	}
230 
231 	if (!flash_check_erased((const struct flash_area *)ctx->flash_area)) {
232 		/* Flash is not empty, therefore flatten/erase the area to prevent issues when
233 		 * the firmware update process begins
234 		 */
235 		rc = flash_area_flatten((const struct flash_area *)ctx->flash_area, 0,
236 					sector_data.fs_size);
237 
238 		if (rc) {
239 			flash_area_close(ctx->flash_area);
240 			ctx->flash_area = NULL;
241 			return rc;
242 		}
243 	}
244 
245 	return stream_flash_init(&ctx->stream, flash_dev, ctx->buf, CONFIG_IMG_BLOCK_BUF_SIZE,
246 				 (ctx->flash_area->fa_off + sector_data.fs_size),
247 				 (ctx->flash_area->fa_size - sector_data.fs_size), NULL);
248 #else
249 	return stream_flash_init(&ctx->stream, flash_dev, ctx->buf,
250 			CONFIG_IMG_BLOCK_BUF_SIZE, ctx->flash_area->fa_off,
251 			ctx->flash_area->fa_size, NULL);
252 #endif
253 }
254 
255 #ifdef CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD
flash_img_get_upload_slot(void)256 uint8_t flash_img_get_upload_slot(void)
257 {
258 	uint8_t slot;
259 
260 	slot = boot_fetch_active_slot();
261 
262 	if (slot == FIXED_PARTITION_ID(slot0_partition)) {
263 		return FIXED_PARTITION_ID(slot1_partition);
264 	}
265 	return FIXED_PARTITION_ID(slot0_partition);
266 }
267 #else  /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD */
flash_img_get_upload_slot(void)268 uint8_t flash_img_get_upload_slot(void)
269 {
270 	return UPLOAD_FLASH_AREA_ID;
271 }
272 #endif /* CONFIG_MCUBOOT_BOOTLOADER_MODE_RAM_LOAD */
273 
flash_img_init(struct flash_img_context * ctx)274 int flash_img_init(struct flash_img_context *ctx)
275 {
276 	return flash_img_init_id(ctx, UPLOAD_FLASH_AREA_ID);
277 }
278 
279 #if defined(CONFIG_IMG_ENABLE_IMAGE_CHECK)
flash_img_check(struct flash_img_context * ctx,const struct flash_img_check * fic,uint8_t area_id)280 int flash_img_check(struct flash_img_context *ctx,
281 		    const struct flash_img_check *fic,
282 		    uint8_t area_id)
283 {
284 	struct flash_area_check fac;
285 	int rc;
286 
287 	if (!ctx || !fic) {
288 		return -EINVAL;
289 	}
290 
291 	rc = flash_area_open(area_id,
292 			     (const struct flash_area **)&(ctx->flash_area));
293 	if (rc) {
294 		return rc;
295 	}
296 
297 	fac.match = fic->match;
298 	fac.clen = fic->clen;
299 	fac.off = boot_get_image_start_offset(area_id);
300 	fac.rbuf = ctx->buf;
301 	fac.rblen = sizeof(ctx->buf);
302 
303 	rc = flash_area_check_int_sha256(ctx->flash_area, &fac);
304 
305 	flash_area_close(ctx->flash_area);
306 	ctx->flash_area = NULL;
307 
308 	return rc;
309 }
310 #endif
311