summaryrefslogtreecommitdiff
path: root/drivers/usb/gadget/f_fastboot.c (plain)
blob: 950c2450d089c1a744cd729decfb6292b91c9da4
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", 5);
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", 5);
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;
361 int status;
362
363 if (fastboot_func == NULL) {
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 } else {
371 f_fb = fastboot_func;
372 }
373
374 f_fb->usb_function.name = "f_fastboot";
375 f_fb->usb_function.hs_descriptors = fb_runtime_descs;
376 f_fb->usb_function.bind = fastboot_bind;
377 f_fb->usb_function.unbind = fastboot_unbind;
378 f_fb->usb_function.set_alt = fastboot_set_alt;
379 f_fb->usb_function.disable = fastboot_disable;
380 f_fb->usb_function.strings = fastboot_strings;
381 f_fb->usb_function.setup = fastboot_setup;
382
383 status = usb_add_function(c, &f_fb->usb_function);
384 if (status) {
385 free(f_fb);
386 fastboot_func = NULL;
387 }
388
389 return status;
390}
391DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add);
392
393static int fastboot_tx_write(const char *buffer, unsigned int buffer_size)
394{
395 struct usb_request *in_req = fastboot_func->in_req;
396 int ret;
397
398 memcpy(in_req->buf, buffer, buffer_size);
399 in_req->length = buffer_size;
400 ret = usb_ep_queue(fastboot_func->in_ep, in_req, 0);
401 if (ret)
402 printf("Error %d on queue\n", ret);
403 return 0;
404}
405
406static int fastboot_tx_write_str(const char *buffer)
407{
408 return fastboot_tx_write(buffer, strlen(buffer));
409}
410
411static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
412{
413 do_reset(NULL, 0, 0, NULL);
414}
415
416static void compl_do_reboot_bootloader(struct usb_ep *ep, struct usb_request *req)
417{
418 if (dynamic_partition)
419 run_command("reboot bootloader", 0);
420 else
421 run_command("reboot fastboot", 0);
422}
423
424static void compl_do_reboot_fastboot(struct usb_ep *ep, struct usb_request *req)
425{
426 f_dwc_otg_pullup(0);
427 run_command("reboot fastboot", 0);
428}
429
430static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
431{
432 char *cmd = req->buf;
433
434 printf("cmd cb_reboot is %s\n", cmd);
435
436 strsep(&cmd, "-");
437 if (!cmd) {
438 fastboot_func->in_req->complete = compl_do_reset;
439 fastboot_tx_write_str("OKAY");
440 return;
441 }
442
443 printf("cmd cb_reboot is %s\n", cmd);
444 if (strcmp(cmd, "bootloader") == 0)
445 fastboot_func->in_req->complete = compl_do_reboot_bootloader;
446 else if (strcmp(cmd, "fastboot") == 0)
447 fastboot_func->in_req->complete = compl_do_reboot_fastboot;
448
449 fastboot_tx_write_str("OKAY");
450}
451
452static int strcmp_l1(const char *s1, const char *s2)
453{
454 if (!s1 || !s2)
455 return -1;
456 return strncmp(s1, s2, strlen(s1));
457}
458
459void dump_lock_info(LockData_t* info)
460{
461 printf("info->version_major = %d\n", info->version_major);
462 printf("info->version_minor = %d\n", info->version_minor);
463 printf("info->lock_state = %d\n", info->lock_state);
464 printf("info->lock_critical_state = %d\n", info->lock_critical_state);
465 printf("info->lock_bootloader = %d\n", info->lock_bootloader);
466}
467
468
469static int check_lock(void)
470{
471 char *lock_s;
472 LockData_t* info;
473
474 lock_s = getenv("lock");
475 if (!lock_s) {
476 printf("lock state is NULL \n");
477 lock_s = "10000000";
478 setenv("lock", "10000000");
479 run_command("defenv_reserv; saveenv;", 0);
480 }
481 printf("lock state: %s\n", lock_s);
482
483 info = malloc(sizeof(struct LockData));
484 if (info) {
485 memset(info,0,LOCK_DATA_SIZE);
486 info->version_major = (int)(lock_s[0] - '0');
487 info->version_minor = (int)(lock_s[1] - '0');
488 info->lock_state = (int)(lock_s[4] - '0');
489 info->lock_critical_state = (int)(lock_s[5] - '0');
490 info->lock_bootloader = (int)(lock_s[6] - '0');
491
492 dump_lock_info(info);
493 } else
494 return 0;
495
496 if ((info->lock_state == 1 ) || ( info->lock_critical_state == 1 )) {
497 free (info);
498 return 1;
499 }
500 else {
501 free (info);
502 return 0;
503 }
504}
505
506static const char* getvar_list[] = {
507 "version-baseband", "version-bootloader", "version", "hw-revision", "max-download-size",
508 "serialno", "product", "off-mode-charge", "variant", "battery-soc-ok",
509 "battery-voltage", "partition-type:boot", "partition-size:boot",
510 "partition-type:system", "partition-size:system", "partition-type:vendor", "partition-size:vendor",
511 "partition-type:odm", "partition-size:odm", "partition-type:data", "partition-size:data",
512 "erase-block-size", "logical-block-size", "secure", "unlocked",
513};
514
515static const char* getvar_list_dynamic[] = {
516 "hw-revision", "battery-voltage", "is-userspace", "is-logical:data",
517 "is-logical:metadata", "is-logical:misc", "is-logical:super", "is-logical:boot",
518 "is-logical:system", "is-logical:vendor", "is-logical:product", "is-logical:odm",
519 "slot-count", "max-download-size", "serialno", "product", "unlocked", "has-slot:data",
520 "has-slot:metadata", "has-slot:misc", "has-slot:super", "has-slot:boot",
521 "has-slot:system", "has-slot:vendor", "has-slot:product", "has-slot:odm",
522 "secure", "super-partition-name", "version-baseband", "version-bootloader",
523 "partition-size:boot", "partition-size:metadata", "partition-size:misc",
524 "partition-size:super", "partition-size:data", "version",
525};
526
527static const char* getvar_list_ab[] = {
528 "version-baseband", "version-bootloader", "version", "hw-revision", "max-download-size",
529 "serialno", "product", "off-mode-charge", "variant", "battery-soc-ok",
530 "battery-voltage", "partition-type:boot", "partition-size:boot",
531 "partition-type:system", "partition-size:system", "partition-type:vendor", "partition-size:vendor",
532 "partition-type:odm", "partition-size:odm", "partition-type:data", "partition-size:data",
533 "partition-type:cache", "partition-size:cache",
534 "erase-block-size", "logical-block-size", "secure", "unlocked",
535 "slot-count", "slot-suffixes","current-slot", "has-slot:bootloader", "has-slot:boot",
536 "has-slot:system", "has-slot:vendor", "has-slot:odm", "has-slot:vbmeta",
537 "has-slot:metadata", "has-slot:product", "has-slot:dtbo",
538 "slot-successful:a", "slot-unbootable:a", "slot-retry-count:a",
539 "slot-successful:b", "slot-unbootable:b", "slot-retry-count:b",
540};
541
542static void cb_getvar(struct usb_ep *ep, struct usb_request *req)
543{
544 char *cmd = req->buf;
545 char cmdBuf[RESPONSE_LEN];
546 char* response = response_str;
547 char *s;
548 char *s1;
549 char *s2;
550 char *s3;
551 char s_version[24];
552 size_t chars_left;
553
554 run_command("get_valid_slot", 0);
555
556 strcpy(response, "OKAY");
557 chars_left = sizeof(response_str) - strlen(response) - 1;
558
559 memcpy(cmdBuf, cmd, strnlen(cmd, RESPONSE_LEN-1)+1);
560 cmd = cmdBuf;
561 strsep(&cmd, ":");
562 printf("cb_getvar: %s\n", cmd);
563 if (!cmd) {
564 error("missing variable\n");
565 fastboot_tx_write_str("FAILmissing var");
566 return;
567 }
568 if (!strncmp(cmd, "all", 3)) {
569 static int cmdIndex = 0;
570 int getvar_num = 0;
571 if (has_boot_slot == 1 && strlen(getvar_list_ab[cmdIndex]) < 64) {
572 strcpy(cmd, getvar_list_ab[cmdIndex]);
573 getvar_num = (sizeof(getvar_list_ab) / sizeof(getvar_list_ab[0]));
574 } else if (dynamic_partition && strlen(getvar_list_dynamic[cmdIndex]) < 64) {
575 strcpy(cmd, getvar_list_dynamic[cmdIndex]);//only support no-arg cmd
576 getvar_num = (sizeof(getvar_list_dynamic) / sizeof(getvar_list_dynamic[0]));
577 } else if (strlen(getvar_list[cmdIndex]) < 64) {
578 strcpy(cmd, getvar_list[cmdIndex]);//only support no-arg cmd
579 getvar_num = (sizeof(getvar_list) / sizeof(getvar_list[0]));
580 }
581 printf("getvar_num: %d\n", getvar_num);
582 if ( ++cmdIndex >= getvar_num) cmdIndex = 0;
583 else fastboot_busy(NULL);
584 FB_MSG("all cmd:%s\n", cmd);
585 strncat(response, cmd, chars_left);
586 strncat(response, ":", 1);
587 chars_left -= strlen(cmd) + 1;
588 }
589
590 strcpy(s_version, "01.01.");
591 printf("U_BOOT_DATE_TIME: %s\n", U_BOOT_DATE_TIME);
592 strcat(s_version, U_BOOT_DATE_TIME);
593 printf("s_version: %s\n", s_version);
594
595 if (!strcmp_l1("version-baseband", cmd)) {
596 strncat(response, "N/A", chars_left);
597 } else if (!strcmp_l1("version-bootloader", cmd)) {
598 strncat(response, s_version, chars_left);
599 } else if (!strcmp_l1("hw-revision", cmd)) {
600 strncat(response, "0", chars_left);
601 } else if (!strcmp_l1("version", cmd)) {
602 strncat(response, FASTBOOT_VERSION, chars_left);
603 } else if (!strcmp_l1("bootloader-version", cmd)) {
604 strncat(response, s_version, chars_left);
605 } else if (!strcmp_l1("off-mode-charge", cmd)) {
606 strncat(response, "0", chars_left);
607 } else if (!strcmp_l1("variant", cmd)) {
608 strncat(response, "US", chars_left);
609 } else if (!strcmp_l1("battery-soc-ok", cmd)) {
610 strncat(response, "yes", chars_left);
611 } else if (!strcmp_l1("battery-voltage", cmd)) {
612 strncat(response, "4", chars_left);
613 } else if (!strcmp_l1("is-userspace", cmd)) {
614 if (dynamic_partition) {
615 strncat(response, "no", chars_left);
616 } else {
617 error("unknown variable: %s\n", cmd);
618 strcpy(response, "FAILVariable not implemented");
619 }
620 } else if (!strcmp_l1("is-logical", cmd)) {
621 strsep(&cmd, ":");
622 printf("partition is %s\n", cmd);
623 if (!dynamic_partition) {
624 strncat(response, "no", chars_left);
625 } else {
626#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
627 if (is_partition_logical(cmd) == 0) {
628 error("%s is logic partition\n", cmd);
629 strncat(response, "yes", chars_left);
630 } else {
631 strncat(response, "no", chars_left);
632 }
633#else
634 strncat(response, "no", chars_left);
635#endif
636 }
637 } else if (!strcmp_l1("super-partition-name", cmd)) {
638 char *slot_name;
639 slot_name = getenv("slot-suffixes");
640 if (has_boot_slot == 0) {
641 strncat(response, "super", chars_left);
642 } else {
643 printf("slot-suffixes: %s\n", slot_name);
644 if (strcmp(slot_name, "0") == 0) {
645 printf("active_slot is %s\n", "a");
646 strncat(response, "super_a", chars_left);
647 } else if (strcmp(slot_name, "1") == 0) {
648 printf("active_slot is %s\n", "b");
649 strncat(response, "super_b", chars_left);
650 }
651 }
652 } else if (!strcmp_l1("downloadsize", cmd) ||
653 !strcmp_l1("max-download-size", cmd)) {
654 char str_num[12];
655
656 sprintf(str_num, "0x%08x", ddr_size_usable(CONFIG_USB_FASTBOOT_BUF_ADDR));
657 strncat(response, str_num, chars_left);
658 } else if (!strcmp_l1("serialno", cmd)) {
659 //s = getenv("serial");
660 s = get_usid_string();
661 if (s)
662 strncat(response, s, chars_left);
663 else
664 strncat(response, DEVICE_SERIAL, chars_left);
665 } else if (!strcmp_l1("product", cmd)) {
666#ifdef DEVICE_PRODUCT
667 s1 = DEVICE_PRODUCT;
668 printf("DEVICE_PRODUCT: %s\n", s1);
669#else
670 s1 = getenv("device_product");
671 printf("device_product: %s\n", s1);
672#endif
673 strncat(response, s1, chars_left);
674 } else if (!strcmp_l1("slot-count", cmd)) {
675 if (has_boot_slot == 1)
676 strncat(response, "2", chars_left);
677 else
678 strncat(response, "0", chars_left);
679 } else if (!strcmp_l1("slot-suffixes", cmd)) {
680 s2 = getenv("slot-suffixes");
681 printf("slot-suffixes: %s\n", s2);
682 if (s2)
683 strncat(response, s2, chars_left);
684 else
685 strncat(response, "0", chars_left);
686 } else if (!strcmp_l1("current-slot", cmd)) {
687 s3 = getenv("slot-suffixes");
688 printf("slot-suffixes: %s\n", s3);
689 if (strcmp(s3, "0") == 0) {
690 printf("active_slot is %s\n", "a");
691 strncat(response, "a", chars_left);
692 } else if (strcmp(s3, "1") == 0) {
693 printf("active_slot is %s\n", "b");
694 strncat(response, "b", chars_left);
695 }
696 } else if (!strcmp_l1("has-slot:bootloader", cmd)) {
697 printf("do not has slot bootloader\n");
698 strncat(response, "no", chars_left);
699 } else if (!strcmp_l1("has-slot:boot", cmd)) {
700 if (has_boot_slot == 1) {
701 printf("has boot slot\n");
702 strncat(response, "yes", chars_left);
703 } else
704 strncat(response, "no", chars_left);
705 } else if (!strcmp_l1("has-slot:system", cmd)) {
706 if (dynamic_partition) {
707 strncat(response, "no", chars_left);
708 } else {
709 if (has_system_slot == 1) {
710 printf("has system slot\n");
711 strncat(response, "yes", chars_left);
712 } else
713 strncat(response, "no", chars_left);
714 }
715 } else if (!strcmp_l1("has-slot:vendor", cmd)) {
716 if (dynamic_partition) {
717 strncat(response, "no", chars_left);
718 } else {
719 if (has_boot_slot == 1) {
720 printf("has vendor slot\n");
721 strncat(response, "yes", chars_left);
722 } else
723 strncat(response, "no", chars_left);
724 }
725 } else if (!strcmp_l1("has-slot:vbmeta", cmd)) {
726 if (dynamic_partition) {
727 strncat(response, "no", chars_left);
728 } else {
729 if (has_boot_slot == 1) {
730 printf("has vbmeta slot\n");
731 strncat(response, "yes", chars_left);
732 } else
733 strncat(response, "no", chars_left);
734 }
735 } else if (!strcmp_l1("has-slot:product", cmd)) {
736 if (dynamic_partition) {
737 strncat(response, "no", chars_left);
738 } else {
739 if (has_boot_slot == 1) {
740 printf("has product slot\n");
741 strncat(response, "yes", chars_left);
742 } else
743 strncat(response, "no", chars_left);
744 }
745 } else if (!strcmp_l1("has-slot:super", cmd)) {
746 if (!dynamic_partition) {
747 strncat(response, "no", chars_left);
748 } else {
749 if (has_boot_slot == 1) {
750 printf("has product slot\n");
751 strncat(response, "yes", chars_left);
752 } else
753 strncat(response, "no", chars_left);
754 }
755 } else if (!strcmp_l1("has-slot:metadata", cmd)) {
756 if (has_boot_slot == 1) {
757 printf("has metadata slot\n");
758 strncat(response, "yes", chars_left);
759 } else
760 strncat(response, "no", chars_left);
761 } else if (!strcmp_l1("has-slot:dtbo", cmd)) {
762 if (has_boot_slot == 1) {
763 printf("has dtbo slot\n");
764 strncat(response, "yes", chars_left);
765 } else
766 strncat(response, "no", chars_left);
767 } else if (!strcmp_l1("has-slot:data", cmd)) {
768 strncat(response, "no", chars_left);
769 } else if (!strcmp_l1("has-slot:misc", cmd)) {
770 strncat(response, "no", chars_left);
771 } else if (!strcmp_l1("has-slot:odm", cmd)) {
772 if (has_boot_slot == 1) {
773 printf("has odm slot\n");
774 strncat(response, "yes", chars_left);
775 } else
776 strncat(response, "no", chars_left);
777 } else if (!strncmp("partition-size", cmd, strlen("partition-size"))) {
778 char str_num[20];
779 struct partitions *pPartition;
780 uint64_t sz;
781 strsep(&cmd, ":");
782 printf("partition is %s\n", cmd);
783 if (strcmp(cmd, "userdata") == 0) {
784 strcpy(cmd, "data");
785 printf("partition is %s\n", cmd);
786 }
787 if (!strncmp("mbr", cmd, strlen("mbr"))) {
788 strcpy(response, "FAILVariable not implemented");
789 } else {
790 if (!strncmp("bootloader-", cmd, strlen("bootloader-"))) {
791 strsep(&cmd, "-");
792 mmc_boot_size(cmd, &sz);
793 printf("size:%016llx\n", sz);
794 sprintf(str_num, "%016llx", sz);
795 } else {
796 pPartition = find_mmc_partition_by_name(cmd);
797 if (pPartition) {
798 printf("size:%016llx\n", pPartition->size);
799 if (strcmp(cmd, "data") == 0) {
800 printf("reserve 0x4000 for fde data\n");
801 sz = pPartition->size - 0x4000;
802 printf("data size :%016llx\n", sz);
803 sprintf(str_num, "%016llx", sz);
804 } else {
805 sprintf(str_num, "%016llx", pPartition->size);
806 }
807 } else {
808 printf("find_mmc_partition_by_name fail\n");
809 sprintf(str_num, "get fail");
810 }
811 }
812 strncat(response, str_num, chars_left);
813 }
814 } else if (!strcmp_l1("partition-type:cache", cmd)) {
815 if (has_boot_slot == 0) {
816 strncat(response, "ext4", chars_left);
817 }
818 } else if (!strcmp_l1("partition-type:data", cmd)) {
819 strncat(response, "ext4", chars_left);
820 } else if (!strcmp_l1("partition-type:userdata", cmd)) {
821 strncat(response, "ext4", chars_left);
822 } else if (!strcmp_l1("partition-type:system", cmd)) {
823 strncat(response, "ext4", chars_left);
824 } else if (!strcmp_l1("partition-type:vendor", cmd)) {
825 strncat(response, "ext4", chars_left);
826 } else if (!strcmp_l1("partition-type:odm", cmd)) {
827 strncat(response, "ext4", chars_left);
828 } else if (!strcmp_l1("partition-type:tee", cmd)) {
829 strncat(response, "ext4", chars_left);
830 } else if (!strcmp_l1("partition-type:param", cmd)) {
831 strncat(response, "ext4", chars_left);
832 } else if (!strcmp_l1("partition-type:product", cmd)) {
833 strncat(response, "ext4", chars_left);
834 } else if (!strcmp_l1("partition-type:metadata", cmd)) {
835 strncat(response, "ext4", chars_left);
836 } else if (!strncmp("partition-type", cmd, strlen("partition-type"))) {
837 strncat(response, "raw", chars_left);
838 } else if (!strcmp_l1("erase-block-size", cmd) ||
839 !strcmp_l1("logical-block-size", cmd)) {
840 strncat(response, "2000", chars_left);
841 } else if (!strcmp_l1("secure", cmd)) {
842 if (check_lock()) {
843 strncat(response, "yes", chars_left);
844 } else {
845 strncat(response, "no", chars_left);
846 }
847 } else if (!strcmp_l1("unlocked", cmd)) {
848 if (check_lock()) {
849 strncat(response, "no", chars_left);
850 } else {
851 strncat(response, "yes", chars_left);
852 }
853 } else if (!strcmp_l1("slot-successful", cmd)) {
854 char str[128];
855 strsep(&cmd, ":");
856 printf("cmd is %s\n", cmd);
857 int ret;
858 if (has_boot_slot == 1) {
859 printf("has boot slot\n");
860 sprintf(str, "get_slot_state %s successful", cmd);
861 printf("command: %s\n", str);
862 ret = run_command(str, 0);
863 printf("ret = %d\n", ret);
864 if (ret == 0)
865 strncat(response, "no", chars_left);
866 else
867 strncat(response, "yes", chars_left);
868 } else
869 strcpy(response, "FAILVariable not implemented in non ab mode");
870 } else if (!strcmp_l1("slot-unbootable", cmd)) {
871 char str[128];
872 strsep(&cmd, ":");
873 printf("cmd is %s\n", cmd);
874 int ret;
875 if (has_boot_slot == 1) {
876 printf("has boot slot\n");
877 sprintf(str, "get_slot_state %s unbootable", cmd);
878 printf("command: %s\n", str);
879 ret = run_command(str, 0);
880 printf("ret = %d\n", ret);
881 if (ret == 0)
882 strncat(response, "yes", chars_left);
883 else
884 strncat(response, "no", chars_left);
885 } else
886 strcpy(response, "FAILVariable not implemented in non ab mode");
887 } else if (!strcmp_l1("slot-retry-count", cmd)) {
888 char str[128];
889 strsep(&cmd, ":");
890 printf("cmd is %s\n", cmd);
891 int ret;
892 if (has_boot_slot == 1) {
893 char str_num[12];
894 printf("has boot slot\n");
895 sprintf(str, "get_slot_state %s retry-count", cmd);
896 printf("command: %s\n", str);
897 ret = run_command(str, 0);
898 printf("ret = %d\n", ret);
899 sprintf(str_num, "%d", ret);
900 strncat(response, str_num, chars_left);
901 } else
902 strcpy(response, "FAILVariable not implemented in non ab mode");
903 } else {
904 error("unknown variable: %s\n", cmd);
905 strcpy(response, "FAILVariable not implemented");
906 }
907
908 fastboot_tx_write_str(response);
909}
910
911static unsigned int rx_bytes_expected(void)
912{
913 int rx_remain = download_size - download_bytes;
914 if (rx_remain < 0)
915 return 0;
916 if (rx_remain > EP_BUFFER_SIZE)
917 return EP_BUFFER_SIZE;
918 return rx_remain;
919}
920
921#define BYTES_PER_DOT 0x20000
922static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
923{
924 char response[RESPONSE_LEN];
925 unsigned int transfer_size = download_size - download_bytes;
926 const unsigned char *buffer = req->buf;
927 unsigned int buffer_size = req->actual;
928 unsigned int pre_dot_num, now_dot_num;
929
930 if (req->status != 0) {
931 printf("Bad status: %d\n", req->status);
932 return;
933 }
934
935 if (buffer_size < transfer_size)
936 transfer_size = buffer_size;
937
938 memcpy((void *)CONFIG_USB_FASTBOOT_BUF_ADDR + download_bytes,
939 buffer, transfer_size);
940
941 pre_dot_num = download_bytes / BYTES_PER_DOT;
942 download_bytes += transfer_size;
943 now_dot_num = download_bytes / BYTES_PER_DOT;
944
945 if (pre_dot_num != now_dot_num) {
946 putc('.');
947 if (!(now_dot_num % 74))
948 putc('\n');
949 }
950
951 /* Check if transfer is done */
952 if (download_bytes >= download_size) {
953 /*
954 * Reset global transfer variable, keep download_bytes because
955 * it will be used in the next possible flashing command
956 */
957 download_size = 0;
958 req->complete = rx_handler_command;
959 req->length = EP_BUFFER_SIZE;
960
961 sprintf(response, "OKAY");
962 fastboot_tx_write_str(response);
963
964 printf("\ndownloading of %d bytes finished\n", download_bytes);
965 } else {
966 req->length = rx_bytes_expected();
967 if (req->length < ep->maxpacket)
968 req->length = ep->maxpacket;
969 }
970
971 req->actual = 0;
972 usb_ep_queue(ep, req, 0);
973}
974
975static void cb_download(struct usb_ep *ep, struct usb_request *req)
976{
977 char *cmd = req->buf;
978 char response[RESPONSE_LEN];
979
980 printf("cmd cb_download is %s\n", cmd);
981
982 strsep(&cmd, ":");
983 download_size = simple_strtoul(cmd, NULL, 16);
984 download_bytes = 0;
985
986 printf("Starting download of %d bytes\n", download_size);
987
988 if (0 == download_size) {
989 sprintf(response, "FAILdata invalid size");
990 } else if (download_size > ddr_size_usable(CONFIG_USB_FASTBOOT_BUF_ADDR)) {
991 download_size = 0;
992 sprintf(response, "FAILdata too large");
993 } else {
994 sprintf(response, "DATA%08x", download_size);
995 req->complete = rx_handler_dl_image;
996 req->length = rx_bytes_expected();
997 if (req->length < ep->maxpacket)
998 req->length = ep->maxpacket;
999 }
1000 fastboot_tx_write_str(response);
1001}
1002
1003typedef struct andr_img_hdr boot_img_hdr;
1004
1005static void do_bootm_on_complete(struct usb_ep *ep, struct usb_request *req)
1006{
1007 char boot_addr_start[12];
1008 unsigned kernel_size;
1009 unsigned ramdisk_size;
1010 boot_img_hdr *hdr_addr = NULL;
1011 int genFmt = 0;
1012 unsigned actualBootImgSz = 0;
1013 unsigned dtbSz = 0;
1014 unsigned char* loadaddr = 0;
1015
1016 puts("Booting kernel...\n");
1017
1018 sprintf(boot_addr_start, "bootm 0x%lx", load_addr);
1019 printf("boot_addr_start %s\n", boot_addr_start);
1020
1021 loadaddr = (unsigned char*)CONFIG_USB_FASTBOOT_BUF_ADDR;
1022 hdr_addr = (boot_img_hdr*)loadaddr;
1023
1024 genFmt = genimg_get_format(hdr_addr);
1025 if (IMAGE_FORMAT_ANDROID != genFmt) {
1026 printf("Fmt unsupported!genFmt 0x%x != 0x%x\n", genFmt, IMAGE_FORMAT_ANDROID);
1027 return;
1028 }
1029
1030 kernel_size =(hdr_addr->kernel_size + (hdr_addr->page_size-1)+hdr_addr->page_size)&(~(hdr_addr->page_size -1));
1031 ramdisk_size =(hdr_addr->ramdisk_size + (hdr_addr->page_size-1))&(~(hdr_addr->page_size -1));
1032 dtbSz = hdr_addr->second_size;
1033 actualBootImgSz = kernel_size + ramdisk_size + dtbSz;
1034 printf("kernel_size 0x%x, page_size 0x%x, totalSz 0x%x\n", hdr_addr->kernel_size, hdr_addr->page_size, kernel_size);
1035 printf("ramdisk_size 0x%x, totalSz 0x%x\n", hdr_addr->ramdisk_size, ramdisk_size);
1036 printf("dtbSz 0x%x, Total actualBootImgSz 0x%x\n", dtbSz, actualBootImgSz);
1037
1038 memcpy((void *)load_addr, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR, actualBootImgSz);
1039
1040 flush_cache(load_addr,(unsigned long)actualBootImgSz);
1041
1042 run_command(boot_addr_start, 0);
1043
1044 /* This only happens if image is somehow faulty so we start over */
1045 do_reset(NULL, 0, 0, NULL);
1046}
1047
1048static void cb_boot(struct usb_ep *ep, struct usb_request *req)
1049{
1050 fastboot_func->in_req->complete = do_bootm_on_complete;
1051 fastboot_tx_write_str("OKAY");
1052}
1053
1054static void do_exit_on_complete(struct usb_ep *ep, struct usb_request *req)
1055{
1056 puts("Booting kernel..\n");
1057 run_command("run storeboot", 0);
1058
1059 /* This only happens if image is somehow faulty so we start over */
1060 do_reset(NULL, 0, 0, NULL);
1061}
1062
1063
1064static void cb_continue(struct usb_ep *ep, struct usb_request *req)
1065{
1066 fastboot_func->in_req->complete = do_exit_on_complete;
1067 fastboot_tx_write_str("OKAY");
1068}
1069
1070static void cb_flashing(struct usb_ep *ep, struct usb_request *req)
1071{
1072 char *cmd;
1073 char* response = response_str;
1074 char* lock_s;
1075 LockData_t* info;
1076 size_t chars_left;
1077 char lock_d[LOCK_DATA_SIZE];
1078
1079 lock_s = getenv("lock");
1080 if (!lock_s) {
1081 printf("lock state is NULL \n");
1082 strcpy(lock_d, "10000000");
1083 lock_s = "10000000";
1084 setenv("lock", "10000000");
1085 run_command("defenv_reserv; saveenv;", 0);
1086 } else {
1087 printf("lock state: %s\n", lock_s);
1088 if (strlen(lock_s) > 15)
1089 strncpy(lock_d, lock_s, 15);
1090 else
1091 strncpy(lock_d, lock_s, strlen(lock_s));
1092 }
1093
1094 info = malloc(sizeof(struct LockData));
1095 if (!info) {
1096 error("malloc error\n");
1097 fastboot_tx_write_str("FAILmalloc error");
1098 return;
1099 }
1100 memset(info,0,LOCK_DATA_SIZE);
1101 info->version_major = (int)(lock_d[0] - '0');
1102 info->version_minor = (int)(lock_d[1] - '0');
1103 info->lock_state = (int)(lock_d[4] - '0');
1104 info->lock_critical_state = (int)(lock_d[5] - '0');
1105 info->lock_bootloader = (int)(lock_d[6] - '0');
1106 dump_lock_info(info);
1107
1108 strcpy(response, "OKAY");
1109 chars_left = sizeof(response_str) - strlen(response) - 1;
1110 cmd = req->buf;
1111 strsep(&cmd, " ");
1112 printf("cb_flashing: %s\n", cmd);
1113 if (!cmd) {
1114 error("missing variable\n");
1115 fastboot_tx_write_str("FAILmissing var");
1116 free(info);
1117 return;
1118 }
1119
1120 if (!strcmp_l1("unlock_critical", cmd)) {
1121 info->lock_critical_state = 0;
1122 } else if (!strcmp_l1("lock_critical", cmd)) {
1123 info->lock_critical_state = 1;
1124 } else if (!strcmp_l1("get_unlock_ability", cmd)) {
1125 char str_num[8];
1126 sprintf(str_num, "%d", info->lock_state);
1127 strncat(response, str_num, chars_left);
1128 } else if (!strcmp_l1("get_unlock_bootloader_nonce", cmd)) {
1129 char str_num[8];
1130 sprintf(str_num, "%d", info->lock_critical_state);
1131 strncat(response, str_num, chars_left);
1132 } else if (!strcmp_l1("unlock_bootloader", cmd)) {
1133 strncat(response, "please run flashing unlock & flashing unlock_critical before write", chars_left);
1134 } else if (!strcmp_l1("lock_bootloader", cmd)) {
1135 info->lock_bootloader = 1;
1136 } else if (!strcmp_l1("unlock", cmd)) {
1137 if (info->lock_state == 1 ) {
1138 char *avb_s;
1139 avb_s = getenv("avb2");
1140 if (avb_s == NULL) {
1141 run_command("get_avb_mode;", 0);
1142 avb_s = getenv("avb2");
1143 }
1144 printf("avb2: %s\n", avb_s);
1145 if (strcmp(avb_s, "1") == 0) {
1146#ifdef CONFIG_AML_ANTIROLLBACK
1147 if (avb_unlock()) {
1148 printf("unlocking device. Erasing userdata partition!\n");
1149 run_command("store erase partition data", 0);
1150 } else {
1151 printf("unlock failed!\n");
1152 }
1153#else
1154 printf("unlocking device. Erasing userdata partition!\n");
1155 run_command("store erase partition data", 0);
1156#endif
1157 }
1158 }
1159 info->lock_state = 0;
1160 info->lock_critical_state = 0;
1161 } else if (!strcmp_l1("lock", cmd)) {
1162 if (info->lock_state == 0 ) {
1163 char *avb_s;
1164 avb_s = getenv("avb2");
1165 if (avb_s == NULL) {
1166 run_command("get_avb_mode;", 0);
1167 avb_s = getenv("avb2");
1168 }
1169 printf("avb2: %s\n", avb_s);
1170 if (strcmp(avb_s, "1") == 0) {
1171#ifdef CONFIG_AML_ANTIROLLBACK
1172 if (avb_lock()) {
1173 printf("lock failed!\n");
1174 } else {
1175 printf("locking device. Erasing userdata partition!\n");
1176 run_command("store erase partition data", 0);
1177 }
1178#else
1179 printf("locking device. Erasing userdata partition!\n");
1180 run_command("store erase partition data", 0);
1181#endif
1182 }
1183 }
1184 info->lock_state = 1;
1185 } else {
1186 error("unknown variable: %s\n", cmd);
1187 strcpy(response, "FAILVariable not implemented");
1188 }
1189
1190 dump_lock_info(info);
1191 sprintf(lock_d, "%d%d00%d%d%d0", info->version_major, info->version_minor, info->lock_state, info->lock_critical_state, info->lock_bootloader);
1192 printf("lock_d state: %s\n", lock_d);
1193 setenv("lock", lock_d);
1194 run_command("defenv_reserv; saveenv;", 0);
1195 printf("response: %s\n", response);
1196 free(info);
1197 fastboot_tx_write_str(response);
1198}
1199
1200
1201#ifdef CONFIG_FASTBOOT_FLASH
1202static void cb_flash(struct usb_ep *ep, struct usb_request *req)
1203{
1204 char *cmd = req->buf;
1205 char* response = response_str;
1206
1207 printf("cmd cb_flash is %s\n", cmd);
1208
1209 strsep(&cmd, ":");
1210 if (!cmd) {
1211 error("missing partition name\n");
1212 fastboot_tx_write_str("FAILmissing partition name");
1213 return;
1214 }
1215
1216 if (check_lock()) {
1217 error("device is locked, can not run this cmd.Please flashing unlock & flashing unlock_critical\n");
1218 fastboot_tx_write_str("FAILlocked device");
1219 return;
1220 }
1221
1222#ifdef CONFIG_BOOTLOADER_CONTROL_BLOCK
1223 if (dynamic_partition) {
1224 if (is_partition_logical(cmd) == 0) {
1225 error("%s is logic partition, can not write here.......\n", cmd);
1226 fastboot_tx_write_str("FAILlogic partition");
1227 return;
1228 }
1229 }
1230#endif
1231
1232 printf("partition is %s\n", cmd);
1233 if (strcmp(cmd, "userdata") == 0) {
1234 strcpy(cmd, "data");
1235 printf("partition is %s\n", cmd);
1236 }
1237
1238 if (strcmp(cmd, "dts") == 0) {
1239 strcpy(cmd, "dtb");
1240 printf("partition is %s\n", cmd);
1241 }
1242
1243 //strcpy(response, "FAILno flash device defined");
1244 if (is_mainstorage_emmc()) {
1245#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
1246 fb_mmc_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR,
1247 download_bytes);
1248#endif
1249 } else if (is_mainstorage_nand()) {
1250#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
1251 fb_nand_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR,
1252 download_bytes);
1253#else
1254 fastboot_fail("not support nftl\n");
1255#endif
1256 } else {
1257 printf("error: no valid fastboot device\n");
1258 fastboot_fail("no vaild device\n");
1259 }
1260 fastboot_tx_write_str(response);
1261}
1262#endif
1263
1264static void cb_set_active(struct usb_ep *ep, struct usb_request *req)
1265{
1266 char *cmd = req->buf;
1267 //char response[RESPONSE_LEN];
1268 int ret = 0;
1269 char str[128];
1270
1271 printf("cmd cb_set_active is %s\n", cmd);
1272 strsep(&cmd, ":");
1273 if (!cmd) {
1274 error("missing slot name\n");
1275 fastboot_tx_write_str("FAILmissing slot name");
1276 return;
1277 }
1278
1279 if (check_lock()) {
1280 error("device is locked, can not run this cmd.Please flashing unlock & flashing unlock_critical\n");
1281 fastboot_tx_write_str("FAILlocked device");
1282 return;
1283 }
1284
1285 sprintf(str, "set_active_slot %s", cmd);
1286 printf("command: %s\n", str);
1287 ret = run_command(str, 0);
1288 printf("ret = %d\n", ret);
1289 if (ret == 0)
1290 fastboot_tx_write_str("OKAY");
1291 else
1292 fastboot_tx_write_str("FAILset slot error");
1293}
1294
1295static void cb_flashall(struct usb_ep *ep, struct usb_request *req)
1296{
1297 char* response = response_str;
1298 char *cmd = req->buf;
1299
1300 printf("cmd cb_flashall is %s\n", cmd);
1301
1302 if (check_lock()) {
1303 error("device is locked, can not run this cmd.Please flashing unlock & flashing unlock_critical\n");
1304 fastboot_tx_write_str("FAILlocked device");
1305 return;
1306 }
1307
1308 //strcpy(response, "FAILno flash device defined");
1309 if (is_mainstorage_emmc()) {
1310#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
1311 fb_mmc_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR,
1312 download_bytes);
1313#endif
1314 } else if (is_mainstorage_nand()) {
1315#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
1316 fb_nand_flash_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR,
1317 download_bytes);
1318#else
1319 fastboot_fail("not support nftl\n");
1320#endif
1321 } else {
1322 printf("error: no valid fastboot device\n");
1323 fastboot_fail("no vaild device\n");
1324 }
1325 fastboot_tx_write_str(response);
1326}
1327
1328static void cb_erase(struct usb_ep *ep, struct usb_request *req)
1329{
1330 char* response = response_str;
1331 char *cmd = req->buf;
1332
1333 printf("cmd cb_erase is %s\n", cmd);
1334
1335 strsep(&cmd, ":");
1336 if (!cmd) {
1337 error("missing partition name\n");
1338 fastboot_tx_write_str("FAILmissing partition name");
1339 return;
1340 }
1341
1342 if (check_lock()) {
1343 error("device is locked, can not run this cmd.Please flashing unlock & flashing unlock_critical\n");
1344 fastboot_tx_write_str("FAILlocked device");
1345 return;
1346 }
1347
1348 printf("partition is %s\n", cmd);
1349 if (strcmp(cmd, "userdata") == 0) {
1350 strcpy(cmd, "data");
1351 printf("partition is %s\n", cmd);
1352 }
1353
1354 if (strcmp(cmd, "dts") == 0) {
1355 strcpy(cmd, "dtb");
1356 printf("partition is %s\n", cmd);
1357 }
1358
1359 //strcpy(response, "FAILno erase device defined");
1360 if (is_mainstorage_emmc()) {
1361#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV
1362 fb_mmc_erase_write(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR);
1363#endif
1364 } else if (is_mainstorage_nand()) {
1365#ifdef CONFIG_FASTBOOT_FLASH_NAND_DEV
1366 fb_nand_erase(cmd, (void *)CONFIG_USB_FASTBOOT_BUF_ADDR);
1367#else
1368 fastboot_fail("not support nftl\n");
1369#endif
1370 } else {
1371 printf("error: no valid fastboot device\n");
1372 fastboot_fail("no vaild device\n");
1373 }
1374 fastboot_tx_write_str(response);
1375}
1376
1377static void cb_devices(struct usb_ep *ep, struct usb_request *req)
1378{
1379 char response[RESPONSE_LEN];
1380 char *cmd = req->buf;
1381
1382 printf("cmd is %s\n", cmd);
1383
1384 strcpy(response, "AMLOGIC");
1385
1386 fastboot_tx_write_str(response);
1387}
1388
1389static void cb_oem_cmd(struct usb_ep *ep, struct usb_request *req)
1390{
1391 char response[RESPONSE_LEN/2 + 1];
1392 char* cmd = req->buf;
1393 printf("oem cmd[%s]\n", cmd);
1394 static int i = 0;
1395
1396 memcpy(response, cmd, strnlen(cmd, RESPONSE_LEN/2)+1);//+1 to terminate str
1397 cmd = response;
1398 strsep(&cmd, " ");
1399 FB_MSG("To run cmd[%s]\n", cmd);
1400 run_command(cmd, 0);
1401
1402 if (++i > 3) i = 0;
1403
1404 i ? fastboot_busy("AMLOGIC") : fastboot_okay(response);
1405 fastboot_tx_write_str(response_str);
1406 return ;
1407}
1408
1409struct cmd_dispatch_info {
1410 char *cmd;
1411 void (*cb)(struct usb_ep *ep, struct usb_request *req);
1412};
1413
1414static const struct cmd_dispatch_info cmd_dispatch_info[] = {
1415 {
1416 .cmd = "reboot",
1417 .cb = cb_reboot,
1418 }, {
1419 .cmd = "getvar:",
1420 .cb = cb_getvar,
1421 }, {
1422 .cmd = "download:",
1423 .cb = cb_download,
1424 }, {
1425 .cmd = "boot",
1426 .cb = cb_boot,
1427 }, {
1428 .cmd = "continue",
1429 .cb = cb_continue,
1430 }, {
1431 .cmd = "flashing",
1432 .cb = cb_flashing,
1433 },
1434#ifdef CONFIG_FASTBOOT_FLASH
1435 {
1436 .cmd = "flash",
1437 .cb = cb_flash,
1438 },
1439#endif
1440 {
1441 .cmd = "update",
1442 .cb = cb_download,
1443 },
1444 {
1445 .cmd = "flashall",
1446 .cb = cb_flashall,
1447 },
1448 {
1449 .cmd = "erase",
1450 .cb = cb_erase,
1451 },
1452 {
1453 .cmd = "devices",
1454 .cb = cb_devices,
1455 },
1456 {
1457 .cmd = "reboot-bootloader",
1458 .cb = cb_reboot,
1459 },
1460 {
1461 .cmd = "reboot-fastboot",
1462 .cb = cb_reboot,
1463 },
1464 {
1465 .cmd = "set_active",
1466 .cb = cb_set_active,
1467 },
1468 {
1469 .cmd = "oem",
1470 .cb = cb_oem_cmd,
1471 }
1472};
1473
1474//cb for out_req->complete
1475static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
1476{
1477 char *cmdbuf = req->buf;
1478 void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
1479 int i;
1480
1481 for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
1482 if (!strcmp_l1(cmd_dispatch_info[i].cmd, cmdbuf)) {
1483 func_cb = cmd_dispatch_info[i].cb;
1484 break;
1485 }
1486 }
1487
1488 if (!func_cb) {
1489 error("unknown command: %s\n", cmdbuf);
1490 fastboot_tx_write_str("FAILunknown command");
1491 } else {
1492 if (req->actual < req->length) {
1493 u8 *buf = (u8 *)req->buf;
1494 buf[req->actual] = 0;
1495 func_cb(ep, req);
1496 } else {
1497 error("buffer overflow\n");
1498 fastboot_tx_write_str("FAILbuffer overflow");
1499 }
1500 }
1501
1502 if (req->status == 0 && !fastboot_is_busy()) {
1503 *cmdbuf = '\0';
1504 req->actual = 0;
1505 usb_ep_queue(ep, req, 0);
1506 }
1507}
1508