1 /*
2  * Copyright (C) 2015-2019 Alibaba Group Holding Limited
3  */
4 
5 #include "amp_boot_file_transfer.h"
6 
7 #include <stdarg.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "amp_platform.h"
13 #include "amp_task.h"
14 #include "amp_utils.h"
15 #include "aos/kernel.h"
16 #include "aos/vfs.h"
17 #include "aos_fs.h"
18 #include "aos_system.h"
19 #include "app_upgrade.h"
20 #include "py_defines.h"
21 #include "app_mgr.h"
22 
23 #define MOD_STR "AMP_FILE_TRANSFER"
24 
25 /* status led mode */
26 static AMP_FILE_TRANSFER_STATUS pyamp_status = AMP_FILE_TRANSFER_STATUS_NORMAL;
27 
28 // this function use to recevie ymodem data
29 extern int pyamp_ymodem_upgrade(void (*func)(unsigned char *, int));
30 
31 static unsigned char *recevie_filename = NULL;
32 static uint32_t recevie_file_size = 0;
33 static int file_fp = -1;
34 static uint32_t receive_file_offset = 0;
35 static int receive_file_end_flag = 0;
36 // static char save_path[256] = { 0 };
37 // static int32_t save_path_len = 0;
38 
39 // static PYAMP_SAVE_PATH_DEFULT pyamp_defult_save_path = PYAMP_SAVE_PATH_DEFULT_DATA;
40 
41 // void pyamp_save_path_defult_set(PYAMP_SAVE_PATH_DEFULT mode)
42 // {
43 //     pyamp_defult_save_path = mode;
44 // }
45 
46 // int pyamp_save_path_defult_get()
47 // {
48 //     return pyamp_defult_save_path;
49 // }
50 
51 // int pyamp_ymodem_check_file_path(unsigned char *path, int32_t path_len)
52 // {
53 //     int ret = 0;
54 //     // set path to test
55 //     char test_path[256] = { 0 };
56 //     char transferpath[256] = { 0 };
57 
58 //     memset(transferpath, 0, path_len);
59 //     memcpy(transferpath, path, path_len);
60 
61 //     strncat(test_path, transferpath, sizeof(test_path) - 1);
62 //     strncat(test_path, "_pathTest", sizeof(test_path) - 1);
63 
64 //     ret = aos_mkdir(test_path);
65 //     if (ret == 0) {
66 //         ret = aos_rmdir_r(test_path);
67 //     }
68 
69 //     return ret;
70 // }
71 
72 // void pyamp_ymodem_save_file_path(unsigned char *path, int32_t path_len)
73 // {
74 //     if (path_len != 0) {
75 //         save_path_len = path_len;
76 //         memset(save_path, 0, path_len);
77 //         memcpy(save_path, path, path_len);
78 //     } else {
79 //         save_path_len = path_len;
80 //     }
81 // }
82 
83 // int pyamp_ymodem_get_file_path(unsigned char *path, int32_t path_len)
84 // {
85 //     if (save_path_len != 0) {
86 //         memcpy(path, save_path, path_len);
87 //         return save_path_len;
88 //     }
89 //     return 0;
90 // }
91 
92 // init file transfer,  register write file callback function
pyamp_ymodem_recovery_file_transfer_init()93 void pyamp_ymodem_recovery_file_transfer_init()
94 {
95     // aos_rmdir_r(AMP_FS_ROOT_DIR);
96     char save_path[256] = { 0 };
97     int save_path_len = 0;
98     save_path_len = pyamp_get_file_path(save_path, 256);
99 
100     if (save_path_len != 0) {
101         aos_mkdir(save_path);
102     } else {
103         if (pyamp_save_path_defult_get() == PYAMP_SAVE_PATH_DEFULT_SDCARD) {
104             aos_mkdir(AMP_FS_EXT_ROOT_DIR);
105         } else {
106             aos_mkdir(AMP_FS_ROOT_DIR);
107         }
108     }
109 }
110 
111 // finish this package transfer
112 // only transfer this package
pyamp_ymodem_recovery_file_transfer_finish(void)113 void pyamp_ymodem_recovery_file_transfer_finish(void)
114 {
115     pyamp_file_transfer_status_set(AMP_FILE_TRANSFER_STATUS_NORMAL);
116     // LOGD(MOD_STR, "pyamp_ymodem_file_transfer_finish");
117 }
118 
pyamp_ymodem_installapp()119 void pyamp_ymodem_installapp()
120 {
121     const char *pFile;
122     int ret = 0;
123     char save_path[256] = { 0 };
124     int save_path_len = 0;
125     save_path_len = pyamp_get_file_path(save_path, 256);
126 
127     // step 1: judge download status
128     if (pyamp_status != AMP_FILE_TRANSFER_STATUS_INSTALL) {
129         // need free recevie file name
130         if (recevie_filename != NULL) {
131             aos_free(recevie_filename);
132             recevie_filename = NULL;
133         }
134         return;
135     }
136 
137     // step 2: judge download file name
138     pFile = strrchr(recevie_filename, '.');
139     if (pFile != NULL) {
140         // judge zip file need install
141         if (!(strcmp(pFile, ".zip"))) {
142             // make pkg path
143             char path[256] = { 0 };
144             if (save_path_len != 0) {
145                 strncat(path, save_path, sizeof(path) - 1);
146                 strncat(path, "/", sizeof(path) - 1);
147             } else {
148                 if (pyamp_save_path_defult_get() == PYAMP_SAVE_PATH_DEFULT_SDCARD) {
149                     strncat(path, AMP_FS_EXT_ROOT_DIR "/", sizeof(path) - 1);
150                 } else {
151                     strncat(path, AMP_FS_ROOT_DIR "/", sizeof(path) - 1);
152                 }
153             }
154             strncat(path, recevie_filename, sizeof(path) - 1);
155             // install app from path to default path
156             // ret = install_pyapp(path, AMP_PY_PKG_DIR);
157             if ((path != NULL) && (AMP_PY_PKG_DIR != NULL)) {
158                 // amp_debug(MOD_STR, "store_file:%s, install_file:%s\n", path, AMP_PY_PKG_DIR);
159                 ret = miniUnzip(path, AMP_PY_PKG_DIR);
160             }
161             if (ret < 0) {
162                 amp_error(MOD_STR, "py app install failed\n");
163             }
164         }
165     }
166 
167     // do not need install
168     // need free recevie file name
169     if (recevie_filename != NULL) {
170         aos_free(recevie_filename);
171         recevie_filename = NULL;
172     }
173 }
174 
pyamp_ymodem_receive_open_file(const char * targetname)175 int pyamp_ymodem_receive_open_file(const char *targetname)
176 {
177     int fp;
178     char path[256] = { 0 };
179     char save_path[256] = { 0 };
180     int save_path_len = 0;
181     save_path_len = pyamp_get_file_path(save_path, 256);
182 
183     if (targetname == NULL) {
184         return -1;
185     }
186     if (save_path_len != 0) {
187         strncat(path, save_path, sizeof(path) - 1);
188         strncat(path, "/", sizeof(path) - 1);
189     } else {
190         if (pyamp_save_path_defult_get() == PYAMP_SAVE_PATH_DEFULT_SDCARD) {
191             strncat(path, AMP_FS_EXT_ROOT_DIR "/", sizeof(path) - 1);
192         } else {
193             strncat(path, AMP_FS_ROOT_DIR "/", sizeof(path) - 1);
194         }
195     }
196     strncat(path, targetname, sizeof(path) - 1);
197 
198     int i = 1;
199     int len = strlen(path);
200     for (; i < len; i++) {
201         if (path[i] == '/') {
202             path[i] = 0;
203             aos_mkdir(path);
204             path[i] = '/';
205         }
206     }
207     // aos_printf("path=%s", path);
208     fp = aos_open(path, O_WRONLY | O_CREAT | O_TRUNC);
209 
210     return fp;
211 }
212 
pyamp_ymodem_save_transfer_file(uint8_t * buf,int32_t buf_len,AMP_FILE_RECEVIE_FLAG flag)213 int pyamp_ymodem_save_transfer_file(uint8_t *buf, int32_t buf_len, AMP_FILE_RECEVIE_FLAG flag)
214 {
215     int32_t write_buf_len = 0;
216     // judge flag
217     if (flag == YMODEM_RECEVIE_HEADER) {
218         // save file name
219         // check receive file name if free
220         if (recevie_filename != NULL) {
221             aos_free(recevie_filename);
222             recevie_filename = NULL;
223         }
224         recevie_filename = aos_malloc(buf_len);
225         memset(recevie_filename, 0, buf_len);
226         memcpy(recevie_filename, buf, buf_len);
227 
228         // aos_printf("name=%s", recevie_filename);
229     } else if (flag == YMODEM_RECEVIE_FILE_SIZE) {
230         // save file size
231         recevie_file_size = buf_len;
232         // aos_printf("size=%d", recevie_file_size);
233     } else if (flag == YMODEM_RECEVIE_BODY) {
234         int ret;
235 
236         if (file_fp == -1) {
237             file_fp = pyamp_ymodem_receive_open_file(recevie_filename);
238         }
239 
240         if (file_fp >= 0) {
241             int32_t i = 0;
242             // judge receive file size
243             receive_file_offset += buf_len;
244             if (receive_file_offset > recevie_file_size) {
245                 // need cal real size, delete 0x1A
246                 for (i = buf_len - 1; i > 0; i--) {
247                     if ((0x1a == buf[i])) {
248                         // aos_printf("len=%d", write_buf_len);
249                         // break;
250                     } else {
251                         write_buf_len = (i + 1);
252                         break;
253                     }
254                 }
255                 // aos_printf("len=%d", write_buf_len);
256                 receive_file_end_flag = 1;
257             } else if (receive_file_offset == recevie_file_size) {
258                 write_buf_len = buf_len;
259                 receive_file_end_flag = 1;
260             } else {
261                 write_buf_len = buf_len;
262             }
263 
264             if (buf_len > 0) {
265                 ret = aos_write(file_fp, buf, write_buf_len);
266             }
267 
268             if (receive_file_end_flag == 1) {
269                 ret = aos_sync(file_fp);
270                 ret = aos_close(file_fp);
271                 file_fp = -1;
272                 // reset flags
273                 receive_file_end_flag = 0;
274                 receive_file_offset = 0;
275                 recevie_file_size = 0;
276             }
277         }
278     } else if (flag == YMODEM_RECEVIE_END) {
279         // finish write file need close file fp
280         // set status install
281         pyamp_file_transfer_status_set(AMP_FILE_TRANSFER_STATUS_INSTALL);
282     } else {
283     }
284 
285     return 0;
286 }
287 
288 // recive ymodem transfer data and write to file
pyamp_ymodem_transfer_file_write(unsigned char * buf,int size,AMP_FILE_RECEVIE_FLAG flag)289 void pyamp_ymodem_transfer_file_write(unsigned char *buf, int size, AMP_FILE_RECEVIE_FLAG flag)
290 {
291     pyamp_file_transfer_status_set(AMP_FILE_TRANSFER_STATUS_UPDATING);
292     pyamp_ymodem_save_transfer_file(buf, size, flag);
293 }
294 
pyamp_file_transfer_status_set(AMP_FILE_TRANSFER_STATUS mode)295 void pyamp_file_transfer_status_set(AMP_FILE_TRANSFER_STATUS mode)
296 {
297     if (mode >= AMP_FILE_TRANSFER_STATUS_END) {
298         return;
299     }
300     pyamp_status = mode;
301 }
302 
pyamp_recovery_file_transfer()303 int pyamp_recovery_file_transfer()
304 {
305     pyamp_ymodem_recovery_file_transfer_init();
306     pyamp_ymodem_upgrade(pyamp_ymodem_transfer_file_write);
307     // instal app
308     pyamp_ymodem_installapp();
309     pyamp_ymodem_recovery_file_transfer_finish();
310 }
311