xref: /openbmc/u-boot/cmd/fastboot.c (revision 14453fbf)
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