本文介绍了fastboot协议,在uboot中如何配置支持fastboot,uboot中fastboot的实现流程以及fastboot命令如何使用。
fastboot简介
1、fastboot协议是一种通过USB或以太网与引导加载程序通信的机制。 它的设计非常简单,可以在各种设备和运行Linux,macOS或Windows的主机上使用。主要是PC机通过fastboot协议与bootloader通信。
我们可以理解在uboot中运行fastboot的为客户端,在PC端(ubuntu)运行fastboot的为服务器端,两者之间的通信走fastboot协议。
2、fastboot协议最基本的要求:
- 2个bulk端点(BULK IN/OUT),可以通过USB枚举信息看到详细的信息:
1 | victor@victor-HP:~ lsusb -d 0525:a4a5 -v |
- USB full-speed最大包为64Bytes,high-speed最大包为512Bytes;
- 该协议完全由主机驱动和同步(与多通道,双向,异步ADB协议不同)。
uboot配置fastboot协议
关于fastboot相关宏的解释,可以参考cmd/fastboot/Kconfig
文件。下面说一下在uboot中配置支持fastboot。
1、uboot中已实现对fastboot协议的支持:
drivers/usb/gadget/fastboot.c
:fastboot usb function源码;doc/README.android-fastboot
:fastboot使能说明文档;doc/README.android-fastboot-protocol
:fastboot协议说明文档;
2、uboot中要使能fastboot,需要在板级配置打开以下的宏:
1 | CONFIG_FASTBOOT |
uboot在命令行中可以通过fastboot命令进入fastboot模式。
3、使能fastboot usb gadget
因为fastboot协议是基于usb gadget,所以需要打开或配置以下几个宏:
1 | CONFIG_USB_GADGET_DOWNLOAD |
这里面指定的VID
和PID
必须要在fastboot client
中能找到,如果没有,也可以用ubuntu fastboot命令的以下选项指定设备。
1 | -s <specific device> specify device serial number |
4、配置缓冲区地址和大小
fastboot需要一块大的内存区域用来下载,需要配置CONFIG_FASTBOOT_BUF_ADDR
缓冲区的起始地址以及CONFIG_FASTBOOT_BUF_SIZE
大小,这两个值决定了你可以通过fastboot烧写多大的镜像。
1 | CONFIG_FASTBOOT_BUF_ADDR=0x82800000 |
5、配置fastboot flash
命令的支持
如果想要通过fastboot flash
命令烧写到flash上,必须打开CONFIG_FASTBOOT_FLASH
相关的配置。比如我板子上使用的是eMMC,必须使能如下的宏:
1 | CONFIG_FASTBOOT_FLASH=y |
uboot中fastboot的实现流程
imx8 uuu基于fastboot协议进行镜像的烧写,以下的分析基于NXP提供的4.14.98_ga版本。
uboot中fastboot命令
1 | static int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) |
1、首先在uboot命令行执行fastboot x
,指定第x
个usb controller,使用这个controller进行通信,如果没有,默认使用CONFIG_FASTBOOT_USB_DEV
指定的usb controller;
2、然后调用board_usb_init()
函数做usb device controller的初始化,这个函数在board/freescale/imx8qxp_mek.c
中定义。在NXP的BSP中,这个函数如果没有打开CONFIG_USB_CDNS3_GADGET
的话就是个空函数。
为什么呢?我的理解是NXP使用imx uuu是使用usb0(chipidea)做为下载口,当将板子设置为SDP模式,rom code就会去初始化usb0 controller,并且配置为hid设备。因此,如果在SDP模式下,usb0 controller就无需初始化了。
3、调用g_dnl_register()
函数注册一个名为usb_dnl_fastboot
的usb复合设备。
1 | /* |
- 在这个文件中配置了设备描述符等信息以及绑定function。
- uboot中的这一套usb composite framework与kernel的一样,后续将会出一个关于这个框架的文章。可以看看我之前的文章Androidadb驱动实现原理 关于usb复合设备的注册是大同小异的。
- 在这个复合设备中,会依次查找绑定的usb function。在
drivers/usb/gadget/f_fastboot.c
中调用了DECLARE_GADGET_BIND_CALLBACK(usb_dnl_fastboot, fastboot_add);
,这就将fastboot的usb function与g_dnl的usb composite device绑定起来了。
1 | static int g_dnl_do_config(struct usb_configuration *c) |
1 | /* |
4、在这之后就进入while(1)
的循环,如果碰到g_dnl
驱动卸载掉或者ctrl + c
就跳出,否则调用usb_gadget_handle_interrupts()
处理usb中断(我这里使用到的是chipidea udc)。至此,当你在uboot命令行执行fastboot 1
后,接下来全部都是在处理usb ep的中断,也就是处理PC端发送过来的指令。
1 | int usb_gadget_handle_interrupts(int index) |
更一般的,这里指就是usb endpoint的中断。具体的,就是处理fastbootusb function中指定的usb endpoint的中断。其中rx_handler_command()
函数用来处理PC端发送过来的数据,fastboot_complete()
用来处理板子发送给PC端的数据。
1 | static int fastboot_set_alt(struct usb_function *f, |
fastboot支持的参数
在前面,我们说到rx_handler_command()
函数用来处理PC端发送过来的数据,其中cmd_dispatch_info[]
数组定义了一系列fastboot所支持的参数列表以及对应的处理函数。
1 | static const struct cmd_dispatch_info cmd_dispatch_info[] = { |
fastboot环境变量配置
前面我们说过,需要配置CONFIG_FASTBOOT_BUF_ADDR
缓冲区的起始地址以及CONFIG_FASTBOOT_BUF_SIZE
大小,这个其实是为了配置一个名为fastboot_buffer
的环境变量。
1 | static void parameters_setup(void) |
uuu进入fastboot模式
CONFIG_MFG_ENV_SETTINGS_DEFAULT
中会执行fastboot 0
进入fastboot下载模式,等待与PC之间的通信。
1 |
|
各个宏之间的关系如下:
1 | include/env_default.h |
ubuntu下载fastboot工具
前面在uboot中配置支持fastboot,接下来要在PC端下载fastboot工具,ubuntu使用如下命令下载。这之后就可以在PC端使用fastboot命令与uboot通信并且执行相关的操作了。
1 | sudo apt-get install android-tools-fastboot |
查看fastboot命令的使用:
1 | usage: fastboot [ <option> ] <command> |
adb与fastboot的区别
Android设备和PC之间的协议通信,除了fastboot
协议还有使用adb
协议。
adb
用于Android设备系统起来后的调试,允许访问Android系统。fastboot
用于Android设备开发过程中刷写镜像使用以及Android设备起不来进入fastboot模式救砖使用,对于线刷来说(Android设备与PC机通过USB线连接)。- 两个协议都是将Android设备配置为USB Gadget,PC做为USB Host,通过USB进行通信,只是一个走的是
adb
协议,一个走的是fastboot
协议,两者之间的角色定位不同。
参考资料
1.fastboot官方文档
2.u-boot/doc/README.android-fastboot
3.samsung uboot fastboot command
4.与fastboot相关的知识