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