tizen: thordown: fix to check partition size more than 4GB
[profile/mobile/platform/kernel/u-boot-tm1.git] / property / thor_mode.c
1 #include <boot_mode.h>
2 #include <config.h>
3 #include <common.h>
4 #include <div64.h>
5 #include <errno.h>
6 #include <version.h>
7 #include <lcd.h>
8 #include <linux/string.h>
9 #include "../drivers/mmc/card_sdio.h"
10 #include "thor_mode.h"
11 #include "tizen_misc.h"
12
13 #ifdef THOR_DEBUG
14 #define thor_debug(fmt, arg...)         printf(fmt, ## arg)
15 #else
16 #define thor_debug(fmt, arg...)
17 #endif
18
19 static unsigned char thor_tx_data_buf[sizeof(struct rsp_box)];
20 static unsigned char thor_rx_data_buf[sizeof(struct rqt_box)];
21
22 static struct rqt_box rqt_buf;
23 static struct rsp_box rsp_buf;
24 static struct data_rsp_box data_rsp_buf;
25
26 static unsigned int thor_file_size;
27 static unsigned long long total_file_size;
28 static unsigned long long downloaded_file_size;
29
30 static u32 download_addr = CONFIG_THOR_TRANSFER_BUFFER;
31
32 /* partition info */
33 struct thor_part_info part_info;
34 static char f_name[F_NAME_BUF_SIZE];
35
36 static void thor_clear_part_info(void)
37 {
38         part_info.offset = 0;
39         part_info.size = 0;
40         part_info.blksz = 0;
41         part_info.valid = 0;
42         part_info.erase = 0;
43 }
44
45 static void send_rsp(const struct rsp_box *rsp)
46 {
47         memcpy(thor_tx_data_buf, rsp, sizeof(struct rsp_box));
48         USB_WriteEx(thor_tx_data_buf, sizeof(struct rsp_box));
49
50         thor_debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data);
51 }
52
53 static void send_data_rsp(signed int ack, signed int count)
54 {
55         struct data_rsp_box *rsp = &data_rsp_buf;
56
57         rsp->ack = ack;
58         rsp->count = count;
59
60         memcpy(thor_tx_data_buf, rsp, sizeof(struct data_rsp_box));
61         USB_WriteEx(thor_tx_data_buf, sizeof(struct data_rsp_box));
62
63         thor_debug("-DATA RSP: %d, %d\n", ack, count);
64 }
65
66 static int download_file_start(void)
67 {
68         unsigned int dn_addr;
69         unsigned int buffered = 0;
70         unsigned int remained = thor_file_size;
71         unsigned int progressed = 0;
72         unsigned int write_ofs = 0;
73
74         int ret;
75         int count = 0;
76         int download_done = 0;
77         int usb_pkt_cnt = 0;
78         int per = 0;
79
80         thor_debug("Download file start\n");
81
82         while (!download_done) {
83                 dn_addr = download_addr + buffered;
84                 ret = USB_ReadEx((char *) dn_addr, THOR_PACKET_SIZE);
85                 if (ret <= 0)
86                         return ret;
87                 buffered += ret;
88                 progressed += ret;
89
90                 if (progressed >= thor_file_size)
91                         download_done = 1;
92
93                 if (download_done)
94                         downloaded_file_size += thor_file_size % ret;
95                 else
96                         downloaded_file_size += ret;
97
98                 per = (int) lldiv(100 * downloaded_file_size, total_file_size);
99                 draw_progress(per);
100
101                 /* MAX UNIT SIZE or done */
102                 if ((buffered >= THOR_STORE_UNIT_SIZE) || download_done) {
103                         unsigned int count, remain, mod;
104
105                         remain = MIN(buffered, remained);
106                         mod = remain % part_info.blksz;
107                         count = remain / part_info.blksz;
108
109                         /* write remain byte < block_size */
110                         if (mod)
111                                 count++;
112
113 #ifdef CONFIG_SIG
114                         /* check board signature when download u-boot-mmc.bin */
115                         ret = check_board_signature(f_name, download_addr, thor_file_size);
116                         if (ret) {
117                                 lcd_printf("Signature Check Failed\n");
118                                 return -EINVAL;
119                         }
120 #endif
121                         ret = Emmc_Write(PARTITION_USER, part_info.offset + write_ofs, count, download_addr);
122                         if (!ret)
123                                 return -EIO;
124
125                         write_ofs += count;
126                         remained -= buffered;
127                         buffered = 0;
128                 }
129
130                 send_data_rsp(0, ++usb_pkt_cnt);
131         }
132
133         return ret;
134 }
135
136 static long long int process_rqt_download(const struct rqt_box *rqt)
137 {
138         struct rsp_box *rsp = &rsp_buf;
139         static long long int left, ret_head;
140         int file_type, ret = 0;
141
142         memset(rsp, 0, sizeof(struct rsp_box));
143         rsp->rsp = rqt->rqt;
144         rsp->rsp_data = rqt->rqt_data;
145
146         switch (rqt->rqt_data) {
147         case RQT_DL_INIT:
148                 thor_file_size = rqt->int_data[0];
149                 total_file_size = thor_file_size;
150
151                 downloaded_file_size = 0;
152                 /* clear partition info */
153                 thor_clear_part_info();
154
155                 thor_debug("INIT: total %d bytes\n", rqt->int_data[0]);
156                 break;
157         case RQT_DL_FILE_INFO:
158                 file_type = rqt->int_data[0];
159                 if (file_type == FILE_TYPE_PIT) {
160                         thor_debug("PIT table file - not supported\n");
161                         rsp->ack = -ENOTSUPP;
162                         ret = rsp->ack;
163                         break;
164                 }
165
166                 thor_file_size = rqt->int_data[1];
167                 memcpy(f_name, rqt->str_data[0], F_NAME_BUF_SIZE);
168
169                 thor_debug("INFO: name(%s, %d), size(%llu), type(%d)\n",
170                       f_name, 0, thor_file_size, file_type);
171
172                 rsp->int_data[0] = THOR_PACKET_SIZE;
173                 /* Get partition info by binary name */
174                 ret = thor_get_part_info(&part_info, f_name);
175                 if (ret < 0) {
176                         thor_debug("Unsupported binary\n");
177                         rsp->ack = -ENODEV;
178                         ret = rsp->ack;
179                 }
180
181                 if ((uint64_t)thor_file_size >
182                     (uint64_t)part_info.size * (uint64_t)part_info.blksz) {
183                         thor_debug("Too large binary\n");
184                         rsp->ack = -EFBIG;
185                         ret = rsp->ack;
186                 }
187
188                 break;
189         case RQT_DL_FILE_START:
190                 send_rsp(rsp);
191                 return download_file_start();
192         case RQT_DL_FILE_END:
193                 thor_debug("DL FILE_END\n");
194                 break;
195         case RQT_DL_EXIT:
196                 thor_debug("DL EXIT\n");
197                 break;
198         default:
199                 thor_debug("Operation not supported: %d", rqt->rqt_data);
200                 ret = -ENOTSUPP;
201         }
202
203         send_rsp(rsp);
204         return ret;
205 }
206
207 static int process_rqt_info(const struct rqt_box *rqt)
208 {
209         struct rsp_box *rsp = &rsp_buf;
210         memset(rsp, 0, sizeof(struct rsp_box));
211
212         rsp->rsp = rqt->rqt;
213         rsp->rsp_data = rqt->rqt_data;
214
215         switch (rqt->rqt_data) {
216         case RQT_INFO_VER_PROTOCOL:
217                 rsp->int_data[0] = VER_PROTOCOL_MAJOR;
218                 rsp->int_data[1] = VER_PROTOCOL_MINOR;
219                 break;
220         case RQT_INIT_VER_HW:
221                 break;
222         case RQT_INIT_VER_BOOT:
223                 sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION);
224                 break;
225         case RQT_INIT_VER_KERNEL:
226                 sprintf(rsp->str_data[0], "%s", "k unknown");
227                 break;
228         case RQT_INIT_VER_PLATFORM:
229                 sprintf(rsp->str_data[0], "%s", "p unknown");
230                 break;
231         case RQT_INIT_VER_CSC:
232                 sprintf(rsp->str_data[0], "%s", "c unknown");
233                 break;
234         default:
235                 return -EINVAL;
236         }
237
238         send_rsp(rsp);
239         return 1;
240 }
241
242 static int process_rqt_cmd(const struct rqt_box *rqt)
243 {
244         struct rsp_box *rsp = &rsp_buf;
245         memset(rsp, 0, sizeof(struct rsp_box));
246
247         rsp->rsp = rqt->rqt;
248         rsp->rsp_data = rqt->rqt_data;
249
250         switch (rqt->rqt_data) {
251         case RQT_CMD_REBOOT:
252                 thor_debug("TARGET RESET\n");
253                 send_rsp(rsp);
254
255                 udc_power_off();
256                 thor_save_env("thor");
257                 reset_cpu(0);
258
259                 break;
260         case RQT_CMD_POWEROFF:
261         case RQT_CMD_EFSCLEAR:
262                 send_rsp(rsp);
263         default:
264                 thor_debug("Command not supported -> cmd: %d\n", rqt->rqt_data);
265                 return -EINVAL;
266         }
267
268         return 1;
269 }
270
271 static int process_data(void)
272 {
273         struct rqt_box *rqt = &rqt_buf;
274         int ret = -EINVAL;
275
276         memcpy(rqt, thor_rx_data_buf, sizeof(struct rqt_box));
277
278         thor_debug("+RQT: %d, %d\n", rqt->rqt, rqt->rqt_data);
279
280         switch (rqt->rqt) {
281         case RQT_INFO:
282                 ret = process_rqt_info(rqt);
283                 break;
284         case RQT_CMD:
285                 ret = process_rqt_cmd(rqt);
286                 break;
287         case RQT_DL:
288                 ret = (int) process_rqt_download(rqt);
289                 break;
290         case RQT_UL:
291                 break;
292         default:
293                 thor_debug("unknown request (%d)", rqt->rqt);
294         }
295
296         return ret;
297 }
298
299 int thor_handle(void)
300 {
301         int ret;
302
303 retry:
304         /* receive the data from Host PC */
305         while (1) {
306                 if (thor_usb_is_connected()) {
307                         ret = USB_ReadEx(thor_rx_data_buf, strlen("THOR"));
308                         if (!strncmp(thor_rx_data_buf, "THOR", strlen("THOR")))
309                         {
310                                 USB_WriteEx("ROHT", strlen("ROHT"));
311                                 goto retry;
312                         }
313                         ret = USB_ReadEx(thor_rx_data_buf + strlen("THOR"), sizeof(thor_rx_data_buf) - strlen("THOR"));
314
315                         if (ret > 0) {
316                                 ret = process_data();
317                                 if (ret < 0)
318                                         return ret;
319                         } else {
320                                 thor_debug("%s: No data received!\n", __func__);
321                                 return ret;
322                         }
323                 }
324         }
325
326         return 0;
327 }
328
329 extern int hw_revision;
330 void thor_mode(void)
331 {
332         lcd_set_cur_pos(1, 2);
333         lcd_printf("THOR MODE\n");
334
335         lcd_set_cur_pos(3, 2);
336         lcd_setfgcolor (CONSOLE_COLOR_WHITE);
337         lcd_printf("HW REV: %d\n", hw_revision);
338
339         MMU_DisableIDCM();
340         thor_USB_Init();
341
342         return;
343 }
344
345 int do_thor_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
346 {
347         puts("TIZEN \"THOR\" Downloader\n");
348
349         thor_mode();
350 }
351
352 U_BOOT_CMD(thordown, 1, 1, do_thor_down,
353            "TIZEN \"THOR\" downloader",
354            ""
355 );