1 /* 2 * cmd_dfu.c -- dfu command 3 * 4 * Copyright (C) 2015 5 * Lukasz Majewski <l.majewski@majess.pl> 6 * 7 * Copyright (C) 2012 Samsung Electronics 8 * authors: Andrzej Pietrasiewicz <andrzej.p@samsung.com> 9 * Lukasz Majewski <l.majewski@samsung.com> 10 * 11 * SPDX-License-Identifier: GPL-2.0+ 12 */ 13 14 #include <common.h> 15 #include <watchdog.h> 16 #include <dfu.h> 17 #include <console.h> 18 #include <g_dnl.h> 19 #include <usb.h> 20 #include <net.h> 21 22 static int do_dfu(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) 23 { 24 bool dfu_reset = false; 25 26 if (argc < 4) 27 return CMD_RET_USAGE; 28 29 char *usb_controller = argv[1]; 30 char *interface = argv[2]; 31 char *devstring = argv[3]; 32 33 int ret, i = 0; 34 #ifdef CONFIG_DFU_TFTP 35 unsigned long addr = 0; 36 if (!strcmp(argv[1], "tftp")) { 37 if (argc == 5) 38 addr = simple_strtoul(argv[4], NULL, 0); 39 40 return update_tftp(addr, interface, devstring); 41 } 42 #endif 43 44 ret = dfu_init_env_entities(interface, devstring); 45 if (ret) 46 goto done; 47 48 ret = CMD_RET_SUCCESS; 49 if (argc > 4 && strcmp(argv[4], "list") == 0) { 50 dfu_show_entities(); 51 goto done; 52 } 53 54 int controller_index = simple_strtoul(usb_controller, NULL, 0); 55 board_usb_init(controller_index, USB_INIT_DEVICE); 56 g_dnl_clear_detach(); 57 g_dnl_register("usb_dnl_dfu"); 58 while (1) { 59 if (g_dnl_detach()) { 60 /* 61 * Check if USB bus reset is performed after detach, 62 * which indicates that -R switch has been passed to 63 * dfu-util. In this case reboot the device 64 */ 65 if (dfu_usb_get_reset()) { 66 dfu_reset = true; 67 goto exit; 68 } 69 70 /* 71 * This extra number of usb_gadget_handle_interrupts() 72 * calls is necessary to assure correct transmission 73 * completion with dfu-util 74 */ 75 if (++i == 10000) 76 goto exit; 77 } 78 79 if (ctrlc()) 80 goto exit; 81 82 if (dfu_get_defer_flush()) { 83 /* 84 * Call to usb_gadget_handle_interrupts() is necessary 85 * to act on ZLP OUT transaction from HOST PC after 86 * transmitting the whole file. 87 * 88 * If this ZLP OUT packet is NAK'ed, the HOST libusb 89 * function fails after timeout (by default it is set to 90 * 5 seconds). In such situation the dfu-util program 91 * exits with error message. 92 */ 93 usb_gadget_handle_interrupts(controller_index); 94 ret = dfu_flush(dfu_get_defer_flush(), NULL, 0, 0); 95 dfu_set_defer_flush(NULL); 96 if (ret) { 97 error("Deferred dfu_flush() failed!"); 98 goto exit; 99 } 100 } 101 102 WATCHDOG_RESET(); 103 usb_gadget_handle_interrupts(controller_index); 104 } 105 exit: 106 g_dnl_unregister(); 107 board_usb_cleanup(controller_index, USB_INIT_DEVICE); 108 done: 109 dfu_free_entities(); 110 111 if (dfu_reset) 112 run_command("reset", 0); 113 114 g_dnl_clear_detach(); 115 116 return ret; 117 } 118 119 U_BOOT_CMD(dfu, CONFIG_SYS_MAXARGS, 1, do_dfu, 120 "Device Firmware Upgrade", 121 "<USB_controller> <interface> <dev> [list]\n" 122 " - device firmware upgrade via <USB_controller>\n" 123 " on device <dev>, attached to interface\n" 124 " <interface>\n" 125 " [list] - list available alt settings\n" 126 #ifdef CONFIG_DFU_TFTP 127 "dfu tftp <interface> <dev> [<addr>]\n" 128 " - device firmware upgrade via TFTP\n" 129 " on device <dev>, attached to interface\n" 130 " <interface>\n" 131 " [<addr>] - address where FIT image has been stored\n" 132 #endif 133 ); 134