1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 #include <zephyr/bluetooth/mesh.h>
9 #include <common/bt_str.h>
10 #include "dfu_slot.h"
11 #include "dfd.h"
12 #include "dfu.h"
13 #include "dfd_srv_internal.h"
14 #include "net.h"
15 #include "transport.h"
16 
17 #define LOG_LEVEL CONFIG_BT_MESH_DFU_LOG_LEVEL
18 #include <zephyr/logging/log.h>
19 LOG_MODULE_REGISTER(bt_mesh_dfd_srv);
20 
21 #define ERASE_BLOCK_SIZE DT_PROP(DT_CHOSEN(zephyr_flash), erase_block_size)
22 
23 #define DFD_UPLOAD_STATUS_MSG_MAXLEN (5 + CONFIG_BT_MESH_DFU_FWID_MAXLEN)
24 
25 BUILD_ASSERT((DFD_UPLOAD_STATUS_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_UPLOAD_STATUS) +
26 	      BT_MESH_MIC_SHORT) <= BT_MESH_TX_SDU_MAX,
27 	     "The Firmware Distribution Upload Status message does not fit into the maximum "
28 	     "outgoing SDU size.");
29 
30 #define DFD_UPLOAD_START_MSG_MAXLEN (16 + CONFIG_BT_MESH_DFU_FWID_MAXLEN + \
31 				     CONFIG_BT_MESH_DFU_METADATA_MAXLEN)
32 
33 BUILD_ASSERT((DFD_UPLOAD_START_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_UPLOAD_START) +
34 	      BT_MESH_MIC_SHORT) <= BT_MESH_RX_SDU_MAX,
35 	     "The Firmware Distribution Upload Start message does not fit into the maximum "
36 	     "incoming SDU size.");
37 
38 #define DFD_RECEIVERS_LIST_MSG_MAXLEN (4 + CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX * 5)
39 
40 BUILD_ASSERT((DFD_RECEIVERS_LIST_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_RECEIVERS_LIST) +
41 	      BT_MESH_MIC_SHORT) <= BT_MESH_TX_SDU_MAX,
42 	     "The Firmware Distribution Receivers List message does not fit into the maximum "
43 	     "outgoing SDU size.");
44 
45 #define DFD_RECEIVERS_ADD_MSG_MAXLEN (CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX * 3)
46 
47 BUILD_ASSERT((DFD_RECEIVERS_ADD_MSG_MAXLEN + BT_MESH_MODEL_OP_LEN(BT_MESH_DFD_OP_RECEIVERS_ADD) +
48 	      BT_MESH_MIC_SHORT) <= BT_MESH_RX_SDU_MAX,
49 	     "The Firmware Distribution Receivers Add message does not fit into the maximum "
50 	     "incoming SDU size.");
51 
52 struct slot_search_ctx {
53 	off_t offset;
54 	size_t size;
55 	bool failed;
56 };
57 
dfd_phase_set(struct bt_mesh_dfd_srv * srv,enum bt_mesh_dfd_phase new_phase)58 static void dfd_phase_set(struct bt_mesh_dfd_srv *srv,
59 			  enum bt_mesh_dfd_phase new_phase)
60 {
61 	srv->phase = new_phase;
62 
63 	if (srv->cb && srv->cb->phase) {
64 		srv->cb->phase(srv, srv->phase);
65 	}
66 }
67 
target_get(struct bt_mesh_dfd_srv * srv,uint16_t addr)68 static struct bt_mesh_dfu_target *target_get(struct bt_mesh_dfd_srv *srv,
69 					     uint16_t addr)
70 {
71 	for (int i = 0; i < srv->target_cnt; ++i) {
72 		if (addr == srv->targets[i].blob.addr) {
73 			return &srv->targets[i];
74 		}
75 	}
76 
77 	return NULL;
78 }
79 
is_busy(const struct bt_mesh_dfd_srv * srv)80 static bool is_busy(const struct bt_mesh_dfd_srv *srv)
81 {
82 	return srv->phase == BT_MESH_DFD_PHASE_TRANSFER_ACTIVE ||
83 	       srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUCCESS ||
84 	       srv->phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE;
85 }
86 
upload_is_busy(const struct bt_mesh_dfd_srv * srv)87 static bool upload_is_busy(const struct bt_mesh_dfd_srv *srv)
88 {
89 	return bt_mesh_blob_srv_is_busy(&srv->upload.blob) ||
90 	       srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE;
91 }
92 
slot_del(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot)93 static int slot_del(struct bt_mesh_dfd_srv *srv, const struct bt_mesh_dfu_slot *slot)
94 {
95 	if (srv->cb && srv->cb->del) {
96 		srv->cb->del(srv, slot);
97 	}
98 
99 	return bt_mesh_dfu_slot_del(slot);
100 }
101 
receivers_status_rsp(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status)102 static void receivers_status_rsp(struct bt_mesh_dfd_srv *srv,
103 				 struct bt_mesh_msg_ctx *ctx,
104 				 enum bt_mesh_dfd_status status)
105 {
106 	BT_MESH_MODEL_BUF_DEFINE(buf, BT_MESH_DFD_OP_RECEIVERS_STATUS, 3);
107 	bt_mesh_model_msg_init(&buf, BT_MESH_DFD_OP_RECEIVERS_STATUS);
108 
109 	net_buf_simple_add_u8(&buf, status);
110 	net_buf_simple_add_le16(&buf, srv->target_cnt);
111 
112 	bt_mesh_model_send(srv->mod, ctx, &buf, NULL, NULL);
113 }
114 
handle_receivers_add(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)115 static int handle_receivers_add(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
116 				struct net_buf_simple *buf)
117 {
118 	enum bt_mesh_dfd_status status = BT_MESH_DFD_SUCCESS;
119 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
120 
121 	if (buf->len % 3) {
122 		return -EINVAL;
123 	}
124 
125 	if (bt_mesh_dfu_cli_is_busy(&srv->dfu)) {
126 		receivers_status_rsp(srv, ctx,
127 				     BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION);
128 		return 0;
129 	}
130 
131 	while (buf->len >= 3 && status == BT_MESH_DFD_SUCCESS) {
132 		uint8_t img_idx;
133 		uint16_t addr;
134 
135 		addr = net_buf_simple_pull_le16(buf);
136 		img_idx = net_buf_simple_pull_u8(buf);
137 
138 		status = bt_mesh_dfd_srv_receiver_add(srv, addr, img_idx);
139 	}
140 
141 	receivers_status_rsp(srv, ctx, status);
142 
143 	return 0;
144 }
145 
handle_receivers_delete_all(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)146 static int handle_receivers_delete_all(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
147 				       struct net_buf_simple *buf)
148 {
149 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
150 
151 	receivers_status_rsp(srv, ctx, bt_mesh_dfd_srv_receivers_delete_all(srv));
152 
153 	return 0;
154 }
155 
handle_receivers_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)156 static int handle_receivers_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
157 				struct net_buf_simple *buf)
158 {
159 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
160 	uint16_t first, cnt;
161 	uint8_t progress;
162 	int i;
163 
164 	first = net_buf_simple_pull_le16(buf);
165 	cnt = net_buf_simple_pull_le16(buf);
166 	if (cnt == 0) {
167 		return -EINVAL;
168 	}
169 
170 	/* Create a buffer that can fit the full target list, maxing out at TX_SDU_MAX: */
171 	NET_BUF_SIMPLE_DEFINE(
172 		rsp, BT_MESH_MODEL_BUF_LEN(BT_MESH_DFD_OP_RECEIVERS_LIST,
173 					   DFD_RECEIVERS_LIST_MSG_MAXLEN));
174 	bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_RECEIVERS_LIST);
175 
176 	net_buf_simple_add_le16(&rsp, srv->target_cnt);
177 	net_buf_simple_add_le16(&rsp, first);
178 
179 	cnt = MIN(cnt, srv->target_cnt - first);
180 	progress = bt_mesh_dfu_cli_progress(&srv->dfu) / 2;
181 
182 	for (i = 0; i < cnt && net_buf_simple_tailroom(&rsp) >= 5 + BT_MESH_MIC_SHORT; i++) {
183 		const struct bt_mesh_dfu_target *t = &srv->targets[i + first];
184 
185 		net_buf_simple_add_le32(
186 			&rsp, ((t->blob.addr & BIT_MASK(15)) |
187 			       ((t->phase & BIT_MASK(4)) << 15U) |
188 			       ((t->status & BIT_MASK(3)) << 19U) |
189 			       ((t->blob.status & BIT_MASK(4)) << 22U) |
190 			       ((progress & BIT_MASK(6)) << 26U)));
191 		net_buf_simple_add_u8(&rsp, t->img_idx);
192 	}
193 
194 	bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
195 
196 	return 0;
197 }
198 
slot_space_cb(const struct bt_mesh_dfu_slot * slot,void * user_data)199 static enum bt_mesh_dfu_iter slot_space_cb(const struct bt_mesh_dfu_slot *slot,
200 					   void *user_data)
201 {
202 	size_t *total = user_data;
203 
204 	*total += slot->size;
205 
206 	return BT_MESH_DFU_ITER_CONTINUE;
207 }
208 
handle_capabilities_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)209 static int handle_capabilities_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
210 				   struct net_buf_simple *buf)
211 {
212 	size_t size = 0;
213 
214 	BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_CAPABILITIES_STATUS, 17);
215 	bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_CAPABILITIES_STATUS);
216 
217 	net_buf_simple_add_le16(&rsp, CONFIG_BT_MESH_DFD_SRV_TARGETS_MAX);
218 	net_buf_simple_add_le16(&rsp, CONFIG_BT_MESH_DFU_SLOT_CNT);
219 	net_buf_simple_add_le32(&rsp, CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE);
220 	net_buf_simple_add_le32(&rsp, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE);
221 
222 	/* Remaining size */
223 	(void)bt_mesh_dfu_slot_foreach(slot_space_cb, &size);
224 	size = MIN(size, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE);
225 
226 	net_buf_simple_add_le32(&rsp, CONFIG_BT_MESH_DFD_SRV_SLOT_SPACE - size);
227 
228 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
229 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
230 
231 	if (srv->oob_schemes.count > 0) {
232 		net_buf_simple_add_u8(&rsp, 1);
233 		net_buf_simple_add_mem(&rsp, srv->oob_schemes.schemes,
234 				       srv->oob_schemes.count);
235 	} else
236 #endif
237 	{
238 		net_buf_simple_add_u8(&rsp, 0);
239 	}
240 
241 	bt_mesh_model_send(mod, ctx, &rsp, NULL, NULL);
242 
243 	return 0;
244 }
245 
status_rsp(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status)246 static void status_rsp(struct bt_mesh_dfd_srv *srv, struct bt_mesh_msg_ctx *ctx,
247 		       enum bt_mesh_dfd_status status)
248 {
249 	BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_STATUS, 12);
250 	bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_STATUS);
251 
252 	net_buf_simple_add_u8(&rsp, status);
253 	net_buf_simple_add_u8(&rsp, srv->phase);
254 
255 	if (srv->phase == BT_MESH_DFD_PHASE_IDLE || !srv->dfu.xfer.slot) {
256 		bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
257 		return;
258 	}
259 
260 	net_buf_simple_add_le16(&rsp, srv->inputs.group);
261 	net_buf_simple_add_le16(&rsp, srv->inputs.app_idx);
262 	net_buf_simple_add_u8(&rsp, srv->inputs.ttl);
263 	net_buf_simple_add_le16(&rsp, srv->inputs.timeout_base);
264 	net_buf_simple_add_u8(&rsp, ((srv->dfu.xfer.blob.mode & BIT_MASK(2)) |
265 				     ((srv->apply & BIT_MASK(1)) << 2)));
266 	net_buf_simple_add_le16(&rsp, srv->slot_idx);
267 
268 	bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
269 }
270 
handle_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)271 static int handle_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
272 		      struct net_buf_simple *buf)
273 {
274 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
275 
276 	status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
277 
278 	return 0;
279 }
280 
handle_start(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)281 static int handle_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
282 			struct net_buf_simple *buf)
283 {
284 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
285 	struct bt_mesh_dfd_start_params params;
286 	uint8_t byte;
287 
288 	params.app_idx = net_buf_simple_pull_le16(buf);
289 	params.ttl = net_buf_simple_pull_u8(buf);
290 	params.timeout_base = net_buf_simple_pull_le16(buf);
291 	byte = net_buf_simple_pull_u8(buf);
292 	params.xfer_mode = byte & BIT_MASK(2);
293 	params.apply = (byte >> 2U) & BIT_MASK(1);
294 	params.slot_idx = net_buf_simple_pull_le16(buf);
295 
296 	if (buf->len == 16) {
297 		/* TODO: Virtual addresses not supported. */
298 		status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
299 		return 0;
300 	}
301 
302 	if (buf->len != 2) {
303 		return -EINVAL;
304 	}
305 
306 	params.group = net_buf_simple_pull_le16(buf);
307 
308 	status_rsp(srv, ctx, bt_mesh_dfd_srv_start(srv, &params));
309 
310 	return 0;
311 }
312 
handle_suspend(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)313 static int handle_suspend(const struct bt_mesh_model *mod,
314 			   struct bt_mesh_msg_ctx *ctx,
315 			   struct net_buf_simple *buf)
316 {
317 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
318 
319 	status_rsp(srv, ctx, bt_mesh_dfd_srv_suspend(srv));
320 
321 	return 0;
322 }
323 
handle_cancel(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)324 static int handle_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
325 			 struct net_buf_simple *buf)
326 {
327 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
328 
329 	bt_mesh_dfd_srv_cancel(srv, ctx);
330 
331 	return 0;
332 }
333 
handle_apply(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)334 static int handle_apply(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
335 			struct net_buf_simple *buf)
336 {
337 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
338 
339 	status_rsp(srv, ctx, bt_mesh_dfd_srv_apply(srv));
340 
341 	return 0;
342 }
343 
upload_status_rsp_with_progress(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status,uint8_t progress)344 static void upload_status_rsp_with_progress(struct bt_mesh_dfd_srv *srv,
345 					    struct bt_mesh_msg_ctx *ctx,
346 					    enum bt_mesh_dfd_status status,
347 					    uint8_t progress)
348 {
349 	BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_UPLOAD_STATUS,
350 				 DFD_UPLOAD_STATUS_MSG_MAXLEN);
351 	bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_UPLOAD_STATUS);
352 
353 	net_buf_simple_add_u8(&rsp, status);
354 	net_buf_simple_add_u8(&rsp, srv->upload.phase);
355 
356 	if (srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_IDLE ||
357 	    !srv->upload.slot) {
358 		bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
359 		return;
360 	}
361 
362 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
363 	if (srv->upload.is_oob) {
364 		net_buf_simple_add_u8(&rsp, progress | BIT(7));
365 		net_buf_simple_add_mem(&rsp, srv->upload.oob.current_fwid,
366 				       srv->upload.oob.current_fwid_len);
367 	} else
368 #endif
369 	{
370 		net_buf_simple_add_u8(&rsp, progress);
371 		net_buf_simple_add_mem(&rsp, srv->upload.slot->fwid,
372 				       srv->upload.slot->fwid_len);
373 	}
374 
375 	bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
376 }
377 
upload_status_rsp(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status)378 static void upload_status_rsp(struct bt_mesh_dfd_srv *srv,
379 			      struct bt_mesh_msg_ctx *ctx,
380 			      enum bt_mesh_dfd_status status)
381 {
382 	uint8_t progress;
383 
384 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
385 	if (srv->upload.is_oob) {
386 		progress = srv->cb->oob_progress_get(srv, srv->upload.slot);
387 	} else
388 #endif
389 	{
390 		progress = bt_mesh_blob_srv_progress(&srv->upload.blob);
391 	}
392 
393 	upload_status_rsp_with_progress(srv, ctx, status, progress);
394 }
395 
handle_upload_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)396 static int handle_upload_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
397 			     struct net_buf_simple *buf)
398 {
399 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
400 
401 	upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
402 
403 	return 0;
404 }
405 
set_upload_fwid(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,const uint8_t * fwid,size_t fwid_len)406 static inline int set_upload_fwid(struct bt_mesh_dfd_srv *srv, struct bt_mesh_msg_ctx *ctx,
407 				  const uint8_t *fwid, size_t fwid_len)
408 {
409 	int err = bt_mesh_dfu_slot_fwid_set(srv->upload.slot, fwid, fwid_len);
410 
411 	switch (err) {
412 	case -EFBIG: /* Fwid too long */
413 	case -EALREADY: /* Other server is in progress with this fwid */
414 		bt_mesh_dfu_slot_release(srv->upload.slot);
415 		srv->upload.slot = NULL;
416 		upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
417 		break;
418 	case -EEXIST: /* Img with this fwid already is in list */
419 		srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS;
420 		bt_mesh_dfu_slot_release(srv->upload.slot);
421 
422 		err = bt_mesh_dfu_slot_get(fwid, fwid_len, &srv->upload.slot);
423 		if (!err) {
424 			upload_status_rsp_with_progress(srv, ctx, BT_MESH_DFD_SUCCESS, 100);
425 		} else {
426 			srv->upload.slot = NULL;
427 			upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
428 		}
429 		break;
430 	case 0:
431 		srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE;
432 		break;
433 	case -EINVAL: /* Slot in wrong state. */
434 	default:
435 		break;
436 	}
437 
438 	return err;
439 }
440 
handle_upload_start(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)441 static int handle_upload_start(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
442 			       struct net_buf_simple *buf)
443 {
444 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
445 	size_t meta_len, fwid_len, size;
446 	const uint8_t *meta, *fwid;
447 	uint16_t timeout_base;
448 	uint64_t blob_id;
449 	int err;
450 	uint8_t ttl;
451 
452 	ttl = net_buf_simple_pull_u8(buf);
453 	timeout_base = net_buf_simple_pull_le16(buf);
454 	blob_id = net_buf_simple_pull_le64(buf);
455 	size = net_buf_simple_pull_le32(buf);
456 	meta_len = net_buf_simple_pull_u8(buf);
457 	if (buf->len < meta_len) {
458 		return -EINVAL;
459 	}
460 
461 	meta = net_buf_simple_pull_mem(buf, meta_len);
462 	fwid_len = buf->len;
463 	fwid = net_buf_simple_pull_mem(buf, fwid_len);
464 
465 	LOG_DBG("Upload Start: size: %d, fwid: %s, metadata: %s", size, bt_hex(fwid, fwid_len),
466 		bt_hex(meta, meta_len));
467 
468 	if (size > CONFIG_BT_MESH_DFD_SRV_SLOT_MAX_SIZE) {
469 		upload_status_rsp(srv, ctx,
470 				  BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES);
471 		return 0;
472 	}
473 
474 	if (upload_is_busy(srv)) {
475 		if (!srv->upload.slot) {
476 			LOG_WRN("Busy with no upload slot");
477 			upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
478 			return 0;
479 		}
480 
481 		if (srv->upload.slot->fwid_len == fwid_len &&
482 		    !memcmp(srv->upload.slot->fwid, fwid, fwid_len) &&
483 		    srv->upload.slot->metadata_len == meta_len &&
484 		    !memcmp(srv->upload.slot->metadata, meta, meta_len) &&
485 		    srv->upload.blob.state.xfer.id == blob_id &&
486 		    srv->upload.blob.state.ttl == ttl &&
487 		    srv->upload.blob.state.timeout_base == timeout_base
488 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
489 		    && !srv->upload.is_oob
490 #endif
491 		    ) {
492 			LOG_DBG("Duplicate upload start");
493 			upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
494 			return 0;
495 		}
496 
497 		LOG_WRN("Upload already in progress");
498 		upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD);
499 		return 0;
500 	}
501 
502 	/* This will be a no-op if the slot state isn't RESERVED, which is
503 	 * what we want.
504 	 */
505 	if (srv->upload.slot) {
506 		bt_mesh_dfu_slot_release(srv->upload.slot);
507 	}
508 
509 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
510 	srv->upload.is_oob = false;
511 #endif
512 	srv->upload.slot = bt_mesh_dfu_slot_reserve();
513 
514 	if (!srv->upload.slot) {
515 		LOG_WRN("No space for slot");
516 		upload_status_rsp(srv, ctx,
517 				  BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES);
518 		return 0;
519 	}
520 
521 	err = set_upload_fwid(srv, ctx, fwid, fwid_len);
522 	if (err) {
523 		return err;
524 	}
525 
526 	err = bt_mesh_dfu_slot_info_set(srv->upload.slot, size, meta, meta_len);
527 	switch (err) {
528 	case -EFBIG:
529 		upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
530 		break;
531 	case 0:
532 		break;
533 	default:
534 		return err;
535 	}
536 
537 	srv->io = NULL;
538 	err = srv->cb->recv(srv, srv->upload.slot, &srv->io);
539 	if (err || !srv->io) {
540 		LOG_ERR("App rejected upload. err: %d io: %p", err, srv->io);
541 		bt_mesh_dfu_slot_release(srv->upload.slot);
542 		upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
543 		return 0;
544 	}
545 
546 	err = bt_mesh_blob_srv_recv(&srv->upload.blob, blob_id, srv->io, ttl,
547 				    timeout_base);
548 	if (err) {
549 		LOG_ERR("BLOB Server rejected upload (err: %d)", err);
550 		bt_mesh_dfu_slot_release(srv->upload.slot);
551 		upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
552 		return 0;
553 	}
554 
555 	LOG_DBG("%s", bt_hex(fwid, fwid_len));
556 
557 	srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE;
558 	upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
559 
560 	return 0;
561 }
562 
handle_upload_start_oob(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)563 static int handle_upload_start_oob(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
564 				   struct net_buf_simple *buf)
565 {
566 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
567 	uint8_t uri_len;
568 	uint8_t *uri;
569 	uint16_t fwid_len;
570 	uint8_t *fwid;
571 
572 	uri_len = net_buf_simple_pull_u8(buf);
573 
574 	if (uri_len > buf->len) {
575 		return -EINVAL;
576 	}
577 
578 	uri = net_buf_simple_pull_mem(buf, uri_len);
579 	fwid_len = buf->len;
580 	fwid = net_buf_simple_pull_mem(buf, fwid_len);
581 
582 	LOG_DBG("Upload OOB Start");
583 	LOG_HEXDUMP_DBG(uri, uri_len, "URI");
584 	LOG_HEXDUMP_DBG(fwid, fwid_len, "FWID");
585 
586 	if (upload_is_busy(srv)) {
587 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
588 		if (srv->upload.is_oob &&
589 		    uri_len == srv->upload.oob.uri_len &&
590 		    fwid_len == srv->upload.oob.current_fwid_len &&
591 		    !memcmp(uri, srv->upload.oob.uri, uri_len) &&
592 		    !memcmp(fwid, srv->upload.oob.current_fwid, fwid_len)) {
593 			/* Same image, return SUCCESS for idempotency */
594 			upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
595 			return 0;
596 		}
597 #endif
598 		upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_BUSY_WITH_UPLOAD);
599 		return 0;
600 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
601 	} else if (srv->upload.is_oob && srv->upload.is_pending_oob_check) {
602 		/* Ignore the request if we didn't confirm the previous one. */
603 		return 0;
604 #endif
605 	}
606 
607 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
608 	if (uri_len > CONFIG_BT_MESH_DFU_URI_MAXLEN ||
609 	    fwid_len > CONFIG_BT_MESH_DFU_FWID_MAXLEN) {
610 		upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
611 		return 0;
612 	}
613 
614 	struct bt_mesh_dfu_slot *slot = bt_mesh_dfu_slot_reserve();
615 
616 	if (slot == NULL) {
617 		upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES);
618 		return 0;
619 	}
620 
621 	/* This will be a no-op if the slot state isn't RESERVED, which is
622 	 * what we want.
623 	 */
624 	if (srv->upload.slot) {
625 		bt_mesh_dfu_slot_release(srv->upload.slot);
626 	}
627 
628 	srv->upload.is_oob = true;
629 	srv->upload.slot = slot;
630 	memcpy(srv->upload.oob.uri, uri, uri_len);
631 	srv->upload.oob.uri_len = uri_len;
632 	memcpy(srv->upload.oob.current_fwid, fwid, fwid_len);
633 	srv->upload.oob.current_fwid_len = fwid_len;
634 	memcpy(&srv->upload.oob.ctx, ctx, sizeof(struct bt_mesh_msg_ctx));
635 
636 	int status = srv->cb->start_oob_upload(srv, srv->upload.slot, srv->upload.oob.uri,
637 					       srv->upload.oob.uri_len,
638 					       srv->upload.oob.current_fwid,
639 					       srv->upload.oob.current_fwid_len);
640 
641 	if (status != BT_MESH_DFD_SUCCESS) {
642 		upload_status_rsp(srv, ctx, status);
643 		bt_mesh_dfu_slot_release(srv->upload.slot);
644 	} else {
645 		srv->upload.is_pending_oob_check = true;
646 	}
647 #else
648 	upload_status_rsp(srv, ctx, BT_MESH_DFD_ERR_URI_NOT_SUPPORTED);
649 #endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */
650 
651 	return 0;
652 }
653 
handle_upload_cancel(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)654 static int handle_upload_cancel(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
655 				struct net_buf_simple *buf)
656 {
657 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
658 
659 	srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE;
660 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
661 	if (srv->upload.is_oob) {
662 		srv->cb->cancel_oob_upload(srv, srv->upload.slot);
663 	} else
664 #endif
665 	{
666 		(void)bt_mesh_blob_srv_cancel(&srv->upload.blob);
667 	}
668 	upload_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
669 
670 	return 0;
671 }
672 
fw_status_rsp(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx,enum bt_mesh_dfd_status status,uint16_t idx,const uint8_t * fwid,size_t fwid_len)673 static void fw_status_rsp(struct bt_mesh_dfd_srv *srv,
674 			  struct bt_mesh_msg_ctx *ctx,
675 			  enum bt_mesh_dfd_status status, uint16_t idx,
676 			  const uint8_t *fwid, size_t fwid_len)
677 {
678 	BT_MESH_MODEL_BUF_DEFINE(rsp, BT_MESH_DFD_OP_FW_STATUS,
679 				 7 + CONFIG_BT_MESH_DFU_FWID_MAXLEN);
680 	bt_mesh_model_msg_init(&rsp, BT_MESH_DFD_OP_FW_STATUS);
681 
682 	net_buf_simple_add_u8(&rsp, status);
683 	net_buf_simple_add_le16(&rsp, bt_mesh_dfu_slot_count());
684 
685 	net_buf_simple_add_le16(&rsp, idx);
686 	if (fwid) {
687 		net_buf_simple_add_mem(&rsp, fwid, fwid_len);
688 	}
689 
690 	bt_mesh_model_send(srv->mod, ctx, &rsp, NULL, NULL);
691 }
692 
handle_fw_get(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)693 static int handle_fw_get(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
694 			 struct net_buf_simple *buf)
695 {
696 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
697 	struct bt_mesh_dfu_slot *slot;
698 	const uint8_t *fwid;
699 	size_t fwid_len;
700 	int idx;
701 
702 	fwid_len = buf->len;
703 	fwid = net_buf_simple_pull_mem(buf, fwid_len);
704 
705 	idx = bt_mesh_dfu_slot_get(fwid, fwid_len, &slot);
706 	if (idx >= 0) {
707 		fw_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS, idx, fwid,
708 			      fwid_len);
709 	} else {
710 		fw_status_rsp(srv, ctx, BT_MESH_DFD_ERR_FW_NOT_FOUND, 0xffff,
711 			      fwid, fwid_len);
712 	}
713 
714 	return 0;
715 }
716 
handle_fw_get_by_index(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)717 static int handle_fw_get_by_index(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
718 				  struct net_buf_simple *buf)
719 {
720 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
721 	const struct bt_mesh_dfu_slot *slot;
722 	uint16_t idx;
723 
724 	idx = net_buf_simple_pull_le16(buf);
725 
726 	slot = bt_mesh_dfu_slot_at(idx);
727 	if (slot) {
728 		fw_status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS, idx, slot->fwid,
729 			      slot->fwid_len);
730 	} else {
731 		fw_status_rsp(srv, ctx, BT_MESH_DFD_ERR_FW_NOT_FOUND, idx,
732 			      NULL, 0);
733 	}
734 
735 	return 0;
736 }
737 
handle_fw_delete(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)738 static int handle_fw_delete(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
739 			    struct net_buf_simple *buf)
740 {
741 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
742 	const uint8_t *fwid;
743 	size_t fwid_len;
744 
745 	fwid_len = buf->len;
746 	fwid = net_buf_simple_pull_mem(buf, fwid_len);
747 
748 	enum bt_mesh_dfd_status status = bt_mesh_dfd_srv_fw_delete(srv, &fwid_len, &fwid);
749 
750 	fw_status_rsp(srv, ctx, status, 0xffff, fwid, fwid_len);
751 
752 	return 0;
753 }
754 
slot_del_cb(const struct bt_mesh_dfu_slot * slot,void * user_data)755 static enum bt_mesh_dfu_iter slot_del_cb(const struct bt_mesh_dfu_slot *slot,
756 					 void *user_data)
757 {
758 	struct bt_mesh_dfd_srv *srv = user_data;
759 
760 	if (srv->cb && srv->cb->del) {
761 		srv->cb->del(srv, slot);
762 	}
763 
764 	return BT_MESH_DFU_ITER_CONTINUE;
765 }
766 
handle_fw_delete_all(const struct bt_mesh_model * mod,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)767 static int handle_fw_delete_all(const struct bt_mesh_model *mod, struct bt_mesh_msg_ctx *ctx,
768 				struct net_buf_simple *buf)
769 {
770 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
771 
772 	fw_status_rsp(srv, ctx, bt_mesh_dfd_srv_fw_delete_all(srv), 0xffff, NULL, 0);
773 
774 	return 0;
775 }
776 
777 const struct bt_mesh_model_op _bt_mesh_dfd_srv_op[] = {
778 	{ BT_MESH_DFD_OP_RECEIVERS_ADD, BT_MESH_LEN_MIN(3), handle_receivers_add },
779 	{ BT_MESH_DFD_OP_RECEIVERS_DELETE_ALL, BT_MESH_LEN_EXACT(0), handle_receivers_delete_all },
780 	{ BT_MESH_DFD_OP_RECEIVERS_GET, BT_MESH_LEN_EXACT(4), handle_receivers_get },
781 	{ BT_MESH_DFD_OP_CAPABILITIES_GET, BT_MESH_LEN_EXACT(0), handle_capabilities_get },
782 	{ BT_MESH_DFD_OP_GET, BT_MESH_LEN_EXACT(0), handle_get },
783 	{ BT_MESH_DFD_OP_START, BT_MESH_LEN_MIN(10), handle_start },
784 	{ BT_MESH_DFD_OP_SUSPEND, BT_MESH_LEN_EXACT(0), handle_suspend },
785 	{ BT_MESH_DFD_OP_CANCEL, BT_MESH_LEN_EXACT(0), handle_cancel },
786 	{ BT_MESH_DFD_OP_APPLY, BT_MESH_LEN_EXACT(0), handle_apply },
787 	{ BT_MESH_DFD_OP_UPLOAD_GET, BT_MESH_LEN_EXACT(0), handle_upload_get },
788 	{ BT_MESH_DFD_OP_UPLOAD_START, BT_MESH_LEN_MIN(16), handle_upload_start },
789 	{ BT_MESH_DFD_OP_UPLOAD_START_OOB, BT_MESH_LEN_MIN(2), handle_upload_start_oob },
790 	{ BT_MESH_DFD_OP_UPLOAD_CANCEL, BT_MESH_LEN_EXACT(0), handle_upload_cancel },
791 	{ BT_MESH_DFD_OP_FW_GET, BT_MESH_LEN_MIN(0), handle_fw_get },
792 	{ BT_MESH_DFD_OP_FW_GET_BY_INDEX, BT_MESH_LEN_EXACT(2), handle_fw_get_by_index },
793 	{ BT_MESH_DFD_OP_FW_DELETE, BT_MESH_LEN_MIN(0), handle_fw_delete },
794 	{ BT_MESH_DFD_OP_FW_DELETE_ALL, BT_MESH_LEN_EXACT(0), handle_fw_delete_all },
795 
796 	BT_MESH_MODEL_OP_END
797 };
798 
dfu_suspended(struct bt_mesh_dfu_cli * cli)799 static void dfu_suspended(struct bt_mesh_dfu_cli *cli)
800 {
801 	struct bt_mesh_dfd_srv *srv =
802 		CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu);
803 
804 	srv->phase = BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED;
805 }
806 
dfu_ended(struct bt_mesh_dfu_cli * cli,enum bt_mesh_dfu_status reason)807 static void dfu_ended(struct bt_mesh_dfu_cli *cli,
808 		      enum bt_mesh_dfu_status reason)
809 {
810 	struct bt_mesh_dfd_srv *srv =
811 		CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu);
812 	int err;
813 
814 	LOG_DBG("reason: %u, phase: %u, apply: %u", reason, srv->phase, srv->apply);
815 
816 	if (srv->phase == BT_MESH_DFD_PHASE_IDLE) {
817 		return;
818 	}
819 
820 	if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) {
821 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
822 		return;
823 	}
824 
825 	if (reason != BT_MESH_DFU_SUCCESS) {
826 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED);
827 		return;
828 	}
829 
830 	if (!srv->apply) {
831 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_SUCCESS);
832 		return;
833 	}
834 
835 	dfd_phase_set(srv, BT_MESH_DFD_PHASE_APPLYING_UPDATE);
836 
837 	err = bt_mesh_dfu_cli_apply(cli);
838 	if (err) {
839 		LOG_ERR("Apply failed: %d", err);
840 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED);
841 	}
842 }
843 
dfu_applied(struct bt_mesh_dfu_cli * cli)844 static void dfu_applied(struct bt_mesh_dfu_cli *cli)
845 {
846 	struct bt_mesh_dfd_srv *srv =
847 		CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu);
848 	int err;
849 
850 	if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) {
851 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED);
852 		return;
853 	}
854 
855 	if (srv->phase != BT_MESH_DFD_PHASE_APPLYING_UPDATE) {
856 		return;
857 	}
858 
859 	err = bt_mesh_dfu_cli_confirm(cli);
860 	if (err) {
861 		LOG_ERR("Confirm failed: %d", err);
862 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_FAILED);
863 	}
864 }
865 
dfu_confirmed(struct bt_mesh_dfu_cli * cli)866 static void dfu_confirmed(struct bt_mesh_dfu_cli *cli)
867 {
868 	struct bt_mesh_dfd_srv *srv =
869 		CONTAINER_OF(cli, struct bt_mesh_dfd_srv, dfu);
870 
871 	if (srv->phase != BT_MESH_DFD_PHASE_APPLYING_UPDATE &&
872 	    srv->phase != BT_MESH_DFD_PHASE_CANCELING_UPDATE) {
873 		return;
874 	}
875 
876 	dfd_phase_set(srv, BT_MESH_DFD_PHASE_COMPLETED);
877 }
878 
879 const struct bt_mesh_dfu_cli_cb _bt_mesh_dfd_srv_dfu_cb = {
880 	.suspended = dfu_suspended,
881 	.ended = dfu_ended,
882 	.applied = dfu_applied,
883 	.confirmed = dfu_confirmed,
884 };
885 
upload_start(struct bt_mesh_blob_srv * b,struct bt_mesh_msg_ctx * ctx,struct bt_mesh_blob_xfer * xfer)886 static int upload_start(struct bt_mesh_blob_srv *b, struct bt_mesh_msg_ctx *ctx,
887 			struct bt_mesh_blob_xfer *xfer)
888 {
889 	LOG_DBG("");
890 	return 0;
891 }
892 
upload_end(struct bt_mesh_blob_srv * b,uint64_t id,bool success)893 static void upload_end(struct bt_mesh_blob_srv *b, uint64_t id, bool success)
894 {
895 	struct bt_mesh_dfd_srv *srv =
896 		CONTAINER_OF(b, struct bt_mesh_dfd_srv, upload.blob);
897 
898 	if (srv->upload.phase != BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE) {
899 		return;
900 	}
901 
902 	LOG_DBG("%u", success);
903 
904 	if (success && (bt_mesh_dfu_slot_commit(srv->upload.slot) == 0)) {
905 		srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS;
906 		return;
907 	}
908 
909 	/* Will delete slot when we start a new upload */
910 	srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR;
911 }
912 
upload_timeout(struct bt_mesh_blob_srv * b)913 static void upload_timeout(struct bt_mesh_blob_srv *b)
914 {
915 	LOG_DBG("");
916 
917 	upload_end(b, b->state.xfer.id, false);
918 }
919 
920 const struct bt_mesh_blob_srv_cb _bt_mesh_dfd_srv_blob_cb = {
921 	.start = upload_start,
922 	.end = upload_end,
923 	.suspended = upload_timeout,
924 };
925 
dfd_srv_init(const struct bt_mesh_model * mod)926 static int dfd_srv_init(const struct bt_mesh_model *mod)
927 {
928 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
929 
930 	srv->mod = mod;
931 
932 	if (IS_ENABLED(CONFIG_BT_MESH_MODEL_EXTENSIONS)) {
933 		bt_mesh_model_extend(mod, srv->upload.blob.mod);
934 	}
935 
936 	return 0;
937 }
938 
dfd_srv_reset(const struct bt_mesh_model * mod)939 static void dfd_srv_reset(const struct bt_mesh_model *mod)
940 {
941 	struct bt_mesh_dfd_srv *srv = mod->rt->user_data;
942 
943 	dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
944 	srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_IDLE;
945 
946 	sys_slist_init(&srv->inputs.targets);
947 	srv->target_cnt = 0;
948 
949 	bt_mesh_dfu_slot_foreach(slot_del_cb, srv);
950 	bt_mesh_dfu_slot_del_all();
951 }
952 
953 const struct bt_mesh_model_cb _bt_mesh_dfd_srv_cb = {
954 	.init = dfd_srv_init,
955 	.reset = dfd_srv_reset,
956 };
957 
bt_mesh_dfd_srv_receiver_add(struct bt_mesh_dfd_srv * srv,uint16_t addr,uint8_t img_idx)958 enum bt_mesh_dfd_status bt_mesh_dfd_srv_receiver_add(struct bt_mesh_dfd_srv *srv, uint16_t addr,
959 						     uint8_t img_idx)
960 {
961 	struct bt_mesh_dfu_target *t;
962 	struct bt_mesh_blob_target_pull *p;
963 
964 	if (!BT_MESH_ADDR_IS_UNICAST(addr)) {
965 		return BT_MESH_DFD_SUCCESS;
966 	}
967 
968 	t = target_get(srv, addr);
969 	if (t) {
970 		t->img_idx = img_idx;
971 		return BT_MESH_DFD_SUCCESS;
972 	}
973 
974 	/* New target node, add it to the list */
975 
976 	if (srv->target_cnt == ARRAY_SIZE(srv->targets)) {
977 		return BT_MESH_DFD_ERR_INSUFFICIENT_RESOURCES;
978 	}
979 
980 	t = &srv->targets[srv->target_cnt];
981 	p = &srv->pull_ctxs[srv->target_cnt];
982 	srv->target_cnt++;
983 
984 	memset(t, 0, sizeof(*t));
985 	memset(p, 0, sizeof(*p));
986 	t->blob.addr = addr;
987 	t->blob.pull = p;
988 	t->img_idx = img_idx;
989 
990 	LOG_DBG("Added receiver 0x%04x img: %u", t->blob.addr,
991 		t->img_idx);
992 
993 	return BT_MESH_DFD_SUCCESS;
994 }
995 
bt_mesh_dfd_srv_receivers_delete_all(struct bt_mesh_dfd_srv * srv)996 enum bt_mesh_dfd_status bt_mesh_dfd_srv_receivers_delete_all(struct bt_mesh_dfd_srv *srv)
997 {
998 	if (bt_mesh_dfu_cli_is_busy(&srv->dfu)) {
999 		return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1000 	}
1001 
1002 	sys_slist_init(&srv->inputs.targets);
1003 	srv->target_cnt = 0;
1004 
1005 	return BT_MESH_DFD_SUCCESS;
1006 }
1007 
bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv * srv,struct bt_mesh_dfd_start_params * params)1008 enum bt_mesh_dfd_status bt_mesh_dfd_srv_start(struct bt_mesh_dfd_srv *srv,
1009 					      struct bt_mesh_dfd_start_params *params)
1010 {
1011 	int err, i;
1012 	struct bt_mesh_dfu_cli_xfer xfer = { 0 };
1013 
1014 	if (!srv->target_cnt) {
1015 		return BT_MESH_DFD_ERR_RECEIVERS_LIST_EMPTY;
1016 	}
1017 
1018 	if (!bt_mesh_app_key_exists(params->app_idx)) {
1019 		return BT_MESH_DFD_ERR_INVALID_APPKEY_INDEX;
1020 	}
1021 
1022 	xfer.mode = params->xfer_mode;
1023 	xfer.slot = bt_mesh_dfu_slot_at(params->slot_idx);
1024 	if (!xfer.slot) {
1025 		return BT_MESH_DFD_ERR_FW_NOT_FOUND;
1026 	}
1027 
1028 	if (srv->inputs.app_idx == params->app_idx &&
1029 	    srv->inputs.timeout_base == params->timeout_base &&
1030 	    srv->inputs.group == params->group && srv->inputs.ttl == params->ttl &&
1031 	    srv->dfu.xfer.blob.mode == xfer.mode && srv->apply == params->apply &&
1032 	    srv->slot_idx == params->slot_idx) {
1033 		if (is_busy(srv) ||
1034 		    srv->phase == BT_MESH_DFD_PHASE_COMPLETED) {
1035 			LOG_WRN("Already completed or in progress");
1036 			return BT_MESH_DFD_SUCCESS;
1037 		} else if (srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) {
1038 			bt_mesh_dfu_cli_resume(&srv->dfu);
1039 			dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_ACTIVE);
1040 			return BT_MESH_DFD_SUCCESS;
1041 		}
1042 	} else if (is_busy(srv) ||
1043 		   srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) {
1044 		LOG_WRN("Busy with distribution");
1045 		return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1046 	}
1047 
1048 	if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE) {
1049 		LOG_WRN("Canceling distribution");
1050 		return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1051 	}
1052 
1053 	srv->io = NULL;
1054 	err = srv->cb->send(srv, xfer.slot, &srv->io);
1055 	if (err || !srv->io) {
1056 		return BT_MESH_DFD_ERR_INTERNAL;
1057 	}
1058 
1059 	sys_slist_init(&srv->inputs.targets);
1060 	for (i = 0; i < srv->target_cnt; i++) {
1061 		uint16_t addr = srv->targets[i].blob.addr;
1062 
1063 		memset(&srv->targets[i].blob, 0, sizeof(struct bt_mesh_blob_target));
1064 		memset(&srv->pull_ctxs[i], 0, sizeof(struct bt_mesh_blob_target_pull));
1065 		srv->targets[i].blob.addr = addr;
1066 		srv->targets[i].blob.pull = &srv->pull_ctxs[i];
1067 
1068 		sys_slist_append(&srv->inputs.targets, &srv->targets[i].blob.n);
1069 	}
1070 
1071 	srv->slot_idx = params->slot_idx;
1072 	srv->inputs.app_idx = params->app_idx;
1073 	srv->inputs.timeout_base = params->timeout_base;
1074 	srv->inputs.group = params->group;
1075 	srv->inputs.ttl = params->ttl;
1076 	srv->apply = params->apply;
1077 
1078 	LOG_DBG("Distribution Start: slot: %d, appidx: %d, tb: %d, addr: %04X, ttl: %d, apply: %d",
1079 		params->slot_idx, params->app_idx, params->timeout_base, params->group, params->ttl,
1080 		params->apply);
1081 
1082 	/* DFD Server will always retrieve targets' capabilities before distributing a firmware.*/
1083 	xfer.blob_params = NULL;
1084 
1085 	dfd_phase_set(srv, BT_MESH_DFD_PHASE_TRANSFER_ACTIVE);
1086 	err = bt_mesh_dfu_cli_send(&srv->dfu, &srv->inputs, srv->io, &xfer);
1087 	if (err) {
1088 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
1089 		return BT_MESH_DFD_ERR_INTERNAL;
1090 	}
1091 
1092 	return BT_MESH_DFD_SUCCESS;
1093 }
1094 
bt_mesh_dfd_srv_suspend(struct bt_mesh_dfd_srv * srv)1095 enum bt_mesh_dfd_status bt_mesh_dfd_srv_suspend(struct bt_mesh_dfd_srv *srv)
1096 {
1097 	int err;
1098 
1099 	if (srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED) {
1100 		return BT_MESH_DFD_SUCCESS;
1101 	}
1102 
1103 	if (srv->phase != BT_MESH_DFD_PHASE_TRANSFER_ACTIVE) {
1104 		return BT_MESH_DFD_ERR_WRONG_PHASE;
1105 	}
1106 
1107 	err = bt_mesh_dfu_cli_suspend(&srv->dfu);
1108 	if (err) {
1109 		return BT_MESH_DFD_ERR_SUSPEND_FAILED;
1110 	}
1111 
1112 	srv->phase = BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED;
1113 	return BT_MESH_DFD_SUCCESS;
1114 }
1115 
bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv * srv,struct bt_mesh_msg_ctx * ctx)1116 enum bt_mesh_dfd_status bt_mesh_dfd_srv_cancel(struct bt_mesh_dfd_srv *srv,
1117 					       struct bt_mesh_msg_ctx *ctx)
1118 {
1119 	enum bt_mesh_dfd_phase prev_phase;
1120 	int err;
1121 
1122 	if (srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE ||
1123 	    srv->phase == BT_MESH_DFD_PHASE_IDLE) {
1124 		if (ctx != NULL) {
1125 			status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
1126 		}
1127 		return BT_MESH_DFD_SUCCESS;
1128 	}
1129 
1130 	if (srv->phase == BT_MESH_DFD_PHASE_COMPLETED ||
1131 	    srv->phase == BT_MESH_DFD_PHASE_FAILED) {
1132 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
1133 		if (ctx != NULL) {
1134 			status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
1135 		}
1136 		return BT_MESH_DFD_SUCCESS;
1137 	}
1138 
1139 	/* Phase TRANSFER_ACTIVE, TRANSFER_SUSPENDED, TRANSFER_SUCCESS, APPLYING_UPDATE: */
1140 
1141 	prev_phase = srv->phase;
1142 	dfd_phase_set(srv, BT_MESH_DFD_PHASE_CANCELING_UPDATE);
1143 	err = bt_mesh_dfu_cli_cancel(&srv->dfu, NULL);
1144 	if (err) {
1145 		if (ctx != NULL) {
1146 			status_rsp(srv, ctx, BT_MESH_DFD_ERR_INTERNAL);
1147 		}
1148 		return BT_MESH_DFD_ERR_INTERNAL;
1149 	}
1150 
1151 	if (prev_phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE && ctx) {
1152 		/* Disable randomization for the Firmware Distribution State message to avoid
1153 		 * reordering when Firmware Distribution Server sends 2 messages in a row when
1154 		 * cancelling the update (see section 6.2.3.10 of MshDFUv1.0).
1155 		 */
1156 		ctx->rnd_delay = false;
1157 	}
1158 
1159 	if (ctx != NULL) {
1160 		status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
1161 	}
1162 
1163 	if (prev_phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE) {
1164 		dfd_phase_set(srv, BT_MESH_DFD_PHASE_IDLE);
1165 		if (ctx != NULL) {
1166 			status_rsp(srv, ctx, BT_MESH_DFD_SUCCESS);
1167 		}
1168 	}
1169 
1170 	return BT_MESH_DFD_SUCCESS;
1171 }
1172 
bt_mesh_dfd_srv_apply(struct bt_mesh_dfd_srv * srv)1173 enum bt_mesh_dfd_status bt_mesh_dfd_srv_apply(struct bt_mesh_dfd_srv *srv)
1174 {
1175 	int err;
1176 
1177 	if (srv->phase == BT_MESH_DFD_PHASE_IDLE ||
1178 	    srv->phase == BT_MESH_DFD_PHASE_CANCELING_UPDATE ||
1179 	    srv->phase == BT_MESH_DFD_PHASE_TRANSFER_ACTIVE ||
1180 	    srv->phase == BT_MESH_DFD_PHASE_TRANSFER_SUSPENDED ||
1181 	    srv->phase == BT_MESH_DFD_PHASE_FAILED) {
1182 		return BT_MESH_DFD_ERR_WRONG_PHASE;
1183 	}
1184 
1185 	if (srv->phase == BT_MESH_DFD_PHASE_APPLYING_UPDATE ||
1186 	    srv->phase == BT_MESH_DFD_PHASE_COMPLETED) {
1187 		return BT_MESH_DFD_SUCCESS;
1188 	}
1189 
1190 	err = bt_mesh_dfu_cli_apply(&srv->dfu);
1191 	if (err) {
1192 		return BT_MESH_DFD_ERR_INTERNAL;
1193 	}
1194 
1195 	dfd_phase_set(srv, BT_MESH_DFD_PHASE_APPLYING_UPDATE);
1196 	return BT_MESH_DFD_SUCCESS;
1197 }
1198 
bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv * srv,size_t * fwid_len,const uint8_t ** fwid)1199 enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete(struct bt_mesh_dfd_srv *srv, size_t *fwid_len,
1200 						  const uint8_t **fwid)
1201 {
1202 	struct bt_mesh_dfu_slot *slot;
1203 	int idx, err;
1204 
1205 	if (srv->phase != BT_MESH_DFD_PHASE_IDLE) {
1206 		*fwid = NULL;
1207 		*fwid_len = 0;
1208 		return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1209 	}
1210 
1211 	idx = bt_mesh_dfu_slot_get(*fwid, *fwid_len, &slot);
1212 	if (idx < 0) {
1213 		return BT_MESH_DFD_SUCCESS;
1214 	}
1215 
1216 	err = slot_del(srv, slot);
1217 	if (err) {
1218 		*fwid = NULL;
1219 		*fwid_len = 0;
1220 		return BT_MESH_DFD_ERR_INTERNAL;
1221 	} else {
1222 		return BT_MESH_DFD_SUCCESS;
1223 	}
1224 }
1225 
bt_mesh_dfd_srv_fw_delete_all(struct bt_mesh_dfd_srv * srv)1226 enum bt_mesh_dfd_status bt_mesh_dfd_srv_fw_delete_all(struct bt_mesh_dfd_srv *srv)
1227 {
1228 	if (srv->phase != BT_MESH_DFD_PHASE_IDLE) {
1229 		return BT_MESH_DFD_ERR_BUSY_WITH_DISTRIBUTION;
1230 	}
1231 
1232 	bt_mesh_dfu_slot_foreach(slot_del_cb, srv);
1233 
1234 	bt_mesh_dfu_slot_del_all();
1235 
1236 	return BT_MESH_DFD_SUCCESS;
1237 }
1238 
1239 #ifdef CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD
bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot,int status,uint8_t * fwid,size_t fwid_len)1240 int bt_mesh_dfd_srv_oob_check_complete(struct bt_mesh_dfd_srv *srv,
1241 				       const struct bt_mesh_dfu_slot *slot, int status,
1242 				       uint8_t *fwid, size_t fwid_len)
1243 {
1244 	int err;
1245 
1246 	if (slot != srv->upload.slot || !srv->upload.is_oob ||
1247 	    srv->upload.phase == BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE ||
1248 	    !srv->upload.is_pending_oob_check) {
1249 		/* This should not happen, unless the application calls the function with a
1250 		 * "wrong" pointer or at a wrong time.
1251 		 */
1252 		return -EINVAL;
1253 	}
1254 
1255 	srv->upload.is_pending_oob_check = false;
1256 
1257 	if (status != BT_MESH_DFD_SUCCESS) {
1258 		bt_mesh_dfu_slot_release(srv->upload.slot);
1259 		upload_status_rsp(srv, &srv->upload.oob.ctx, status);
1260 		return -ECANCELED;
1261 	}
1262 
1263 	err = set_upload_fwid(srv, &srv->upload.oob.ctx, fwid, fwid_len);
1264 
1265 	if (err) {
1266 		return err;
1267 	}
1268 
1269 	upload_status_rsp(srv, &srv->upload.oob.ctx, BT_MESH_DFD_SUCCESS);
1270 	return 0;
1271 }
1272 
bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot,bool success,size_t size,const uint8_t * metadata,size_t metadata_len)1273 int bt_mesh_dfd_srv_oob_store_complete(struct bt_mesh_dfd_srv *srv,
1274 				       const struct bt_mesh_dfu_slot *slot, bool success,
1275 				       size_t size, const uint8_t *metadata, size_t metadata_len)
1276 {
1277 	int err = 0;
1278 
1279 	if (srv->upload.phase != BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ACTIVE ||
1280 	    srv->upload.slot != slot || !srv->upload.is_oob) {
1281 		return -EINVAL;
1282 	}
1283 
1284 	if (!success) {
1285 		goto error;
1286 	}
1287 
1288 	err = bt_mesh_dfu_slot_info_set(srv->upload.slot, size, metadata, metadata_len);
1289 	if (err) {
1290 		goto error;
1291 	}
1292 
1293 	err = bt_mesh_dfu_slot_commit(srv->upload.slot);
1294 	if (err) {
1295 		goto error;
1296 	}
1297 
1298 	srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_SUCCESS;
1299 	return 0;
1300 
1301 error:
1302 	srv->upload.phase = BT_MESH_DFD_UPLOAD_PHASE_TRANSFER_ERROR;
1303 	bt_mesh_dfu_slot_release(srv->upload.slot);
1304 	return err;
1305 }
1306 #endif /* CONFIG_BT_MESH_DFD_SRV_OOB_UPLOAD */
1307