1 /*
2 * Copyright (C) 2018-2020 Alibaba Group Holding Limited
3 */
4
5 #include <port/mesh_hal_ble.h>
6
7 #define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_MESH_DEBUG_OTA)
8 #include "common/log.h"
9 #include "bt_mesh_custom_log.h"
10
11 #include "genie_service.h"
12 #include "ali_dfu_port.h"
13
14 genie_ota_ctx_t genie_ota_ctx;
15
genie_ota_is_ready(void)16 bool genie_ota_is_ready(void)
17 {
18 return genie_ota_ctx.ota_ready;
19 }
20
genie_ota_get_indication(void)21 bool genie_ota_get_indication(void)
22 {
23 uint8_t ota_indicat = 0xFF;
24 genie_storage_status_e ret;
25
26 ret = genie_storage_read_userdata(GFI_OTA_INDICAT, &ota_indicat, sizeof(ota_indicat));
27 if (ret == GENIE_STORAGE_SUCCESS && ota_indicat == 1)
28 {
29 return 1;
30 }
31
32 return 0;
33 }
34
35 #ifdef CONFIG_GENIE_OTA_PINGPONG
ota_check_image_id(void)36 void ota_check_image_id(void)
37 {
38 uint32_t saved_ota_image_id = 0;
39 uint8_t ota_image_id = DFU_IMAGE_INVALID_ID;
40 genie_storage_status_e ret;
41
42 ret = genie_storage_read_reliable(GFI_OTA_IMAGE_ID, (uint8_t *)&saved_ota_image_id, sizeof(saved_ota_image_id));
43 if (ret == GENIE_STORAGE_SUCCESS)
44 {
45 ota_image_id = saved_ota_image_id & 0xFF;
46 if ((saved_ota_image_id >> 8) == GENIE_OTA_IMAGE_ID_MAGIC && ota_image_id < DFU_IMAGE_INVALID_ID)
47 {
48 if (ota_image_id != genie_sal_ota_get_current_image_id())
49 {
50 BT_INFO("switch to %d", ota_image_id);
51 if (genie_sal_ota_change_image_id(ota_image_id) == ota_image_id)
52 {
53 genie_storage_delete_reliable(GFI_OTA_IMAGE_ID);
54 hal_reboot();
55 }
56 }
57 }
58 BT_DBG("del change %d", ota_image_id);
59 genie_storage_delete_reliable(GFI_OTA_IMAGE_ID);
60 }
61 }
62 #endif
63
_ais_set_ota_change(void)64 static void _ais_set_ota_change(void)
65 {
66 uint8_t ota_indicat = 1;
67
68 #ifdef CONFIG_GENIE_OTA_PINGPONG
69 uint32_t ota_image_id = GENIE_OTA_IMAGE_ID_A;
70 #endif
71
72 genie_storage_write_userdata(GFI_OTA_INDICAT, &ota_indicat, sizeof(ota_indicat));
73
74 #ifdef CONFIG_GENIE_OTA_PINGPONG
75 if (genie_sal_ota_get_current_image_id() == DFU_IMAGE_A)
76 {
77 ota_image_id = GENIE_OTA_IMAGE_ID_B;
78 }
79 else
80 {
81 ota_image_id = GENIE_OTA_IMAGE_ID_A;
82 }
83
84 BT_DBG("switch to %d", ota_image_id & 0xFF);
85 genie_storage_write_reliable(GFI_OTA_IMAGE_ID, (uint8_t *)&ota_image_id, sizeof(ota_image_id));
86 #endif
87
88 genie_ota_ctx.ota_ready = 1;
89 }
90
genie_ota_status_report(void)91 void genie_ota_status_report(void)
92 {
93 uint8_t plaine_data[GENIE_CRYPTO_UNIT_SIZE];
94 uint8_t encrypt_data[GENIE_CRYPTO_UNIT_SIZE];
95
96 ais_ota_status_report_t *p_status_report = (ais_ota_status_report_t *)plaine_data;
97
98 memset(plaine_data, 11, sizeof(plaine_data));
99 p_status_report->last_seq = genie_ota_ctx.last_seq;
100 p_status_report->total_frame = genie_ota_ctx.total_frame;
101 p_status_report->rx_size = genie_ota_ctx.rx_size;
102
103 printf("ota last[%d] total[%d] size[%d] err[%d]\r\n", p_status_report->last_seq, p_status_report->total_frame, p_status_report->rx_size, genie_ota_ctx.err_count);
104
105 genie_crypto_encrypt(plaine_data, encrypt_data);
106 genie_ais_notify(0, AIS_OTA_STATUS, encrypt_data, GENIE_CRYPTO_UNIT_SIZE);
107 }
108
genie_ota_handle_version_request(uint8_t msg_id,ais_ota_ver_req_t * p_ver_req,uint8_t encrypt)109 bool genie_ota_handle_version_request(uint8_t msg_id, ais_ota_ver_req_t *p_ver_req, uint8_t encrypt)
110 {
111 uint8_t plaine_data[GENIE_CRYPTO_UNIT_SIZE];
112 uint8_t encrypt_data[GENIE_CRYPTO_UNIT_SIZE];
113
114 ais_ota_ver_resp_t *p_ver_resp = (ais_ota_ver_resp_t *)plaine_data;
115
116 if (p_ver_req->image_type == 0)
117 {
118 memset(plaine_data, 11, sizeof(plaine_data));
119 p_ver_resp->image_type = 0;
120 p_ver_resp->ver = genie_version_appver_get();
121
122 if (encrypt > 0)
123 {
124 genie_crypto_encrypt(plaine_data, encrypt_data);
125 genie_ais_notify(msg_id, AIS_OTA_VER_RESP, encrypt_data, GENIE_CRYPTO_UNIT_SIZE);
126 }
127 else
128 {
129 genie_ais_notify(msg_id, AIS_OTA_VER_RESP, plaine_data, 5); //5=sizeof(ais_ota_ver_resp_t)
130 }
131
132 return true;
133 }
134
135 return false;
136 }
137
genie_ota_handle_update_request(uint8_t msg_id,ais_ota_upd_req_t * p_ota_req,uint8_t encrypt)138 bool genie_ota_handle_update_request(uint8_t msg_id, ais_ota_upd_req_t *p_ota_req, uint8_t encrypt)
139 {
140 uint8_t plaine_data[GENIE_CRYPTO_UNIT_SIZE];
141 uint8_t encrypt_data[GENIE_CRYPTO_UNIT_SIZE];
142
143 ais_ota_upd_resp_t *p_upd_resp = (ais_ota_upd_resp_t *)plaine_data;
144
145 printf("ota ver:0x%08x imgT:%d imgS:%d maxS:%d\r\n", p_ota_req->ver, p_ota_req->image_type, p_ota_req->fw_size, ali_dfu_get_ota_partition_max_size());
146
147 memset(plaine_data, 10, sizeof(plaine_data));
148 if (p_ota_req->image_type != 0 || p_ota_req->ver <= genie_version_appver_get() ||
149 ali_dfu_get_ota_partition_max_size() < p_ota_req->fw_size || 0 == p_ota_req->fw_size) //Is illeagal
150 {
151 p_upd_resp->state = 0;
152 p_upd_resp->rx_size = 0;
153 }
154 else
155 {
156 genie_ais_state_set(AIS_STATE_OTA);
157 memset(&genie_ota_ctx, 0, sizeof(genie_ota_ctx));
158 genie_ota_ctx.image_type = p_ota_req->image_type;
159 genie_ota_ctx.image_ver = p_ota_req->ver;
160 genie_ota_ctx.image_size = p_ota_req->fw_size;
161 genie_ota_ctx.image_crc16 = p_ota_req->crc16;
162 genie_ota_ctx.ota_flag = p_ota_req->ota_flag;
163 p_upd_resp->state = 1;
164
165 /*If support breakpoint continue,you should set rx_size*/
166 p_upd_resp->rx_size = 0;
167 }
168
169 p_upd_resp->total_frame = CONFIG_AIS_TOTAL_FRAME - 1;
170
171 if (encrypt > 0)
172 {
173 genie_crypto_encrypt(plaine_data, encrypt_data);
174
175 genie_ais_notify(msg_id, AIS_OTA_UPD_RESP, encrypt_data, GENIE_CRYPTO_UNIT_SIZE);
176 }
177 else
178 {
179 genie_ais_notify(msg_id, AIS_OTA_UPD_RESP, plaine_data, 6); //response use plain data
180 }
181
182 return true;
183 }
184
genie_ota_parse_pdu(ais_pdu_t * p_msg)185 bool genie_ota_parse_pdu(ais_pdu_t *p_msg)
186 {
187 uint8_t *p_payload = p_msg->payload;
188 uint16_t payload_len = p_msg->header.payload_len;
189
190 if (p_msg->header.seq > p_msg->header.total_frame)
191 {
192 BT_ERR("invalid");
193 return false;
194 }
195
196 if (p_msg->header.seq != genie_ota_ctx.except_seq)
197 {
198 printf("except_seq:%d rx_seq:%d len:%d\r\n", genie_ota_ctx.except_seq, p_msg->header.seq, p_msg->header.payload_len);
199 if (genie_ota_ctx.err_count++ == 0)
200 {
201 /* send fail */
202 genie_ota_status_report();
203 /* refresh timer */
204 return true;
205 }
206 return false;
207 }
208
209 BT_DBG("b4:rx %d/%d", genie_ota_ctx.rx_size, genie_ota_ctx.image_size);
210 if (genie_ota_ctx.rx_size + p_msg->header.payload_len > genie_ota_ctx.image_size)
211 {
212 BT_ERR("out of size, rx %ld, recv %d", genie_ota_ctx.rx_size, p_msg->header.payload_len);
213 return false;
214 }
215
216 genie_ota_ctx.err_count = 0;
217
218 if (p_msg->header.seq == 0)
219 {
220 genie_ota_ctx.rx_len = 0;
221 memset(genie_ota_ctx.recv_buf, 0, sizeof(genie_ota_ctx.recv_buf));
222 }
223
224 if (payload_len)
225 {
226 //BT_DBG("save %d", payload_len);
227 genie_ota_ctx.flash_clean = 1;
228 memcpy(genie_ota_ctx.recv_buf + genie_ota_ctx.rx_len, p_payload, payload_len);
229 genie_ota_ctx.rx_len += payload_len;
230 }
231
232 genie_ota_ctx.last_seq = p_msg->header.seq;
233 genie_ota_ctx.total_frame = p_msg->header.total_frame;
234 genie_ota_ctx.rx_size += p_msg->header.payload_len;
235 BT_DBG("rx %d/%d", genie_ota_ctx.rx_size, genie_ota_ctx.image_size);
236 if (p_msg->header.seq == p_msg->header.total_frame)
237 {
238 ali_dfu_image_update(genie_ota_ctx.image_type,
239 genie_ota_ctx.rx_size - genie_ota_ctx.rx_len, genie_ota_ctx.rx_len,
240 (int *)genie_ota_ctx.recv_buf);
241 genie_ota_ctx.rx_len = 0;
242 genie_ota_ctx.except_seq = 0;
243 }
244 else
245 {
246 genie_ota_ctx.except_seq = p_msg->header.seq + 1;
247 }
248
249 if (genie_ota_ctx.rx_size == genie_ota_ctx.image_size || p_msg->header.seq == p_msg->header.total_frame)
250 {
251 genie_ota_status_report();
252 }
253
254 return true;
255 }
256
genie_ota_check_firmware(uint8_t msg_id,ais_ota_check_req_t * p_check_req)257 bool genie_ota_check_firmware(uint8_t msg_id, ais_ota_check_req_t *p_check_req)
258 {
259 uint16_t crc16 = 0;
260 uint8_t plaine_data[GENIE_CRYPTO_UNIT_SIZE];
261 uint8_t encrypt_data[GENIE_CRYPTO_UNIT_SIZE];
262 ais_ota_check_resp_t *p_check_resp = (ais_ota_check_resp_t *)plaine_data;
263
264 genie_ais_state_set(AIS_STATE_IDLE);
265
266 if (p_check_req->state == 1)
267 {
268 memset(plaine_data, 15, sizeof(plaine_data));
269
270 p_check_resp->state = dfu_check_checksum(genie_ota_ctx.image_type, &crc16);
271
272 BT_DBG("check %d %04x %04x", p_check_resp->state, genie_ota_ctx.image_crc16, crc16);
273 if (p_check_resp->state && crc16 != genie_ota_ctx.image_crc16)
274 {
275 p_check_resp->state = 0;
276 BT_ERR("crc error");
277 }
278
279 if (p_check_resp->state)
280 {
281 genie_ais_state_set(AIS_STATE_REBOOT);
282 _ais_set_ota_change();
283 BT_WARN("ota success, reboot in 3s!");
284 }
285 else
286 {
287 BT_ERR("ota failed");
288 }
289
290 genie_crypto_encrypt(plaine_data, encrypt_data);
291 genie_ais_notify(msg_id, AIS_OTA_CHECK_RESP, encrypt_data, GENIE_CRYPTO_UNIT_SIZE);
292
293 return true;
294 }
295 else
296 {
297 return false;
298 }
299 }
300
genie_ota_is_updating(void)301 bool genie_ota_is_updating(void)
302 {
303 return (genie_ota_ctx.rx_size > 0) ? 1 : 0;
304 }
305
ota_report_version_result_cb(transport_result_e result_e)306 static int ota_report_version_result_cb(transport_result_e result_e)
307 {
308 if (result_e == SEND_RESULT_SUCCESS)
309 {
310 genie_storage_delete_userdata(GFI_OTA_INDICAT);
311 }
312
313 return 0;
314 }
315
genie_ota_report_version(void)316 int genie_ota_report_version(void)
317 {
318 uint8_t payload[8];
319 uint32_t version = genie_version_appver_get();
320 genie_transport_payload_param_t transport_payload_param;
321
322 payload[0] = ATTR_TYPE_REPORT_VERSION & 0xff;
323 payload[1] = (ATTR_TYPE_REPORT_VERSION >> 8) & 0xff;
324 memcpy(&payload[2], &version, 4);
325 payload[6] = VENDOR_MODEL_VERSION;
326 payload[7] = SDK_VERSION;
327
328 memset(&transport_payload_param, 0, sizeof(genie_transport_payload_param_t));
329 transport_payload_param.opid = VENDOR_OP_ATTR_INDICATE;
330 transport_payload_param.p_payload = payload;
331 transport_payload_param.payload_len = sizeof(payload);
332 transport_payload_param.retry_cnt = GENIE_TRANSPORT_DEFAULT_RETRY_COUNT;
333 transport_payload_param.result_cb = ota_report_version_result_cb;
334
335 return genie_transport_send_payload(&transport_payload_param);
336 }
337
genie_ota_init(void)338 int genie_ota_init(void)
339 {
340 genie_ais_init();
341
342 genie_ota_report_version();
343
344 return 0;
345 }
346
genie_ota_pre_init(void)347 int genie_ota_pre_init(void)
348 {
349 #ifdef CONFIG_GENIE_OTA_PINGPONG
350 ota_check_image_id();
351 #endif
352
353 genie_ais_pre_init();
354
355 memset(&genie_ota_ctx, 0, sizeof(genie_ota_ctx_t));
356
357 erase_dfu_flash();
358
359 return 0;
360 }
361