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)190 static int callback_write_not_defined(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
191 uint8_t *data, uint16_t data_len, bool last_block,
192 size_t total_size)
193 {
194 LOG_ERR("Callback not defined for inst %u", obj_inst_id);
195 return -EINVAL;
196 }
197
callback_read_not_defined(uint16_t obj_inst_id,uint16_t res_id,uint16_t res_inst_id,size_t * data_len)198 static void *callback_read_not_defined(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
199 size_t *data_len)
200 {
201 LOG_ERR("Callback not defined for inst %u", obj_inst_id);
202 return NULL;
203 }
204
set_sw_update_state(struct lwm2m_swmgmt_data * instance,uint8_t state)205 static void set_sw_update_state(struct lwm2m_swmgmt_data *instance, uint8_t state)
206 {
207 int ret;
208 struct lwm2m_obj_path obj_path = LWM2M_OBJ(LWM2M_OBJECT_SOFTWARE_MANAGEMENT_ID,
209 instance->obj_inst_id,
210 SWMGMT_UPDATE_STATE_ID);
211
212 ret = lwm2m_set_u8(obj_path, state);
213 if (ret != 0) {
214 LOG_ERR("Could not set state");
215 }
216 }
217
set_sw_update_result(struct lwm2m_swmgmt_data * instance,uint8_t result)218 static void set_sw_update_result(struct lwm2m_swmgmt_data *instance, uint8_t result)
219 {
220 int ret;
221 struct lwm2m_obj_path obj_path = LWM2M_OBJ(LWM2M_OBJECT_SOFTWARE_MANAGEMENT_ID,
222 instance->obj_inst_id,
223 SWMGMT_UPDATE_RESULT_ID);
224
225 ret = lwm2m_set_u8(&obj_path, result);
226 if (ret != 0) {
227 LOG_ERR("Could not set result");
228 }
229 }
230
set_sw_update_act_state(struct lwm2m_swmgmt_data * instance,bool state)231 static void set_sw_update_act_state(struct lwm2m_swmgmt_data *instance, bool state)
232 {
233 int ret;
234 struct lwm2m_obj_path obj_path = LWM2M_OBJ(LWM2M_OBJECT_SOFTWARE_MANAGEMENT_ID,
235 instance->obj_inst_id,
236 SWMGMT_ACTIVATION_UPD_STATE_ID);
237
238 ret = lwm2m_set_bool(&obj_path, state);
239 if (ret != 0) {
240 LOG_ERR("Could not set activation state");
241 }
242 }
243
244 static struct lwm2m_swmgmt_data swmgmt_data[MAX_INSTANCE_COUNT] = { 0 };
245
find_index(uint16_t obj_inst_id)246 static struct lwm2m_swmgmt_data *find_index(uint16_t obj_inst_id)
247 {
248 int index;
249
250 for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
251 if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
252 return &swmgmt_data[index];
253 }
254 }
255
256 LOG_DBG("No instance found for obj id %u", obj_inst_id);
257 return NULL;
258 }
259
lwm2m_swmgmt_set_activate_cb(uint16_t obj_inst_id,lwm2m_engine_execute_cb_t cb)260 int lwm2m_swmgmt_set_activate_cb(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb)
261 {
262 struct lwm2m_swmgmt_data *instance = NULL;
263
264 instance = find_index(obj_inst_id);
265 if (!instance) {
266 return -ENOENT;
267 }
268
269 if (!cb) {
270 cb = callback_execute_not_defined;
271 }
272
273 instance->activate_cb = cb;
274 return 0;
275 }
276
lwm2m_swmgmt_set_deactivate_cb(uint16_t obj_inst_id,lwm2m_engine_execute_cb_t cb)277 int lwm2m_swmgmt_set_deactivate_cb(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb)
278 {
279 struct lwm2m_swmgmt_data *instance = NULL;
280
281 instance = find_index(obj_inst_id);
282 if (!instance) {
283 return -ENOENT;
284 }
285
286 if (!cb) {
287 cb = callback_execute_not_defined;
288 }
289
290 instance->deactivate_cb = cb;
291 return 0;
292 }
293
lwm2m_swmgmt_set_install_package_cb(uint16_t obj_inst_id,lwm2m_engine_execute_cb_t cb)294 int lwm2m_swmgmt_set_install_package_cb(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb)
295 {
296 struct lwm2m_swmgmt_data *instance = NULL;
297
298 instance = find_index(obj_inst_id);
299 if (!instance) {
300 return -ENOENT;
301 }
302
303 if (!cb) {
304 cb = callback_execute_not_defined;
305 }
306
307 instance->install_package_cb = cb;
308 return 0;
309 }
310
lwm2m_swmgmt_set_delete_package_cb(uint16_t obj_inst_id,lwm2m_engine_execute_cb_t cb)311 int lwm2m_swmgmt_set_delete_package_cb(uint16_t obj_inst_id, lwm2m_engine_execute_cb_t cb)
312 {
313 struct lwm2m_swmgmt_data *instance = NULL;
314
315 instance = find_index(obj_inst_id);
316 if (!instance) {
317 return -ENOENT;
318 }
319
320 if (!cb) {
321 cb = callback_execute_not_defined;
322 }
323
324 instance->delete_package_cb = cb;
325 return 0;
326 }
327
lwm2m_swmgmt_set_write_package_cb(uint16_t obj_inst_id,lwm2m_engine_set_data_cb_t cb)328 int lwm2m_swmgmt_set_write_package_cb(uint16_t obj_inst_id, lwm2m_engine_set_data_cb_t cb)
329 {
330 struct lwm2m_swmgmt_data *instance = NULL;
331
332 instance = find_index(obj_inst_id);
333 if (!instance) {
334 return -ENOENT;
335 }
336
337 if (!cb) {
338 cb = callback_write_not_defined;
339 }
340
341 instance->write_package_cb = cb;
342 return 0;
343 }
344
lwm2m_swmgmt_set_read_package_version_cb(uint16_t obj_inst_id,lwm2m_engine_get_data_cb_t cb)345 int lwm2m_swmgmt_set_read_package_version_cb(uint16_t obj_inst_id, lwm2m_engine_get_data_cb_t cb)
346 {
347 struct lwm2m_swmgmt_data *instance = NULL;
348
349 instance = find_index(obj_inst_id);
350 if (!instance) {
351 return -ENOENT;
352 }
353
354 if (!cb) {
355 cb = callback_read_not_defined;
356 }
357
358 instance->read_package_cb = cb;
359 return 0;
360 }
361
state_read_pkg_version(uint16_t obj_inst_id,uint16_t res_id,uint16_t res_inst_id,size_t * data_len)362 void *state_read_pkg_version(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
363 size_t *data_len)
364 {
365 struct lwm2m_swmgmt_data *instance = NULL;
366 void *result = NULL;
367
368 instance = find_index(obj_inst_id);
369 if (!instance) {
370 return NULL;
371 }
372
373 if (instance->read_package_cb) {
374 result = instance->read_package_cb(obj_inst_id, res_id, res_inst_id, data_len);
375 }
376
377 return result;
378 }
379
handle_event(struct lwm2m_swmgmt_data * instance,uint8_t event)380 static int handle_event(struct lwm2m_swmgmt_data *instance, uint8_t event)
381 {
382 int ret = 0;
383
384 if (!instance) {
385 return -EINVAL;
386 }
387
388 switch (instance->update_state) {
389 case UPD_STATE_INITIAL:
390 switch (event) {
391 case EVENT_PKG_URI_WRITE:
392 set_sw_update_state(instance, UPD_STATE_DOWNLOAD_STARTED);
393 set_sw_update_result(instance, UPD_RES_DOWNLOADING);
394 ret = 0;
395 break;
396 default:
397 ret = -EINVAL;
398 break;
399 }
400 break;
401 case UPD_STATE_DOWNLOAD_STARTED:
402 switch (event) {
403 case EVENT_PKG_WRITTEN:
404 set_sw_update_state(instance, UPD_STATE_DOWNLOADED);
405 set_sw_update_result(instance, UPD_RES_INITIAL);
406 break;
407 case EVENT_DOWNLOAD_FAILED:
408 set_sw_update_state(instance, UPD_STATE_INITIAL);
409
410 /* Inform the instance of DOWNLOAD_FAILED by calling
411 * write_package_cb with a bunch of NULL parameters
412 */
413 instance->write_package_cb(instance->obj_inst_id, 0, 0, NULL, 0, false, 0);
414 break;
415 default:
416 ret = -EINVAL;
417 break;
418 }
419 break;
420 case UPD_STATE_DOWNLOADED:
421 switch (event) {
422 case (EVENT_PKG_INTEGRITY_VERIFIED):
423 set_sw_update_state(instance, UPD_STATE_DELIVERED);
424 set_sw_update_result(instance, UPD_RES_INITIAL);
425 break;
426 case (EVENT_PKG_INTEGRITY_FAILED):
427 set_sw_update_state(instance, UPD_STATE_INITIAL);
428 set_sw_update_result(instance, UPD_RES_PACKAGE_INTEGRITY_CHECK_FAILURE);
429 break;
430 default:
431 ret = -EINVAL;
432 break;
433 }
434 break;
435 case UPD_STATE_DELIVERED:
436 switch (event) {
437 case EVENT_INSTALL:
438 if (instance->next_package_is_upgrade) {
439 ret = instance->upgrade_package_cb(instance->obj_inst_id);
440 }
441
442 else {
443 ret = instance->install_package_cb(instance->obj_inst_id, NULL, 0);
444 }
445
446 break;
447
448 case EVENT_INSTALL_SUCCESSFUL:
449 set_sw_update_state(instance, UPD_STATE_INSTALLED);
450 set_sw_update_result(instance, UPD_RES_SW_SUCCESSFULLY_INSTALLED);
451 instance->next_package_is_upgrade = false;
452 break;
453
454 case EVENT_INSTALL_FAIL:
455 set_sw_update_state(instance, UPD_STATE_DELIVERED);
456 set_sw_update_result(instance, UPD_RES_SW_INSTALLATION_FAILURE);
457 break;
458
459 case EVENT_DELETE_PACKAGE:
460 ret = instance->delete_package_cb(instance->obj_inst_id, NULL, 0);
461 if (ret == 0) {
462 set_sw_update_state(instance, UPD_STATE_INITIAL);
463 /* update_result unchanged */
464 }
465 break;
466
467 default:
468 ret = -EINVAL;
469 break;
470 }
471 break;
472 case UPD_STATE_INSTALLED:
473 switch (event) {
474 case EVENT_ACTIVATE:
475 ret = instance->activate_cb(instance->obj_inst_id, NULL, 0);
476 if (ret == 0) {
477 set_sw_update_act_state(instance, true);
478 }
479 break;
480 case EVENT_DEACTIVATE:
481 ret = instance->deactivate_cb(instance->obj_inst_id, NULL, 0);
482 if (ret == 0) {
483 set_sw_update_act_state(instance, false);
484 }
485 break;
486 case EVENT_FOR_UPDATE:
487 instance->next_package_is_upgrade = true;
488 set_sw_update_state(instance, UPD_STATE_INITIAL);
489 set_sw_update_result(instance, UPD_RES_INITIAL);
490 case EVENT_DELETE_PACKAGE:
491 ret = instance->delete_package_cb(instance->obj_inst_id, NULL, 0);
492 if (ret == 0) {
493 set_sw_update_state(instance, UPD_STATE_INITIAL);
494 set_sw_update_result(instance, UPD_RES_INITIAL);
495 }
496 break;
497 default:
498 ret = -EINVAL;
499 break;
500 }
501 break;
502 default:
503 ret = -EINVAL;
504 break;
505 }
506
507 return ret;
508 }
509
install_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)510 static int install_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
511 {
512 struct lwm2m_swmgmt_data *instance = NULL;
513
514 instance = find_index(obj_inst_id);
515
516 return handle_event(instance, EVENT_INSTALL);
517 }
518
lwm2m_swmgmt_install_completed(uint16_t obj_inst_id,int error_code)519 int lwm2m_swmgmt_install_completed(uint16_t obj_inst_id, int error_code)
520 {
521 struct lwm2m_swmgmt_data *instance = NULL;
522
523 instance = find_index(obj_inst_id);
524
525 if (error_code) {
526 error_code = handle_event(instance, EVENT_INSTALL_FAIL);
527 } else {
528 error_code = handle_event(instance, EVENT_INSTALL_SUCCESSFUL);
529 }
530
531 return error_code;
532 }
533
uninstall_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)534 static int uninstall_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
535 {
536 struct lwm2m_swmgmt_data *instance = NULL;
537
538 instance = find_index(obj_inst_id);
539
540 return handle_event(instance, EVENT_DELETE_PACKAGE);
541 }
542
activate_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)543 static int activate_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
544 {
545 struct lwm2m_swmgmt_data *instance = NULL;
546
547 instance = find_index(obj_inst_id);
548
549 return handle_event(instance, EVENT_ACTIVATE);
550 }
551
deactivate_cb(uint16_t obj_inst_id,uint8_t * args,uint16_t args_len)552 static int deactivate_cb(uint16_t obj_inst_id, uint8_t *args, uint16_t args_len)
553 {
554 struct lwm2m_swmgmt_data *instance = NULL;
555
556 instance = find_index(obj_inst_id);
557
558 return handle_event(instance, EVENT_DEACTIVATE);
559 }
560
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)561 static int package_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
562 uint8_t *data, uint16_t data_len, bool last_block, size_t total_size)
563 {
564 int ret = -EINVAL;
565 struct lwm2m_swmgmt_data *instance = NULL;
566
567 instance = find_index(obj_inst_id);
568
569 ret = handle_event(instance, EVENT_PKG_URI_WRITE);
570
571 if (ret < 0) {
572 return ret;
573 }
574
575 ret = instance->write_package_cb(obj_inst_id, res_id, res_inst_id, data, data_len,
576 last_block, total_size);
577
578 if (ret < 0) {
579 handle_event(instance, EVENT_DOWNLOAD_FAILED);
580 switch (ret) {
581 case -ENOMEM:
582 set_sw_update_result(instance, UPD_RES_OUT_OF_MEMORY_DURING_DOWNLOAD);
583 break;
584 case -ENOSPC:
585 set_sw_update_result(instance, UPD_RES_NOT_ENOUGH_STORAGE);
586 ret = -EFBIG;
587 break;
588 case -EFAULT:
589 set_sw_update_result(instance, UPD_RES_PACKAGE_INTEGRITY_CHECK_FAILURE);
590 break;
591 default:
592 set_sw_update_result(instance, UPD_RES_LOST_CONNECTION_DURING_DOWNLOAD);
593 break;
594 }
595
596 return ret;
597 }
598
599 if (last_block) {
600 handle_event(instance, EVENT_PKG_WRITTEN);
601 }
602
603 return 0;
604 }
605
set_update_result(uint16_t obj_inst_id,int error_code)606 static void set_update_result(uint16_t obj_inst_id, int error_code)
607 {
608 int ret;
609 struct lwm2m_swmgmt_data *instance;
610
611 instance = find_index(obj_inst_id);
612
613 if (error_code == 0) {
614 handle_event(instance, EVENT_PKG_WRITTEN);
615
616 /* If the verify function wasn't provided, skip the check. */
617 if (verify_package) {
618 ret = verify_package();
619 } else {
620 ret = 0;
621 }
622
623 if (ret == 0) {
624 handle_event(instance, EVENT_PKG_INTEGRITY_VERIFIED);
625 } else {
626 handle_event(instance, EVENT_PKG_INTEGRITY_FAILED);
627 }
628
629 return;
630 }
631
632 handle_event(instance, EVENT_DOWNLOAD_FAILED);
633 if (error_code == -ENOMEM) {
634 set_sw_update_result(instance, UPD_RES_OUT_OF_MEMORY_DURING_DOWNLOAD);
635 } else if (error_code == -ENOSPC) {
636 set_sw_update_result(instance, UPD_RES_NOT_ENOUGH_STORAGE);
637 } else if (error_code == -EFAULT) {
638 set_sw_update_result(instance, UPD_RES_PACKAGE_INTEGRITY_CHECK_FAILURE);
639 } else if (error_code == -ENOTSUP) {
640 set_sw_update_result(instance, UPD_RES_INVALID_URI);
641 } else {
642 set_sw_update_result(instance, UPD_RES_LOST_CONNECTION_DURING_DOWNLOAD);
643 }
644 }
645
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)646 static int package_uri_write_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id,
647 uint8_t *data, uint16_t data_len, bool last_block,
648 size_t total_size)
649 {
650 #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
651 int error_code;
652 struct lwm2m_swmgmt_data *instance = NULL;
653
654 instance = find_index(obj_inst_id);
655
656 struct requesting_object req = { .obj_inst_id = obj_inst_id,
657 .is_firmware_uri = false,
658 .result_cb = set_update_result,
659 .write_cb = instance->write_package_cb,
660 .verify_cb = NULL };
661
662 verify_package = req.verify_cb;
663
664 error_code = lwm2m_pull_context_start_transfer(instance->package_uri, req, K_NO_WAIT);
665
666 if (error_code) {
667 return error_code;
668 }
669
670 return handle_event(instance, EVENT_PKG_URI_WRITE);
671
672 #else
673 return -EINVAL;
674 #endif
675 }
676
swmgmt_create(uint16_t obj_inst_id)677 static struct lwm2m_engine_obj_inst *swmgmt_create(uint16_t obj_inst_id)
678 {
679 struct lwm2m_swmgmt_data *instance = NULL;
680 int index, res_idx = 0, res_inst_idx = 0;
681
682 /* Check that there is no other instance with this ID */
683 for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
684 if (inst[index].obj && inst[index].obj_inst_id == obj_inst_id) {
685 LOG_ERR("Can not create instance - "
686 "already existing: %u",
687 obj_inst_id);
688 return NULL;
689 }
690 }
691
692 for (index = 0; index < MAX_INSTANCE_COUNT; index++) {
693 if (!inst[index].obj) {
694 break;
695 }
696 }
697
698 if (index >= MAX_INSTANCE_COUNT) {
699 LOG_ERR("Can not create instance - no more room: %u", obj_inst_id);
700 return NULL;
701 }
702
703 instance = &swmgmt_data[index];
704
705 /* Set default values */
706 (void)memset(res[index], 0, sizeof(res[index][0]) * ARRAY_SIZE(res[index]));
707 init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index]));
708
709 (void)memset(instance->package_name, 0, PACKAGE_NAME_LEN);
710 (void)memset(instance->package_version, 0, PACKAGE_VERSION_LEN);
711
712 instance->obj_inst_id = obj_inst_id;
713 instance->update_state = 0;
714 instance->update_result = 0;
715 instance->activation_state = false;
716
717 instance->next_package_is_upgrade = false;
718
719 instance->install_package_cb = callback_execute_not_defined;
720 instance->delete_package_cb = callback_execute_not_defined;
721 instance->activate_cb = callback_execute_not_defined;
722 instance->deactivate_cb = callback_execute_not_defined;
723 instance->write_package_cb = callback_write_not_defined;
724
725 #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
726 (void)memset(instance->package_uri, 0, PACKAGE_URI_LEN);
727 #endif
728
729 /* initialize instance resource data */
730 INIT_OBJ_RES_DATA_LEN(SWMGMT_PACKAGE_NAME_ID, res[index], res_idx, res_inst[index],
731 res_inst_idx, &instance->package_name, PACKAGE_NAME_LEN, 0);
732
733 INIT_OBJ_RES_LEN(SWMGMT_PACKAGE_VERSION_ID, res[index], res_idx, res_inst[index],
734 res_inst_idx, 1, false, true, &instance->package_version,
735 PACKAGE_VERSION_LEN, 0, state_read_pkg_version, NULL, NULL, NULL, NULL);
736
737 INIT_OBJ_RES_OPT(SWMGMT_PACKAGE_ID, res[index], res_idx, res_inst[index], res_inst_idx, 1,
738 false, false, NULL, NULL, NULL, package_write_cb, NULL);
739
740 #ifdef CONFIG_LWM2M_FIRMWARE_UPDATE_PULL_SUPPORT
741 INIT_OBJ_RES(SWMGMT_PACKAGE_URI_ID, res[index], res_idx, res_inst[index], res_inst_idx, 1,
742 false, true, instance->package_uri, PACKAGE_URI_LEN, NULL, NULL, NULL,
743 package_uri_write_cb, NULL);
744 #else
745 INIT_OBJ_RES_OPT(SWMGMT_PACKAGE_URI_ID, res[index], res_idx, res_inst[index], res_inst_idx,
746 1, false, true, NULL, NULL, NULL, package_uri_write_cb, NULL);
747 #endif
748
749 INIT_OBJ_RES_EXECUTE(SWMGMT_INSTALL_ID, res[index], res_idx, install_cb);
750
751 INIT_OBJ_RES_OPTDATA(SWMGMT_CHECKPOINT_ID, res[index], res_idx, res_inst[index],
752 res_inst_idx);
753
754 INIT_OBJ_RES_EXECUTE(SWMGMT_UNINSTALL_ID, res[index], res_idx, uninstall_cb);
755
756 INIT_OBJ_RES_DATA(SWMGMT_UPDATE_STATE_ID, res[index], res_idx, res_inst[index],
757 res_inst_idx, &instance->update_state, sizeof(uint8_t));
758
759 INIT_OBJ_RES_OPTDATA(SWMGMT_UPDATE_SUPPORTED_OBJECTS_ID, res[index], res_idx,
760 res_inst[index], res_inst_idx);
761
762 INIT_OBJ_RES_DATA(SWMGMT_UPDATE_RESULT_ID, res[index], res_idx, res_inst[index],
763 res_inst_idx, &instance->update_result, sizeof(uint8_t));
764
765 INIT_OBJ_RES_EXECUTE(SWMGMT_ACTIVATE_ID, res[index], res_idx, activate_cb);
766 INIT_OBJ_RES_EXECUTE(SWMGMT_DEACTIVATE_ID, res[index], res_idx, deactivate_cb);
767
768 INIT_OBJ_RES_DATA(SWMGMT_ACTIVATION_UPD_STATE_ID, res[index], res_idx, res_inst[index],
769 res_inst_idx, &instance->activation_state, sizeof(bool));
770
771 INIT_OBJ_RES_OPTDATA(SWMGMT_PACKAGE_SETTINGS_ID, res[index], res_idx, res_inst[index],
772 res_inst_idx);
773 INIT_OBJ_RES_OPTDATA(SWMGMT_USER_NAME_ID, res[index], res_idx, res_inst[index],
774 res_inst_idx);
775 INIT_OBJ_RES_OPTDATA(SWMGMT_PASSWORD_ID, res[index], res_idx, res_inst[index],
776 res_inst_idx);
777
778 inst[index].resources = res[index];
779 inst[index].resource_count = res_idx;
780 return &inst[index];
781 }
782
lwm2m_swmgmt_init(void)783 static int lwm2m_swmgmt_init(void)
784 {
785 swmgmt.obj_id = LWM2M_OBJECT_SOFTWARE_MANAGEMENT_ID;
786 swmgmt.version_major = SWMGMT_VERSION_MAJOR;
787 swmgmt.version_minor = SWMGMT_VERSION_MINOR;
788 swmgmt.fields = fields;
789 swmgmt.field_count = ARRAY_SIZE(fields);
790 swmgmt.max_instance_count = MAX_INSTANCE_COUNT;
791 swmgmt.create_cb = swmgmt_create;
792 lwm2m_register_obj(&swmgmt);
793
794 return 0;
795 }
796
797 SYS_INIT(lwm2m_swmgmt_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
798