blob: 6aea42a8a7a7f1069b3dff111a56cc28923c55b6 [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>
tracychuid184b912020-06-05 17:31:38 +080041/*[20200605][TracyChui] Implement get Serial Number start*/
42#include <devinfo.h>
43/*[20200605][TracyChui] Implement get Serial Number end*/
Brian Swetland9c4c0752009-01-25 16:23:50 -080044
Amol Jadi7c4316c2013-10-07 14:19:26 -070045#ifdef USB30_SUPPORT
46#include <usb30_udc.h>
47#endif
48
49typedef struct
50{
51 int (*udc_init)(struct udc_device *devinfo);
52 int (*udc_register_gadget)(struct udc_gadget *gadget);
53 int (*udc_start)(void);
54 int (*udc_stop)(void);
55
56 struct udc_endpoint *(*udc_endpoint_alloc)(unsigned type, unsigned maxpkt);
57 void (*udc_endpoint_free)(struct udc_endpoint *ept);
58 struct udc_request *(*udc_request_alloc)(void);
59 void (*udc_request_free)(struct udc_request *req);
60
61 int (*usb_read)(void *buf, unsigned len);
62 int (*usb_write)(void *buf, unsigned len);
63} usb_controller_interface_t;
64
65usb_controller_interface_t usb_if;
66
Hanumant Singh108cdc62012-12-11 16:48:49 -080067#define MAX_USBFS_BULK_SIZE (32 * 1024)
Channagoud Kadabi87823802014-11-05 13:10:05 -080068#define MAX_USBSS_BULK_SIZE (0x1000000)
Shashank Mittal6a5609f2011-08-04 15:51:59 -070069
Brian Swetland9c4c0752009-01-25 16:23:50 -080070void boot_linux(void *bootimg, unsigned sz);
Amol Jadi5edf3552013-07-23 14:15:34 -070071static void fastboot_notify(struct udc_gadget *gadget, unsigned event);
72static struct udc_endpoint *fastboot_endpoints[2];
73
74static struct udc_device surf_udc_device = {
75 .vendor_id = 0x18d1,
76 .product_id = 0xD00D,
77 .version_id = 0x0100,
78 .manufacturer = "Google",
79 .product = "Android",
80};
81
82static struct udc_gadget fastboot_gadget = {
83 .notify = fastboot_notify,
84 .ifc_class = 0xff,
85 .ifc_subclass = 0x42,
86 .ifc_protocol = 0x03,
87 .ifc_endpoints = 2,
88 .ifc_string = "fastboot",
89 .ept = fastboot_endpoints,
90};
Brian Swetland9c4c0752009-01-25 16:23:50 -080091
92/* todo: give lk strtoul and nuke this */
93static unsigned hex2unsigned(const char *x)
94{
95 unsigned n = 0;
96
97 while(*x) {
98 switch(*x) {
99 case '0': case '1': case '2': case '3': case '4':
100 case '5': case '6': case '7': case '8': case '9':
101 n = (n << 4) | (*x - '0');
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 case 'A': case 'B': case 'C':
108 case 'D': case 'E': case 'F':
109 n = (n << 4) | (*x - 'A' + 10);
110 break;
111 default:
112 return n;
113 }
114 x++;
115 }
116
117 return n;
118}
119
120struct fastboot_cmd {
121 struct fastboot_cmd *next;
122 const char *prefix;
123 unsigned prefix_len;
124 void (*handle)(const char *arg, void *data, unsigned sz);
125};
126
127struct fastboot_var {
128 struct fastboot_var *next;
129 const char *name;
130 const char *value;
131};
Amol Jadi5edf3552013-07-23 14:15:34 -0700132
Brian Swetland9c4c0752009-01-25 16:23:50 -0800133static struct fastboot_cmd *cmdlist;
134
135void fastboot_register(const char *prefix,
136 void (*handle)(const char *arg, void *data, unsigned sz))
137{
138 struct fastboot_cmd *cmd;
139 cmd = malloc(sizeof(*cmd));
140 if (cmd) {
141 cmd->prefix = prefix;
142 cmd->prefix_len = strlen(prefix);
143 cmd->handle = handle;
144 cmd->next = cmdlist;
145 cmdlist = cmd;
146 }
147}
148
149static struct fastboot_var *varlist;
150
151void fastboot_publish(const char *name, const char *value)
152{
153 struct fastboot_var *var;
154 var = malloc(sizeof(*var));
155 if (var) {
156 var->name = name;
157 var->value = value;
158 var->next = varlist;
159 varlist = var;
160 }
161}
162
163
164static event_t usb_online;
165static event_t txn_done;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800166static struct udc_endpoint *in, *out;
167static struct udc_request *req;
168int txn_status;
169
170static void *download_base;
171static unsigned download_max;
172static unsigned download_size;
Parth Dixitf8071f02017-09-27 17:59:30 +0530173static void *upload_base_addr;
174static unsigned upload_size;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800175
176#define STATE_OFFLINE 0
177#define STATE_COMMAND 1
178#define STATE_COMPLETE 2
179#define STATE_ERROR 3
180
181static unsigned fastboot_state = STATE_OFFLINE;
182
183static void req_complete(struct udc_request *req, unsigned actual, int status)
184{
185 txn_status = status;
186 req->length = actual;
Hanumant Singh108cdc62012-12-11 16:48:49 -0800187
Brian Swetland9c4c0752009-01-25 16:23:50 -0800188 event_signal(&txn_done, 0);
189}
190
Amol Jadi5e52d722013-08-19 17:10:33 -0700191#ifdef USB30_SUPPORT
Channagoud Kadabi87823802014-11-05 13:10:05 -0800192static int usb30_usb_read(void *_buf, unsigned len)
Amol Jadi5e52d722013-08-19 17:10:33 -0700193{
194 int r;
195 struct udc_request req;
Channagoud Kadabi87823802014-11-05 13:10:05 -0800196 uint32_t xfer;
197 int count = 0;
198 uint32_t trans_len = len;
199 const char *buf = _buf;
Amol Jadi5e52d722013-08-19 17:10:33 -0700200
201 ASSERT(buf);
202 ASSERT(len);
203
204 if (fastboot_state == STATE_ERROR)
205 goto oops;
206
207 dprintf(SPEW, "usb_read(): len = %d\n", len);
208
Channagoud Kadabi87823802014-11-05 13:10:05 -0800209 while (len > 0)
Amol Jadi5e52d722013-08-19 17:10:33 -0700210 {
Channagoud Kadabi87823802014-11-05 13:10:05 -0800211 xfer = (len > MAX_USBSS_BULK_SIZE) ? MAX_USBSS_BULK_SIZE : len;
Amol Jadi5e52d722013-08-19 17:10:33 -0700212
Channagoud Kadabi87823802014-11-05 13:10:05 -0800213 req.buf = (void*) PA((addr_t)buf);
214 req.length = xfer;
215 req.complete = req_complete;
Amol Jadi5e52d722013-08-19 17:10:33 -0700216
Channagoud Kadabi87823802014-11-05 13:10:05 -0800217 r = usb30_udc_request_queue(out, &req);
218 if (r < 0)
219 {
220 dprintf(CRITICAL, "usb_read() queue failed. r = %d\n", r);
221 goto oops;
222 }
223 event_wait(&txn_done);
224
225 if (txn_status < 0)
226 {
227 dprintf(CRITICAL, "usb_read() transaction failed. txn_status = %d\n",
228 txn_status);
229 goto oops;
230 }
231
232 count += req.length;
233 buf += req.length;
234 len -= req.length;
235
236 /* note: req.length is update by callback to reflect the amount of data
237 * actually read.
238 */
239 dprintf(SPEW, "usb_read(): DONE. req.length = %d\n\n", req.length);
240
241 /* For USB3.0 if the data transfer is less than MaxpacketSize, its
242 * short packet and DWC layer generates transfer complete. App layer
243 * shold handle this and continue trasnferring the data instead of treating
244 * this as a transfer complete. This case is not applicable for transfers
245 * which involve protocol communication to exchange information whose length
246 * is always equal to MAX_RSP_SIZE. This check ensures that we dont abort
247 * data transfers on short packet.
248 */
249 if (req.length != xfer && trans_len == MAX_RSP_SIZE) break;
250 }
Amol Jadi5e52d722013-08-19 17:10:33 -0700251
252 /* invalidate any cached buf data (controller updates main memory) */
lijuangc2676752018-05-15 13:52:36 +0800253 arch_invalidate_cache_range((addr_t) _buf, ROUNDUP(count, CACHE_LINE));
Amol Jadi5e52d722013-08-19 17:10:33 -0700254
Channagoud Kadabi87823802014-11-05 13:10:05 -0800255 return count;
Amol Jadi5e52d722013-08-19 17:10:33 -0700256
257oops:
258 fastboot_state = STATE_ERROR;
259 dprintf(CRITICAL, "usb_read(): DONE: ERROR: len = %d\n", len);
260 return -1;
261}
262
Amol Jadi7c4316c2013-10-07 14:19:26 -0700263static int usb30_usb_write(void *buf, unsigned len)
Amol Jadi5e52d722013-08-19 17:10:33 -0700264{
265 int r;
266 struct udc_request req;
267
268 ASSERT(buf);
269 ASSERT(len);
270
271 if (fastboot_state == STATE_ERROR)
272 goto oops;
273
274 dprintf(SPEW, "usb_write(): len = %d str = %s\n", len, (char *) buf);
275
276 /* flush buffer to main memory before giving to udc */
277 arch_clean_invalidate_cache_range((addr_t) buf, len);
278
279 req.buf = (void*) PA((addr_t)buf);
280 req.length = len;
281 req.complete = req_complete;
282
Amol Jadi7c4316c2013-10-07 14:19:26 -0700283 r = usb30_udc_request_queue(in, &req);
Amol Jadi5e52d722013-08-19 17:10:33 -0700284 if (r < 0) {
285 dprintf(CRITICAL, "usb_write() queue failed. r = %d\n", r);
286 goto oops;
287 }
288 event_wait(&txn_done);
289
290 dprintf(SPEW, "usb_write(): DONE: len = %d req->length = %d str = %s\n",
291 len, req.length, (char *) buf);
292
293 if (txn_status < 0) {
294 dprintf(CRITICAL, "usb_write() transaction failed. txn_status = %d\n",
295 txn_status);
296 goto oops;
297 }
298
299 return req.length;
300
301oops:
302 fastboot_state = STATE_ERROR;
303 dprintf(CRITICAL, "usb_write(): DONE: ERROR: len = %d\n", len);
304 return -1;
305}
Amol Jadi7c4316c2013-10-07 14:19:26 -0700306#endif
Amol Jadi5e52d722013-08-19 17:10:33 -0700307
Amol Jadi7c4316c2013-10-07 14:19:26 -0700308static int hsusb_usb_read(void *_buf, unsigned len)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800309{
310 int r;
311 unsigned xfer;
312 unsigned char *buf = _buf;
313 int count = 0;
314
315 if (fastboot_state == STATE_ERROR)
316 goto oops;
317
318 while (len > 0) {
Shashank Mittal1cc65b02011-12-20 15:30:17 -0800319 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530320 req->buf = (unsigned char *)PA((addr_t)buf);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800321 req->length = xfer;
322 req->complete = req_complete;
323 r = udc_request_queue(out, req);
324 if (r < 0) {
325 dprintf(INFO, "usb_read() queue failed\n");
326 goto oops;
327 }
328 event_wait(&txn_done);
329
330 if (txn_status < 0) {
331 dprintf(INFO, "usb_read() transaction failed\n");
332 goto oops;
333 }
334
335 count += req->length;
336 buf += req->length;
337 len -= req->length;
338
339 /* short transfer? */
340 if (req->length != xfer) break;
341 }
Hanumant Singh108cdc62012-12-11 16:48:49 -0800342 /*
343 * Force reload of buffer from memory
344 * since transaction is complete now.
345 */
lijuangc2676752018-05-15 13:52:36 +0800346 arch_invalidate_cache_range((addr_t)_buf, ROUNDUP(count, CACHE_LINE));
Brian Swetland9c4c0752009-01-25 16:23:50 -0800347 return count;
348
349oops:
350 fastboot_state = STATE_ERROR;
351 return -1;
352}
353
Amol Jadi7c4316c2013-10-07 14:19:26 -0700354static int hsusb_usb_write(void *buf, unsigned len)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800355{
356 int r;
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700357 uint32_t xfer;
358 unsigned char *_buf = buf;
359 int count = 0;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800360
361 if (fastboot_state == STATE_ERROR)
362 goto oops;
363
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700364 while (len > 0) {
365 xfer = (len > MAX_USBFS_BULK_SIZE) ? MAX_USBFS_BULK_SIZE : len;
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530366 req->buf = (unsigned char *)PA((addr_t)_buf);
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700367 req->length = xfer;
368 req->complete = req_complete;
369 r = udc_request_queue(in, req);
370 if (r < 0) {
371 dprintf(INFO, "usb_write() queue failed\n");
372 goto oops;
373 }
374 event_wait(&txn_done);
375 if (txn_status < 0) {
376 dprintf(INFO, "usb_write() transaction failed\n");
377 goto oops;
378 }
379
380 count += req->length;
381 _buf += req->length;
382 len -= req->length;
383
384 /* short transfer? */
385 if (req->length != xfer) break;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800386 }
Channagoud Kadabiad50b6a2014-04-07 17:56:05 -0700387
388 return count;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800389
390oops:
391 fastboot_state = STATE_ERROR;
392 return -1;
393}
394
395void fastboot_ack(const char *code, const char *reason)
396{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700397 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800398
399 if (fastboot_state != STATE_COMMAND)
400 return;
401
402 if (reason == 0)
403 reason = "";
404
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530405 snprintf((char *)response, MAX_RSP_SIZE, "%s%s", code, reason);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800406 fastboot_state = STATE_COMPLETE;
407
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530408 usb_if.usb_write(response, strlen((const char *)response));
Brian Swetland9c4c0752009-01-25 16:23:50 -0800409
410}
411
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700412void fastboot_info(const char *reason)
413{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700414 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700415
416 if (fastboot_state != STATE_COMMAND)
417 return;
418
419 if (reason == 0)
420 return;
421
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530422 snprintf((char *)response, MAX_RSP_SIZE, "INFO%s", reason);
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700423
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530424 usb_if.usb_write(response, strlen((const char *)response));
Shashank Mittal6a5609f2011-08-04 15:51:59 -0700425}
426
Brian Swetland9c4c0752009-01-25 16:23:50 -0800427void fastboot_fail(const char *reason)
428{
429 fastboot_ack("FAIL", reason);
430}
431
432void fastboot_okay(const char *info)
433{
434 fastboot_ack("OKAY", info);
435}
436
Channagoud Kadabi03550162015-03-10 13:32:27 -0700437static void getvar_all()
438{
439 struct fastboot_var *var;
Mayank Grover351a75e2017-05-30 20:06:08 +0530440 char getvar_all[256];
Channagoud Kadabi03550162015-03-10 13:32:27 -0700441
442 for (var = varlist; var; var = var->next)
443 {
444 strlcpy((char *) getvar_all, var->name, sizeof(getvar_all));
445 strlcat((char *) getvar_all, ":", sizeof(getvar_all));
446 strlcat((char *) getvar_all, var->value, sizeof(getvar_all));
447 fastboot_info(getvar_all);
448 memset((void *) getvar_all, '\0', sizeof(getvar_all));
449 }
450 fastboot_okay("");
451}
452
Brian Swetland9c4c0752009-01-25 16:23:50 -0800453static void cmd_getvar(const char *arg, void *data, unsigned sz)
454{
455 struct fastboot_var *var;
456
lijuang102dfa92015-10-09 18:31:03 +0800457#if CHECK_BAT_VOLTAGE
458 update_battery_status();
459#endif
460
Mayank Grover351a75e2017-05-30 20:06:08 +0530461
Channagoud Kadabi03550162015-03-10 13:32:27 -0700462 if (!strncmp("all", arg, strlen(arg)))
463 {
464 getvar_all();
465 return;
466 }
467
Brian Swetland9c4c0752009-01-25 16:23:50 -0800468 for (var = varlist; var; var = var->next) {
469 if (!strcmp(var->name, arg)) {
470 fastboot_okay(var->value);
471 return;
472 }
473 }
474 fastboot_okay("");
475}
476
477static void cmd_download(const char *arg, void *data, unsigned sz)
478{
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700479 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800480 unsigned len = hex2unsigned(arg);
481 int r;
482
483 download_size = 0;
484 if (len > download_max) {
485 fastboot_fail("data too large");
486 return;
487 }
488
Unnati Gandhi0c8e7c52014-07-17 14:33:09 +0530489 snprintf((char *)response, MAX_RSP_SIZE, "DATA%08x", len);
490 if (usb_if.usb_write(response, strlen((const char *)response)) < 0)
Brian Swetland9c4c0752009-01-25 16:23:50 -0800491 return;
Channagoud Kadabi5389f372015-02-27 15:26:28 -0800492 /*
493 * Discard the cache contents before starting the download
494 */
lijuangc2676752018-05-15 13:52:36 +0800495 arch_invalidate_cache_range((addr_t) download_base, ROUNDUP(len, CACHE_LINE));
Brian Swetland9c4c0752009-01-25 16:23:50 -0800496
Amol Jadi7c4316c2013-10-07 14:19:26 -0700497 r = usb_if.usb_read(download_base, len);
Greg Griscod6250552011-06-29 14:40:23 -0700498 if ((r < 0) || ((unsigned) r != len)) {
Brian Swetland9c4c0752009-01-25 16:23:50 -0800499 fastboot_state = STATE_ERROR;
500 return;
501 }
502 download_size = len;
503 fastboot_okay("");
504}
505
Parth Dixitf8071f02017-09-27 17:59:30 +0530506int fboot_set_upload(void *buf, uint32_t buf_size)
507{
508 /* sanity checks*/
509 if((buf == NULL)||(buf_size > download_max))
510 {
511 return ERR_INVALID_ARGS;
512 }
513 upload_base_addr = buf;
514 upload_size = buf_size;
515 return NO_ERROR;
516}
517
518static void cmd_upload(const char *arg, void *data, unsigned sz)
519{
520 STACKBUF_DMA_ALIGN(response, MAX_RSP_SIZE);
521 unsigned len = upload_size;
522 int r;
523
524 if ((upload_base_addr == NULL)||(upload_size == 0)) {
525 fastboot_fail("invalid data");
526 goto cleanup;
527 }
528 snprintf((char *)response, MAX_RSP_SIZE, "DATA%08x", len);
529 if (usb_if.usb_write(response, strlen((const char *)response)) < 0)
530 goto cleanup;
531 /*
532 * Discard the cache contents before starting the download
533 */
534 arch_invalidate_cache_range((addr_t) upload_base_addr, len);
535
536 r = usb_if.usb_write(upload_base_addr, len);
537 if ((r < 0) || ((unsigned) r != len)) {
538 fastboot_state = STATE_ERROR;
539 goto cleanup;
540 }
541 fastboot_okay("");
542cleanup:
543 upload_base_addr = NULL;
544 upload_size = 0;
545 return;
546}
547
Brian Swetland9c4c0752009-01-25 16:23:50 -0800548static void fastboot_command_loop(void)
549{
550 struct fastboot_cmd *cmd;
551 int r;
lijuangd86b38e2015-10-13 18:13:01 +0800552#if CHECK_BAT_VOLTAGE
553 boolean is_first_erase_flash = false;
554#endif
555
Brian Swetland9c4c0752009-01-25 16:23:50 -0800556 dprintf(INFO,"fastboot: processing commands\n");
557
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700558 uint8_t *buffer = (uint8_t *)memalign(CACHE_LINE, ROUNDUP(4096, CACHE_LINE));
559 if (!buffer)
560 {
561 dprintf(CRITICAL, "Could not allocate memory for fastboot buffer\n.");
562 ASSERT(0);
563 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800564again:
565 while (fastboot_state != STATE_ERROR) {
Amol Jadi5edf3552013-07-23 14:15:34 -0700566
567 /* Read buffer must be cleared first. If buffer is not cleared,
568 * the original data in buf trailing the received command is
569 * interpreted as part of the command.
570 */
571 memset(buffer, 0, MAX_RSP_SIZE);
572 arch_clean_invalidate_cache_range((addr_t) buffer, MAX_RSP_SIZE);
573
Amol Jadi7c4316c2013-10-07 14:19:26 -0700574 r = usb_if.usb_read(buffer, MAX_RSP_SIZE);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800575 if (r < 0) break;
576 buffer[r] = 0;
577 dprintf(INFO,"fastboot: %s\n", buffer);
578
lijuangd86b38e2015-10-13 18:13:01 +0800579#if CHECK_BAT_VOLTAGE
580 /* check battery voltage before erase or flash image */
581 if (!strncmp((const char*) buffer, "getvar:partition-type", 21))
582 is_first_erase_flash = true;
583
584 if (is_first_erase_flash) {
585 if (!strncmp((const char*) buffer, "erase", 5) ||
586 !strncmp((const char*) buffer, "flash", 5)) {
587 if (!target_battery_soc_ok()) {
588 dprintf(INFO,"fastboot: battery voltage: %d\n",
589 target_get_battery_voltage());
590 fastboot_fail("Warning: battery's capacity is very low\n");
Mayank Grover3f5f97c2017-09-26 11:48:50 +0530591 continue;
lijuangd86b38e2015-10-13 18:13:01 +0800592 }
593 }
594 }
595#endif
596
Channagoud Kadabi69c16732013-12-05 17:29:18 -0800597 fastboot_state = STATE_COMMAND;
598
Brian Swetland9c4c0752009-01-25 16:23:50 -0800599 for (cmd = cmdlist; cmd; cmd = cmd->next) {
600 if (memcmp(buffer, cmd->prefix, cmd->prefix_len))
601 continue;
Brian Swetland9c4c0752009-01-25 16:23:50 -0800602 cmd->handle((const char*) buffer + cmd->prefix_len,
603 (void*) download_base, download_size);
604 if (fastboot_state == STATE_COMMAND)
605 fastboot_fail("unknown reason");
lijuangd86b38e2015-10-13 18:13:01 +0800606
607#if CHECK_BAT_VOLTAGE
608 if (!strncmp((const char*) buffer, "erase", 5) ||
609 !strncmp((const char*) buffer, "flash", 5)) {
610 if (is_first_erase_flash) {
611 is_first_erase_flash = false;
612 }
613 }
614#endif
Brian Swetland9c4c0752009-01-25 16:23:50 -0800615 goto again;
616 }
617
618 fastboot_fail("unknown command");
Amol Jadi5edf3552013-07-23 14:15:34 -0700619
Brian Swetland9c4c0752009-01-25 16:23:50 -0800620 }
621 fastboot_state = STATE_OFFLINE;
622 dprintf(INFO,"fastboot: oops!\n");
Deepa Dinamani26bc2d32013-03-15 13:17:16 -0700623 free(buffer);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800624}
625
626static int fastboot_handler(void *arg)
627{
628 for (;;) {
629 event_wait(&usb_online);
630 fastboot_command_loop();
631 }
632 return 0;
633}
634
635static void fastboot_notify(struct udc_gadget *gadget, unsigned event)
636{
637 if (event == UDC_EVENT_ONLINE) {
638 event_signal(&usb_online, 0);
639 }
640}
641
Brian Swetland9c4c0752009-01-25 16:23:50 -0800642int fastboot_init(void *base, unsigned size)
643{
tracychuid184b912020-06-05 17:31:38 +0800644/*[20200605][TracyChui] Implement get Serial Number start*/
645#if defined(ENABLE_PRODINFO_ACCESS)
646 char sn_buf[PRODINFO_MAX_ISN_LEN + 1];
647#else
Amol Jadi5edf3552013-07-23 14:15:34 -0700648 char sn_buf[13];
tracychuid184b912020-06-05 17:31:38 +0800649#endif
650/*[20200605][TracyChui] Implement get Serial Number end*/
Brian Swetland9c4c0752009-01-25 16:23:50 -0800651 thread_t *thr;
652 dprintf(INFO, "fastboot_init()\n");
653
654 download_base = base;
655 download_max = size;
656
Amol Jadi5edf3552013-07-23 14:15:34 -0700657 /* target specific initialization before going into fastboot. */
658 target_fastboot_init();
659
660 /* setup serialno */
661 target_serialno((unsigned char *) sn_buf);
662 dprintf(SPEW,"serial number: %s\n",sn_buf);
663 surf_udc_device.serialno = sn_buf;
664
Amol Jadi7c4316c2013-10-07 14:19:26 -0700665 if(!strcmp(target_usb_controller(), "dwc"))
666 {
667#ifdef USB30_SUPPORT
Channagoud Kadabi728ef0a2014-02-04 17:11:08 -0800668 surf_udc_device.t_usb_if = target_usb30_init();
669
Amol Jadi7c4316c2013-10-07 14:19:26 -0700670 /* initialize udc functions to use dwc controller */
671 usb_if.udc_init = usb30_udc_init;
672 usb_if.udc_register_gadget = usb30_udc_register_gadget;
673 usb_if.udc_start = usb30_udc_start;
674 usb_if.udc_stop = usb30_udc_stop;
675
676 usb_if.udc_endpoint_alloc = usb30_udc_endpoint_alloc;
677 usb_if.udc_request_alloc = usb30_udc_request_alloc;
678 usb_if.udc_request_free = usb30_udc_request_free;
679
680 usb_if.usb_read = usb30_usb_read;
681 usb_if.usb_write = usb30_usb_write;
682#else
683 dprintf(CRITICAL, "USB30 needs to be enabled for this target.\n");
684 ASSERT(0);
685#endif
686 }
687 else
688 {
689 /* initialize udc functions to use the default chipidea controller */
690 usb_if.udc_init = udc_init;
691 usb_if.udc_register_gadget = udc_register_gadget;
692 usb_if.udc_start = udc_start;
693 usb_if.udc_stop = udc_stop;
694
695 usb_if.udc_endpoint_alloc = udc_endpoint_alloc;
696 usb_if.udc_request_alloc = udc_request_alloc;
697 usb_if.udc_request_free = udc_request_free;
698
699 usb_if.usb_read = hsusb_usb_read;
700 usb_if.usb_write = hsusb_usb_write;
701 }
702
Amol Jadi5edf3552013-07-23 14:15:34 -0700703 /* register udc device */
Amol Jadi7c4316c2013-10-07 14:19:26 -0700704 usb_if.udc_init(&surf_udc_device);
Amol Jadi5edf3552013-07-23 14:15:34 -0700705
Brian Swetland9c4c0752009-01-25 16:23:50 -0800706 event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);
707 event_init(&txn_done, 0, EVENT_FLAG_AUTOUNSIGNAL);
708
Amol Jadi7c4316c2013-10-07 14:19:26 -0700709 in = usb_if.udc_endpoint_alloc(UDC_TYPE_BULK_IN, 512);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800710 if (!in)
711 goto fail_alloc_in;
Amol Jadi7c4316c2013-10-07 14:19:26 -0700712 out = usb_if.udc_endpoint_alloc(UDC_TYPE_BULK_OUT, 512);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800713 if (!out)
714 goto fail_alloc_out;
715
716 fastboot_endpoints[0] = in;
717 fastboot_endpoints[1] = out;
718
Amol Jadi7c4316c2013-10-07 14:19:26 -0700719 req = usb_if.udc_request_alloc();
Brian Swetland9c4c0752009-01-25 16:23:50 -0800720 if (!req)
721 goto fail_alloc_req;
722
Amol Jadi5edf3552013-07-23 14:15:34 -0700723 /* register gadget */
Amol Jadi7c4316c2013-10-07 14:19:26 -0700724 if (usb_if.udc_register_gadget(&fastboot_gadget))
Brian Swetland9c4c0752009-01-25 16:23:50 -0800725 goto fail_udc_register;
726
727 fastboot_register("getvar:", cmd_getvar);
728 fastboot_register("download:", cmd_download);
Parth Dixitf8071f02017-09-27 17:59:30 +0530729 fastboot_register("upload", cmd_upload);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800730 fastboot_publish("version", "0.5");
731
Mayank Groverc19c2e52017-12-19 14:43:23 +0530732 thr = thread_create("fastboot", fastboot_handler, 0, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
neetid32ba8472011-12-07 16:34:06 -0800733 if (!thr)
734 {
735 goto fail_alloc_in;
736 }
Brian Swetland9c4c0752009-01-25 16:23:50 -0800737 thread_resume(thr);
Amol Jadi5edf3552013-07-23 14:15:34 -0700738
Amol Jadi7c4316c2013-10-07 14:19:26 -0700739 usb_if.udc_start();
Amol Jadi5edf3552013-07-23 14:15:34 -0700740
Brian Swetland9c4c0752009-01-25 16:23:50 -0800741 return 0;
742
743fail_udc_register:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700744 usb_if.udc_request_free(req);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800745fail_alloc_req:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700746 usb_if.udc_endpoint_free(out);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800747fail_alloc_out:
Amol Jadi7c4316c2013-10-07 14:19:26 -0700748 usb_if.udc_endpoint_free(in);
Brian Swetland9c4c0752009-01-25 16:23:50 -0800749fail_alloc_in:
750 return -1;
751}
Amol Jadi7c4316c2013-10-07 14:19:26 -0700752
753void fastboot_stop(void)
754{
755 usb_if.udc_stop();
756}