高通平台UEFI有关介绍
背景
我需要在高通平台上学习点亮LCD,目前通过同事在别的平台的配置代码,我已经将kernel部分的屏幕点亮了;剩余的工作量就在BP侧,也就是系统刚开机的那一段时间。在开发过程中,我发现我对BP侧的开发有点不太熟悉,因此我需要搞清楚有关的概念。只有搞清楚了这些基本概念,我才能够在后续的工作中不留下隐患。
有关文档:
- https://www.cnblogs.com/we-hjb/p/9800627.html
- https://blog.csdn.net/u014089131/article/details/73617716
- https://blog.csdn.net/weixin_41803132/article/details/107692862
- 高通UEFI、XBL及ABL的详细介绍: 《80_P2484_37_LINUX_ANDROID_UEFI_OVERVIEW.pdf》。
UEFI 介绍
UEFI(Unified extensible firmware interface)统一的可扩展固件接口,是一种详细描述类型接口的标准。
可扩展固件接口(Extensible Firmware Interface,EFI)是 Intel 为 PC 固件的体系结构、接口和服务提出的建议标准。其主要目的是为了提供一组在 OS 加载之前(启动前)在所有平台上一致的、正确指定的启动服务,被看做是有近20多年历史的 BIOS 的继任者。
BIOS是汇编实现的,采用的是16bit 实模式寻址方式,最大支持的内存只有1M,代码易读性以及实现的功能都受到限制,而且移植起来不方便。BIOS支持的最大磁盘空间不超过2TB。
UEFI克服了上述的所有缺点,采用C语言实现,分层,模块化设计,实现了CPU以及驱动的无关性。UEFI可以理解为一个完整的系统,包含了上电时序,驱动实现,os环境建立(这个os可以理解为UEFI运行独有的os,非linux,windows),应用程序。其中应用程序支持网络配置,类shell环境,fastboot,linux loader等。
UEFI启动阶段
UEFI从上电到关机,一共有七个阶段:
-
SEC(安全验证)
其功能包括:接受处理系统启动与重启信号、初始化临时RAM区、作为可信系统的根、以及传递系统参数到下一阶段。
其执行流程是:
上电 -> ResetVector -> SEC函数入口 -> PEI函数入口 -
PEI
主要功能是为DXE准备执行环境,将HOB列表传递给DXE。此阶段到后期内存才被初始化,所以资源相当有限,尚未可进行复杂的工作。 -
DXE
此阶段执行大部分系统初始化工作,内存已被初始化,可以进行大量复杂工作。当所有的Driver都执行完毕,说明系统初始化完成,接着通过EFI_BDS_ARCH_PROTOCAL找到BDS并调用BDS的入口函数,进入BDS阶段。 -
BDS
此阶段主要功能是执行启动策略,等OS Loader启动后,系统进入TSL阶段。 -
TSL
TSL是OS Loader执行的第一阶段,OS Loader在这个阶段作为UEFI APPLICATION运行,当ExitBootServices服务被调用后,进入RT(RunTime)阶段。 -
RT
系统进入此阶段后,系统控制权从UEFI内核转交到OS Loader上。随着OS Loader的执行,OS最终取得对系统的 控制权。 -
AL
在RT阶段,如果系统遇到灾难性错误,系统固件需要提供错误处理和灾难恢复机制,而这种机制运行在AL阶段。
其中UEFI中涉及的名词缩写 :
缩写 | 意义 |
---|---|
UEFI | Unified extensible firmware interface |
SEC | Security |
PEI | Pre EFI initialization |
DXE | Driver execution Environment |
BDS | Boot Dev Select |
TSL | Transient System Loa |
RT | Runtime |
AL | After life |
GUID | Globally Unique Identifier |
CSM | Compatibility Support Modul |
TCG | Trusted Computing Group |
PE | Portable executable |
COFF | Common object file format |
FV | Firmware Volume |
UEFI有关文件格式
fdf:flash definitionfile,描述flash分区地址范围
dec:package declarationfile,定义了不同模块的GUID信息
dsc:description file,主要包含需要用到的所有inf文件
inf:单个模块的编译信息,类似makefile
efi :最终编译生成的UEFI可执行文件
高通平台的UEFI设计
高通在MSM8998上引入了UEFI,用来代替LK(Little Kernel)。
而高通UEFI由XBL和ABL两部分组成。
在老版本中,LK的设备驱动都放在了XBL核心,Linux加载启动及fastboot等功能组件则作为独立的UEFI应用存在。
XBL
XBL负责芯片驱动及充电等核心应用功能。
XBL核心是none-HLOS boot_image
代码的一部分,属于高通私有代码。
// todo
UEFI代码中大量使用了protocol概念,这个protocol其实指的是驱动,包含了驱动函数指针和数据。以rampatition为例:
boot_images/QcomPkg/Include/Protocol/EFIRamPartition.h中声明了了rampatition protocol:
ABL
ABL包括芯片无关的应用如fastboot
。ABL则在开源Linux Android代码树里。
ABL的编译非常简单,依次执行命令:
source build/envsetup.sh
lunch 32
make aboot
不同的厂商对UEFI有不同的实现,一种比较常用的开源实现是EDK2;EDK2是一个遵循UEFI标准和PI标准的跨平台固件开发环境,EDK2支持多种操作系统, 也支持跨平台编译。
确切来讲,高通所使用的edk2即为ABL部分的代码。
高通UEFI有关源码
对于高通平台启动过程依次为:PBL
->XBL
->ABL
。
一般用户定制化主要集中在ABL中,这部分代码树如下:
这部分里面主要是作为linux-loader 用来加载linux,以及fastboot。
用户修改主要集中在这两个部分,入口函数LinuxLoaderEntry。
${Andrioid源码树}/bootable/bootloader/edk2/QcomModulePkg
├── Application
│ └── LinuxLoader
│ ├── LinuxLoader.c
│ └── LinuxLoader.inf
├── Include
│ ├── Library
│ │ ├──BoardCustom.h
│ │ ├── Board.h
│ │ ├──BootImage.h
│ │ ├──BootLinux.h
│ │ ├──BootStats.h
│ │ ├──Decompress.h
│ │ ├──DeviceInfo.h
│ │ ├── DrawUI.h
│ │ ├──FastbootMenu.h
│ │ ├── Fonts.h
│ │ ├── KeyPad.h
│ │ ├──LinuxLoaderLib.h
│ │ ├── list.h
│ │ ├──LocateDeviceTree.h
│ │ ├──MenuKeysDetection.h
│ │ ├──PartitionTableUpdate.h
│ │ ├── Recovery.h
│ │ ├── Reg.h
│ │ ├──ShutdownServices.h
│ │ ├──StackCanary.h
│ │ ├──UnlockMenu.h
│ │ ├──UpdateCmdLine.h
│ │ ├──UpdateDeviceTree.h
│ │ └──VerifiedBootMenu.h
│ └── Protocol
│ ├── EFICardInfo.h
│ ├── EFIChargerEx.h
│ ├── EFIChipInfo.h
│ ├── EFIChipInfoTypes.h
│ ├── EFIEraseBlock.h
│ ├── EFILimits.h
│ ├── EFIMdtp.h
│ ├── EFIPlatformInfo.h
│ ├── EFIPlatformInfoTypes.h
│ ├── EFIPmicPon.h
│ ├── EFIPmicVersion.h
│ ├── EFIQseecom.h
│ ├── EFIRamPartition.h
│ ├── EFIResetReason.h
│ ├── EFIRng.h
│ ├── EFIScmModeSwitch.h
│ ├── EFIUsbDevice.h
│ ├── EFIUsbEx.h
│ ├── EFIVerifiedBoot.h
│ └── UsbEx.h
├── Library
│ ├── BootLib
│ │ ├── Board.c
│ │ ├──BootLib.inf
│ │ ├──BootLinux.c
│ │ ├──BootStats.c
│ │ ├──Decompress.c
│ │ ├──DeviceInfo.c
│ │ ├── DrawUI.c
│ │ ├──FastbootMenu.c
│ │ ├── KeyPad.c
│ │ ├──LinuxLoaderLib.c
│ │ ├──LocateDeviceTree.c
│ │ ├──MenuKeysDetection.c
│ │ ├──PartitionTableUpdate.c
│ │ ├── Recovery.c
│ │ ├──ShutdownServices.c
│ │ ├──UnlockMenu.c
│ │ ├──UpdateCmdLine.c
│ │ ├──UpdateDeviceTree.c
│ │ └──VerifiedBootMenu.c
│ ├── FastbootLib
│ │ ├──FastbootCmds.c
│ │ ├──FastbootCmds.h
│ │ ├──FastbootLib.inf
│ │ ├──FastbootMain.c
│ │ ├──FastbootMain.h
│ │ ├──MetaFormat.h
│ │ ├──SparseFormat.h
│ │ ├──UsbDescriptors.c
│ │ └──UsbDescriptors.h
│ ├── StackCanary
│ │ ├──StackCanary.c
│ │ └──StackCanary.inf
│ └── zlib
│ ├── adler32.c
│ ├── inffast.c
│ ├── inffast.h
│ ├── inffixed.h
│ ├── inflate.c
│ ├── inflate.h
│ ├── inftrees.c
│ ├── inftrees.h
│ ├── zconf.h
│ ├── zlib.h
│ ├── zlib.inf
│ ├── zutil.c
│ └── zutil.h
├──QcomModulePkg.dec
├──QcomModulePkg.dsc
├──QcomModulePkg.fdf
└── Tools
├── app_path_set.cmm
├── check_paths.cmm
├── debug_app.cmm
├── elf_tools.py
├── image_header.py
├── load_uefi_dump.cmm
├── log_save.cmm
├── symbol_Load.cmm
└── uefi_core_path_set.cmm
附录:为什么android 默认bootloader选择lk?
reference:https://blog.csdn.net/leo_wdls/article/details/45173643
结论:用于移动通信的android设备(如手机平板):软件小巧,架构简单,满足android bootloader的基本需求。
lk源码目录位置:
bootable/bootloader/lk
Android bootloader需求:
-
加载引导
linux kernel
-
需要驱动
Display
、Usb
、Keypad
、Pmic
、Vibrator
Uboot 的特点:
-
加载引导linux kernel
-
发展早,软件成熟稳定,功能完备;
-
支持的多个CPU 体系
-
支持复杂驱动,如Fs/Network等等;
Little Kernel特点:
-
加载引导linux kernel
-
轻量级、不支持复杂的驱动