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