2 * USB Downloader for SAMSUNG Platform
4 * Copyright (C) 2007-2008 Samsung Electronics
5 * Minkyu Kang <mk7.kang@samsung.com>
11 #include <asm/errno.h>
14 /* version of USB Downloader Application */
15 #define APP_VERSION "1.5.3"
20 #ifdef CONFIG_CMD_MTDPARTS
21 #include <jffs2/load_kernel.h>
22 static struct part_info *parts[16];
25 static const char pszMe[] = "usbd: ";
27 static struct usbd_ops usbd_ops;
29 static unsigned int part_id;
30 static unsigned int write_part = 0;
31 static unsigned long fs_offset = 0x0;
33 #ifdef CONFIG_USE_YAFFS
34 static unsigned int yaffs_len = 0;
35 static unsigned char yaffs_data[2112];
36 #define YAFFS_PAGE 2112
39 #define NAND_PAGE_SIZE 2048
41 static unsigned long down_ram_addr;
45 /* cpu/${CPU} dependent */
46 extern void do_reset(void);
49 extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
50 extern int do_run(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
52 int mtdparts_init(void);
53 int find_dev_and_part(const char*, struct mtd_device**, u8*, struct part_info**);
55 /* common/cmd_jffs2.c */
56 extern struct list_head devices;
58 static u8 count_mtdparts(void)
60 struct list_head *dentry, *pentry;
61 struct mtd_device *dev;
64 list_for_each(dentry, &devices) {
65 dev = list_entry(dentry, struct mtd_device, link);
67 /* list partitions for given device */
68 list_for_each(pentry, &dev->parts)
76 static int check_ubi_mode(void)
81 env_ubifs = getenv("ubi");
82 ubi_mode = !strcmp(env_ubifs, "enabled");
87 #define check_ubi_mode() 0
90 #ifdef CONFIG_MTD_PARTITIONS
91 static int get_part_info(void)
93 struct mtd_device *dev;
101 #if defined(CONFIG_CMD_NAND)
102 sprintf(nand_name, "nand0");
103 #elif defined(CONFIG_CMD_ONENAND)
104 sprintf(nand_name, "onenand0");
106 printf("Configure your NAND sub-system\n");
113 ubi_mode = check_ubi_mode();
115 part_num = count_mtdparts();
116 for (i = 0; i < part_num; i++) {
117 sprintf(part_name, "%s,%d", nand_name, i);
119 if (find_dev_and_part(part_name, &dev, &out_partnum, &parts[i]))
126 static int get_part_id(char *name)
128 int nparts = count_mtdparts();
131 for (i = 0; i < nparts; i++) {
132 if (strcmp(parts[i]->name, name) == 0)
136 printf("Error: Unknown partition -> %s\n", name);
140 static int get_part_info(void)
142 printf("Error: Can't get patition information\n");
146 static int get_part_id(char *name)
152 static void boot_cmd(char *addr)
154 char *argv[] = { "bootm", addr };
155 do_bootm(NULL, 0, 2, argv);
158 static void run_cmd(char *cmd)
160 char *argv[] = { "run", cmd };
161 do_run(NULL, 0, 2, argv);
164 #if defined(CONFIG_CMD_NAND)
165 extern int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
166 #elif defined(CONFIG_CMD_ONENAND)
167 extern int do_onenand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
170 /* NAND erase and write using nand command */
171 static int nand_cmd(int type, char *p1, char *p2, char *p3)
175 int (*nand_func) (cmd_tbl_t *, int, int, char **);
177 #if defined(CONFIG_CMD_NAND)
178 sprintf(nand_name, "nand");
180 #elif defined(CONFIG_CMD_ONENAND)
181 sprintf(nand_name, "onenand");
182 nand_func = do_onenand;
184 printf("Configure your NAND sub-system\n");
189 char *argv[] = {nand_name, "erase", p1, p2};
190 printf("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
191 ret = nand_func(NULL, 0, 4, argv);
192 } else if (type == 1) {
193 char *argv[] = {nand_name, "write", p1, p2, p3};
194 printf("%s %s %s %s %s\n", argv[0], argv[1], argv[2],
196 ret = nand_func(NULL, 0, 5, argv);
197 } else if (type == 2) {
198 char *argv[] = {nand_name, "write.yaffs", p1, p2, p3};
199 printf("%s %s %s %s %s\n", argv[0], argv[1], argv[2],
201 ret = nand_func(NULL, 0, 5, argv);
202 } else if (type == 3) {
203 char *argv[] = {nand_name, "lock", p1, p2};
204 printf("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
205 ret = nand_func(NULL, 0, 4, argv);
209 printf("Error: NAND Command\n");
214 #ifdef CONFIG_CMD_UBI
215 int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
217 int ubi_cmd(int part, char *p1, char *p2, char *p3)
221 if (part == RAMDISK_PART_ID) {
222 char *argv[] = {"ubi", "write", p1, "rootfs.cramfs", p2, p3};
223 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
224 argv[3], argv[4], argv[5]);
225 ret = do_ubi(NULL, 0, 6, argv);
226 } else if (part == FILESYSTEM_PART_ID) {
227 char *argv[] = {"ubi", "write", p1, "factoryfs.cramfs", p2, p3};
228 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
229 argv[3], argv[4], argv[5]);
230 ret = do_ubi(NULL, 0, 6, argv);
231 } else if (part == FILESYSTEM2_PART_ID) {
232 char *argv[] = {"ubi", "write", p1, "datafs.ubifs", 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);
242 #ifdef CONFIG_CMD_MMC
245 extern int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
247 static int mmc_cmd(int ops, char *p1, char *p2, char *p3)
252 char *argv[] = {"mmc", "write", "0", p1, p2, p3};
253 ret = do_mmcops(NULL, 0, 6, argv);
255 char *argv[] = {"mmc", "read", "0", p1, p2, p3};
256 ret = do_mmcops(NULL, 0, 6, argv);
262 #define NORMAL_PARTITION 0
263 #define EXTEND_PARTITION 1
265 #define EXTEND_PART_TYPE 5
267 #define EXTEND_MAX_PART 32
269 static unsigned int cur_blk_offset;
270 static unsigned int cur_part_size;
271 static unsigned int cur_part;
273 static unsigned int mmc_parts;
274 static unsigned int mmc_part_write;
276 static u8 part_mode = 0;
278 struct partition_info {
282 } __attribute__((packed));
284 struct partition_header {
285 u8 fat32head[16]; /* RFSHEAD identifier */
286 struct partition_info partition[EXTEND_MAX_PART];
287 u8 res[112]; /* reserved */
288 } __attribute__((packed));
290 struct partition_table {
297 } __attribute__((packed));
301 struct partition_table partition[4];
303 } __attribute__((packed));
305 struct mul_partition_info {
308 } __attribute__((packed));
310 #define MBR_OFFSET 0x10
312 struct partition_header part_info;
313 struct mbr_table mbr_info;
314 struct mul_partition_info mul_info[EXTEND_MAX_PART];
316 static int write_mmc_partition(struct usbd_ops *usbd, u32 *ram_addr, u32 len)
319 char offset[12], length[12], ramaddr[12];
325 if (cur_part_size > len) {
326 blocks = len / usbd->mmc_blk;
329 blocks = cur_part_size / usbd->mmc_blk;
330 ret = len - cur_part_size;
333 if (len % usbd->mmc_blk)
336 loop = blocks / usbd->mmc_max;
337 if (blocks % usbd->mmc_max)
340 for (i = 0; i < loop; i++) {
342 cnt = blocks % usbd->mmc_max;
349 sprintf(length, "%x", cnt);
350 sprintf(offset, "%x", cur_blk_offset);
351 sprintf(ramaddr, "0x%x", *ram_addr);
352 mmc_cmd(OPS_WRITE, ramaddr, offset, length);
354 cur_blk_offset += cnt;
356 *ram_addr += (cnt * usbd->mmc_blk);
362 static int write_file_mmc(struct usbd_ops *usbd, char *ramaddr, u32 len,
363 char *offset, char *length)
368 struct mbr_table *mbr;
370 if (!usbd->mmc_total) {
371 printf("MMC is not supported!\n");
375 ram_addr = (u32)down_ram_addr;
377 if (cur_blk_offset == 0) {
381 memcpy(&part_info, (void *)ram_addr,
382 sizeof(struct partition_header));
384 ram_addr += sizeof(struct partition_header);
385 len -= sizeof(struct partition_header);
386 mbr = (struct mbr_table*)ram_addr;
387 mbr_blk_size = mbr->partition[0].lba_begin;
389 if (mbr->partition[0].type_code != EXTEND_PART_TYPE) {
390 part_mode = NORMAL_PARTITION;
392 /* modify sectors of p1 */
393 mbr->partition[0].num_sectors = usbd->mmc_total -
395 mbr->partition[1].num_sectors +
396 mbr->partition[2].num_sectors +
397 mbr->partition[3].num_sectors);
401 /* modify lba_begin of p2 and p3 and p4 */
402 for (i = 1; i < 4; i++) {
403 if (part_info.partition[i].size == 0)
407 mbr->partition[i].lba_begin =
408 mbr->partition[i - 1].lba_begin +
409 mbr->partition[i - 1].num_sectors;
413 memcpy(&mbr_info, mbr, sizeof(struct mbr_table));
415 printf("Total Size: 0x%08x #parts %d\n",
416 (unsigned int)usbd->mmc_total,
418 for (i = 0; i < mmc_parts; i++) {
419 printf("p%d\t0x%08x\t0x%08x\n", i + 1,
420 mbr_info.partition[i].lba_begin,
421 mbr_info.partition[i].num_sectors);
425 sprintf(length, "%x", mbr_blk_size);
426 sprintf(offset, "%x", 0);
427 sprintf(ramaddr, "0x%x", (u32)ram_addr);
428 ret = mmc_cmd(OPS_WRITE, ramaddr, offset, length);
430 ram_addr += mbr_blk_size * usbd->mmc_blk;
431 len -= mbr_blk_size * usbd->mmc_blk;
433 cur_blk_offset = mbr_blk_size;
435 cur_part_size = part_info.partition[0].size;
437 /* modify p1's total sector */
438 bs = (boot_sector *)ram_addr;
439 bs->total_sect = mbr_info.partition[0].num_sectors;
441 printf("\nWrite Partition %d.. %d blocks\n",
443 part_info.partition[cur_part].size /
446 part_mode = EXTEND_PARTITION;
448 for (i = 0; i < EXTEND_MAX_PART; i++) {
449 if (part_info.partition[i].size == 0)
457 printf("found %d partitions\n", mmc_parts);
459 /* build partition table */
461 mul_info[0].num_sectors =
462 usbd->mmc_total - mbr_blk_size * 2;
463 for (i = 1; i < mmc_parts; i++) {
464 mul_info[i].num_sectors =
465 part_info.partition[i].res;
468 for (i = 1; i < mmc_parts; i++) {
469 mul_info[0].num_sectors -=
470 mul_info[i].num_sectors;
473 mul_info[0].lba_begin = mbr->partition[0].lba_begin;
474 for (i = 1; i < mmc_parts; i++) {
475 mul_info[i].lba_begin =
476 mul_info[i-1].lba_begin +
477 mul_info[i-1].num_sectors;
480 /* modify main MBR */
481 mbr->partition[0].num_sectors =
482 usbd->mmc_total - mbr_blk_size;
484 /* modify MBR data of p1 */
485 mbr = (struct mbr_table *)
486 (ram_addr + mbr_blk_size * usbd->mmc_blk);
488 mbr->partition[0].num_sectors =
489 mul_info[0].num_sectors - mbr_blk_size;
490 mbr->partition[1].lba_begin =
491 mul_info[1].lba_begin - mbr_blk_size;
493 /* modify BPB data of p1 */
495 ((u32)mbr + mbr_blk_size * usbd->mmc_blk);
496 memset(&bs->sectors, 0, 2);
497 bs->total_sect = mbr->partition[0].num_sectors;
499 printf("Total Size: 0x%08x #parts %d\n",
500 (unsigned int)usbd->mmc_total,
502 for (i = 0; i < mmc_parts; i++) {
503 printf("p%d\t0x%08x\t0x%08x\n", i + 1,
504 mul_info[i].lba_begin,
505 mul_info[i].num_sectors);
510 cur_part_size = part_info.partition[0].size;
512 printf("\nWrite Partition %d.. %d blocks\n",
514 part_info.partition[cur_part].size /
519 for (i = cur_part; i < mmc_parts; i++) {
520 ret = write_mmc_partition(usbd, &ram_addr, len);
523 cur_part_size -= len;
528 part_info.partition[cur_part].size;
530 if (part_mode == NORMAL_PARTITION) {
532 mbr_info.partition[cur_part].lba_begin;
535 mul_info[cur_part].lba_begin;
537 if (cur_part <= mmc_parts) {
538 mbr = (struct mbr_table *)ram_addr;
539 mbr->partition[1].lba_begin =
540 mul_info[cur_part+1].lba_begin -
541 mbr->partition[0].lba_begin;
550 printf("\nWrite Partition %d.. %d blocks\n",
552 part_info.partition[cur_part].size /
560 static int write_file_mmc_part(struct usbd_ops *usbd, char *ramaddr, u32 len,
561 char *offset, char *length)
566 struct mbr_table *mbr;
569 ram_addr = (u32)down_ram_addr;
572 if (cur_blk_offset == 0) {
574 sprintf(length, "%x", (unsigned int)
575 (sizeof(struct mbr_table)/usbd->mmc_blk));
576 sprintf(offset, "%x", 0);
577 sprintf(ramaddr, "0x%x", (u32)mbr);
578 mmc_cmd(OPS_READ, ramaddr, offset, length);
580 mbr_blk_size = mbr->partition[0].lba_begin;
582 if (mbr->partition[0].type_code != EXTEND_PART_TYPE) {
583 part_mode = NORMAL_PARTITION;
585 for (i = 0; i < 4; i++) {
586 printf("p%d\t0x%08x\t0x%08x\n", i + 1,
587 mbr_info.partition[i].lba_begin,
588 mbr_info.partition[i].num_sectors);
592 mbr->partition[mmc_part_write - 1].lba_begin;
593 cur_part = mmc_part_write - 1;
596 if (mmc_part_write == 1) {
597 ram_addr += sizeof(struct mbr_table);
598 cur_blk_offset += sizeof(struct mbr_table) /
600 len -= sizeof(struct mbr_table);
603 part_mode = EXTEND_PARTITION;
605 mbr_blk_size = mbr->partition[0].lba_begin;
607 for (i = 1; i < mmc_part_write; i++) {
608 ofs = mbr->partition[0].lba_begin +
609 mbr->partition[1].lba_begin;
610 printf("P%d start blk: 0x%x, size: 0x%x\n", i,
611 ofs, mbr->partition[0].num_sectors);
612 sprintf(length, "%x", (unsigned int)
613 (sizeof(struct mbr_table) /
615 sprintf(offset, "%x", ofs);
616 sprintf(ramaddr, "0x%x", (u32)mbr);
617 mmc_cmd(OPS_READ, ramaddr, offset, length);
620 ofs = mbr->partition[0].lba_begin +
621 mbr->partition[1].lba_begin;
623 ofs += mbr_blk_size; /* skip MBR */
624 cur_blk_offset = ofs;
625 cur_part = mmc_part_write - 1;
628 if (mmc_part_write == 1) {
632 /* modify BPB data of p1 */
633 sprintf(length, "%x", (unsigned int)
634 (sizeof(struct mbr_table) /
636 sprintf(offset, "%x", cur_blk_offset);
637 sprintf(ramaddr, "0x%x", (u32)mbr);
638 mmc_cmd(OPS_READ, ramaddr, offset, length);
640 bs = (boot_sector *)mbr;
641 total_sect = bs->total_sect;
643 bs = (boot_sector *)ram_addr;
644 memset(&bs->sectors, 0, 2);
645 bs->total_sect = total_sect;
650 printf("\nWrite Partition %d.. %d blocks\n",
652 len / (int)usbd->mmc_blk);
654 write_mmc_partition(usbd, &ram_addr, len);
660 static int write_file_system(char *ramaddr, ulong len, char *offset,
661 char *length, int part_num, int ubi_update)
663 #ifdef CONFIG_USE_YAFFS
669 #ifdef CONFIG_CMD_UBI
672 sprintf(length, "0x%x", (uint)len);
673 ret = ubi_cmd(part_id, ramaddr, length, "cont");
678 /* Erase entire partition at the first writing */
679 if (write_part == 0 && ubi_update == 0) {
680 sprintf(offset, "0x%x", (uint)parts[part_num]->offset);
681 sprintf(length, "0x%x", (uint)parts[part_num]->size);
682 nand_cmd(0, offset, length, NULL);
685 #ifdef CONFIG_USE_YAFFS
686 /* if using yaffs, wirte size must be 2112*X
687 * so, must have to realloc, and writing */
688 if (!strcmp("yaffs", getenv(parts[part_num]->name))) {
691 memcpy((void *)down_ram_addr, yaffs_data, yaffs_len);
693 actual_len = len + yaffs_len;
694 yaffs_len = actual_len % YAFFS_PAGE;
695 len = actual_len - yaffs_len;
697 memset(yaffs_data, 0x00, YAFFS_PAGE);
698 memcpy(yaffs_data, (char *)down_ram_addr + len, yaffs_len);
702 sprintf(offset, "0x%x", (uint)(parts[part_num]->offset + fs_offset));
703 sprintf(length, "0x%x", (uint)len);
705 #ifdef CONFIG_USE_YAFFS
707 ret = nand_cmd(2, ramaddr, offset, length);
709 ret = nand_cmd(1, ramaddr, offset, length);
711 if (!strcmp("yaffs", getenv(parts[part_num]->name)))
712 fs_offset += len / YAFFS_PAGE * NAND_PAGE_SIZE;
718 ret = nand_cmd(1, ramaddr, offset, length);
724 static int qboot_erase = 0;
726 /* Erase the qboot */
727 static void erase_qboot_area(void)
729 char offset[12], length[12];
735 qboot_id = get_part_id("qboot");
737 if (qboot_id != -1) {
738 printf("\nCOMMAND_ERASE_QBOOT\n");
739 sprintf(offset, "%x", parts[qboot_id]->offset);
740 sprintf(length, "%x", parts[qboot_id]->size);
741 nand_cmd(0, offset, length, NULL);
746 /* Parsing received data packet and Process data */
747 static int process_data(struct usbd_ops *usbd)
749 ulong cmd = 0, arg = 0, ofs = 0, len = 0, flag = 0;
750 char offset[12], length[12], ramaddr[12];
752 unsigned int blocks = 0;
758 sprintf(ramaddr, "0x%x", (uint) down_ram_addr);
761 cmd = *((ulong *) usbd->rx_data + 0);
762 arg = *((ulong *) usbd->rx_data + 1);
763 len = *((ulong *) usbd->rx_data + 2);
764 flag = *((ulong *) usbd->rx_data + 3);
766 /* Reset tx buffer */
767 memset(usbd->tx_data, 0, sizeof(usbd->tx_data));
769 ubi_mode = check_ubi_mode();
772 case COMMAND_DOWNLOAD_IMAGE:
773 printf("\nCOMMAND_DOWNLOAD_IMAGE\n");
775 #ifdef CONFIG_USE_YAFFS
776 usbd->recv_setup((char *)down_ram_addr + yaffs_len, (int)len);
777 printf("Download to 0x%08x, %d bytes\n",
778 (uint)down_ram_addr + yaffs_len, (int)len);
780 usbd->recv_setup((char *)down_ram_addr, (int)len);
781 printf("Download to 0x%08x, %d bytes\n",
782 (uint)down_ram_addr, (int)len);
785 usbd->send_data(usbd->tx_data, usbd->tx_len);
787 /* Receive image by using dma */
788 recvlen = usbd->recv_data();
790 printf("Error: wrong image size -> %d/%d\n",
791 (int)recvlen, (int)len);
793 /* Retry this commad */
794 *((ulong *) usbd->tx_data) = STATUS_RETRY;
796 *((ulong *) usbd->tx_data) = STATUS_DONE;
798 usbd->send_data(usbd->tx_data, usbd->tx_len);
801 /* Report partition info */
802 case COMMAND_PARTITION_SYNC:
805 #ifdef CONFIG_CMD_UBI
807 if (part_id == RAMDISK_PART_ID ||
808 part_id == FILESYSTEM_PART_ID ||
809 part_id == FILESYSTEM2_PART_ID) {
810 /* change to yaffs style */
814 if (part_id == FILESYSTEM3_PART_ID) {
815 /* change ubi style */
821 if (part_id == FILESYSTEM3_PART_ID)
822 part_id = get_part_id("UBI");
823 else if (part_id == MODEM_PART_ID)
824 part_id = get_part_id("modem");
825 else if (part_id == KERNEL_PART_ID)
826 part_id = get_part_id("kernel");
831 printf("COMMAND_PARTITION_SYNC - Part%d\n", part_id);
833 blocks = parts[part_id]->size / 1024 / 128;
834 printf("COMMAND_PARTITION_SYNC - Part%d, %d blocks\n",
837 *((ulong *) usbd->tx_data) = blocks;
838 usbd->send_data(usbd->tx_data, usbd->tx_len);
841 case COMMAND_WRITE_PART_0:
843 printf("COMMAND_WRITE_PART_0\n");
846 case COMMAND_WRITE_PART_1:
847 printf("COMMAND_WRITE_PART_BOOT\n");
848 part_id = get_part_id("bootloader");
852 case COMMAND_WRITE_PART_2:
853 case COMMAND_ERASE_PARAMETER:
854 printf("COMMAND_PARAMETER - not support!\n");
857 case COMMAND_WRITE_PART_3:
858 printf("COMMAND_WRITE_KERNEL\n");
859 part_id = get_part_id("kernel");
860 img_type = IMG_KERNEL;
863 case COMMAND_WRITE_PART_4:
864 printf("COMMAND_WRITE_ROOTFS\n");
865 part_id = get_part_id("Root");
866 img_type = IMG_FILESYSTEM;
870 case COMMAND_WRITE_PART_5:
871 printf("COMMAND_WRITE_FACTORYFS\n");
872 part_id = get_part_id("Fact");
873 img_type = IMG_FILESYSTEM;
877 case COMMAND_WRITE_PART_6:
878 printf("COMMAND_WRITE_DATAFS\n");
879 part_id = get_part_id("Data");
880 img_type = IMG_FILESYSTEM;
884 case COMMAND_WRITE_PART_7:
885 printf("COMMAND_WRITE_UBI\n");
886 part_id = get_part_id("UBI");
887 img_type = IMG_FILESYSTEM;
889 /* someday, it will be deleted */
893 case COMMAND_WRITE_PART_8:
894 printf("COMMAND_WRITE_MODEM\n");
895 part_id = get_part_id("modem");
896 img_type = IMG_MODEM;
899 #ifdef CONFIG_CMD_MMC
900 case COMMAND_WRITE_PART_9:
901 printf("COMMAND_WRITE_MMC\n");
903 mmc_part_write = arg;
907 case COMMAND_WRITE_UBI_INFO:
908 printf("COMMAND_WRITE_UBI_INFO\n");
911 #ifdef CONFIG_CMD_UBI
913 sprintf(length, "0x%x", (uint)len);
914 ret = ubi_cmd(part_id, ramaddr, length, "begin");
917 printf("Error: Not UBI mode\n");
921 *((ulong *) usbd->tx_data) = ret;
922 /* Write image success -> Report status */
923 usbd->send_data(usbd->tx_data, usbd->tx_len);
926 /* Download complete -> reset */
927 case COMMAND_RESET_PDA:
928 printf("\nDownload finished and Auto reset!\nWait........\n");
941 case COMMAND_RESET_USB:
942 printf("\nError is occured!(maybe previous step)->\
943 Turn off and restart!\n");
949 case COMMAND_RAM_BOOT:
954 case COMMAND_RAMDISK_MODE:
955 printf("COMMAND_RAMDISK_MODE\n");
956 #ifdef CONFIG_RAMDISK_ADDR
958 down_ram_addr = usbd->ram_addr;
960 down_ram_addr = CONFIG_RAMDISK_ADDR;
966 #ifdef CONFIG_DOWN_PHONE
967 case COMMAND_DOWN_PHONE:
968 printf("COMMAND_RESET_PHONE\n");
972 *((ulong *) usbd->tx_data) = STATUS_DONE;
973 usbd->send_data(usbd->tx_data, usbd->tx_len);
976 case COMMAND_CHANGE_USB:
977 printf("COMMAND_CHANGE_USB\n");
987 case COMMAND_CSA_CLEAR:
988 printf("COMMAND_CSA_CLEAR\n");
989 part_id = get_part_id("csa");
990 img_type = IMG_MODEM;
993 case COMMAND_PROGRESS:
994 if (usbd->set_progress)
995 usbd->set_progress(arg);
999 printf("Error: Unknown command -> (%d)\n", (int)cmd);
1003 /* Erase and Write to NAND */
1006 ofs = parts[part_id]->offset;
1007 #ifdef CONFIG_RECOVERY
1010 1m = ipl(16k)+recovery(240k)+bootloader(768k)*/
1011 long *buf = (long *)down_ram_addr;
1013 u32 bootloader_edge = parts[part_id]->size;
1014 u32 bootloader_addr = bootloader_edge >> 2;
1015 u32 recovery_edge = bootloader_addr;
1016 u32 recovery_addr = recovery_edge >> 4;
1019 if (len > bootloader_addr) {
1020 ofst = bootloader_addr / sizeof(buf);
1021 if (*(buf + ofst) == 0xea000012) {
1022 /* case: ipl + recovery + bootloader */
1023 printf("target: ipl + recovery + loader\n");
1026 /* case: unknown format */
1027 printf("target: unknown\n");
1028 *((ulong *) usbd->tx_data) = STATUS_ERROR;
1029 usbd->send_data(usbd->tx_data, usbd->tx_len);
1033 ofst = recovery_addr/sizeof(buf);
1034 if (*(buf + ofst) == 0xea000012 &&
1035 *(buf + ofst - 1) == 0x00000000) {
1036 /* case: ipl + bootloader (old type) */
1037 printf("target: ipl + bootloader\n");
1040 /* case: bootloader only */
1041 printf("target: bootloader\n");
1042 ofs = bootloader_addr;
1044 /* skip revision check */
1045 down_mode = MODE_FORCE;
1049 sprintf(offset, "%x", (uint)ofs);
1050 sprintf(length, "%x", parts[part_id]->size);
1052 /* check block is locked/locked-tight */
1053 ret = nand_cmd(3, offset, length, NULL);
1055 printf("target is locked%s\n",
1056 (ret == 1) ? "-tight" : "");
1057 printf("-> try at recovery mode "
1058 "to update 'system'.\n");
1059 printf(" how-to: reset "
1060 "while pressing volume up and down.\n");
1061 *((ulong *) usbd->tx_data) = STATUS_ERROR;
1062 usbd->send_data(usbd->tx_data, usbd->tx_len);
1067 #ifdef CONFIG_S5PC1XX
1068 /* Workaround: for prevent revision mismatch */
1069 if (cpu_is_s5pc110() && (down_mode != MODE_FORCE)) {
1071 long *img_header = (long *)down_ram_addr;
1073 if (*img_header == 0xea000012)
1075 else if (*(img_header + 0x400) == 0xea000012)
1078 if (img_rev != s5p_get_cpu_rev()) {
1079 printf("CPU revision mismatch!\n"
1080 "bootloader is %s%s\n"
1081 "download image is %s%s\n",
1082 s5p_get_cpu_rev() ? "EVT1" : "EVT0",
1083 s5p_get_cpu_rev() == 2 ? "-Fused" : "",
1084 img_rev ? "EVT1" : "EVT0",
1085 img_rev == 2 ? "-Fused" : "");
1086 *((ulong *) usbd->tx_data) = STATUS_ERROR;
1087 usbd->send_data(usbd->tx_data, usbd->tx_len);
1092 #if defined(CONFIG_ENV_IS_IN_NAND) || defined(CONFIG_ENV_IS_IN_ONENAND)
1093 /* Erase the environment also when write bootloader */
1096 param_id = get_part_id("params");
1098 if (param_id == -1) {
1099 sprintf(offset, "%x", CONFIG_ENV_ADDR);
1100 sprintf(length, "%x", CONFIG_ENV_SIZE);
1102 sprintf(offset, "%x", parts[param_id]->offset);
1103 sprintf(length, "%x", parts[param_id]->size);
1105 nand_cmd(0, offset, length, NULL);
1108 sprintf(offset, "%x", (uint)ofs);
1110 sprintf(length, "%x", parts[part_id]->size - (uint)ofs);
1112 sprintf(length, "%x", parts[part_id]->size);
1115 nand_cmd(0, offset, length, NULL);
1117 sprintf(length, "%x", (unsigned int) len);
1118 ret = nand_cmd(1, ramaddr, offset, length);
1122 sprintf(offset, "%x", parts[part_id]->offset);
1123 sprintf(length, "%x", parts[part_id]->size);
1126 nand_cmd(0, offset, length, NULL);
1128 sprintf(length, "%x", (unsigned int) len);
1129 ret = nand_cmd(1, ramaddr, offset, length);
1135 case IMG_FILESYSTEM:
1136 ret = write_file_system(ramaddr, len, offset, length,
1137 part_id, ubi_update);
1143 sprintf(offset, "%x", parts[part_id]->offset);
1144 sprintf(length, "%x", parts[part_id]->size);
1148 nand_cmd(0, offset, length, NULL);
1150 printf("CSA Clear will be skipped temporary\n");
1152 /* Write : arg (0 Modem) / (1 CSA) */
1154 sprintf(length, "%x", (unsigned int) len);
1155 ret = nand_cmd(1, ramaddr, offset, length);
1159 #ifdef CONFIG_CMD_MMC
1163 ret = write_file_mmc_part(usbd, ramaddr,
1164 len, offset, length);
1166 ret = write_file_mmc(usbd, ramaddr,
1167 len, offset, length);
1179 /* Retry this commad */
1180 *((ulong *) usbd->tx_data) = STATUS_RETRY;
1181 usbd->send_data(usbd->tx_data, usbd->tx_len);
1184 *((ulong *) usbd->tx_data) = STATUS_DONE;
1186 /* Write image success -> Report status */
1187 usbd->send_data(usbd->tx_data, usbd->tx_len);
1191 /* Reset write count for another image */
1195 #ifdef CONFIG_USE_YAFFS
1203 static const char *recv_key = "SAMSUNG";
1204 static const char *tx_key = "MPL";
1206 int do_usbd_down(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
1208 struct usbd_ops *usbd;
1212 down_mode = simple_strtoul(argv[1], NULL, 10);
1214 down_mode = MODE_NORMAL;
1216 printf("USB Downloader v%s\n", APP_VERSION);
1218 /* get partition info */
1219 err = get_part_info();
1223 /* interface setting */
1224 usbd = usbd_set_interface(&usbd_ops);
1225 down_ram_addr = usbd->ram_addr;
1227 /* init the usb controller */
1230 /* receive setting */
1231 usbd->recv_setup(usbd->rx_data, usbd->rx_len);
1233 /* detect the download request from Host PC */
1234 if (usbd->recv_data()) {
1235 if (strncmp(usbd->rx_data, recv_key, strlen(recv_key)) == 0) {
1236 printf("Download request from the Host PC\n");
1239 strcpy(usbd->tx_data, tx_key);
1240 usbd->send_data(usbd->tx_data, usbd->tx_len);
1242 printf("No download request from the Host PC!! 1\n");
1246 printf("No download request from the Host PC!!\n");
1250 printf("Receive the packet\n");
1252 /* receive the data from Host PC */
1254 usbd->recv_setup(usbd->rx_data, usbd->rx_len);
1256 if (usbd->recv_data()) {
1257 if (process_data(usbd) == 0)
1265 U_BOOT_CMD(usbdown, CONFIG_SYS_MAXARGS, 1, do_usbd_down,
1266 "Initialize USB device and Run USB Downloader (specific)",
1268 "usbdown mode - specific mode (0: NORAML, 1: FORCE)"