Commit 57c6941b433722ab83a50dab35b8ab5a0954942a
Exists in
v2017.01-smarct4x
and in
37 other branches
Merge git://git.denx.de/u-boot-usb
Showing 13 changed files Side-by-side Diff
- board/samsung/common/board.c
- board/samsung/common/misc.c
- board/samsung/odroid/odroid.c
- common/cmd_fastboot.c
- common/fb_mmc.c
- doc/README.android-fastboot
- drivers/dfu/dfu.c
- drivers/usb/gadget/f_fastboot.c
- drivers/usb/host/xhci-exynos5.c
- drivers/usb/musb-new/omap2430.c
- include/dfu.h
- include/fb_mmc.h
- include/samsung/misc.h
board/samsung/common/board.c
board/samsung/common/misc.c
... | ... | @@ -22,7 +22,7 @@ |
22 | 22 | DECLARE_GLOBAL_DATA_PTR; |
23 | 23 | |
24 | 24 | #ifdef CONFIG_SET_DFU_ALT_INFO |
25 | -void set_dfu_alt_info(void) | |
25 | +void set_dfu_alt_info(char *interface, char *devstr) | |
26 | 26 | { |
27 | 27 | size_t buf_size = CONFIG_SET_DFU_ALT_BUF_LEN; |
28 | 28 | ALLOC_CACHE_ALIGN_BUFFER(char, buf, buf_size); |
29 | 29 | |
... | ... | @@ -34,13 +34,13 @@ |
34 | 34 | |
35 | 35 | puts("DFU alt info setting: "); |
36 | 36 | |
37 | - alt_setting = get_dfu_alt_boot(); | |
37 | + alt_setting = get_dfu_alt_boot(interface, devstr); | |
38 | 38 | if (alt_setting) { |
39 | 39 | setenv("dfu_alt_boot", alt_setting); |
40 | 40 | offset = snprintf(buf, buf_size, "%s", alt_setting); |
41 | 41 | } |
42 | 42 | |
43 | - alt_setting = get_dfu_alt_system(); | |
43 | + alt_setting = get_dfu_alt_system(interface, devstr); | |
44 | 44 | if (alt_setting) { |
45 | 45 | if (offset) |
46 | 46 | alt_sep = ";"; |
board/samsung/odroid/odroid.c
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | #include <power/pmic.h> |
16 | 16 | #include <power/max77686_pmic.h> |
17 | 17 | #include <errno.h> |
18 | +#include <mmc.h> | |
18 | 19 | #include <usb.h> |
19 | 20 | #include <usb/s3c_udc.h> |
20 | 21 | #include <samsung/misc.h> |
21 | 22 | |
22 | 23 | |
23 | 24 | |
24 | 25 | |
... | ... | @@ -61,27 +62,29 @@ |
61 | 62 | #endif |
62 | 63 | |
63 | 64 | #ifdef CONFIG_SET_DFU_ALT_INFO |
64 | -char *get_dfu_alt_system(void) | |
65 | +char *get_dfu_alt_system(char *interface, char *devstr) | |
65 | 66 | { |
66 | 67 | return getenv("dfu_alt_system"); |
67 | 68 | } |
68 | 69 | |
69 | -char *get_dfu_alt_boot(void) | |
70 | +char *get_dfu_alt_boot(char *interface, char *devstr) | |
70 | 71 | { |
72 | + struct mmc *mmc; | |
71 | 73 | char *alt_boot; |
74 | + int dev_num; | |
72 | 75 | |
73 | - switch (get_boot_mode()) { | |
74 | - case BOOT_MODE_SD: | |
75 | - alt_boot = CONFIG_DFU_ALT_BOOT_SD; | |
76 | - break; | |
77 | - case BOOT_MODE_EMMC: | |
78 | - case BOOT_MODE_EMMC_SD: | |
79 | - alt_boot = CONFIG_DFU_ALT_BOOT_EMMC; | |
80 | - break; | |
81 | - default: | |
82 | - alt_boot = NULL; | |
83 | - break; | |
84 | - } | |
76 | + dev_num = simple_strtoul(devstr, NULL, 10); | |
77 | + | |
78 | + mmc = find_mmc_device(dev_num); | |
79 | + if (!mmc) | |
80 | + return NULL; | |
81 | + | |
82 | + if (mmc_init(mmc)) | |
83 | + return NULL; | |
84 | + | |
85 | + alt_boot = IS_SD(mmc) ? CONFIG_DFU_ALT_BOOT_SD : | |
86 | + CONFIG_DFU_ALT_BOOT_EMMC; | |
87 | + | |
85 | 88 | return alt_boot; |
86 | 89 | } |
87 | 90 | #endif |
common/cmd_fastboot.c
common/fb_mmc.c
... | ... | @@ -10,6 +10,7 @@ |
10 | 10 | #include <part.h> |
11 | 11 | #include <aboot.h> |
12 | 12 | #include <sparse_format.h> |
13 | +#include <mmc.h> | |
13 | 14 | |
14 | 15 | #ifndef CONFIG_FASTBOOT_GPT_NAME |
15 | 16 | #define CONFIG_FASTBOOT_GPT_NAME GPT_ENTRY_NAME |
16 | 17 | |
... | ... | @@ -22,13 +23,13 @@ |
22 | 23 | |
23 | 24 | void fastboot_fail(const char *s) |
24 | 25 | { |
25 | - strncpy(response_str, "FAIL", 4); | |
26 | + strncpy(response_str, "FAIL\0", 5); | |
26 | 27 | strncat(response_str, s, RESPONSE_LEN - 4 - 1); |
27 | 28 | } |
28 | 29 | |
29 | 30 | void fastboot_okay(const char *s) |
30 | 31 | { |
31 | - strncpy(response_str, "OKAY", 4); | |
32 | + strncpy(response_str, "OKAY\0", 5); | |
32 | 33 | strncat(response_str, s, RESPONSE_LEN - 4 - 1); |
33 | 34 | } |
34 | 35 | |
... | ... | @@ -109,5 +110,60 @@ |
109 | 110 | else |
110 | 111 | write_raw_image(dev_desc, &info, cmd, download_buffer, |
111 | 112 | download_bytes); |
113 | +} | |
114 | + | |
115 | +void fb_mmc_erase(const char *cmd, char *response) | |
116 | +{ | |
117 | + int ret; | |
118 | + block_dev_desc_t *dev_desc; | |
119 | + disk_partition_t info; | |
120 | + lbaint_t blks, blks_start, blks_size, grp_size; | |
121 | + struct mmc *mmc = find_mmc_device(CONFIG_FASTBOOT_FLASH_MMC_DEV); | |
122 | + | |
123 | + if (mmc == NULL) { | |
124 | + error("invalid mmc device"); | |
125 | + fastboot_fail("invalid mmc device"); | |
126 | + return; | |
127 | + } | |
128 | + | |
129 | + /* initialize the response buffer */ | |
130 | + response_str = response; | |
131 | + | |
132 | + dev_desc = get_dev("mmc", CONFIG_FASTBOOT_FLASH_MMC_DEV); | |
133 | + if (!dev_desc || dev_desc->type == DEV_TYPE_UNKNOWN) { | |
134 | + error("invalid mmc device"); | |
135 | + fastboot_fail("invalid mmc device"); | |
136 | + return; | |
137 | + } | |
138 | + | |
139 | + ret = get_partition_info_efi_by_name(dev_desc, cmd, &info); | |
140 | + if (ret) { | |
141 | + error("cannot find partition: '%s'", cmd); | |
142 | + fastboot_fail("cannot find partition"); | |
143 | + return; | |
144 | + } | |
145 | + | |
146 | + /* Align blocks to erase group size to avoid erasing other partitions */ | |
147 | + grp_size = mmc->erase_grp_size; | |
148 | + blks_start = (info.start + grp_size - 1) & ~(grp_size - 1); | |
149 | + if (info.size >= grp_size) | |
150 | + blks_size = (info.size - (blks_start - info.start)) & | |
151 | + (~(grp_size - 1)); | |
152 | + else | |
153 | + blks_size = 0; | |
154 | + | |
155 | + printf("Erasing blocks " LBAFU " to " LBAFU " due to alignment\n", | |
156 | + blks_start, blks_start + blks_size); | |
157 | + | |
158 | + blks = dev_desc->block_erase(dev_desc->dev, blks_start, blks_size); | |
159 | + if (blks != blks_size) { | |
160 | + error("failed erasing from device %d", dev_desc->dev); | |
161 | + fastboot_fail("failed erasing from device"); | |
162 | + return; | |
163 | + } | |
164 | + | |
165 | + printf("........ erased " LBAFU " bytes from '%s'\n", | |
166 | + blks_size * info.blksz, cmd); | |
167 | + fastboot_okay(""); | |
112 | 168 | } |
doc/README.android-fastboot
... | ... | @@ -6,9 +6,8 @@ |
6 | 6 | The protocol that is used over USB is described in |
7 | 7 | README.android-fastboot-protocol in same directory. |
8 | 8 | |
9 | -The current implementation does not yet support the erase command or the | |
10 | -"oem format" command, and there is minimal support for the flash command; | |
11 | -it only supports eMMC devices. | |
9 | +The current implementation is a minimal support of the erase command,the | |
10 | +"oem format" command and flash command;it only supports eMMC devices. | |
12 | 11 | |
13 | 12 | Client installation |
14 | 13 | =================== |
drivers/dfu/dfu.c
drivers/usb/gadget/f_fastboot.c
... | ... | @@ -55,6 +55,7 @@ |
55 | 55 | static struct f_fastboot *fastboot_func; |
56 | 56 | static unsigned int download_size; |
57 | 57 | static unsigned int download_bytes; |
58 | +static bool is_high_speed; | |
58 | 59 | |
59 | 60 | static struct usb_endpoint_descriptor fs_ep_in = { |
60 | 61 | .bLength = USB_DT_ENDPOINT_SIZE, |
... | ... | @@ -136,6 +137,7 @@ |
136 | 137 | int id; |
137 | 138 | struct usb_gadget *gadget = c->cdev->gadget; |
138 | 139 | struct f_fastboot *f_fb = func_to_fastboot(f); |
140 | + const char *s; | |
139 | 141 | |
140 | 142 | /* DYNAMIC interface numbers assignments */ |
141 | 143 | id = usb_interface_id(c, f); |
... | ... | @@ -161,6 +163,10 @@ |
161 | 163 | |
162 | 164 | hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress; |
163 | 165 | |
166 | + s = getenv("serial#"); | |
167 | + if (s) | |
168 | + g_dnl_set_serialnumber((char *)s); | |
169 | + | |
164 | 170 | return 0; |
165 | 171 | } |
166 | 172 | |
167 | 173 | |
168 | 174 | |
... | ... | @@ -219,10 +225,13 @@ |
219 | 225 | __func__, f->name, interface, alt); |
220 | 226 | |
221 | 227 | /* make sure we don't enable the ep twice */ |
222 | - if (gadget->speed == USB_SPEED_HIGH) | |
228 | + if (gadget->speed == USB_SPEED_HIGH) { | |
223 | 229 | ret = usb_ep_enable(f_fb->out_ep, &hs_ep_out); |
224 | - else | |
230 | + is_high_speed = true; | |
231 | + } else { | |
225 | 232 | ret = usb_ep_enable(f_fb->out_ep, &fs_ep_out); |
233 | + is_high_speed = false; | |
234 | + } | |
226 | 235 | if (ret) { |
227 | 236 | puts("failed to enable out ep\n"); |
228 | 237 | return ret; |
229 | 238 | |
230 | 239 | |
... | ... | @@ -370,13 +379,20 @@ |
370 | 379 | fastboot_tx_write_str(response); |
371 | 380 | } |
372 | 381 | |
373 | -static unsigned int rx_bytes_expected(void) | |
382 | +static unsigned int rx_bytes_expected(unsigned int maxpacket) | |
374 | 383 | { |
375 | 384 | int rx_remain = download_size - download_bytes; |
385 | + int rem = 0; | |
376 | 386 | if (rx_remain < 0) |
377 | 387 | return 0; |
378 | 388 | if (rx_remain > EP_BUFFER_SIZE) |
379 | 389 | return EP_BUFFER_SIZE; |
390 | + if (rx_remain < maxpacket) { | |
391 | + rx_remain = maxpacket; | |
392 | + } else if (rx_remain % maxpacket != 0) { | |
393 | + rem = rx_remain % maxpacket; | |
394 | + rx_remain = rx_remain + (maxpacket - rem); | |
395 | + } | |
380 | 396 | return rx_remain; |
381 | 397 | } |
382 | 398 | |
... | ... | @@ -388,6 +404,7 @@ |
388 | 404 | const unsigned char *buffer = req->buf; |
389 | 405 | unsigned int buffer_size = req->actual; |
390 | 406 | unsigned int pre_dot_num, now_dot_num; |
407 | + unsigned int max; | |
391 | 408 | |
392 | 409 | if (req->status != 0) { |
393 | 410 | printf("Bad status: %d\n", req->status); |
... | ... | @@ -425,7 +442,9 @@ |
425 | 442 | |
426 | 443 | printf("\ndownloading of %d bytes finished\n", download_bytes); |
427 | 444 | } else { |
428 | - req->length = rx_bytes_expected(); | |
445 | + max = is_high_speed ? hs_ep_out.wMaxPacketSize : | |
446 | + fs_ep_out.wMaxPacketSize; | |
447 | + req->length = rx_bytes_expected(max); | |
429 | 448 | if (req->length < ep->maxpacket) |
430 | 449 | req->length = ep->maxpacket; |
431 | 450 | } |
... | ... | @@ -438,6 +457,7 @@ |
438 | 457 | { |
439 | 458 | char *cmd = req->buf; |
440 | 459 | char response[RESPONSE_LEN]; |
460 | + unsigned int max; | |
441 | 461 | |
442 | 462 | strsep(&cmd, ":"); |
443 | 463 | download_size = simple_strtoul(cmd, NULL, 16); |
... | ... | @@ -453,7 +473,9 @@ |
453 | 473 | } else { |
454 | 474 | sprintf(response, "DATA%08x", download_size); |
455 | 475 | req->complete = rx_handler_dl_image; |
456 | - req->length = rx_bytes_expected(); | |
476 | + max = is_high_speed ? hs_ep_out.wMaxPacketSize : | |
477 | + fs_ep_out.wMaxPacketSize; | |
478 | + req->length = rx_bytes_expected(max); | |
457 | 479 | if (req->length < ep->maxpacket) |
458 | 480 | req->length = ep->maxpacket; |
459 | 481 | } |
... | ... | @@ -513,6 +535,50 @@ |
513 | 535 | } |
514 | 536 | #endif |
515 | 537 | |
538 | +static void cb_oem(struct usb_ep *ep, struct usb_request *req) | |
539 | +{ | |
540 | + char *cmd = req->buf; | |
541 | +#ifdef CONFIG_FASTBOOT_FLASH | |
542 | + if (strncmp("format", cmd + 4, 6) == 0) { | |
543 | + char cmdbuf[32]; | |
544 | + sprintf(cmdbuf, "gpt write mmc %x $partitions", | |
545 | + CONFIG_FASTBOOT_FLASH_MMC_DEV); | |
546 | + if (run_command(cmdbuf, 0)) | |
547 | + fastboot_tx_write_str("FAIL"); | |
548 | + else | |
549 | + fastboot_tx_write_str("OKAY"); | |
550 | + } else | |
551 | +#endif | |
552 | + if (strncmp("unlock", cmd + 4, 8) == 0) { | |
553 | + fastboot_tx_write_str("FAILnot implemented"); | |
554 | + } | |
555 | + else { | |
556 | + fastboot_tx_write_str("FAILunknown oem command"); | |
557 | + } | |
558 | +} | |
559 | + | |
560 | +#ifdef CONFIG_FASTBOOT_FLASH | |
561 | +static void cb_erase(struct usb_ep *ep, struct usb_request *req) | |
562 | +{ | |
563 | + char *cmd = req->buf; | |
564 | + char response[RESPONSE_LEN]; | |
565 | + | |
566 | + strsep(&cmd, ":"); | |
567 | + if (!cmd) { | |
568 | + error("missing partition name"); | |
569 | + fastboot_tx_write_str("FAILmissing partition name"); | |
570 | + return; | |
571 | + } | |
572 | + | |
573 | + strcpy(response, "FAILno flash device defined"); | |
574 | + | |
575 | +#ifdef CONFIG_FASTBOOT_FLASH_MMC_DEV | |
576 | + fb_mmc_erase(cmd, response); | |
577 | +#endif | |
578 | + fastboot_tx_write_str(response); | |
579 | +} | |
580 | +#endif | |
581 | + | |
516 | 582 | struct cmd_dispatch_info { |
517 | 583 | char *cmd; |
518 | 584 | void (*cb)(struct usb_ep *ep, struct usb_request *req); |
519 | 585 | |
... | ... | @@ -539,8 +605,15 @@ |
539 | 605 | { |
540 | 606 | .cmd = "flash", |
541 | 607 | .cb = cb_flash, |
608 | + }, { | |
609 | + .cmd = "erase", | |
610 | + .cb = cb_erase, | |
542 | 611 | }, |
543 | 612 | #endif |
613 | + { | |
614 | + .cmd = "oem", | |
615 | + .cb = cb_oem, | |
616 | + }, | |
544 | 617 | }; |
545 | 618 | |
546 | 619 | static void rx_handler_command(struct usb_ep *ep, struct usb_request *req) |
drivers/usb/host/xhci-exynos5.c
... | ... | @@ -182,7 +182,7 @@ |
182 | 182 | set_usbdrd_phy_ctrl(POWER_USB_DRD_PHY_CTRL_DISABLE); |
183 | 183 | } |
184 | 184 | |
185 | -void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) | |
185 | +static void dwc3_set_mode(struct dwc3 *dwc3_reg, u32 mode) | |
186 | 186 | { |
187 | 187 | clrsetbits_le32(&dwc3_reg->g_ctl, |
188 | 188 | DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG), |
drivers/usb/musb-new/omap2430.c
... | ... | @@ -321,6 +321,7 @@ |
321 | 321 | { |
322 | 322 | u32 l; |
323 | 323 | int status = 0; |
324 | + unsigned long int start; | |
324 | 325 | #ifndef __UBOOT__ |
325 | 326 | struct device *dev = musb->controller; |
326 | 327 | struct omap2430_glue *glue = dev_get_drvdata(dev->parent); |
... | ... | @@ -331,6 +332,21 @@ |
331 | 332 | (struct omap_musb_board_data *)musb->controller; |
332 | 333 | #endif |
333 | 334 | |
335 | + /* Reset the controller */ | |
336 | + musb_writel(musb->mregs, OTG_SYSCONFIG, SOFTRST); | |
337 | + | |
338 | + start = get_timer(0); | |
339 | + | |
340 | + while (1) { | |
341 | + l = musb_readl(musb->mregs, OTG_SYSCONFIG); | |
342 | + if ((l & SOFTRST) == 0) | |
343 | + break; | |
344 | + | |
345 | + if (get_timer(start) > (CONFIG_SYS_HZ / 1000)) { | |
346 | + dev_err(musb->controller, "MUSB reset is taking too long\n"); | |
347 | + return -ENODEV; | |
348 | + } | |
349 | + } | |
334 | 350 | |
335 | 351 | #ifndef __UBOOT__ |
336 | 352 | /* We require some kind of external transceiver, hooked |
include/dfu.h
... | ... | @@ -140,6 +140,9 @@ |
140 | 140 | unsigned int inited:1; |
141 | 141 | }; |
142 | 142 | |
143 | +#ifdef CONFIG_SET_DFU_ALT_INFO | |
144 | +void set_dfu_alt_info(char *interface, char *devstr); | |
145 | +#endif | |
143 | 146 | int dfu_config_entities(char *s, char *interface, char *devstr); |
144 | 147 | void dfu_free_entities(void); |
145 | 148 | void dfu_show_entities(void); |
include/fb_mmc.h
include/samsung/misc.h
... | ... | @@ -29,9 +29,8 @@ |
29 | 29 | #endif |
30 | 30 | |
31 | 31 | #ifdef CONFIG_SET_DFU_ALT_INFO |
32 | -char *get_dfu_alt_system(void); | |
33 | -char *get_dfu_alt_boot(void); | |
34 | -void set_dfu_alt_info(void); | |
32 | +char *get_dfu_alt_system(char *interface, char *devstr); | |
33 | +char *get_dfu_alt_boot(char *interface, char *devstr); | |
35 | 34 | #endif |
36 | 35 | #ifdef CONFIG_BOARD_TYPES |
37 | 36 | void set_board_type(void); |