1
2 /*
3 * Copyright (C) 2015-2019 Alibaba Group Holding Limited
4 */
5
6 #include <stdarg.h>
7 #include <string.h>
8
9 #include "aos_system.h"
10 #include "board_config.h"
11 #include "py/builtin.h"
12 #include "py/obj.h"
13 #include "py/runtime.h"
14 #include "py/stackctrl.h"
15 #include "py_defines.h"
16 //#include "be_inl.h"
17 #include "amp_utils.h"
18 #include "app_upgrade.h"
19 #include "module_aiot.h"
20 #include "ota_agent.h"
21 #include "ota_import.h"
22
23 #define MOD_STR "APP_OTA"
24
25 static ota_service_t customer_ota_ctx = { 0 };
26 static ota_store_module_info_t customer_module_info[3];
27 static aos_task_t user_module_ota_task = { 0 };
28 static char default_ver[128] = {0};
29 typedef struct ota_package_info {
30 int res;
31 int js_cb_ref;
32 unsigned int length;
33 char version[64];
34 char module_name[64];
35 int hash_type;
36 char hash[64];
37 char store_path[64];
38 char install_path[64];
39 char url[256];
40 } ota_package_info_t;
41
42 typedef enum {
43 ON_TRIGGER = 1,
44 ON_DOWNLOAD = 2,
45 ON_VERIFY = 3,
46 ON_UPGRADE = 4,
47 } ota_cb_func_t;
48
49 static mp_obj_t ota_on_trigger;
50 static mp_obj_t ota_on_download;
51 static mp_obj_t ota_on_verify;
52 static mp_obj_t ota_on_upgrade;
53
ota_install_notify(void * pdata)54 static void ota_install_notify(void *pdata)
55 {
56 ota_package_info_t *ota_package_info = (ota_package_info_t *)pdata;
57
58 if (mp_obj_is_fun(ota_on_upgrade)) {
59 callback_to_python(ota_on_upgrade,
60 mp_obj_new_int(ota_package_info->res));
61 } else {
62 amp_error(MOD_STR, "ota_on_trigger is not function");
63 }
64
65 aos_free(ota_package_info);
66 }
67
ota_install_handler(void * pdata)68 static void ota_install_handler(void *pdata)
69 {
70 int res = -1;
71 int js_cb_ref;
72 ota_package_info_t *ota_package_info = (ota_package_info_t *)pdata;
73 /* clear jsengine timer, distory js app*/
74 // amp_module_free();
75 // app_js_stop();
76
77 res = ota_install_pyapp(&customer_ota_ctx, ota_package_info->store_path,
78 ota_package_info->length,
79 ota_package_info->install_path);
80 if (res < 0) {
81 amp_error(MOD_STR, "module install failed!");
82 } else {
83 /*启动app.js*/
84 // res = ota_load_jsapp(&customer_ota_ctx);
85 // if(res < 0) {
86 // amp_error(MOD_STR, "module load failed!");
87 // }
88 }
89 ota_package_info->res = 0;
90
91 py_task_schedule_call(ota_install_notify, ota_package_info);
92 aos_task_exit(0);
93 }
94
ota_upgrade(mp_obj_t data)95 static mp_obj_t ota_upgrade(mp_obj_t data)
96 {
97 int res = -1;
98 unsigned int length = 0;
99 const char *install_path = NULL;
100 const char *store_path = NULL;
101 aos_task_t ota_install_task;
102 ota_package_info_t *ota_package_info = NULL;
103
104 if (!mp_obj_is_dict_or_ordereddict(data)) {
105 amp_error(MOD_STR, "ota_report function param must be dict");
106 return mp_obj_new_int(-1);
107 }
108
109 /* get verify info */
110 mp_obj_t index = mp_obj_new_str_via_qstr("length", 6);
111 length = mp_obj_get_int(mp_obj_dict_get(data, index));
112
113 /* get hash_type */
114 index = mp_obj_new_str_via_qstr("store_path", 10);
115 store_path = mp_obj_str_get_str(mp_obj_dict_get(data, index));
116
117 /* get install_path */
118 index = mp_obj_new_str_via_qstr("install_path", 12);
119 install_path = mp_obj_str_get_str(mp_obj_dict_get(data, index));
120
121 ota_package_info = aos_malloc(sizeof(ota_package_info_t));
122 if (!ota_package_info) {
123 amp_error(MOD_STR, "alloc device notify param fail");
124 return;
125 }
126 memset(ota_package_info, 0x00, sizeof(ota_package_info_t));
127 ota_package_info->length = length;
128 strncpy(ota_package_info->store_path, store_path,
129 sizeof(ota_package_info->store_path));
130 strncpy(ota_package_info->install_path, install_path,
131 sizeof(ota_package_info->install_path));
132
133 res = aos_task_new_ext(&ota_install_task, "amp ota install task",
134 ota_install_handler, ota_package_info, 1024 * 10,
135 AOS_DEFAULT_APP_PRI);
136 if (res != 0) {
137 amp_warn(MOD_STR, "iot create task failed");
138 aos_free(ota_package_info);
139 goto out;
140 }
141 out:
142 mp_obj_new_int(0);
143 }
144 MP_DEFINE_CONST_FUN_OBJ_1(native_ota_upgrade, ota_upgrade);
145
ota_verify_notify(void * pdata)146 static void ota_verify_notify(void *pdata)
147 {
148 ota_package_info_t *ota_package_info = (ota_package_info_t *)pdata;
149
150 if (mp_obj_is_fun(ota_on_verify)) {
151 callback_to_python(ota_on_verify,
152 mp_obj_new_int(ota_package_info->res));
153 } else {
154 amp_error(MOD_STR, "ota_on_verify is not function");
155 }
156
157 aos_free(ota_package_info);
158 }
159
ota_verify_handler(void * pdata)160 static void ota_verify_handler(void *pdata)
161 {
162 int res = -1;
163 int js_cb_ref;
164 ota_boot_param_t ota_param = { 0 };
165 ota_package_info_t *ota_package_info = (ota_package_info_t *)pdata;
166
167 memset(&ota_param, 0, sizeof(ota_boot_param_t));
168
169 ota_param.len = ota_package_info->length;
170 ota_param.hash_type = ota_package_info->hash_type;
171 strncpy(ota_param.hash, ota_package_info->hash,
172 strlen(ota_package_info->hash));
173 res = ota_verify_fsfile(&ota_param, ota_package_info->store_path);
174 if (res < 0) {
175 amp_error(MOD_STR, "amp jsota verified failed!");
176 }
177 ota_package_info->res = res;
178 py_task_schedule_call(ota_verify_notify, ota_package_info);
179 aos_task_exit(0);
180 }
181
py_ota_verify(mp_obj_t data)182 static mp_obj_t py_ota_verify(mp_obj_t data)
183 {
184 int res = -1;
185 // int js_cb_ref;
186 aos_task_t ota_verify_task;
187 ota_package_info_t *ota_package_info = NULL;
188
189 unsigned int length = 0;
190 const char *hash_type = NULL;
191 const char *hash = NULL;
192 const char *store_path = NULL;
193
194 if (!mp_obj_is_dict_or_ordereddict(data)) {
195 amp_error(MOD_STR, "ota_report function param must be dict");
196 return mp_obj_new_int(-1);
197 }
198
199 /* get verify info */
200 // duk_get_prop_string(ctx, 0, "length");
201 mp_obj_t index = mp_obj_new_str_via_qstr("length", 6);
202 length = mp_obj_get_int(mp_obj_dict_get(data, index));
203
204 /* get hash_type */
205 index = mp_obj_new_str_via_qstr("hash_type", 9);
206 hash_type = mp_obj_str_get_str(mp_obj_dict_get(data, index));
207
208 /* get hash */
209 index = mp_obj_new_str_via_qstr("hash", 4);
210 hash = mp_obj_str_get_str(mp_obj_dict_get(data, index));
211
212 /* get store_path */
213 index = mp_obj_new_str_via_qstr("store_path", 10);
214 store_path = mp_obj_str_get_str(mp_obj_dict_get(data, index));
215
216 ota_package_info = aos_malloc(sizeof(ota_package_info_t));
217 if (!ota_package_info) {
218 amp_error(MOD_STR, "alloc device notify param fail");
219 return;
220 }
221 memset(ota_package_info, 0x00, sizeof(ota_package_info_t));
222 ota_package_info->length = length;
223 if (strcmp(hash_type, "null") == 0) {
224 ota_package_info->hash_type = 0;
225 } else if (strcmp(hash_type, "md5") == 0) {
226 ota_package_info->hash_type = 2;
227 } else if (strcmp(hash_type, "sha256") == 0) {
228 ota_package_info->hash_type = 1;
229 } else {
230 ota_package_info->hash_type = 3;
231 }
232 strncpy(ota_package_info->hash, hash, sizeof(ota_package_info->hash));
233 strncpy(ota_package_info->store_path, store_path,
234 sizeof(ota_package_info->store_path));
235
236 res = aos_task_new_ext(&ota_verify_task, "amp ota verify task",
237 ota_verify_handler, ota_package_info, 1024 * 10,
238 AOS_DEFAULT_APP_PRI);
239 if (res != 0) {
240 amp_warn(MOD_STR, "iot create task failed");
241 aos_free(ota_package_info);
242 goto out;
243 }
244 out:
245 return mp_obj_new_int(1);
246 }
247 MP_DEFINE_CONST_FUN_OBJ_1(native_ota_verify, py_ota_verify);
248
ota_download_notify(void * pdata)249 static void ota_download_notify(void *pdata)
250 {
251 ota_package_info_t *ota_package_info = (ota_package_info_t *)pdata;
252
253 if (mp_obj_is_fun(ota_on_download)) {
254 callback_to_python(ota_on_download,
255 mp_obj_new_int(ota_package_info->res));
256 } else {
257 amp_error(MOD_STR, "ota_on_download is not function");
258 }
259
260 aos_free(ota_package_info);
261 }
262
ota_download_handler(void * pdata)263 static void ota_download_handler(void *pdata)
264 {
265 int res = -1;
266 int js_cb_ref;
267 ota_package_info_t *ota_package_info = (ota_package_info_t *)pdata;
268
269 res = ota_download_store_fs_start(
270 ota_package_info->url, strlen(ota_package_info->url),
271 ota_package_info->store_path,
272 customer_ota_ctx.report_func.report_status_cb,
273 customer_ota_ctx.report_func.param);
274 if (res < 0) {
275 amp_error(MOD_STR, "amp jsota download file failed!");
276 }
277
278 ota_package_info->res = res;
279 py_task_schedule_call(ota_download_notify, ota_package_info);
280 aos_task_exit(0);
281 }
282
ota_download(mp_obj_t data)283 static mp_obj_t ota_download(mp_obj_t data)
284 {
285 int res = -1;
286 int js_cb_ref;
287 aos_task_t ota_download_task;
288 ota_package_info_t *ota_package_info = NULL;
289 const char *url = NULL;
290 const char *store_path = NULL;
291
292 if (!mp_obj_is_dict_or_ordereddict(data)) {
293 amp_error(MOD_STR, "ota_report function param must be dict");
294 return mp_obj_new_int(-1);
295 }
296
297 /* get store path */
298 mp_obj_t index = mp_obj_new_str_via_qstr("url", 3);
299 url = mp_obj_str_get_str(mp_obj_dict_get(data, index));
300
301 /* get url */
302 index = mp_obj_new_str_via_qstr("store_path", 10);
303 store_path = mp_obj_str_get_str(mp_obj_dict_get(data, index));
304
305 ota_package_info = aos_malloc(sizeof(ota_package_info_t));
306 if (!ota_package_info) {
307 amp_error(MOD_STR, "alloc device notify param fail");
308 return;
309 }
310 memset(ota_package_info, 0x00, sizeof(ota_package_info_t));
311 strncpy(ota_package_info->url, url, sizeof(ota_package_info->url));
312 strncpy(ota_package_info->store_path, store_path,
313 sizeof(ota_package_info->store_path));
314
315 res = aos_task_new_ext(&ota_download_task, "amp ota download task",
316 ota_download_handler, ota_package_info, 1024 * 10,
317 AOS_DEFAULT_APP_PRI);
318 if (res != 0) {
319 amp_warn(MOD_STR, "iot create task failed");
320 aos_free(ota_package_info);
321 goto out;
322 }
323 out:
324 return mp_obj_new_int(1);
325 }
326 MP_DEFINE_CONST_FUN_OBJ_1(native_ota_download, ota_download);
327
ota_report(mp_obj_t data)328 static mp_obj_t ota_report(mp_obj_t data)
329 {
330 int res = -1;
331 int js_cb_ref;
332 iot_device_handle_t *iot_device_handle = NULL;
333
334 if (!mp_obj_is_dict_or_ordereddict(data)) {
335 amp_error(MOD_STR, "ota_report function param must be dict");
336 return mp_obj_new_int(-1);
337 }
338
339 /* get device handle */
340 mp_obj_t index = mp_obj_new_str_via_qstr("device_handle", 13);
341 iot_device_handle = MP_OBJ_TO_PTR(mp_obj_dict_get(data, index));
342
343 /* get product_key */
344 index = mp_obj_new_str_via_qstr("product_key", 11);
345 const char *productkey = mp_obj_str_get_str(mp_obj_dict_get(data, index));
346
347 /* get devicename */
348 index = mp_obj_new_str_via_qstr("device_name", 11);
349 const char *devicename = mp_obj_str_get_str(mp_obj_dict_get(data, index));
350
351 /* get module_name */
352 index = mp_obj_new_str_via_qstr("module_name", 11);
353 const char *modulename = mp_obj_str_get_str(mp_obj_dict_get(data, index));
354
355 /* get version */
356 index = mp_obj_new_str_via_qstr("version", 7);
357 const char *ver = mp_obj_str_get_str(mp_obj_dict_get(data, index));
358
359 amp_warn(MOD_STR, "js report ver!");
360 if (!strncmp(modulename, "default", strlen("default") + 1)) {
361 strcpy(default_ver, ver);
362 }
363 res = ota_transport_inform(iot_device_handle->mqtt_handle, productkey,
364 devicename, modulename, ver);
365 if (res < 0) {
366 amp_error(MOD_STR, "amp pyota report ver failed!");
367 }
368 out:
369 return mp_obj_new_int(0);
370 }
371 MP_DEFINE_CONST_FUN_OBJ_1(native_ota_report, ota_report);
372
ota_trigger_notify(void * pdata)373 static void ota_trigger_notify(void *pdata)
374 {
375 ota_package_info_t *ota_package_info = (ota_package_info_t *)pdata;
376
377 mp_obj_t dict = mp_obj_new_dict(4);
378 mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), mp_obj_new_str("length", 6),
379 mp_obj_new_int(ota_package_info->length));
380 mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), mp_obj_new_str("module_name", 11),
381 mp_obj_new_str(ota_package_info->module_name,
382 strlen(ota_package_info->module_name)));
383 mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), mp_obj_new_str("version", 7),
384 mp_obj_new_str(ota_package_info->version,
385 strlen(ota_package_info->version)));
386 mp_obj_dict_store(
387 MP_OBJ_FROM_PTR(dict), mp_obj_new_str("url", 3),
388 mp_obj_new_str(ota_package_info->url, strlen(ota_package_info->url)));
389 mp_obj_dict_store(
390 MP_OBJ_FROM_PTR(dict), mp_obj_new_str("hash", 4),
391 mp_obj_new_str(ota_package_info->hash, strlen(ota_package_info->hash)));
392
393 const char *hash_type = NULL;
394 if (ota_package_info->hash_type == 0) {
395 hash_type = "null";
396 } else if (ota_package_info->hash_type == 1) {
397 hash_type = "sha256";
398 } else if (ota_package_info->hash_type == 2) {
399 hash_type = "md5";
400 } else {
401 hash_type = "sha512";
402 }
403 mp_obj_dict_store(MP_OBJ_FROM_PTR(dict), mp_obj_new_str("hash_type", 9),
404 mp_obj_new_str(hash_type, strlen(hash_type)));
405
406 amp_debug(MOD_STR, "module_name is %s ; length is %d",
407 ota_package_info->module_name,
408 strlen(ota_package_info->module_name));
409 amp_debug(MOD_STR, "version is %s ; length is %d",
410 ota_package_info->version, strlen(ota_package_info->version));
411
412 if (mp_obj_is_fun(ota_on_trigger)) {
413 callback_to_python(ota_on_trigger, dict);
414 } else {
415 amp_error(MOD_STR, "ota_on_trigger is not function");
416 }
417
418 aos_free(ota_package_info);
419 }
420
421 /* system image upgrade */
customer_upgrade_cb(void * pctx,char * ver,char * module_name,void * args)422 static int32_t customer_upgrade_cb(void *pctx, char *ver, char *module_name,
423 void *args)
424 {
425 int32_t ret = OTA_TRANSPORT_PAR_FAIL;
426 ota_package_info_t *ota_package_info = NULL;
427 ota_boot_param_t ota_param = { 0 };
428 aos_task_t customer_ota_task;
429 if ((pctx == NULL) || (ver == NULL) || (module_name == NULL) ||
430 (args == NULL)) {
431 amp_error(MOD_STR, "amp:ota triggered param err!");
432 return ret;
433 }
434 if (strncmp(module_name, "default", strlen(module_name)) == 0) {
435 ret = 0;
436 printf("ver:%s current_ver:%s\r\n", ver, default_ver);
437 if (strncmp(ver, default_ver, strlen(ver)) <= 0) {
438 ret = OTA_TRANSPORT_VER_FAIL;
439 amp_error(MOD_STR, "amp ota version too old!");
440 } else {
441 amp_debug(MOD_STR,
442 "ota version:%s is coming, if OTA upgrade or not ?\n",
443 ver);
444 /* clear jsengine timer, distory js app*/
445 if (aos_task_new_ext(&customer_ota_task, "amp_customer_ota",
446 internal_sys_upgrade_start, (void *)pctx,
447 1024 * 8, AOS_DEFAULT_APP_PRI) != 0) {
448 amp_debug(MOD_STR, "internal ota task create failed!");
449 ret = OTA_TRANSPORT_PAR_FAIL;
450 }
451 amp_debug(MOD_STR, "app management center start");
452 }
453 } else {
454 /*读取ota 触发时云端下发的文件信息*/
455 ret = ota_read_parameter(&ota_param);
456 if (ret < 0) {
457 amp_error(MOD_STR, "get store ota param info failed\n");
458 }
459
460 ota_package_info = aos_malloc(sizeof(ota_package_info_t));
461 if (!ota_package_info) {
462 amp_error(MOD_STR, "alloc device notify param fail");
463 return;
464 }
465
466 ota_package_info->js_cb_ref = (int)args;
467 ota_package_info->length = ota_param.len;
468 ota_package_info->hash_type = ota_param.hash_type;
469 strncpy(ota_package_info->url, ota_param.url,
470 sizeof(ota_package_info->url));
471 strncpy(ota_package_info->version, ver, strlen(ver));
472 strncpy(ota_package_info->module_name, module_name,
473 strlen(module_name));
474 strncpy(ota_package_info->hash, ota_param.hash,
475 sizeof(ota_package_info->hash));
476
477 /** todo call ota_trigger_notify */
478 py_task_schedule_call(ota_trigger_notify, ota_package_info);
479 }
480 }
481
ota_init(mp_obj_t data)482 static mp_obj_t ota_init(mp_obj_t data)
483 {
484 int res = -1;
485 int productkey_len = IOTX_PRODUCT_KEY_LEN;
486 int productsecret_len = IOTX_PRODUCT_SECRET_LEN;
487 int devicename_len = IOTX_DEVICE_NAME_LEN;
488 int devicesecret_len = IOTX_DEVICE_SECRET_LEN;
489 iot_device_handle_t *iot_device_handle = NULL;
490 ota_package_info_t *ota_package_info = NULL;
491
492 if (!mp_obj_is_dict_or_ordereddict(data)) {
493 return mp_obj_new_int(res);
494 }
495
496 /* get http request url */
497 mp_obj_t index = mp_obj_new_str_via_qstr("device_handle", 13);
498
499 iot_device_handle = MP_OBJ_TO_PTR(mp_obj_dict_get(data, index));
500 ota_service_param_reset(&customer_ota_ctx);
501 /* get device info
502 todo:save kv when do device_connect
503 */
504 aos_kv_get(AMP_CUSTOMER_PRODUCTKEY, customer_ota_ctx.pk, &productkey_len);
505 aos_kv_get(AMP_CUSTOMER_PRODUCTSECRET, customer_ota_ctx.ps,
506 &productsecret_len);
507 aos_kv_get(AMP_CUSTOMER_DEVICENAME, customer_ota_ctx.dn, &devicename_len);
508 aos_kv_get(AMP_CUSTOMER_DEVICESECRET, customer_ota_ctx.ds,
509 &devicesecret_len);
510
511 memset(customer_module_info, 0x00, sizeof(customer_module_info));
512 customer_ota_ctx.mqtt_client = (void *)iot_device_handle->mqtt_handle;
513
514 ota_package_info = aos_malloc(sizeof(ota_package_info_t));
515 if (!ota_package_info) {
516 amp_error(MOD_STR, "alloc device notify param fail");
517 goto out;
518 }
519 memset(ota_package_info, 0, sizeof(ota_package_info_t));
520 ota_package_info->js_cb_ref = 0;
521
522 ota_register_module_store(&customer_ota_ctx, customer_module_info, 3);
523 ota_register_trigger_msg_cb(&customer_ota_ctx, (void *)customer_upgrade_cb,
524 1);
525
526 /* init ota service */
527 res = ota_service_init(&customer_ota_ctx);
528 if (res < 0) {
529 amp_error(MOD_STR, "customer ota init failed!");
530 } else {
531 amp_error(MOD_STR, "customer ota init success!");
532 }
533 out:
534 if (res < 0) {
535 // todo:ota_package_info->js_cb_ref 是否需要free?
536 if (ota_package_info != NULL) {
537 aos_free(ota_package_info);
538 }
539 return mp_obj_new_int(-1);
540 }
541 mp_obj_new_int(0);
542 }
543 MP_DEFINE_CONST_FUN_OBJ_1(native_ota_init, ota_init);
544
ota_register_cb(mp_obj_t id,mp_obj_t func)545 STATIC mp_obj_t ota_register_cb(mp_obj_t id, mp_obj_t func)
546 {
547 int res = -1;
548 int callback_id = mp_obj_get_int(id);
549 switch (callback_id) {
550 case ON_TRIGGER:
551 ota_on_trigger = func;
552 break;
553 case ON_DOWNLOAD:
554 ota_on_download = func;
555 break;
556 case ON_VERIFY:
557 ota_on_verify = func;
558 break;
559 case ON_UPGRADE:
560 ota_on_upgrade = func;
561 break;
562
563 default:
564 break;
565 }
566 return mp_obj_new_int(0);
567 }
568 MP_DEFINE_CONST_FUN_OBJ_2(native_ota_register_cb, ota_register_cb);
569
570 STATIC const mp_rom_map_elem_t ota_module_globals_table[] = {
571 { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ota) },
572 { MP_OBJ_NEW_QSTR(MP_QSTR_init), MP_ROM_PTR(&native_ota_init) },
573 { MP_OBJ_NEW_QSTR(MP_QSTR_on), MP_ROM_PTR(&native_ota_register_cb) },
574 { MP_OBJ_NEW_QSTR(MP_QSTR_download), MP_ROM_PTR(&native_ota_download) },
575 { MP_OBJ_NEW_QSTR(MP_QSTR_verify), MP_ROM_PTR(&native_ota_verify) },
576 { MP_OBJ_NEW_QSTR(MP_QSTR_report), MP_ROM_PTR(&native_ota_report) },
577 { MP_OBJ_NEW_QSTR(MP_QSTR_upgrade), MP_ROM_PTR(&native_ota_upgrade) },
578 };
579
580 STATIC MP_DEFINE_CONST_DICT(ota_module_globals, ota_module_globals_table);
581
582 const mp_obj_module_t ota_module = {
583 .base = { &mp_type_module },
584 .globals = (mp_obj_dict_t *)&ota_module_globals,
585 };
586