运行于u-boot中的Fastboot(FB)协议的详细介绍(快速烧写 eMMC、NAND、UFS 等存储设备的协议)

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 运行流程:

  1. 设备进入 Fastboot 模式,等待命令。
  2. PC 端使用 fastboot 工具发送指令(如分区擦除、镜像写入等)。
  3. 设备执行相应的操作,并返回执行状态。

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 环境变量(如 setenvsaveenv
  • 执行 U-Boot 内部命令(如 mmc partconfbootreset
  • 进行一些逻辑判断(如 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(内核镜像 zImageImage
  • 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.hconfigs/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 维护的一个分区名称,例如 bootloaderbootsystem 等。
  • 这些分区的具体存储地址是由 U-Boot 代码中的 fastboot_partitions 机制决定的。

U-Boot 代码实现

  • cmd/fastboot.cdrivers/fastboot 相关代码中,Fastboot 处理 flash 命令时,会先查找 U-Boot 内部的 分区表(通常定义在 fastboot_get_ptn() 函数中)。
  • 具体的分区信息可能来自:
    • U-Boot 代码中硬编码的表
    • 设备树(Device Tree)中的 Fastboot 分区配置
    • U-Boot 环境变量

2、 哪里决定 bootloader 被烧写的位置?

(1)U-Boot 代码中的 Fastboot 分区表
cmd/fastboot.ccommon/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 实际被烧录的位置,你可以:

  1. 检查 U-Boot 代码
    如果你自己编译 U-Boot,看看 cmd/fastboot.cdrivers/fastboot/ 相关代码,是否定义了 bootloader 对应的 eMMC 分区。但很遗憾的是,天知道通过烧写工具发送到内存中支持Fastboots模式的u-boot中的代码是怎么样的。

  2. 烧写完成后,启动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中的哪个分区了。

  3. 烧写完成后,启动u-boot后,手动读取 eMMC 内容
    你可以用 mmc readhexdump 检查不同分区:
    先用命令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 分区映射到 boot0boot1,或者直接修改它的位置参数。

修改设备树

  • 确保 bootloader 对应的 .dts 定义正确。

使用环境变量

setenv fastboot_partition_bootloader mmcblk0boot0
saveenv

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值