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