summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/f_fastboot.c (plain)
blob: 5d86e709c23c5c8f03cf2713126e42e16d337a48
1/*
2 * (C) Copyright 2008 - 2009
3 * Windriver, <www.windriver.com>
4 * Tom Rix <Tom.Rix@windriver.com>
5 *
6 * Copyright 2011 Sebastian Andrzej Siewior <bigeasy@linutronix.de>
7 *
8 * Copyright 2014 Linaro, Ltd.
9 * Rob Herring <robh@kernel.org>
10 *
11 * SPDX-License-Identifier: GPL-2.0+
12 */
13#include <config.h>
14#include <common.h>
15#include <errno.h>
16#include <malloc.h>
17#include <linux/usb/ch9.h>
18#include <linux/usb/gadget.h>
19#include <linux/usb/composite.h>
20#include <linux/compiler.h>
21#include <version.h>
22#include <g_dnl.h>
23#include <asm/arch/cpu.h>
24#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
25#include <fb_mmc.h>
26#include <fb_storage.h>
27#include <fb_fastboot.h>
28#include <emmc_partitions.h>
29#endif
30#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
31#include <fb_nand.h>
32#endif
33#include <partition_table.h>
34#include <android_image.h>
35#include <image.h>
36#ifdef CONFIG_AML_ANTIROLLBACK
37#include <anti-rollback.h>
38#endif
39
40DECLARE_GLOBAL_DATA_PTR;
41
42#define FASTBOOT_VERSION "0.4"
43
44#define FASTBOOT_INTERFACE_CLASS 0xff
45#define FASTBOOT_INTERFACE_SUB_CLASS 0x42
46#define FASTBOOT_INTERFACE_PROTOCOL 0x03
47
48#define ENDPOINT_MAXIMUM_PACKET_SIZE_2_0 (0x0200)
49
50#ifdef CONFIG_DEVICE_PRODUCT
51#define DEVICE_PRODUCT CONFIG_DEVICE_PRODUCT
52#endif
53#define DEVICE_SERIAL "1234567890"
54
55#define FB_ERR(fmt ...) printf("[ERR]%sL%d:", __func__, __LINE__),printf(fmt)
56#define FB_MSG(fmt ...) printf("[MSG]"fmt)
57#define FB_WRN(fmt ...) printf("[WRN]"fmt)
58#define FB_DBG(...)
59#define FB_HERE() printf("f(%s)L%d\n", __func__, __LINE__)
60
61extern void f_dwc_otg_pullup(int is_on);
62
63#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
64extern int is_partition_logical(char* parition_name);
65#endif
66
67/* The 64 defined bytes plus \0 */
68
69#define EP_BUFFER_SIZE 4096
70
71struct f_fastboot {
72 struct usb_function usb_function;
73
74 /* IN/OUT EP's and corresponding requests */
75 struct usb_ep *in_ep, *out_ep;
76 struct usb_request *in_req, *out_req;
77};
78
79static inline struct f_fastboot *func_to_fastboot(struct usb_function *f)
80{
81 return container_of(f, struct f_fastboot, usb_function);
82}
83
84static struct f_fastboot *fastboot_func;
85static unsigned int download_size;
86static unsigned int download_bytes;
87
88
89static struct usb_endpoint_descriptor ep_in = {
90 .bLength = USB_DT_ENDPOINT_SIZE,
91 .bDescriptorType = USB_DT_ENDPOINT,
92 .bEndpointAddress = USB_DIR_IN,
93 .bmAttributes = USB_ENDPOINT_XFER_BULK,
94 .wMaxPacketSize = ENDPOINT_MAXIMUM_PACKET_SIZE_2_0,
95 .bInterval = 0x00,
96};
97
98static struct usb_endpoint_descriptor ep_out = {
99 .bLength = USB_DT_ENDPOINT_SIZE,
100 .bDescriptorType = USB_DT_ENDPOINT,
101 .bEndpointAddress = USB_DIR_OUT,
102 .bmAttributes = USB_ENDPOINT_XFER_BULK,
103 .wMaxPacketSize = ENDPOINT_MAXIMUM_PACKET_SIZE_2_0,
104 .bInterval = 0x00,
105};
106
107static struct usb_interface_descriptor interface_desc = {
108 .bLength = USB_DT_INTERFACE_SIZE,
109 .bDescriptorType = USB_DT_INTERFACE,
110 .bInterfaceNumber = 0x00,
111 .bAlternateSetting = 0x00,
112 .bNumEndpoints = 0x02,
113 .bInterfaceClass = FASTBOOT_INTERFACE_CLASS,
114 .bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS,
115 .bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL,
116};
117
118static struct usb_descriptor_header *fb_runtime_descs[] = {
119 (struct usb_descriptor_header *)&interface_desc,
120 (struct usb_descriptor_header *)&ep_in,
121 (struct usb_descriptor_header *)&ep_out,
122 NULL,
123};
124
125/*
126 * static strings, in UTF-8
127 */
128static const char fastboot_name[] = "Android Fastboot";
129
130static struct usb_string fastboot_string_defs[] = {
131 [0].s = fastboot_name,
132 { } /* end of list */
133};
134
135static struct usb_gadget_strings stringtab_fastboot = {
136 .language = 0x0409, /* en-us */
137 .strings = fastboot_string_defs,
138};
139
140static struct usb_gadget_strings *fastboot_strings[] = {
141 &stringtab_fastboot,
142 NULL,
143};
144
145#define DRAM_UBOOT_RESERVE 0x01000000
146unsigned int ddr_size_usable(unsigned int addr_start)
147{
148 unsigned int ddr_size=0;
149 unsigned int free_size = 0;
150 int i;
151
152 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++)
153 ddr_size += gd->bd->bi_dram[i].size;
154
155 free_size = (ddr_size - DRAM_UBOOT_RESERVE - addr_start - CONFIG_SYS_MALLOC_LEN - CONFIG_SYS_MEM_TOP_HIDE);
156#if defined CONFIG_FASTBOOT_MAX_DOWN_SIZE
157 if (free_size > CONFIG_FASTBOOT_MAX_DOWN_SIZE)
158 free_size = CONFIG_FASTBOOT_MAX_DOWN_SIZE;
159#endif
160 return free_size;
161}
162
163static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
164
165static char response_str[RESPONSE_LEN + 1];
166
167void fastboot_fail(const char *s)
168{
169 strncpy(response_str, "FAIL", 4);
170 if (s)strncat(response_str, s, RESPONSE_LEN - 4 - 1) ;
171}
172
173void fastboot_okay(const char *s)
174{
175 strncpy(response_str, "OKAY", 4);
176 if (s)strncat(response_str, s, RESPONSE_LEN - 4 - 1) ;
177}
178
179void fastboot_busy(const char* s)
180{
181 strncpy(response_str, "INFO", 4 + 1);//add terminated 0
182 if (s)strncat(response_str, s, RESPONSE_LEN - 4 - 1) ;
183}
184int fastboot_is_busy(void)
185{
186 return !strncmp("INFO", response_str, strlen("INFO"));
187}
188
189//cb for bulk in_req->complete
190static void fastboot_complete(struct usb_ep *ep, struct usb_request *req)
191{
192 int status = req->status;
193
194 if ( fastboot_is_busy() && fastboot_func) {
195 struct usb_ep* out_ep = fastboot_func->out_ep;
196 struct usb_request* out_req = fastboot_func->out_req;
197 rx_handler_command(out_ep, out_req);
198 return;
199 }
200 if (!status)
201 return;
202 printf("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual);
203}
204
205static int fastboot_bind(struct usb_configuration *c, struct usb_function *f)
206{
207 int id;
208 struct usb_gadget *gadget = c->cdev->gadget;
209 struct f_fastboot *f_fb = func_to_fastboot(f);
210
211 /* DYNAMIC interface numbers assignments */
212 id = usb_interface_id(c, f);
213 if (id < 0)
214 return id;
215 interface_desc.bInterfaceNumber = id;
216
217 id = usb_string_id(c->cdev);
218 if (id < 0)
219 return id;
220 fastboot_string_defs[0].id = id;
221 interface_desc.iInterface = id;
222
223 f_fb->in_ep = usb_ep_autoconfig(gadget, &ep_in);
224 if (!f_fb->in_ep)
225 return -ENODEV;
226 f_fb->in_ep->driver_data = c->cdev;
227
228 f_fb->out_ep = usb_ep_autoconfig(gadget, &ep_out);
229 if (!f_fb->out_ep)
230 return -ENODEV;
231 f_fb->out_ep->driver_data = c->cdev;
232
233 return 0;
234}
235
236static void fastboot_unbind(struct usb_configuration *c, struct usb_function *f)
237{
238 memset(fastboot_func, 0, sizeof(*fastboot_func));
239}
240
241static void fastboot_disable(struct usb_function *f)
242{
243 struct f_fastboot *f_fb = func_to_fastboot(f);
244
245 usb_ep_disable(f_fb->out_ep);
246 usb_ep_disable(f_fb->in_ep);
247
248 if (f_fb->out_req) {
249 free(f_fb->out_req->buf);
250 usb_ep_free_request(f_fb->out_ep, f_fb->out_req);
251 f_fb->out_req = NULL;
252 }
253 if (f_fb->in_req) {
254 free(f_fb->in_req->buf);
255 usb_ep_free_request(f_fb->in_ep, f_fb->in_req);
256 f_fb->in_req = NULL;
257 }
258}
259
260static struct usb_request *fastboot_start_ep(struct usb_ep *ep)
261{
262 struct usb_request *req;
263
264 req = usb_ep_alloc_request(ep, 0);
265 if (!req)
266 return NULL;
267
268 req->length = EP_BUFFER_SIZE;
269 req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);
270 if (!req->buf) {
271 usb_ep_free_request(ep, req);
272 return NULL;
273 }
274
275 memset(req->buf, 0, req->length);
276 return req;
277}
278
279static int fastboot_set_alt(struct usb_function *f,
280 unsigned interface, unsigned alt)
281{
282 int ret;
283 struct f_fastboot *f_fb = func_to_fastboot(f);
284
285 debug("%s: func: %s intf: %d alt: %d\n",
286 __func__, f->name, interface, alt);
287
288 /* make sure we don't enable the ep twice */
289 ret = usb_ep_enable(f_fb->out_ep, &ep_out);
290 if (ret) {
291 puts("failed to enable out ep\n");
292 return ret;
293 }
294
295 f_fb->out_req = fastboot_start_ep(f_fb->out_ep);
296 if (!f_fb->out_req) {
297 puts("failed to alloc out req\n");
298 ret = -EINVAL;
299 goto err;
300 }
301 f_fb->out_req->complete = rx_handler_command;
302
303 ret = usb_ep_enable(f_fb->in_ep, &ep_in);
304 if (ret) {
305 puts("failed to enable in ep\n");
306 goto err;
307 }
308
309 f_fb->in_req = fastboot_start_ep(f_fb->in_ep);
310 if (!f_fb->in_req) {
311 puts("failed alloc req in\n");
312 ret = -EINVAL;
313 goto err;
314 }
315 f_fb->in_req->complete = fastboot_complete;
316
317 ret = usb_ep_queue(f_fb->out_ep, f_fb->out_req, 0);
318 if (ret)
319 goto err;
320
321 return 0;
322err:
323 fastboot_disable(f);
324 return ret;
325}
326
327static int fastboot_setup(struct usb_function *f,
328 const struct usb_ctrlrequest *ctrl)
329{
330 int value = -EOPNOTSUPP;
331 struct f_fastboot *f_fb = func_to_fastboot(f);
332
333 /* composite driver infrastructure handles everything; interface
334 * activation uses set_alt().
335 */
336 if (((ctrl->bRequestType & USB_RECIP_MASK) == USB_RECIP_ENDPOINT)
337 && (ctrl->bRequest == USB_REQ_CLEAR_FEATURE)
338 && (ctrl->wValue== USB_ENDPOINT_HALT)) {
339 switch (ctrl->wIndex & 0xfe) {
340 case USB_DIR_OUT:
341 value = ctrl->wLength;
342 usb_ep_clear_halt(f_fb->out_ep);
343 break;
344
345 case USB_DIR_IN:
346 value = ctrl->wLength;
347 usb_ep_clear_halt(f_fb->in_ep);
348 break;
349 default:
350 printf("unknown usb_ctrlrequest\n");
351 break;
352 }
353 }
354
355 return value;
356}
357
358static int fastboot_add(struct usb_configuration *c)
359{
360 struct f_fastboot *f_fb = fastboot_func;
361 int status;
362
363 if (!f_fb) {
364 f_fb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_fb));
365 if (!f_fb)
366 return -ENOMEM;
367
368 fastboot_func = f_fb;
369 memset(f_fb, 0, sizeof(*f_fb));
370 }
371
372 f_fb->usb_function.name = "f_fastboot";
373 f_fb->usb_function.hs_descriptors = fb_runtime_descs;
374 f_fb->usb_function.bind = fastboot_bind;
375 f_fb->usb_function.unbind = fastboot_unbind;
376 f_fb->usb_function.set_alt = fastboot_set_alt;
377 f_fb->usb_function.disable = fastboot_disable;
378 f_fb->usb_function.strings = fastboot_strings;
379 f_fb->usb_function.setup = fastboot_setup;
380
381 status = usb_add_function(c, &f_fb->usb_function);
382 if (status) {
383 free(f_fb);
384 fastboot_func = f_fb;
385 }
386
387 return status;
388}
389DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add);
390
391static int fastboot_tx_write(const char *buffer, unsigned int buffer_size)
392{
393 struct usb_request *in_req = fastboot_func->in_req;
394 int ret;
395
396 memcpy(in_req->buf, buffer, buffer_size);
397 in_req->length = buffer_size;
398 ret = usb_ep_queue(fastboot_func->in_ep, in_req, 0);
399 if (ret)
400 printf("Error %d on queue\n", ret);
401 return 0;
402}
403
404static int fastboot_tx_write_str(const char *buffer)
405{
406 return fastboot_tx_write(buffer, strlen(buffer));
407}
408
409static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
410{
411 do_reset(NULL, 0, 0, NULL);
412}
413
414static void compl_do_reboot_bootloader(struct usb_ep *ep, struct usb_request *req)
415{
416 if (dynamic_partition)
417 run_command("reboot bootloader", 0);
418 else
419 run_command("reboot fastboot", 0);
420}
421
422static void compl_do_reboot_fastboot(struct usb_ep *ep, struct usb_request *req)
423{
424 f_dwc_otg_pullup(0);
425 run_command("reboot fastboot", 0);
426}
427
428static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
429{
430 char *cmd = req->buf;
431
432 printf("cmd cb_reboot is %s\n", cmd);
433
434 strsep(&cmd, "-");
435 if (!cmd) {
436 fastboot_func->in_req->complete = compl_do_reset;
437 fastboot_tx_write_str("OKAY");
438 return;
439 }
440
441 printf("cmd cb_reboot is %s\n", cmd);
442 if (strcmp(cmd, "bootloader") == 0)
443 fastboot_func->in_req->complete = compl_do_reboot_bootloader;
444 else if (strcmp(cmd, "fastboot") == 0)
445 fastboot_func->in_req->complete = compl_do_reboot_fastboot;
446
447 fastboot_tx_write_str("OKAY");
448}
449
450static int strcmp_l1(const char *s1, const char *s2)
451{
452 if (!s1 || !s2)
453 return -1;
454 return strncmp(s1, s2, strlen(s1));
455}
456
457void dump_lock_info(LockData_t* info)
458{
459 printf("info->version_major = %d\n", info->version_major);
460 printf("info->version_minor = %d\n", info->version_minor);
461 printf("info->lock_state = %d\n", info->lock_state);
462 printf("info->lock_critical_state = %d\n", info->lock_critical_state);
463 printf("info->lock_bootloader = %d\n", info->lock_bootloader);
464}
465
466
467static int check_lock(void)
468{
469 char *lock_s;
470 LockData_t* info;
471
472 lock_s = getenv("lock");
473 if (!lock_s) {
474 printf("lock state is NULL \n");
475 lock_s = "10000000";
476 setenv("lock", "10000000");
477 run_command("defenv_reserv; saveenv;", 0);
478 }
479 printf("lock state: %s\n", lock_s);
480
481 info = (LockData_t*)malloc(sizeof(struct LockData));
482 memset(info,0,LOCK_DATA_SIZE);
483 info->version_major = (int)(lock_s[0] - '0');
484 info->version_minor = (int)(lock_s[1] - '0');
485 info->lock_state = (int)(lock_s[4] - '0');
486 info->lock_critical_state = (int)(lock_s[5] - '0');
487 info->lock_bootloader = (int)(lock_s[6] - '0');
488
489 dump_lock_info(info);
490
491 if (( info->lock_state == 1 ) || ( info->lock_critical_state == 1 ))
492 return 1;
493 else
494 return 0;
495}
496
497static const char* getvar_list[] = {
498 "version-baseband", "version-bootloader", "version", "hw-revision", "max-download-size",
499 "serialno", "product", "off-mode-charge", "variant", "battery-soc-ok",
500 "battery-voltage", "partition-type:boot", "partition-size:boot",
501 "partition-type:system", "partition-size:system", "partition-type:vendor", "partition-size:vendor",
502 "partition-type:odm", "partition-size:odm", "partition-type:data", "partition-size:data",
503 "erase-block-size", "logical-block-size", "secure", "unlocked",
504};
505
506static const char* getvar_list_dynamic[] = {
507 "hw-revision", "battery-voltage", "is-userspace", "is-logical:data",
508 "is-logical:metadata", "is-logical:misc", "is-logical:super", "is-logical:boot",
509 "is-logical:system", "is-logical:vendor", "is-logical:product", "is-logical:odm",
510 "slot-count", "max-download-size", "serialno", "product", "unlocked", "has-slot:data",
511 "has-slot:metadata", "has-slot:misc", "has-slot:super", "has-slot:boot",
512 "has-slot:system", "has-slot:vendor", "has-slot:product", "has-slot:odm",
513 "secure", "super-partition-name", "version-baseband", "version-bootloader",
514 "partition-size:boot", "partition-size:metadata", "partition-size:misc",
515 "partition-size:super", "partition-size:data", "version",
516};
517
518static const char* getvar_list_ab[] = {
519 "version-baseband", "version-bootloader", "version", "hw-revision", "max-download-size",
520 "serialno", "product", "off-mode-charge", "variant", "battery-soc-ok",
521 "battery-voltage", "partition-type:boot", "partition-size:boot",
522 "partition-type:system", "partition-size:system", "partition-type:vendor", "partition-size:vendor",
523 "partition-type:odm", "partition-size:odm", "partition-type:data", "partition-size:data",
524 "partition-type:cache", "partition-size:cache",
525 "erase-block-size", "logical-block-size", "secure", "unlocked",
526 "slot-count", "slot-suffixes","current-slot", "has-slot:bootloader", "has-slot:boot",
527 "has-slot:system", "has-slot:vendor", "has-slot:odm", "has-slot:vbmeta",
528 "has-slot:metadata", "has-slot:product", "has-slot:dtbo",
529 "slot-successful:a", "slot-unbootable:a", "slot-retry-count:a",
530 "slot-successful:b", "slot-unbootable:b", "slot-retry-count:b",
531};
532
533static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
534{
535 char *cmd = req->buf;
536 char cmdBuf[RESPONSE_LEN];
537 char* response = response_str;
538 char *s;
539 char *s1;
540 char *s2;
541 char *s3;
542 char s_version[24];
543 size_t chars_left;
544
545 run_command("get_valid_slot", 0);
546
547 strcpy(response, "OKAY");
548 chars_left = sizeof(response_str) - strlen(response) - 1;
549
550 memcpy(cmdBuf, cmd, strnlen(cmd, RESPONSE_LEN-1)+1);
551 cmd = cmdBuf;
552 strsep(&cmd, ":");
553 printf("cb_getvar: %s\n", cmd);
554 if (!cmd) {
555 error("missing variable\n");
556 fastboot_tx_write_str("FAILmissing var");
557 return;
558 }
559 if (!strncmp(cmd, "all", 3)) {
560 static int cmdIndex = 0;
561 int getvar_num;
562 if (has_boot_slot == 1) {
563 strcpy(cmd, getvar_list_ab[cmdIndex]);
564 getvar_num = (sizeof(getvar_list_ab) / sizeof(getvar_list_ab[0]));
565 } else if (dynamic_partition) {
566 strcpy(cmd, getvar_list_dynamic[cmdIndex]);//only support no-arg cmd
567 getvar_num = (sizeof(getvar_list_dynamic) / sizeof(getvar_list_dynamic[0]));
568 } else {
569 strcpy(cmd, getvar_list[cmdIndex]);//only support no-arg cmd
570 getvar_num = (sizeof(getvar_list) / sizeof(getvar_list[0]));
571 }
572 printf("getvar_num: %d\n", getvar_num);
573 if ( ++cmdIndex >= getvar_num) cmdIndex = 0;
574 else fastboot_busy(NULL);
575 FB_MSG("all cmd:%s\n", cmd);
576 strncat(response, cmd, chars_left);
577 strncat(response, ":", 1);
578 chars_left -= strlen(cmd) + 1;
579 }
580
581 strcpy(s_version, "01.01.");
582 printf("U_BOOT_DATE_TIME: %s\n", U_BOOT_DATE_TIME);
583 strcat(s_version, U_BOOT_DATE_TIME);
584 printf("s_version: %s\n", s_version);
585
586 if (!strcmp_l1("version-baseband", cmd)) {
587 strncat(response, "N/A", chars_left);
588 } else if (!strcmp_l1("version-bootloader", cmd)) {
589 strncat(response, s_version, chars_left);
590 } else if (!strcmp_l1("hw-revision", cmd)) {
591 strncat(response, "0", chars_left);
592 } else if (!strcmp_l1("version", cmd)) {
593 strncat(response, FASTBOOT_VERSION, chars_left);
594 } else if (!strcmp_l1("bootloader-version", cmd)) {
595 strncat(response, s_version, chars_left);
596 } else if (!strcmp_l1("off-mode-charge", cmd)) {
597 strncat(response, "0", chars_left);
598 } else if (!strcmp_l1("variant", cmd)) {
599 strncat(response, "US", chars_left);
600 } else if (!strcmp_l1("battery-soc-ok", cmd)) {
601 strncat(response, "yes", chars_left);
602 } else if (!strcmp_l1("battery-voltage", cmd)) {
603 strncat(response, "4", chars_left);
604 } else if (!strcmp_l1("is-userspace", cmd)) {
605 if (dynamic_partition) {
606 strncat(response, "no", chars_left);
607 } else {
608 error("unknown variable: %s\n", cmd);
609 strcpy(response, "FAILVariable not implemented");
610 }
611 } else if (!strcmp_l1("is-logical", cmd)) {
612 strsep(&cmd, ":");
613 printf("partition is %s\n", cmd);
614 if (!dynamic_partition) {
615 strncat(response, "no", chars_left);
616 } else {
617#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
618 if (is_partition_logical(cmd) == 0) {
619 error("%s is logic partition\n", cmd);
620 strncat(response, "yes", chars_left);
621 } else {
622 strncat(response, "no", chars_left);
623 }
624#else
625 strncat(response, "no", chars_left);
626#endif
627 }
628 } else if (!strcmp_l1("super-partition-name", cmd)) {
629 char *slot_name;
630 slot_name = getenv("slot-suffixes");
631 if (has_boot_slot == 0) {
632 strncat(response, "super", chars_left);
633 } else {
634 printf("slot-suffixes: %s\n", slot_name);
635 if (strcmp(slot_name, "0") == 0) {
636 printf("active_slot is %s\n", "a");
637 strncat(response, "super_a", chars_left);
638 } else if (strcmp(slot_name, "1") == 0) {
639 printf("active_slot is %s\n", "b");
640 strncat(response, "super_b", chars_left);
641 }
642 }
643 } else if (!strcmp_l1("downloadsize", cmd) ||
644 !strcmp_l1("max-download-size", cmd)) {
645 char str_num[12];
646
647 sprintf(str_num, "0x%08x", ddr_size_usable(CONFIG_USB_FASTBOOT_BUF_ADDR));
648 strncat(response, str_num, chars_left);
649 } else if (!strcmp_l1("serialno", cmd)) {
650 //s = getenv("serial");
651 s = get_usid_string();
652 if (s)
653 strncat(response, s, chars_left);
654 else
655 strncat(response, DEVICE_SERIAL, chars_left);
656 } else if (!strcmp_l1("product", cmd)) {
657#ifdef DEVICE_PRODUCT
658 s1 = DEVICE_PRODUCT;
659 printf("DEVICE_PRODUCT: %s\n", s1);
660#else
661 s1 = getenv("device_product");
662 printf("device_product: %s\n", s1);
663#endif
664 strncat(response, s1, chars_left);
665 } else if (!strcmp_l1("slot-count", cmd)) {
666 if (has_boot_slot == 1)
667 strncat(response, "2", chars_left);
668 else
669 strncat(response, "0", chars_left);
670 } else if (!strcmp_l1("slot-suffixes", cmd)) {
671 s2 = getenv("slot-suffixes");
672 printf("slot-suffixes: %s\n", s2);
673 if (s2)
674 strncat(response, s2, chars_left);
675 else
676 strncat(response, "0", chars_left);
677 } else if (!strcmp_l1("current-slot", cmd)) {
678 s3 = getenv("slot-suffixes");
679 printf("slot-suffixes: %s\n", s3);
680 if (strcmp(s3, "0") == 0) {
681 printf("active_slot is %s\n", "a");
682 strncat(response, "a", chars_left);
683 } else if (strcmp(s3, "1") == 0) {
684 printf("active_slot is %s\n", "b");
685 strncat(response, "b", chars_left);
686 }
687 } else if (!strcmp_l1("has-slot:bootloader", cmd)) {
688 printf("do not has slot bootloader\n");
689 strncat(response, "no", chars_left);
690 } else if (!strcmp_l1("has-slot:boot", cmd)) {
691 if (has_boot_slot == 1) {
692 printf("has boot slot\n");
693 strncat(response, "yes", chars_left);
694 } else
695 strncat(response, "no", chars_left);
696 } else if (!strcmp_l1("has-slot:system", cmd)) {
697 if (dynamic_partition) {
698 strncat(response, "no", chars_left);
699 } else {
700 if (has_system_slot == 1) {
701 printf("has system slot\n");
702 strncat(response, "yes", chars_left);
703 } else
704 strncat(response, "no", chars_left);
705 }
706 } else if (!strcmp_l1("has-slot:vendor", cmd)) {
707 if (dynamic_partition) {
708 strncat(response, "no", chars_left);
709 } else {
710 if (has_boot_slot == 1) {
711 printf("has vendor slot\n");
712 strncat(response, "yes", chars_left);
713 } else
714 strncat(response, "no", chars_left);
715 }
716 } else if (!strcmp_l1("has-slot:vbmeta", cmd)) {
717 if (dynamic_partition) {
718 strncat(response, "no", chars_left);
719 } else {
720 if (has_boot_slot == 1) {
721 printf("has vbmeta slot\n");
722 strncat(response, "yes", chars_left);
723 } else
724 strncat(response, "no", chars_left);
725 }
726 } else if (!strcmp_l1("has-slot:product", cmd)) {
727 if (dynamic_partition) {
728 strncat(response, "no", chars_left);
729 } else {
730 if (has_boot_slot == 1) {
731 printf("has product slot\n");
732 strncat(response, "yes", chars_left);
733 } else
734 strncat(response, "no", chars_left);
735 }
736 } else if (!strcmp_l1("has-slot:super", cmd)) {
737 if (!dynamic_partition) {
738 strncat(response, "no", chars_left);
739 } else {
740 if (has_boot_slot == 1) {
741 printf("has product slot\n");
742 strncat(response, "yes", chars_left);
743 } else
744 strncat(response, "no", chars_left);
745 }
746 } else if (!strcmp_l1("has-slot:metadata", cmd)) {
747 if (has_boot_slot == 1) {
748 printf("has metadata slot\n");
749 strncat(response, "yes", chars_left);
750 } else
751 strncat(response, "no", chars_left);
752 } else if (!strcmp_l1("has-slot:dtbo", cmd)) {
753 if (has_boot_slot == 1) {
754 printf("has dtbo slot\n");
755 strncat(response, "yes", chars_left);
756 } else
757 strncat(response, "no", chars_left);
758 } else if (!strcmp_l1("has-slot:data", cmd)) {
759 strncat(response, "no", chars_left);
760 } else if (!strcmp_l1("has-slot:misc", cmd)) {
761 strncat(response, "no", chars_left);
762 } else if (!strcmp_l1("has-slot:odm", cmd)) {
763 if (has_boot_slot == 1) {
764 printf("has odm slot\n");
765 strncat(response, "yes", chars_left);
766 } else
767 strncat(response, "no", chars_left);
768 } else if (!strncmp("partition-size", cmd, strlen("partition-size"))) {
769 char str_num[20];
770 struct partitions *pPartition;
771 uint64_t sz;
772 strsep(&cmd, ":");
773 printf("partition is %s\n", cmd);
774 if (strcmp(cmd, "userdata") == 0) {
775 strcpy(cmd, "data");
776 printf("partition is %s\n", cmd);
777 }
778 if (!strncmp("mbr", cmd, strlen("mbr"))) {
779 strcpy(response, "FAILVariable not implemented");
780 } else {
781 if (!strncmp("bootloader-", cmd, strlen("bootloader-"))) {
782 strsep(&cmd, "-");
783 mmc_boot_size(cmd, &sz);
784 printf("size:%016llx\n", sz);
785 sprintf(str_num, "%016llx", sz);
786 } else {
787 pPartition = find_mmc_partition_by_name(cmd);
788 if (pPartition) {
789 printf("size:%016llx\n", pPartition->size);
790 if (strcmp(cmd, "data") == 0) {
791 printf("reserve 0x4000 for fde data\n");
792 sz = pPartition->size - 0x4000;
793 printf("data size :%016llx\n", sz);
794 sprintf(str_num, "%016llx", sz);
795 } else {
796 sprintf(str_num, "%016llx", pPartition->size);
797 }
798 } else {
799 printf("find_mmc_partition_by_name fail\n");
800 sprintf(str_num, "get fail");
801 }
802 }
803 strncat(response, str_num, chars_left);
804 }
805 } else if (!strcmp_l1("partition-type:cache", cmd)) {
806 if (has_boot_slot == 0) {
807 strncat(response, "ext4", chars_left);
808 }
809 } else if (!strcmp_l1("partition-type:data", cmd)) {
810 strncat(response, "ext4", chars_left);
811 } else if (!strcmp_l1("partition-type:userdata", cmd)) {
812 strncat(response, "ext4", chars_left);
813 } else if (!strcmp_l1("partition-type:system", cmd)) {
814 strncat(response, "ext4", chars_left);
815 } else if (!strcmp_l1("partition-type:vendor", cmd)) {
816 strncat(response, "ext4", chars_left);
817 } else if (!strcmp_l1("partition-type:odm", cmd)) {
818 strncat(response, "ext4", chars_left);
819 } else if (!strcmp_l1("partition-type:tee", cmd)) {
820 strncat(response, "ext4", chars_left);
821 } else if (!strcmp_l1("partition-type:param", cmd)) {
822 strncat(response, "ext4", chars_left);
823 } else if (!strcmp_l1("partition-type:product", cmd)) {
824 strncat(response, "ext4", chars_left);
825 } else if (!strcmp_l1("partition-type:metadata", cmd)) {
826 strncat(response, "ext4", chars_left);
827 } else if (!strncmp("partition-type", cmd, strlen("partition-type"))) {
828 strncat(response, "raw", chars_left);
829 } else if (!strcmp_l1("erase-block-size", cmd) ||
830 !strcmp_l1("logical-block-size", cmd)) {
831 strncat(response, "2000", chars_left);
832 } else if (!strcmp_l1("secure", cmd)) {
833 if (check_lock()) {
834 strncat(response, "yes", chars_left);
835 } else {
836 strncat(response, "no", chars_left);
837 }
838 } else if (!strcmp_l1("unlocked", cmd)) {
839 if (check_lock()) {
840 strncat(response, "no", chars_left);
841 } else {
842 strncat(response, "yes", chars_left);
843 }
844 } else if (!strcmp_l1("slot-successful", cmd)) {
845 char str[128];
846 strsep(&cmd, ":");
847 printf("cmd is %s\n", cmd);
848 int ret;
849 if (has_boot_slot == 1) {
850 printf("has boot slot\n");
851 sprintf(str, "get_slot_state %s successful", cmd);
852 printf("command: %s\n", str);
853 ret = run_command(str, 0);
854 printf("ret = %d\n", ret);
855 if (ret == 0)
856 strncat(response, "no", chars_left);
857 else
858 strncat(response, "yes", chars_left);
859 } else
860 strcpy(response, "FAILVariable not implemented in non ab mode");
861 } else if (!strcmp_l1("slot-unbootable", cmd)) {
862 char str[128];
863 strsep(&cmd, ":");
864 printf("cmd is %s\n", cmd);
865 int ret;
866 if (has_boot_slot == 1) {
867 printf("has boot slot\n");
868 sprintf(str, "get_slot_state %s unbootable", cmd);
869 printf("command: %s\n", str);
870 ret = run_command(str, 0);
871 printf("ret = %d\n", ret);
872 if (ret == 0)
873 strncat(response, "yes", chars_left);
874 else
875 strncat(response, "no", chars_left);
876 } else
877 strcpy(response, "FAILVariable not implemented in non ab mode");
878 } else if (!strcmp_l1("slot-retry-count", cmd)) {
879 char str[128];
880 strsep(&cmd, ":");
881 printf("cmd is %s\n", cmd);
882 int ret;
883 if (has_boot_slot == 1) {
884 char str_num[12];
885 printf("has boot slot\n");
886 sprintf(str, "get_slot_state %s retry-count", cmd);
887 printf("command: %s\n", str);
888 ret = run_command(str, 0);
889 printf("ret = %d\n", ret);
890 sprintf(str_num, "%d", ret);
891 strncat(response, str_num, chars_left);
892 } else
893 strcpy(response, "FAILVariable not implemented in non ab mode");
894 } else {
895 error("unknown variable: %s\n", cmd);
896 strcpy(response, "FAILVariable not implemented");
897 }
898
899 fastboot_tx_write_str(response);
900}
901
902static unsigned int rx_bytes_expected(void)
903{
904 int rx_remain = download_size - download_bytes;
905 if (rx_remain < 0)
906 return 0;
907 if (rx_remain > EP_BUFFER_SIZE)
908 return EP_BUFFER_SIZE;
909 return rx_remain;
910}
911
912#define BYTES_PER_DOT 0x20000
913static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
914{
915 char response[RESPONSE_LEN];
916 unsigned int transfer_size = download_size - download_bytes;
917 const unsigned char *buffer = req->buf;
918 unsigned int buffer_size = req->actual;
919 unsigned int pre_dot_num, now_dot_num;
920
921 if (req->status != 0) {
922 printf("Bad status: %d\n", req->status);
923 return;
924 }
925
926 if (buffer_size < transfer_size)
927 transfer_size = buffer_size;
928
929 memcpy((void *)CONFIG_USB_FASTBOOT_BUF_ADDR + download_bytes,
930 buffer, transfer_size);
931
932 pre_dot_num = download_bytes / BYTES_PER_DOT;
933 download_bytes += transfer_size;
934 now_dot_num = download_bytes / BYTES_PER_DOT;
935
936 if (pre_dot_num != now_dot_num) {
937 putc('.');
938 if (!(now_dot_num % 74))
939 putc('\n');
940 }
941
942 /* Check if transfer is done */
943 if (download_bytes >= download_size) {
944 /*
945 * Reset global transfer variable, keep download_bytes because
946 * it will be used in the next possible flashing command
947 */
948 download_size = 0;
949 req->complete = rx_handler_command;
950 req->length = EP_BUFFER_SIZE;
951
952 sprintf(response, "OKAY");
953 fastboot_tx_write_str(response);
954
955 printf("\ndownloading of %d bytes finished\n", download_bytes);
956 } else {
957 req->length = rx_bytes_expected();
958 if (req->length < ep->maxpacket)
959 req->length = ep->maxpacket;
960 }
961
962 req->actual = 0;
963 usb_ep_queue(ep, req, 0);
964}
965
966static void cb_download(struct usb_ep *ep, struct usb_request *req)
967{
968 char *cmd = req->buf;
969 char response[RESPONSE_LEN];
970
971 printf("cmd cb_download is %s\n", cmd);
972
973 strsep(&cmd, ":");
974 download_size = simple_strtoul(cmd, NULL, 16);
975 download_bytes = 0;
976
977 printf("Starting download of %d bytes\n", download_size);
978
979 if (0 == download_size) {
980 sprintf(response, "FAILdata invalid size");
981 } else if (download_size > ddr_size_usable(CONFIG_USB_FASTBOOT_BUF_ADDR)) {
982 download_size = 0;
983 sprintf(response, "FAILdata too large");
984 } else {
985 sprintf(response, "DATA%08x", download_size);
986 req->complete = rx_handler_dl_image;
987 req->length = rx_bytes_expected();
988 if (req->length < ep->maxpacket)
989 req->length = ep->maxpacket;
990 }
991 fastboot_tx_write_str(response);
992}
993
994typedef struct andr_img_hdr boot_img_hdr;
995
996static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req)
997{
998 char boot_addr_start[12];
999 unsigned kernel_size;
1000 unsigned ramdisk_size;
1001 boot_img_hdr *hdr_addr = NULL;
1002 int genFmt = 0;
1003 unsigned actualBootImgSz = 0;
1004 unsigned dtbSz = 0;
1005 unsigned char* loadaddr = 0;
1006
1007 puts("Booting kernel...\n");
1008
1009 sprintf(boot_addr_start, "bootm 0x%lx", load_addr);
1010 printf("boot_addr_start %s\n", boot_addr_start);
1011
1012 loadaddr = (unsigned char*)CONFIG_USB_FASTBOOT_BUF_ADDR;
1013 hdr_addr = (boot_img_hdr*)loadaddr;
1014
1015 genFmt = genimg_get_format(hdr_addr);
1016 if (IMAGE_FORMAT_ANDROID != genFmt) {
1017 printf("Fmt unsupported!genFmt 0x%x != 0x%x\n", genFmt, IMAGE_FORMAT_ANDROID);
1018 return;
1019 }
1020
1021 kernel_size =(hdr_addr->kernel_size + (hdr_addr->page_size-1)+hdr_addr->page_size)&(~(hdr_addr->page_size -1));
1022 ramdisk_size =(hdr_addr->ramdisk_size + (hdr_addr->page_size-1))&(~(hdr_addr->page_size -1));
1023 dtbSz = hdr_addr->second_size;
1024 actualBootImgSz = kernel_size + ramdisk_size + dtbSz;
1025 printf("kernel_size 0x%x, page_size 0x%x, totalSz 0x%x\n", hdr_addr->kernel_size, hdr_addr->page_size, kernel_size);
1026 printf("ramdisk_size 0x%x, totalSz 0x%x\n", hdr_addr->ramdisk_size, ramdisk_size);
1027 printf("dtbSz 0x%x, Total actualBootImgSz 0x%x\n", dtbSz, actualBootImgSz);
1028
1029 memcpy((void *)load_addr, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR, actualBootImgSz);
1030
1031 flush_cache(load_addr,(unsigned long)actualBootImgSz);
1032
1033 run_command(boot_addr_start, 0);
1034
1035 /* This only happens if image is somehow faulty so we start over */
1036 do_reset(NULL, 0, 0, NULL);
1037}
1038
1039static void cb_boot(struct usb_ep *ep, struct usb_request *req)
1040{
1041 fastboot_func->in_req->complete = do_bootm_on_complete;
1042 fastboot_tx_write_str("OKAY");
1043}
1044
1045static void do_exit_on_complete(struct usb_ep *ep, struct usb_request *req)
1046{
1047 puts("Booting kernel..\n");
1048 run_command("run storeboot", 0);
1049
1050 /* This only happens if image is somehow faulty so we start over */
1051 do_reset(NULL, 0, 0, NULL);
1052}
1053
1054
1055static void cb_continue(struct usb_ep *ep, struct usb_request *req)
1056{
1057 fastboot_func->in_req->complete = do_exit_on_complete;
1058 fastboot_tx_write_str("OKAY");
1059}
1060
1061static void cb_flashing(struct usb_ep *ep, struct usb_request *req)
1062{
1063 char *cmd;
1064 char* response = response_str;
1065 char *lock_s;
1066 LockData_t* info;
1067 size_t chars_left;
1068 char lock_d[LOCK_DATA_SIZE];
1069 static int cmd_index = -1;
1070
1071 lock_s = getenv("lock");
1072 if (!lock_s) {
1073 printf("lock state is NULL \n");
1074 strcpy(lock_d, "10000000");
1075 lock_s = "10000000";
1076 setenv("lock", "10000000");
1077 run_command("defenv_reserv; saveenv;", 0);
1078 } else {
1079 printf("lock state: %s\n", lock_s);
1080 strcpy(lock_d, lock_s);
1081 }
1082
1083 info = (LockData_t*)malloc(sizeof(struct LockData));
1084 memset(info,0,LOCK_DATA_SIZE);
1085 info->version_major = (int)(lock_d[0] - '0');
1086 info->version_minor = (int)(lock_d[1] - '0');
1087 info->lock_state = (int)(lock_d[4] - '0');
1088 info->lock_critical_state = (int)(lock_d[5] - '0');
1089 info->lock_bootloader = (int)(lock_d[6] - '0');
1090 dump_lock_info(info);
1091
1092 strcpy(response, "OKAY");
1093 chars_left = sizeof(response_str) - strlen(response) - 1;
1094 cmd = req->buf;
1095 strsep(&cmd, " ");
1096 printf("cb_flashing: %s\n", cmd);
1097 if (!cmd) {
1098 if ( cmd_index == -1 ) {
1099 error("missing variable\n");
1100 fastboot_tx_write_str("FAILmissing var");
1101 return;
1102 } else {
1103 fastboot_tx_write_str(response);
1104 return;
1105 }
1106 }
1107
1108 if (!strncmp(cmd, "get_unlock_ability", 18)) {
1109 cmd_index = 0;
1110 strcpy(cmd, "get_unlock_ability");
1111 if ( ++cmd_index >= 2) cmd_index = 0;
1112 else fastboot_busy(NULL);
1113 FB_MSG("flashing cmd:%s\n", cmd);
1114 chars_left = sizeof(response_str) - strlen(response) - 1;
1115 strncat(response, cmd, chars_left);
1116 strncat(response, ":", 1);
1117 chars_left -= strlen(cmd) + 1;
1118 }
1119
1120 if (!strncmp(cmd, "get_unlock_bootloader_nonce", 27)) {
1121 cmd_index = 0;
1122 strcpy(cmd, "get_unlock_bootloader_nonce");
1123 if ( ++cmd_index >= 2) cmd_index = 0;
1124 else fastboot_busy(NULL);
1125 FB_MSG("flashing cmd:%s\n", cmd);
1126 chars_left = sizeof(response_str) - strlen(response) - 1;
1127 strncat(response, cmd, chars_left);
1128 strncat(response, ":", 1);
1129 chars_left -= strlen(cmd) + 1;
1130 }
1131
1132 if (!strcmp_l1("unlock_critical", cmd)) {
1133 info->lock_critical_state = 0;
1134 } else if (!strcmp_l1("lock_critical", cmd)) {
1135 info->lock_critical_state = 1;
1136 } else if (!strcmp_l1("get_unlock_ability", cmd)) {
1137 char str_num[1];
1138 sprintf(str_num, "%d", info->lock_state);
1139 strncat(response, str_num, chars_left);
1140 } else if (!strcmp_l1("get_unlock_bootloader_nonce", cmd)) {
1141 char str_num[1];
1142 sprintf(str_num, "%d", info->lock_critical_state);
1143 strncat(response, str_num, chars_left);
1144 } else if (!strcmp_l1("unlock_bootloader", cmd)) {
1145 strncat(response, "please run flashing unlock & flashing unlock_critical before write", chars_left);
1146 } else if (!strcmp_l1("lock_bootloader", cmd)) {
1147 info->lock_bootloader = 1;
1148 } else if (!strcmp_l1("unlock", cmd)) {
1149 if (info->lock_state == 1 ) {
1150 char *avb_s;
1151 avb_s = getenv("avb2");
1152 if (avb_s == NULL) {
1153 run_command("get_avb_mode;", 0);
1154 avb_s = getenv("avb2");
1155 }
1156 printf("avb2: %s\n", avb_s);
1157 if (strcmp(avb_s, "1") == 0) {
1158#ifdef CONFIG_AML_ANTIROLLBACK
1159 if (avb_unlock()) {
1160 printf("unlocking device. Erasing userdata partition!\n");
1161 run_command("store erase partition data", 0);
1162 } else {
1163 printf("unlock failed!\n");
1164 }
1165#else
1166 printf("unlocking device. Erasing userdata partition!\n");
1167 run_command("store erase partition data", 0);
1168#endif
1169 }
1170 }
1171 info->lock_state = 0;
1172 info->lock_critical_state = 0;
1173 } else if (!strcmp_l1("lock", cmd)) {
1174 if (info->lock_state == 0 ) {
1175 char *avb_s;
1176 avb_s = getenv("avb2");
1177 if (avb_s == NULL) {
1178 run_command("get_avb_mode;", 0);
1179 avb_s = getenv("avb2");
1180 }
1181 printf("avb2: %s\n", avb_s);
1182 if (strcmp(avb_s, "1") == 0) {
1183#ifdef CONFIG_AML_ANTIROLLBACK
1184 if (avb_lock()) {
1185 printf("lock failed!\n");
1186 } else {
1187 printf("locking device. Erasing userdata partition!\n");
1188 run_command("store erase partition data", 0);
1189 }
1190#else
1191 printf("locking device. Erasing userdata partition!\n");
1192 run_command("store erase partition data", 0);
1193#endif
1194 }
1195 }
1196 info->lock_state = 1;
1197 } else {
1198 error("unknown variable: %s\n", cmd);
1199 strcpy(response, "FAILVariable not implemented");
1200 }
1201
1202 dump_lock_info(info);
1203 sprintf(lock_d, "%d%d00%d%d%d0", info->version_major, info->version_minor, info->lock_state, info->lock_critical_state, info->lock_bootloader);
1204 printf("lock_d state: %s\n", lock_d);
1205 setenv("lock", lock_d);
1206 run_command("defenv_reserv; saveenv;", 0);
1207 printf("response: %s\n", response);
1208
1209 fastboot_tx_write_str(response);
1210}
1211
1212
1213#ifdef CONFIG_FASTBOOT_FLASH
1214static void cb_flash(struct usb_ep *ep, struct usb_request *req)
1215{
1216 char *cmd = req->buf;
1217 char* response = response_str;
1218
1219 printf("cmd cb_flash is %s\n", cmd);
1220
1221 strsep(&cmd, ":");
1222 if (!cmd) {
1223 error("missing partition name\n");
1224 fastboot_tx_write_str("FAILmissing partition name");
1225 return;
1226 }
1227
1228 if (check_lock()) {
1229 error("device is locked, can not run this cmd.Please flashing unlock & flashing unlock_critical\n");
1230 fastboot_tx_write_str("FAILlocked device");
1231 return;
1232 }
1233
1234#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
1235 if (dynamic_partition) {
1236 if (is_partition_logical(cmd) == 0) {
1237 error("%s is logic partition, can not write here.......\n", cmd);
1238 fastboot_tx_write_str("FAILlogic partition");
1239 return;
1240 }
1241 }
1242#endif
1243
1244 printf("partition is %s\n", cmd);
1245 if (strcmp(cmd, "userdata") == 0) {
1246 strcpy(cmd, "data");
1247 printf("partition is %s\n", cmd);
1248 }
1249
1250 if (strcmp(cmd, "dts") == 0) {
1251 strcpy(cmd, "dtb");
1252 printf("partition is %s\n", cmd);
1253 }
1254
1255 //strcpy(response, "FAILno flash device defined");
1256 if (is_mainstorage_emmc()) {
1257#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
1258 fb_mmc_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR,
1259 download_bytes);
1260#endif
1261 } else if (is_mainstorage_nand()) {
1262#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
1263 fb_nand_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR,
1264 download_bytes);
1265#else
1266 fastboot_fail("not support nftl\n");
1267#endif
1268 } else {
1269 printf("error: no valid fastboot device\n");
1270 fastboot_fail("no vaild device\n");
1271 }
1272 fastboot_tx_write_str(response);
1273}
1274#endif
1275
1276static void cb_set_active(struct usb_ep *ep, struct usb_request *req)
1277{
1278 char *cmd = req->buf;
1279 //char response[RESPONSE_LEN];
1280 int ret = 0;
1281 char str[128];
1282
1283 printf("cmd cb_set_active is %s\n", cmd);
1284 strsep(&cmd, ":");
1285 if (!cmd) {
1286 error("missing slot name\n");
1287 fastboot_tx_write_str("FAILmissing slot name");
1288 return;
1289 }
1290
1291 if (check_lock()) {
1292 error("device is locked, can not run this cmd.Please flashing unlock & flashing unlock_critical\n");
1293 fastboot_tx_write_str("FAILlocked device");
1294 return;
1295 }
1296
1297 sprintf(str, "set_active_slot %s", cmd);
1298 printf("command: %s\n", str);
1299 ret = run_command(str, 0);
1300 printf("ret = %d\n", ret);
1301 if (ret == 0)
1302 fastboot_tx_write_str("OKAY");
1303 else
1304 fastboot_tx_write_str("FAILset slot error");
1305}
1306
1307static void cb_flashall(struct usb_ep *ep, struct usb_request *req)
1308{
1309 char* response = response_str;
1310 char *cmd = req->buf;
1311
1312 printf("cmd cb_flashall is %s\n", cmd);
1313
1314 if (check_lock()) {
1315 error("device is locked, can not run this cmd.Please flashing unlock & flashing unlock_critical\n");
1316 fastboot_tx_write_str("FAILlocked device");
1317 return;
1318 }
1319
1320 //strcpy(response, "FAILno flash device defined");
1321 if (is_mainstorage_emmc()) {
1322#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
1323 fb_mmc_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR,
1324 download_bytes);
1325#endif
1326 } else if (is_mainstorage_nand()) {
1327#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
1328 fb_nand_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR,
1329 download_bytes);
1330#else
1331 fastboot_fail("not support nftl\n");
1332#endif
1333 } else {
1334 printf("error: no valid fastboot device\n");
1335 fastboot_fail("no vaild device\n");
1336 }
1337 fastboot_tx_write_str(response);
1338}
1339
1340static void cb_erase(struct usb_ep *ep, struct usb_request *req)
1341{
1342 char* response = response_str;
1343 char *cmd = req->buf;
1344
1345 printf("cmd cb_erase is %s\n", cmd);
1346
1347 strsep(&cmd, ":");
1348 if (!cmd) {
1349 error("missing partition name\n");
1350 fastboot_tx_write_str("FAILmissing partition name");
1351 return;
1352 }
1353
1354 if (check_lock()) {
1355 error("device is locked, can not run this cmd.Please flashing unlock & flashing unlock_critical\n");
1356 fastboot_tx_write_str("FAILlocked device");
1357 return;
1358 }
1359
1360 printf("partition is %s\n", cmd);
1361 if (strcmp(cmd, "userdata") == 0) {
1362 strcpy(cmd, "data");
1363 printf("partition is %s\n", cmd);
1364 }
1365
1366 if (strcmp(cmd, "dts") == 0) {
1367 strcpy(cmd, "dtb");
1368 printf("partition is %s\n", cmd);
1369 }
1370
1371 //strcpy(response, "FAILno erase device defined");
1372 if (is_mainstorage_emmc()) {
1373#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
1374 fb_mmc_erase_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR);
1375#endif
1376 } else if (is_mainstorage_nand()) {
1377#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
1378 fb_nand_erase(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR);
1379#else
1380 fastboot_fail("not support nftl\n");
1381#endif
1382 } else {
1383 printf("error: no valid fastboot device\n");
1384 fastboot_fail("no vaild device\n");
1385 }
1386 fastboot_tx_write_str(response);
1387}
1388
1389static void cb_devices(struct usb_ep *ep, struct usb_request *req)
1390{
1391 char response[RESPONSE_LEN];
1392 char *cmd = req->buf;
1393
1394 printf("cmd is %s\n", cmd);
1395
1396 strcpy(response, "AMLOGIC");
1397
1398 fastboot_tx_write_str(response);
1399}
1400
1401static void cb_oem_cmd(struct usb_ep *ep, struct usb_request *req)
1402{
1403 char response[RESPONSE_LEN/2 + 1];
1404 char* cmd = req->buf;
1405 printf("oem cmd[%s]\n", cmd);
1406 static int i = 0;
1407
1408 memcpy(response, cmd, strnlen(cmd, RESPONSE_LEN/2)+1);//+1 to terminate str
1409 cmd = response;
1410 strsep(&cmd, " ");
1411 FB_MSG("To run cmd[%s]\n", cmd);
1412 run_command(cmd, 0);
1413
1414 if (++i > 3) i = 0;
1415
1416 i ? fastboot_busy("AMLOGIC") : fastboot_okay(response);
1417 fastboot_tx_write_str(response_str);
1418 return ;
1419}
1420
1421struct cmd_dispatch_info {
1422 char *cmd;
1423 void (*cb)(struct usb_ep *ep, struct usb_request *req);
1424};
1425
1426static const struct cmd_dispatch_info cmd_dispatch_info[] = {
1427 {
1428 .cmd = "reboot",
1429 .cb = cb_reboot,
1430 }, {
1431 .cmd = "getvar:",
1432 .cb = cb_getvar,
1433 }, {
1434 .cmd = "download:",
1435 .cb = cb_download,
1436 }, {
1437 .cmd = "boot",
1438 .cb = cb_boot,
1439 }, {
1440 .cmd = "continue",
1441 .cb = cb_continue,
1442 }, {
1443 .cmd = "flashing",
1444 .cb = cb_flashing,
1445 },
1446#ifdef CONFIG_FASTBOOT_FLASH
1447 {
1448 .cmd = "flash",
1449 .cb = cb_flash,
1450 },
1451#endif
1452 {
1453 .cmd = "update",
1454 .cb = cb_download,
1455 },
1456 {
1457 .cmd = "flashall",
1458 .cb = cb_flashall,
1459 },
1460 {
1461 .cmd = "erase",
1462 .cb = cb_erase,
1463 },
1464 {
1465 .cmd = "devices",
1466 .cb = cb_devices,
1467 },
1468 {
1469 .cmd = "reboot-bootloader",
1470 .cb = cb_reboot,
1471 },
1472 {
1473 .cmd = "reboot-fastboot",
1474 .cb = cb_reboot,
1475 },
1476 {
1477 .cmd = "set_active",
1478 .cb = cb_set_active,
1479 },
1480 {
1481 .cmd = "oem",
1482 .cb = cb_oem_cmd,
1483 }
1484};
1485
1486//cb for out_req->complete
1487static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
1488{
1489 char *cmdbuf = req->buf;
1490 void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
1491 int i;
1492
1493 for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
1494 if (!strcmp_l1(cmd_dispatch_info[i].cmd, cmdbuf)) {
1495 func_cb = cmd_dispatch_info[i].cb;
1496 break;
1497 }
1498 }
1499
1500 if (!func_cb) {
1501 error("unknown command: %s\n", cmdbuf);
1502 fastboot_tx_write_str("FAILunknown command");
1503 } else {
1504 if (req->actual < req->length) {
1505 u8 *buf = (u8 *)req->buf;
1506 buf[req->actual] = 0;
1507 func_cb(ep, req);
1508 } else {
1509 error("buffer overflow\n");
1510 fastboot_tx_write_str("FAILbuffer overflow");
1511 }
1512 }
1513
1514 if (req->status == 0 && !fastboot_is_busy()) {
1515 *cmdbuf = '\0';
1516 req->actual = 0;
1517 usb_ep_queue(ep, req, 0);
1518 }
1519}
1520