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