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