4 * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
5 * PROPRIETARY/CONFIDENTIAL
6 * This software is the confidential and proprietary information of
7 * SAMSUNG ELECTRONICS ("Confidential Information").
8 * You shall not disclose such Confidential Information and shall
9 * use it only in accordance with the terms of the license agreement
10 * you entered into with SAMSUNG ELECTRONICS. SAMSUNG make no
11 * representations or warranties about the suitability
12 * of the software, either express or implied, including but not
13 * limited to the implied warranties of merchantability, fitness for
14 * a particular purpose, or non-infringement.
15 * SAMSUNG shall not be liable for any damages suffered by licensee as
16 * a result of using, modifying or distributing this software or its derivatives.
22 #include <asm/errno.h>
23 #include <asm/arch/power.h>
30 #include <mobile/header.h>
31 #include <mobile/pit.h>
32 #include <mobile/fota.h>
33 #include <mobile/misc.h>
34 #include <mobile/fs_type_check.h>
35 #include <mobile/stopwatch.h>
36 #ifndef CONFIG_CMD_PIT
37 #error "USB Downloader need to define the CONFIG_CMD_PIT"
39 #ifndef CONFIG_GENERIC_MMC
40 #error "USB Downloader need to define the CONFIG_GENERIC_MMC"
43 #define DEBUG(level, fmt, args...) \
44 if (level < debug_level) printf(fmt, ##args);
45 #define ERROR(fmt, args...) \
46 printf("error: " fmt, ##args);
48 #ifdef CONFIG_MMC_ASYNC_WRITE
49 #define mmc_async_on(d, c) mmc_async_on(d, c)
51 #define mmc_async_on(d, c) do { } while(0)
54 /* version of USB Downloader Application */
55 #define APP_VERSION "1.0"
57 /* download/upload packet size */
58 #define PKT_DOWNLOAD_SIZE (1 << 20)
59 #define PKT_DOWNLOAD_CHUNK_SIZE (32 << 20)
60 #define PKT_UPLOAD_SIZE (512 << 10)
73 static struct usbd_ops usbd_ops;
74 static struct mmc *mmc;
76 static int down_mode = MODE_NORMAL;
77 static int debug_level = 2;
78 static int check_speed = 0;
80 static u32 download_addr;
81 static u32 download_addr_ofs;
83 static u32 download_total_size;
84 static u32 download_packet_size;
85 static u32 download_unit;
86 static u32 download_prog;
87 static u32 download_prog_check;
89 static int dump_start;
93 static int file_offset;
95 extern struct pitpart_data pitparts[];
97 static int pkt_download(void *dest, const int size);
98 static void send_data_rsp(s32 ack, s32 count);
100 #ifdef CONFIG_ENV_UPDATE_WITH_DL
101 static unsigned char update_flag = 0;
105 static void set_update_state(int on)
107 static int state = 0;
115 setenv("updatestate", "going");
117 setenv("updatestate", NULL);
122 static void set_update_flag(void)
125 #ifdef CONFIG_ENV_UPDATE_WITH_DL
127 char buf[512] = {0, };
128 char *paramlist[] = { "SLP_KERNEL_NEW", "SLP_ROOTFS_NEW" };
130 if (update_flag & (1 << SLP_KERNEL_NEW))
131 setenv("SLP_KERNEL_NEW","1");
132 if (update_flag & (1 << SLP_ROOTFS_NEW))
133 setenv("SLP_ROOTFS_NEW","1");
134 #ifdef CONFIG_ENV_UPDATE_WITH_DL
135 for (i = 0; i < ARRAY_SIZE(paramlist); i++) {
136 count += sprintf(buf + count, "%s=%s;",
137 paramlist[i], getenv(paramlist[i]));
138 DEBUG(3, "buf: %s\n", buf);
141 setenv("updated", "1");
142 setenv("updateparam", buf);
144 DEBUG(1, "update env: %s(%d)\n", buf, strlen(buf));
149 static int mmc_cmd(int ops, int dev_num, ulong start, lbaint_t cnt, void *addr)
153 DEBUG(1, "mmc %s 0 0x%x 0x%x 0x%x\n", ops ? "write" : "read",
154 (u32)addr, (u32)start, (u32)cnt);
156 if (ops == OPS_WRITE)
157 ret = mmc->block_dev.block_write(dev_num, start, cnt, addr);
158 else if (ops == OPS_READ)
159 ret = mmc->block_dev.block_read(dev_num, start, cnt, addr);
169 static int mmc_write(struct usbd_ops *usbd, unsigned int len, int part_num)
173 int blk_len = len / usbd->mmc_blk;
177 if (gpt_parts <= part_num) {
178 ERROR("Partition table have %d partitions (request %d)\n",
179 gpt_parts, part_num);
183 /* check partition overwrite */
184 if ((gpt_offset[part_num] + file_offset + blk_len) > gpt_offset[part_num + 1]
185 && (part_num + 1) < gpt_parts) {
186 ERROR("download img is too large (blk size: 0x%x)\n",
187 gpt_offset[part_num + 1] - gpt_offset[part_num]);
189 set_font_color(FONT_YELLOW);
190 if (!board_no_lcd_support()) {
191 fb_printf("\nError: download img is too large\n");
197 ret = mmc_cmd(OPS_WRITE, usbd->mmc_dev,
198 gpt_offset[part_num] + file_offset,
200 (void *)download_addr);
202 file_offset += blk_len;
207 static int fs_write(struct usbd_ops *usbd, char *file_name, int part_id, int len)
210 char cmd[12], arg1[12], arg2[128], arg3[128], arg4[12];
211 char * const argv[] = {cmd, "mmc", arg1, arg2, arg3, arg4};
214 ret = fstype_register_device(&mmc->block_dev, part_id);
216 ERROR("fstype_register_divce\n");
220 sprintf(arg1, "%d:%d", usbd->mmc_dev, part_id);
221 fstype = fstype_check(&mmc->block_dev);
223 /* detect filesystem */
224 if (fstype == FS_TYPE_EXT4) {
225 #if defined(CONFIG_CMD_EXT4)
226 sprintf(cmd, "ext4write");
227 sprintf(arg2, "/%s", file_name);
228 sprintf(arg3, "0x%x", (u32)download_addr);
229 sprintf(arg4, "%d", len);
231 if (do_ext4_write(NULL, 0, 6, argv)) {
232 ERROR("writing %s\n", file_name);
237 } else if (fstype == FS_TYPE_VFAT) {
238 #if defined(CONFIG_FAT_WRITE)
239 sprintf(cmd, "fatwrite");
240 sprintf(arg2, "0x%x", (u32)download_addr);
241 sprintf(arg3, "%s", file_name);
242 sprintf(arg4, "%d", len);
244 if (do_fat_fswrite(NULL, 0, 6, argv)) {
245 ERROR("writing %s\n", file_name);
252 /* change filesystem by CONFIG define
253 fs priority: ext4 -> vfat */
254 #if defined(CONFIG_CMD_EXT4)
255 if (fstype != FS_TYPE_EXT4) {
256 sprintf(cmd, "ext4format");
257 if (do_ext4_format(NULL, 0, 3, argv)) {
258 ERROR("format with ext4\n");
263 sprintf(cmd, "ext4write");
264 sprintf(arg2, "/%s", file_name);
265 sprintf(arg3, "0x%x", (u32)download_addr);
266 sprintf(arg4, "%d", len);
268 ret = do_ext4_write(NULL, 0, 6, argv);
269 #elif defined(CONFIG_FAT_WRITE)
270 if (fstype != FS_TYPE_VFAT) {
271 sprintf(cmd, "fatformat");
272 if (do_fat_format(NULL, 0, 3, argv)) {
273 ERROR("format with vfat\n");
278 sprintf(cmd, "fatwrite");
279 sprintf(arg2, "0x%x", (u32)download_addr);
280 sprintf(arg3, "%s", file_name);
281 sprintf(arg4, "%d", len);
283 ret = do_fat_fswrite(NULL, 0, 6, argv);
285 ERROR("doesn't support filesystem\n");
290 ERROR("writing %s\n", file_name);
297 static int fusing_mmc(u32 pit_idx, u32 addr, u32 len, u32 is_last)
301 char *name = pitparts[pit_idx].name;
302 int part_id = pitparts[pit_idx].id;
303 int part_type = pitparts[pit_idx].part_type;
304 int part_fstype = pitparts[pit_idx].filesys;
306 name = pitparts[pit_idx].name;
311 DEBUG(3, "mmc (%d, %s) len(0x%x)\n", part_id, name, len);
313 if (part_id >= PIT_BOOTPART0_ID) {
314 sprintf(buf, "mmc boot 0 1 1 %d", PIT_BOOTPARTn_GET(part_id));
315 if (run_command(buf, 0) > 0) {
316 sprintf(buf, "mmc write 0 0x%x 0 0x%x", addr,
317 (u32)pitparts[pit_idx].size / usbd_ops.mmc_blk);
318 ret = run_command(buf, 0);
320 ERROR("s-boot update failed\n");
322 run_command("mmc boot 0 1 1 0", 0);
327 if (part_type != PART_TYPE_DATA) {
328 ERROR("not supported type: %d\n", part_type);
332 if (part_fstype == PART_FS_TYPE_BASIC) {
333 DEBUG(3, "at hidden partition\n");
334 ret = mmc_cmd(OPS_WRITE, usbd_ops.mmc_dev,
335 pitparts[pit_idx].offset / usbd_ops.mmc_blk,
336 pitparts[pit_idx].size / usbd_ops.mmc_blk,
339 DEBUG(3, "at normal partition as image\n");
340 int part_base = pit_get_partition_base();
341 ret = mmc_write(&usbd_ops, len, (pit_idx - part_base));
345 DEBUG(3, "mmc done\n");
350 static int fusing_fs(u32 pit_idx, u32 addr, u32 len, u32 is_last)
355 char *name = pitparts[pit_idx].name;
356 static u32 offset = 0; /* At last, offset is file size */
358 DEBUG(3, "file (%d, %s) len(0x%x)\n", pitparts[pit_idx].id, name, len);
360 memcpy(CONFIG_SYS_BACKUP_ADDR + offset, download_addr, len);
366 download_addr = CONFIG_SYS_BACKUP_ADDR;
368 if (!strncmp(name, "install-", 8) ||
369 !strncmp(name, "fota-delta", 10)) {
370 /* need to erase for hibernation */
371 erase_given_area(PARTS_QBOOT, QBOOT_ERASE_SIZE);
373 tmp_id = get_pitpart_id(PARTS_UMS);
375 tmp_id = get_pitpart_id(PARTS_BOOT);
377 part_id = pit_adjust_id_on_mmc(tmp_id);
378 ret = fs_write(&usbd_ops, pitparts[pit_idx].file_name, part_id, offset);
381 #ifdef CONFIG_FOTA_DELTA_DOWNLOAD
382 if (!ret && !strncmp(name, "fota-delta", 10)) {
383 DEBUG(3, "set FOTA flag\n");
384 board_inform_set(REBOOT_FOTA);
387 DEBUG(3, "file done\n");
392 static int update_pit(void)
394 char arg1[12], arg2[12];
395 char *argv[] = {"pit", arg1, arg2};
400 boot_idx = get_pitpart_id(PARTS_BOOT);
402 boot_offset = pitparts[boot_idx].offset;
403 boot_size = pitparts[boot_idx].size;
406 sprintf(arg1, "update");
407 sprintf(arg2, "%x", (u32)download_addr);
408 do_pit(NULL, 0, 3, argv);
410 sprintf(arg1, "write");
411 sprintf(arg2, "%x", (u32)download_addr);
412 do_pit(NULL, 0, 3, argv);
414 if (!pit_no_partition_support()) {
415 char *mbr = getenv("mbrparts");
416 int len = strlen(mbr) + 1;
417 int mbr_idx = pit_get_partition_base();
418 memcpy((void *)download_addr, (void *)mbr, len);
419 set_gpt_info(&mmc->block_dev, (char *)download_addr, len,
420 pitparts[mbr_idx].offset / usbd_ops.mmc_blk);
424 * boot partition format, that is only formatted at bootloader.
425 * format conditions are,
426 * - can't detect filesystem (e.g., not formatted, broken)
427 * - boot partition size or location is changed.
429 boot_idx = get_pitpart_id(PARTS_BOOT);
430 if ((boot_offset != pitparts[boot_idx].offset) ||
431 (boot_size != pitparts[boot_idx].size)) {
433 /* just erase partition head to format at writing */
434 DEBUG(1, "erase /boot partition to format");
435 sprintf(cmd, "mmc erase 0 0x%x 4",
436 pitparts[boot_idx].offset / usbd_ops.mmc_blk);
440 printf("Update pit is done!\n");
445 static int fusing_recv_data(u32 addr, int pit_idx, s32 size, int final)
449 int uboot_index = -1;
451 if (file_type == FILE_TYPE_PIT)
454 name = pitparts[pit_idx].name;
457 switch (pitparts[pit_idx].dev_type) {
458 case PIT_DEVTYPE_MMC:
459 ret = fusing_mmc(pit_idx, addr, size, final);
461 case PIT_DEVTYPE_FILE:
462 ret = fusing_fs(pit_idx, addr, size, final);
465 DEBUG(1, "unknown device type(%d). plz check PIT\n", pitparts[pit_idx].dev_type);
472 static inline void set_async_buffer(void)
474 if (download_addr_ofs)
475 download_addr_ofs = 0;
477 download_addr_ofs = PKT_DOWNLOAD_CHUNK_SIZE + (5 << 20);
479 download_addr = usbd_ops.ram_addr + download_addr_ofs;
480 DEBUG(3, "download addr: 0x%8x\n", download_addr);
483 static void recv_data_end(int pit_idx)
488 ERROR("invalid pit index\n");
492 name = pitparts[pit_idx].name;
494 #ifndef CONFIG_ENV_UPDATE_WITH_DL
495 if (!strncmp(name, PARTS_BOOTLOADER, 6)) {
496 erase_given_area(PARTS_PARAMS, 0);
499 if (!strncmp(name, PARTS_QBOOT, 5)) {
501 } else if (!strncmp(name, PARTS_KERNEL, 6)) {
502 update_flag |= 1 << SLP_KERNEL_NEW;
503 erase_given_area(PARTS_QBOOT, QBOOT_ERASE_SIZE);
504 } else if (!strncmp(name, PARTS_ROOT, 8) ||
505 !strncmp(name, PARTS_DATA,4)) {
506 update_flag |= 1 << SLP_ROOTFS_NEW;
507 erase_given_area(PARTS_QBOOT, QBOOT_ERASE_SIZE);
508 } else if (!strncmp(name, PARTS_CSC,3)) {
509 update_flag |= 1 << SLP_ROOTFS_NEW;
510 } else if (!strncmp(name, PARTS_UBI, 3)) {
511 erase_given_area(PARTS_QBOOT, QBOOT_ERASE_SIZE);
515 static int recv_data(int pit_idx)
520 s32 remained = file_size;
524 unsigned long long sw_size;
529 if ((pit_idx < 0) && (file_type != FILE_TYPE_PIT)) {
530 ERROR("invalid pit index because of wrong file name\n");
535 sw_size = (unsigned long long) download_packet_size *
536 stopwatch_tick_clock() / 1024; /* KB */
541 sw_check = stopwatch_tick_count();
543 if (!sw_time && sw_bak)
544 sw_time = sw_check - sw_bak;
546 sw_time = (sw_time + (sw_check - sw_bak)) / 2;
549 dn_addr = download_addr + buffered;
550 ret = pkt_download((void *)dn_addr, download_packet_size);
554 buffered += download_packet_size;
555 progressed += download_packet_size;
557 /* check last packet */
558 if (progressed >= file_size)
561 /* fusing per chunk */
562 if ((buffered >= PKT_DOWNLOAD_CHUNK_SIZE) || final) {
564 printf("[%d MB/s]\n", (u32)(sw_size / sw_time / 1024));
567 ret = fusing_recv_data(download_addr, pit_idx, MIN(buffered, remained), final);
572 remained -= buffered;
577 recv_data_end(pit_idx);
579 send_data_rsp(0, count++);
582 download_prog += download_packet_size;
583 if (download_prog > download_prog_check) {
584 if (usbd_ops.set_progress)
585 usbd_ops.set_progress(download_prog / download_unit);
586 download_prog_check += max(download_unit, download_packet_size);
597 #define VER_PROTOCOL_MAJOR 4
598 #define VER_PROTOCOL_MINOR 0
609 RQT_INFO_VER_PROTOCOL = 1,
613 RQT_INIT_VER_PLATFORM,
635 typedef struct _rqt_box { /* total: 256B */
636 s32 rqt; /* request id */
637 s32 rqt_data; /* request data id */
638 s32 int_data[14]; /* int data */
639 char str_data[5][32]; /* string data */
640 char md5[32]; /* md5 checksum */
641 } __attribute__((packed)) rqt_box;
643 typedef struct _rsp_box { /* total: 128B */
644 s32 rsp; /* response id (= request id) */
645 s32 rsp_data; /* response data id */
647 s32 int_data[5]; /* int data */
648 char str_data[3][32]; /* string data */
649 } __attribute__((packed)) rsp_box;
651 typedef struct _data_rsp_box { /* total: 8B */
652 s32 ack; /* response id (= request id) */
653 s32 count; /* response data id */
654 } __attribute__((packed)) data_rsp_box;
657 static const char dl_key[] = "THOR";
658 static const char dl_ack[] = "ROHT";
660 static inline int pkt_download(void *dest, const int size)
662 usbd_ops.recv_setup((char *)dest, size);
663 return usbd_ops.recv_data();
666 static inline void pkt_upload(void *src, const int size)
668 usbd_ops.send_data((char *)src, size);
671 static void send_rsp(const rsp_box *rsp)
673 /* should be copy on dma duffer */
674 memcpy(usbd_ops.tx_data, rsp, sizeof(rsp_box));
675 pkt_upload(usbd_ops.tx_data, sizeof(rsp_box));
677 DEBUG(1, "-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data);
680 static void send_data_rsp(s32 ack, s32 count)
687 /* should be copy on dma duffer */
688 memcpy(usbd_ops.tx_data, &rsp, sizeof(data_rsp_box));
689 pkt_upload(usbd_ops.tx_data, sizeof(data_rsp_box));
691 DEBUG(3, "-DATA RSP: %d, %d\n", ack, count);
694 static int process_rqt_info(const rqt_box *rqt)
699 rsp.rsp_data = rqt->rqt_data;
701 switch (rqt->rqt_data) {
702 case RQT_INFO_VER_PROTOCOL:
703 rsp.int_data[0] = VER_PROTOCOL_MAJOR;
704 rsp.int_data[1] = VER_PROTOCOL_MINOR;
706 case RQT_INIT_VER_HW:
707 sprintf(rsp.str_data[0], "%x", get_board_rev());
709 case RQT_INIT_VER_BOOT:
710 sprintf(rsp.str_data[0], "%s", getenv("ver"));
712 case RQT_INIT_VER_KERNEL:
713 sprintf(rsp.str_data[0], "%s", "k unknown");
715 case RQT_INIT_VER_PLATFORM:
716 sprintf(rsp.str_data[0], "%s", "p unknown");
718 case RQT_INIT_VER_CSC:
719 sprintf(rsp.str_data[0], "%s", "c unknown");
729 static int process_rqt_cmd(const rqt_box *rqt)
734 rsp.rsp_data = rqt->rqt_data;
736 switch (rqt->rqt_data) {
738 DEBUG(1, "TARGET RESET\n");
741 board_inform_clear(0);
744 run_command("reset", 0);
746 case RQT_CMD_POWEROFF:
747 DEBUG(1, "TARGET POWEROFF\n");
752 case RQT_CMD_EFSCLEAR:
753 /* DEBUG(1, "EFS CLEAR\n"); */
754 /* erase /csa/nv/nvdata.bin */
755 fs_write(&usbd_ops, "nv/nvdata.bin", 1, 0);
765 static int process_rqt_download(const rqt_box *rqt)
773 rsp.rsp_data = rqt->rqt_data;
775 switch (rqt->rqt_data) {
777 download_total_size = rqt->int_data[0];
778 download_unit = download_total_size / 100;
780 download_prog_check = 0 + download_unit;
782 DEBUG(1, "INIT: total %d bytes\n", download_total_size);
784 download_addr_ofs = 0;
785 mmc_async_on(mmc, 1);
787 case RQT_DL_FILE_INFO:
788 file_type = rqt->int_data[0];
789 file_size = rqt->int_data[1];
790 file_name = rqt->str_data[0];
792 if (file_type == FILE_TYPE_PIT) {
793 int pit_is_up = pit_check_version(file_name);
795 * Partition policy is changed from 08 version.
796 * When 08 version is installed, we will block migrating
797 * to previous version by pit.
799 if ((pit_get_version() == 8) && (pit_is_up < 0)) {
802 set_font_color(FONT_RED);
803 fb_printf("[Error]\n\n");
804 set_font_color(FONT_WHITE);
805 fb_printf("Must download pit version larger than 8.\n");
806 fb_printf("Press power key retry to download again.\n");
807 while(!check_exit_key());
810 pit_idx = get_pitpart_id_for_pit(file_name);
812 pit_idx = get_pitpart_id_by_filename(file_name);
814 DEBUG(1, "INFO: name(%s, %d), size(%d), type(%d)\n", file_name, pit_idx, file_size, file_type);
816 rsp.int_data[0] = PKT_DOWNLOAD_SIZE;
817 download_packet_size = PKT_DOWNLOAD_SIZE;
819 case RQT_DL_FILE_START:
821 return recv_data(pit_idx);
822 case RQT_DL_FILE_END:
825 mmc_async_on(mmc, 0);
837 static int process_rqt_upload(const rqt_box *rqt)
842 rsp.rsp_data = rqt->rqt_data;
844 switch (rqt->rqt_data) {
861 static int process_download_data(struct usbd_ops *usbd)
866 memset(&rqt, 0, sizeof(rqt));
867 memcpy(&rqt, usbd->rx_data, sizeof(rqt));
869 DEBUG(1, "+RQT: %d, %d\n", rqt.rqt, rqt.rqt_data);
873 ret = process_rqt_info(&rqt);
876 ret = process_rqt_cmd(&rqt);
879 ret = process_rqt_download(&rqt);
882 ret = process_rqt_upload(&rqt);
885 ERROR("unknown request (%d)\n", rqt.rqt);
891 * = 0 : error -> exit
892 * < 0 : error -> retry
901 static const char rdx_preamble[] = "PrEaMbLe";
902 static const char rdx_postamble[] = "PoStAmBlE";
903 static const char rdx_ack[] = "AcKnOwLeDgMeNt";
905 static const char rdx_probe[] = "PrObE";
906 static const char rdx_xfer[] = "DaTaXfEr";
908 extern int rdx_info_get(void **info_buf, int *info_size);
910 static int process_upload_data(struct usbd_ops *usbd)
912 static u32 dump_start, dump_end, upstate = 0;
913 char *rx = usbd->rx_data;
914 char *tx = usbd->tx_data;
919 if (!strncmp(rx, rdx_probe, strlen(rdx_probe))) {
920 DEBUG(1, "up: information upload\n");
922 rdx_info_get(&buf, &size);
923 memcpy(tx, buf , size);
924 usbd->send_data(usbd_ops.tx_data, size);
926 } else if (!strncmp(rx, rdx_preamble, strlen(rdx_preamble))) {
927 DEBUG(1, "up: preamble\n");
931 usbd->send_data(tx, sizeof(rdx_ack));
935 /* get dump start, end address */
936 if ((upstate == 1 || upstate == 2) && (strlen(rx) == 8)) {
938 dump_start = simple_strtoul(rx, NULL, 16);
939 else if (upstate == 2)
940 dump_end = simple_strtoul(rx, NULL, 16);
942 DEBUG(1, "up: oops!\n");
946 DEBUG(1, "up: start(0x%08x), end(0x%08x)\n",
947 dump_start, dump_end);
950 usbd->send_data(tx, sizeof(rdx_ack));
955 && (!strncmp(rx, rdx_xfer, strlen(rdx_xfer))
956 || !strncmp(rx, rdx_ack, strlen(rdx_ack)))) {
957 if (dump_start > dump_end) {
959 strcpy(tx, rdx_postamble);
960 usbd->send_data(tx, sizeof(rdx_postamble));
964 /* dummy command for system reset */
965 if ((dump_start == 0xfffffffc) && (dump_end == 0xffffffff))
966 usbd->cancel(END_BOOT);
968 chunk_size = min(PKT_UPLOAD_SIZE, (dump_end - dump_start + 1));
969 usbd->send_data(dump_start, chunk_size);
970 dump_start += chunk_size;
972 if (!(dump_start % 0x1000000))
973 DEBUG(1, "up: uploaded 0x%08x / 0x%08x\n",
974 dump_start, dump_end);
982 int do_usbd_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
984 struct usbd_ops *usbd;
985 int (*process_data) (struct usbd_ops *);
991 /* check debug level */
992 if (p = getenv("usbdebug")) {
993 debug_level = simple_strtoul(p, NULL, 10);
994 DEBUG(0, "debug level %d\n", debug_level);
997 /* download speed check option */
998 if (debug_level >= 2)
1004 if (!strncmp(p, "fail", 4)) {
1005 DEBUG(1, "opt: fail\n");
1007 } else if (!strncmp(p, "force", 5)) {
1008 DEBUG(1, "opt: force\n");
1009 down_mode = MODE_FORCE;
1010 } else if (!strncmp(p, "upload", 6)) {
1011 DEBUG(1, "opt: upload\n");
1012 down_mode = MODE_UPLOAD;
1016 usbd = usbd_set_interface(&usbd_ops, down_mode);
1019 if (down_mode == MODE_UPLOAD)
1022 download_addr = (u32)usbd->ram_addr;
1025 usbd->set_logo(APP_VERSION, usbd->mmc_info, update_fail);
1027 mmc = find_mmc_device(usbd->mmc_dev);
1031 set_gpt_dev(usbd->mmc_dev);
1032 gpt_parts = get_gpt_table(&mmc->block_dev, gpt_offset);
1035 sprintf(buf, "gpt default %d", usbd->mmc_dev);
1036 run_command(buf, 0);
1039 DEBUG(1, "Downloader v%s %s\n",
1041 down_mode == MODE_FORCE ? "- Force" : "");
1044 /* init the usb controller */
1045 if (!usbd->usb_init()) {
1046 usbd->cancel(END_BOOT);
1050 /* refresh download logo since downloading fail */
1053 usbd->set_logo(APP_VERSION, usbd->mmc_info, 0);
1058 usbd->recv_setup(usbd->rx_data, strlen(dl_key));
1059 /* detect the download request from Host PC */
1060 ret = usbd->recv_data();
1062 if (!strncmp(usbd->rx_data, dl_key, strlen(dl_key))) {
1063 DEBUG(1, "Download request from the Host PC\n");
1066 strcpy(usbd->tx_data, dl_ack);
1067 usbd->send_data(usbd->tx_data, strlen(dl_ack));
1068 } else if (!strncmp(usbd->rx_data, rdx_preamble, strlen(rdx_preamble))) {
1069 DEBUG(1, "Upload request from the Host\n");
1072 strcpy(usbd->tx_data, rdx_ack);
1073 usbd->send_data(usbd->tx_data, sizeof(rdx_ack));
1074 } else if (strncmp(usbd->rx_data, "AT", 2) == 0) {
1077 const char aterr_key[13] = {
1079 'C' , 'M' , 'E' , ' ' ,'E', 'R', 'R', 'O', 'R',
1083 strncpy(atcmd_rev, usbd->rx_data, sizeof(atcmd_rev));
1084 for (i = 2; i < sizeof(atcmd_rev); i++) {
1085 if (atcmd_rev[i] == 0x0d) {
1086 atcmd_rev[i] = '\0';
1087 DEBUG(1, "Received AT cmd from the Host PC:%s , length:%d\n",atcmd_rev, i);
1092 strncpy(usbd->tx_data, aterr_key, sizeof(aterr_key));
1093 usbd->send_data(usbd->tx_data, sizeof(aterr_key));
1095 #ifdef CONFIG_S5P_USB_DMA
1097 /*BULK_IN/OUT_RESET_DATA_PID to 0*/
1098 usbd->prepare_dma(NULL, 0, 0);
1100 DEBUG(1, "Retry waiting key from the Host PC\n");
1103 DEBUG(1, "Invalid request from the Host PC!! (len=%lu)\n", usbd->rx_len);
1104 usbd->cancel(END_RETRY);
1107 } else if (ret < 0) {
1108 usbd->cancel(END_RETRY);
1111 usbd->cancel(END_BOOT);
1118 if (down_mode == MODE_UPLOAD) {
1119 process_data = process_upload_data;
1120 usbd->rx_len = sizeof(rdx_probe);
1122 process_data = process_download_data;
1125 /* receive the data from Host PC */
1127 usbd->recv_setup(usbd->rx_data, usbd->rx_len);
1129 ret = usbd->recv_data();
1131 ret = process_data(usbd);
1133 usbd->cancel(END_RETRY);
1135 } else if (ret == 0) {
1136 usbd->cancel(END_NORMAL);
1139 } else if (ret < 0) {
1140 usbd->cancel(END_FAIL);
1143 usbd->cancel(END_BOOT);
1151 U_BOOT_CMD(usbdown, CONFIG_SYS_MAXARGS, 1, do_usbd_down,
1152 "USB Downloader for SLP",
1153 "usbdown <force> - download binary images (force - don't check target)\n"
1154 "usbdown upload - upload debug info"