1 /*
2  * Copyright (c) 2017, 2020 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 <stddef.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <zephyr/dfu/flash_img.h>
13 #include <zephyr/storage/flash_map.h>
14 #include <zephyr/storage/stream_flash.h>
15 
16 #ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
17 #include <bootutil/bootutil_public.h>
18 #include <zephyr/dfu/mcuboot.h>
19 #endif
20 
21 #include <zephyr/devicetree.h>
22 #ifdef CONFIG_TRUSTED_EXECUTION_NONSECURE
23 	#define UPLOAD_FLASH_AREA_LABEL slot1_ns_partition
24 #else
25 #if FIXED_PARTITION_EXISTS(slot1_partition)
26 	#define UPLOAD_FLASH_AREA_LABEL slot1_partition
27 #else
28 	#define UPLOAD_FLASH_AREA_LABEL slot0_partition
29 #endif
30 #endif
31 
32 /* FIXED_PARTITION_ID() values used below are auto-generated by DT */
33 #define UPLOAD_FLASH_AREA_ID FIXED_PARTITION_ID(UPLOAD_FLASH_AREA_LABEL)
34 #define UPLOAD_FLASH_AREA_CONTROLLER \
35 	DT_GPARENT(DT_NODELABEL(UPLOAD_FLASH_AREA_LABEL))
36 
37 #if DT_NODE_HAS_PROP(UPLOAD_FLASH_AREA_CONTROLLER, write_block_size)
38 #define FLASH_WRITE_BLOCK_SIZE \
39 	DT_PROP(UPLOAD_FLASH_AREA_CONTROLLER, write_block_size)
40 
41 BUILD_ASSERT((CONFIG_IMG_BLOCK_BUF_SIZE % FLASH_WRITE_BLOCK_SIZE == 0),
42 	     "CONFIG_IMG_BLOCK_BUF_SIZE is not a multiple of "
43 	     "FLASH_WRITE_BLOCK_SIZE");
44 #endif
45 
flash_img_buffered_write(struct flash_img_context * ctx,const uint8_t * data,size_t len,bool flush)46 int flash_img_buffered_write(struct flash_img_context *ctx, const uint8_t *data,
47 			     size_t len, bool flush)
48 {
49 	int rc;
50 
51 	rc = stream_flash_buffered_write(&ctx->stream, data, len, flush);
52 	if (!flush) {
53 		return rc;
54 	}
55 
56 #ifdef CONFIG_IMG_ERASE_PROGRESSIVELY
57 	ssize_t status_offset = boot_get_trailer_status_offset(
58 		ctx->flash_area->fa_size);
59 	rc = stream_flash_erase_page(&ctx->stream,
60 				ctx->flash_area->fa_off +
61 				status_offset);
62 	if (rc) {
63 		return rc;
64 	}
65 #endif
66 
67 	flash_area_close(ctx->flash_area);
68 	ctx->flash_area = NULL;
69 
70 	return rc;
71 }
72 
flash_img_bytes_written(struct flash_img_context * ctx)73 size_t flash_img_bytes_written(struct flash_img_context *ctx)
74 {
75 	return stream_flash_bytes_written(&ctx->stream);
76 }
77 
flash_img_init_id(struct flash_img_context * ctx,uint8_t area_id)78 int flash_img_init_id(struct flash_img_context *ctx, uint8_t area_id)
79 {
80 	int rc;
81 	const struct device *flash_dev;
82 
83 	rc = flash_area_open(area_id,
84 			       (const struct flash_area **)&(ctx->flash_area));
85 	if (rc) {
86 		return rc;
87 	}
88 
89 	flash_dev = flash_area_get_device(ctx->flash_area);
90 
91 	return stream_flash_init(&ctx->stream, flash_dev, ctx->buf,
92 			CONFIG_IMG_BLOCK_BUF_SIZE, ctx->flash_area->fa_off,
93 			ctx->flash_area->fa_size, NULL);
94 }
95 
flash_img_init(struct flash_img_context * ctx)96 int flash_img_init(struct flash_img_context *ctx)
97 {
98 	return flash_img_init_id(ctx, UPLOAD_FLASH_AREA_ID);
99 }
100 
101 #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)102 int flash_img_check(struct flash_img_context *ctx,
103 		    const struct flash_img_check *fic,
104 		    uint8_t area_id)
105 {
106 	struct flash_area_check fac;
107 	int rc;
108 
109 	if (!ctx || !fic) {
110 		return -EINVAL;
111 	}
112 
113 	rc = flash_area_open(area_id,
114 			     (const struct flash_area **)&(ctx->flash_area));
115 	if (rc) {
116 		return rc;
117 	}
118 
119 	fac.match = fic->match;
120 	fac.clen = fic->clen;
121 	fac.off = 0;
122 	fac.rbuf = ctx->buf;
123 	fac.rblen = sizeof(ctx->buf);
124 
125 	rc = flash_area_check_int_sha256(ctx->flash_area, &fac);
126 
127 	flash_area_close(ctx->flash_area);
128 	ctx->flash_area = NULL;
129 
130 	return rc;
131 }
132 #endif
133