1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright 2008 - 2009 Windriver, <www.windriver.com> 4 * Author: Tom Rix <Tom.Rix@windriver.com> 5 * 6 * (C) Copyright 2014 Linaro, Ltd. 7 * Rob Herring <robh@kernel.org> 8 */ 9 #include <common.h> 10 #include <command.h> 11 #include <console.h> 12 #include <g_dnl.h> 13 #include <fastboot.h> 14 #include <net.h> 15 #include <usb.h> 16 #include <watchdog.h> 17 18 static int do_fastboot_udp(int argc, char *const argv[], 19 uintptr_t buf_addr, size_t buf_size) 20 { 21 #if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT) 22 int err = net_loop(FASTBOOT); 23 24 if (err < 0) { 25 printf("fastboot udp error: %d\n", err); 26 return CMD_RET_FAILURE; 27 } 28 29 return CMD_RET_SUCCESS; 30 #else 31 pr_err("Fastboot UDP not enabled\n"); 32 return CMD_RET_FAILURE; 33 #endif 34 } 35 36 static int do_fastboot_usb(int argc, char *const argv[], 37 uintptr_t buf_addr, size_t buf_size) 38 { 39 #if CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT) 40 int controller_index; 41 char *usb_controller; 42 char *endp; 43 int ret; 44 45 if (argc < 2) 46 return CMD_RET_USAGE; 47 48 usb_controller = argv[1]; 49 controller_index = simple_strtoul(usb_controller, &endp, 0); 50 if (*endp != '\0') { 51 pr_err("Error: Wrong USB controller index format\n"); 52 return CMD_RET_FAILURE; 53 } 54 55 ret = usb_gadget_initialize(controller_index); 56 if (ret) { 57 pr_err("USB init failed: %d\n", ret); 58 return CMD_RET_FAILURE; 59 } 60 61 g_dnl_clear_detach(); 62 ret = g_dnl_register("usb_dnl_fastboot"); 63 if (ret) 64 return ret; 65 66 if (!g_dnl_board_usb_cable_connected()) { 67 puts("\rUSB cable not detected.\n" \ 68 "Command exit.\n"); 69 ret = CMD_RET_FAILURE; 70 goto exit; 71 } 72 73 while (1) { 74 if (g_dnl_detach()) 75 break; 76 if (ctrlc()) 77 break; 78 WATCHDOG_RESET(); 79 usb_gadget_handle_interrupts(controller_index); 80 } 81 82 ret = CMD_RET_SUCCESS; 83 84 exit: 85 g_dnl_unregister(); 86 g_dnl_clear_detach(); 87 usb_gadget_release(controller_index); 88 89 return ret; 90 #else 91 pr_err("Fastboot USB not enabled\n"); 92 return CMD_RET_FAILURE; 93 #endif 94 } 95 96 static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) 97 { 98 uintptr_t buf_addr = (uintptr_t)NULL; 99 size_t buf_size = 0; 100 101 if (argc < 2) 102 return CMD_RET_USAGE; 103 104 while (argc > 1 && **(argv + 1) == '-') { 105 char *arg = *++argv; 106 107 --argc; 108 while (*++arg) { 109 switch (*arg) { 110 case 'l': 111 if (--argc <= 0) 112 return CMD_RET_USAGE; 113 buf_addr = simple_strtoul(*++argv, NULL, 16); 114 goto NXTARG; 115 116 case 's': 117 if (--argc <= 0) 118 return CMD_RET_USAGE; 119 buf_size = simple_strtoul(*++argv, NULL, 16); 120 goto NXTARG; 121 122 default: 123 return CMD_RET_USAGE; 124 } 125 } 126 NXTARG: 127 ; 128 } 129 130 /* Handle case when USB controller param is just '-' */ 131 if (argc == 1) { 132 pr_err("Error: Incorrect USB controller index\n"); 133 return CMD_RET_USAGE; 134 } 135 136 fastboot_init((void *)buf_addr, buf_size); 137 138 if (!strcmp(argv[1], "udp")) 139 return do_fastboot_udp(argc, argv, buf_addr, buf_size); 140 141 if (!strcmp(argv[1], "usb")) { 142 argv++; 143 argc--; 144 } 145 146 return do_fastboot_usb(argc, argv, buf_addr, buf_size); 147 } 148 149 #ifdef CONFIG_SYS_LONGHELP 150 static char fastboot_help_text[] = 151 "[-l addr] [-s size] usb <controller> | udp\n" 152 "\taddr - address of buffer used during data transfers (" 153 __stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n" 154 "\tsize - size of buffer used during data transfers (" 155 __stringify(CONFIG_FASTBOOT_BUF_SIZE) ")" 156 ; 157 #endif 158 159 U_BOOT_CMD( 160 fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot, 161 "run as a fastboot usb or udp device", fastboot_help_text 162 ); 163