blob: 81ed76f1bc7736e2d750e6886ca2f9222a7b9374 [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"
b.liu9e8584b2024-11-06 19:21:28 +080026#include "mbtk_utils.h"
27#include "mbtk_type.h"
LUOJian60136c32023-11-24 13:59:45 +080028
29#ifdef DEBUG
30 #define fota_log(...) printf(__VA_ARGS__)
31#else
32 #define fota_log(...)
33#endif
34
LUOJian60136c32023-11-24 13:59:45 +080035#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");
b.liu9e8584b2024-11-06 19:21:28 +0800167 mbtk_system(cmd);
luojian487f2352024-08-16 17:51:48 +0800168 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");
b.liu9e8584b2024-11-06 19:21:28 +0800205 mbtk_system(cmd);
luojian487f2352024-08-16 17:51:48 +0800206 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");
b.liu9e8584b2024-11-06 19:21:28 +0800249 mbtk_system(cmd);
luojian487f2352024-08-16 17:51:48 +0800250 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");
b.liu9e8584b2024-11-06 19:21:28 +0800288 mbtk_system(cmd);
luojian487f2352024-08-16 17:51:48 +0800289 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) {
b.liu9e8584b2024-11-06 19:21:28 +0800338 mbtk_system("sync");
339 mbtk_system("reboot");
LUOJian60136c32023-11-24 13:59:45 +0800340 }
341 return 0;
LUOJian9a2d3ba2024-01-05 17:14:41 +0800342
343}
344
345int mbtk_fota_done1(int is_reboot)
346{
347 if (is_reboot) {
b.liu9e8584b2024-11-06 19:21:28 +0800348 mbtk_system("sync");
349 mbtk_system("reboot");
LUOJian9a2d3ba2024-01-05 17:14:41 +0800350 }
351 return 0;
LUOJian60136c32023-11-24 13:59:45 +0800352}
353
354void* mbtk_fota_thread(void* argc)
355{
b.liu9e8584b2024-11-06 19:21:28 +0800356 int ret;
LUOJian60136c32023-11-24 13:59:45 +0800357 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{
LUOJian60136c32023-11-24 13:59:45 +0800381 int retries = 0;
382
383 /*create ubus loop to listen to RIL event*/
384 uloop_init();
385 fota_ubus_ctx = ubus_connect(NULL);
386 if (!fota_ubus_ctx) {
luojian487f2352024-08-16 17:51:48 +0800387 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800388 uloop_done();
389 return 0;
390 }
391
392 ubus_add_uloop(fota_ubus_ctx);
393
394 do {
395 //register for ril request
396 retries = 0;
397 if (ubus_lookup_id(fota_ubus_ctx, "ota", &fota_request_id)) {
luojian487f2352024-08-16 17:51:48 +0800398 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800399 sleep(1);
400 } else {
401 break;
402 }
403 } while (retries++ < 20);
404 if (retries >= 20) {
luojian487f2352024-08-16 17:51:48 +0800405 LOGE("%s,%d\n", __FUNCTION__, __LINE__);
LUOJian60136c32023-11-24 13:59:45 +0800406 goto fail1;
407 }
408 pthread_create(&fota_status_pthread, NULL, (void*)mbtk_fota_thread, NULL);
409 fota_cb = cb;
LUOJian60136c32023-11-24 13:59:45 +0800410 return 0;
LUOJian09598702023-12-14 13:58:42 +0800411fail1:
412 return 1;
LUOJian60136c32023-11-24 13:59:45 +0800413}
414
luojian17de8c52024-05-31 09:46:11 +0800415int mbtk_fota_get_asr_reboot_cnt_flag(void)
luojianb72371a2024-04-23 17:47:46 +0800416{
luojian49e53402024-06-05 15:37:57 +0800417 int type = 0;
418 char time_type[] ={0};
419 property_get("persist.mbtk.reboot_cnt", time_type, "0");
luojianb72371a2024-04-23 17:47:46 +0800420
luojian49e53402024-06-05 15:37:57 +0800421 type = atoi(time_type);
luojianb72371a2024-04-23 17:47:46 +0800422
luojian49e53402024-06-05 15:37:57 +0800423 return type;
luojianb72371a2024-04-23 17:47:46 +0800424}
425
426
LUOJian9a2d3ba2024-01-05 17:14:41 +0800427int mbtk_fota_status(void)
428{
429 return fota_dowload_flag;
430}
431
b.liubcf86c92024-08-19 19:48:28 +0800432void mbtk_fota_lib_info_print()
433{
434 MBTK_SOURCE_INFO_PRINT("mbtk_fota_lib");
435}
luojian487f2352024-08-16 17:51:48 +0800436
r.xiao4e246fe2024-11-01 03:43:58 -0700437int mbtk_fota_get_active_absys_type(void)
438{
439 int type = 0;
440 char tmp_type[] ={0};
441
442 property_get("persist.mbtk.absys_active", tmp_type, "0");
443 type = atoi(tmp_type);
444 if (type == 97)
445 {
446 type = mbtk_sys_A;
447 }
448 else if (type == 98)
449 {
450 type = mbtk_sys_B;
451 }
452 else
453 {
454 LOGE("get_active_absys_type %s fail",tmp_type);
455 type = -1;
456 }
457
458 return type;
459}
460
461int mbtk_fota_get_tmp_absys_type(void)
462{
463 int type = 0;
464 char tmp_type[] ={0};
465
466 property_get("persist.mbtk.absys_tmp", tmp_type, "0");
467 type = atoi(tmp_type);
468 if (type == 97)
469 {
470 type = mbtk_sys_A;
471 }
472 else if (type == 98)
473 {
474 type = mbtk_sys_B;
475 }
476 else
477 {
478 LOGE("get_tmp_absys_type %s fail",tmp_type);
479 type = -1;
480 }
481
482 return type;
483}
484
485int mbtk_fota_get_sync_absys_type(void)
486{
487 int type = 0;
488 char tmp_type[] ={0};
489
490 property_get("persist.mbtk.absys_sync", tmp_type, "0");
491 type = atoi(tmp_type);
492
493 return type;
494}
495
496int mbtk_fota_get_mtd_check_type(void)
497{
498 int type = 0;
499 char tmp_type[] ={0};
500
501 property_get("persist.mbtk.mtd_check", tmp_type, "0");
502 type = atoi(tmp_type);
503
504 return type;
505}
506
hj.shao0c556f52025-09-08 05:49:44 -0700507int mbtk_fota_get_sync_status(void)
508{
509 int type = 0;
510 char sync_status[] ={0};
511
512 property_get("persist.mbtk.sync_status", sync_status, "0");
513 type = atoi(sync_status);
514
515 return type;
516}