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