前言
本文汇总所有本人在基于 SM8250 处理器的高通参考设计移动平台开发时遇到的所有问题及其解决方案。不定期更新。
Questions & Solutions
新版本 UEFI ABL (uefi.lnx.5.0) 内存访问越界导致 UEFI panic 的相关问题
前言:设备一直使用的是 LE.UM.
开头的 ABL 仓库代码,高通表示这是给 Ubuntu 用的(也能解释安全启动相关代码中的 VB_LE 的优先级最高了),不能用于 Android 启动(事实上成功启动了,但是 VerifiedBoot 是废的),于是研究决定采用高通官方提供的 LA.
开头的 ABL。(高通这个代码命名好抽象,LE.UM
是 Debian 等发行版、LA
是 Android、UBUN
是 Ubuntu...)。刚开始用的是 SoC BSP 里内核推荐的版本 uefi.lnx.4.0,但是开机运行到某个函数有玄学问题,随后代码比对发现 uefi.lnx.5.0 中的该函数签名和 LE.UM.
开头的 ABL 的仓库代码中一致,觉得用 5.0 更有戏,然后就开始折腾了...
关键词: data fault/panic/mmu/avb
设备在 Bootloader 阶段默认允许访问地址从 0x80000000
开始,XBL 中有对设备所有 Bootloader 阶段的内存定义。
分析新版本 ABL 中的 AVB 启动流程,vbmeta
、boot
、dtbo
、vendor_boot
分区都是由 avb_slot_verify()
负责加载到内存,并且存在代码的 loaded_partitions
,随后核心函数 BootLinux()
调用 GetImage()
函数,而 GetImage()
函数则将启动参数结构体中的 ImageBuffer
指向 loaded_partitions[0].image_buffer
(代码均是写死的,除非内核在 recovery 分区(某些 Android 版本是这样设计的),否则 boot 分区永远第一)。然后开机发现,出现 data fault panic 了,查看寄存器中的地址,后续调试发现与 DtSingleHdr
指针地址一致,该指针计算方法为 ImageBuffer + DtbOffset
(新版本 UEFI 根据启动头版本判断是否小于 1 再加 PageSize),与旧版 ABL 启动日志比对发现,DtbOffset 和 PageSize 均未变化,唯一有变化且为巨大变化的是 ImageBuffer 的地址。随后发现 AllocateZeroPool()
函数不知道为什么分配了一个 0x2XXXXXXX 的地址。该地址在 UEFI 中肯定是不允许访问的,而且 MMU 检测到 CPU 越界访问直接 Panic...
至此问题明了(一句话带过一天一夜的心酸努力),调整为 UEFI DXE 分配的内存地址和大小后,刷入顺利开机。
Android 启动失败,init 进程找不到默认 fstab
根据结果,逆向查找问题原因:发现 Ramdisk 已正确挂载,init 找不到这几个 prop:fstab_suffix
, hardware
, hardware.platform
,无法获取到正确的默认 fstab 文件名。
查看 init 代码发现,这几个 props 是从内核 cmdline 或 bootconfig 获取,高通在 HDR v4 通过 bootconfig 提供这几个参数。
观察启动日志,注意到 Failed to parse bootconfig: Value is redefined at
错误,发现内核未能正确处理 bootconfig,有重复定义的值,经过检查,发现 bootconfig 中确实存在重复值 androidboot.boot_devices
。但是高通的设备树中又定义了这个值,删去后问题解决。查询重复原因,发现 ABL 会向 bootconfig 中添加 androidboot.boot_devices
,因此无需在设备树中再次添加。
Android 启动失败,init 进程找不到默认 super 分区
检查 Bootloader 向后传递的启动参数中的soc/
是否更正为soc@0/
评论 (0)