usbd: fix the typo
[kernel/u-boot.git] / common / cmd_usbd.c
1 /*
2  * USB Downloader for SAMSUNG Platform
3  *
4  * Copyright (C) 2007-2008 Samsung Electronics
5  * Minkyu Kang <mk7.kang@samsung.com>
6  *
7  */
8
9 #include <common.h>
10 #include <usbd.h>
11 #include <asm/errno.h>
12 #include <malloc.h>
13
14 /* version of USB Downloader Application */
15 #define APP_VERSION     "1.6.0"
16
17 #define OPS_READ        0
18 #define OPS_WRITE       1
19
20 #ifdef CONFIG_CMD_MTDPARTS
21 #include <jffs2/load_kernel.h>
22 static struct part_info *parts[16];
23 #endif
24
25 #ifdef CONFIG_UBIFS_MK
26 #include <mkfs.ubifs.h>
27 #endif
28
29 #ifdef CONFIG_UBINIZE
30 #include <ubinize.h>
31 #endif
32
33 #include <mbr.h>
34
35 static const char pszMe[] = "usbd: ";
36
37 static struct usbd_ops usbd_ops;
38
39 static unsigned int part_id;
40 static unsigned int write_part = 0;
41 static unsigned int fs_offset = 0x0;
42
43 #ifdef CONFIG_USE_YAFFS
44 static unsigned int yaffs_len = 0;
45 static unsigned char yaffs_data[2112];
46 #define YAFFS_PAGE 2112
47 #endif
48
49 #define NAND_PAGE_SIZE 2048
50
51 static unsigned long down_ram_addr;
52
53 static int down_mode;
54
55 /* cpu/${CPU} dependent */
56 extern void do_reset(void);
57
58 /* common commands */
59 extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
60 extern int do_run(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
61
62 int mtdparts_init(void);
63 int find_dev_and_part(const char*, struct mtd_device**, u8*, struct part_info**);
64
65 /* common/cmd_jffs2.c */
66 extern struct list_head devices;
67
68 static u8 count_mtdparts(void)
69 {
70         struct list_head *dentry, *pentry;
71         struct mtd_device *dev;
72         u8 part_num = 0;
73
74         list_for_each(dentry, &devices) {
75                 dev = list_entry(dentry, struct mtd_device, link);
76
77                 /* list partitions for given device */
78                 list_for_each(pentry, &dev->parts)
79                         part_num++;
80         }
81
82         return part_num;
83 }
84
85 #ifdef CONFIG_CMD_UBI
86 static int check_ubi_mode(void)
87 {
88         char *env_ubifs;
89         int ubi_mode;
90
91         env_ubifs = getenv("ubi");
92         ubi_mode = !strcmp(env_ubifs, "enabled");
93
94         return ubi_mode;
95 }
96 #else
97 #define check_ubi_mode()                0
98 #endif
99
100 #ifdef CONFIG_MTD_PARTITIONS
101 static int get_part_info(void)
102 {
103         struct mtd_device *dev;
104         u8 out_partnum;
105         char part_name[12];
106         char nand_name[12];
107         int i;
108         int part_num;
109         int ubi_mode = 0;
110
111 #if defined(CONFIG_CMD_NAND)
112         sprintf(nand_name, "nand0");
113 #elif defined(CONFIG_CMD_ONENAND)
114         sprintf(nand_name, "onenand0");
115 #else
116         printf("Configure your NAND sub-system\n");
117         return 0;
118 #endif
119
120         if (mtdparts_init())
121                 return 0;
122
123         ubi_mode = check_ubi_mode();
124
125         part_num = count_mtdparts();
126         for (i = 0; i < part_num; i++) {
127                 sprintf(part_name, "%s,%d", nand_name, i);
128
129                 if (find_dev_and_part(part_name, &dev, &out_partnum, &parts[i]))
130                         return -EINVAL;
131         }
132
133         return 0;
134 }
135
136 static int get_part_id(char *name)
137 {
138         int nparts = count_mtdparts();
139         int i;
140
141         for (i = 0; i < nparts; i++) {
142                 if (strcmp(parts[i]->name, name) == 0)
143                         return i;
144         }
145
146         printf("Error: Unknown partition -> %s\n", name);
147         return -1;
148 }
149 #else
150 static int get_part_info(void)
151 {
152         printf("Error: Can't get patition information\n");
153         return -EINVAL;
154 }
155
156 static int get_part_id(char *name)
157 {
158         return 0;
159 }
160 #endif
161
162 static void boot_cmd(char *addr)
163 {
164         char *argv[] = { "bootm", addr };
165         do_bootm(NULL, 0, 2, argv);
166 }
167
168 #if defined(CONFIG_CMD_NAND)
169 extern int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
170 #elif defined(CONFIG_CMD_ONENAND)
171 extern int do_onenand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
172 #endif
173
174 /* NAND erase and write using nand command */
175 static int nand_cmd(int type, char *p1, char *p2, char *p3)
176 {
177         int ret = 1;
178         char nand_name[12];
179         int (*nand_func) (cmd_tbl_t *, int, int, char **);
180
181 #if defined(CONFIG_CMD_NAND)
182         sprintf(nand_name, "nand");
183         nand_func = do_nand;
184 #elif defined(CONFIG_CMD_ONENAND)
185         sprintf(nand_name, "onenand");
186         nand_func = do_onenand;
187 #else
188         printf("Configure your NAND sub-system\n");
189         return 0;
190 #endif
191
192         if (type == 0) {
193                 char *argv[] = {nand_name, "erase", p1, p2};
194                 printf("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
195                 ret = nand_func(NULL, 0, 4, argv);
196         } else if (type == 1) {
197                 char *argv[] = {nand_name, "write", p1, p2, p3};
198                 printf("%s %s %s %s %s\n", argv[0], argv[1], argv[2],
199                                 argv[3], argv[4]);
200                 ret = nand_func(NULL, 0, 5, argv);
201         } else if (type == 2) {
202                 char *argv[] = {nand_name, "write.yaffs", p1, p2, p3};
203                 printf("%s %s %s %s %s\n", argv[0], argv[1], argv[2],
204                                 argv[3], argv[4]);
205                 ret = nand_func(NULL, 0, 5, argv);
206         } else if (type == 3) {
207                 char *argv[] = {nand_name, "lock", p1, p2};
208                 printf("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
209                 ret = nand_func(NULL, 0, 4, argv);
210         }
211
212         if (ret)
213                 printf("Error: NAND Command\n");
214
215         return ret;
216 }
217
218 #ifdef CONFIG_CMD_UBI
219 int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
220
221 int ubi_cmd(int part, char *p1, char *p2, char *p3)
222 {
223         int ret = 1;
224
225         if (part == RAMDISK_PART_ID) {
226                 char *argv[] = {"ubi", "write", p1, "rootfs.cramfs", p2, p3};
227                 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
228                                 argv[3], argv[4], argv[5]);
229                 ret = do_ubi(NULL, 0, 6, argv);
230         } else if (part == FILESYSTEM_PART_ID) {
231                 char *argv[] = {"ubi", "write", p1, "factoryfs.cramfs", p2, p3};
232                 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
233                                 argv[3], argv[4], argv[5]);
234                 ret = do_ubi(NULL, 0, 6, argv);
235         } else if (part == FILESYSTEM2_PART_ID) {
236                 char *argv[] = {"ubi", "write", p1, "datafs.ubifs", p2, p3};
237                 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
238                                 argv[3], argv[4], argv[5]);
239                 ret = do_ubi(NULL, 0, 6, argv);
240         }
241
242         return ret;
243 }
244 #endif
245
246 #ifdef CONFIG_CMD_MMC
247 #include <mmc.h>
248 #include <fat.h>
249
250 static struct mmc *mmc;
251
252 static int mmc_cmd(int ops, int dev_num, ulong start, lbaint_t cnt, void *addr)
253 {
254         int ret;
255
256         if (ops) {
257                 printf("mmc write 0x%x 0x%x\n", start, cnt);
258                 ret = mmc->block_dev.block_write(dev_num, start, cnt, addr);
259         } else {
260                 printf("mmc read 0x%x 0x%x\n", start, cnt);
261                 ret = mmc->block_dev.block_read(dev_num, start, cnt, addr);
262         }
263
264         if (ret > 0)
265                 ret = 0;
266         else
267                 ret = 1;
268
269         return ret;
270 }
271
272 #define NORMAL_PARTITION        0
273 #define EXTEND_PARTITION        1
274
275 #define EXTEND_PART_TYPE        5
276
277 #define EXTEND_MAX_PART         32
278
279 static unsigned int cur_blk_offset;
280 static unsigned int cur_part_size;
281 static unsigned int cur_part;
282
283 static unsigned int mmc_parts;
284 static unsigned int mmc_part_write;
285
286 static u8 part_mode = 0;
287
288 struct partition_info {
289         u32 size;
290         u32 checksum;
291         u32 res;
292 } __attribute__((packed));
293
294 struct partition_header {
295         u8                      fat32head[16];  /* RFSHEAD identifier */
296         struct partition_info   partition[EXTEND_MAX_PART];
297         u8                      res[112];       /* only data (without MBR) */
298 } __attribute__((packed));
299
300 struct mul_partition_info {
301         u32 lba_begin;          /* absolute address from 0 block */
302         u32 num_sectors;
303 } __attribute__((packed));
304
305 #define MBR_OFFSET      0x10
306
307 struct partition_header part_info;
308 struct mbr mbr_info;
309 struct mul_partition_info mul_info[EXTEND_MAX_PART];
310
311 static int write_mmc_partition(struct usbd_ops *usbd, u32 *ram_addr, u32 len)
312 {
313         unsigned int blocks;
314         int i;
315         int loop;
316         u32 cnt;
317         int ret;
318
319         if (cur_part_size > len) {
320                 blocks = len / usbd->mmc_blk;
321                 ret = -1;
322         } else {
323                 blocks = cur_part_size / usbd->mmc_blk;
324                 ret = len - cur_part_size;
325         }
326
327         if (len % usbd->mmc_blk)
328                 blocks++;
329
330         loop = blocks / usbd->mmc_max;
331         if (blocks % usbd->mmc_max)
332                 loop++;
333
334         for (i = 0; i < loop; i++) {
335                 if (i == 0) {
336                         cnt = blocks % usbd->mmc_max;
337                         if (cnt == 0)
338                                 cnt = usbd->mmc_max;
339                 } else {
340                         cnt = usbd->mmc_max;
341                 }
342
343                 mmc_cmd(OPS_WRITE, usbd->mmc_dev, cur_blk_offset,
344                                 cnt, (void *)*ram_addr);
345
346                 cur_blk_offset += cnt;
347
348                 *ram_addr += (cnt * usbd->mmc_blk);
349         }
350
351         return ret;
352 }
353
354 static int write_file_mmc(struct usbd_ops *usbd, u32 len)
355 {
356         u32 ram_addr;
357         int i;
358         int ret;
359         struct mbr *mbr;
360
361         if (!usbd->mmc_total) {
362                 printf("MMC is not supported!\n");
363                 return 0;
364         }
365
366         ram_addr = (u32)down_ram_addr;
367
368         if (cur_blk_offset == 0) {
369                 boot_sector *bs;
370                 u32 mbr_blk_size;
371
372                 memcpy(&part_info, (void *)ram_addr,
373                                 sizeof(struct partition_header));
374
375                 ram_addr += sizeof(struct partition_header);
376                 len -= sizeof(struct partition_header);
377                 mbr = (struct mbr *)ram_addr;
378                 mbr_blk_size = mbr->parts[0].lba;
379
380                 if (mbr->parts[0].partition_type != EXTEND_PART_TYPE) {
381                         part_mode = NORMAL_PARTITION;
382
383                         /* modify sectors of p1 */
384                         mbr->parts[0].nsectors = usbd->mmc_total -
385                                         (mbr_blk_size +
386                                         mbr->parts[1].nsectors +
387                                         mbr->parts[2].nsectors +
388                                         mbr->parts[3].nsectors);
389
390                         mmc_parts++;
391
392                         /* modify lba_begin of p2 and p3 and p4 */
393                         for (i = 1; i < 4; i++) {
394                                 if (part_info.partition[i].size == 0)
395                                         break;
396
397                                 mmc_parts++;
398                                 mbr->parts[i].lba =
399                                         mbr->parts[i - 1].lba +
400                                         mbr->parts[i - 1].nsectors;
401                         }
402
403                         /* copy MBR */
404                         memcpy(&mbr_info, mbr, sizeof(struct mbr));
405
406                         printf("Total Size: 0x%08x #parts %d\n",
407                                         (unsigned int)usbd->mmc_total,
408                                         mmc_parts);
409                         for (i = 0; i < mmc_parts; i++) {
410                                 printf("p%d\t0x%08x\t0x%08x\n", i + 1,
411                                         mbr_info.parts[i].lba,
412                                         mbr_info.parts[i].nsectors);
413                         }
414
415                         /* write MBR */
416                         mmc_cmd(OPS_WRITE, usbd->mmc_dev, 0,
417                                         mbr_blk_size, (void *)ram_addr);
418
419                         ram_addr += mbr_blk_size * usbd->mmc_blk;
420                         len -= mbr_blk_size * usbd->mmc_blk;
421
422                         cur_blk_offset = mbr_blk_size;
423                         cur_part = 0;
424                         cur_part_size = part_info.partition[0].size;
425
426                         /* modify p1's total sector */
427                         bs = (boot_sector *)ram_addr;
428                         bs->total_sect = mbr_info.parts[0].nsectors;
429
430                         printf("\nWrite Partition %d.. %d blocks\n",
431                                 cur_part + 1,
432                                 part_info.partition[cur_part].size /
433                                 (int)usbd->mmc_blk);
434                 } else {
435                         part_mode = EXTEND_PARTITION;
436
437                         for (i = 0; i < EXTEND_MAX_PART; i++) {
438                                 if (part_info.partition[i].size == 0)
439                                         break;
440                                 mmc_parts++;
441                         }
442
443                         if (mmc_parts == 0)
444                                 return -1;
445                         else
446                                 printf("found %d partitions\n", mmc_parts);
447
448                         /* build partition table */
449
450                         mul_info[0].num_sectors =
451                                 usbd->mmc_total - mbr_blk_size;
452                         for (i = 1; i < mmc_parts; i++) {
453                                 mul_info[i].num_sectors =
454                                         part_info.partition[i].res +
455                                         mbr_blk_size; /* add MBR */
456                         }
457
458                         for (i = 1; i < mmc_parts; i++) {
459                                 mul_info[0].num_sectors -=
460                                         mul_info[i].num_sectors;
461                         }
462
463                         mul_info[0].lba_begin = mbr_blk_size;
464                         for (i = 1; i < mmc_parts; i++) {
465                                 mul_info[i].lba_begin =
466                                         mul_info[i-1].lba_begin +
467                                         mul_info[i-1].num_sectors;
468                         }
469
470                         /* modify MBR of extended partition: p1 */
471                         mbr->parts[0].nsectors =
472                                 usbd->mmc_total - mbr_blk_size;
473
474                         /* modify MBR of first logical partition: p5 */
475                         mbr = (struct mbr *)
476                                 (ram_addr + mbr_blk_size * usbd->mmc_blk);
477
478                         mbr->parts[0].nsectors =
479                                 mul_info[0].num_sectors - mbr_blk_size;
480                         mbr->parts[1].lba=
481                                 mul_info[1].lba_begin - mbr_blk_size;
482
483                         /* modify BPB data of p5 */
484                         bs = (boot_sector *)
485                                 ((u32)mbr + mbr_blk_size * usbd->mmc_blk);
486                         memset(&bs->sectors, 0, 2);
487                         bs->total_sect = mbr->parts[0].nsectors;
488
489                         printf("Total Size: 0x%08x #parts %d\n",
490                                         (unsigned int)usbd->mmc_total,
491                                         mmc_parts);
492                         for (i = 0; i < mmc_parts; i++) {
493                                 printf("p%d\t0x%08x\t0x%08x\n", i + 1,
494                                         mul_info[i].lba_begin,
495                                         mul_info[i].num_sectors);
496                         }
497
498                         cur_blk_offset = 0;
499                         cur_part = 0;
500                         cur_part_size = part_info.partition[0].size;
501
502                         printf("\nWrite Partition %d.. %d blocks\n",
503                                 cur_part + 1,
504                                 part_info.partition[cur_part].size /
505                                 (int)usbd->mmc_blk);
506                 }
507         }
508
509         for (i = cur_part; i < mmc_parts; i++) {
510                 ret = write_mmc_partition(usbd, &ram_addr, len);
511
512                 if (ret < 0) {
513                         cur_part_size -= len;
514                         break;
515                 } else {
516                         cur_part++;
517                         cur_part_size =
518                                 part_info.partition[cur_part].size;
519
520                         if (part_mode == NORMAL_PARTITION) {
521                                 cur_blk_offset =
522                                         mbr_info.parts[cur_part].lba;
523                         } else {
524                                 cur_blk_offset =
525                                         mul_info[cur_part].lba_begin;
526                                 /* modify MBR */
527                                 if (cur_part < mmc_parts) {
528                                         mbr = (struct mbr *)ram_addr;
529                                         mbr->parts[1].lba=
530                                                 mul_info[cur_part+1].lba_begin -
531                                                 mbr->parts[0].lba;
532                                 }
533                         }
534
535                         if (ret == 0)
536                                 break;
537                         else
538                                 len = ret;
539
540                         printf("\nWrite Partition %d.. %d blocks\n",
541                                 cur_part + 1,
542                                 part_info.partition[cur_part].size /
543                                 (int)usbd->mmc_blk);
544                 }
545         }
546
547         return 0;
548 }
549
550 static int write_file_mmc_part(struct usbd_ops *usbd, u32 len)
551 {
552         u32 ram_addr;
553         u32 ofs;
554         int i;
555         struct mbr *mbr;
556         u32 mbr_blk_size;
557
558         ram_addr = (u32)down_ram_addr;
559         mbr = &mbr_info;
560
561         if (cur_blk_offset == 0) {
562                 /* read MBR */
563                 mmc_cmd(OPS_READ, usbd->mmc_dev, 0,
564                         sizeof(struct mbr)/usbd->mmc_blk, (void *)mbr);
565
566                 mbr_blk_size = mbr->parts[0].lba;
567
568                 if (mbr->parts[0].partition_type != EXTEND_PART_TYPE) {
569                         part_mode = NORMAL_PARTITION;
570
571                         for (i = 0; i < 4; i++) {
572                                 printf("p%d\t0x%08x\t0x%08x\n", i + 1,
573                                         mbr_info.parts[i].lba,
574                                         mbr_info.parts[i].nsectors);
575                         }
576
577                         cur_blk_offset =
578                                 mbr->parts[mmc_part_write - 1].lba;
579                         cur_part = mmc_part_write - 1;
580                         cur_part_size =
581                                 usbd->mmc_blk *
582                                 mbr->parts[mmc_part_write - 1].nsectors;
583
584                         if (mmc_part_write == 1) {
585                                 ram_addr += sizeof(struct mbr);
586                                 cur_blk_offset += sizeof(struct mbr) /
587                                         usbd->mmc_blk;
588                                 len -= sizeof(struct mbr);
589                         }
590                 } else {
591                         part_mode = EXTEND_PARTITION;
592
593                         for (i = 1; i < mmc_part_write; i++) {
594                                 ofs = mbr->parts[0].lba + mbr->parts[1].lba;
595                                 printf("P%d start blk: 0x%x, size: 0x%x\n", i,
596                                         ofs, mbr->parts[1].nsectors);
597                                 mmc_cmd(OPS_READ, usbd->mmc_dev, ofs,
598                                         (sizeof(struct mbr) / usbd->mmc_blk),
599                                         (void *)mbr);
600                         }
601
602                         ofs = mbr->parts[0].lba + mbr->parts[1].lba;
603                         printf("P%d start blk: 0x%x, size: 0x%x\n", i,
604                                 ofs, mbr->parts[1].nsectors);
605
606                         ofs += mbr_blk_size; /* skip MBR */
607                         cur_blk_offset = ofs;
608                         cur_part = mmc_part_write - 1;
609                         cur_part_size =
610                                 usbd->mmc_blk *
611                                 mbr->parts[1].nsectors;
612
613                         if (mmc_part_write == 1) {
614                                 boot_sector *bs;
615                                 u32 total_sect;
616                                 /* modify BPB data of p1 */
617                                 mmc_cmd(OPS_READ, usbd->mmc_dev, cur_blk_offset,
618                                         (sizeof(struct mbr) / usbd->mmc_blk),
619                                         mbr);
620
621                                 bs = (boot_sector *)mbr;
622                                 total_sect = bs->total_sect;
623
624                                 bs = (boot_sector *)ram_addr;
625                                 memset(&bs->sectors, 0, 2);
626                                 bs->total_sect = total_sect;
627                         }
628                 }
629         }
630
631         printf("\nWrite Partition %d.. %d blocks\n",
632                 cur_part + 1,
633                 len / (int)usbd->mmc_blk);
634
635         write_mmc_partition(usbd, &ram_addr, len);
636
637         return 0;
638 }
639 #endif
640
641 static unsigned int mbr_offset[16];
642 static int mbr_parts = 0;
643
644 static unsigned long memsize_parse (const char *const ptr, const char **retptr)
645 {
646         unsigned long ret = simple_strtoul(ptr, (char **)retptr, 0);
647
648         switch (**retptr) {
649                 case 'G':
650                 case 'g':
651                         ret <<= 10;
652                 case 'M':
653                 case 'm':
654                         ret <<= 10;
655                 case 'K':
656                 case 'k':
657                         ret <<= 10;
658                         (*retptr)++;
659                 default:
660                         break;
661         }
662
663         return ret;
664 }
665
666 static void set_mbr_info(struct usbd_ops *usbd, char *ramaddr, u32 len)
667 {
668         char mbr_str[256];
669         char save[16][16];
670         char *p;
671         char *tok;
672         unsigned int size[16];
673         int i = 0;
674
675         strncpy(mbr_str, ramaddr, len);
676         p = mbr_str;
677
678         for (i = 0; ; i++, p = NULL) {
679                 tok = strtok(p, ",");
680                 if (tok == NULL)
681                         break;
682                 strcpy(save[i], tok);
683                 printf("part%d: %s\n", i, save[i]);
684         }
685
686         mbr_parts = i;
687         printf("find %d partitions\n", mbr_parts);
688
689         for (i = 0; i < mbr_parts; i++) {
690                 p = save[i];
691                 size[i] = memsize_parse(p, (const char **)&p) / 512;
692         }
693
694         puts("save the MBR Table...\n");
695         set_mbr_table(0x800, mbr_parts, size, mbr_offset);
696 }
697
698 static int write_mmc_image(struct usbd_ops *usbd, unsigned int len, int part_num)
699 {
700         int ret = 0;
701
702         if (mbr_parts <= part_num) {
703                 printf("Error: MBR table have %d partitions (request %d)\n",
704                                 mbr_parts, part_num);
705                 return 1;
706         }
707
708 #if 0
709         /* modify size of UMS partition */
710         if (part_num == 4 && fs_offset == 0) {
711                 boot_sector *bs;
712                 bs = (boot_sector *)down_ram_addr;
713                 memset(&bs->sectors, 0, 2);
714                 bs->total_sect = usbd->mmc_total - mbr_offset[part_num];
715         }
716 #endif
717         ret = mmc_cmd(OPS_WRITE, usbd->mmc_dev,
718                         mbr_offset[part_num] + fs_offset,
719                         len / usbd->mmc_blk,
720                         (void *)down_ram_addr);
721
722         fs_offset += (len / usbd->mmc_blk);
723
724         return ret;
725 }
726
727 static int write_fat_file(struct usbd_ops *usbd, char *file_name,
728                         int part_id, int len)
729 {
730 #ifdef CONFIG_FAT_WRITE
731         int ret;
732
733         ret = fat_register_device(&mmc->block_dev, part_id);
734         if (ret < 0) {
735                 printf("error : fat_register_divce\n");
736                 return 0;
737         }
738
739         ret = file_fat_write(file_name, (void *)down_ram_addr, len);
740         if (ret < 0) {
741                 printf("error : writing uImage\n");
742                 return 0;
743         }
744 #else
745         printf("error: doesn't support fat_write\n");
746 #endif
747         return 0;
748 }
749
750 static int write_file_system(char *ramaddr, ulong len, char *offset,
751                 char *length, int part_num, int ubi_update)
752 {
753 #ifdef CONFIG_USE_YAFFS
754         int actual_len = 0;
755         int yaffs_write = 0;
756 #endif
757         int ret = 0;
758
759 #ifdef CONFIG_CMD_UBI
760         /* UBI Update */
761         if (ubi_update) {
762                 sprintf(length, "0x%x", (uint)len);
763                 ret = ubi_cmd(part_id, ramaddr, length, "cont");
764                 return ret;
765         }
766 #endif
767
768         /* Erase entire partition at the first writing */
769         if (write_part == 0 && ubi_update == 0) {
770                 sprintf(offset, "0x%x", (uint)parts[part_num]->offset);
771                 sprintf(length, "0x%x", (uint)parts[part_num]->size);
772                 nand_cmd(0, offset, length, NULL);
773         }
774
775 #ifdef CONFIG_USE_YAFFS
776         /* if using yaffs, wirte size must be 2112*X
777          * so, must have to realloc, and writing */
778         if (!strcmp("yaffs", getenv(parts[part_num]->name))) {
779                 yaffs_write = 1;
780
781                 memcpy((void *)down_ram_addr, yaffs_data, yaffs_len);
782
783                 actual_len = len + yaffs_len;
784                 yaffs_len = actual_len % YAFFS_PAGE;
785                 len = actual_len - yaffs_len;
786
787                 memset(yaffs_data, 0x00, YAFFS_PAGE);
788                 memcpy(yaffs_data, (char *)down_ram_addr + len, yaffs_len);
789         }
790 #endif
791
792         sprintf(offset, "0x%x", (uint)(parts[part_num]->offset + fs_offset));
793         sprintf(length, "0x%x", (uint)len);
794
795 #ifdef CONFIG_USE_YAFFS
796         if (yaffs_write)
797                 ret = nand_cmd(2, ramaddr, offset, length);
798         else
799                 ret = nand_cmd(1, ramaddr, offset, length);
800
801         if (!strcmp("yaffs", getenv(parts[part_num]->name)))
802                 fs_offset += len / YAFFS_PAGE * NAND_PAGE_SIZE;
803         else
804                 fs_offset += len;
805
806 #else
807         fs_offset += len;
808         ret = nand_cmd(1, ramaddr, offset, length);
809 #endif
810
811         return ret;
812 }
813
814 static int qboot_erase = 0;
815
816 /* Erase the qboot */
817 static void erase_qboot_area(void)
818 {
819         char offset[12], length[12];
820         int qboot_id;
821
822         if (qboot_erase)
823                 return;
824
825         qboot_id = get_part_id("qboot");
826
827         if (qboot_id != -1) {
828                 printf("\nCOMMAND_ERASE_QBOOT\n");
829                 sprintf(offset, "%x", parts[qboot_id]->offset);
830                 sprintf(length, "%x", parts[qboot_id]->size);
831                 nand_cmd(0, offset, length, NULL);
832                 qboot_erase = 1;
833         }
834 }
835
836 /* Erase the environment */
837 static void erase_env_area(struct usbd_ops *usbd)
838 {
839 #if defined(CONFIG_ENV_IS_IN_NAND) || defined(CONFIG_ENV_IS_IN_ONENAND)
840         int param_id;
841         char offset[12], length[12];
842
843         param_id = get_part_id("params");
844
845         if (param_id == -1) {
846                 sprintf(offset, "%x", CONFIG_ENV_ADDR);
847                 sprintf(length, "%x", CONFIG_ENV_SIZE);
848         } else {
849                 sprintf(offset, "%x", parts[param_id]->offset);
850                 sprintf(length, "%x", parts[param_id]->size);
851         }
852         nand_cmd(0, offset, length, NULL);
853 #elif defined(CONFIG_ENV_IS_IN_MMC)
854         char buf[usbd->mmc_blk];
855
856         memset(buf, 0x0, usbd->mmc_blk);
857         mmc_cmd(OPS_WRITE, CONFIG_SYS_MMC_ENV_DEV,
858                         CONFIG_ENV_OFFSET / usbd->mmc_blk,
859                         1, (void *)buf);
860 #endif
861 }
862
863 /* Parsing received data packet and Process data */
864 static int process_data(struct usbd_ops *usbd)
865 {
866         unsigned int cmd = 0, arg = 0, ofs = 0, len = 0, flag = 0;
867         char offset[12], length[12], ramaddr[12];
868         int recvlen = 0;
869         unsigned int blocks = 0;
870         int ret = 0;
871         int ubi_update = 0;
872         int ubi_mode = 0;
873         int img_type;
874
875         sprintf(ramaddr, "0x%x", (uint) down_ram_addr);
876
877         /* Parse command */
878         cmd  = *((ulong *) usbd->rx_data + 0);
879         arg  = *((ulong *) usbd->rx_data + 1);
880         len  = *((ulong *) usbd->rx_data + 2);
881         flag = *((ulong *) usbd->rx_data + 3);
882
883         /* Reset tx buffer */
884         memset(usbd->tx_data, 0, sizeof(usbd->tx_data));
885
886         ubi_mode = check_ubi_mode();
887
888         switch (cmd) {
889         case COMMAND_DOWNLOAD_IMAGE:
890                 printf("\nCOMMAND_DOWNLOAD_IMAGE\n");
891
892 #ifdef CONFIG_USE_YAFFS
893                 usbd->recv_setup((char *)down_ram_addr + yaffs_len, (int)len);
894                 printf("Download to 0x%08x, %d bytes\n",
895                                 (uint)down_ram_addr + yaffs_len, (int)len);
896 #else
897                 if (arg)
898                         down_ram_addr = usbd->ram_addr + 0x1000000;
899                 else
900                         down_ram_addr = usbd->ram_addr;
901
902                 usbd->recv_setup((char *)down_ram_addr, (int)len);
903                 printf("Download to 0x%08x, %d bytes\n",
904                                 (uint)down_ram_addr, (int)len);
905 #endif
906                 /* response */
907                 usbd->send_data(usbd->tx_data, usbd->tx_len);
908
909                 /* Receive image by using dma */
910                 recvlen = usbd->recv_data();
911                 if (recvlen < len) {
912                         printf("Error: wrong image size -> %d/%d\n",
913                                         (int)recvlen, (int)len);
914
915                         /* Retry this commad */
916                         *((ulong *) usbd->tx_data) = STATUS_RETRY;
917                 } else
918                         *((ulong *) usbd->tx_data) = STATUS_DONE;
919
920                 usbd->send_data(usbd->tx_data, usbd->tx_len);
921                 return 1;
922
923         /* Report partition info */
924         case COMMAND_PARTITION_SYNC:
925                 part_id = arg;
926
927 #ifdef CONFIG_CMD_UBI
928                 if (ubi_mode) {
929                         if (part_id == RAMDISK_PART_ID ||
930                             part_id == FILESYSTEM_PART_ID ||
931                             part_id == FILESYSTEM2_PART_ID) {
932                                 /* change to yaffs style */
933                                 get_part_info();
934                         }
935                 } else {
936                         if (part_id == FILESYSTEM3_PART_ID) {
937                                 /* change ubi style */
938                                 get_part_info();
939                         }
940                 }
941 #endif
942
943                 if (part_id == FILESYSTEM3_PART_ID)
944                         part_id = get_part_id("UBI");
945                 else if (part_id == MODEM_PART_ID)
946                         part_id = get_part_id("modem");
947                 else if (part_id == KERNEL_PART_ID)
948                         part_id = get_part_id("kernel");
949                 else if (part_id == BOOT_PART_ID)
950                         part_id = get_part_id("bootloader");
951 #ifdef CONFIG_MIRAGE
952                 if (part_id)
953                         part_id--;
954 #endif
955                 printf("COMMAND_PARTITION_SYNC - Part%d\n", part_id);
956
957                 blocks = parts[part_id]->size / 1024 / 128;
958                 printf("COMMAND_PARTITION_SYNC - Part%d, %d blocks\n",
959                                 part_id, blocks);
960
961                 *((ulong *) usbd->tx_data) = blocks;
962                 usbd->send_data(usbd->tx_data, usbd->tx_len);
963                 return 1;
964
965         case COMMAND_WRITE_PART_0:
966                 /* Do nothing */
967                 printf("COMMAND_WRITE_PART_0\n");
968                 return 1;
969
970         case COMMAND_WRITE_PART_1:
971                 printf("COMMAND_WRITE_PART_BOOT\n");
972                 part_id = get_part_id("bootloader");
973                 img_type = IMG_BOOT;
974                 break;
975
976         case COMMAND_WRITE_PART_2:
977         case COMMAND_ERASE_PARAMETER:
978                 printf("COMMAND_PARAMETER - not support!\n");
979                 break;
980
981         case COMMAND_WRITE_PART_3:
982                 printf("COMMAND_WRITE_KERNEL\n");
983                 part_id = get_part_id("kernel");
984                 img_type = IMG_KERNEL;
985                 break;
986
987         case COMMAND_WRITE_PART_4:
988                 printf("COMMAND_WRITE_ROOTFS\n");
989                 part_id = get_part_id("Root");
990                 img_type = IMG_FILESYSTEM;
991                 ubi_update = arg;
992                 break;
993
994         case COMMAND_WRITE_PART_5:
995                 printf("COMMAND_WRITE_FACTORYFS\n");
996                 part_id = get_part_id("Fact");
997                 img_type = IMG_FILESYSTEM;
998                 ubi_update = arg;
999                 break;
1000
1001         case COMMAND_WRITE_PART_6:
1002                 printf("COMMAND_WRITE_DATAFS\n");
1003                 part_id = get_part_id("Data");
1004                 img_type = IMG_FILESYSTEM;
1005                 ubi_update = arg;
1006                 break;
1007
1008         case COMMAND_WRITE_PART_7:
1009                 printf("COMMAND_WRITE_UBI\n");
1010                 part_id = get_part_id("UBI");
1011                 img_type = IMG_FILESYSTEM;
1012                 ubi_update = 0;
1013                 /* someday, it will be deleted */
1014                 get_part_info();
1015                 break;
1016
1017         case COMMAND_WRITE_PART_8:
1018                 printf("COMMAND_WRITE_MODEM\n");
1019                 part_id = get_part_id("modem");
1020                 img_type = IMG_MODEM;
1021                 break;
1022
1023 #ifdef CONFIG_CMD_MMC
1024         case COMMAND_WRITE_PART_9:
1025                 printf("COMMAND_WRITE_MMC\n");
1026                 img_type = IMG_MMC;
1027                 mmc_part_write = arg;
1028                 break;
1029 #endif
1030
1031         case COMMAND_WRITE_IMG_0:
1032                 printf("COMMAND_WRITE_MBR\n");
1033                 img_type = IMG_MBR;
1034                 break;
1035
1036         case COMMAND_WRITE_IMG_1:
1037                 printf("COMMAND_WRITE_BOOTLOADER\n");
1038                 img_type = IMG_BOOTLOADER;
1039                 break;
1040
1041         case COMMAND_WRITE_IMG_2:
1042                 printf("COMMAND_WRITE_KERNEL\n");
1043                 img_type = IMG_KERNEL_V2;
1044                 part_id = 2;
1045                 break;
1046
1047         case COMMAND_WRITE_IMG_3:
1048                 printf("COMMAND_WRITE_MODEM\n");
1049                 img_type = IMG_MODEM_V2;
1050                 part_id = 2;
1051                 break;
1052
1053         case COMMAND_WRITE_IMG_4:
1054                 printf("COMMAND_WRITE_BOOT_PART\n");
1055                 part_id = 1;
1056                 img_type = IMG_V2;
1057                 break;
1058
1059         case COMMAND_WRITE_IMG_5:
1060                 printf("COMMAND_WRITE_SYSTEM_PART\n");
1061                 part_id = 2;
1062                 img_type = IMG_V2;
1063                 break;
1064
1065         case COMMAND_WRITE_IMG_6:
1066                 printf("COMMAND_WRITE_UMS_PART\n");
1067                 part_id = 4;
1068                 img_type = IMG_V2;
1069                 break;
1070
1071         case COMMAND_WRITE_UBI_INFO:
1072                 printf("COMMAND_WRITE_UBI_INFO\n");
1073
1074                 if (ubi_mode) {
1075 #ifdef CONFIG_CMD_UBI
1076                         part_id = arg-1;
1077                         sprintf(length, "0x%x", (uint)len);
1078                         ret = ubi_cmd(part_id, ramaddr, length, "begin");
1079                 } else {
1080 #endif
1081                         printf("Error: Not UBI mode\n");
1082                         ret = 1;
1083                 }
1084
1085                 *((ulong *) usbd->tx_data) = ret;
1086                 /* Write image success -> Report status */
1087                 usbd->send_data(usbd->tx_data, usbd->tx_len);
1088
1089                 return !ret;
1090         /* Download complete -> reset */
1091         case COMMAND_RESET_PDA:
1092                 printf("\nDownload finished and Auto reset!\nWait........\n");
1093
1094                 /* Stop USB */
1095                 usbd->usb_stop();
1096
1097                 if (usbd->cpu_reset)
1098                         usbd->cpu_reset();
1099                 else
1100                         do_reset();
1101
1102                 return 0;
1103
1104         /* Error */
1105         case COMMAND_RESET_USB:
1106                 printf("\nError is occured!(maybe previous step)->\
1107                                 Turn off and restart!\n");
1108
1109                 /* Stop USB */
1110                 usbd->usb_stop();
1111                 return 0;
1112
1113         case COMMAND_RAM_BOOT:
1114                 usbd->usb_stop();
1115                 boot_cmd(ramaddr);
1116                 return 0;
1117
1118         case COMMAND_RAMDISK_MODE:
1119                 printf("COMMAND_RAMDISK_MODE\n");
1120 #ifdef CONFIG_RAMDISK_ADDR
1121                 if (arg) {
1122                         down_ram_addr = usbd->ram_addr;
1123                 } else {
1124                         down_ram_addr = CONFIG_RAMDISK_ADDR;
1125                         run_command("run ramboot", 0);
1126                 }
1127 #endif
1128                 return 1;
1129
1130 #ifdef CONFIG_DOWN_PHONE
1131         case COMMAND_DOWN_PHONE:
1132                 printf("COMMAND_RESET_PHONE\n");
1133
1134                 usbd_phone_down();
1135
1136                 *((ulong *) usbd->tx_data) = STATUS_DONE;
1137                 usbd->send_data(usbd->tx_data, usbd->tx_len);
1138                 return 1;
1139
1140         case COMMAND_CHANGE_USB:
1141                 printf("COMMAND_CHANGE_USB\n");
1142
1143                 /* Stop USB */
1144                 usbd->usb_stop();
1145
1146                 usbd_path_change();
1147
1148                 do_reset();
1149                 return 0;
1150 #endif
1151         case COMMAND_CSA_CLEAR:
1152                 printf("COMMAND_CSA_CLEAR\n");
1153                 part_id = get_part_id("csa");
1154                 img_type = IMG_MODEM;
1155                 break;
1156
1157         case COMMAND_PROGRESS:
1158                 if (usbd->set_progress)
1159                         usbd->set_progress(arg);
1160                 return 1;
1161
1162         default:
1163                 printf("Error: Unknown command -> (%d)\n", (int)cmd);
1164                 return 1;
1165         }
1166
1167         /* Erase and Write to NAND */
1168         switch (img_type) {
1169         case IMG_BOOT:
1170                 ofs = parts[part_id]->offset;
1171 #ifdef CONFIG_S5PC1XX
1172                 /* Workaround: for prevent revision mismatch */
1173                 if (cpu_is_s5pc110() && (down_mode != MODE_FORCE)) {
1174                         int img_rev = 1;
1175                         long *img_header = (long *)down_ram_addr;
1176
1177                         if (*img_header == 0xea000012)
1178                                 img_rev = 0;
1179                         else if (*(img_header + 0x400) == 0xea000012)
1180                                 img_rev = 2;
1181
1182                         if (img_rev != s5p_get_cpu_rev()) {
1183                                 printf("CPU revision mismatch!\n"
1184                                         "bootloader is %s%s\n"
1185                                         "download image is %s%s\n",
1186                                         s5p_get_cpu_rev() ? "EVT1" : "EVT0",
1187                                         s5p_get_cpu_rev() == 2 ? "-Fused" : "",
1188                                         img_rev ? "EVT1" : "EVT0",
1189                                         img_rev == 2 ? "-Fused" : "");
1190                                 *((ulong *) usbd->tx_data) = STATUS_ERROR;
1191                                 usbd->send_data(usbd->tx_data, usbd->tx_len);
1192                                 return 0;
1193                         }
1194                 }
1195 #endif
1196 #ifdef CONFIG_SBOOT
1197                 /* Only u-boot.bin is allowed */
1198                 {
1199                         long *img_header = (long *)down_ram_addr;
1200
1201                         if (*img_header != 0xea000018) {
1202                                 printf("\n!!! ERROR !!!\n"
1203                                         "Please download the u-boot.bin.\n"
1204                                         "Other images are not allowed.\n\n");
1205                                 *((ulong *) usbd->tx_data) = STATUS_ERROR;
1206                                 usbd->send_data(usbd->tx_data, usbd->tx_len);
1207                                 return 0;
1208                         }
1209                 }
1210 #endif
1211
1212                 erase_env_area(usbd);
1213
1214                 sprintf(offset, "%x", (uint)ofs);
1215                 if (ofs != 0)
1216                         sprintf(length, "%x", parts[part_id]->size - (uint)ofs);
1217                 else
1218                         sprintf(length, "%x", parts[part_id]->size);
1219
1220                 /* Erase */
1221                 nand_cmd(0, offset, length, NULL);
1222                 /* Write */
1223                 sprintf(length, "%x", (unsigned int) len);
1224                 ret = nand_cmd(1, ramaddr, offset, length);
1225                 break;
1226
1227         case IMG_KERNEL:
1228                 sprintf(offset, "%x", parts[part_id]->offset);
1229                 sprintf(length, "%x", parts[part_id]->size);
1230
1231                 /* Erase */
1232                 nand_cmd(0, offset, length, NULL);
1233                 /* Write */
1234                 sprintf(length, "%x", (unsigned int) len);
1235                 ret = nand_cmd(1, ramaddr, offset, length);
1236
1237                 erase_qboot_area();
1238                 break;
1239
1240         /* File Systems */
1241         case IMG_FILESYSTEM:
1242                 ret = write_file_system(ramaddr, len, offset, length,
1243                                 part_id, ubi_update);
1244
1245                 erase_qboot_area();
1246                 break;
1247
1248         case IMG_MODEM:
1249                 sprintf(offset, "%x", parts[part_id]->offset);
1250                 sprintf(length, "%x", parts[part_id]->size);
1251
1252                 /* Erase */
1253                 if (!arg)
1254                         nand_cmd(0, offset, length, NULL);
1255                 else
1256                         printf("CSA Clear will be skipped temporary\n");
1257
1258                 /* Check ubi image, 0x23494255 is UBI# */
1259                 {
1260                         long *img_header = (long *)down_ram_addr;
1261
1262                         if (*img_header == 0x23494255)
1263                                 goto ubi_img;
1264                 }
1265
1266 #ifdef CONFIG_UBIFS_MK
1267                 void *dest_addr = (void *) down_ram_addr + 0xc00000;
1268                 void *src_addr = (void *) down_ram_addr;
1269                 int leb_size, max_leb_cnt, mkfs_min_io_size;
1270                 unsigned long ubifs_dest_size, ubi_dest_size;
1271 #ifdef CONFIG_S5PC110
1272                 mkfs_min_io_size = 4096;
1273                 leb_size = 248 * 1024;
1274                 max_leb_cnt = 4096;
1275 #elif CONFIG_S5PC210
1276                 mkfs_min_io_size = 2048;
1277                 leb_size = 126 * 1024;
1278                 max_leb_cnt = 4096;
1279 #endif
1280                 printf("Start making ubifs\n");
1281                 ret = mkfs(src_addr, len, dest_addr, &ubifs_dest_size,
1282                            mkfs_min_io_size, leb_size, max_leb_cnt);
1283                 if (ret) {
1284                         printf("Error : making ubifs failed\n");
1285                         goto out;
1286                 }
1287                 printf("Complete making ubifs\n");
1288 #endif
1289
1290 #ifdef CONFIG_UBINIZE
1291                 int peb_size, ubi_min_io_size, subpage_size, vid_hdr_offs;
1292 #ifdef CONFIG_S5PC110
1293                 ubi_min_io_size = 4096;
1294                 peb_size = 256 * 1024;
1295                 subpage_size = 4096;
1296                 vid_hdr_offs = 0;
1297 #elif CONFIG_S5PC210
1298                 ubi_min_io_size = 2048;
1299                 peb_size = 128 * 1024;
1300                 subpage_size = 512;
1301                 vid_hdr_offs = 512;
1302 #endif
1303                 printf("Start ubinizing\n");
1304                 ret = ubinize(dest_addr, ubifs_dest_size,
1305                               src_addr, &ubi_dest_size,
1306                               peb_size, ubi_min_io_size,
1307                               subpage_size, vid_hdr_offs);
1308                 if (ret) {
1309                         printf("Error : ubinizing failed\n");
1310                         goto out;
1311                 }
1312                 printf("Complete ubinizing\n");
1313
1314                 len = (unsigned int) ubi_dest_size;
1315 #endif
1316
1317 ubi_img:
1318                 /* Write : arg (0 Modem) / (1 CSA) */
1319                 if (!arg) {
1320                         sprintf(length, "%x", (unsigned int) len);
1321                         ret = nand_cmd(1, ramaddr, offset, length);
1322                 }
1323 out:
1324                 break;
1325
1326 #ifdef CONFIG_CMD_MMC
1327         case IMG_MMC:
1328
1329                 if (mmc_part_write)
1330                         ret = write_file_mmc_part(usbd, len);
1331                 else
1332                         ret = write_file_mmc(usbd, len);
1333
1334                 erase_qboot_area();
1335                 break;
1336 #endif
1337         case IMG_V2:
1338                 ret = write_mmc_image(usbd, len, part_id);
1339                 break;
1340
1341         case IMG_MBR:
1342 #ifdef CONFIG_CMD_MBR
1343                 set_mbr_info(usbd, (char *)down_ram_addr, len);
1344 #endif
1345                 break;
1346
1347         case IMG_BOOTLOADER:
1348 #ifdef CONFIG_BOOTLOADER_SECTOR
1349                 erase_env_area(usbd);
1350
1351                 ret = mmc_cmd(OPS_WRITE, usbd->mmc_dev,
1352                                 CONFIG_BOOTLOADER_SECTOR,
1353                                 len / usbd->mmc_blk + 1,
1354                                 (void *)down_ram_addr);
1355 #endif
1356                 break;
1357
1358         case IMG_KERNEL_V2:
1359                 ret = write_fat_file(usbd, "uImage", part_id, len);
1360                 break;
1361
1362         case IMG_MODEM_V2:
1363                 ret = write_fat_file(usbd, "modem.bin", part_id, len);
1364                 break;
1365
1366         default:
1367                 /* Retry? */
1368                 write_part--;
1369         }
1370
1371         if (ret) {
1372                 /* Retry this commad */
1373                 *((ulong *) usbd->tx_data) = STATUS_RETRY;
1374                 usbd->send_data(usbd->tx_data, usbd->tx_len);
1375                 return 1;
1376         } else
1377                 *((ulong *) usbd->tx_data) = STATUS_DONE;
1378
1379         /* Write image success -> Report status */
1380         usbd->send_data(usbd->tx_data, usbd->tx_len);
1381
1382         write_part++;
1383
1384         /* Reset write count for another image */
1385         if (flag) {
1386                 write_part = 0;
1387                 fs_offset = 0;
1388 #ifdef CONFIG_USE_YAFFS
1389                 yaffs_len = 0;
1390 #endif
1391         }
1392
1393         return 1;
1394 }
1395
1396 static const char *recv_key = "SAMSUNG";
1397 static const char *tx_key = "MPL";
1398
1399 int do_usbd_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1400 {
1401         struct usbd_ops *usbd;
1402         int err;
1403
1404         if (argc > 1)
1405                 down_mode = simple_strtoul(argv[1], NULL, 10);
1406         else
1407                 down_mode = MODE_NORMAL;
1408
1409         printf("USB Downloader v%s\n", APP_VERSION);
1410
1411         /* get partition info */
1412         err = get_part_info();
1413         if (err)
1414                 return err;
1415
1416         /* interface setting */
1417         usbd = usbd_set_interface(&usbd_ops);
1418         down_ram_addr = usbd->ram_addr;
1419
1420 #ifdef CONFIG_CMD_MBR
1421         /* get mbr info */
1422         mbr_parts = get_mbr_table(mbr_offset);
1423         if (!mbr_parts) {
1424                 char *mbrparts;
1425
1426                 puts("using default MBR\n");
1427
1428                 mbrparts = getenv("mbrparts");
1429                 set_mbr_info(usbd, mbrparts, strlen(mbrparts));
1430         }
1431 #endif
1432
1433         /* init the usb controller */
1434         if (!usbd->usb_init()) {
1435                 usbd->down_cancel();
1436                 return 0;
1437         }
1438         mmc = find_mmc_device(usbd->mmc_dev);
1439         mmc_init(mmc);
1440
1441         /* receive setting */
1442         usbd->recv_setup(usbd->rx_data, usbd->rx_len);
1443
1444         /* detect the download request from Host PC */
1445         if (usbd->recv_data()) {
1446                 if (strncmp(usbd->rx_data, recv_key, strlen(recv_key)) == 0) {
1447                         printf("Download request from the Host PC\n");
1448                         msleep(30);
1449
1450                         strcpy(usbd->tx_data, tx_key);
1451                         usbd->send_data(usbd->tx_data, usbd->tx_len);
1452                 } else {
1453                         printf("No download request from the Host PC!! 1\n");
1454                         return 0;
1455                 }
1456         } else {
1457                 usbd->down_cancel();
1458                 return 0;
1459         }
1460
1461         usbd->down_start();
1462         printf("Receive the packet\n");
1463
1464         /* receive the data from Host PC */
1465         while (1) {
1466                 usbd->recv_setup(usbd->rx_data, usbd->rx_len);
1467
1468                 if (usbd->recv_data()) {
1469                         if (process_data(usbd) == 0)
1470                                 return 0;
1471                 }
1472         }
1473
1474         return 0;
1475 }
1476
1477 U_BOOT_CMD(usbdown, CONFIG_SYS_MAXARGS, 1, do_usbd_down,
1478         "Initialize USB device and Run USB Downloader (specific)",
1479         "- normal mode\n"
1480         "usbdown mode - specific mode (0: NORAML, 1: FORCE)"
1481 );