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.3.5"
17 #ifdef CONFIG_CMD_MTDPARTS
18 #include <jffs2/load_kernel.h>
19 static struct part_info *parts[8];
22 static const char pszMe[] = "usbd: ";
24 static struct usbd_ops usbd_ops;
26 static unsigned int part_id = BOOT_PART_ID;
27 static unsigned int write_part = 0;
28 static unsigned long fs_offset = 0x0;
30 #ifdef CONFIG_USE_YAFFS
31 static unsigned int yaffs_len = 0;
32 static unsigned char yaffs_data[2112];
33 #define YAFFS_PAGE 2112
36 #define NAND_PAGE_SIZE 2048
38 static unsigned long down_ram_addr;
40 /* cpu/${CPU} dependent */
41 extern void do_reset(void);
44 extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
45 extern int do_run(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
47 int mtdparts_init(void);
48 int find_dev_and_part(const char*, struct mtd_device**, u8*, struct part_info**);
50 /* common/cmd_jffs2.c */
51 extern struct list_head devices;
53 static u8 count_mtdparts(void)
55 struct list_head *dentry, *pentry;
56 struct mtd_device *dev;
59 list_for_each(dentry, &devices) {
60 dev = list_entry(dentry, struct mtd_device, link);
62 /* list partitions for given device */
63 list_for_each(pentry, &dev->parts)
71 static int check_ubi_mode(void)
76 env_ubifs = getenv("ubi");
77 ubi_mode = !strcmp(env_ubifs, "enabled");
82 #define check_ubi_mode() 0
85 #ifdef CONFIG_MTD_PARTITIONS
86 static int get_part_info(void)
88 struct mtd_device *dev;
96 #if defined(CONFIG_CMD_NAND)
97 sprintf(nand_name, "nand0");
98 #elif defined(CONFIG_CMD_ONENAND)
99 sprintf(nand_name, "onenand0");
101 printf("Configure your NAND sub-system\n");
108 ubi_mode = check_ubi_mode();
110 part_num = count_mtdparts();
111 for (i = 0; i < part_num; i++) {
112 sprintf(part_name, "%s,%d", nand_name, i);
114 if (find_dev_and_part(part_name, &dev, &out_partnum, &parts[i]))
121 static int get_part_id(char *name, int id)
123 int nparts = count_mtdparts();
126 for (i = 0; i < nparts; i++) {
127 if (strcmp(parts[i]->name, name) == 0)
131 printf("Error: Unknown partition -> %s(%d)\n", name, id);
135 static int get_part_info(void)
137 printf("Error: Can't get patition information\n");
141 static int get_part_id(char *name, int id)
147 static void boot_cmd(char *addr)
149 char *argv[] = { "bootm", addr };
150 do_bootm(NULL, 0, 2, argv);
153 static void run_cmd(char *cmd)
155 char *argv[] = { "run", cmd };
156 do_run(NULL, 0, 2, argv);
159 #if defined(CONFIG_CMD_NAND)
160 extern int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
161 #elif defined(CONFIG_CMD_ONENAND)
162 extern int do_onenand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
165 /* NAND erase and write using nand command */
166 static int nand_cmd(int type, char *p1, char *p2, char *p3)
170 int (*nand_func) (cmd_tbl_t *, int, int, char **);
172 #if defined(CONFIG_CMD_NAND)
173 sprintf(nand_name, "nand");
175 #elif defined(CONFIG_CMD_ONENAND)
176 sprintf(nand_name, "onenand");
177 nand_func = do_onenand;
179 printf("Configure your NAND sub-system\n");
184 char *argv[] = {nand_name, "erase", p1, p2};
185 printf("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
186 ret = nand_func(NULL, 0, 4, argv);
187 } else if (type == 1) {
188 char *argv[] = {nand_name, "write", p1, p2, p3};
189 printf("%s %s %s %s %s\n", argv[0], argv[1], argv[2],
191 ret = nand_func(NULL, 0, 5, argv);
192 } else if (type == 2) {
193 char *argv[] = {nand_name, "write.yaffs", 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);
200 printf("Error: NAND Command\n");
205 #ifdef CONFIG_CMD_UBI
206 int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
208 int ubi_cmd(int part, char *p1, char *p2, char *p3)
212 if (part == RAMDISK_PART_ID) {
213 char *argv[] = {"ubi", "write", p1, "rootfs.cramfs", p2, p3};
214 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
215 argv[3], argv[4], argv[5]);
216 ret = do_ubi(NULL, 0, 6, argv);
217 } else if (part == FILESYSTEM_PART_ID) {
218 char *argv[] = {"ubi", "write", p1, "factoryfs.cramfs", p2, p3};
219 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
220 argv[3], argv[4], argv[5]);
221 ret = do_ubi(NULL, 0, 6, argv);
222 } else if (part == FILESYSTEM2_PART_ID) {
223 char *argv[] = {"ubi", "write", p1, "datafs.ubifs", p2, p3};
224 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
225 argv[3], argv[4], argv[5]);
226 ret = do_ubi(NULL, 0, 6, argv);
233 #ifdef CONFIG_CMD_MMC
236 extern int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
238 static int mmc_cmd(char *p1, char *p2, char *p3)
240 char *argv[] = {"mmc", "write", "0", p1, p2, p3};
243 ret = do_mmcops(NULL, 0, 6, argv);
248 static unsigned int org_blk_offset;
249 static unsigned int org_root_blk;
250 static unsigned int org_data_blk;
252 static unsigned int cur_blk_offset;
253 static unsigned int cur_root_blk;
254 static unsigned int cur_data_blk;
256 static int erase_mmc_block(struct usbd_ops *usbd,
257 unsigned int blocks, unsigned int start)
260 char offset[12], length[12], ramaddr[12];
266 loop = blocks / usbd->mmc_max;
267 if (blocks % usbd->mmc_max)
270 data = malloc(usbd->mmc_max);
271 memset(data, 0, usbd->mmc_max);
273 for (i = 0; i < loop; i++) {
275 cnt = blocks % usbd->mmc_max;
282 sprintf(length, "%x", cnt);
283 sprintf(offset, "%x", start);
284 sprintf(ramaddr, "0x%x", (u32)data);
285 ret = mmc_cmd(ramaddr, offset, length);
295 static int write_file_mmc(struct usbd_ops *usbd, char *ramaddr, u32 len,
296 char *offset, char *length)
305 if (cur_blk_offset == 0) {
312 bs = (boot_sector *)down_ram_addr;
314 org_root_blk = bs->fat32_length + bs->reserved;
315 org_data_blk = bs->fat32_length * 2 + bs->reserved;
317 cluster_size = bs->cluster_size;
318 fat32_length = bs->fat32_length;
319 total_sect = bs->total_sect;
321 if (cluster_size != 0x8) {
322 printf("Cluster size must be 0x8\n");
326 bs->total_sect = usbd->mmc_total;
327 bs->fat32_length = usbd->mmc_total / usbd->mmc_blk / 2;
329 cur_root_blk = bs->fat32_length + bs->reserved;
330 cur_data_blk = (bs->fat32_length + 0x10) * 2;
332 /* backup boot block */
333 bs = (boot_sector *)(down_ram_addr +
334 usbd->mmc_blk * bs->backup_boot);
335 bs->total_sect = usbd->mmc_total;
336 bs->fat32_length = usbd->mmc_total / usbd->mmc_blk / 2;
338 /* write reserved blocks */
339 sprintf(length, "%x", bs->reserved);
340 sprintf(offset, "%x", cur_blk_offset);
341 sprintf(ramaddr, "0x%x", (uint)down_ram_addr);
342 ret = mmc_cmd(ramaddr, offset, length);
344 cur_blk_offset = bs->reserved;
346 /* write root blocks */
347 erase_mmc_block(usbd, bs->fat32_length, cur_blk_offset);
348 sprintf(length, "%x", fat32_length);
349 sprintf(offset, "%x", cur_blk_offset);
350 sprintf(ramaddr, "0x%x", (uint)(down_ram_addr +
351 cur_blk_offset * usbd->mmc_blk));
352 ret = mmc_cmd(ramaddr, offset, length);
354 org_blk_offset = org_root_blk;
355 cur_blk_offset = cur_root_blk;
357 erase_mmc_block(usbd, bs->fat32_length, cur_blk_offset);
358 sprintf(length, "%x", fat32_length);
359 sprintf(offset, "%x", cur_blk_offset);
360 sprintf(ramaddr, "0x%x", (uint)(down_ram_addr +
361 org_blk_offset * usbd->mmc_blk));
362 ret = mmc_cmd(ramaddr, offset, length);
364 org_blk_offset = org_data_blk;
365 cur_blk_offset = cur_data_blk;
367 /* write file list */
368 sprintf(length, "%x", cluster_size);
369 sprintf(offset, "%x", cur_blk_offset);
370 sprintf(ramaddr, "0x%x", (uint)(down_ram_addr +
371 org_blk_offset * usbd->mmc_blk));
372 ret = mmc_cmd(ramaddr, offset, length);
374 org_blk_offset += cluster_size;
375 cur_blk_offset += cluster_size;
377 ram_addr = down_ram_addr + org_blk_offset * usbd->mmc_blk;
378 blocks = len / usbd->mmc_blk - org_blk_offset;
380 if (len % usbd->mmc_blk)
383 loop = blocks / usbd->mmc_max;
384 if (blocks % usbd->mmc_max)
387 blocks = len / usbd->mmc_blk;
388 if (len % usbd->mmc_blk)
391 loop = blocks / usbd->mmc_max;
392 if (blocks % usbd->mmc_max)
395 ram_addr = down_ram_addr;
398 for (i = 0; i < loop; i++) {
400 cnt = blocks % usbd->mmc_max;
407 sprintf(length, "%x", cnt);
408 sprintf(offset, "%x", cur_blk_offset);
409 sprintf(ramaddr, "0x%x", ram_addr);
410 ret = mmc_cmd(ramaddr, offset, length);
412 org_blk_offset += cnt;
413 cur_blk_offset += cnt;
415 ram_addr += cnt * usbd->mmc_blk;
422 int write_file_system(char *ramaddr, ulong len, char *offset,
423 char *length, int part_num, int ubi_update)
425 #ifdef CONFIG_USE_YAFFS
431 #ifdef CONFIG_CMD_UBI
434 sprintf(length, "0x%x", (uint)len);
435 ret = ubi_cmd(part_id, ramaddr, length, "cont");
440 /* Erase entire partition at the first writing */
441 if (write_part == 0 && ubi_update == 0) {
442 sprintf(offset, "0x%x", (uint)parts[part_num]->offset);
443 sprintf(length, "0x%x", (uint)parts[part_num]->size);
444 nand_cmd(0, offset, length, NULL);
447 #ifdef CONFIG_USE_YAFFS
448 /* if using yaffs, wirte size must be 2112*X
449 * so, must have to realloc, and writing */
450 if (!strcmp("yaffs", getenv(parts[part_num]->name))) {
453 memcpy((void *)down_ram_addr, yaffs_data, yaffs_len);
455 actual_len = len + yaffs_len;
456 yaffs_len = actual_len % YAFFS_PAGE;
457 len = actual_len - yaffs_len;
459 memset(yaffs_data, 0x00, YAFFS_PAGE);
460 memcpy(yaffs_data, (char *)down_ram_addr + len, yaffs_len);
464 sprintf(offset, "0x%x", (uint)(parts[part_num]->offset + fs_offset));
465 sprintf(length, "0x%x", (uint)len);
467 #ifdef CONFIG_USE_YAFFS
469 ret = nand_cmd(2, ramaddr, offset, length);
471 ret = nand_cmd(1, ramaddr, offset, length);
473 if (!strcmp("yaffs", getenv(parts[part_num]->name)))
474 fs_offset += len / YAFFS_PAGE * NAND_PAGE_SIZE;
480 ret = nand_cmd(1, ramaddr, offset, length);
486 /* Parsing received data packet and Process data */
487 static int process_data(struct usbd_ops *usbd)
489 ulong cmd = 0, arg = 0, len = 0, flag = 0;
490 char offset[12], length[12], ramaddr[12];
492 unsigned int blocks = 0;
497 sprintf(ramaddr, "0x%x", (uint) down_ram_addr);
500 cmd = *((ulong *) usbd->rx_data + 0);
501 arg = *((ulong *) usbd->rx_data + 1);
502 len = *((ulong *) usbd->rx_data + 2);
503 flag = *((ulong *) usbd->rx_data + 3);
505 /* Reset tx buffer */
506 memset(usbd->tx_data, 0, sizeof(usbd->tx_data));
508 ubi_mode = check_ubi_mode();
511 case COMMAND_DOWNLOAD_IMAGE:
512 printf("\nCOMMAND_DOWNLOAD_IMAGE\n");
514 #ifdef CONFIG_USE_YAFFS
515 usbd->recv_setup((char *)down_ram_addr + yaffs_len, (int)len);
516 printf("Download to 0x%08x, %d bytes\n",
517 (uint)down_ram_addr + yaffs_len, (int)len);
519 usbd->recv_setup((char *)down_ram_addr, (int)len);
520 printf("Download to 0x%08x, %d bytes\n",
521 (uint)down_ram_addr, (int)len);
524 usbd->send_data(usbd->tx_data, usbd->tx_len);
526 /* Receive image by using dma */
527 recvlen = usbd->recv_data();
529 printf("Error: wrong image size -> %d/%d\n",
530 (int)recvlen, (int)len);
532 /* Retry this commad */
533 *((ulong *) usbd->tx_data) = STATUS_RETRY;
535 *((ulong *) usbd->tx_data) = STATUS_DONE;
537 usbd->send_data(usbd->tx_data, usbd->tx_len);
540 /* Report partition info */
541 case COMMAND_PARTITION_SYNC:
544 #ifdef CONFIG_CMD_UBI
546 if (part_id == RAMDISK_PART_ID ||
547 part_id == FILESYSTEM_PART_ID ||
548 part_id == FILESYSTEM2_PART_ID) {
549 /* change to yaffs style */
553 if (part_id == FILESYSTEM3_PART_ID) {
554 /* change ubi style */
560 if (part_id == FILESYSTEM3_PART_ID)
561 part_id = get_part_id("UBI", FILESYSTEM_PART_ID);
562 else if (part_id == MODEM_PART_ID)
563 part_id = get_part_id("modem", MODEM_PART_ID);
568 printf("COMMAND_PARTITION_SYNC - Part%d\n", part_id);
570 blocks = parts[part_id]->size / 1024 / 128;
571 printf("COMMAND_PARTITION_SYNC - Part%d, %d blocks\n",
574 *((ulong *) usbd->tx_data) = blocks;
575 usbd->send_data(usbd->tx_data, usbd->tx_len);
578 case COMMAND_WRITE_PART_0:
580 printf("COMMAND_WRITE_PART_0\n");
583 case COMMAND_WRITE_PART_1:
584 printf("COMMAND_WRITE_PART_BOOT\n");
585 part_id = get_part_id("bootloader", BOOT_PART_ID);
588 case COMMAND_WRITE_PART_2:
589 case COMMAND_ERASE_PARAMETER:
590 printf("COMMAND_PARAMETER - not support!\n");
593 case COMMAND_WRITE_PART_3:
594 printf("COMMAND_WRITE_KERNEL\n");
595 part_id = get_part_id("kernel", KERNEL_PART_ID);
598 case COMMAND_WRITE_PART_4:
599 printf("COMMAND_WRITE_ROOTFS\n");
600 part_id = get_part_id("Root", RAMDISK_PART_ID);
604 case COMMAND_WRITE_PART_5:
605 printf("COMMAND_WRITE_FACTORYFS\n");
606 part_id = get_part_id("Fact", FILESYSTEM_PART_ID);
610 case COMMAND_WRITE_PART_6:
611 printf("COMMAND_WRITE_DATAFS\n");
612 part_id = get_part_id("Data", FILESYSTEM2_PART_ID);
616 case COMMAND_WRITE_PART_7:
617 printf("COMMAND_WRITE_UBI\n");
618 part_id = get_part_id("UBI", FILESYSTEM3_PART_ID);
620 /* someday, it will be deleted */
624 case COMMAND_WRITE_PART_8:
625 printf("COMMAND_WRITE_MODEM\n");
626 part_id = MODEM_PART_ID;
629 case COMMAND_WRITE_PART_9:
630 printf("COMMAND_WRITE_MMC\n");
631 part_id = MMC_PART_ID;
634 case COMMAND_WRITE_UBI_INFO:
635 printf("COMMAND_WRITE_UBI_INFO\n");
638 #ifdef CONFIG_CMD_UBI
640 sprintf(length, "0x%x", (uint)len);
641 ret = ubi_cmd(part_id, ramaddr, length, "begin");
644 printf("Error: Not UBI mode\n");
648 *((ulong *) usbd->tx_data) = ret;
649 /* Write image success -> Report status */
650 usbd->send_data(usbd->tx_data, usbd->tx_len);
653 /* Download complete -> reset */
654 case COMMAND_RESET_PDA:
655 printf("\nDownload finished and Auto reset!\nWait........\n");
664 case COMMAND_RESET_USB:
665 printf("\nError is occured!(maybe previous step)->\
666 Turn off and restart!\n");
672 case COMMAND_RAM_BOOT:
677 case COMMAND_RAMDISK_MODE:
678 printf("COMMAND_RAMDISK_MODE\n");
679 #ifdef CONFIG_RAMDISK_ADDR
681 down_ram_addr = usbd->ram_addr;
683 down_ram_addr = CONFIG_RAMDISK_ADDR;
689 #ifdef CONFIG_DOWN_PHONE
690 case COMMAND_DOWN_PHONE:
691 printf("COMMAND_RESET_PHONE\n");
695 *((ulong *) usbd->tx_data) = STATUS_DONE;
696 usbd->send_data(usbd->tx_data, usbd->tx_len);
699 case COMMAND_CHANGE_USB:
700 printf("COMMAND_CHANGE_USB\n");
710 case COMMAND_PROGRESS:
711 if (usbd->set_progress)
712 usbd->set_progress(arg);
716 printf("Error: Unknown command -> (%d)\n", (int)cmd);
720 /* Erase and Write to NAND */
723 #ifdef CONFIG_S5PC1XX
724 /* Workaround: for prevent revision mismatch */
725 if (cpu_is_s5pc110()) {
727 long *img_header = (long *)down_ram_addr;
729 if (*img_header == 0xea000012)
732 if (img_rev != s5pc1xx_get_cpu_rev()) {
733 printf("CPU revision mismatch!\n");
734 *((ulong *) usbd->tx_data) = STATUS_ERROR;
735 usbd->send_data(usbd->tx_data, usbd->tx_len);
740 #if defined(CONFIG_ENV_IS_IN_NAND) || defined(CONFIG_ENV_IS_IN_ONENAND)
741 /* Erase the environment also when write bootloader */
744 param_id = get_part_id("params", 1);
746 if (param_id == -1) {
747 sprintf(offset, "%x", CONFIG_ENV_OFFSET);
748 sprintf(length, "%x", CONFIG_ENV_SIZE);
750 sprintf(offset, "%x", parts[param_id]->offset);
751 sprintf(length, "%x", parts[param_id]->size);
753 nand_cmd(0, offset, length, NULL);
756 /* Fall through for write bootloader */
758 sprintf(offset, "%x", parts[part_id]->offset);
759 sprintf(length, "%x", parts[part_id]->size);
762 nand_cmd(0, offset, length, NULL);
764 sprintf(length, "%x", (unsigned int) len);
765 ret = nand_cmd(1, ramaddr, offset, length);
769 case RAMDISK_PART_ID: /* rootfs */
770 case FILESYSTEM_PART_ID: /* factoryfs */
771 case FILESYSTEM2_PART_ID: /* datafs */
772 case FILESYSTEM3_PART_ID: /* ubifs */
773 ret = write_file_system(ramaddr, len, offset, length,
774 part_id, ubi_update);
778 part_id = get_part_id("modem", MODEM_PART_ID);
780 sprintf(offset, "%x", parts[part_id]->offset);
781 sprintf(length, "%x", parts[part_id]->size);
784 nand_cmd(0, offset, length, NULL);
786 sprintf(length, "%x", (unsigned int) len);
787 ret = nand_cmd(1, ramaddr, offset, length);
790 #ifdef CONFIG_CMD_MMC
792 write_file_mmc(usbd, ramaddr, len, offset, length);
802 /* Retry this commad */
803 *((ulong *) usbd->tx_data) = STATUS_RETRY;
804 usbd->send_data(usbd->tx_data, usbd->tx_len);
807 *((ulong *) usbd->tx_data) = STATUS_DONE;
809 /* Write image success -> Report status */
810 usbd->send_data(usbd->tx_data, usbd->tx_len);
814 /* Reset write count for another image */
818 #ifdef CONFIG_USE_YAFFS
826 static const char *recv_key = "SAMSUNG";
827 static const char *tx_key = "MPL";
829 int do_usbd_down(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
831 struct usbd_ops *usbd;
834 printf("USB Downloader v%s\n", APP_VERSION);
836 /* get partition info */
837 err = get_part_info();
841 /* interface setting */
842 usbd = usbd_set_interface(&usbd_ops);
843 down_ram_addr = usbd->ram_addr;
845 /* init the usb controller */
848 /* receive setting */
849 usbd->recv_setup(usbd->rx_data, usbd->rx_len);
851 /* detect the download request from Host PC */
852 if (usbd->recv_data()) {
853 if (strncmp(usbd->rx_data, recv_key, strlen(recv_key)) == 0) {
854 printf("Download request from the Host PC\n");
857 strcpy(usbd->tx_data, tx_key);
858 usbd->send_data(usbd->tx_data, usbd->tx_len);
860 printf("No download request from the Host PC!! 1\n");
864 printf("No download request from the Host PC!!\n");
868 printf("Receive the packet\n");
870 /* receive the data from Host PC */
872 usbd->recv_setup(usbd->rx_data, usbd->rx_len);
874 if (usbd->recv_data()) {
875 if (process_data(usbd) == 0)
883 U_BOOT_CMD(usbdown, 3, 0, do_usbd_down,
884 "initialize USB device and ready to receive"
885 " for Windows server (specific)\n",
886 "[download address]\n"