Fastboot 协议简介和前言
Fastboot 是一种用于在 Android 设备或嵌入式设备上快速刷写 eMMC、NAND、UFS 等存储的协议。它最初由 Google 开发,并集成到 Android 设备的 Bootloader中,但也被广泛用于其他嵌入式 Linux 设备的固件更新。
在Linux嵌入式设备开发中,通常Fastboot都是被集成到U-boot之中的。在本篇博文的后面,也介绍了如何在U-Boot 中启用 Fastboot。
备注:本文中的“刷写”就是我们常说的“烧写”的意思。
u-boot中有两个功能块对MMC(eMMC/SD)设备进行管理。
其中一个是fastboot、另一个是 MMC sub system(MMC子系统)。
fastboot
主要是实现烧写数据的功能,而MMC子系统则拥有完整的命令集对MMC(eMMC/SD)设备进行管理。
其中fastboot
也会调用MMC sub system
的命令来实现其功能。关于这一点,本博文后面有说明,详情请在本篇博文中搜索“Fastboot 的PC端可利用FB”。
本篇博文介绍fastboot
,而关于MMC sub system
的介绍,请见我的另一篇博文:
https://blog.csdn.net/wenhao_ir/article/details/146016551
1. Fastboot 的工作模式
Fastboot进行工作时,可分为三个部分。
第1部分:PC端,PC端主要是发送要执行的Fastboot命令;
第2部分:开发板(即嵌入式设备),开发板上主要是运行一个特制的u-boot,这个u-boot运行后会进入Fastboot模式,进而可接收来自PC端发来的Fastboot命令,并进行执行。
第3部分:存储器设备,这就是我们要进行烧写的对象。
嵌入式设备(比如我的开发板)运行特制的u-boot进入 Fastboot 模式后,等待来自通过USB(或 UART、网络等接口)连接的PC发来的 Fastboot 命令,以执行相应的刷写操作。
嵌入式设备通常是通过 U-Boot 或 Bootloader 进入Fastboot 模式,NXP官方开发的uuu烧写工具也是利用u-boot提供的 Fastboot 接口 实现固件更新。uuu烧写工具准备工作时,它会通过 USB 临时加载一个特制的 U-Boot 到 RAM(内存) 中运行,这个特制的 U-Boot 在内存中运行起来后会自动进入Fastboot 模式,进而PC端就可以发送各种Fastboot命令给开发板进行执行操作了。
典型的 Fastboot 运行流程:
- 设备进入 Fastboot 模式,等待命令。
- PC 端使用
fastboot
工具发送指令(如分区擦除、镜像写入等)。 - 设备执行相应的操作,并返回执行状态。
2. Fastboot 协议数据交互
Fastboot 协议基于 USB(也可以扩展到 UART、网络等),主要包括 命令格式 和 数据传输 规则。
(1)Fastboot 命令格式
Fastboot 命令通常是 64 字节的字符串,不带参数的情况下格式如下:
COMMAND[ ][PARAMETERS]
例如:
fastboot flash boot boot.img
其命令结构为:
flash
—— Fastboot 命令boot
—— 目标分区boot.img
—— 需要刷写的镜像文件
(2)Fastboot 主要命令
Fastboot 命令 | 说明 |
---|---|
fastboot devices | 列出连接的 Fastboot 设备 |
fastboot reboot | 让设备重启 |
fastboot reboot-bootloader | 让设备重启回 Bootloader |
fastboot flash <分区> <文件> | 向指定分区刷写镜像 |
fastboot erase <分区> | 擦除指定分区的数据 |
fastboot format <分区> | 格式化指定分区 |
fastboot boot <boot.img> | 临时引导一个内核镜像 |
fastboot getvar <变量名> | 查询设备信息,例如 fastboot getvar version |
(3)Fastboot 的PC端可利用FB: ucmd
发送属于u-boot的命令
通过前面的叙述,开发板通过直接发送到RAM中的特制u-boot进入Fastboot 模式后,PC端就可以发送各种Fastboot命令给这个进入Fastboot 模式的u-boot来执行了。那有时候我们希望在Fastboot 模式下运行u-boot自身的命令,比如设置环境变这些,那又该怎么做呢?可以用FB的命令格式FB: ucmd
来执行。
FB: ucmd
允许NXP开发的烧写工具 uuu
通过 Fastboot 执行 U-Boot 的Shell 命令,这些命令通常用于:
- 检查和修改 U-Boot 环境变量(如
setenv
、saveenv
) - 执行 U-Boot 内部命令(如
mmc partconf
、boot
、reset
) - 进行一些逻辑判断(如
if-else
语句)
📌 示例
FB: ucmd setenv bootcmd "run bootcmd_mmc"
FB: ucmd saveenv
- 设置
bootcmd
为"run bootcmd_mmc"
- 保存 U-Boot 环境变量
再如:
FB: ucmd mmc partconf <dev> <boot_ack> <boot_partition> <partition_access>
mmc partconf
命令属于 U-Boot 的 MMC(MultiMediaCard)子系统命令,用于 配置 eMMC 的分区访问模式。它的作用是设置 eMMC 的 Boot 分区和访问方式,通常用于指定 eMMC 启动的分区。
📌 命令格式:
mmc partconf <dev> <boot_ack> <boot_partition> <partition_access>
<dev>
:eMMC 设备编号,通常是0
(表示/dev/mmcblk0
)。<boot_ack>
:是否启用 BOOT_ACK(0 = 关闭,1 = 启用)。<boot_partition>
:选择哪个 Boot 分区(0 = 用户区,1 =boot1
,2 =boot2
)。<partition_access>
:选择 eMMC进入“正常数据操作阶段”后,哪个分区作为活动分区,这里一般都是设置的是0,表示eMMC进入“正常数据操作阶段”后,使User Area区作为当前活动分区。关于这一点详细的介绍请参看我的另一篇博文 https://blog.csdn.net/wenhao_ir/article/details/145967306 【搜索“控制当前访问的 eMMC 分区”】)
📌 示例:
mmc partconf 0 1 1 0
- 设备
0
(eMMC) - 启用
BOOT_ACK
- 选择
boot1
作为启动分区 - eMMC进入“正常数据操作阶段”后,使User Area区作为当前活动分区。
3. Fastboot 在 eMMC 烧写中的作用
Fastboot 主要用于 eMMC 的固件烧写和更新,通常涉及以下几个关键分区:
- Bootloader(如 U-Boot)
- Kernel(内核镜像
zImage
或Image
) - Device Tree(设备树
dtb
) - RootFS(根文件系统)
- Recovery(恢复分区)
例如,在 eMMC 上使用 Fastboot 刷写一个新的 U-Boot:
fastboot flash bootloader u-boot.imx
如果需要刷写完整的系统:
fastboot flash boot boot.img
fastboot flash system system.img
fastboot flash userdata userdata.img
fastboot flash recovery recovery.img
fastboot reboot
4. 如何在 U-Boot 中启用 Fastboot
如果你使用的是 U-Boot 作为 Bootloader,并希望支持 Fastboot 模式,则需要配置 U-Boot 以启用 Fastboot 功能。
(1)U-Boot 配置选项
在 U-Boot 的 include/configs/your_board.h
或 configs/your_board_defconfig
中,需要启用以下选项:
CONFIG_CMD_FASTBOOT=y
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_FASTBOOT_BUF_ADDR=0x80800000 // 数据缓冲区
CONFIG_FASTBOOT_BUF_SIZE=0x20000000 // 缓冲区大小
CONFIG_FASTBOOT_FLASH=y
CONFIG_FASTBOOT_FLASH_MMC_DEV=0
(2)U-Boot 进入 Fastboot 模式
编译并启动 U-Boot 后,可以手动进入 Fastboot 模式:
=> fastboot 0
或者自动进入:
setenv bootcmd "fastboot 0"
saveenv
reset
(3)PC 端测试
PC 端可以通过 USB 连接设备,并使用 fastboot
命令:
fastboot devices
如果设备正确进入 Fastboot 模式,会显示设备 ID。
5. Fastboot 如何烧写 eMMC 存储器
对于 eMMC 设备,可以使用 Fastboot 直接刷写各个分区,例如:
fastboot flash bootloader u-boot.imx
fastboot flash boot boot.img
fastboot flash recovery recovery.img
fastboot flash system rootfs.img
然后让设备重启:
fastboot reboot
6.Fastboot的flash命令如何确定将镜像烧写到哪里?
关于这个问题,其实通过下面这个问题:
下面这条Fastboot命令:
flash bootloader ../../../files/u-boot-dtb.imx
它到底是把u-boot-dtb.imx烧写到eMMC设备的哪个分区?它写到哪个分区是在哪里设置的?
的回答,我们就知道答案了。
回答如下:
1、关键决策因素
Fastboot 在 U-Boot 中决定烧写目标区域的关键点有:
① 分区映射:
- Fastboot 的
flash <partition>
命令,其中<partition>
是 U-Boot 维护的一个分区名称,例如bootloader
、boot
、system
等。 - 这些分区的具体存储地址是由 U-Boot 代码中的
fastboot_partitions
机制决定的。
②U-Boot 代码实现:
- 在
cmd/fastboot.c
或drivers/fastboot
相关代码中,Fastboot 处理flash
命令时,会先查找 U-Boot 内部的 分区表(通常定义在fastboot_get_ptn()
函数中)。 - 具体的分区信息可能来自:
- U-Boot 代码中硬编码的表
- 设备树(Device Tree)中的 Fastboot 分区配置
- U-Boot 环境变量
2、 哪里决定 bootloader
被烧写的位置?
(1)U-Boot 代码中的 Fastboot 分区表
在 cmd/fastboot.c
或 common/fastboot.c
代码中,有一部分代码会定义 Fastboot 的MMC设备的分区表,比如:
static struct fastboot_ptentry partition_table[] = {
{ .name = "bootloader", .start = 0x400, .length = 0x800, .flags = FASTBOOT_PT_BOOTABLE },
{ .name = "boot", .start = 0x1000, .length = 0x8000 },
{ .name = "system", .start = 0x9000, .length = 0x20000 },
};
这里定义了 bootloader
分区的起始地址为 0x400
(单位可能是扇区或字节),这就决定了命令 fastboot flash bootloader
会写入 eMMC 的这个偏移。
(2)设备树 (Device Tree)
在一些 SoC(如 i.MX6ULL)上,Fastboot 的分区信息可能会从 设备树 (.dts
) 里获取,例如:
partition@0 {
label = "bootloader";
reg = <0x400 0x800>;
};
如果 Fastboot 代码支持解析设备树,则 bootloader
分区的位置是由 .dts
定义的。
(3)U-Boot 环境变量
有些 U-Boot 版本允许使用 环境变量 来决定 bootloader
该写入哪里,比如:
setenv fastboot_partition_bootloader mmcblk0boot0
saveenv
这意味着 bootloader
会被写入编号为0的MMC设备的boot0
分区(即Boot partition 1
分区)。
你可以运行以下命令检查:
printenv | grep fastboot
看看是否有 fastboot_partition_*
相关的环境变量。
3、如何确定 bootloader
被写到哪里?
如果你想确定 bootloader
实际被烧录的位置,你可以:
-
检查 U-Boot 代码
如果你自己编译 U-Boot,看看cmd/fastboot.c
或drivers/fastboot/
相关代码,是否定义了bootloader
对应的 eMMC 分区。但很遗憾的是,天知道通过烧写工具发送到内存中支持Fastboots模式的u-boot中的代码是怎么样的。 -
烧写完成后,启动u-boot后,使用
mmc
的相关命令查看EXT_CSD[179]的信息
烧写完成后,并正常启动u-boot后,可以使用使用mmc
的相关命令查看EXT_CSD[179]的信息,详情见 https://blog.csdn.net/wenhao_ir/article/details/146016551 【搜索“利用MMC子系统查看和修改eMMC设备的”】。当知道EXT_CSD[179]的信息后,又由于u-boot能正常启动,就可以倒推烧写命令是把u-boot-dtb.imx烧写到eMMC中的哪个分区了。 -
烧写完成后,启动u-boot后,手动读取 eMMC 内容
你可以用mmc read
或hexdump
检查不同分区:
先用命令mmc list
获取eMMC在u-boot中的编号:
这个结果的详细解释见 https://blog.csdn.net/wenhao_ir/article/details/146016551【搜索“先运行命令看下eMMC设备在u-boot中的编号”】
然后用下面的命令分别读取编号为1的eMMC设备的各个区:mmc dev 1 1 选择 boot1 mmc read 0x82000000 0 0x100 读取前 0x100 个块 md 0x82000000 查看数据 mmc dev 1 2 选择 boot2 mmc read 0x82000000 0 0x100 md 0x82000000 mmc dev 1 0 选择用户区 mmc read 0x82000000 0 0x100 md 0x82000000
通过以上这几条命令,读取到各区的前100个数据,然后去分析到底是烧写到了哪里。至于boot1、boot2、用户数据区的编号为什么分别为1、2、0,请参看我的另一篇博文 添加链接描述 【搜索“选择当前访问的 eMMC 分区”】
4. 如何更改 bootloader
的烧写位置?
如果你希望让 fastboot flash bootloader
写入 eMMC 的 boot0 或 boot1 分区,你可以:
①直接指定 eMMC 分区(如果 U-Boot 支持)
fastboot flash mmcblk0boot0 ../../../files/u-boot-dtb.imx
或者:
fastboot flash mmcblk0boot1 ../../../files/u-boot-dtb.imx
② 修改 U-Boot 代码
- 在
cmd/fastboot.c
里,把bootloader
分区映射到boot0
或boot1
,或者直接修改它的位置参数。
③修改设备树
- 确保
bootloader
对应的.dts
定义正确。
④使用环境变量
setenv fastboot_partition_bootloader mmcblk0boot0
saveenv