1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "iotx_dm_internal.h"
5
6 #if defined(OTA_ENABLED) && !defined(BUILD_AOS)
7
8 #ifdef INFRA_MEM_STATS
9 #include "linkkit/infra/infra_mem_stats.h"
10 #define DM_COTA_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "dm.cota")
11 #define DM_COTA_FREE(ptr) LITE_free(ptr)
12 #else
13 #define DM_COTA_MALLOC(size) HAL_Malloc(size)
14 #define DM_COTA_FREE(ptr) \
15 { \
16 HAL_Free((void *)ptr); \
17 ptr = NULL; \
18 }
19 #endif
20
21 static dm_cota_ctx_t g_dm_cota_ctx;
22
dm_cota_get_ctx(void)23 dm_cota_ctx_t *dm_cota_get_ctx(void)
24 {
25 return &g_dm_cota_ctx;
26 }
27
dm_cota_init(void)28 int dm_cota_init(void)
29 {
30 dm_cota_ctx_t *ctx = dm_cota_get_ctx();
31
32 memset(ctx, 0, sizeof(dm_cota_ctx_t));
33
34 return SUCCESS_RETURN;
35 }
36
dm_cota_deinit(void)37 int dm_cota_deinit(void)
38 {
39 dm_cota_ctx_t *ctx = dm_cota_get_ctx();
40
41 memset(ctx, 0, sizeof(dm_cota_ctx_t));
42
43 return SUCCESS_RETURN;
44 }
45
_dm_cota_send_new_config_to_user(void * ota_handle)46 static int _dm_cota_send_new_config_to_user(void *ota_handle)
47 {
48 int res = 0, message_len = 0;
49 char *message = NULL;
50 uint32_t config_size = 0;
51 char *config_id = NULL, *sign = NULL, *sign_method = NULL, *url = NULL,
52 *get_type = NULL;
53 const char *cota_new_config_fmt =
54 "{\"configId\":\"%s\",\"configSize\":%d,\"getType\":\"%s\",\"sign\":\"%"
55 "s\",\"signMethod\":\"%s\",\"url\":\"%s\"}";
56
57 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_CONFIG_ID, (void *)&config_id, 1);
58 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_CONFIG_SIZE, &config_size, 4);
59 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_SIGN, (void *)&sign, 1);
60 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_SIGN_METHOD, (void *)&sign_method,
61 1);
62 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_URL, (void *)&url, 1);
63 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_GETTYPE, (void *)&get_type, 1);
64
65 if (config_id == NULL || sign == NULL || sign_method == NULL ||
66 url == NULL || get_type == NULL) {
67 res = FAIL_RETURN;
68 goto ERROR;
69 }
70
71 message_len = strlen(cota_new_config_fmt) + strlen(config_id) +
72 DM_UTILS_UINT32_STRLEN + strlen(get_type) + strlen(sign) +
73 strlen(sign_method) + strlen(url) + 1;
74
75 message = DM_malloc(message_len);
76 if (message == NULL) {
77 res = DM_MEMORY_NOT_ENOUGH;
78 goto ERROR;
79 }
80 memset(message, 0, message_len);
81 HAL_Snprintf(message, message_len, cota_new_config_fmt, config_id,
82 config_size, get_type, sign, sign_method, url);
83
84 dm_log_info("Send To User: %s", message);
85
86 res = _dm_msg_send_to_user(IOTX_DM_EVENT_COTA_NEW_CONFIG, message);
87 if (res != SUCCESS_RETURN) {
88 if (message) {
89 DM_free(message);
90 }
91 res = FAIL_RETURN;
92 goto ERROR;
93 }
94
95 res = SUCCESS_RETURN;
96 ERROR:
97 if (config_id) {
98 DM_COTA_FREE(config_id);
99 }
100 if (sign) {
101 DM_COTA_FREE(sign);
102 }
103 if (sign_method) {
104 DM_COTA_FREE(sign_method);
105 }
106 if (url) {
107 DM_COTA_FREE(url);
108 }
109 if (get_type) {
110 DM_COTA_FREE(get_type);
111 }
112
113 return res;
114 }
115
dm_cota_perform_sync(_OU_ char * output,_IN_ int output_len)116 int dm_cota_perform_sync(_OU_ char *output, _IN_ int output_len)
117 {
118 int res = 0, file_download = 0;
119 uint32_t file_size = 0, file_downloaded = 0;
120 uint32_t percent_pre = 0, percent_now = 0;
121 unsigned long long report_pre = 0, report_now = 0;
122 dm_cota_ctx_t *ctx = dm_cota_get_ctx();
123 void *ota_handle = NULL;
124 uint32_t ota_type = IOT_OTAT_NONE;
125
126 if (output == NULL || output_len <= 0) {
127 return DM_INVALID_PARAMETER;
128 }
129
130 /* Get Ota Handle */
131 res = dm_ota_get_ota_handle(&ota_handle);
132 if (res != SUCCESS_RETURN) {
133 return FAIL_RETURN;
134 }
135
136 if (ota_handle == NULL) {
137 return FAIL_RETURN;
138 }
139 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
140
141 if (ota_type != IOT_OTAT_COTA) {
142 return FAIL_RETURN;
143 }
144
145 /* reset the size_fetched in ota_handle to be 0 */
146 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_FETCHED_SIZE, ota_handle, 4);
147 /* Prepare Write Data To Storage */
148 HAL_Firmware_Persistence_Start();
149
150 while (1) {
151 file_download = IOT_OTA_FetchYield(ota_handle, output, output_len, 1);
152 if (file_download < 0) {
153 IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_FETCH_FAILED, NULL);
154 HAL_Firmware_Persistence_Stop();
155 ctx->is_report_new_config = 0;
156 return FAIL_RETURN;
157 }
158
159 /* Write Config File Into Stroage */
160 HAL_Firmware_Persistence_Write(output, file_download);
161
162 /* Get OTA information */
163 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FETCHED_SIZE, &file_downloaded, 4);
164 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FILE_SIZE, &file_size, 4);
165
166 /* Calculate Download Percent And Update Report Timestamp*/
167 percent_now = (file_downloaded * 100) / file_size;
168 report_now = HAL_UptimeMs();
169
170 /* Report Download Process To Cloud */
171 if (report_now < report_pre) {
172 report_pre = report_now;
173 }
174 if ((((percent_now - percent_pre) > 5) &&
175 ((report_now - report_pre) > 50)) ||
176 (percent_now >= IOT_OTAP_FETCH_PERCENTAGE_MAX)) {
177 IOT_OTA_ReportProgress(ota_handle, percent_now, NULL);
178 percent_pre = percent_now;
179 report_pre = report_now;
180 }
181
182 /* Check If OTA Finished */
183 if (IOT_OTA_IsFetchFinish(ota_handle)) {
184 uint32_t file_isvalid = 0;
185 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_CHECK_CONFIG, &file_isvalid, 4);
186 if (file_isvalid == 0) {
187 HAL_Firmware_Persistence_Stop();
188 ctx->is_report_new_config = 0;
189 return FAIL_RETURN;
190 } else {
191 break;
192 }
193 }
194 }
195
196 HAL_Firmware_Persistence_Stop();
197 ctx->is_report_new_config = 0;
198
199 return SUCCESS_RETURN;
200 }
201
dm_cota_get_config(const char * config_scope,const char * get_type,const char * attribute_keys)202 int dm_cota_get_config(const char *config_scope, const char *get_type,
203 const char *attribute_keys)
204 {
205 int res = 0;
206 void *ota_handle = NULL;
207
208 /* Get Ota Handle */
209 res = dm_ota_get_ota_handle(&ota_handle);
210 if (res != SUCCESS_RETURN) {
211 return FAIL_RETURN;
212 }
213
214 return iotx_ota_get_config(ota_handle, config_scope, get_type,
215 attribute_keys);
216 }
217
dm_cota_status_check(void)218 int dm_cota_status_check(void)
219 {
220 int res = 0;
221 dm_cota_ctx_t *ctx = dm_cota_get_ctx();
222 void *ota_handle = NULL;
223
224 /* Get Ota Handle */
225 res = dm_ota_get_ota_handle(&ota_handle);
226 if (res != SUCCESS_RETURN) {
227 return FAIL_RETURN;
228 }
229
230 if (IOT_OTA_IsFetching(ota_handle)) {
231 uint32_t ota_type = IOT_OTAT_NONE;
232
233 IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
234
235 if (ota_type == IOT_OTAT_COTA) {
236 /* Send New Config Information To User */
237 if (ctx->is_report_new_config == 0) {
238 dm_log_debug("Cota Status Check");
239 res = _dm_cota_send_new_config_to_user(ota_handle);
240 if (res == SUCCESS_RETURN) {
241 ctx->is_report_new_config = 1;
242 }
243 }
244 }
245 }
246
247 return SUCCESS_RETURN;
248 }
249 #endif
250