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