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