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