xref: /openbmc/u-boot/cmd/fastboot.c (revision 66c433ed)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
22e192b24SSimon Glass /*
32e192b24SSimon Glass  * Copyright 2008 - 2009 Windriver, <www.windriver.com>
42e192b24SSimon Glass  * Author: Tom Rix <Tom.Rix@windriver.com>
52e192b24SSimon Glass  *
62e192b24SSimon Glass  * (C) Copyright 2014 Linaro, Ltd.
72e192b24SSimon Glass  * Rob Herring <robh@kernel.org>
82e192b24SSimon Glass  */
92e192b24SSimon Glass #include <common.h>
102e192b24SSimon Glass #include <command.h>
112e192b24SSimon Glass #include <console.h>
122e192b24SSimon Glass #include <g_dnl.h>
13f73a7df9SAlex Kiernan #include <fastboot.h>
14f73a7df9SAlex Kiernan #include <net.h>
152e192b24SSimon Glass #include <usb.h>
16*731785dfSSean Nyekjaer #include <watchdog.h>
172e192b24SSimon Glass 
do_fastboot_udp(int argc,char * const argv[],uintptr_t buf_addr,size_t buf_size)18f73a7df9SAlex Kiernan static int do_fastboot_udp(int argc, char *const argv[],
19f73a7df9SAlex Kiernan 			   uintptr_t buf_addr, size_t buf_size)
202e192b24SSimon Glass {
21f73a7df9SAlex Kiernan #if CONFIG_IS_ENABLED(UDP_FUNCTION_FASTBOOT)
22f73a7df9SAlex Kiernan 	int err = net_loop(FASTBOOT);
23f73a7df9SAlex Kiernan 
24f73a7df9SAlex Kiernan 	if (err < 0) {
25f73a7df9SAlex Kiernan 		printf("fastboot udp error: %d\n", err);
26f73a7df9SAlex Kiernan 		return CMD_RET_FAILURE;
27f73a7df9SAlex Kiernan 	}
28f73a7df9SAlex Kiernan 
29f73a7df9SAlex Kiernan 	return CMD_RET_SUCCESS;
30f73a7df9SAlex Kiernan #else
31f73a7df9SAlex Kiernan 	pr_err("Fastboot UDP not enabled\n");
32f73a7df9SAlex Kiernan 	return CMD_RET_FAILURE;
33f73a7df9SAlex Kiernan #endif
34f73a7df9SAlex Kiernan }
35f73a7df9SAlex Kiernan 
do_fastboot_usb(int argc,char * const argv[],uintptr_t buf_addr,size_t buf_size)36f73a7df9SAlex Kiernan static int do_fastboot_usb(int argc, char *const argv[],
37f73a7df9SAlex Kiernan 			   uintptr_t buf_addr, size_t buf_size)
38f73a7df9SAlex Kiernan {
39f73a7df9SAlex Kiernan #if CONFIG_IS_ENABLED(USB_FUNCTION_FASTBOOT)
402e192b24SSimon Glass 	int controller_index;
412e192b24SSimon Glass 	char *usb_controller;
42aa51579fSSam Protsenko 	char *endp;
432e192b24SSimon Glass 	int ret;
442e192b24SSimon Glass 
452e192b24SSimon Glass 	if (argc < 2)
462e192b24SSimon Glass 		return CMD_RET_USAGE;
472e192b24SSimon Glass 
482e192b24SSimon Glass 	usb_controller = argv[1];
49aa51579fSSam Protsenko 	controller_index = simple_strtoul(usb_controller, &endp, 0);
50aa51579fSSam Protsenko 	if (*endp != '\0') {
51aa51579fSSam Protsenko 		pr_err("Error: Wrong USB controller index format\n");
52aa51579fSSam Protsenko 		return CMD_RET_FAILURE;
53aa51579fSSam Protsenko 	}
542e192b24SSimon Glass 
55a06955aeSJean-Jacques Hiblot 	ret = usb_gadget_initialize(controller_index);
562e192b24SSimon Glass 	if (ret) {
5771002b50SSeung-Woo Kim 		pr_err("USB init failed: %d\n", ret);
582e192b24SSimon Glass 		return CMD_RET_FAILURE;
592e192b24SSimon Glass 	}
602e192b24SSimon Glass 
612e192b24SSimon Glass 	g_dnl_clear_detach();
622e192b24SSimon Glass 	ret = g_dnl_register("usb_dnl_fastboot");
632e192b24SSimon Glass 	if (ret)
642e192b24SSimon Glass 		return ret;
652e192b24SSimon Glass 
662e192b24SSimon Glass 	if (!g_dnl_board_usb_cable_connected()) {
672e192b24SSimon Glass 		puts("\rUSB cable not detected.\n" \
682e192b24SSimon Glass 		     "Command exit.\n");
692e192b24SSimon Glass 		ret = CMD_RET_FAILURE;
702e192b24SSimon Glass 		goto exit;
712e192b24SSimon Glass 	}
722e192b24SSimon Glass 
732e192b24SSimon Glass 	while (1) {
742e192b24SSimon Glass 		if (g_dnl_detach())
752e192b24SSimon Glass 			break;
762e192b24SSimon Glass 		if (ctrlc())
772e192b24SSimon Glass 			break;
78*731785dfSSean Nyekjaer 		WATCHDOG_RESET();
792e192b24SSimon Glass 		usb_gadget_handle_interrupts(controller_index);
802e192b24SSimon Glass 	}
812e192b24SSimon Glass 
822e192b24SSimon Glass 	ret = CMD_RET_SUCCESS;
832e192b24SSimon Glass 
842e192b24SSimon Glass exit:
852e192b24SSimon Glass 	g_dnl_unregister();
862e192b24SSimon Glass 	g_dnl_clear_detach();
87a06955aeSJean-Jacques Hiblot 	usb_gadget_release(controller_index);
882e192b24SSimon Glass 
892e192b24SSimon Glass 	return ret;
90f73a7df9SAlex Kiernan #else
91f73a7df9SAlex Kiernan 	pr_err("Fastboot USB not enabled\n");
92f73a7df9SAlex Kiernan 	return CMD_RET_FAILURE;
93f73a7df9SAlex Kiernan #endif
942e192b24SSimon Glass }
952e192b24SSimon Glass 
do_fastboot(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])96f73a7df9SAlex Kiernan static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
97f73a7df9SAlex Kiernan {
98f73a7df9SAlex Kiernan 	uintptr_t buf_addr = (uintptr_t)NULL;
99f73a7df9SAlex Kiernan 	size_t buf_size = 0;
100f73a7df9SAlex Kiernan 
101f73a7df9SAlex Kiernan 	if (argc < 2)
102f73a7df9SAlex Kiernan 		return CMD_RET_USAGE;
103f73a7df9SAlex Kiernan 
104f73a7df9SAlex Kiernan 	while (argc > 1 && **(argv + 1) == '-') {
105f73a7df9SAlex Kiernan 		char *arg = *++argv;
106f73a7df9SAlex Kiernan 
107f73a7df9SAlex Kiernan 		--argc;
108f73a7df9SAlex Kiernan 		while (*++arg) {
109f73a7df9SAlex Kiernan 			switch (*arg) {
110f73a7df9SAlex Kiernan 			case 'l':
111f73a7df9SAlex Kiernan 				if (--argc <= 0)
112f73a7df9SAlex Kiernan 					return CMD_RET_USAGE;
113f73a7df9SAlex Kiernan 				buf_addr = simple_strtoul(*++argv, NULL, 16);
114f73a7df9SAlex Kiernan 				goto NXTARG;
115f73a7df9SAlex Kiernan 
116f73a7df9SAlex Kiernan 			case 's':
117f73a7df9SAlex Kiernan 				if (--argc <= 0)
118f73a7df9SAlex Kiernan 					return CMD_RET_USAGE;
119f73a7df9SAlex Kiernan 				buf_size = simple_strtoul(*++argv, NULL, 16);
120f73a7df9SAlex Kiernan 				goto NXTARG;
121f73a7df9SAlex Kiernan 
122f73a7df9SAlex Kiernan 			default:
123f73a7df9SAlex Kiernan 				return CMD_RET_USAGE;
124f73a7df9SAlex Kiernan 			}
125f73a7df9SAlex Kiernan 		}
126f73a7df9SAlex Kiernan NXTARG:
127f73a7df9SAlex Kiernan 		;
128f73a7df9SAlex Kiernan 	}
129f73a7df9SAlex Kiernan 
130aa51579fSSam Protsenko 	/* Handle case when USB controller param is just '-' */
131aa51579fSSam Protsenko 	if (argc == 1) {
132aa51579fSSam Protsenko 		pr_err("Error: Incorrect USB controller index\n");
133aa51579fSSam Protsenko 		return CMD_RET_USAGE;
134aa51579fSSam Protsenko 	}
135aa51579fSSam Protsenko 
136f73a7df9SAlex Kiernan 	fastboot_init((void *)buf_addr, buf_size);
137f73a7df9SAlex Kiernan 
138f73a7df9SAlex Kiernan 	if (!strcmp(argv[1], "udp"))
139f73a7df9SAlex Kiernan 		return do_fastboot_udp(argc, argv, buf_addr, buf_size);
140f73a7df9SAlex Kiernan 
141f73a7df9SAlex Kiernan 	if (!strcmp(argv[1], "usb")) {
142f73a7df9SAlex Kiernan 		argv++;
143f73a7df9SAlex Kiernan 		argc--;
144f73a7df9SAlex Kiernan 	}
145f73a7df9SAlex Kiernan 
146f73a7df9SAlex Kiernan 	return do_fastboot_usb(argc, argv, buf_addr, buf_size);
147f73a7df9SAlex Kiernan }
148f73a7df9SAlex Kiernan 
149f73a7df9SAlex Kiernan #ifdef CONFIG_SYS_LONGHELP
150f73a7df9SAlex Kiernan static char fastboot_help_text[] =
151f73a7df9SAlex Kiernan 	"[-l addr] [-s size] usb <controller> | udp\n"
152f73a7df9SAlex Kiernan 	"\taddr - address of buffer used during data transfers ("
153f73a7df9SAlex Kiernan 	__stringify(CONFIG_FASTBOOT_BUF_ADDR) ")\n"
154f73a7df9SAlex Kiernan 	"\tsize - size of buffer used during data transfers ("
155f73a7df9SAlex Kiernan 	__stringify(CONFIG_FASTBOOT_BUF_SIZE) ")"
156f73a7df9SAlex Kiernan 	;
157f73a7df9SAlex Kiernan #endif
158f73a7df9SAlex Kiernan 
1592e192b24SSimon Glass U_BOOT_CMD(
160f73a7df9SAlex Kiernan 	fastboot, CONFIG_SYS_MAXARGS, 1, do_fastboot,
161f73a7df9SAlex Kiernan 	"run as a fastboot usb or udp device", fastboot_help_text
1622e192b24SSimon Glass );
163