-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathdfu_target.c
220 lines (190 loc) · 5.07 KB
/
dfu_target.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/dfu/mcuboot.h>
#include <dfu/dfu_target.h>
#define DEF_DFU_TARGET(name) \
static const struct dfu_target dfu_target_ ## name = { \
.init = dfu_target_ ## name ## _init, \
.offset_get = dfu_target_## name ##_offset_get, \
.write = dfu_target_ ## name ## _write, \
.done = dfu_target_ ## name ## _done, \
.schedule_update = dfu_target_ ## name ## _schedule_update, \
.reset = dfu_target_ ## name ## _reset, \
}
#ifdef CONFIG_DFU_TARGET_MODEM_DELTA
#include "dfu/dfu_target_modem_delta.h"
DEF_DFU_TARGET(modem_delta);
#endif
#ifdef CONFIG_DFU_TARGET_MCUBOOT
#include "dfu/dfu_target_mcuboot.h"
DEF_DFU_TARGET(mcuboot);
#endif
#ifdef CONFIG_DFU_TARGET_FULL_MODEM
#include "dfu/dfu_target_full_modem.h"
DEF_DFU_TARGET(full_modem);
#endif
#ifdef CONFIG_DFU_TARGET_SMP
#include "dfu/dfu_target_smp.h"
DEF_DFU_TARGET(smp);
#endif
#ifdef CONFIG_DFU_TARGET_SUIT
#include "dfu/dfu_target_suit.h"
DEF_DFU_TARGET(suit);
#endif
#ifdef CONFIG_DFU_TARGET_CUSTOM
#include "dfu/dfu_target_custom.h"
DEF_DFU_TARGET(custom);
#endif
#define MIN_SIZE_IDENTIFY_BUF 32
LOG_MODULE_REGISTER(dfu_target, CONFIG_DFU_TARGET_LOG_LEVEL);
static const struct dfu_target *current_target;
static int current_img_num = -1;
enum dfu_target_image_type dfu_target_img_type(const void *const buf, size_t len)
{
if (len < MIN_SIZE_IDENTIFY_BUF) {
return DFU_TARGET_IMAGE_TYPE_NONE;
}
#ifdef CONFIG_DFU_TARGET_MCUBOOT
if (dfu_target_mcuboot_identify(buf)) {
return DFU_TARGET_IMAGE_TYPE_MCUBOOT;
}
#endif
#ifdef CONFIG_DFU_TARGET_MODEM_DELTA
if (dfu_target_modem_delta_identify(buf)) {
return DFU_TARGET_IMAGE_TYPE_MODEM_DELTA;
}
#endif
#ifdef CONFIG_DFU_TARGET_FULL_MODEM
if (dfu_target_full_modem_identify(buf)) {
return DFU_TARGET_IMAGE_TYPE_FULL_MODEM;
}
#endif
#ifdef CONFIG_DFU_TARGET_CUSTOM
if (dfu_target_custom_identify(buf)) {
return DFU_TARGET_IMAGE_TYPE_CUSTOM;
}
#endif
LOG_ERR("No supported image type found");
return DFU_TARGET_IMAGE_TYPE_NONE;
}
enum dfu_target_image_type dfu_target_smp_img_type_check(const void *const buf, size_t len)
{
#ifdef CONFIG_DFU_TARGET_SMP
if (len < MIN_SIZE_IDENTIFY_BUF) {
return DFU_TARGET_IMAGE_TYPE_NONE;
}
if (dfu_target_smp_identify(buf)) {
return DFU_TARGET_IMAGE_TYPE_SMP;
}
#endif
LOG_ERR("No supported image type found");
return DFU_TARGET_IMAGE_TYPE_NONE;
}
int dfu_target_init(int img_type, int img_num, size_t file_size, dfu_target_callback_t cb)
{
const struct dfu_target *new_target = NULL;
#ifdef CONFIG_DFU_TARGET_MCUBOOT
if (img_type == DFU_TARGET_IMAGE_TYPE_MCUBOOT) {
new_target = &dfu_target_mcuboot;
}
#endif
#ifdef CONFIG_DFU_TARGET_MODEM_DELTA
if (img_type == DFU_TARGET_IMAGE_TYPE_MODEM_DELTA) {
new_target = &dfu_target_modem_delta;
}
#endif
#ifdef CONFIG_DFU_TARGET_FULL_MODEM
if (img_type == DFU_TARGET_IMAGE_TYPE_FULL_MODEM) {
new_target = &dfu_target_full_modem;
}
#endif
#ifdef CONFIG_DFU_TARGET_SMP
if (img_type == DFU_TARGET_IMAGE_TYPE_SMP) {
new_target = &dfu_target_smp;
}
#endif
#ifdef CONFIG_DFU_TARGET_SUIT
if (img_type == DFU_TARGET_IMAGE_TYPE_SUIT) {
new_target = &dfu_target_suit;
}
#endif
#ifdef CONFIG_DFU_TARGET_CUSTOM
if (img_type == DFU_TARGET_IMAGE_TYPE_CUSTOM) {
new_target = &dfu_target_custom;
}
#endif
if (new_target == NULL) {
LOG_ERR("Unknown image type");
return -ENOTSUP;
}
/* The user is re-initializing with an previously aborted target
* or initializes the same target for a different image.
* Avoid re-initializing generally to ensure that the download can
* continue where it left off. Re-initializing is required for
* modem_delta upgrades to re-open the DFU socket that is closed on
* abort and to change the image number.
*/
if (new_target == current_target && img_type != DFU_TARGET_IMAGE_TYPE_MODEM_DELTA &&
img_type != DFU_TARGET_IMAGE_TYPE_SMP && current_img_num == img_num &&
img_type != DFU_TARGET_IMAGE_TYPE_SUIT) {
return 0;
}
current_target = new_target;
current_img_num = img_num;
return current_target->init(file_size, img_num, cb);
}
int dfu_target_offset_get(size_t *offset)
{
if (current_target == NULL) {
return -EACCES;
}
return current_target->offset_get(offset);
}
int dfu_target_write(const void *const buf, size_t len)
{
if (current_target == NULL || buf == NULL) {
return -EACCES;
}
return current_target->write(buf, len);
}
int dfu_target_done(bool successful)
{
int err;
if (current_target == NULL) {
return -EACCES;
}
err = current_target->done(successful);
if (err != 0) {
LOG_ERR("Unable to clean up dfu_target");
return err;
}
return 0;
}
int dfu_target_reset(void)
{
int err;
if (current_target == NULL) {
return -EACCES;
}
err = current_target->reset();
if (err != 0) {
LOG_ERR("Unable to clean up dfu_target");
return err;
}
current_target = NULL;
return 0;
}
int dfu_target_schedule_update(int img_num)
{
int err = 0;
if (current_target == NULL) {
return -EACCES;
}
err = current_target->schedule_update(img_num);
return err;
}