1 /*
2 * Copyright (c) 2017 Linaro Limited
3 * Copyright (c) 2018-2019 Foundries.io
4 * Copyright (c) 2021 Voi Technology AB
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #define LOG_MODULE_NAME net_lwm2m_obj_swmgmt
10 #define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
11
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(LOG_MODULE_NAME);
14
15 #include <string.h>
16 #include <zephyr/init.h>
17
18 #include <stdint.h>
19 #include <zephyr/net/lwm2m.h>
20
21 #include "lwm2m_object.h"
22 #include "lwm2m_engine.h"
23
24 #include "lwm2m_pull_context.h"
25
26 #define SWMGMT_VERSION_MAJOR 1
27 #define SWMGMT_VERSION_MINOR 0
28
29 #define SWMGMT_PACKAGE_NAME_ID 0
30 #define SWMGMT_PACKAGE_VERSION_ID 1
31 #define SWMGMT_PACKAGE_ID 2
32 #define SWMGMT_PACKAGE_URI_ID 3
33 #define SWMGMT_INSTALL_ID 4
34 #define SWMGMT_CHECKPOINT_ID 5
35 #define SWMGMT_UNINSTALL_ID 6
36 #define SWMGMT_UPDATE_STATE_ID 7
37 #define SWMGMT_UPDATE_SUPPORTED_OBJECTS_ID 8
38 #define SWMGMT_UPDATE_RESULT_ID 9
39 #define SWMGMT_ACTIVATE_ID 10
40 #define SWMGMT_DEACTIVATE_ID 11
41 #define SWMGMT_ACTIVATION_UPD_STATE_ID 12
42 #define SWMGMT_PACKAGE_SETTINGS_ID 13
43 #define SWMGMT_USER_NAME_ID 14
44 #define SWMGMT_PASSWORD_ID 15
45 #define SWMGMT_MAX_ID 16
46
47 #define PACKAGE_NAME_LEN CONFIG_LWM2M_SWMGMT_PACKAGE_NAME_LEN
48 #define PACKAGE_VERSION_LEN CONFIG_LWM2M_SWMGMT_PACKAGE_VERSION_LEN
49 #define PACKAGE_URI_LEN CONFIG_LWM2M_SWMGMT_PACKAGE_URI_LEN
50 #define MAX_INSTANCE_COUNT CONFIG_LWM2M_SWMGMT_MAX_INSTANCE_COUNT
51
52 /*
53 * Calculate resource instances as follows:
54 * start with SWMGMT_MAX_ID
55 * subtract EXEC resources (4)
56 */
57 #define NR_EXEC_RESOURCES 4
58 #define RESOURCE_INSTANCE_COUNT (SWMGMT_MAX_ID - NR_EXEC_RESOURCES)
59
60 static struct lwm2m_engine_obj swmgmt;
61 static struct lwm2m_engine_obj_field fields[] = {
62 OBJ_FIELD(SWMGMT_PACKAGE_NAME_ID, R, STRING),
63 OBJ_FIELD(SWMGMT_PACKAGE_VERSION_ID, R, STRING),
64 OBJ_FIELD(SWMGMT_PACKAGE_ID, W_OPT, OPAQUE),
65 OBJ_FIELD(SWMGMT_PACKAGE_URI_ID, W_OPT, STRING),
66 OBJ_FIELD_EXECUTE(SWMGMT_INSTALL_ID),
67 OBJ_FIELD(SWMGMT_CHECKPOINT_ID, R_OPT, OBJLNK),
68 OBJ_FIELD_EXECUTE(SWMGMT_UNINSTALL_ID),
69 OBJ_FIELD(SWMGMT_UPDATE_STATE_ID, R, U8),
70 OBJ_FIELD(SWMGMT_UPDATE_SUPPORTED_OBJECTS_ID, RW_OPT, BOOL),
71 OBJ_FIELD(SWMGMT_UPDATE_RESULT_ID, R, U8),
72 OBJ_FIELD_EXECUTE(SWMGMT_ACTIVATE_ID),
73 OBJ_FIELD_EXECUTE(SWMGMT_DEACTIVATE_ID),
74 OBJ_FIELD(SWMGMT_ACTIVATION_UPD_STATE_ID, R, BOOL),
75 OBJ_FIELD(SWMGMT_PACKAGE_SETTINGS_ID, RW_OPT, OBJLNK),
76 OBJ_FIELD(SWMGMT_USER_NAME_ID, W_OPT, STRING),
77 OBJ_FIELD(SWMGMT_PASSWORD_ID, W_OPT, STRING),
78 };
79
80 static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT];
81 static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SWMGMT_MAX_ID];
82 static struct lwm2m_engine_res_inst res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT];
83
84 #define UPD_STATE_INITIAL 0
85 #define UPD_STATE_DOWNLOAD_STARTED 1
86 #define UPD_STATE_DOWNLOADED 2
87 #define UPD_STATE_DELIVERED 3
88 #define UPD_STATE_INSTALLED 4
89
90 #define EVENT_PKG_URI_WRITE 0
91 #define EVENT_PKG_WRITTEN 1
92 #define EVENT_PKG_INTEGRITY_VERIFIED 2
93 #define EVENT_INSTALL 4
94 #define EVENT_INSTALL_SUCCESSFUL 5
95 #define EVENT_INSTALL_FAIL 6
96 #define EVENT_DELETE_PACKAGE 7
97 #define EVENT_FOR_UPDATE 8
98 #define EVENT_DOWNLOAD_FAILED 9
99 #define EVENT_PKG_INTEGRITY_FAILED 10
100 #define EVENT_ACTIVATE 11
101 #define EVENT_DEACTIVATE 12
102
103 /*
104 * 0: Initial value. Prior to download any new package in the Device, Update
105 * Result MUST be reset to this initial value. One side effect of executing
106 * the Uninstall resource is to reset Update Result to this initial value 0.
107 */
108 #define UPD_RES_INITIAL 0
109
110 /* 1: Downloading. The package downloading process is ongoing. */
111 #define UPD_RES_DOWNLOADING 1
112
113 /* 2: Software successfully installed. */
114 #define UPD_RES_SW_SUCCESSFULLY_INSTALLED 2
115
116 /* 3: Successfully Downloaded and package integrity verified */
117 #define UPD_RES_DOWNLOADED_AND_VERIFIED 3
118
119 /* 4-49: reserved for expansion of other scenarios>> */
120 /* 50: Not enough storage for the new software package. */
121 #define UPD_RES_NOT_ENOUGH_STORAGE 50
122
123 /* 51: Out of memory during downloading process. */
124 #define UPD_RES_OUT_OF_MEMORY_DURING_DOWNLOAD 51
125
126 /* 52: Connection lost during downloading process. */
127 #define UPD_RES_LOST_CONNECTION_DURING_DOWNLOAD 52
128
129 /* 53: Package integrity check failure. */
130 #define UPD_RES_PACKAGE_INTEGRITY_CHECK_FAILURE 53
131
132 /* 54: Unsupported package type. */
133 #define UPD_RES_UNSUPPORTED_PACKAGE_TYPE 54
134
135 /* 55: Undefined */
136 /* 56: Invalid URI */
137 #define UPD_RES_INVALID_URI 56
138
139 /* 57: Device defined update error */
140 #define UPD_RES_DEVICE_DEFINED_UPDATE_ERROR 57
141
142 /* 58: Software installation failure */
143 #define UPD_RES_SW_INSTALLATION_FAILURE 58
144
145 /* 59: Uninstallation Failure during forUpdate(arg=0) */
146 #define UPD_RES_UNINSTALLATION_FAILURE_FOR_UPDATE 59
147
148 /*
149 * 60-200 : reserved for expansion selection to be in blocks depending on new
150 * introduction of features
151 */
152
153 struct lwm2m_swmgmt_data {
154 uint16_t obj_inst_id;
155
156 char package_name[PACKAGE_NAME_LEN];
157 char package_version[PACKAGE_VERSION_LEN];
158
159 bool next_package_is_upgrade;
160
161 uint8_t update_state;
162 uint8_t update_result;
163
164 bool activation_state;
165
166 lwm2m_engine_get_data_cb_t read_package_cb;
167 lwm2m_engine_execute_cb_t install_package_cb;
168 lwm2m_engine_user_cb_t upgrade_package_cb;
169 lwm2m_engine_execute_cb_t delete_package_cb;
170 lwm2m_engine_execute_cb_t activate_cb;
171 lwm2m_engine_execute_cb_t deactivate_cb;
172 lwm2m_engine_set_data_cb_t write_package_cb;
173
174 #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
175 char package_uri[PACKAGE_URI_LEN];
176 #endif
177 };
178
179 /* Package pull request should come with a verify_cb which needs to be stored for when package
180 * gets downloaded
181 */
182 static int (*verify_package)(void);
183
callback_execute_not_defined(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)184 static int callback_execute_not_defined(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
185 {
186 LOG_ERR("Callback not defined for inst %u", obj_inst_id);
187 return -EINVAL;
188 }
189
callback_write_not_defined(uint16_t obj_inst_id,uint16_t res_id,uint16_t res_inst_id,uint8_t * data,uint16_t data_len,bool last_block,size_t total_size,size_t offset)190 static int callback_write_not_defined(uint16_t obj_inst_id, uint16_t res_id,
191 uint16_t res_inst_id, uint8_t *data,
192 uint16_t data_len, bool last_block,
193 size_t total_size, size_t offset)
194 {
195 LOG_ERR("Callback not defined for inst %u", obj_inst_id);
196 return -EINVAL;
197 }
198
callback_read_not_defined(uint16_t obj_inst_id,uint16_t res_id,uint16_t res_inst_id,size_t * data_len)199 static void *callback_read_not_defined(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
200 size_t *data_len)
201 {
202 LOG_ERR("Callback not defined for inst %u", obj_inst_id);
203 return NULL;
204 }
205
set_sw_update_state(struct lwm2m_swmgmt_data * instance,uint8_t state)206 static void set_sw_update_state(struct lwm2m_swmgmt_data *instance, uint8_t state)
207 {
208 int ret;
209 struct lwm2m_obj_path obj_path = LWM2M_OBJ(LWM2M_OBJECT_SOFTWARE_MANAGEMENT_ID,
210 instance->obj_inst_id,
211 SWMGMT_UPDATE_STATE_ID);
212
213 ret = lwm2m_set_u8(&obj_path, state);
214 if (ret != 0) {
215 LOG_ERR("Could not set state");
216 }
217 }
218
set_sw_update_result(struct lwm2m_swmgmt_data * instance,uint8_t result)219 static void set_sw_update_result(struct lwm2m_swmgmt_data *instance, uint8_t result)
220 {
221 int ret;
222 struct lwm2m_obj_path obj_path = LWM2M_OBJ(LWM2M_OBJECT_SOFTWARE_MANAGEMENT_ID,
223 instance->obj_inst_id,
224 SWMGMT_UPDATE_RESULT_ID);
225
226 ret = lwm2m_set_u8(&obj_path, result);
227 if (ret != 0) {
228 LOG_ERR("Could not set result");
229 }
230 }
231
set_sw_update_act_state(struct lwm2m_swmgmt_data * instance,bool state)232 static void set_sw_update_act_state(struct lwm2m_swmgmt_data *instance, bool state)
233 {
234 int ret;
235 struct lwm2m_obj_path obj_path = LWM2M_OBJ(LWM2M_OBJECT_SOFTWARE_MANAGEMENT_ID,
236 instance->obj_inst_id,
237 SWMGMT_ACTIVATION_UPD_STATE_ID);
238
239 ret = lwm2m_set_bool(&obj_path, state);
240 if (ret != 0) {
241 LOG_ERR("Could not set activation state");
242 }
243 }
244
245 static struct lwm2m_swmgmt_data swmgmt_data[MAX_INSTANCE_COUNT] = { 0 };
246
find_index(uint16_t obj_inst_id)247 static struct lwm2m_swmgmt_data *find_index(uint16_t obj_inst_id)
248 {
249 int index;
250
251 for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
252 if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
253 return &swmgmt_data[index];
254 }
255 }
256
257 LOG_DBG("No instance found for obj id %u", obj_inst_id);
258 return NULL;
259 }
260
lwm2m_swmgmt_set_activate_cb(uint16_t obj_inst_id,lwm2m_engine_execute_cb_t cb)261 int lwm2m_swmgmt_set_activate_cb(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb)
262 {
263 struct lwm2m_swmgmt_data *instance = NULL;
264
265 instance = find_index(obj_inst_id);
266 if (!instance) {
267 return -ENOENT;
268 }
269
270 if (!cb) {
271 cb = callback_execute_not_defined;
272 }
273
274 instance->activate_cb = cb;
275 return 0;
276 }
277
lwm2m_swmgmt_set_deactivate_cb(uint16_t obj_inst_id,lwm2m_engine_execute_cb_t cb)278 int lwm2m_swmgmt_set_deactivate_cb(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb)
279 {
280 struct lwm2m_swmgmt_data *instance = NULL;
281
282 instance = find_index(obj_inst_id);
283 if (!instance) {
284 return -ENOENT;
285 }
286
287 if (!cb) {
288 cb = callback_execute_not_defined;
289 }
290
291 instance->deactivate_cb = cb;
292 return 0;
293 }
294
lwm2m_swmgmt_set_install_package_cb(uint16_t obj_inst_id,lwm2m_engine_execute_cb_t cb)295 int lwm2m_swmgmt_set_install_package_cb(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb)
296 {
297 struct lwm2m_swmgmt_data *instance = NULL;
298
299 instance = find_index(obj_inst_id);
300 if (!instance) {
301 return -ENOENT;
302 }
303
304 if (!cb) {
305 cb = callback_execute_not_defined;
306 }
307
308 instance->install_package_cb = cb;
309 return 0;
310 }
311
lwm2m_swmgmt_set_delete_package_cb(uint16_t obj_inst_id,lwm2m_engine_execute_cb_t cb)312 int lwm2m_swmgmt_set_delete_package_cb(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb)
313 {
314 struct lwm2m_swmgmt_data *instance = NULL;
315
316 instance = find_index(obj_inst_id);
317 if (!instance) {
318 return -ENOENT;
319 }
320
321 if (!cb) {
322 cb = callback_execute_not_defined;
323 }
324
325 instance->delete_package_cb = cb;
326 return 0;
327 }
328
lwm2m_swmgmt_set_write_package_cb(uint16_t obj_inst_id,lwm2m_engine_set_data_cb_t cb)329 int lwm2m_swmgmt_set_write_package_cb(uint16_t obj_inst_id, lwm2m_engine_set_data_cb_t cb)
330 {
331 struct lwm2m_swmgmt_data *instance = NULL;
332
333 instance = find_index(obj_inst_id);
334 if (!instance) {
335 return -ENOENT;
336 }
337
338 if (!cb) {
339 cb = callback_write_not_defined;
340 }
341
342 instance->write_package_cb = cb;
343 return 0;
344 }
345
lwm2m_swmgmt_set_read_package_version_cb(uint16_t obj_inst_id,lwm2m_engine_get_data_cb_t cb)346 int lwm2m_swmgmt_set_read_package_version_cb(uint16_t obj_inst_id, lwm2m_engine_get_data_cb_t cb)
347 {
348 struct lwm2m_swmgmt_data *instance = NULL;
349
350 instance = find_index(obj_inst_id);
351 if (!instance) {
352 return -ENOENT;
353 }
354
355 if (!cb) {
356 cb = callback_read_not_defined;
357 }
358
359 instance->read_package_cb = cb;
360 return 0;
361 }
362
state_read_pkg_version(uint16_t obj_inst_id,uint16_t res_id,uint16_t res_inst_id,size_t * data_len)363 void *state_read_pkg_version(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
364 size_t *data_len)
365 {
366 struct lwm2m_swmgmt_data *instance = NULL;
367 void *result = NULL;
368
369 instance = find_index(obj_inst_id);
370 if (!instance) {
371 return NULL;
372 }
373
374 if (instance->read_package_cb) {
375 result = instance->read_package_cb(obj_inst_id, res_id, res_inst_id, data_len);
376 }
377
378 return result;
379 }
380
handle_event(struct lwm2m_swmgmt_data * instance,uint8_t event)381 static int handle_event(struct lwm2m_swmgmt_data *instance, uint8_t event)
382 {
383 int ret = 0;
384
385 if (!instance) {
386 return -EINVAL;
387 }
388
389 switch (instance->update_state) {
390 case UPD_STATE_INITIAL:
391 switch (event) {
392 case EVENT_PKG_URI_WRITE:
393 set_sw_update_state(instance, UPD_STATE_DOWNLOAD_STARTED);
394 set_sw_update_result(instance, UPD_RES_DOWNLOADING);
395 ret = 0;
396 break;
397 default:
398 ret = -EINVAL;
399 break;
400 }
401 break;
402 case UPD_STATE_DOWNLOAD_STARTED:
403 switch (event) {
404 case EVENT_PKG_WRITTEN:
405 set_sw_update_state(instance, UPD_STATE_DOWNLOADED);
406 set_sw_update_result(instance, UPD_RES_INITIAL);
407 break;
408 case EVENT_DOWNLOAD_FAILED:
409 set_sw_update_state(instance, UPD_STATE_INITIAL);
410
411 /* Inform the instance of DOWNLOAD_FAILED by calling
412 * write_package_cb with a bunch of NULL parameters
413 */
414 instance->write_package_cb(instance->obj_inst_id, 0, 0, NULL, 0, false, 0);
415 break;
416 default:
417 ret = -EINVAL;
418 break;
419 }
420 break;
421 case UPD_STATE_DOWNLOADED:
422 switch (event) {
423 case (EVENT_PKG_INTEGRITY_VERIFIED):
424 set_sw_update_state(instance, UPD_STATE_DELIVERED);
425 set_sw_update_result(instance, UPD_RES_INITIAL);
426 break;
427 case (EVENT_PKG_INTEGRITY_FAILED):
428 set_sw_update_state(instance, UPD_STATE_INITIAL);
429 set_sw_update_result(instance, UPD_RES_PACKAGE_INTEGRITY_CHECK_FAILURE);
430 break;
431 default:
432 ret = -EINVAL;
433 break;
434 }
435 break;
436 case UPD_STATE_DELIVERED:
437 switch (event) {
438 case EVENT_INSTALL:
439 if (instance->next_package_is_upgrade) {
440 ret = instance->upgrade_package_cb(instance->obj_inst_id);
441 }
442
443 else {
444 ret = instance->install_package_cb(instance->obj_inst_id, NULL, 0);
445 }
446
447 break;
448
449 case EVENT_INSTALL_SUCCESSFUL:
450 set_sw_update_state(instance, UPD_STATE_INSTALLED);
451 set_sw_update_result(instance, UPD_RES_SW_SUCCESSFULLY_INSTALLED);
452 instance->next_package_is_upgrade = false;
453 break;
454
455 case EVENT_INSTALL_FAIL:
456 set_sw_update_state(instance, UPD_STATE_DELIVERED);
457 set_sw_update_result(instance, UPD_RES_SW_INSTALLATION_FAILURE);
458 break;
459
460 case EVENT_DELETE_PACKAGE:
461 ret = instance->delete_package_cb(instance->obj_inst_id, NULL, 0);
462 if (ret == 0) {
463 set_sw_update_state(instance, UPD_STATE_INITIAL);
464 /* update_result unchanged */
465 }
466 break;
467
468 default:
469 ret = -EINVAL;
470 break;
471 }
472 break;
473 case UPD_STATE_INSTALLED:
474 switch (event) {
475 case EVENT_ACTIVATE:
476 ret = instance->activate_cb(instance->obj_inst_id, NULL, 0);
477 if (ret == 0) {
478 set_sw_update_act_state(instance, true);
479 }
480 break;
481 case EVENT_DEACTIVATE:
482 ret = instance->deactivate_cb(instance->obj_inst_id, NULL, 0);
483 if (ret == 0) {
484 set_sw_update_act_state(instance, false);
485 }
486 break;
487 case EVENT_FOR_UPDATE:
488 instance->next_package_is_upgrade = true;
489 set_sw_update_state(instance, UPD_STATE_INITIAL);
490 set_sw_update_result(instance, UPD_RES_INITIAL);
491 case EVENT_DELETE_PACKAGE:
492 ret = instance->delete_package_cb(instance->obj_inst_id, NULL, 0);
493 if (ret == 0) {
494 set_sw_update_state(instance, UPD_STATE_INITIAL);
495 set_sw_update_result(instance, UPD_RES_INITIAL);
496 }
497 break;
498 default:
499 ret = -EINVAL;
500 break;
501 }
502 break;
503 default:
504 ret = -EINVAL;
505 break;
506 }
507
508 return ret;
509 }
510
install_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)511 static int install_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
512 {
513 struct lwm2m_swmgmt_data *instance = NULL;
514
515 instance = find_index(obj_inst_id);
516
517 return handle_event(instance, EVENT_INSTALL);
518 }
519
lwm2m_swmgmt_install_completed(uint16_t obj_inst_id,int error_code)520 int lwm2m_swmgmt_install_completed(uint16_t obj_inst_id, int error_code)
521 {
522 struct lwm2m_swmgmt_data *instance = NULL;
523
524 instance = find_index(obj_inst_id);
525
526 if (error_code) {
527 error_code = handle_event(instance, EVENT_INSTALL_FAIL);
528 } else {
529 error_code = handle_event(instance, EVENT_INSTALL_SUCCESSFUL);
530 }
531
532 return error_code;
533 }
534
uninstall_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)535 static int uninstall_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
536 {
537 struct lwm2m_swmgmt_data *instance = NULL;
538
539 instance = find_index(obj_inst_id);
540
541 return handle_event(instance, EVENT_DELETE_PACKAGE);
542 }
543
activate_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)544 static int activate_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
545 {
546 struct lwm2m_swmgmt_data *instance = NULL;
547
548 instance = find_index(obj_inst_id);
549
550 return handle_event(instance, EVENT_ACTIVATE);
551 }
552
deactivate_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)553 static int deactivate_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
554 {
555 struct lwm2m_swmgmt_data *instance = NULL;
556
557 instance = find_index(obj_inst_id);
558
559 return handle_event(instance, EVENT_DEACTIVATE);
560 }
561
package_write_cb(uint16_t obj_inst_id,uint16_t res_id,uint16_t res_inst_id,uint8_t * data,uint16_t data_len,bool last_block,size_t total_size,size_t offset)562 static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id,
563 uint16_t res_inst_id, uint8_t *data,
564 uint16_t data_len, bool last_block,
565 size_t total_size, size_t offset)
566 {
567 int ret = -EINVAL;
568 struct lwm2m_swmgmt_data *instance = NULL;
569
570 instance = find_index(obj_inst_id);
571
572 ret = handle_event(instance, EVENT_PKG_URI_WRITE);
573
574 if (ret < 0) {
575 return ret;
576 }
577
578 ret = instance->write_package_cb(obj_inst_id, res_id, res_inst_id, data, data_len,
579 last_block, total_size);
580
581 if (ret < 0) {
582 handle_event(instance, EVENT_DOWNLOAD_FAILED);
583 switch (ret) {
584 case -ENOMEM:
585 set_sw_update_result(instance, UPD_RES_OUT_OF_MEMORY_DURING_DOWNLOAD);
586 break;
587 case -ENOSPC:
588 set_sw_update_result(instance, UPD_RES_NOT_ENOUGH_STORAGE);
589 ret = -EFBIG;
590 break;
591 case -EFAULT:
592 set_sw_update_result(instance, UPD_RES_PACKAGE_INTEGRITY_CHECK_FAILURE);
593 break;
594 default:
595 set_sw_update_result(instance, UPD_RES_LOST_CONNECTION_DURING_DOWNLOAD);
596 break;
597 }
598
599 return ret;
600 }
601
602 if (last_block) {
603 handle_event(instance, EVENT_PKG_WRITTEN);
604 }
605
606 return 0;
607 }
608
set_update_result(uint16_t obj_inst_id,int error_code)609 static void set_update_result(uint16_t obj_inst_id, int error_code)
610 {
611 int ret;
612 struct lwm2m_swmgmt_data *instance;
613
614 instance = find_index(obj_inst_id);
615
616 if (error_code == 0) {
617 handle_event(instance, EVENT_PKG_WRITTEN);
618
619 /* If the verify function wasn't provided, skip the check. */
620 if (verify_package) {
621 ret = verify_package();
622 } else {
623 ret = 0;
624 }
625
626 if (ret == 0) {
627 handle_event(instance, EVENT_PKG_INTEGRITY_VERIFIED);
628 } else {
629 handle_event(instance, EVENT_PKG_INTEGRITY_FAILED);
630 }
631
632 return;
633 }
634
635 handle_event(instance, EVENT_DOWNLOAD_FAILED);
636 if (error_code == -ENOMEM) {
637 set_sw_update_result(instance, UPD_RES_OUT_OF_MEMORY_DURING_DOWNLOAD);
638 } else if (error_code == -ENOSPC) {
639 set_sw_update_result(instance, UPD_RES_NOT_ENOUGH_STORAGE);
640 } else if (error_code == -EFAULT) {
641 set_sw_update_result(instance, UPD_RES_PACKAGE_INTEGRITY_CHECK_FAILURE);
642 } else if (error_code == -ENOTSUP) {
643 set_sw_update_result(instance, UPD_RES_INVALID_URI);
644 } else {
645 set_sw_update_result(instance, UPD_RES_LOST_CONNECTION_DURING_DOWNLOAD);
646 }
647 }
648
package_uri_write_cb(uint16_t obj_inst_id,uint16_t res_id,uint16_t res_inst_id,uint8_t * data,uint16_t data_len,bool last_block,size_t total_size,size_t offset)649 static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id,
650 uint16_t res_inst_id, uint8_t *data,
651 uint16_t data_len, bool last_block,
652 size_t total_size, size_t offset)
653 {
654 #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
655 int error_code;
656 struct lwm2m_swmgmt_data *instance = NULL;
657
658 instance = find_index(obj_inst_id);
659
660 struct requesting_object req = { .obj_inst_id = obj_inst_id,
661 .is_firmware_uri = false,
662 .result_cb = set_update_result,
663 .write_cb = instance->write_package_cb,
664 .verify_cb = NULL };
665
666 verify_package = req.verify_cb;
667
668 error_code = lwm2m_pull_context_start_transfer(instance->package_uri, req, K_NO_WAIT);
669
670 if (error_code) {
671 return error_code;
672 }
673
674 return handle_event(instance, EVENT_PKG_URI_WRITE);
675
676 #else
677 return -EINVAL;
678 #endif
679 }
680
swmgmt_create(uint16_t obj_inst_id)681 static struct lwm2m_engine_obj_inst *swmgmt_create(uint16_t obj_inst_id)
682 {
683 struct lwm2m_swmgmt_data *instance = NULL;
684 int index, res_idx = 0, res_inst_idx = 0;
685
686 /* Check that there is no other instance with this ID */
687 for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
688 if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
689 LOG_ERR("Can not create instance - "
690 "already existing: %u",
691 obj_inst_id);
692 return NULL;
693 }
694 }
695
696 for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
697 if (!inst[index].obj) {
698 break;
699 }
700 }
701
702 if (index >= MAX_INSTANCE_COUNT) {
703 LOG_ERR("Can not create instance - no more room: %u", obj_inst_id);
704 return NULL;
705 }
706
707 instance = &swmgmt_data[index];
708
709 /* Set default values */
710 (void)memset(res[index], 0, sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
711 init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
712
713 (void)memset(instance->package_name, 0, PACKAGE_NAME_LEN);
714 (void)memset(instance->package_version, 0, PACKAGE_VERSION_LEN);
715
716 instance->obj_inst_id = obj_inst_id;
717 instance->update_state = 0;
718 instance->update_result = 0;
719 instance->activation_state = false;
720
721 instance->next_package_is_upgrade = false;
722
723 instance->install_package_cb = callback_execute_not_defined;
724 instance->delete_package_cb = callback_execute_not_defined;
725 instance->activate_cb = callback_execute_not_defined;
726 instance->deactivate_cb = callback_execute_not_defined;
727 instance->write_package_cb = callback_write_not_defined;
728
729 #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
730 (void)memset(instance->package_uri, 0, PACKAGE_URI_LEN);
731 #endif
732
733 /* initialize instance resource data */
734 INIT_OBJ_RES_DATA_LEN(SWMGMT_PACKAGE_NAME_ID, res[index], res_idx, res_inst[index],
735 res_inst_idx, &instance->package_name, PACKAGE_NAME_LEN, 0);
736
737 INIT_OBJ_RES_LEN(SWMGMT_PACKAGE_VERSION_ID, res[index], res_idx, res_inst[index],
738 res_inst_idx, 1, false, true, &instance->package_version,
739 PACKAGE_VERSION_LEN, 0, state_read_pkg_version, NULL, NULL, NULL, NULL);
740
741 INIT_OBJ_RES_OPT(SWMGMT_PACKAGE_ID, res[index], res_idx, res_inst[index], res_inst_idx, 1,
742 false, false, NULL, NULL, NULL, package_write_cb, NULL);
743
744 #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
745 INIT_OBJ_RES(SWMGMT_PACKAGE_URI_ID, res[index], res_idx, res_inst[index], res_inst_idx, 1,
746 false, true, instance->package_uri, PACKAGE_URI_LEN, NULL, NULL, NULL,
747 package_uri_write_cb, NULL);
748 #else
749 INIT_OBJ_RES_OPT(SWMGMT_PACKAGE_URI_ID, res[index], res_idx, res_inst[index], res_inst_idx,
750 1, false, true, NULL, NULL, NULL, package_uri_write_cb, NULL);
751 #endif
752
753 INIT_OBJ_RES_EXECUTE(SWMGMT_INSTALL_ID, res[index], res_idx, install_cb);
754
755 INIT_OBJ_RES_OPTDATA(SWMGMT_CHECKPOINT_ID, res[index], res_idx, res_inst[index],
756 res_inst_idx);
757
758 INIT_OBJ_RES_EXECUTE(SWMGMT_UNINSTALL_ID, res[index], res_idx, uninstall_cb);
759
760 INIT_OBJ_RES_DATA(SWMGMT_UPDATE_STATE_ID, res[index], res_idx, res_inst[index],
761 res_inst_idx, &instance->update_state, sizeof(uint8_t));
762
763 INIT_OBJ_RES_OPTDATA(SWMGMT_UPDATE_SUPPORTED_OBJECTS_ID, res[index], res_idx,
764 res_inst[index], res_inst_idx);
765
766 INIT_OBJ_RES_DATA(SWMGMT_UPDATE_RESULT_ID, res[index], res_idx, res_inst[index],
767 res_inst_idx, &instance->update_result, sizeof(uint8_t));
768
769 INIT_OBJ_RES_EXECUTE(SWMGMT_ACTIVATE_ID, res[index], res_idx, activate_cb);
770 INIT_OBJ_RES_EXECUTE(SWMGMT_DEACTIVATE_ID, res[index], res_idx, deactivate_cb);
771
772 INIT_OBJ_RES_DATA(SWMGMT_ACTIVATION_UPD_STATE_ID, res[index], res_idx, res_inst[index],
773 res_inst_idx, &instance->activation_state, sizeof(bool));
774
775 INIT_OBJ_RES_OPTDATA(SWMGMT_PACKAGE_SETTINGS_ID, res[index], res_idx, res_inst[index],
776 res_inst_idx);
777 INIT_OBJ_RES_OPTDATA(SWMGMT_USER_NAME_ID, res[index], res_idx, res_inst[index],
778 res_inst_idx);
779 INIT_OBJ_RES_OPTDATA(SWMGMT_PASSWORD_ID, res[index], res_idx, res_inst[index],
780 res_inst_idx);
781
782 inst[index].resources = res[index];
783 inst[index].resource_count = res_idx;
784 return &inst[index];
785 }
786
lwm2m_swmgmt_init(void)787 static int lwm2m_swmgmt_init(void)
788 {
789 swmgmt.obj_id = LWM2M_OBJECT_SOFTWARE_MANAGEMENT_ID;
790 swmgmt.version_major = SWMGMT_VERSION_MAJOR;
791 swmgmt.version_minor = SWMGMT_VERSION_MINOR;
792 swmgmt.fields = fields;
793 swmgmt.field_count = ARRAY_SIZE(fields);
794 swmgmt.max_instance_count = MAX_INSTANCE_COUNT;
795 swmgmt.create_cb = swmgmt_create;
796 lwm2m_register_obj(&swmgmt);
797
798 return 0;
799 }
800
801 LWM2M_OBJ_INIT(lwm2m_swmgmt_init);
802