blob: 33db80a6ff766a87f3a01f4456bd5d176fa02354 [file] [log] [blame]
Brian Swetland9c4c0752009-01-25 16:23:50 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Channagoud Kadabi03550162015-03-10 13:32:27 -07005 * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
Deepa Dinamani26bc2d32013-03-15 13:17:16 -07006 *
Brian Swetland9c4c0752009-01-25 16:23:50 -08007 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
Deepa Dinamani26bc2d32013-03-15 13:17:16 -070010 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
Brian Swetland9c4c0752009-01-25 16:23:50 -080013 * notice, this list of conditions and the following disclaimer in
Deepa Dinamani26bc2d32013-03-15 13:17:16 -070014 * the documentation and/or other materials provided with the
Brian Swetland9c4c0752009-01-25 16:23:50 -080015 * distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
Deepa Dinamani26bc2d32013-03-15 13:17:16 -070024 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
Brian Swetland9c4c0752009-01-25 16:23:50 -080025 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31#include <debug.h>
32#include <string.h>
33#include <stdlib.h>
Deepa Dinamani0bf2f442012-10-19 11:41:06 -070034#include <platform.h>
Amol Jadi5edf3552013-07-23 14:15:34 -070035#include <target.h>
Brian Swetland9c4c0752009-01-25 16:23:50 -080036#include <kernel/thread.h>
37#include <kernel/event.h>
38#include <dev/udc.h>
Channagoud Kadabia0930b92013-04-16 15:14:37 -070039#include "fastboot.h"
Brian Swetland9c4c0752009-01-25 16:23:50 -080040
Amol Jadi7c4316c2013-10-07 14:19:26 -070041#ifdef USB30_SUPPORT
42#include <usb30_udc.h>
43#endif
44
45typedef struct
46{
47 int (*udc_init)(struct udc_device *devinfo);
48 int (*udc_register_gadget)(struct udc_gadget *gadget);
49 int (*udc_start)(void);
50 int (*udc_stop)(void);
51
52 struct udc_endpoint *(*udc_endpoint_alloc)(unsigned type, unsigned maxpkt);
53 void (*udc_endpoint_free)(struct udc_endpoint *ept);
54 struct udc_request *(*udc_request_alloc)(void);
55 void (*udc_request_free)(struct udc_request *req);
56
57 int (*usb_read)(void *buf, unsigned len);
58 int (*usb_write)(void *buf, unsigned len);
59} usb_controller_interface_t;
60
61usb_controller_interface_t usb_if;
62
Hanumant Singh108cdc62012-12-11 16:48:49 -080063#define MAX_USBFS_BULK_SIZE (32 * 1024)
Channagoud Kadabi87823802014-11-05 13:10:05 -080064#define MAX_USBSS_BULK_SIZE (0x1000000)
Shashank Mittal6a5609f2011-08-04 15:51:59 -070065
Brian Swetland9c4c0752009-01-25 16:23:50 -080066void boot_linux(void *bootimg, unsigned sz);
Amol Jadi5edf3552013-07-23 14:15:34 -070067static void fastboot_notify(struct udc_gadget *gadget, unsigned event);
68static struct udc_endpoint *fastboot_endpoints[2];
69
70static struct udc_device surf_udc_device = {
71 .vendor_id = 0x18d1,
72 .product_id = 0xD00D,
73 .version_id = 0x0100,
74 .manufacturer = "Google",
75 .product = "Android",
76};
77
78static struct udc_gadget fastboot_gadget = {
79 .notify = fastboot_notify,
80 .ifc_class = 0xff,
81 .ifc_subclass = 0x42,
82 .ifc_protocol = 0x03,
83 .ifc_endpoints = 2,
84 .ifc_string = "fastboot",
85 .ept = fastboot_endpoints,
86};
Brian Swetland9c4c0752009-01-25 16:23:50 -080087
88/* todo: give lk strtoul and nuke this */
89static unsigned hex2unsigned(const char *x)
90{
91 unsigned n = 0;
92
93 while(*x) {
94 switch(*x) {
95 case '0': case '1': case '2': case '3': case '4':
96 case '5': case '6': case '7': case '8': case '9':
97 n = (n << 4) | (*x - '0');
98 break;
99 case 'a': case 'b': case 'c':
100 case 'd': case 'e': case 'f':
101 n = (n << 4) | (*x - 'a' + 10);
102 break;
103 case 'A': case 'B': case 'C':
104 case 'D': case 'E': case 'F':
105 n = (n << 4) | (*x - 'A' + 10);
106 break;
107 default:
108 return n;
109 }
110 x++;
111 }
112
113 return n;
114}
115
116struct fastboot_cmd {
117 struct fastboot_cmd *next;
118 const char *prefix;
119 unsigned prefix_len;
120 void (*handle)(const char *arg, void *data, unsigned sz);
121};
122
123struct fastboot_var {
124 struct fastboot_var *next;
125 const char *name;
126 const char *value;
127};
Amol Jadi5edf3552013-07-23 14:15:34 -0700128
Brian Swetland9c4c0752009-01-25 16:23:50 -0800129static struct fastboot_cmd *cmdlist;
130
131void fastboot_register(const char *prefix,
132 void (*handle)(const char *arg, void *data, unsigned sz))
133{
134 struct fastboot_cmd *cmd;
135 cmd = malloc(sizeof(*cmd));
136 if (cmd) {
137 cmd->prefix = prefix;
138 cmd->prefix_len = strlen(prefix);
139 cmd->handle = handle;
140 cmd->next = cmdlist;
141 cmdlist = cmd;
142 }
143}
144
145static struct fastboot_var *varlist;
146
147void fastboot_publish(const char *name, const char *value)
148{
149 struct fastboot_var *var;
150 var = malloc(sizeof(*var));
151 if (var) {
152 var->name = name;
153 var->value = value;
154 var->next = varlist;
155 varlist = var;
156 }
157}
158
159
160static event_t usb_online;
161static event_t txn_done;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800162static struct udc_endpoint *in, *out;
163static struct udc_request *req;
164int txn_status;
165
166static void *download_base;
167static unsigned download_max;
168static unsigned download_size;
169
170#define STATE_OFFLINE 0
171#define STATE_COMMAND 1
172#define STATE_COMPLETE 2
173#define STATE_ERROR 3
174
175static unsigned fastboot_state = STATE_OFFLINE;
176
177static void req_complete(struct udc_request *req, unsigned actual, int status)
178{
179 txn_status = status;
180 req->length = actual;
Hanumant Singh108cdc62012-12-11 16:48:49 -0800181
Brian Swetland9c4c0752009-01-25 16:23:50 -0800182 event_signal(&txn_done, 0);
183}
184
Amol Jadi5e52d722013-08-19 17:10:33 -0700185#ifdef USB30_SUPPORT
Channagoud Kadabi87823802014-11-05 13:10:05 -0800186static int usb30_usb_read(void *_buf, unsigned len)
Amol Jadi5e52d722013-08-19 17:10:33 -0700187{
188 int r;
189 struct udc_request req;
Channagoud Kadabi87823802014-11-05 13:10:05 -0800190 uint32_t xfer;
191 int count = 0;
192 uint32_t trans_len = len;
193 const char *buf = _buf;
Amol Jadi5e52d722013-08-19 17:10:33 -0700194
195 ASSERT(buf);
196 ASSERT(len);
197
198 if (fastboot_state == STATE_ERROR)
199 goto oops;
200
201 dprintf(SPEW, "usb_read(): len = %d\n", len);
202
Channagoud Kadabi87823802014-11-05 13:10:05 -0800203 while (len > 0)
Amol Jadi5e52d722013-08-19 17:10:33 -0700204 {
Channagoud Kadabi87823802014-11-05 13:10:05 -0800205 xfer = (len > MAX_USBSS_BULK_SIZE) ? MAX_USBSS_BULK_SIZE : len;
Amol Jadi5e52d722013-08-19 17:10:33 -0700206
Channagoud Kadabi87823802014-11-05 13:10:05 -0800207 req.buf = (void*) PA((addr_t)buf);
208 req.length = xfer;
209 req.complete = req_complete;
Amol Jadi5e52d722013-08-19 17:10:33 -0700210
Channagoud Kadabi87823802014-11-05 13:10:05 -0800211 r = usb30_udc_request_queue(out, &req);
212 if (r < 0)
213 {
214 dprintf(CRITICAL, "usb_read() queue failed. r = %d\n", r);
215 goto oops;
216 }
217 event_wait(&txn_done);
218
219 if (txn_status < 0)
220 {
221 dprintf(CRITICAL, "usb_read() transaction failed. txn_status = %d\n",
222 txn_status);
223 goto oops;
224 }
225
226 count += req.length;
227 buf += req.length;
228 len -= req.length;
229
230 /* note: req.length is update by callback to reflect the amount of data
231 * actually read.
232 */
233 dprintf(SPEW, "usb_read(): DONE. req.length = %d\n\n", req.length);
234
235 /* For USB3.0 if the data transfer is less than MaxpacketSize, its
236 * short packet and DWC layer generates transfer complete. App layer
237 * shold handle this and continue trasnferring the data instead of treating
238 * this as a transfer complete. This case is not applicable for transfers
239 * which involve protocol communication to exchange information whose length
240 * is always equal to MAX_RSP_SIZE. This check ensures that we dont abort
241 * data transfers on short packet.
242 */
243 if (req.length != xfer && trans_len == MAX_RSP_SIZE) break;
244 }
Amol Jadi5e52d722013-08-19 17:10:33 -0700245
246 /* invalidate any cached buf data (controller updates main memory) */
Channagoud Kadabi87823802014-11-05 13:10:05 -0800247 arch_invalidate_cache_range((addr_t) _buf, count);
Amol Jadi5e52d722013-08-19 17:10:33 -0700248
Channagoud Kadabi87823802014-11-05 13:10:05 -0800249 return count;
Amol Jadi5e52d722013-08-19 17:10:33 -0700250
251oops:
252 fastboot_state = STATE_ERROR;
253 dprintf(CRITICAL, "usb_read(): DONE: ERROR: len = %d\n", len);
254 return -1;
255}
256
Amol Jadi7c4316c2013-10-07 14:19:26 -0700257static int usb30_usb_write(void *buf, unsigned len)
Amol Jadi5e52d722013-08-19 17:10:33 -0700258{
259 int r;
260 struct udc_request req;
261
262 ASSERT(buf);
263 ASSERT(len);
264
265 if (fastboot_state == STATE_ERROR)
266 goto oops;
267
268 dprintf(SPEW, "usb_write(): len = %d str = %s\n", len, (char *) buf);
269
270 /* flush buffer to main memory before giving to udc */
271 arch_clean_invalidate_cache_range((addr_t) buf, len);
272
273 req.buf = (void*) PA((addr_t)buf);
274 req.length = len;
275 req.complete = req_complete;
276
Amol Jadi7c4316c2013-10-07 14:19:26 -0700277 r = usb30_udc_request_queue(in, &req);
Amol Jadi5e52d722013-08-19 17:10:33 -0700278 if (r < 0) {
279 dprintf(CRITICAL, "usb_write() queue failed. r = %d\n", r);
280 goto oops;
281 }
282 event_wait(&txn_done);
283
284 dprintf(SPEW, "usb_write(): DONE: len = %d req->length = %d str = %s\n",
285 len, req.length, (char *) buf);
286
287 if (txn_status < 0) {
288 dprintf(CRITICAL, "usb_write() transaction failed. txn_status = %d\n",
289 txn_status);
290 goto oops;
291 }
292
293 return req.length;
294
295oops:
296 fastboot_state = STATE_ERROR;
297 dprintf(CRITICAL, "usb_write(): DONE: ERROR: len = %d\n", len);
298 return -1;
299}
Amol Jadi7c4316c2013-10-07 14:19:26 -0700300#endif
Amol Jadi5e52d722013-08-19 17:10:33 -0700301
Amol Jadi7c4316c2013-10-07 14:19:26 -0700302static int hsusb_usb_read(void *_buf, unsigned len)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800303{
304 int r;
305 unsigned xfer;
306 unsigned char *buf = _buf;
307 int count = 0;
308
309 if (fastboot_state == STATE_ERROR)
310 goto oops;
311
312 while (len > 0) {
Shashank Mittal1cc65b02011-12-20 15:30:17 -0800313 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530314 req->buf = (unsigned char *)PA((addr_t)buf);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800315 req->length = xfer;
316 req->complete = req_complete;
317 r = udc_request_queue(out, req);
318 if (r < 0) {
319 dprintf(INFO, "usb_read() queue failed\n");
320 goto oops;
321 }
322 event_wait(&txn_done);
323
324 if (txn_status < 0) {
325 dprintf(INFO, "usb_read() transaction failed\n");
326 goto oops;
327 }
328
329 count += req->length;
330 buf += req->length;
331 len -= req->length;
332
333 /* short transfer? */
334 if (req->length != xfer) break;
335 }
Hanumant Singh108cdc62012-12-11 16:48:49 -0800336 /*
337 * Force reload of buffer from memory
338 * since transaction is complete now.
339 */
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530340 arch_invalidate_cache_range((addr_t)_buf, count);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800341 return count;
342
343oops:
344 fastboot_state = STATE_ERROR;
345 return -1;
346}
347
Amol Jadi7c4316c2013-10-07 14:19:26 -0700348static int hsusb_usb_write(void *buf, unsigned len)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800349{
350 int r;
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700351 uint32_t xfer;
352 unsigned char *_buf = buf;
353 int count = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800354
355 if (fastboot_state == STATE_ERROR)
356 goto oops;
357
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700358 while (len > 0) {
359 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530360 req->buf = (unsigned char *)PA((addr_t)_buf);
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700361 req->length = xfer;
362 req->complete = req_complete;
363 r = udc_request_queue(in, req);
364 if (r < 0) {
365 dprintf(INFO, "usb_write() queue failed\n");
366 goto oops;
367 }
368 event_wait(&txn_done);
369 if (txn_status < 0) {
370 dprintf(INFO, "usb_write() transaction failed\n");
371 goto oops;
372 }
373
374 count += req->length;
375 _buf += req->length;
376 len -= req->length;
377
378 /* short transfer? */
379 if (req->length != xfer) break;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800380 }
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700381
382 return count;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800383
384oops:
385 fastboot_state = STATE_ERROR;
386 return -1;
387}
388
389void fastboot_ack(const char *code, const char *reason)
390{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700391 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800392
393 if (fastboot_state != STATE_COMMAND)
394 return;
395
396 if (reason == 0)
397 reason = "";
398
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530399 snprintf((char *)response, MAX_RSP_SIZE, "%s%s", code, reason);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800400 fastboot_state = STATE_COMPLETE;
401
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530402 usb_if.usb_write(response, strlen((const char *)response));
Brian Swetland9c4c0752009-01-25 16:23:50 -0800403
404}
405
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700406void fastboot_info(const char *reason)
407{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700408 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700409
410 if (fastboot_state != STATE_COMMAND)
411 return;
412
413 if (reason == 0)
414 return;
415
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530416 snprintf((char *)response, MAX_RSP_SIZE, "INFO%s", reason);
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700417
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530418 usb_if.usb_write(response, strlen((const char *)response));
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700419}
420
Brian Swetland9c4c0752009-01-25 16:23:50 -0800421void fastboot_fail(const char *reason)
422{
423 fastboot_ack("FAIL", reason);
424}
425
426void fastboot_okay(const char *info)
427{
428 fastboot_ack("OKAY", info);
429}
430
Channagoud Kadabi03550162015-03-10 13:32:27 -0700431static void getvar_all()
432{
433 struct fastboot_var *var;
Mayank Grover351a75e2017-05-30 20:06:08 +0530434 char getvar_all[256];
Channagoud Kadabi03550162015-03-10 13:32:27 -0700435
436 for (var = varlist; var; var = var->next)
437 {
438 strlcpy((char *) getvar_all, var->name, sizeof(getvar_all));
439 strlcat((char *) getvar_all, ":", sizeof(getvar_all));
440 strlcat((char *) getvar_all, var->value, sizeof(getvar_all));
441 fastboot_info(getvar_all);
442 memset((void *) getvar_all, '\0', sizeof(getvar_all));
443 }
444 fastboot_okay("");
445}
446
Brian Swetland9c4c0752009-01-25 16:23:50 -0800447static void cmd_getvar(const char *arg, void *data, unsigned sz)
448{
449 struct fastboot_var *var;
450
lijuang102dfa92015-10-09 18:31:03 +0800451#if CHECK_BAT_VOLTAGE
452 update_battery_status();
453#endif
454
Mayank Grover351a75e2017-05-30 20:06:08 +0530455
Channagoud Kadabi03550162015-03-10 13:32:27 -0700456 if (!strncmp("all", arg, strlen(arg)))
457 {
458 getvar_all();
459 return;
460 }
461
Brian Swetland9c4c0752009-01-25 16:23:50 -0800462 for (var = varlist; var; var = var->next) {
463 if (!strcmp(var->name, arg)) {
464 fastboot_okay(var->value);
465 return;
466 }
467 }
468 fastboot_okay("");
469}
470
471static void cmd_download(const char *arg, void *data, unsigned sz)
472{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700473 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800474 unsigned len = hex2unsigned(arg);
475 int r;
476
477 download_size = 0;
478 if (len > download_max) {
479 fastboot_fail("data too large");
480 return;
481 }
482
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530483 snprintf((char *)response, MAX_RSP_SIZE, "DATA%08x", len);
484 if (usb_if.usb_write(response, strlen((const char *)response)) < 0)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800485 return;
Channagoud Kadabi5389f372015-02-27 15:26:28 -0800486 /*
487 * Discard the cache contents before starting the download
488 */
Channagoud Kadabifa88c782015-07-17 18:11:30 -0700489 arch_invalidate_cache_range((addr_t) download_base, len);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800490
Amol Jadi7c4316c2013-10-07 14:19:26 -0700491 r = usb_if.usb_read(download_base, len);
Greg Griscod6250552011-06-29 14:40:23 -0700492 if ((r < 0) || ((unsigned) r != len)) {
Brian Swetland9c4c0752009-01-25 16:23:50 -0800493 fastboot_state = STATE_ERROR;
494 return;
495 }
496 download_size = len;
497 fastboot_okay("");
498}
499
500static void fastboot_command_loop(void)
501{
502 struct fastboot_cmd *cmd;
503 int r;
lijuangd86b38e2015-10-13 18:13:01 +0800504#if CHECK_BAT_VOLTAGE
505 boolean is_first_erase_flash = false;
506#endif
507
Brian Swetland9c4c0752009-01-25 16:23:50 -0800508 dprintf(INFO,"fastboot: processing commands\n");
509
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700510 uint8_t *buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(4096, CACHE_LINE));
511 if (!buffer)
512 {
513 dprintf(CRITICAL, "Could not allocate memory for fastboot buffer\n.");
514 ASSERT(0);
515 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800516again:
517 while (fastboot_state != STATE_ERROR) {
Amol Jadi5edf3552013-07-23 14:15:34 -0700518
519 /* Read buffer must be cleared first. If buffer is not cleared,
520 * the original data in buf trailing the received command is
521 * interpreted as part of the command.
522 */
523 memset(buffer, 0, MAX_RSP_SIZE);
524 arch_clean_invalidate_cache_range((addr_t) buffer, MAX_RSP_SIZE);
525
Amol Jadi7c4316c2013-10-07 14:19:26 -0700526 r = usb_if.usb_read(buffer, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800527 if (r < 0) break;
528 buffer[r] = 0;
529 dprintf(INFO,"fastboot: %s\n", buffer);
530
lijuangd86b38e2015-10-13 18:13:01 +0800531#if CHECK_BAT_VOLTAGE
532 /* check battery voltage before erase or flash image */
533 if (!strncmp((const char*) buffer, "getvar:partition-type", 21))
534 is_first_erase_flash = true;
535
536 if (is_first_erase_flash) {
537 if (!strncmp((const char*) buffer, "erase", 5) ||
538 !strncmp((const char*) buffer, "flash", 5)) {
539 if (!target_battery_soc_ok()) {
540 dprintf(INFO,"fastboot: battery voltage: %d\n",
541 target_get_battery_voltage());
542 fastboot_fail("Warning: battery's capacity is very low\n");
Mayank Grover3f5f97c2017-09-26 11:48:50 +0530543 continue;
lijuangd86b38e2015-10-13 18:13:01 +0800544 }
545 }
546 }
547#endif
548
Channagoud Kadabi69c16732013-12-05 17:29:18 -0800549 fastboot_state = STATE_COMMAND;
550
Brian Swetland9c4c0752009-01-25 16:23:50 -0800551 for (cmd = cmdlist; cmd; cmd = cmd->next) {
552 if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
553 continue;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800554 cmd->handle((const char*) buffer + cmd->prefix_len,
555 (void*) download_base, download_size);
556 if (fastboot_state == STATE_COMMAND)
557 fastboot_fail("unknown reason");
lijuangd86b38e2015-10-13 18:13:01 +0800558
559#if CHECK_BAT_VOLTAGE
560 if (!strncmp((const char*) buffer, "erase", 5) ||
561 !strncmp((const char*) buffer, "flash", 5)) {
562 if (is_first_erase_flash) {
563 is_first_erase_flash = false;
564 }
565 }
566#endif
Brian Swetland9c4c0752009-01-25 16:23:50 -0800567 goto again;
568 }
569
570 fastboot_fail("unknown command");
Amol Jadi5edf3552013-07-23 14:15:34 -0700571
Brian Swetland9c4c0752009-01-25 16:23:50 -0800572 }
573 fastboot_state = STATE_OFFLINE;
574 dprintf(INFO,"fastboot: oops!\n");
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700575 free(buffer);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800576}
577
578static int fastboot_handler(void *arg)
579{
580 for (;;) {
581 event_wait(&usb_online);
582 fastboot_command_loop();
583 }
584 return 0;
585}
586
587static void fastboot_notify(struct udc_gadget *gadget, unsigned event)
588{
589 if (event == UDC_EVENT_ONLINE) {
590 event_signal(&usb_online, 0);
591 }
592}
593
Brian Swetland9c4c0752009-01-25 16:23:50 -0800594int fastboot_init(void *base, unsigned size)
595{
Amol Jadi5edf3552013-07-23 14:15:34 -0700596 char sn_buf[13];
Brian Swetland9c4c0752009-01-25 16:23:50 -0800597 thread_t *thr;
598 dprintf(INFO, "fastboot_init()\n");
599
600 download_base = base;
601 download_max = size;
602
Amol Jadi5edf3552013-07-23 14:15:34 -0700603 /* target specific initialization before going into fastboot. */
604 target_fastboot_init();
605
606 /* setup serialno */
607 target_serialno((unsigned char *) sn_buf);
608 dprintf(SPEW,"serial number: %s\n",sn_buf);
609 surf_udc_device.serialno = sn_buf;
610
Amol Jadi7c4316c2013-10-07 14:19:26 -0700611 if(!strcmp(target_usb_controller(), "dwc"))
612 {
613#ifdef USB30_SUPPORT
Channagoud Kadabi728ef0a2014-02-04 17:11:08 -0800614 surf_udc_device.t_usb_if = target_usb30_init();
615
Amol Jadi7c4316c2013-10-07 14:19:26 -0700616 /* initialize udc functions to use dwc controller */
617 usb_if.udc_init = usb30_udc_init;
618 usb_if.udc_register_gadget = usb30_udc_register_gadget;
619 usb_if.udc_start = usb30_udc_start;
620 usb_if.udc_stop = usb30_udc_stop;
621
622 usb_if.udc_endpoint_alloc = usb30_udc_endpoint_alloc;
623 usb_if.udc_request_alloc = usb30_udc_request_alloc;
624 usb_if.udc_request_free = usb30_udc_request_free;
625
626 usb_if.usb_read = usb30_usb_read;
627 usb_if.usb_write = usb30_usb_write;
628#else
629 dprintf(CRITICAL, "USB30 needs to be enabled for this target.\n");
630 ASSERT(0);
631#endif
632 }
633 else
634 {
635 /* initialize udc functions to use the default chipidea controller */
636 usb_if.udc_init = udc_init;
637 usb_if.udc_register_gadget = udc_register_gadget;
638 usb_if.udc_start = udc_start;
639 usb_if.udc_stop = udc_stop;
640
641 usb_if.udc_endpoint_alloc = udc_endpoint_alloc;
642 usb_if.udc_request_alloc = udc_request_alloc;
643 usb_if.udc_request_free = udc_request_free;
644
645 usb_if.usb_read = hsusb_usb_read;
646 usb_if.usb_write = hsusb_usb_write;
647 }
648
Amol Jadi5edf3552013-07-23 14:15:34 -0700649 /* register udc device */
Amol Jadi7c4316c2013-10-07 14:19:26 -0700650 usb_if.udc_init(&surf_udc_device);
Amol Jadi5edf3552013-07-23 14:15:34 -0700651
Brian Swetland9c4c0752009-01-25 16:23:50 -0800652 event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);
653 event_init(&txn_done, 0, EVENT_FLAG_AUTOUNSIGNAL);
654
Amol Jadi7c4316c2013-10-07 14:19:26 -0700655 in = usb_if.udc_endpoint_alloc(UDC_TYPE_BULK_IN, 512);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800656 if (!in)
657 goto fail_alloc_in;
Amol Jadi7c4316c2013-10-07 14:19:26 -0700658 out = usb_if.udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800659 if (!out)
660 goto fail_alloc_out;
661
662 fastboot_endpoints[0] = in;
663 fastboot_endpoints[1] = out;
664
Amol Jadi7c4316c2013-10-07 14:19:26 -0700665 req = usb_if.udc_request_alloc();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800666 if (!req)
667 goto fail_alloc_req;
668
Amol Jadi5edf3552013-07-23 14:15:34 -0700669 /* register gadget */
Amol Jadi7c4316c2013-10-07 14:19:26 -0700670 if (usb_if.udc_register_gadget(&fastboot_gadget))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800671 goto fail_udc_register;
672
673 fastboot_register("getvar:", cmd_getvar);
674 fastboot_register("download:", cmd_download);
675 fastboot_publish("version", "0.5");
676
677 thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, 4096);
neetid32ba8472011-12-07 16:34:06 -0800678 if (!thr)
679 {
680 goto fail_alloc_in;
681 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800682 thread_resume(thr);
Amol Jadi5edf3552013-07-23 14:15:34 -0700683
Amol Jadi7c4316c2013-10-07 14:19:26 -0700684 usb_if.udc_start();
Amol Jadi5edf3552013-07-23 14:15:34 -0700685
Brian Swetland9c4c0752009-01-25 16:23:50 -0800686 return 0;
687
688fail_udc_register:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700689 usb_if.udc_request_free(req);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800690fail_alloc_req:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700691 usb_if.udc_endpoint_free(out);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800692fail_alloc_out:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700693 usb_if.udc_endpoint_free(in);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800694fail_alloc_in:
695 return -1;
696}
Amol Jadi7c4316c2013-10-07 14:19:26 -0700697
698void fastboot_stop(void)
699{
700 usb_if.udc_stop();
701}