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, §or_count,
219 §or_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