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