i.MX8 BootLoader中AVB启动验证流程分析
do_boota函数分析
函数在./drivers/usb/gadget/f_fastboot.c
文件中。
1. 判断从boot分区还是recovery启动
1 |
|
2. 判断是否跳过AVB
1 |
|
如果环境变量设置了skip_avb = 1,则将跳过AVB。
3. 如果定义了CONFIG_FASTBOOT_LOCK
3.1 检查fastboot有没有被锁定
如果设置了skip_avb = 1
,则fsatboot已解锁,否则则认为已锁定。
如果设置了skip_avb = 1
,则允许校验失败。
1 |
|
3.2 判断是否为A/B双系统
- AB双系统:调用
avb_ab_flow_fast()
进行AVB校验 - 非AB双系统:调用
avb_single_flow()
并判断从boot
分区还是recovery
分区启动1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#ifdef CONFIG_ANDROID_AB_SUPPORT
/* we can use avb to verify Trusty if we want */
const char *requested_partitions[] = {"boot", 0};
avb_result = avb_ab_flow_fast(&fsl_avb_ab_ops, requested_partitions, allow_fail,
AVB_HASHTREE_ERROR_MODE_RESTART_AND_INVALIDATE, &avb_out_data);
#else /* CONFIG_ANDROID_AB_SUPPORT */
if (!is_recovery_mode) {
const char *requested_partitions[] = {"boot", 0};
avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail,
AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
} else {
const char *requested_partitions[] = {"recovery", 0};
avb_result = avb_single_flow(&fsl_avb_ab_ops, requested_partitions, allow_fail,
AVB_HASHTREE_ERROR_MODE_RESTART, &avb_out_data);
}
#endif /* CONFIG_ANDROID_AB_SUPPORT */
3.2.1 avb_ab_flow_fast()
函数在文件./lib/avb/libavb_ab/avb_ab_flow.c
中,这里只分析A/B双系统的情况。
首先加载meta dada,如果出错,则直接报错返回。
然后判断slot启动优先级:1
target_slot = (ab_data.slots[1].priority > ab_data.slots[0].priority ? 1 : 0);
然后判断该slot能否启动,如果不能启动则切换为另一个slot。
1
2
3if (!slot_is_bootable(&ab_data.slots[target_slot])) {
target_slot = (target_slot == 1 ? 0 : 1);
continue;其中判断能否启动的函数是通过slot的successful_boo标志位和剩余尝试次数来判断的。
1
2
3
4static bool slot_is_bootable(AvbABSlotData *slot) {
return slot->priority > 0 &&
(slot->successful_boot || (slot->tries_remaining > 0));
}实际上调用
avb_slot_verify
函数进行AVB校验。1
2
3
4
5
6verify_result = avb_slot_verify(ops,
requested_partitions,
slot_suffixes[target_slot],
flags,
hashtree_error_mode,
&slot_data[target_slot]);验证结果处理
如果是
ERROR_OOM
或者ERROR_IO
,会直接返回校验失败并goto至clean_up函数。如果验证成功,会将当前slot作为启动的slot。
1
2
3
4case AVB_SLOT_VERIFY_RESULT_OK:
slot_index_to_boot = target_slot;
n = 2;
break;如果是不合法的元数据或者不允许的版本(回滚保护),及时设置flag允许校验失败也没有用,会将当前slot设置为unbootable。
1
2
3
4
5
6
7case AVB_SLOT_VERIFY_RESULT_ERROR_INVALID_METADATA:
case AVB_SLOT_VERIFY_RESULT_ERROR_UNSUPPORTED_VERSION:
/* Even with AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR
* these mean game over.
*/
set_slot_unbootable = true;
break;如果是下列的校验不通过结果,会判断是否设置了允许启动,是的话则允许启动,否则标记当前slot为不可启动,接下来会循环判断另一个分区。
所以在安卓O里自动切换可启动分区是在这里实现的。
1 |
|
1 |
|
- 如果参数不对,则也直接返回。
1 |
|
3.3 AVB校验结果处理
- 校验成功:加载分区。
- 校验失败但是设置了允许失败(allow_fail):设置了skip_avb = 1或者判断fastboot已解锁,still 加载分区
- 校验失败且fastboot已锁定:打印校验失败且锁定,goto fail,进入fastboot刷新模式;
- 校验失败但fastboot未锁定:实际不会走到该分支,fastboot解锁后失败会走第二个分支。
i.MX8 BootLoader中AVB启动验证流程分析
https://www.shangyexin.com/2018/12/28/imx8-bootloader-avb/