Fastboot 是引导加载程序模块和模式的名称。Android 10 及更高版本通过将 fastboot 实现从引导加载程序重新定位至用户空间,支持对分区大小进行调整。经过重定位之后,硬件抽象层 (HAL) 只需要实现 fastboot 的供应商特定部分,便可将代码移动和刷写到可维护且可测试的公共位置。此外,Android 12 及更高版本还支持通过一条新增的 fastboot 命令刷写 ramdisk。
统一 fastboot 和 recovery
由于用户空间 fastboot 和 recovery 彼此类似,因此您可以将它们合并为一个分区或二进制文件。这样做的优势包括从整体上减少所占用的空间以及使用的分区数,并使 fastboot 和 recovery 能够共享彼此的内核和库。
Fastbootd 是用户空间守护程序和模式的名称。为支持 fastbootd
,引导加载程序必须实现 boot-fastboot
的一个新启动控制块 (BCB) 命令。如需进入 fastbootd
模式,引导加载程序应将 boot-fastboot
写入 BCB 消息的命令字段,并保持 BCB 的 recovery
字段不变(以重启中断的 recovery 任务)。status
、stage
和 reserved
字段也保持不变。引导加载程序在 BCB 命令字段中发现 boot-fastboot
时,会加载并启动到恢复映像。然后,recovery 会解析 BCB 消息并切换到 fastbootd
模式。
ADB 命令
本部分介绍了用于集成 fastbootd
的 adb
命令。该命令会返回不同的结果,具体取决于命令是由 system 还是由 recovery 来执行的。
命令 | 说明 |
---|---|
reboot fastboot |
|
fastboot 命令
本部分介绍了用于集成 fastbootd
的 fastboot 命令,其中包括用于刷写和管理逻辑分区的新命令。有些命令会返回不同的结果,具体取决于命令是由引导加载程序还是由 fastbootd
来执行的。
命令 | 说明 |
---|---|
reboot recovery |
|
reboot fastboot |
重新启动到 fastbootd 。 |
getvar is-userspace |
|
getvar is-logical:<partition> |
如果指定的分区是逻辑分区,则返回 yes ,否则返回 no 。
逻辑分区支持下面列出的所有命令。 |
getvar super-partition-name |
返回超级分区的名称。如果超级分区是 A/B 分区(通常并不是),则该名称会包含当前槽后缀。 |
create-logical-partition <partition> <size> |
创建具有指定名称和大小的逻辑分区。该名称不得为现有逻辑分区的名称。 |
delete-logical-partition <partition> |
删除指定的逻辑分区(有效擦除分区)。 |
resize-logical-partition <partition> <size> |
将逻辑分区的大小调整为新的大小,而不更改其内容。如果没有足够的空间来调整大小,则会失败。 |
update-super <partition> |
合并对超级分区元数据的更改。如果无法合并(例如,设备上的格式版本不受支持),则此命令将失败。可选的 wipe 参数会覆盖设备的元数据,而不是执行合并。 |
flash <partition> [ <filename> ] |
将文件写入刷写分区。设备必须处于解锁状态。 |
erase <partition> |
擦除分区(不要求安全擦除)。设备必须处于解锁状态。 |
getvar <variable> | all |
显示引导加载程序变量或所有变量。如果变量不存在,则返回错误。 |
set_active <slot> |
将指定的 A/B 启动槽设置为 对于 A/B 支持,槽是指可以单独启动的重复分区集。槽的名称为 |
reboot |
正常重新启动设备。 |
reboot-bootloader (或 reboot bootloader ) |
将设备重新启动到引导加载程序。 |
fastboot fetch vendor_boot <out.img> |
在 Android 12 及更高版本中用于支持刷写供应商 ramdisk。
获取整个分区的大小和分块的大小。获取每个分块的数据,然后将数据拼接成
如需了解详情,请参阅 |
fastboot flash vendor_boot:default <vendor-ramdisk.img> |
在 Android 12 及更高版本中用于支持刷写供应商 ramdisk。 这是 flash 命令的一个特殊变体。它用于执行
如需了解详情,请参阅 |
fastboot flash vendor_boot:<foo> <vendor-ramdisk.img> |
在 Android 12 及更高版本中用于支持刷写供应商 ramdisk。 获取 如需了解详情,请参阅 |
fastboot 和引导加载程序
引导加载程序会刷写 bootloader
、radio
和 boot/recovery
分区,之后设备将启动到 fastboot(用户空间)并刷写所有其他分区。引导加载程序应支持以下命令。
命令 | 说明 |
---|---|
download |
下载映像以进行刷写。 |
flash recovery <image>/ flash boot <image>/ flash
bootloader <image>/ |
刷写 recovery/boot 分区和引导加载程序。 |
reboot |
重新启动设备。 |
reboot fastboot |
重新启动到 fastboot。 |
reboot recovery |
重新启动到 recovery。 |
getvar |
获取刷写 recovery/启动映像所需的引导加载程序变量(例如 current-slot 和 max-download-size )。 |
oem <command> |
由原始设备制造商 (OEM) 定义的命令。 |
动态分区
引导加载程序不得允许刷写或清空动态分区,并且必须在尝试这些操作时返回错误。对于改装的动态分区设备,fastboot 工具(和引导加载程序)支持强制模式,以便在引导加载程序模式下直接刷写动态分区。例如,如果 system
是改装设备上的动态分区,那么,使用 fastboot --force flash system
命令可让引导加载程序(而不是 fastbootd
)刷写该分区。
关机模式充电
如果设备支持关机模式充电,或者在通电时自动启动到特殊模式,fastboot oem off-mode-charge 0
命令的实现必须绕过这些特殊模式,以便设备像用户按了电源按钮一样启动。
fastboot OEM HAL
如需完全替换引导加载程序 fastboot,fastboot 必须处理所有现有的 fastboot 命令。其中很多命令都来自 OEM 并已形成文档,但需要自定义实现。也有很多 OEM 专用命令没有形成文档。为处理此类命令,fastboot HAL 会指定所需的 OEM 命令。OEM 也可以实现自己的命令。
fastboot HAL 的定义如下:
import IFastbootLogger;
/**
* IFastboot interface implements vendor specific fastboot commands.
*/
interface IFastboot {
/**
* Returns a bool indicating whether the bootloader is enforcing verified
* boot.
*
* @return verifiedBootState True if the bootloader is enforcing verified
* boot and False otherwise.
*/
isVerifiedBootEnabled() generates (bool verifiedBootState);
/**
* Returns a bool indicating the off-mode-charge setting. If off-mode
* charging is enabled, the device autoboots into a special mode when
* power is applied.
*
* @return offModeChargeState True if the setting is enabled and False if
* not.
*/
isOffModeChargeEnabled() generates (bool offModeChargeState);
/**
* Returns the minimum battery voltage required for flashing in mV.
*
* @return batteryVoltage Minimum battery voltage (in mV) required for
* flashing to be successful.
*/
getBatteryVoltageFlashingThreshold() generates (int32_t batteryVoltage);
/**
* Returns the file system type of the partition. This is only required for
* physical partitions that need to be wiped and reformatted.
*
* @return type Can be ext4, f2fs or raw.
* @return result SUCCESS if the operation is successful,
* FAILURE_UNKNOWN if the partition is invalid or does not require
* reformatting.
*/
getPartitionType(string partitionName) generates (FileSystemType type, Result result);
/**
* Executes a fastboot OEM command.
*
* @param oemCmd The oem command that is passed to the fastboot HAL.
* @response result Returns the status SUCCESS if the operation is
* successful,
* INVALID_ARGUMENT for bad arguments,
* FAILURE_UNKNOWN for an invalid/unsupported command.
*/
doOemCommand(string oemCmd) generates (Result result);
};
启用 fastbootd
如需在设备上启用 fastbootd
,请执行以下操作:
将
fastbootd
添加到device.mk
中的PRODUCT_PACKAGES
:PRODUCT_PACKAGES += fastbootd
。确保将 fastboot HAL、启动控制 HAL 和运行状况 HAL 打包为恢复映像的一部分。
添加
fastbootd
所需的任何设备特定 SEPolicy 权限。例如,fastbootd
需要对设备特定分区进行写入访问,才能刷写该分区。此外,fastboot HAL 实现也可能需要设备特定权限。
如需验证用户空间 fastboot,请运行供应商测试套件 (VTS)。
刷写供应商 ramdisk
Android 12 及更高版本支持通过一条新增的 fastboot 命令从设备中拉取整个 vendor_boot
映像,从而刷写供应商 ramdisk。该命令会提示主机端 fastboot 工具读取供应商启动头文件、重装映像并刷写新映像。
为了拉取整个 vendor_boot
映像,Android 12 中为 fastboot 协议和该协议的 fastbootd 实现都添加了 fetch:vendor_boot
命令。请注意,fastbootd 的确实现了这一点,但引导加载程序本身可能没有实现。OEM 可以将 fetch:vendor_boot
命令添加到该协议的引导加载程序实现中。不过,如果在引导加载程序模式下无法识别该命令,那么在引导加载程序模式下刷写各供应商 ramdisk 就不能作为供应商支持的选项。
引导加载程序的变更
命令 getvar:max-fetch-size
和 fetch:name
在 fastbootd
中实现。如需支持在引导加载程序中刷写供应商 ramdisk,必须实现这两个命令。
fastbootd 变更
getvar:max-fetch-size
类似于 max-download-size
。它用于指定设备在一个 DATA 响应中可以发送的大小上限。驱动程序不得提取大于此值的大小。
fetch:name[:offset[:size]]
用于对设备执行一系列检查。如果满足以下所有条件,fetch:name[:offset[:size]]
命令将返回数据:
- 设备运行的是可调试的 build。
- 设备已解锁(启动状态为橙色)。
- 提取的分区名称为
vendor_boot
。 size
值在 0 <size
<=max-fetch-size
的范围内。
验证上述条件后,fetch:name[:offset[:size]]
将返回分区大小和偏移量。
请注意以下几点:
fetch:name
相当于fetch:name:0
,相当于fetch:name:0:partition_size
。fetch:name:offset
相当于fetch:name:offset:(partition_size - offset)
因此 fetch:name[:offset[:size]]
= fetch:name:offset:(partition_size - offset)
。
如果未指定 offset
和/或 partition_size
,系统将使用默认值,即 offset
使用 0,size
使用 partition_size - offset
计算出的值。
- 指定了偏移量,未指定大小:
size = partition_size - offset
- 二者都未指定:二者都使用默认值,即
size = partition_size
- 0。
例如,fetch:foo
会在偏移量 0 处提取整个 foo
分区。
驱动程序变更
fastboot 工具中添加了用于实现驱动程序变更的命令。每项命令都链接到其在 fastboot 命令表中的完整定义。
fastboot fetch vendor_boot out.img
- 调用
getvar max-fetch-size
可确定分块大小。 - 调用
getvar partition-size:vendor_boot[_a]
可确定整个分区的大小。 - 针对每个分块调用
fastboot fetch vendor_boot[_a]:offset:size
。(分块大小大于vendor_boot
大小,因此通常只有一个分块。) - 将数据拼接成
out.img
。
- 调用
fastboot flash vendor_boot:default vendor-ramdisk.img
这是 flash 命令的一个特殊变体。它用于提取
vendor_boot
映像,就好像调用了fastboot fetch
一样。fastboot flash vendor_boot:foo vendor-ramdisk.img
提取
vendor_boot image
,就好像调用了fastboot fetch
一样。- 如果供应商启动头文件为版本 3,它会返回错误。
如果供应商启动头文件为版本 4,它会执行以下操作:
- 查找名为
ramdisk_<var><foo></var>
的供应商 ramdisk 片段。如果找不到或有多个匹配项,就返回错误。 - 将供应商 ramdisk 片段替换为指定映像。
- 重新计算供应商 ramdisk 表中的每个大小和偏移量。
- 刷写新的
vendor_boot
映像。
- 查找名为
如果未指定 <foo>,则会尝试查找
ramdisk_
。
mkbootimg
在 Android 12 及更高版本中,default
为预留名称,不能为供应商 ramdisk fragment 设定此名称。虽然 fastboot flash vendor_boot:default
语义保持不变,但您不得将 ramdisk fragment 命名为 default
。
SELinux 更改
为了支持刷写供应商 ramdisk,fastbootd.te
中做出了一项更改。