blob: 323ec9be66f96fb20669d07ff5d3bc0e0004d9e9 [file] [log] [blame]
LUOJian60136c32023-11-24 13:59:45 +08001#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/types.h>
6#include <errno.h>
7#include <fcntl.h>
8#include <pthread.h>
9#include <libubox/blobmsg_json.h>
10#include "libubus.h"
r.xiao4e246fe2024-11-01 03:43:58 -070011
LUOJian09598702023-12-14 13:58:42 +080012#include <semaphore.h>
luojian49e53402024-06-05 15:37:57 +080013#include <cutils/properties.h>
r.xiao4e246fe2024-11-01 03:43:58 -070014#include <libubox/blob.h>
15#include <libubox/uloop.h>
16#include <libubox/usock.h>
17#include <libubox/list.h>
18#include <libubus.h>
19#include <uci.h>
LUOJian60136c32023-11-24 13:59:45 +080020
r.xiao4e246fe2024-11-01 03:43:58 -070021#include <sys/ioctl.h>
22#include <mtd/mtd-user.h>
23
24#include "mbtk_fota.h"
luojian487f2352024-08-16 17:51:48 +080025#include "mbtk_log.h"
26
LUOJian60136c32023-11-24 13:59:45 +080027
28#ifdef DEBUG
29 #define fota_log(...) printf(__VA_ARGS__)
30#else
31 #define fota_log(...)
32#endif
33
34#define UNUSEDPARAM(param) (void)param;
35#define OTA_MAX_STRING_LEN 128
36
37static struct ubus_context *fota_ubus_ctx = NULL;
38static uint32_t fota_request_id;
39static struct ubus_subscriber notification_event;
40static pthread_t fota_status_pthread;
41static struct blob_buf b;
42static fota_callback fota_cb = NULL;
LUOJian09598702023-12-14 13:58:42 +080043sem_t sem;
LUOJian9a2d3ba2024-01-05 17:14:41 +080044volatile int fota_dowload_flag = -1;
45//3: upding
46//4: updata success
47//5: updata fail
LUOJian60136c32023-11-24 13:59:45 +080048
49enum {
50 ATTR_SMSGPS,
51 ATTR_SMSGPS_MAX,
52};
53
54static const struct blobmsg_policy ota_info_attr_policy[] = {
55 [ATTR_SMSGPS] ={.name = "notification", .type = BLOBMSG_TYPE_STRING,},
56};
57
58/**
59 * \brief strstr_n
60 *
61 * find string return number
62 *
63 * \param param
64 * \return return type
65 */
66static int strstr_n(const char *s1, const char *s2)
67{
68 int n;
69 int strlen = 0;
70
71 if(*s2) {
72 while(*s1) {
73 for(n = 0; *(s1+n) == *(s2 + n); n++) {
74 if(!*(s2 + n + 1)) {
75 strlen++;
76 return strlen;
77 }
78 }
79 s1++;
80 strlen++;
81 }
82 return 0;
83 }
84 else
85 return 0;
86}
87
88static int otad_notify(struct ubus_context* ctx, struct ubus_object* obj,
89 struct ubus_request_data* req, const char* method,
90 struct blob_attr* msg)
91{
92 UNUSEDPARAM(ctx);
93 UNUSEDPARAM(obj);
94 UNUSEDPARAM(req);
95 UNUSEDPARAM(method);
96 // User can get downloading process information from here
97 int ret, len;
98 char progress[4] = {0};
99 char *notify_str;
100
101 struct blob_attr *tb[ATTR_SMSGPS_MAX];
102 ret = blobmsg_parse(ota_info_attr_policy, ARRAY_SIZE(ota_info_attr_policy), tb,
103 blob_data(msg), blob_len(msg));
104
105 if (ret || !tb[ATTR_SMSGPS]) {
106 printf("invalid SMS\n");
107 return -1;
108 }
109
110 notify_str = blobmsg_get_string(tb[ATTR_SMSGPS]);
111 len = strlen(notify_str);
luojian487f2352024-08-16 17:51:48 +0800112 LOGE("%s : %s\r\n", __FUNCTION__, notify_str);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800113// printf("L11111%s : %s\r\n", __FUNCTION__, notify_str);
LUOJian60136c32023-11-24 13:59:45 +0800114 if (strstr_n(notify_str, "start")) {
115 fota_cb(0, 0);
116 } else if (strstr_n(notify_str, "end[1]")) {
117 fota_cb(0, 100);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800118 fota_dowload_flag = 4;
LUOJian09598702023-12-14 13:58:42 +0800119// sem_post(&sem);
luojian487f2352024-08-16 17:51:48 +0800120 LOGE("download firmware success!\r\n");
LUOJian60136c32023-11-24 13:59:45 +0800121 } else if (strstr_n(notify_str, "end[0]")) {
122 fota_cb(1, 100);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800123 fota_dowload_flag = 5;
LUOJian09598702023-12-14 13:58:42 +0800124// sem_post(&sem);
luojian487f2352024-08-16 17:51:48 +0800125 LOGE("download firmware fail!\r\n");
LUOJian60136c32023-11-24 13:59:45 +0800126 }
127 ret = strstr_n(notify_str, "progress");
128 if (ret) {
129 memcpy(progress, &notify_str[ret + 8], len - ret - 9);
130 fota_cb(0, atoi(progress));
131 }
132 return 0;
133}
134
135static void otad_subscriber_remove_cb(struct ubus_context* ctx,
136 struct ubus_subscriber* obj, uint32_t id)
137{
138 UNUSEDPARAM(ctx);
139 UNUSEDPARAM(obj);
140 UNUSEDPARAM(id);
luojian487f2352024-08-16 17:51:48 +0800141 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800142}
143
144
145/*******************************************************************************
146* @brief write firmware package, the firmware package is written in segments.
147 and The result of the write is output by calling the callback function.
148 the firmware package size must less than 32MB
149 @param
150 fname: firmware package file
151 segment_size: the length of once write, recommending 3*1024*1024 bytes
152 @return
153 if success return 0, else return -1
154 *******************************************************************************/
155int mbtk_fota_fw_write(char* fname, int segment_size)
156{
LUOJian9a2d3ba2024-01-05 17:14:41 +0800157 fota_dowload_flag = 3;
luojian487f2352024-08-16 17:51:48 +0800158 LOGE("mbtk_fota_fw_write start3\n");
LUOJian09598702023-12-14 13:58:42 +0800159 int ret = -1;
LUOJian60136c32023-11-24 13:59:45 +0800160 static struct ubus_request req;
161 int _segment_size;
luojian487f2352024-08-16 17:51:48 +0800162 char cmd[128]={0};
163
164 if(!access("/sys/power/wake_lock", W_OK))
165 {
166 sprintf(cmd, "echo %s > /sys/power/wake_lock", "ota_lock");
167 system(cmd);
168 LOGE("/sys/power/wake_lock success\n");
169 }
170 else
171 {
172 LOGE("/sys/power/wake_lock can not write.\n");
173 }
174
LUOJian60136c32023-11-24 13:59:45 +0800175 blob_buf_init(&b, 0);
176 blobmsg_add_string(&b, "url", fname);
177 blobmsg_add_u32(&b, "type", 2);
178 blobmsg_add_u32(&b, "sync", 1);
179 _segment_size = segment_size;
180 if (_segment_size > 1024) {
181 blobmsg_add_u32(&b, "segment_size", _segment_size);
182 }
183 blobmsg_add_u32(&b, "sync", 1);
184 ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
185 ubus_complete_request_async(fota_ubus_ctx, &req);
luojian487f2352024-08-16 17:51:48 +0800186
LUOJian09598702023-12-14 13:58:42 +0800187 while(1)
188 {
luojian487f2352024-08-16 17:51:48 +0800189 /* V2������ */
LUOJian09598702023-12-14 13:58:42 +0800190// sem_wait(&sem);
191// break;
LUOJian60136c32023-11-24 13:59:45 +0800192
LUOJian9a2d3ba2024-01-05 17:14:41 +0800193 if(fota_dowload_flag != 3)
LUOJian09598702023-12-14 13:58:42 +0800194 {
LUOJian9a2d3ba2024-01-05 17:14:41 +0800195 // printf("break while(), fota_dowload_flag:%d", fota_dowload_flag);
LUOJian09598702023-12-14 13:58:42 +0800196 break;
197 }
luojian487f2352024-08-16 17:51:48 +0800198 sleep(1);
LUOJian09598702023-12-14 13:58:42 +0800199 }
luojian487f2352024-08-16 17:51:48 +0800200
201 if(!access("/sys/power/wake_unlock", W_OK))
202 {
203 char cmd[128]={0};
204 sprintf(cmd, "echo %s > /sys/power/wake_unlock", "ota_lock");
205 system(cmd);
206 LOGE("/sys/power/wake_unlock success\n");
207 }
208 else
209 {
210 LOGE("/sys/power/wake_unlock can not write.\n");
211 }
212 LOGE("%s, fota_dowload_flag = :%d", __FUNCTION__, fota_dowload_flag);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800213 if(fota_dowload_flag == 4)
LUOJian09598702023-12-14 13:58:42 +0800214 {
215 ret = 0;
216 }
217 return ret;
LUOJian60136c32023-11-24 13:59:45 +0800218}
219
LUOJian60136c32023-11-24 13:59:45 +0800220/*******************************************************************************
221* @brief download firmware by url, and write firmware package, the firmware
222 package is written in segments. The result of the write is output by
223 calling the callback function. the firmware package size must less than
224 32MB
225 @param
226 url: [IN] the address of download firmware package file, the url
227 support http or https protocol.
228 segment_size: [IN] the length of once write, recommending 3*1024*1024 bytes
229 conn_timeout: [IN] timeout to connect to the server, if set 0 that means
230 switch to the default build-in connection timeout(300s)
231 download_timeout: [IN] timeout for download the firmware file. if set 0 that means
232 it never time out
233 @return
234 if success return 0, else return -1
235 *******************************************************************************/
236int mbtk_fota_fw_write_by_url(char* url, int segment_size,
237 int conn_timeout, int download_timeout)
238{
luojian487f2352024-08-16 17:51:48 +0800239 LOGE("mbtk_fota_fw_write_by_url start2\n");
240 int ret = -1;
LUOJian9a2d3ba2024-01-05 17:14:41 +0800241 fota_dowload_flag = 3;
LUOJian60136c32023-11-24 13:59:45 +0800242 static struct ubus_request req;
243 int _segment_size;
luojian487f2352024-08-16 17:51:48 +0800244 char cmd[128]={0};
245
246 if(!access("/sys/power/wake_lock", W_OK))
247 {
248 sprintf(cmd, "echo %s > /sys/power/wake_lock", "ota_lock");
249 system(cmd);
250 LOGE("/sys/power/wake_lock success\n");
251 }
252 else
253 {
254 LOGE("/sys/power/wake_lock can not write.\n");
255 }
b.liubcf86c92024-08-19 19:48:28 +0800256
LUOJian60136c32023-11-24 13:59:45 +0800257 blob_buf_init(&b, 0);
258 blobmsg_add_string(&b, "url", url);
259 blobmsg_add_string(&b, "username", "user name");
260 blobmsg_add_u32(&b, "type", 0);
261 blobmsg_add_u32(&b, "sync", 1);
262 _segment_size = segment_size;
263 if (_segment_size > 1024) {
264 blobmsg_add_u32(&b, "segment_size", _segment_size);
265 }
266 blobmsg_add_u32(&b, "sync", 1);
267 ubus_invoke_async(fota_ubus_ctx, fota_request_id, "download", b.head, &req);
268 ubus_complete_request_async(fota_ubus_ctx, &req);
LUOJian09598702023-12-14 13:58:42 +0800269
270 while(1)
271 {
luojian487f2352024-08-16 17:51:48 +0800272 /* V2������ */
LUOJian09598702023-12-14 13:58:42 +0800273// sem_wait(&sem);
274// break;
275
LUOJian9a2d3ba2024-01-05 17:14:41 +0800276 if(fota_dowload_flag != 3)
LUOJian09598702023-12-14 13:58:42 +0800277 {
LUOJian9a2d3ba2024-01-05 17:14:41 +0800278 // printf("break while(), fota_dowload_flag:%d", fota_dowload_flag);
LUOJian09598702023-12-14 13:58:42 +0800279 break;
280 }
luojian487f2352024-08-16 17:51:48 +0800281 sleep(1);
LUOJian09598702023-12-14 13:58:42 +0800282 }
283
luojian487f2352024-08-16 17:51:48 +0800284 if(!access("/sys/power/wake_unlock", W_OK))
285 {
286 char cmd[128]={0};
287 sprintf(cmd, "echo %s > /sys/power/wake_unlock", "ota_lock");
288 system(cmd);
289 LOGE("/sys/power/wake_unlock success\n");
290 }
291 else
292 {
293 LOGE("/sys/power/wake_unlock can not write.\n");
294 }
295
296 LOGE("%s, fota_dowload_flag = :%d", __FUNCTION__, fota_dowload_flag);
LUOJian9a2d3ba2024-01-05 17:14:41 +0800297 if(fota_dowload_flag == 4)
LUOJian09598702023-12-14 13:58:42 +0800298 {
299 ret = 0;
300 }
301 return ret;
302
LUOJian60136c32023-11-24 13:59:45 +0800303}
304/*******************************************************************************
305* @brief reboot system and clear env
306 @param
307 is_reboot: if set 1, after fota success, reboot system
308 @return
309 if success return 0, else return -1
310 *******************************************************************************/
311int mbtk_fota_done(int is_reboot)
312{
313 int ret;
314
315 ret = pthread_cancel(fota_status_pthread);
luojian487f2352024-08-16 17:51:48 +0800316 LOGE("kill pthread : %d \n", ret);
LUOJian60136c32023-11-24 13:59:45 +0800317 pthread_join(fota_status_pthread, NULL);
318 do {
319 ret = pthread_kill(fota_status_pthread, 0);
luojian487f2352024-08-16 17:51:48 +0800320 LOGE("kill pthread: %d \n", ret);
LUOJian60136c32023-11-24 13:59:45 +0800321 if (ret == ESRCH) {
luojian487f2352024-08-16 17:51:48 +0800322 LOGE("The specified thread does not exist or has terminated\n");
LUOJian60136c32023-11-24 13:59:45 +0800323 } else if (ret == EINVAL) {
luojian487f2352024-08-16 17:51:48 +0800324 LOGE("Useless signal\n");
LUOJian60136c32023-11-24 13:59:45 +0800325 } else {
luojian487f2352024-08-16 17:51:48 +0800326 LOGE("The thread exists\n");
LUOJian60136c32023-11-24 13:59:45 +0800327 }
328 usleep(100000);
329 } while (0 == ret);
330
331
332 ubus_free(fota_ubus_ctx);
333 uloop_done();
334
335 fota_cb = NULL;
336
337 if (is_reboot) {
338 system("sync");
339 system("reboot");
340 }
341 return 0;
LUOJian9a2d3ba2024-01-05 17:14:41 +0800342
343}
344
345int mbtk_fota_done1(int is_reboot)
346{
347 if (is_reboot) {
348 system("sync");
349 system("reboot");
350 }
351 return 0;
LUOJian60136c32023-11-24 13:59:45 +0800352}
353
354void* mbtk_fota_thread(void* argc)
355{
356 int ret, retries = 0;
357 UNUSEDPARAM(argc);
358
LUOJian09598702023-12-14 13:58:42 +0800359 printf("mbtk_fota_thread() start\n");
360 pthread_detach(pthread_self());
LUOJian60136c32023-11-24 13:59:45 +0800361 //register for ril indication
362 ret = ubus_register_subscriber(fota_ubus_ctx, &notification_event);
363 if (ret) {
luojian487f2352024-08-16 17:51:48 +0800364 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800365 pthread_exit(NULL);
366 }
367 notification_event.cb = otad_notify;
368 notification_event.remove_cb = otad_subscriber_remove_cb;
369
370 ubus_subscribe(fota_ubus_ctx, &notification_event, fota_request_id);
371 uloop_run();
372 ubus_unsubscribe(fota_ubus_ctx, &notification_event, fota_request_id);
373 pthread_exit(NULL);
374
375 return NULL;
376}
377
378
379int mbtk_fota_init(fota_callback cb)
380{
381 int id;
382 int retries = 0;
383
384 /*create ubus loop to listen to RIL event*/
385 uloop_init();
386 fota_ubus_ctx = ubus_connect(NULL);
387 if (!fota_ubus_ctx) {
luojian487f2352024-08-16 17:51:48 +0800388 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800389 uloop_done();
390 return 0;
391 }
392
393 ubus_add_uloop(fota_ubus_ctx);
394
395 do {
396 //register for ril request
397 retries = 0;
398 if (ubus_lookup_id(fota_ubus_ctx, "ota", &fota_request_id)) {
luojian487f2352024-08-16 17:51:48 +0800399 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800400 sleep(1);
401 } else {
402 break;
403 }
404 } while (retries++ < 20);
405 if (retries >= 20) {
luojian487f2352024-08-16 17:51:48 +0800406 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800407 goto fail1;
408 }
409 pthread_create(&fota_status_pthread, NULL, (void*)mbtk_fota_thread, NULL);
410 fota_cb = cb;
LUOJian60136c32023-11-24 13:59:45 +0800411 return 0;
LUOJian09598702023-12-14 13:58:42 +0800412fail1:
413 return 1;
LUOJian60136c32023-11-24 13:59:45 +0800414}
415
luojian17de8c52024-05-31 09:46:11 +0800416int mbtk_fota_get_asr_reboot_cnt_flag(void)
luojianb72371a2024-04-23 17:47:46 +0800417{
luojian49e53402024-06-05 15:37:57 +0800418 int type = 0;
419 char time_type[] ={0};
420 property_get("persist.mbtk.reboot_cnt", time_type, "0");
luojianb72371a2024-04-23 17:47:46 +0800421
luojian49e53402024-06-05 15:37:57 +0800422 type = atoi(time_type);
luojianb72371a2024-04-23 17:47:46 +0800423
luojian49e53402024-06-05 15:37:57 +0800424 return type;
luojianb72371a2024-04-23 17:47:46 +0800425}
426
427
LUOJian9a2d3ba2024-01-05 17:14:41 +0800428int mbtk_fota_status(void)
429{
430 return fota_dowload_flag;
431}
432
b.liubcf86c92024-08-19 19:48:28 +0800433void mbtk_fota_lib_info_print()
434{
435 MBTK_SOURCE_INFO_PRINT("mbtk_fota_lib");
436}
luojian487f2352024-08-16 17:51:48 +0800437
r.xiao4e246fe2024-11-01 03:43:58 -0700438int mbtk_fota_get_active_absys_type(void)
439{
440 int type = 0;
441 char tmp_type[] ={0};
442
443 property_get("persist.mbtk.absys_active", tmp_type, "0");
444 type = atoi(tmp_type);
445 if (type == 97)
446 {
447 type = mbtk_sys_A;
448 }
449 else if (type == 98)
450 {
451 type = mbtk_sys_B;
452 }
453 else
454 {
455 LOGE("get_active_absys_type %s fail",tmp_type);
456 type = -1;
457 }
458
459 return type;
460}
461
462int mbtk_fota_get_tmp_absys_type(void)
463{
464 int type = 0;
465 char tmp_type[] ={0};
466
467 property_get("persist.mbtk.absys_tmp", tmp_type, "0");
468 type = atoi(tmp_type);
469 if (type == 97)
470 {
471 type = mbtk_sys_A;
472 }
473 else if (type == 98)
474 {
475 type = mbtk_sys_B;
476 }
477 else
478 {
479 LOGE("get_tmp_absys_type %s fail",tmp_type);
480 type = -1;
481 }
482
483 return type;
484}
485
486int mbtk_fota_get_sync_absys_type(void)
487{
488 int type = 0;
489 char tmp_type[] ={0};
490
491 property_get("persist.mbtk.absys_sync", tmp_type, "0");
492 type = atoi(tmp_type);
493
494 return type;
495}
496
497int mbtk_fota_get_mtd_check_type(void)
498{
499 int type = 0;
500 char tmp_type[] ={0};
501
502 property_get("persist.mbtk.mtd_check", tmp_type, "0");
503 type = atoi(tmp_type);
504
505 return type;
506}
507