fastboot刷写与嵌入式Linux启动优化实战 - 第1节

1.1 Fastboot 协议概述

Fastboot 是 Android 与嵌入式 Linux 系统在 bootloader 阶段使用的一种主机-设备通信协议。它运行在 USB 或 TCP 传输层之上,允许主机向设备的分区写入镜像、读取设备信息、控制启动流程。与 adb 不同,Fastboot 在操作系统内核启动之前即可工作,因此是刷写固件、恢复变砖设备的最后一道防线。

核心定位:Fastboot 是 bootloader 暴露给主机的命令通道,不依赖内核驱动,仅依赖 bootloader 的 USB 设备栈与协议解析逻辑。

1.1.1 协议工作模式

Fastboot 采用 请求-响应 模型:主机发送 ASCII 命令包,设备执行后返回状态码(OKAY、FAIL、DATA 或 INFO)。整个交互过程在 bootloader 的 main loop 中同步完成,不支持并发命令。

阶段 动作 典型耗时
设备枚举 设备以 Fastboot 模式枚举 USB 描述符(idVendor=0x18D1, idProduct=0x0D02) < 1s
命令发送 主机发送 getvar:version 等探测命令 10–50ms
数据传输 主机通过 download: 命令发送镜像数据 取决于镜像大小与 USB 速率
刷写执行 设备将数据写入分区(flash:boot) 100ms–数秒
实战提示:如果设备在 fastboot devices 中不显示,优先检查 USB 线缆、驱动(Windows 需安装 Google USB Driver)以及设备是否确实进入了 Fastboot 模式(通常通过组合键或 adb reboot bootloader 进入)。

1.2 USB 通信原理

Fastboot 基于 USB 批量传输(Bulk Transfer) 实现,使用端点 1(IN)和端点 1(OUT),最大包大小通常为 512 字节(USB 2.0)或 1024 字节(USB 3.0)。协议层不依赖 USB 中断传输或同步传输,因此延迟可控且吞吐量较高。

1.2.1 USB 描述符与枚举

设备在 Fastboot 模式下必须暴露以下 USB 描述符信息,主机通过 libusb 或内核 USB 子系统识别并与之通信:

  • 设备描述符:idVendor = 0x18D1(Google),idProduct = 0x0D02(Fastboot)
  • 接口描述符:bInterfaceClass = 0xFF(vendor-specific),bInterfaceSubClass = 0x42,bInterfaceProtocol = 0x03
  • 端点描述符:批量端点 IN(0x81)与 OUT(0x01),wMaxPacketSize = 512
常见陷阱:部分嵌入式 Linux 板卡(如 Rockchip、Allwinner)使用自定义 VID/PID,此时需要手动添加 udev 规则或驱动映射,否则主机无法识别设备。

1.2.2 批量传输流程

一次完整的 Fastboot 命令交互包含以下 USB 传输步骤:

  1. 主机通过 OUT 端点发送命令字符串(如 getvar:version),末尾无换行符。
  2. 设备解析命令,执行操作,通过 IN 端点返回状态包(4 字节 ASCII 码:OKAY、FAIL、DATA、INFO)。
  3. 若为 DATA 状态,后续跟一个 8 字节的十六进制数据长度(如 0x00001000),主机据此准备接收数据。
  4. 主机继续发送或接收数据包,直到设备返回 OKAY 或 FAIL 结束本次事务。
Fastboot USB 批量传输流程 主机 (Host) 设备 (Device) 发送命令 (OUT) 返回状态 (IN) 传输数据 (Bulk) 批量传输端点 EP1 OUT / EP1 IN

1.3 Fastboot 命令集解析

Fastboot 命令集分为 查询命令、刷写命令、控制命令 三大类。所有命令均为 ASCII 字符串,以 \0 或 \n 结尾(具体由 bootloader 实现决定)。

1.3.1 常用命令速查表

命令 参数 功能描述 典型响应
getvar version / product / serialno 查询 bootloader 版本、产品名、序列号 OKAY 0.4
download ${size_in_hex} 通知设备即将下载指定字节的数据 DATA 0x00001000
flash ${partition_name} 将已下载的数据写入指定分区 OKAY 或 FAIL
erase ${partition_name} 擦除指定分区(通常用全 0 填充) OKAY
boot 无 从内存中已下载的内核镜像直接启动 OKAY 后设备重启
reboot bootloader 或空 重启设备,可选进入 bootloader 模式 OKAY 后设备重启
oem 厂商自定义子命令 执行厂商特定操作(如解锁、日志输出) 厂商定义

1.3.2 命令交互示例

以下是一次完整的 fastboot flash boot boot.img 操作对应的协议层交互:

# 主机发送下载命令,告知设备即将发送 0x1000 字节
> download:00001000
# 设备回复 DATA,表示准备好接收
< DATA 0x00001000
# 主机发送 0x1000 字节的镜像数据(分多个批量包)
> [binary data ...]
# 设备接收完毕,回复 OKAY
< OKAY
# 主机发送刷写命令
> flash:boot
# 设备将数据写入 boot 分区,回复 OKAY
< OKAY
关键细节:所有长度字段均为小写十六进制字符串,无 0x 前缀。设备返回的 DATA 状态后跟 8 字节长度(高位在前),主机必须严格按此长度收发数据,否则协议会进入死锁。

1.3.3 命令集分类对比

类别 命令举例 是否修改分区 是否依赖下载
查询命令 getvar, devices 否 否
刷写命令 flash, erase, update 是 是(flash 需要先 download)
控制命令 reboot, boot, continue 否 否(boot 需要先 download)
OEM 命令 oem unlock, oem device-info 可能 通常否
Fastboot 命令集分类结构 Fastboot 命令集 查询命令 刷写命令 控制命令 OEM 命令 getvar, devices flash, erase, update reboot, boot, continue oem unlock, oem … 所有命令均为 ASCII 文本,通过批量端点传输

1.3.4 状态码与错误处理

设备返回的 4 字节状态码决定了命令的执行结果:

  • OKAY:命令执行成功,无后续数据。
  • FAIL:命令执行失败,后续可跟一条 INFO 消息说明原因(如分区不存在、镜像大小超限)。
  • DATA:命令需要传输数据,后续 8 字节为数据长度(十六进制)。
  • INFO:信息消息,可连续出现多条,用于向主机输出日志或进度。
调试建议:当刷写失败时,使用 fastboot getvar all 获取设备全部变量,检查分区表、槽位(slot)状态、安全锁状态。很多 FAIL 响应源于分区保护或签名校验未通过。