blob: cac7f8f9ca31230b05d54c8d8caa0e346ce5cf96 [file] [log] [blame]
Brian Swetland9c4c0752009-01-25 16:23:50 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
lijuangc2676752018-05-15 13:52:36 +08005 * Copyright (c) 2013-2015, 2018, 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"
Parth Dixitf8071f02017-09-27 17:59:30 +053040#include <err.h>
Brian Swetland9c4c0752009-01-25 16:23:50 -080041
Amol Jadi7c4316c2013-10-07 14:19:26 -070042#ifdef USB30_SUPPORT
43#include <usb30_udc.h>
44#endif
45
46typedef struct
47{
48 int (*udc_init)(struct udc_device *devinfo);
49 int (*udc_register_gadget)(struct udc_gadget *gadget);
50 int (*udc_start)(void);
51 int (*udc_stop)(void);
52
53 struct udc_endpoint *(*udc_endpoint_alloc)(unsigned type, unsigned maxpkt);
54 void (*udc_endpoint_free)(struct udc_endpoint *ept);
55 struct udc_request *(*udc_request_alloc)(void);
56 void (*udc_request_free)(struct udc_request *req);
57
58 int (*usb_read)(void *buf, unsigned len);
59 int (*usb_write)(void *buf, unsigned len);
60} usb_controller_interface_t;
61
62usb_controller_interface_t usb_if;
63
Hanumant Singh108cdc62012-12-11 16:48:49 -080064#define MAX_USBFS_BULK_SIZE (32 * 1024)
Channagoud Kadabi87823802014-11-05 13:10:05 -080065#define MAX_USBSS_BULK_SIZE (0x1000000)
Shashank Mittal6a5609f2011-08-04 15:51:59 -070066
Brian Swetland9c4c0752009-01-25 16:23:50 -080067void boot_linux(void *bootimg, unsigned sz);
Amol Jadi5edf3552013-07-23 14:15:34 -070068static void fastboot_notify(struct udc_gadget *gadget, unsigned event);
69static struct udc_endpoint *fastboot_endpoints[2];
70
71static struct udc_device surf_udc_device = {
72 .vendor_id = 0x18d1,
73 .product_id = 0xD00D,
74 .version_id = 0x0100,
75 .manufacturer = "Google",
76 .product = "Android",
77};
78
79static struct udc_gadget fastboot_gadget = {
80 .notify = fastboot_notify,
81 .ifc_class = 0xff,
82 .ifc_subclass = 0x42,
83 .ifc_protocol = 0x03,
84 .ifc_endpoints = 2,
85 .ifc_string = "fastboot",
86 .ept = fastboot_endpoints,
87};
Brian Swetland9c4c0752009-01-25 16:23:50 -080088
89/* todo: give lk strtoul and nuke this */
90static unsigned hex2unsigned(const char *x)
91{
92 unsigned n = 0;
93
94 while(*x) {
95 switch(*x) {
96 case '0': case '1': case '2': case '3': case '4':
97 case '5': case '6': case '7': case '8': case '9':
98 n = (n << 4) | (*x - '0');
99 break;
100 case 'a': case 'b': case 'c':
101 case 'd': case 'e': case 'f':
102 n = (n << 4) | (*x - 'a' + 10);
103 break;
104 case 'A': case 'B': case 'C':
105 case 'D': case 'E': case 'F':
106 n = (n << 4) | (*x - 'A' + 10);
107 break;
108 default:
109 return n;
110 }
111 x++;
112 }
113
114 return n;
115}
116
117struct fastboot_cmd {
118 struct fastboot_cmd *next;
119 const char *prefix;
120 unsigned prefix_len;
121 void (*handle)(const char *arg, void *data, unsigned sz);
122};
123
124struct fastboot_var {
125 struct fastboot_var *next;
126 const char *name;
127 const char *value;
128};
Amol Jadi5edf3552013-07-23 14:15:34 -0700129
Brian Swetland9c4c0752009-01-25 16:23:50 -0800130static struct fastboot_cmd *cmdlist;
131
132void fastboot_register(const char *prefix,
133 void (*handle)(const char *arg, void *data, unsigned sz))
134{
135 struct fastboot_cmd *cmd;
136 cmd = malloc(sizeof(*cmd));
137 if (cmd) {
138 cmd->prefix = prefix;
139 cmd->prefix_len = strlen(prefix);
140 cmd->handle = handle;
141 cmd->next = cmdlist;
142 cmdlist = cmd;
143 }
144}
145
146static struct fastboot_var *varlist;
147
148void fastboot_publish(const char *name, const char *value)
149{
150 struct fastboot_var *var;
151 var = malloc(sizeof(*var));
152 if (var) {
153 var->name = name;
154 var->value = value;
155 var->next = varlist;
156 varlist = var;
157 }
158}
159
160
161static event_t usb_online;
162static event_t txn_done;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800163static struct udc_endpoint *in, *out;
164static struct udc_request *req;
165int txn_status;
166
167static void *download_base;
168static unsigned download_max;
169static unsigned download_size;
Parth Dixitf8071f02017-09-27 17:59:30 +0530170static void *upload_base_addr;
171static unsigned upload_size;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800172
173#define STATE_OFFLINE 0
174#define STATE_COMMAND 1
175#define STATE_COMPLETE 2
176#define STATE_ERROR 3
177
178static unsigned fastboot_state = STATE_OFFLINE;
179
180static void req_complete(struct udc_request *req, unsigned actual, int status)
181{
182 txn_status = status;
183 req->length = actual;
Hanumant Singh108cdc62012-12-11 16:48:49 -0800184
Brian Swetland9c4c0752009-01-25 16:23:50 -0800185 event_signal(&txn_done, 0);
186}
187
Amol Jadi5e52d722013-08-19 17:10:33 -0700188#ifdef USB30_SUPPORT
Channagoud Kadabi87823802014-11-05 13:10:05 -0800189static int usb30_usb_read(void *_buf, unsigned len)
Amol Jadi5e52d722013-08-19 17:10:33 -0700190{
191 int r;
192 struct udc_request req;
Channagoud Kadabi87823802014-11-05 13:10:05 -0800193 uint32_t xfer;
194 int count = 0;
195 uint32_t trans_len = len;
196 const char *buf = _buf;
Amol Jadi5e52d722013-08-19 17:10:33 -0700197
198 ASSERT(buf);
199 ASSERT(len);
200
201 if (fastboot_state == STATE_ERROR)
202 goto oops;
203
204 dprintf(SPEW, "usb_read(): len = %d\n", len);
205
Channagoud Kadabi87823802014-11-05 13:10:05 -0800206 while (len > 0)
Amol Jadi5e52d722013-08-19 17:10:33 -0700207 {
Channagoud Kadabi87823802014-11-05 13:10:05 -0800208 xfer = (len > MAX_USBSS_BULK_SIZE) ? MAX_USBSS_BULK_SIZE : len;
Amol Jadi5e52d722013-08-19 17:10:33 -0700209
Channagoud Kadabi87823802014-11-05 13:10:05 -0800210 req.buf = (void*) PA((addr_t)buf);
211 req.length = xfer;
212 req.complete = req_complete;
Amol Jadi5e52d722013-08-19 17:10:33 -0700213
Channagoud Kadabi87823802014-11-05 13:10:05 -0800214 r = usb30_udc_request_queue(out, &req);
215 if (r < 0)
216 {
217 dprintf(CRITICAL, "usb_read() queue failed. r = %d\n", r);
218 goto oops;
219 }
220 event_wait(&txn_done);
221
222 if (txn_status < 0)
223 {
224 dprintf(CRITICAL, "usb_read() transaction failed. txn_status = %d\n",
225 txn_status);
226 goto oops;
227 }
228
229 count += req.length;
230 buf += req.length;
231 len -= req.length;
232
233 /* note: req.length is update by callback to reflect the amount of data
234 * actually read.
235 */
236 dprintf(SPEW, "usb_read(): DONE. req.length = %d\n\n", req.length);
237
238 /* For USB3.0 if the data transfer is less than MaxpacketSize, its
239 * short packet and DWC layer generates transfer complete. App layer
240 * shold handle this and continue trasnferring the data instead of treating
241 * this as a transfer complete. This case is not applicable for transfers
242 * which involve protocol communication to exchange information whose length
243 * is always equal to MAX_RSP_SIZE. This check ensures that we dont abort
244 * data transfers on short packet.
245 */
246 if (req.length != xfer && trans_len == MAX_RSP_SIZE) break;
247 }
Amol Jadi5e52d722013-08-19 17:10:33 -0700248
249 /* invalidate any cached buf data (controller updates main memory) */
lijuangc2676752018-05-15 13:52:36 +0800250 arch_invalidate_cache_range((addr_t) _buf, ROUNDUP(count, CACHE_LINE));
Amol Jadi5e52d722013-08-19 17:10:33 -0700251
Channagoud Kadabi87823802014-11-05 13:10:05 -0800252 return count;
Amol Jadi5e52d722013-08-19 17:10:33 -0700253
254oops:
255 fastboot_state = STATE_ERROR;
256 dprintf(CRITICAL, "usb_read(): DONE: ERROR: len = %d\n", len);
257 return -1;
258}
259
Amol Jadi7c4316c2013-10-07 14:19:26 -0700260static int usb30_usb_write(void *buf, unsigned len)
Amol Jadi5e52d722013-08-19 17:10:33 -0700261{
262 int r;
263 struct udc_request req;
264
265 ASSERT(buf);
266 ASSERT(len);
267
268 if (fastboot_state == STATE_ERROR)
269 goto oops;
270
271 dprintf(SPEW, "usb_write(): len = %d str = %s\n", len, (char *) buf);
272
273 /* flush buffer to main memory before giving to udc */
274 arch_clean_invalidate_cache_range((addr_t) buf, len);
275
276 req.buf = (void*) PA((addr_t)buf);
277 req.length = len;
278 req.complete = req_complete;
279
Amol Jadi7c4316c2013-10-07 14:19:26 -0700280 r = usb30_udc_request_queue(in, &req);
Amol Jadi5e52d722013-08-19 17:10:33 -0700281 if (r < 0) {
282 dprintf(CRITICAL, "usb_write() queue failed. r = %d\n", r);
283 goto oops;
284 }
285 event_wait(&txn_done);
286
287 dprintf(SPEW, "usb_write(): DONE: len = %d req->length = %d str = %s\n",
288 len, req.length, (char *) buf);
289
290 if (txn_status < 0) {
291 dprintf(CRITICAL, "usb_write() transaction failed. txn_status = %d\n",
292 txn_status);
293 goto oops;
294 }
295
296 return req.length;
297
298oops:
299 fastboot_state = STATE_ERROR;
300 dprintf(CRITICAL, "usb_write(): DONE: ERROR: len = %d\n", len);
301 return -1;
302}
Amol Jadi7c4316c2013-10-07 14:19:26 -0700303#endif
Amol Jadi5e52d722013-08-19 17:10:33 -0700304
Amol Jadi7c4316c2013-10-07 14:19:26 -0700305static int hsusb_usb_read(void *_buf, unsigned len)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800306{
307 int r;
308 unsigned xfer;
309 unsigned char *buf = _buf;
310 int count = 0;
311
312 if (fastboot_state == STATE_ERROR)
313 goto oops;
314
315 while (len > 0) {
Shashank Mittal1cc65b02011-12-20 15:30:17 -0800316 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530317 req->buf = (unsigned char *)PA((addr_t)buf);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800318 req->length = xfer;
319 req->complete = req_complete;
320 r = udc_request_queue(out, req);
321 if (r < 0) {
322 dprintf(INFO, "usb_read() queue failed\n");
323 goto oops;
324 }
325 event_wait(&txn_done);
326
327 if (txn_status < 0) {
328 dprintf(INFO, "usb_read() transaction failed\n");
329 goto oops;
330 }
331
332 count += req->length;
333 buf += req->length;
334 len -= req->length;
335
336 /* short transfer? */
337 if (req->length != xfer) break;
338 }
Hanumant Singh108cdc62012-12-11 16:48:49 -0800339 /*
340 * Force reload of buffer from memory
341 * since transaction is complete now.
342 */
lijuangc2676752018-05-15 13:52:36 +0800343 arch_invalidate_cache_range((addr_t)_buf, ROUNDUP(count, CACHE_LINE));
Brian Swetland9c4c0752009-01-25 16:23:50 -0800344 return count;
345
346oops:
347 fastboot_state = STATE_ERROR;
348 return -1;
349}
350
Amol Jadi7c4316c2013-10-07 14:19:26 -0700351static int hsusb_usb_write(void *buf, unsigned len)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800352{
353 int r;
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700354 uint32_t xfer;
355 unsigned char *_buf = buf;
356 int count = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800357
358 if (fastboot_state == STATE_ERROR)
359 goto oops;
360
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700361 while (len > 0) {
362 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530363 req->buf = (unsigned char *)PA((addr_t)_buf);
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700364 req->length = xfer;
365 req->complete = req_complete;
366 r = udc_request_queue(in, req);
367 if (r < 0) {
368 dprintf(INFO, "usb_write() queue failed\n");
369 goto oops;
370 }
371 event_wait(&txn_done);
372 if (txn_status < 0) {
373 dprintf(INFO, "usb_write() transaction failed\n");
374 goto oops;
375 }
376
377 count += req->length;
378 _buf += req->length;
379 len -= req->length;
380
381 /* short transfer? */
382 if (req->length != xfer) break;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800383 }
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700384
385 return count;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800386
387oops:
388 fastboot_state = STATE_ERROR;
389 return -1;
390}
391
392void fastboot_ack(const char *code, const char *reason)
393{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700394 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800395
396 if (fastboot_state != STATE_COMMAND)
397 return;
398
399 if (reason == 0)
400 reason = "";
401
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530402 snprintf((char *)response, MAX_RSP_SIZE, "%s%s", code, reason);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800403 fastboot_state = STATE_COMPLETE;
404
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530405 usb_if.usb_write(response, strlen((const char *)response));
Brian Swetland9c4c0752009-01-25 16:23:50 -0800406
407}
408
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700409void fastboot_info(const char *reason)
410{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700411 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700412
413 if (fastboot_state != STATE_COMMAND)
414 return;
415
416 if (reason == 0)
417 return;
418
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530419 snprintf((char *)response, MAX_RSP_SIZE, "INFO%s", reason);
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700420
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530421 usb_if.usb_write(response, strlen((const char *)response));
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700422}
423
Brian Swetland9c4c0752009-01-25 16:23:50 -0800424void fastboot_fail(const char *reason)
425{
426 fastboot_ack("FAIL", reason);
427}
428
429void fastboot_okay(const char *info)
430{
431 fastboot_ack("OKAY", info);
432}
433
Channagoud Kadabi03550162015-03-10 13:32:27 -0700434static void getvar_all()
435{
436 struct fastboot_var *var;
Mayank Grover351a75e2017-05-30 20:06:08 +0530437 char getvar_all[256];
Channagoud Kadabi03550162015-03-10 13:32:27 -0700438
439 for (var = varlist; var; var = var->next)
440 {
441 strlcpy((char *) getvar_all, var->name, sizeof(getvar_all));
442 strlcat((char *) getvar_all, ":", sizeof(getvar_all));
443 strlcat((char *) getvar_all, var->value, sizeof(getvar_all));
444 fastboot_info(getvar_all);
445 memset((void *) getvar_all, '\0', sizeof(getvar_all));
446 }
447 fastboot_okay("");
448}
449
Brian Swetland9c4c0752009-01-25 16:23:50 -0800450static void cmd_getvar(const char *arg, void *data, unsigned sz)
451{
452 struct fastboot_var *var;
453
lijuang102dfa92015-10-09 18:31:03 +0800454#if CHECK_BAT_VOLTAGE
455 update_battery_status();
456#endif
457
Mayank Grover351a75e2017-05-30 20:06:08 +0530458
Channagoud Kadabi03550162015-03-10 13:32:27 -0700459 if (!strncmp("all", arg, strlen(arg)))
460 {
461 getvar_all();
462 return;
463 }
464
Brian Swetland9c4c0752009-01-25 16:23:50 -0800465 for (var = varlist; var; var = var->next) {
466 if (!strcmp(var->name, arg)) {
467 fastboot_okay(var->value);
468 return;
469 }
470 }
471 fastboot_okay("");
472}
473
474static void cmd_download(const char *arg, void *data, unsigned sz)
475{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700476 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800477 unsigned len = hex2unsigned(arg);
478 int r;
479
480 download_size = 0;
481 if (len > download_max) {
482 fastboot_fail("data too large");
483 return;
484 }
485
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530486 snprintf((char *)response, MAX_RSP_SIZE, "DATA%08x", len);
487 if (usb_if.usb_write(response, strlen((const char *)response)) < 0)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800488 return;
Channagoud Kadabi5389f372015-02-27 15:26:28 -0800489 /*
490 * Discard the cache contents before starting the download
491 */
lijuangc2676752018-05-15 13:52:36 +0800492 arch_invalidate_cache_range((addr_t) download_base, ROUNDUP(len, CACHE_LINE));
Brian Swetland9c4c0752009-01-25 16:23:50 -0800493
Amol Jadi7c4316c2013-10-07 14:19:26 -0700494 r = usb_if.usb_read(download_base, len);
Greg Griscod6250552011-06-29 14:40:23 -0700495 if ((r < 0) || ((unsigned) r != len)) {
Brian Swetland9c4c0752009-01-25 16:23:50 -0800496 fastboot_state = STATE_ERROR;
497 return;
498 }
499 download_size = len;
500 fastboot_okay("");
501}
502
Parth Dixitf8071f02017-09-27 17:59:30 +0530503int fboot_set_upload(void *buf, uint32_t buf_size)
504{
505 /* sanity checks*/
506 if((buf == NULL)||(buf_size > download_max))
507 {
508 return ERR_INVALID_ARGS;
509 }
510 upload_base_addr = buf;
511 upload_size = buf_size;
512 return NO_ERROR;
513}
514
515static void cmd_upload(const char *arg, void *data, unsigned sz)
516{
517 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
518 unsigned len = upload_size;
519 int r;
520
521 if ((upload_base_addr == NULL)||(upload_size == 0)) {
522 fastboot_fail("invalid data");
523 goto cleanup;
524 }
525 snprintf((char *)response, MAX_RSP_SIZE, "DATA%08x", len);
526 if (usb_if.usb_write(response, strlen((const char *)response)) < 0)
527 goto cleanup;
528 /*
529 * Discard the cache contents before starting the download
530 */
531 arch_invalidate_cache_range((addr_t) upload_base_addr, len);
532
533 r = usb_if.usb_write(upload_base_addr, len);
534 if ((r < 0) || ((unsigned) r != len)) {
535 fastboot_state = STATE_ERROR;
536 goto cleanup;
537 }
538 fastboot_okay("");
539cleanup:
540 upload_base_addr = NULL;
541 upload_size = 0;
542 return;
543}
544
Brian Swetland9c4c0752009-01-25 16:23:50 -0800545static void fastboot_command_loop(void)
546{
547 struct fastboot_cmd *cmd;
548 int r;
lijuangd86b38e2015-10-13 18:13:01 +0800549#if CHECK_BAT_VOLTAGE
550 boolean is_first_erase_flash = false;
551#endif
552
Brian Swetland9c4c0752009-01-25 16:23:50 -0800553 dprintf(INFO,"fastboot: processing commands\n");
554
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700555 uint8_t *buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(4096, CACHE_LINE));
556 if (!buffer)
557 {
558 dprintf(CRITICAL, "Could not allocate memory for fastboot buffer\n.");
559 ASSERT(0);
560 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800561again:
562 while (fastboot_state != STATE_ERROR) {
Amol Jadi5edf3552013-07-23 14:15:34 -0700563
564 /* Read buffer must be cleared first. If buffer is not cleared,
565 * the original data in buf trailing the received command is
566 * interpreted as part of the command.
567 */
568 memset(buffer, 0, MAX_RSP_SIZE);
569 arch_clean_invalidate_cache_range((addr_t) buffer, MAX_RSP_SIZE);
570
Amol Jadi7c4316c2013-10-07 14:19:26 -0700571 r = usb_if.usb_read(buffer, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800572 if (r < 0) break;
573 buffer[r] = 0;
574 dprintf(INFO,"fastboot: %s\n", buffer);
575
lijuangd86b38e2015-10-13 18:13:01 +0800576#if CHECK_BAT_VOLTAGE
577 /* check battery voltage before erase or flash image */
578 if (!strncmp((const char*) buffer, "getvar:partition-type", 21))
579 is_first_erase_flash = true;
580
581 if (is_first_erase_flash) {
582 if (!strncmp((const char*) buffer, "erase", 5) ||
583 !strncmp((const char*) buffer, "flash", 5)) {
584 if (!target_battery_soc_ok()) {
585 dprintf(INFO,"fastboot: battery voltage: %d\n",
586 target_get_battery_voltage());
587 fastboot_fail("Warning: battery's capacity is very low\n");
Mayank Grover3f5f97c2017-09-26 11:48:50 +0530588 continue;
lijuangd86b38e2015-10-13 18:13:01 +0800589 }
590 }
591 }
592#endif
593
Channagoud Kadabi69c16732013-12-05 17:29:18 -0800594 fastboot_state = STATE_COMMAND;
595
Brian Swetland9c4c0752009-01-25 16:23:50 -0800596 for (cmd = cmdlist; cmd; cmd = cmd->next) {
597 if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
598 continue;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800599 cmd->handle((const char*) buffer + cmd->prefix_len,
600 (void*) download_base, download_size);
601 if (fastboot_state == STATE_COMMAND)
602 fastboot_fail("unknown reason");
lijuangd86b38e2015-10-13 18:13:01 +0800603
604#if CHECK_BAT_VOLTAGE
605 if (!strncmp((const char*) buffer, "erase", 5) ||
606 !strncmp((const char*) buffer, "flash", 5)) {
607 if (is_first_erase_flash) {
608 is_first_erase_flash = false;
609 }
610 }
611#endif
Brian Swetland9c4c0752009-01-25 16:23:50 -0800612 goto again;
613 }
614
615 fastboot_fail("unknown command");
Amol Jadi5edf3552013-07-23 14:15:34 -0700616
Brian Swetland9c4c0752009-01-25 16:23:50 -0800617 }
618 fastboot_state = STATE_OFFLINE;
619 dprintf(INFO,"fastboot: oops!\n");
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700620 free(buffer);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800621}
622
623static int fastboot_handler(void *arg)
624{
625 for (;;) {
626 event_wait(&usb_online);
627 fastboot_command_loop();
628 }
629 return 0;
630}
631
632static void fastboot_notify(struct udc_gadget *gadget, unsigned event)
633{
634 if (event == UDC_EVENT_ONLINE) {
635 event_signal(&usb_online, 0);
636 }
637}
638
Brian Swetland9c4c0752009-01-25 16:23:50 -0800639int fastboot_init(void *base, unsigned size)
640{
Amol Jadi5edf3552013-07-23 14:15:34 -0700641 char sn_buf[13];
Brian Swetland9c4c0752009-01-25 16:23:50 -0800642 thread_t *thr;
643 dprintf(INFO, "fastboot_init()\n");
644
645 download_base = base;
646 download_max = size;
647
Amol Jadi5edf3552013-07-23 14:15:34 -0700648 /* target specific initialization before going into fastboot. */
649 target_fastboot_init();
650
651 /* setup serialno */
652 target_serialno((unsigned char *) sn_buf);
653 dprintf(SPEW,"serial number: %s\n",sn_buf);
654 surf_udc_device.serialno = sn_buf;
655
Amol Jadi7c4316c2013-10-07 14:19:26 -0700656 if(!strcmp(target_usb_controller(), "dwc"))
657 {
658#ifdef USB30_SUPPORT
Channagoud Kadabi728ef0a2014-02-04 17:11:08 -0800659 surf_udc_device.t_usb_if = target_usb30_init();
660
Amol Jadi7c4316c2013-10-07 14:19:26 -0700661 /* initialize udc functions to use dwc controller */
662 usb_if.udc_init = usb30_udc_init;
663 usb_if.udc_register_gadget = usb30_udc_register_gadget;
664 usb_if.udc_start = usb30_udc_start;
665 usb_if.udc_stop = usb30_udc_stop;
666
667 usb_if.udc_endpoint_alloc = usb30_udc_endpoint_alloc;
668 usb_if.udc_request_alloc = usb30_udc_request_alloc;
669 usb_if.udc_request_free = usb30_udc_request_free;
670
671 usb_if.usb_read = usb30_usb_read;
672 usb_if.usb_write = usb30_usb_write;
673#else
674 dprintf(CRITICAL, "USB30 needs to be enabled for this target.\n");
675 ASSERT(0);
676#endif
677 }
678 else
679 {
680 /* initialize udc functions to use the default chipidea controller */
681 usb_if.udc_init = udc_init;
682 usb_if.udc_register_gadget = udc_register_gadget;
683 usb_if.udc_start = udc_start;
684 usb_if.udc_stop = udc_stop;
685
686 usb_if.udc_endpoint_alloc = udc_endpoint_alloc;
687 usb_if.udc_request_alloc = udc_request_alloc;
688 usb_if.udc_request_free = udc_request_free;
689
690 usb_if.usb_read = hsusb_usb_read;
691 usb_if.usb_write = hsusb_usb_write;
692 }
693
Amol Jadi5edf3552013-07-23 14:15:34 -0700694 /* register udc device */
Amol Jadi7c4316c2013-10-07 14:19:26 -0700695 usb_if.udc_init(&surf_udc_device);
Amol Jadi5edf3552013-07-23 14:15:34 -0700696
Brian Swetland9c4c0752009-01-25 16:23:50 -0800697 event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);
698 event_init(&txn_done, 0, EVENT_FLAG_AUTOUNSIGNAL);
699
Amol Jadi7c4316c2013-10-07 14:19:26 -0700700 in = usb_if.udc_endpoint_alloc(UDC_TYPE_BULK_IN, 512);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800701 if (!in)
702 goto fail_alloc_in;
Amol Jadi7c4316c2013-10-07 14:19:26 -0700703 out = usb_if.udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800704 if (!out)
705 goto fail_alloc_out;
706
707 fastboot_endpoints[0] = in;
708 fastboot_endpoints[1] = out;
709
Amol Jadi7c4316c2013-10-07 14:19:26 -0700710 req = usb_if.udc_request_alloc();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800711 if (!req)
712 goto fail_alloc_req;
713
Amol Jadi5edf3552013-07-23 14:15:34 -0700714 /* register gadget */
Amol Jadi7c4316c2013-10-07 14:19:26 -0700715 if (usb_if.udc_register_gadget(&fastboot_gadget))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800716 goto fail_udc_register;
717
718 fastboot_register("getvar:", cmd_getvar);
719 fastboot_register("download:", cmd_download);
Parth Dixitf8071f02017-09-27 17:59:30 +0530720 fastboot_register("upload", cmd_upload);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800721 fastboot_publish("version", "0.5");
722
Mayank Groverc19c2e52017-12-19 14:43:23 +0530723 thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
neetid32ba8472011-12-07 16:34:06 -0800724 if (!thr)
725 {
726 goto fail_alloc_in;
727 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800728 thread_resume(thr);
Amol Jadi5edf3552013-07-23 14:15:34 -0700729
Amol Jadi7c4316c2013-10-07 14:19:26 -0700730 usb_if.udc_start();
Amol Jadi5edf3552013-07-23 14:15:34 -0700731
Brian Swetland9c4c0752009-01-25 16:23:50 -0800732 return 0;
733
734fail_udc_register:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700735 usb_if.udc_request_free(req);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800736fail_alloc_req:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700737 usb_if.udc_endpoint_free(out);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800738fail_alloc_out:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700739 usb_if.udc_endpoint_free(in);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800740fail_alloc_in:
741 return -1;
742}
Amol Jadi7c4316c2013-10-07 14:19:26 -0700743
744void fastboot_stop(void)
745{
746 usb_if.udc_stop();
747}