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.4.0"
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;
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;
42 /* cpu/${CPU} dependent */
43 extern void do_reset(void);
46 extern int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
47 extern int do_run(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
49 int mtdparts_init(void);
50 int find_dev_and_part(const char*, struct mtd_device**, u8*, struct part_info**);
52 /* common/cmd_jffs2.c */
53 extern struct list_head devices;
55 static u8 count_mtdparts(void)
57 struct list_head *dentry, *pentry;
58 struct mtd_device *dev;
61 list_for_each(dentry, &devices) {
62 dev = list_entry(dentry, struct mtd_device, link);
64 /* list partitions for given device */
65 list_for_each(pentry, &dev->parts)
73 static int check_ubi_mode(void)
78 env_ubifs = getenv("ubi");
79 ubi_mode = !strcmp(env_ubifs, "enabled");
84 #define check_ubi_mode() 0
87 #ifdef CONFIG_MTD_PARTITIONS
88 static int get_part_info(void)
90 struct mtd_device *dev;
98 #if defined(CONFIG_CMD_NAND)
99 sprintf(nand_name, "nand0");
100 #elif defined(CONFIG_CMD_ONENAND)
101 sprintf(nand_name, "onenand0");
103 printf("Configure your NAND sub-system\n");
110 ubi_mode = check_ubi_mode();
112 part_num = count_mtdparts();
113 for (i = 0; i < part_num; i++) {
114 sprintf(part_name, "%s,%d", nand_name, i);
116 if (find_dev_and_part(part_name, &dev, &out_partnum, &parts[i]))
123 static int get_part_id(char *name)
125 int nparts = count_mtdparts();
128 for (i = 0; i < nparts; i++) {
129 if (strcmp(parts[i]->name, name) == 0)
133 printf("Error: Unknown partition -> %s\n", name);
137 static int get_part_info(void)
139 printf("Error: Can't get patition information\n");
143 static int get_part_id(char *name)
149 static void boot_cmd(char *addr)
151 char *argv[] = { "bootm", addr };
152 do_bootm(NULL, 0, 2, argv);
155 static void run_cmd(char *cmd)
157 char *argv[] = { "run", cmd };
158 do_run(NULL, 0, 2, argv);
161 #if defined(CONFIG_CMD_NAND)
162 extern int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
163 #elif defined(CONFIG_CMD_ONENAND)
164 extern int do_onenand(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
167 /* NAND erase and write using nand command */
168 static int nand_cmd(int type, char *p1, char *p2, char *p3)
172 int (*nand_func) (cmd_tbl_t *, int, int, char **);
174 #if defined(CONFIG_CMD_NAND)
175 sprintf(nand_name, "nand");
177 #elif defined(CONFIG_CMD_ONENAND)
178 sprintf(nand_name, "onenand");
179 nand_func = do_onenand;
181 printf("Configure your NAND sub-system\n");
186 char *argv[] = {nand_name, "erase", p1, p2};
187 printf("%s %s %s %s\n", argv[0], argv[1], argv[2], argv[3]);
188 ret = nand_func(NULL, 0, 4, argv);
189 } else if (type == 1) {
190 char *argv[] = {nand_name, "write", p1, p2, p3};
191 printf("%s %s %s %s %s\n", argv[0], argv[1], argv[2],
193 ret = nand_func(NULL, 0, 5, argv);
194 } else if (type == 2) {
195 char *argv[] = {nand_name, "write.yaffs", p1, p2, p3};
196 printf("%s %s %s %s %s\n", argv[0], argv[1], argv[2],
198 ret = nand_func(NULL, 0, 5, argv);
202 printf("Error: NAND Command\n");
207 #ifdef CONFIG_CMD_UBI
208 int do_ubi(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
210 int ubi_cmd(int part, char *p1, char *p2, char *p3)
214 if (part == RAMDISK_PART_ID) {
215 char *argv[] = {"ubi", "write", p1, "rootfs.cramfs", p2, p3};
216 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
217 argv[3], argv[4], argv[5]);
218 ret = do_ubi(NULL, 0, 6, argv);
219 } else if (part == FILESYSTEM_PART_ID) {
220 char *argv[] = {"ubi", "write", p1, "factoryfs.cramfs", p2, p3};
221 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
222 argv[3], argv[4], argv[5]);
223 ret = do_ubi(NULL, 0, 6, argv);
224 } else if (part == FILESYSTEM2_PART_ID) {
225 char *argv[] = {"ubi", "write", p1, "datafs.ubifs", p2, p3};
226 printf("%s %s %s %s %s %s\n", argv[0], argv[1], argv[2],
227 argv[3], argv[4], argv[5]);
228 ret = do_ubi(NULL, 0, 6, argv);
235 #ifdef CONFIG_CMD_MMC
238 extern int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
240 static int mmc_cmd(char *p1, char *p2, char *p3)
242 char *argv[] = {"mmc", "write", "0", p1, p2, p3};
245 ret = do_mmcops(NULL, 0, 6, argv);
250 static unsigned int org_blk_offset;
251 static unsigned int org_root_blk;
252 static unsigned int org_data_blk;
254 static unsigned int cur_blk_offset;
255 static unsigned int cur_root_blk;
256 static unsigned int cur_data_blk;
258 static int erase_mmc_block(struct usbd_ops *usbd,
259 unsigned int blocks, unsigned int start)
262 char offset[12], length[12], ramaddr[12];
268 loop = blocks / usbd->mmc_max;
269 if (blocks % usbd->mmc_max)
272 data = malloc(usbd->mmc_max);
273 memset(data, 0, usbd->mmc_max);
275 for (i = 0; i < loop; i++) {
277 cnt = blocks % usbd->mmc_max;
284 sprintf(length, "%x", cnt);
285 sprintf(offset, "%x", start);
286 sprintf(ramaddr, "0x%x", (u32)data);
287 ret = mmc_cmd(ramaddr, offset, length);
297 static int write_file_mmc(struct usbd_ops *usbd, char *ramaddr, u32 len,
298 char *offset, char *length)
307 if (cur_blk_offset == 0) {
314 bs = (boot_sector *)down_ram_addr;
316 org_root_blk = bs->fat32_length + bs->reserved;
317 org_data_blk = bs->fat32_length * 2 + bs->reserved;
319 cluster_size = bs->cluster_size;
320 fat32_length = bs->fat32_length;
321 total_sect = bs->total_sect;
323 if (cluster_size != 0x8) {
324 printf("Cluster size must be 0x8\n");
328 bs->total_sect = usbd->mmc_total;
329 bs->fat32_length = usbd->mmc_total / usbd->mmc_blk / 2;
331 cur_root_blk = bs->fat32_length + bs->reserved;
332 cur_data_blk = (bs->fat32_length + 0x10) * 2;
334 /* backup boot block */
335 bs = (boot_sector *)(down_ram_addr +
336 usbd->mmc_blk * bs->backup_boot);
337 bs->total_sect = usbd->mmc_total;
338 bs->fat32_length = usbd->mmc_total / usbd->mmc_blk / 2;
340 /* write reserved blocks */
341 sprintf(length, "%x", bs->reserved);
342 sprintf(offset, "%x", cur_blk_offset);
343 sprintf(ramaddr, "0x%x", (uint)down_ram_addr);
344 ret = mmc_cmd(ramaddr, offset, length);
346 cur_blk_offset = bs->reserved;
348 /* write root blocks */
349 erase_mmc_block(usbd, bs->fat32_length, cur_blk_offset);
350 sprintf(length, "%x", fat32_length);
351 sprintf(offset, "%x", cur_blk_offset);
352 sprintf(ramaddr, "0x%x", (uint)(down_ram_addr +
353 cur_blk_offset * usbd->mmc_blk));
354 ret = mmc_cmd(ramaddr, offset, length);
356 org_blk_offset = org_root_blk;
357 cur_blk_offset = cur_root_blk;
359 erase_mmc_block(usbd, bs->fat32_length, cur_blk_offset);
360 sprintf(length, "%x", fat32_length);
361 sprintf(offset, "%x", cur_blk_offset);
362 sprintf(ramaddr, "0x%x", (uint)(down_ram_addr +
363 org_blk_offset * usbd->mmc_blk));
364 ret = mmc_cmd(ramaddr, offset, length);
366 org_blk_offset = org_data_blk;
367 cur_blk_offset = cur_data_blk;
369 /* write file list */
370 sprintf(length, "%x", cluster_size);
371 sprintf(offset, "%x", cur_blk_offset);
372 sprintf(ramaddr, "0x%x", (uint)(down_ram_addr +
373 org_blk_offset * usbd->mmc_blk));
374 ret = mmc_cmd(ramaddr, offset, length);
376 org_blk_offset += cluster_size;
377 cur_blk_offset += cluster_size;
379 ram_addr = down_ram_addr + org_blk_offset * usbd->mmc_blk;
380 blocks = len / usbd->mmc_blk - org_blk_offset;
382 if (len % usbd->mmc_blk)
385 loop = blocks / usbd->mmc_max;
386 if (blocks % usbd->mmc_max)
389 blocks = len / usbd->mmc_blk;
390 if (len % usbd->mmc_blk)
393 loop = blocks / usbd->mmc_max;
394 if (blocks % usbd->mmc_max)
397 ram_addr = down_ram_addr;
400 for (i = 0; i < loop; i++) {
402 cnt = blocks % usbd->mmc_max;
409 sprintf(length, "%x", cnt);
410 sprintf(offset, "%x", cur_blk_offset);
411 sprintf(ramaddr, "0x%x", ram_addr);
412 ret = mmc_cmd(ramaddr, offset, length);
414 org_blk_offset += cnt;
415 cur_blk_offset += cnt;
417 ram_addr += cnt * usbd->mmc_blk;
424 int write_file_system(char *ramaddr, ulong len, char *offset,
425 char *length, int part_num, int ubi_update)
427 #ifdef CONFIG_USE_YAFFS
433 #ifdef CONFIG_CMD_UBI
436 sprintf(length, "0x%x", (uint)len);
437 ret = ubi_cmd(part_id, ramaddr, length, "cont");
442 /* Erase entire partition at the first writing */
443 if (write_part == 0 && ubi_update == 0) {
444 sprintf(offset, "0x%x", (uint)parts[part_num]->offset);
445 sprintf(length, "0x%x", (uint)parts[part_num]->size);
446 nand_cmd(0, offset, length, NULL);
449 #ifdef CONFIG_USE_YAFFS
450 /* if using yaffs, wirte size must be 2112*X
451 * so, must have to realloc, and writing */
452 if (!strcmp("yaffs", getenv(parts[part_num]->name))) {
455 memcpy((void *)down_ram_addr, yaffs_data, yaffs_len);
457 actual_len = len + yaffs_len;
458 yaffs_len = actual_len % YAFFS_PAGE;
459 len = actual_len - yaffs_len;
461 memset(yaffs_data, 0x00, YAFFS_PAGE);
462 memcpy(yaffs_data, (char *)down_ram_addr + len, yaffs_len);
466 sprintf(offset, "0x%x", (uint)(parts[part_num]->offset + fs_offset));
467 sprintf(length, "0x%x", (uint)len);
469 #ifdef CONFIG_USE_YAFFS
471 ret = nand_cmd(2, ramaddr, offset, length);
473 ret = nand_cmd(1, ramaddr, offset, length);
475 if (!strcmp("yaffs", getenv(parts[part_num]->name)))
476 fs_offset += len / YAFFS_PAGE * NAND_PAGE_SIZE;
482 ret = nand_cmd(1, ramaddr, offset, length);
488 /* Parsing received data packet and Process data */
489 static int process_data(struct usbd_ops *usbd)
491 ulong cmd = 0, arg = 0, len = 0, flag = 0;
492 char offset[12], length[12], ramaddr[12];
494 unsigned int blocks = 0;
500 sprintf(ramaddr, "0x%x", (uint) down_ram_addr);
503 cmd = *((ulong *) usbd->rx_data + 0);
504 arg = *((ulong *) usbd->rx_data + 1);
505 len = *((ulong *) usbd->rx_data + 2);
506 flag = *((ulong *) usbd->rx_data + 3);
508 /* Reset tx buffer */
509 memset(usbd->tx_data, 0, sizeof(usbd->tx_data));
511 ubi_mode = check_ubi_mode();
514 case COMMAND_DOWNLOAD_IMAGE:
515 printf("\nCOMMAND_DOWNLOAD_IMAGE\n");
517 #ifdef CONFIG_USE_YAFFS
518 usbd->recv_setup((char *)down_ram_addr + yaffs_len, (int)len);
519 printf("Download to 0x%08x, %d bytes\n",
520 (uint)down_ram_addr + yaffs_len, (int)len);
522 usbd->recv_setup((char *)down_ram_addr, (int)len);
523 printf("Download to 0x%08x, %d bytes\n",
524 (uint)down_ram_addr, (int)len);
527 usbd->send_data(usbd->tx_data, usbd->tx_len);
529 /* Receive image by using dma */
530 recvlen = usbd->recv_data();
532 printf("Error: wrong image size -> %d/%d\n",
533 (int)recvlen, (int)len);
535 /* Retry this commad */
536 *((ulong *) usbd->tx_data) = STATUS_RETRY;
538 *((ulong *) usbd->tx_data) = STATUS_DONE;
540 usbd->send_data(usbd->tx_data, usbd->tx_len);
543 /* Report partition info */
544 case COMMAND_PARTITION_SYNC:
547 #ifdef CONFIG_CMD_UBI
549 if (part_id == RAMDISK_PART_ID ||
550 part_id == FILESYSTEM_PART_ID ||
551 part_id == FILESYSTEM2_PART_ID) {
552 /* change to yaffs style */
556 if (part_id == FILESYSTEM3_PART_ID) {
557 /* change ubi style */
563 if (part_id == FILESYSTEM3_PART_ID)
564 part_id = get_part_id("UBI");
565 else if (part_id == MODEM_PART_ID)
566 part_id = get_part_id("modem");
571 printf("COMMAND_PARTITION_SYNC - Part%d\n", part_id);
573 blocks = parts[part_id]->size / 1024 / 128;
574 printf("COMMAND_PARTITION_SYNC - Part%d, %d blocks\n",
577 *((ulong *) usbd->tx_data) = blocks;
578 usbd->send_data(usbd->tx_data, usbd->tx_len);
581 case COMMAND_WRITE_PART_0:
583 printf("COMMAND_WRITE_PART_0\n");
586 case COMMAND_WRITE_PART_1:
587 printf("COMMAND_WRITE_PART_BOOT\n");
588 part_id = get_part_id("bootloader");
592 case COMMAND_WRITE_PART_2:
593 case COMMAND_ERASE_PARAMETER:
594 printf("COMMAND_PARAMETER - not support!\n");
597 case COMMAND_WRITE_PART_3:
598 printf("COMMAND_WRITE_KERNEL\n");
599 part_id = get_part_id("kernel");
600 img_type = IMG_KERNEL;
603 case COMMAND_WRITE_PART_4:
604 printf("COMMAND_WRITE_ROOTFS\n");
605 part_id = get_part_id("Root");
606 img_type = IMG_FILESYSTEM;
610 case COMMAND_WRITE_PART_5:
611 printf("COMMAND_WRITE_FACTORYFS\n");
612 part_id = get_part_id("Fact");
613 img_type = IMG_FILESYSTEM;
617 case COMMAND_WRITE_PART_6:
618 printf("COMMAND_WRITE_DATAFS\n");
619 part_id = get_part_id("Data");
620 img_type = IMG_FILESYSTEM;
624 case COMMAND_WRITE_PART_7:
625 printf("COMMAND_WRITE_UBI\n");
626 part_id = get_part_id("UBI");
627 img_type = IMG_FILESYSTEM;
629 /* someday, it will be deleted */
633 case COMMAND_WRITE_PART_8:
634 printf("COMMAND_WRITE_MODEM\n");
635 part_id = get_part_id("modem");
636 img_type = IMG_MODEM;
639 case COMMAND_WRITE_PART_9:
640 printf("COMMAND_WRITE_MMC\n");
644 case COMMAND_WRITE_UBI_INFO:
645 printf("COMMAND_WRITE_UBI_INFO\n");
648 #ifdef CONFIG_CMD_UBI
650 sprintf(length, "0x%x", (uint)len);
651 ret = ubi_cmd(part_id, ramaddr, length, "begin");
654 printf("Error: Not UBI mode\n");
658 *((ulong *) usbd->tx_data) = ret;
659 /* Write image success -> Report status */
660 usbd->send_data(usbd->tx_data, usbd->tx_len);
663 /* Download complete -> reset */
664 case COMMAND_RESET_PDA:
665 printf("\nDownload finished and Auto reset!\nWait........\n");
674 case COMMAND_RESET_USB:
675 printf("\nError is occured!(maybe previous step)->\
676 Turn off and restart!\n");
682 case COMMAND_RAM_BOOT:
687 case COMMAND_RAMDISK_MODE:
688 printf("COMMAND_RAMDISK_MODE\n");
689 #ifdef CONFIG_RAMDISK_ADDR
691 down_ram_addr = usbd->ram_addr;
693 down_ram_addr = CONFIG_RAMDISK_ADDR;
699 #ifdef CONFIG_DOWN_PHONE
700 case COMMAND_DOWN_PHONE:
701 printf("COMMAND_RESET_PHONE\n");
705 *((ulong *) usbd->tx_data) = STATUS_DONE;
706 usbd->send_data(usbd->tx_data, usbd->tx_len);
709 case COMMAND_CHANGE_USB:
710 printf("COMMAND_CHANGE_USB\n");
720 case COMMAND_PROGRESS:
721 if (usbd->set_progress)
722 usbd->set_progress(arg);
726 printf("Error: Unknown command -> (%d)\n", (int)cmd);
730 /* Erase and Write to NAND */
733 #ifdef CONFIG_S5PC1XX
734 /* Workaround: for prevent revision mismatch */
735 if (cpu_is_s5pc110() && (down_mode != MODE_FORCE)) {
737 long *img_header = (long *)down_ram_addr;
739 if (*img_header == 0xea000012)
742 if (img_rev != s5pc1xx_get_cpu_rev()) {
743 printf("CPU revision mismatch!\n");
744 *((ulong *) usbd->tx_data) = STATUS_ERROR;
745 usbd->send_data(usbd->tx_data, usbd->tx_len);
750 #if defined(CONFIG_ENV_IS_IN_NAND) || defined(CONFIG_ENV_IS_IN_ONENAND)
751 /* Erase the environment also when write bootloader */
754 param_id = get_part_id("params");
756 if (param_id == -1) {
757 sprintf(offset, "%x", CONFIG_ENV_OFFSET);
758 sprintf(length, "%x", CONFIG_ENV_SIZE);
760 sprintf(offset, "%x", parts[param_id]->offset);
761 sprintf(length, "%x", parts[param_id]->size);
763 nand_cmd(0, offset, length, NULL);
766 /* Fall through for write bootloader */
768 sprintf(offset, "%x", parts[part_id]->offset);
769 sprintf(length, "%x", parts[part_id]->size);
772 nand_cmd(0, offset, length, NULL);
774 sprintf(length, "%x", (unsigned int) len);
775 ret = nand_cmd(1, ramaddr, offset, length);
780 ret = write_file_system(ramaddr, len, offset, length,
781 part_id, ubi_update);
785 sprintf(offset, "%x", parts[part_id]->offset);
786 sprintf(length, "%x", parts[part_id]->size);
789 nand_cmd(0, offset, length, NULL);
791 sprintf(length, "%x", (unsigned int) len);
792 ret = nand_cmd(1, ramaddr, offset, length);
795 #ifdef CONFIG_CMD_MMC
797 write_file_mmc(usbd, ramaddr, len, offset, length);
807 /* Retry this commad */
808 *((ulong *) usbd->tx_data) = STATUS_RETRY;
809 usbd->send_data(usbd->tx_data, usbd->tx_len);
812 *((ulong *) usbd->tx_data) = STATUS_DONE;
814 /* Write image success -> Report status */
815 usbd->send_data(usbd->tx_data, usbd->tx_len);
819 /* Reset write count for another image */
823 #ifdef CONFIG_USE_YAFFS
831 static const char *recv_key = "SAMSUNG";
832 static const char *tx_key = "MPL";
834 int do_usbd_down(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
836 struct usbd_ops *usbd;
840 down_mode = simple_strtoul(argv[1], NULL, 10);
842 down_mode = MODE_NORMAL;
844 printf("USB Downloader v%s (%d)\n", APP_VERSION, down_mode);
846 /* get partition info */
847 err = get_part_info();
851 /* interface setting */
852 usbd = usbd_set_interface(&usbd_ops);
853 down_ram_addr = usbd->ram_addr;
855 /* init the usb controller */
858 /* receive setting */
859 usbd->recv_setup(usbd->rx_data, usbd->rx_len);
861 /* detect the download request from Host PC */
862 if (usbd->recv_data()) {
863 if (strncmp(usbd->rx_data, recv_key, strlen(recv_key)) == 0) {
864 printf("Download request from the Host PC\n");
867 strcpy(usbd->tx_data, tx_key);
868 usbd->send_data(usbd->tx_data, usbd->tx_len);
870 printf("No download request from the Host PC!! 1\n");
874 printf("No download request from the Host PC!!\n");
878 printf("Receive the packet\n");
880 /* receive the data from Host PC */
882 usbd->recv_setup(usbd->rx_data, usbd->rx_len);
884 if (usbd->recv_data()) {
885 if (process_data(usbd) == 0)
893 U_BOOT_CMD(usbdown, CONFIG_SYS_MAXARGS, 1, do_usbd_down,
894 "Initialize USB device and Run USB Downloader (specific)",
896 "usbdown mode - specific mode (0: NORAML, 1: FORCE)\n"