diff options
author | LiGang <b41990@freescale.com> | 2012-12-27 13:27:34 +0800 |
---|---|---|
committer | LiGang <b41990@freescale.com> | 2012-12-27 14:52:50 +0800 |
commit | 0e7ae7d5470d784a447bc94704ff1e8db5aca7de (patch) | |
tree | d5f85f277730f93b5b2f5994aae3875c195018fc /drivers/fastboot | |
parent | b07b53788a970985363f6daee88e0ead9aff05b7 (diff) | |
download | u-boot-imx-0e7ae7d5470d784a447bc94704ff1e8db5aca7de.zip u-boot-imx-0e7ae7d5470d784a447bc94704ff1e8db5aca7de.tar.gz u-boot-imx-0e7ae7d5470d784a447bc94704ff1e8db5aca7de.tar.bz2 |
ENGR00238300: enhance the download speed for fastboot
1. the new fastboot is an add-on feature, the original fastboot is reserved
2. the new fastboot is a subset of original fastboot, only support "download"
and "flash" command
3. type "fastboot" in uboot to launch the original fastboot utility,
type "fastboot q" in uboot to launch the new fastboot utility
Signed-off-by: LiGang <b41990@freescale.com>
Diffstat (limited to 'drivers/fastboot')
-rw-r--r-- | drivers/fastboot/fastboot.c | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/drivers/fastboot/fastboot.c b/drivers/fastboot/fastboot.c index 3dcab32..fe0b6b8 100644 --- a/drivers/fastboot/fastboot.c +++ b/drivers/fastboot/fastboot.c @@ -788,3 +788,160 @@ void check_fastboot_mode(void) if (fastboot_check_and_clean_flag()) do_fastboot(NULL, 0, 0, 0); } + +u8 fastboot_debug_level; +void fastboot_dump_memory(u32 *ptr, u32 len) +{ + u32 i; + for (i = 0; i < len; i++) { + DBG_DEBUG("0x%p: %08x %08x %08x %08x\n", ptr, + *ptr, *(ptr+1), *(ptr+2), *(ptr+3)); + ptr += 4; + } +} + +#define FASTBOOT_STS_CMD 0 +#define FASTBOOT_STS_CMD_WAIT 1 +#define FASTBOOT_STS_DATA 2 +#define FASTBOOT_STS_DATA_WAIT 3 + +static u8 fastboot_status; +static u8 g_fastboot_recvbuf[MAX_PAKET_LEN]; +static u8 g_fastboot_sendbuf[MAX_PAKET_LEN]; + +static u32 g_fastboot_datalen; +static u8 g_fastboot_outep_index, g_fastboot_inep_index; +static u8 g_usb_connected; + +void fastboot_get_ep_num(u8 *in, u8 *out) +{ + if (out) + *out = rx_endpoint + EP0_OUT_INDEX + 1; + if (in) + *in = tx_endpoint + EP0_IN_INDEX + 1; +} + +static void fastboot_data_handler(u32 len, u8 *recvbuf) +{ + if (len != g_fastboot_datalen) + DBG_ERR("Fastboot data recv error, want:%d, recv:%d\n", + g_fastboot_datalen, len); + sprintf((char *)g_fastboot_sendbuf, "OKAY"); + udc_send_data(g_fastboot_inep_index, g_fastboot_sendbuf, 4, NULL); + fastboot_status = FASTBOOT_STS_CMD; +} + +static void fastboot_cmd_handler(u32 len, u8 *recvbuf) +{ + u32 *databuf = (u32 *)CONFIG_FASTBOOT_TRANSFER_BUF; + + if (len > sizeof(g_fastboot_recvbuf)) { + DBG_ERR("%s, recv len=%d error\n", __func__, len); + return; + } + recvbuf[len] = 0; + DBG_ALWS("\nFastboot Cmd, len=%u, %s\n", len, recvbuf); + + if (memcmp(recvbuf, "download:", 9) == 0) { + g_fastboot_datalen = simple_strtoul((const char *)recvbuf + 9, + NULL, 16); + if (g_fastboot_datalen > CONFIG_FASTBOOT_TRANSFER_BUF_SIZE) { + DBG_ERR("Download too much data\n"); + sprintf((char *)g_fastboot_sendbuf, "FAIL"); + udc_send_data(g_fastboot_inep_index, g_fastboot_sendbuf, + 4, NULL); + fastboot_status = FASTBOOT_STS_CMD; + } else { + sprintf((char *)g_fastboot_sendbuf, "DATA%08x", + g_fastboot_datalen); + udc_send_data(g_fastboot_inep_index, g_fastboot_sendbuf, + 12, NULL); + DBG_ALWS("Fastboot is receiveing data...\n"); + udc_recv_data(g_fastboot_outep_index, (u8 *)databuf, + g_fastboot_datalen, fastboot_data_handler); + fastboot_status = FASTBOOT_STS_DATA_WAIT; + } + } else if (memcmp(recvbuf, "flash:", 6) == 0) { + if (g_fastboot_datalen == + fastboot_write_mmc(recvbuf+6, g_fastboot_datalen)) { + DBG_ALWS("Fastboot write OK, send OKAY...\n"); + sprintf((char *)g_fastboot_sendbuf, "OKAY"); + udc_send_data(g_fastboot_inep_index, g_fastboot_sendbuf, + 4, NULL); + } else { + DBG_ERR("Fastboot write error, write 0x%x\n", + g_fastboot_datalen); + sprintf((char *)g_fastboot_sendbuf, "FAIL"); + udc_send_data(g_fastboot_inep_index, g_fastboot_sendbuf, + 4, NULL); + } + g_fastboot_datalen = 0; + fastboot_status = FASTBOOT_STS_CMD; + } else { + DBG_ERR("Not support command:%s\n", recvbuf); + sprintf((char *)g_fastboot_sendbuf, "FAIL"); + udc_send_data(g_fastboot_inep_index, g_fastboot_sendbuf, + 4, NULL); + g_fastboot_datalen = 0; + fastboot_status = FASTBOOT_STS_CMD; + } +} + +static struct cmd_fastboot_interface interface = { + .rx_handler = NULL, + .reset_handler = NULL, + .product_name = NULL, + .serial_no = NULL, + .nand_block_size = 0, + .transfer_buffer = (unsigned char *)0xffffffff, + .transfer_buffer_size = 0, +}; + +void *fastboot_get_string_table(void) +{ + return fastboot_string_table; +} + +/* + * fastboot main process, only support 'download', 'flash' command now + * + * @debug control debug level, support three level now, + * 0(normal), 1(debug), 2(info), default is 0 + */ +void fastboot_quick(u8 debug) +{ + u32 plug_cnt = 0; + if (debug > 2) + debug = 0; + fastboot_debug_level = debug; + + fastboot_init(&interface); + fastboot_get_ep_num(&g_fastboot_inep_index, &g_fastboot_outep_index); + DBG_INFO("g_fastboot_inep_index=%d, g_fastboot_outep_index=%d\n", + g_fastboot_inep_index, g_fastboot_outep_index); + while (++plug_cnt) { + fastboot_status = FASTBOOT_STS_CMD; + udc_hal_data_init(); + udc_run(); + if (plug_cnt > 1) + DBG_ALWS("wait usb cable into the connector!\n"); + udc_wait_connect(); + g_usb_connected = 1; + if (plug_cnt > 1) + DBG_ALWS("USB Mini b cable Connected!\n"); + while (g_usb_connected) { + int usb_irq = udc_irq_handler(); + if (usb_irq > 0) { + if (fastboot_status == FASTBOOT_STS_CMD) { + memset(g_fastboot_recvbuf, 0 , MAX_PAKET_LEN); + udc_recv_data(g_fastboot_outep_index, + g_fastboot_recvbuf, MAX_PAKET_LEN, + fastboot_cmd_handler); + fastboot_status = FASTBOOT_STS_CMD_WAIT; + } + } + if (usb_irq < 0) + g_usb_connected = 0; + } + } +} |