【SA8295P 源码分析】06 - SA8295P XBL Loader 阶段 sbl1_main_ctl 函数代码分析
- 一、XBL Loader 汇编源码分析
- 1.1 解析 boot\QcomPkg\XBLLoader\XBLLoader.inf
- 1.2 boot\QcomPkg\XBLDevPrg\ModuleEntryPoint.S:跳转 sbl1_entry 函数
- 1.3 XBLLoaderLib\sbl1_Aarch64.s:跳转 sbl1_main_ctl 函数
- 二、XBL Loader C代码分析
- 2.1 XBLLoaderLib\sbl1_mc.c:入口函数 sbl1_main_ctl(), SBL1(XBL Loader环境初始化)
- 2.2 SBL1(XBL Loader)解析 sbl1_config_table:加载并验证 SMSS、XBL Config、shrm、apdp、sblramdump(dload)、aop、QSEE Devcfg、QSEE、secdata、QHEE, 最终返回sbl 后跳转 QSEE,启动 TrustZone
系列文章汇总见:《【SA8295P 源码分析】00 - 系列文章链接汇总》
本文链接:《【SA8295P 源码分析】06 - SA8295P XBL Loader 阶段 sbl1_main_ctl() 函数代码分析》
在前文《【SA8295P 源码分析】05 - SA8295P QNX Host 上电开机过程 进一步梳理(结合代码)》中,
我们从把 SA8295P 上电启动流程从头到尾的梳理了一遍,整体流程已经很清楚了,包括每个流程所对应的代码在哪,我们也都清楚了。
万事俱备,从本文开始,我们就深入代码,一点一点地分析下,SA8295P芯片,从上电开始的每个步骤的代码实现。
在前文中,我们知道 XBL Loader
是由APPS PBL
加载起来的,的源码位置如下:
源代码位于:sa8295p-hqx-4-2-4-0_amss_standard_oem.git\boot\boot_images\boot\QcomPkg\XBLLoader
汇编代码位于:sa8295p-hqx-4-2-4-0_amss_standard_oem.git\boot\boot_images\boot\QcomPkg\XBLLoader\ModuleEntryPoint.S
入口汇编位于:sa8295p-hqx-4-2-4-0_amss_standard_oem.git\boot\boot_images\boot\QcomPkg\SocPkg\Library\XBLLoaderLib\sbl1_Aarch64.s
入口函数为:BL sbl1_main_ctl
好,话不多说,我们开始分析代码吧:
一、XBL Loader 汇编源码分析
1.1 解析 boot\QcomPkg\XBLLoader\XBLLoader.inf
从 XBLLoader.inf
中可以看出,XBLDevPrg
的汇编代码为 ModuleEntryPoint.S
,
它是运行在 FEATURE_START_EL3
安全环境下。
# sa8295p-hqx-4-2-4-0_amss.git\boot\boot_images\boot\QcomPkg\XBLLoader\XBLLoader.inf
[Defines]INF_VERSION = 0x00010005BASE_NAME = XBLLoaderFILE_GUID = BD4CC3FB-4872-DDC9-2CE9-AF999D7B9264MODULE_TYPE = USER_DEFINEDVERSION_STRING = 1.0[Sources.common]boot_gpt_partition_id.c[Sources.AARCH64]ModuleEntryPoint.S[BuildOptions.AARCH64]#GCC:*_*_*_CC_FLAGS = -O0 -fno-inline#GCC:*_*_*_PP_FLAGS = -DFEATURE_START_EL3 // 定义GCC 编译宏控 FEATURE_START_EL3
1.2 boot\QcomPkg\XBLDevPrg\ModuleEntryPoint.S:跳转 sbl1_entry 函数
ModuleEntryPoint.S
的主要工作如下:
- 获取当前的运行环境,保存在
x4
寄存器中,CurrentEL : 0xC=EL3; 0x8=EL2; 0x4=EL1
- 第一个传参
X0
是APPS_PBL
传入的共享数据地址,将x0
的值保存到X19
寄存器中 - 禁止所有中断,对应的指令为
asm
{msr daifset, #DAIF_WR_INT_BITS
(禁止中断) ;isb
(清除指令流水线) } - 关闭所有的
Caches
和MMU
- 关闭 指令缓存 功能
- 关闭
TLB
页缓存 功能 - 恢复
x9
的值 (APPS_PBL
传入的共享数据地址) 到x0
中,作为第一个传参,传入sbl1_entry
中 - 跳转到
sbl1_entry
函数,传参为x0
(APPS_PBL
传入的共享数据地址pbl_shared_data_pointer
)
# sa8295p-hqx-4-2-4-0_amss.git\boot\boot_images\boot\QcomPkg\XBLLoader\ModuleEntryPoint.S.global pbl_shared_data_pointer
pbl_shared_data_pointer:.quad 0x14810270_ModuleEntryPoint:
#ifdef FEATURE_START_EL3// 1. 获取当前的运行环境,保存在 x4 寄存器中, CurrentEL : 0xC=EL3; 0x8=EL2; 0x4=EL1EL1_OR_EL2_OR_EL3(x4)
1:// 2. 第一个传参X0 是 APPS_PBL 传入的共享数据地址,将经x0的值保存到X19 寄存器中
BootBackupX0: mov x19, x0// 3. 禁止所有中断,对应的指令为 asm{ msr daifset, #DAIF_WR_INT_BITS(禁止中断) ; isb(清除指令流水线) }
BootDisableInterrupts:bl ASM_PFX(ArmDisableInterrupts) // 4. 关闭所有的Caches 和 MMU
BootDisableCacheMmu:bl ASM_PFX(ArmDisableCachesAndMmu)// 5. 关闭 指令缓存功能
BootInvalInstructionCache: bl ASM_PFX(ArmInvalidateInstructionCache)// 6. 关闭 TLB 页缓存
BootInvalidateTlb:bl ASM_PFX(ArmInvalidateTlb)// 7. 恢复x9的值 (APPS_PBL 传入的共享数据地址) 到x0 中,作为第一个传参,传入sbl1_entry 中
BootRestoreX0: mov x0, x19
#endif// 8. 跳转到 sbl1_entry 函数,传参为 x0 (APPS_PBL传入的共享数据地址 pbl_shared_data_pointer)
BootBranchLoaderEntry: b sbl1_entry
1.3 XBLLoaderLib\sbl1_Aarch64.s:跳转 sbl1_main_ctl 函数
sbl1_Aarch64.s
主要工作:
- 将
x0
传参保存到x7
寄存器中,它是APPS_PBL
传入的共享数据地址pbl_shared_data_pointer
- 将 栈指针寄存器
sp
配置为0
- 禁止
Cache
、MMU
和exception
异常处理功能,关闭TLB
页缓存,禁止CPU
的指令和数据cache
功能 - 将
SCTLR_EL1
寄存器的MMU
位(0x1
)、Cache
位(0x4
)、Stack Alignment Check
位(0x8
)清零 - 配置异常向量表:将
sbl1_vector_table
异常向量表的地址 保存在X0
寄存器中,然后写入VBAR_EL1
异常向量表寄存器中 - 设置
FPEN
bit20
和bit 21
,不捕获FP
和高级SIMD
指令 - 读取中断状态寄存器
ISR_EL1
的值到X0
中,通过ISR_EL1_A_BIT
位来检查是否有pending
的异常,如果有则进入死循环 - 开启外部中止功能:在指令获取失败(指令中止)或数据访问失败(数据中止)时会生成中止
- 配置
Stack
栈地址,SBL
的栈大小默认为12kb
, 定义在\boot\boot_images\boot\QcomPkg\SocPkg\Library\DevPrgDLib\sbl1.ld
中 - 使能 指令
Cache
缓存功能 - 设置
PXN
的SPAN
位,SPAN
位用于设置EL1
或EL2
的异常 - 初始化栈内存、配置栈为
16
字节对齐 - 将
x7
寄存器的值 保存到X0
中,将它以参数传递入sbl1_main_ctl
中,它是APPS_PBL
传入的共享数据地址pbl_shared_data_pointer
# sa8295p-hqx-4-2-4-0_amss.git\boot\boot_images\boot\QcomPkg\SocPkg\Library\XBLLoaderLib\sbl1_Aarch64.s
.global sbl1_entry
sbl1_entry:// 1. 将 x0传参保存到 x7寄存器中,它是APPS_PBL传入的共享数据地址 pbl_shared_data_pointerMOV x7, x0// 2. 将 栈指针寄存器 配置为0, sp = 0MOV X0, #0MOV SP, X0// 3. 禁止 Cache、MMU 和 exception异常处理功能,关闭 TLB 页缓存,禁止CPU的指令和数据cache功能DSB SY // 清除CPU数据流水线ISB SY // 清除CPU指令流水线TLBI VMALLE1 // TLB invalidateIC IALLU // Invalidate cache to PoUDSB SY // 清除CPU数据流水线ISB SY // 清除CPU指令流水线// 4. 将 SCTLR_EL1 寄存器的 MMU 位(0x1)、Cache位(0x4)、Stack Alignment Check位(0x8)清零MRS X0, SCTLR_EL1 // 读取EL1状态的系统控制寄存器 的值到X0中AND X0,X0, #~(M_BIT) // 将 MMU 位清零, 禁止MMU, X0 = X0 & (~0x1) #define M_BIT 0x1 /* MMU Enable */AND X0,X0, #~(C_BIT) // 将 Cache 位清零, 禁止Cache, X0 = X0 & (~0x1) #define C_BIT 0x4 /* Cache */// ORR X0,X0, #(A_BIT) //TODO: Enable after CPR fixes alignment faultORR X0,X0, #(SA_BIT) // 禁止栈对检测 #define SA_BIT 0x8 /* Stack Alignment Check */MSR SCTLR_EL1, X0 // 将 X0 写回 SCTLR_EL1寄存器中DSB SY // 清除CPU数据流水线ISB SY // 清除CPU指令流水线// 5. 配置异常向量表:将 sbl1_vector_table 异常向量表的地址 保存在 X0 寄存器中,然后写入 VBAR_EL1 异常向量表寄存器中LDR x0, =sbl1_vector_table MSR VBAR_EL1, x0// 6. 设置FPEN bit20 和 bit 21 ,不捕获 FP和高级SIMD指令// SET FPEN BITS 20 AND 21 FOR NOT TRAPPING FP AND ADVANCED SIMD INSTRUCTIONSMRS X0, CPACR_EL1ORR X0, X0, #0X300000 MSR CPACR_EL1, X0ISB SY // 清除CPU指令流水线// 7. 读取中断状态寄存器ISR_EL1的值到 X0中,通过 ISR_EL1_A_BIT 位来检查是否有pending的异常,如果有则进入死循环MRS X0, ISR_EL1AND X0, X0, #ISR_EL1_A_BITCBNZ X0, boot_loop_here// 8. 开启外部中止功能:在指令获取失败(指令中止)或数据访问失败(数据中止)时会生成中止// Enable external aborts// msr daifset, #1 //关闭FIQ msr daifclr, #1 //开启FIQ// msr daifset, #2 //关闭IRQ msr daifclr, #2 //开启IRQ// msr daifset, #4 //关闭Async msr daifclr, #4 //开启Async// msr daifset, #8 //关闭Dbg msr daifclr, #8 //开启DbgMSR DAIFClr, #INT_A_BITisb// 9. 配置Stack 栈地址,SBL的栈大小默认为12kb, 定义在 \boot\boot_images\boot\QcomPkg\SocPkg\Library\DevPrgDLib\sbl1.ld 中LDR x0, = Image$$SBL1_STACK_BASE$$PointerMOV SP, x0// 10. 使能 指令Cache 缓存功能// Enable instruction cacheMRS X0, SCTLR_EL1ORR X0,X0, #I_BIT// 11. 设置PXN的SPAN位,用于设置EL1或EL2的异常 SET SPAN bit for PXNSET SPAN bit for PXNORR X0,X0, #CTRL_SPAN_BITMSR SCTLR_EL1, X0// 12. 初始化栈内存、配置栈为16字节对齐LDR x0, = Image$$SBL1_STACK$$BaseLDR x1, = Image$$SBL1_STACK$$LengthBIC x1, x1, #0xF MOV x2, #0 // used as counterwrite_16bytes_loop:stp xzr,xzr,[x0], #0x10 // 将 xzr=xzr, [0]=0x10 往栈底写入#0x10 add x2, x2, #0x10 // x2 += 0x10, increment by 16 bytescmp x1, x2 // 判断 x1 == x2 ?b.ne write_16bytes_loop sbl1_entry_init_stack: // 13. 将 x7寄存器的值 保存到 X0中,将它以参数传递入sbl1_main_ctl中,它是APPS_PBL传入的共享数据地址 pbl_shared_data_pointerMOV w0, w7 // mov x0, x7BL sbl1_main_ctl// For safetyBL boot_loop_here // never returns
汇总下,在汇编代码中,主要做了四件事,如下:
- 禁止
CPU
的中断、Cache
、MMU
、TLB
功能 - 初始化中断向量表
VBAR_EL1 = &sbl1_vector_table
- 开启外部中止功能:在指令获取失败(指令中止)或数据访问失败(数据中止)时会生成中止
- 初始化栈
- 跳转进入
C
函数sbl1_main_ctl()
二、XBL Loader C代码分析
2.1 XBLLoaderLib\sbl1_mc.c:入口函数 sbl1_main_ctl(), SBL1(XBL Loader环境初始化)
sbl1_main_ctl()
主要工作如下:
- 记录
sbl1
开始运行的时间,保存在sbl_start_time
中 - 初始化
DAL
层(Device Abstraction Layer
)的 堆head
内存,大小为207kb
(0x33C00
) - 初始化
DAL
层(Device Abstraction Layer
,位于硬件与应用层之间,DAL API
定义在DDI
文件中,应用层调用DDI
接口使用驱动提供的服务) - 初始化
boot_config_context
保存在config_context_handle
中,memory_mgr_dal=config_context_handle->mem_if
- 配置
ConfigContext
参数,将Context ID
和Context interface
接口 绑定在一起 - 获取
CONFIG_CONTEXT_CLK_INTERFACE
对应的clk
接口指针 保存在clk_if
中 - 调用
clk_if->Clock_DebugInit()
函数初始化clock
,QREF,PLL
,LPASS
等 - 初始化栈溢出保护 (
SSP
) 功能机制的参数__stack_chk_guard
为一个随机数
主要作用是,在调用子函数时,将__stack_chk_guard
的值存入栈顶,然后在函数返回之前取出栈顶的值,
与__stack_chk_guard
比较,如果一致则说明栈数据没有被破坏,继续返回运行母函数
如果比较不一致,说明出现了栈溢出,则直接调用__stack_chk_fail()
函数宕机 - 获取
CONFIG_CONTEXT_MEMORY_MGR_INTERFACE
对应的mem
接口指针 保存在mem_if
中 - 将
pbl_shared
的数据保存在sbl1_pbl_shared_data
中,处理pbl传入的数据后保存在sbl_verified_info
中 - 在
pbl_shared->pbl_flash_shared_data
中保存了启动设备的boot_device
信息,将其保存在ConfigContext的CONFIG_CONTEXT_BOOT_DEVICE
处 - 调用
mem_if->malloc
申请media_if
的内存,用于保存media_interface_if
的接口 - 将
media_interface_if
的接口地址保存在config_context
的CONFIG_CONTEXT_BOOT_MEDIA_INTERFACE
中 - 初始化
SBL memory map
内存表 - 获取
CONFIG_CONTEXT_BUSYWAIT_INTERFACE
对应的busywait
接口指针 保存在busywait_if
中 - 初始化
busywait
模块, 获取HWIO QTimer
的地址 和QTimerfreq
,后面uart
串口需要用到 - 初始化共享
imem
boot_shared_imem
- 读取
SMEM
缓冲区数据进行初始化XBL_Core
chip info driver
芯片信息驱动程序,它是在XBL Loader
阶段PlatformInfo
填充的,如chip id
,chip serial
等 - 获取
CONFIG_CONTEXT_BOOT_STATS_INTERFACE
对应的boot_stats
接口指针 保存在boot_stats_if
中,初始化boot_statistics_obj
结构体中的time
统计信息 - 初始化
boot logger
, 将boot logger
与logger_uart_if
绑定在一起,这样log
就可以通过uart
口打印出来 - 打印串口
log
及boot
的相关属性,如下:
第一句log
:Format: Log Type - Time(microsec) - Message - Optional Info
第二句log
:Log Type: B - Since Boot(Power On Reset), D - Delta, S - Statistic
镜像版本号:QC_IMAGE_VERSION_STRING=BOOT.MXF.1.1-00539-MAKENA-1
启动设备类型:Boot Interface: UFS
secure boot
状态:Secure Boot: Off
- 如果配置了
debug cookie
, 则会停留在此处等待JTag
调试器的接入 - 获取
CONFIG_CONTEXT_DDR_INFO_INTERFACE
对应的ddr
接口指针 保存在di_if
中, 然后初始化DDR
,
主要是申请了boot_ddr_info
类型的内存,指针保存在ddr_info_ptr->mem_if
和di_ptr->mem_if
中 - 初始化
QSEE
接口,为后续SBL1
跳转到QSEE
做准备 - 初始化
Temperature Sensor
温度传感器,通过Tsens_Init()
配置使能PMIC
的PS_HOLD reset
功能,这样我们就可以通过PS_HOLD
来做warm reset
初始化QUSB2
,配置High Speed QUSB2 PHY
到无驱动模式,为dload
下载做准备 SBL1 (XBL Loader)
阶段即将结束,解析sbl1_config_table
,加载SMSS
、XBL Config
、shrm
、apdp
、sblramdump
(dload
)、aop
、QSEE Devcfg
、QSEE
、secdata
、QHEE
, 最终返回sbl
后跳转QSEE
,启动TrustZone
源码及注释分析如下:
# sa8295p-hqx-4-2-4-0_amss.git\boot\boot_images\boot\QcomPkg\SocPkg\Library\XBLLoaderLib\sbl1_mc.c
void sbl1_main_ctl(boot_pbl_shared_data_type *pbl_shared)
{do{// 1. 记录 sbl1 开始运行的时间,保存在sbl_start_time 中sbl_start_time = CALCULATE_TIMESTAMP(HWIO_IN(TIMETICK_CLK));// 2. 初始化 DAL层(Device Abstraction Layer)的 堆head内存,大小为207kb (0x33C00)dal_result = dal_if.HeapInit(boot_internal_heap, BOOT_INTERNAL_HEAP_SIZE, FALSE);================>+ // dal_if 定义在 boot\boot_images\boot\QcomPkg\XBLLoader\ExtDrivers\boot_dal.c中+ boot_dal_if_type dal_if = {+ DALSYS_InitMod,+ DALSYS_DeInitMod,+ ......+ DALSYS_HeapInit,+ DALSYS_HeapDeInit,+ ......+ };<================// 3. 初始化 DAL 层(Device Abstraction Layer,位于硬件与应用层之间,DAL API定义在DDI文件中,应用层调用DDI接口使用驱动提供的服务)// 待研究 SBL DAL Device 驱动dal_if.InitMod(NULL);// 4. 初始化 boot_config_context 保存在 config_context_handle中, memory_mgr_dal=config_context_handle->mem_ifstatus = boot_config_context_open(&config_context_handle, &memory_mgr_dal);================>+ // 初始化 ConfigContext支持的参数, 保存在config_context->entries[] 数组中+ // boot\boot_images\boot\QcomPkg\LoaderFramework\ConfigContext\boot_config_context.c+ do{+ memset((uint8 *)config_context, 0, sizeof(config_context_type));+ + config_context->handle_data.id = CONFIG_CONTEXT_ID;+ config_context->handle_data.config_context_handle = NULL;+ + for(int i = 0; i < CONFIG_CONTEXT_NO_PARAMS; i++){+ config_context->entries[i].set = NOT_SET;+ config_context->entries[i].ptr.allocated = FALSE;+ }+ }+ while(FALSE);+ + // 定义在 boot\boot_images\boot\QcomPkg\Include\api\boot\boot_config_context.h中+ typedef enum{+ CONFIG_CONTEXT_PRE_PROCS = 0, //_populate_config_context_per_image+ ......+ CONFIG_CONTEXT_TIMER_INTERFACE //config_context_global_values+ CONFIG_CONTEXT_MEMORY_MGR_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_BAM_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_BUS_INTERFACE, //config_context_global_values+ ......+ CONFIG_CONTEXT_DAL_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_QSEE_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_SEC_IMG_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_BOOT_STATS_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_TLMM_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_TSENSOR_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_UART_INTERFACE, //config_context_global_values+ CONFIG_CONTEXT_PARTITION_ID, //_populate_config_context_per_image+ CONFIG_CONTEXT_LOAD_FLAG, //_populate_config_context_per_image+ CONFIG_CONTEXT_EXEC_FLAG, //_populate_config_context_per_image+ CONFIG_CONTEXT_JUMP_FLAG, //_populate_config_context_per_image+ CONFIG_CONTEXT_XBLCFG_PARTITION_ID,+ ......+ CONFIG_CONTEXT_NO_PARAMS+ } boot_config_context_param_type;<================// 5. 配置 ConfigContext 参数,将 Context ID 和 Context interface接口 绑定在一起status = boot_config_context_set_parameters(config_context_handle, config_context_global_values, sizeof(config_context_global_values)/sizeof(boot_config_context_populate_table));================>+ // sa8295p-hqx-4-2-4-0_amss.git\boot\boot_images\boot\QcomPkg\SocPkg\Library\XBLLoaderLib\sbl1_mc.c+ boot_config_context_populate_table config_context_global_values[] =+ {+ ......+ {CONFIG_CONTEXT_MEMORY_MGR_INTERFACE, PARAMETER_TYPE_PTR, {}, {&memory_mgr_dal, 0, NULL}, },+ {CONFIG_CONTEXT_BUS_INTERFACE, PARAMETER_TYPE_PTR, {}, {&boot_bus, 0, NULL}, },+ {CONFIG_CONTEXT_RESET_INTERFACE, PARAMETER_TYPE_PTR, {}, {&reset_if, 0, NULL}, },+ {CONFIG_CONTEXT_CLK_INTERFACE, PARAMETER_TYPE_PTR, {}, {&clk_if, 0, NULL}, },+ {CONFIG_CONTEXT_DAL_INTERFACE, PARAMETER_TYPE_PTR, {}, {&dal_if, 0, NULL}, },+ {CONFIG_CONTEXT_DDI_INTERFACE, PARAMETER_TYPE_PTR, {}, {&ddi_if, 0, NULL}, },+ {CONFIG_CONTEXT_DDR_INFO_INTERFACE, PARAMETER_TYPE_PTR, {}, {&ddr_info_if, 0, NULL}, },+ {CONFIG_CONTEXT_DDR_INTERFACE, PARAMETER_TYPE_PTR, {}, {&ddr_if, 0, NULL}, },+ {CONFIG_CONTEXT_EFS_INTERFACE, PARAMETER_TYPE_PTR, {}, {&efs_if, 0, NULL}, },+ {CONFIG_CONTEXT_PIMEM_INTERFACE, PARAMETER_TYPE_PTR, {}, {&pimem_if, 0, NULL}, },+ {CONFIG_CONTEXT_PLATFORMINFO_INTERFACE, PARAMETER_TYPE_PTR, {}, {&platforminfo_if, 0, NULL}, },+ {CONFIG_CONTEXT_PMIC_INTERFACE, PARAMETER_TYPE_PTR, {}, {&pmic_if, 0, NULL}, },+ {CONFIG_CONTEXT_POWER_INTERFACE, PARAMETER_TYPE_PTR, {}, {&power_if, 0, NULL}, },+ {CONFIG_CONTEXT_QSEE_INTERFACE, PARAMETER_TYPE_PTR, {}, {&qsee_if, 0, NULL}, },+ {CONFIG_CONTEXT_QUSB_LDR_INTERFACE, PARAMETER_TYPE_PTR, {}, {&qusb_ldr_if, 0, NULL}, },+ {CONFIG_CONTEXT_BOOT_STATS_INTERFACE, PARAMETER_TYPE_PTR, {}, {&boot_statistics_if, 0, NULL}, },+ {CONFIG_CONTEXT_SECCFG_INTERFACE, PARAMETER_TYPE_PTR, {}, {&seccfg_if, 0, NULL}, },+ {CONFIG_CONTEXT_SECLIB_INTERFACE, PARAMETER_TYPE_PTR, {}, {&seclib_if, 0, NULL}, },+ {CONFIG_CONTEXT_SMEM_INTERFACE, PARAMETER_TYPE_PTR, {}, {&smem_if, 0, NULL}, },+ {CONFIG_CONTEXT_TLMM_INTERFACE, PARAMETER_TYPE_PTR, {}, {&tlmm_if, 0, NULL}, },+ {CONFIG_CONTEXT_TSENSOR_INTERFACE, PARAMETER_TYPE_PTR, {}, {&tsensor_if, 0, NULL}, },+ {CONFIG_CONTEXT_UART_INTERFACE, PARAMETER_TYPE_PTR, {}, {&uart_if, 0, NULL}, },+ {CONFIG_CONTEXT_VSENSE_INTERFACE, PARAMETER_TYPE_PTR, {}, {&vsense_if, 0, NULL}, },+ {CONFIG_CONTEXT_CONFIG_DATA_INTERFACE, PARAMETER_TYPE_PTR, {}, {&cdt_if, 0, NULL}, },+ {CONFIG_CONTEXT_TIMER_HW_INTERFACE, PARAMETER_TYPE_PTR, {}, {&timer_hw_if, 0, NULL}, },+ {CONFIG_CONTEXT_VSENSE_INTERFACE, PARAMETER_TYPE_PTR, {}, {&vsense_if, 0, NULL}, },+ {CONFIG_CONTEXT_EDK2_CACHE_INTERFACE, PARAMETER_TYPE_PTR, {}, {&edk2_cache_if, 0, NULL}, },+ {CONFIG_CONTEXT_EDK2_MMU_INTERFACE, PARAMETER_TYPE_PTR, {}, {&edk2_mmu_if, 0, NULL}, },+ ......+ {CONFIG_CONTEXT_SAHARA_STATUS_MAP_INTERFACE, PARAMETER_TYPE_PTR, {}, {&sahara_status_map_if, 0, NULL}, },+ };<================// 6. 获取CONFIG_CONTEXT_CLK_INTERFACE 对应的 clk接口指针 保存在clk_if中status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_CLK_INTERFACE, (void **)&clk_if);// 7. 调用 clk_if->Clock_DebugInit() 函数初始化clock,QREF,PLL,LPASS等 // 定义在boot\boot_images\boot\QcomPkg\XBLLoader\ExtDrivers\boot_clk.c中ret = clk_if->debug_init();// 8. 初始化栈溢出保护(SSP)功能机制的参数__stack_chk_guard为一个随机数// 主要作用是,在调用子函数时,将__stack_chk_guard的值存入栈顶,然后在函数返回之前取出栈顶的值,// 与__stack_chk_guard比较,如果一致则说明栈数据没有被破坏,继续返回运行母函数// 如果比较不一致,说明出现了栈溢出,则直接调用__stack_chk_fail()函数宕机boot_init_stack_chk_canary();// 9. 获取CONFIG_CONTEXT_MEMORY_MGR_INTERFACE 对应的 mem接口指针 保存在mem_if中status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_MEMORY_MGR_INTERFACE, (void **)&mem_if);// 10. 将pbl_shared的数据保存在sbl1_pbl_shared_data中,处理pbl传入的数据后保存在sbl_verified_info中status = sbl1_retrieve_shared_info_from_pbl(pbl_shared);// PBL Shared 内容如下:====================> // boot\boot_images\boot\QcomPkg\SocPkg\Library\XBLLoaderLib\SM\pbl_sbl_shared.h+ typedef struct boot_pbl_shared_data_type{+ uint32 bl_sdata_version; /* 共享数据版本号 */+ uint32 pbl_version; /* PBL 版本号 */+ uint32 pbl_patch_version; /* PBL Patch 版本号 */+ uint32 boot_option_fuse_val; /* PBL Boot option configured in the fuse */+ uint32 bl_loader_auth_enabled; /* BL loader authentication state */+ uint32 deprecated_hash_integrity_check_disabled; /*Deprecated dummy entry for XBL-sec - temporary*/+ uint32 deprecated_bl_sec_boot_flow_supported; /*Deprecated dummy entry for XBL-sec - temporary*/+ uint32 bl_sec_auth_disabled; /* BL-Sec authentication state */+ uint8 *boot_stack_base; /* PBL 栈顶地址 */+ uint32 boot_stack_size; /* PBL 栈大小 */+ uint32 reserved_fields_bl[BL_RESERVED_LENGTH]; /* Reserved fields*/+ pbl_apps_timestamp_type * timestamps; /* Timestamps at main milestones in PBL */+ void* pbl_debug_shared_data; /* PBL shared data structure, maps to: pbl_sdata_type */+ void* deprecated_pbl_clock_shared_data; /*Deprecated dummy entry for XBL-sec - temporary*/+ void* pbl_elf_shared_data; /* Pointer to elf image shared data structure, maps to: pbl_elf_img_share_info_type */+ void* pbl_secboot_shared_data; /* Pointer to Secboot shared data structure, maps to: secboot_pbl_shared_info_type */+ void* pbl_pcie_shared_data; /* Pointer to PCIE shared shared data structure, maps to: pcie_bhi_shared_data_type*/+ void* pbl_flash_shared_data; /* Pointer to flash shared data structure, maps to: boot_flash_shared_dev_info_type */+ void* pbl_cache_mmu_share_data; /* Pointer to cache mmu shared data structure,maps to: pbl_cache_mmu_share_info_type */+ void* pbl_ecc_shared_data; /* Pointer to ECC shared data structure,maps to: crypto_ecc_shared_info_type */+ void* pbl_crypto_hash_cipher_shared_data; /* Pointer to cipher Hash shared data structure,maps to: crypto_hash_cipher_shared_info_type */+ } boot_pbl_shared_data_type;<====================// 11. 在pbl_shared->pbl_flash_shared_data中保存了启动设备的boot_device信息,将其保存在 ConfigContext的CONFIG_CONTEXT_BOOT_DEVICE处status = boot_config_context_set_value(config_context_handle, CONFIG_CONTEXT_BOOT_DEVICE, (uint32)((((boot_flash_shared_dev_info_type*)(pbl_shared->pbl_flash_shared_data))->type)));// pbl shared data 中的 boot_device 信息结构体如下:=====================>+ /* This defines Flash shared data */+ typedef struct // boot\boot_images\boot\QcomPkg\SocPkg\Library\XBLLoaderLib\SM\pbl_sbl_shared.h+ {+ uint32 shared_data_version;+ boot_media_type type; /* Type of flash */+ uint32 CS_base; /* Base address of chip select device is connected to.*/+ uint32 data_width; /* Bit width of device ie: 8bit/16bit */+ boot_flash_ctrl_type ctrl_type; /* Controller used to interface with device*/+ boolean is_recovery_partition;+ union+ {+ boot_flash_shared_nand_dev_type nand; /* Shared info for NAND device */+ boot_flash_shared_sdc_dev_type sdc; /* Shared info for SDC device */+ boot_flash_shared_spi_dev_type spi; /* Shared info for SPI device */+ struct boot_sahara_shared_data* sahara;/* Shared info pointer for Sahara flashless boot/eDL */+ }dev_info;+ }boot_flash_shared_dev_info_type;<=====================// 12. 调用mem_if->malloc 申请 media_if 的内存,用于保存 media_interface_if 的接口status = mem_if->malloc(sizeof(boot_media_interface_if_type), (void *)&media_if);status = boot_media_get_interface(config_context_handle, media_if);==========-========> // boot\boot_images\boot\QcomPkg\XBLLoader\BlockDev\boot_block_dev.c((boot_media_interface_if_type *)media_interface_if)->media_hw_init = boot_block_dev_hw_init;((boot_media_interface_if_type *)media_interface_if)->media_hw_deinit = NULL;((boot_media_interface_if_type *)media_interface_if)->open = boot_block_dev_open;((boot_media_interface_if_type *)media_interface_if)->close = boot_block_dev_close;((boot_media_interface_if_type *)media_interface_if)->read = boot_block_dev_read;((boot_media_interface_if_type *)media_interface_if)->write = boot_block_dev_write;((boot_media_interface_if_type *)media_interface_if)->async_read = NULL;((boot_media_interface_if_type *)media_interface_if)->async_read_poll = NULL;<====================// 13. 将media_interface_if 的接口地址保存在 config_context 的 CONFIG_CONTEXT_BOOT_MEDIA_INTERFACE中status = boot_config_context_set_ptr(config_context_handle, CONFIG_CONTEXT_BOOT_MEDIA_INTERFACE, (void *)(media_if));// 14. 初始化 SBL memory map内存表status = xbl_populate_initial_mem_map(config_context_handle);===================>+ ARM_MEMORY_REGION_DESCRIPTOR xbl_initial_memory_map[]=+ {+ // [1M - 3M] BASE=0x00100000 (1M), size=0x1f0000 (2M, 1.9375M)+ { GCC_CLK_CTL_REG_REG_BASE, GCC_CLK_CTL_REG_REG_BASE, GCC_CLK_CTL_REG_REG_BASE_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // [1M - 7.5M] BASE=0x00100000(1M), size=0x00680000 (6.5M)+ { REGISTER_REGION1_BASE, REGISTER_REGION1_BASE, REGISTER_REGION1_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // [7.5M - 7.5625M] BASE=0x00780000(7.5M), size=0x00010000(0.0625M)+ { SECURITY_CONTROL_BASE, SECURITY_CONTROL_BASE, QFPROM_READONLY_BLOCK_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE_RO },+ // [7.523M - 176.875M] BASE=0x00786000(7.523M), size=0x0A95A000 (169.35M) + { REGISTER_REGION2_BASE, REGISTER_REGION2_BASE, REGISTER_REGION2_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // [176.875M - 176.3063M] BASE=0x0B0E0000 (176.875M), size=0x8000 (32kb) 对应 AOP Data RAM region, MEMORY_REGION3+ { SCL_AOP_DATA_RAM_BASE, SCL_AOP_DATA_RAM_BASE, SCL_AOP_DATA_RAM_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XN },+ // [176.9M - 256M] BASE=0x0B0E8000 (176.9M), size=0x04F18000 (79.09375M) + { REGISTER_REGION3_BASE, REGISTER_REGION3_BASE, REGISTER_REGION3_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // [336M - 336.0156M] BASE=0x15000000 (336M), size=0x4000 (16kb) + { SYS_TCU_CFG_V2APPS_MMU500_SMMU_APP_BASE, SYS_TCU_CFG_V2APPS_MMU500_SMMU_APP_BASE, SYS_TCU_CFG_V2APPS_MMU500_SMMU_APP_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // [326.679M - 326.6914M] BASE=0x146AE000(326.679M), size= 0x00003000(12kb) + { SCL_SYSTEM_DEBUG_CO_RO_BASE, SCL_SYSTEM_DEBUG_CO_RO_BASE, SCL_SYSTEM_DEBUG_CO_RO_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_RO },+ // [326.746M - 326.75M] BASE=0x146BF000 (326.746M), size=0x00001000 (4kb) + { (uint64)SHARED_IMEM_BASE, (uint64)SHARED_IMEM_BASE, (uint64)SHARED_IMEM_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED_XN },+ // [328M - 329.5M] BASE=0x14800000 (328M), size=0x00180000 (1.5M) + { (uint64)SCL_BOOT_IMEM_BASE_ADDR, (uint64)SCL_BOOT_IMEM_BASE_ADDR, (uint64)SCL_BOOT_IMEM_START_XBL_UNUSED, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // SBL1 code 代码段起始地址 // boot\boot_images\boot\QcomPkg\SocPkg\Library\DevPrgDLib\sbl1.ld+ { (uint64)Image$$SBL1_CODE$$Base, (uint64)Image$$SBL1_CODE$$Base, (uint64)Image$$SBL1_CODE$$Length, ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_RO },+ // SBL1 data_ro 只读数据段起始地址 // boot\boot_images\boot\QcomPkg\SocPkg\Library\DevPrgDLib\sbl1.ld+ { (uint64)Image$$SBL1_DATA_RO$$Base, (uint64)Image$$SBL1_DATA_RO$$Base, (uint64)Image$$SBL1_DATA_RO$$Length, ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XN_RO },+ // SBL1 stack 栈段起始地址 // boot\boot_images\boot\QcomPkg\SocPkg\Library\DevPrgDLib\sbl1.ld+ { (uint64)Image$$SBL1_STACK$$Base, (uint64)Image$$SBL1_STACK$$Base, (uint64)Image$$SBL1_STACK$$Length, ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XN },+ // SBL1 data 数据段起始地址 // boot\boot_images\boot\QcomPkg\SocPkg\Library\DevPrgDLib\sbl1.ld+ { (uint64)Image$$SBL1_DATA_RW$$Base, (uint64)Image$$SBL1_DATA_RW$$Base, (uint64)Image$$SBL1_DATA_RW$$Length, ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XN },+ // SBL1 data_zi 数据段起始地址, 保存未初始化的可读写全局或静态变量+ { (uint64)Image$$SBL1_DATA_ZI$$Base, (uint64)Image$$SBL1_DATA_ZI$$Base, (uint64)Image$$SBL1_DATA_ZI$$Length, ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XN },+ // [376M - 389.5977M] BASE=0x17800000 (376M), size=0x00d99000 (13.5976M) + { APSS_HM_BASE, APSS_HM_BASE, APSS_HM_BASE_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // [2G - 16G] BASE=0x80000000 (2G), size=0x380000000 (14G) + { DDR_MEM_BASE_1, DDR_MEM_BASE_1, DDR_MEM_SIZE_1, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // [32G - 64G] BASE=0x800000000 (M), size=0x800000000 (32G) + { DDR_MEM_BASE_2, DDR_MEM_BASE_2, DDR_MEM_SIZE_2, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // [768M - 1G] BASE=0x30000000 (768M), size=0x10000000 (256M) + { PCIE_REGION_BASE, PCIE_REGION_BASE, PCIE_REGION_SIZE, ARM_MEMORY_REGION_ATTRIBUTE_DEVICE },+ // SBL1 SBL1_DEVPROG_UNCACHED_ZI segment段+ {(uint64)Image$$SBL1_DEVPROG_UNCACHED_ZI$$Base,(uint64)Image$$SBL1_DEVPROG_UNCACHED_ZI$$Base, (uint64)Image$$SBL1_DEVPROG_UNCACHED_ZI$$ZI$$Length, EFI_ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED_XN },+ // SBL1 data_zi 数据段末尾地址, 保存未初始化的可读写全局或静态变量+ {(uint64)Image$$SBL1_DATA_ZI$$End,(uint64)Image$$SBL1_DATA_ZI$$End,(( (uint64)(SCL_XBL_SEC_BASE_ADDR))-(uint64)(Image$$SBL1_DATA_ZI$$End)),ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK_XN}, + {0,0,0,0}+ };<==================// 15. 获取CONFIG_CONTEXT_BUSYWAIT_INTERFACE 对应的 busywait接口指针 保存在busywait_if中status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_BUSYWAIT_INTERFACE, (void **)&busywait_if);// 16. 初始化busywait模块, 获取HWIO QTimer的地址 和 QTimerfreq,后面uart 串口需要用到bsy_wait_init = busywait_if->init();// 17. 初始化共享imem boot_shared_imemboot_shared_imem_init();// 18. 读取SMEM缓冲区数据进行初始化XBL_Core chip info driver芯片信息驱动程序,它是在XBL Loader阶段PlatformInfo填充的,如chip id,chip serial等ChipInfo_Init();==================>+ // Read the chip information from SMem+ ChipInfoCtxt.nRawPartNum = pSMem->nRawChipId;+ ChipInfoCtxt.eChipInfoId = (ChipInfoIdType)pSMem->eChipId;+ ChipInfoCtxt.nRevNumber = pSMem->nRawChipVersion;+ ChipInfoCtxt.nVersion = pSMem->nChipVersion;+ ChipInfoCtxt.eFamilyId = (ChipInfoFamilyType)pSMem->nChipFamily;+ ChipInfoCtxt.nFamilyDeviceId = pSMem->nRawDeviceNumber;+ ChipInfoCtxt.nRawFamilyId = pSMem->nRawDeviceFamily;+ ChipInfoCtxt.eFoundryId = (ChipInfoFoundryIdType)pSMem->nFoundryId;+ ChipInfoCtxt.nSerialNum = pSMem->nChipSerial;+ ChipInfoCtxt.nQFPROMChipId = pSMem->nQFPROMChipId;+ ChipInfoCtxt.nModemSupported = pSMem->nModemSupported;+ ChipInfo_strcpy(ChipInfoCtxt.szChipIdString, pSMem->szChipIdStr, CHIPINFO_MAX_ID_LENGTH);++ // SMem 中的 chip info 结构体如下;+ // 定义在 sa8295p-hqx-4-2-4-0_amss.git\boot\boot_images\boot\QcomPkg\Include\PlatformInfoDefs.h+ typedef struct+ {+ uint32 nFormat; /**< Format of the structure. */+ uint32 eChipId; /**< Chip ID. */+ uint32 nChipVersion; /**< Chip version. */+ char aBuildId[DALPLATFORMINFO_SMEM_BUILD_ID_LENGTH];+ /**< Build ID. */+ uint32 nRawChipId; /**< Raw chip ID. */+ uint32 nRawChipVersion; /**< Raw chip version. */+ DalPlatformInfoPlatformType ePlatformType; /**< Platform type. */+ uint32 nPlatformVersion; /**< Platform version. */+ uint32 bFusion; /**< TRUE if Fusion; FALSE otherwise. */+ uint32 nPlatformSubtype; /**< Platform subtype. */+ DalPlatformInfoSMemPMICType aPMICInfo[DALPLATFORMINFO_SMEM_MAX_PMIC_DEVICES];+ /**< DEPRECATED. May not contain the full list. Use array at nPMICArrayOffset instead. */+ uint32 nFoundryId; /**< Chip foundry ID. */+ uint32 nChipSerial; /**< Chip serial number. */+ uint32 nNumPMICs; /**< Number of PMICs in array. */+ uint32 nPMICArrayOffset; /**< Offset from base of structure to array of DalPlatformInfoSMemPMICType. */+ uint32 nChipFamily; /**< Chip family. */+ uint32 nRawDeviceFamily; /**< Raw device family. */+ uint32 nRawDeviceNumber; /**< Raw device number. */+ + uint32 nQFPROMChipId; /**< QFPROM Chip ID */+ char szChipIdStr[DALPLATFORMINFO_SMEM_MAX_CHIP_ID_LENGTH]; /**< Chip name */+ uint32 nNumClusters; /**< Number of clusters for PartialGoods to consider */+ uint32 nClusterArrayOffset; /**< Offset from base of structure to uint32 array of defective CPU clusters. */+ uint32 nNumDefectiveParts; /**< Number of defective parts supported by the PartialGoods APIs */+ uint32 nDefectivePartsArrayOffset; /**< Offset from base of structure to uint32 array of defective parts */+ uint32 nModemSupported; /**< 0 if not supported, nonzero if supported */+ } DalPlatformInfoSMemType;<==================// 19. 获取CONFIG_CONTEXT_BOOT_STATS_INTERFACE 对应的 boot_stats接口指针 保存在boot_stats_if中, 初始化 boot_statistics_obj 结构体中的time 统计信息status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_BOOT_STATS_INTERFACE, (void **)&boot_stats_if);// 初始化 boot_statistics_obj 结构体中的time 统计信息status = boot_stats_if->init(); // boot_statistics_init()============>+ boot_statistics_obj.flash_timer_start_timetick = 0;+ boot_statistics_obj.flash_total_time_us = 0;+ boot_statistics_obj.flash_total_bytes_read = 0;+ boot_statistics_obj.flash_byte_counter = 0;<============// 20. 初始化 boot logger, 将 boot logger 与 logger_uart_if 绑定在一起,这样 log 就可以通过uart 口打印出来status = sbl1_boot_logger_init(config_context_handle, &boot_log_data, pbl_shared);=============>+ status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_LOGGER_INTERFACE, (void *)&logger_if);+ /*initialize boot logger*/+ logger_if->init(config_context_handle, boot_log_data);++ status = boot_logger_uart_get_interface(&logger_uart_if);+ status = logger_if->register_logger(logger_uart_if);<=============// 21. 打印串口log 及 boot 的相关属性,如下:// 第一句log: Format: Log Type - Time(microsec) - Message - Optional Info// 第二句log:Log Type: B - Since Boot(Power On Reset), D - Delta, S - Statistic// 镜像版本号:QC_IMAGE_VERSION_STRING=BOOT.MXF.1.1-00539-MAKENA-1// 启动设备类型:Boot Interface: UFS// secure boot 状态:Secure Boot: Offboot_log_early_info(&boot_log_data, sbl_start_time, pbl_shared);============>+ void boot_log_early_info(boot_log_init_data *boot_log_data, uint32 sbl_start_time, boot_pbl_shared_data_type *pbl_shared)+ {+ // 打印: Format: Log Type - Time(microsec) - Message - Optional Info+ boot_log_message_raw("\b\b\b\bFormat: Log Type - Time(microsec) - Message - Optional Info", BOOT_DND_TIMESTAMP, LOG_MSG_TYPE_STATISTIC, NULL);+ // 打印: Log Type: B - Since Boot(Power On Reset), D - Delta, S - Statistic+ boot_log_message_raw("\b\b\b\bLog Type: B - Since Boot(Power On Reset), D - Delta, S - Statistic", BOOT_DND_TIMESTAMP, LOG_MSG_TYPE_STATISTIC, NULL);+ // 打印: S - QC_IMAGE_VERSION_STRING=BOOT.MXF.1.1-00539-MAKENA-1+ // S - IMAGE_VARIANT_STRING=SocMakenaAU+ // S - OEM_IMAGE_VERSION_STRING=f556ff7556f9+ boot_log_image_version();+ // 打印: S - Boot Interface: UFS+ boot_log_boot_device_type();+ // 打印: S - Secure Boot: Off+ boot_log_secboot_status();+ // 打印: S - Boot Config @ 0x00786064 = 0x00000001+ // S - JTAG ID @ 0x00786130 = 0x1014b0e1+ // S - OEM ID @ 0x00786138 = 0x00000000+ // S - Serial Number @ 0x00786134 = 0x87bb3c39+ // S - OEM Config Row 0 @ 0x007841c8 = 0x0000000000000000+ // S - OEM Config Row 1 @ 0x007841d0 = 0x0000000000000001+ // S - Feature Config Row 0 @ 0x00784148 = 0x0000000000000000+ // S - Feature Config Row 1 @ 0x00784150 = 0x0000000000000000+ boot_log_raw_fuse_values();+ // 打印: S - Core 0 Frequency, 1440 MHz+ boot_log_apps_frequency(0);+ // 打印: S - PBL Patch Ver: 0+ boot_log_pbl_version();+ // 打印: "PBL freq: %d MHZ",+ boot_log_pbl_clk_freq();+ // 将 pbl 的时间戳 写在 log开头,+ // 打印log S - 102178 - PBL, End+ boot_pbl_log_milestones(pbl_shared);+ // 打印 B - 112331 - SBL1, Start+ boot_log_message_raw("SBL1, Start", sbl_start_time, LOG_MSG_TYPE_BOOT, NULL);+ // 打印SBL编译时间 B - 244518 - SBL1 BUILD @ 12:28:32 on Apr 20 2023+ boot_log_message("SBL1 BUILD @ " __TIME__ " on " __DATE__);+ }<============boot_log_set_meta_info(boot_log_data.meta_info_start); // 空函数// 22. 如果配置 debug cookie, 则会停留在此处等待 jtag 调试器的接入boot_debug_mode_check();// 23. 获取CONFIG_CONTEXT_DDR_INFO_INTERFACE对应的 ddr接口指针 保存在di_if中, 然后初始化DDR,// 主要是申请了 boot_ddr_info 类型的内存,指针保存在 ddr_info_ptr->mem_if 和 di_ptr->mem_if中 // sa8295p-hqx-4-2-4-0_amss.git\boot\boot_images\boot\QcomPkg\XBLLoader\ExtDrivers\boot_ddr_info.cstatus = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_DDR_INFO_INTERFACE, (void **)&di_if);status = di_if->init(config_context_handle);// 24. 初始化 QSEE 接口,为后续SBL1跳转到QSEE 做准备/* Initialize the QSEE interface */sbl1_init_sbl_qsee_interface(config_context_handle, &sbl_verified_info);// 25. 初始化 temperature sensor温度传感器,通过Tsens_Init() 配置使能PMIC 的 PS_HOLD reset功能,这样我们就可以通过PS_HOLD来做 warm reset // 初始化QUSB2,配置 High Speed QUSB2 PHY到无驱动模式,为dload下载做准备/* Call sbl1_hw_init to config pmic device so we can use PS_HOLD to reset */// 打印log: D - 256322 - sbl1_hw_initstatus = sbl1_hw_init(config_context_handle);=================> + return_status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_TSENSOR_INTERFACE, (void **)&tsensor_if);+ status = tsensor_if->Init();+ ----------->+ + TsensResultType Tsens_Init(void)+ + --------> // boot\boot_images\boot\QcomPkg\Library\TsensLib\TsensLoader.c+ + + static TsensResultType Tsens_ConfigureControllers(void)+ + + -----> //boot_images\boot\QcomPkg\SocPkg\Makena\Library\TsensTargetLib\HALtsens.c+ + + + // Enables / disables PS_HOLD reset functionality+ + + + void HAL_tsens_srot_SetPSHoldResetEn(uint8 *pucTsensSROTAddr, boolean bEnable)+ + + <-----+ + <---------+ <-------------<=================#ifdef FEATURE_DEVICEPROGRAMMER_IMAGE/* Check if we need to branch to device programmer */device_programmer_lite_check(config_context_handle);device_programmer_ddr_check(config_context_handle);
#endif// 26. SBL1 (XBL Loader)阶段即将结束,解析sbl1_config_table,加载并验证 SMSS、XBL Config、shrm、apdp、sblramdump(dload)、aop、QSEE Devcfg、QSEE、secdata、QHEE, 最终返回sbl 后跳转 QSEE,启动 TrustZonestatus = sbl1_config_process_bl(config_context_handle, sbl1_config_table);} while (FALSE);error_if.error_handler(__FILE_BASENAME__, __LINE__, status);} /* sbl1_main_ctl() */
2.2 SBL1(XBL Loader)解析 sbl1_config_table:加载并验证 SMSS、XBL Config、shrm、apdp、sblramdump(dload)、aop、QSEE Devcfg、QSEE、secdata、QHEE, 最终返回sbl 后跳转 QSEE,启动 TrustZone
考虑到文章篇幅,本文先写到这,后续的内容,请见下篇文章,谢谢!
解析sbl1_config_table
,并载并验证如下 target_img_partition_id
处的镜像,最终需要跳转到 qsee_jump_func()
,启动QSEE
smss_partition_id
XBLConfig_partition_id
shrm_partition_id
apdp_partition_id
sbl1_partition_id
:执行sbl1_dload_entry()
进入下载模式multi_image_partition_id
multi_image_qti_partition_id
aop_partition_id
qsee_devcfg_image_partition_id
qsee_partition_id
secdata_partition_id
cpucpfw_partition_id
qhee_partition_id
sbl1_partition_id
: 执行qsee_jump_func()
# sa8295p-hqx-4-2-4-0_amss.git\boot\boot_images\boot\QcomPkg\SocPkg\Library\XBLLoaderLib\sbl1_config.c
#define CDT_STR (uint8 *)"CDT"
#define DDR_STR (uint8 *)"DDR"
#define QSEE_STR (uint8 *)"QSEE"
#define QHEE_STR (uint8 *)"QHEE"
#define APPSBL_STR (uint8 *)"APPSBL"
#define QSEE_DEVCFG_STR (uint8 *)"QSEE Dev Config"
#define XCFG_STR (uint8 *)"XBL Config"
#define APDP_STR (uint8 *)"APDP"
#define AOP_STR (uint8 *)"AOP"
#define OEM_MISC_STR (uint8 *)"OEM_MISC"
#define QTI_MISC_STR (uint8 *)"QTI_MISC"
#define SEC_STR (uint8 *)"SEC"
#define CPUCPFW_STR (uint8 *)"CPUCPFW"
#define SHRM_STR (uint8 *)"SHRM"
#define RAMDUMP_STR (uint8 *)"RamDump"
#define SMSS_STR (uint8 *)"SMSS"/*==========================================================================DEFINE TARGET BOOT CONFIG TABLE
===========================================================================*/
boot_configuration_table_entry sbl1_config_table[] =
{
/* boot_media_type target_img_sec_type config_img_type boot_elf_loader_sync_type optional_image load auth exec jump exec_func jump_func pre_procs post_procs load_cancel_func load_metadata_func target_img_partition_id recovery_img_partition_id seg_elf_entry_point ram_part_entry_type whitelist_ptr whitelist_num_valid_entries target_img_str */{PBL_MEDIA, SECBOOT_SMSS_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, TRUE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, smss_pre_procs, smss_post_procs, NULL, NULL, smss_partition_id, smss_recovery_partition_id, 0x0, 0x0, smss_img_whitelist, WHITELIST_VALID_ENTRIES(smss_img_whitelist), SMSS_STR },{PBL_MEDIA, SECBOOT_XBL_CONFIG_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, FALSE, TRUE, FALSE, FALSE, NULL, NULL, xcfg_pre_procs, NULL, NULL, NULL, XBLConfig_partition_id, XBLConfig_recovery_partition_id, 0x0, 0x0, xcfg_img_whitelist, WHITELIST_VALID_ENTRIES(xcfg_img_whitelist), XCFG_STR },{PBL_MEDIA, SECBOOT_SHRM_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, shrm_pre_procs, NULL, NULL, NULL, shrm_partition_id, shrm_recovery_partition_id, 0x0, 0x0, shrm_img_whitelist, WHITELIST_VALID_ENTRIES(shrm_img_whitelist), SHRM_STR },{PBL_MEDIA, SECBOOT_INVALID_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, FALSE, FALSE, FALSE, FALSE, NULL, NULL, cdt_pre_procs, NULL, NULL, NULL, cdt_partition_id, NULL, 0x0, 0x0, cdt_img_whitelist, WHITELIST_VALID_ENTRIES(cdt_img_whitelist), CDT_STR },{PBL_MEDIA, SECBOOT_INVALID_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, FALSE, FALSE, FALSE, FALSE, NULL, NULL, ddr_pre_procs, NULL, NULL, NULL, ddr_params_partition_id, NULL, 0x0, 0x0, ddr_img_whitelist, WHITELIST_VALID_ENTRIES(ddr_img_whitelist), DDR_STR },{PBL_MEDIA, SECBOOT_APDP_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, TRUE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, apdp_pre_procs, apdp_post_procs, NULL, NULL, apdp_partition_id, apdp_recovery_partition_id, 0x0, 0x0, apdp_img_whitelist, WHITELIST_VALID_ENTRIES(apdp_img_whitelist), APDP_STR },{PBL_MEDIA, SECBOOT_SBL_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, TRUE, TRUE, TRUE, FALSE, TRUE, NULL, sbl1_dload_entry, xblramdump_pre_procs, NULL, NULL, xblramdump_load_metadata, sbl1_partition_id, sbl1_recovery_partition_id, SCL_RAMDUMP_CODE_BASE, 0x0, ramdump_img_whitelist, WHITELIST_VALID_ENTRIES(ramdump_img_whitelist), RAMDUMP_STR },{PBL_MEDIA, SECBOOT_OEM_MISC_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, TRUE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, oemm_pre_procs, NULL, NULL, NULL, multi_image_partition_id, multi_image_recovery_partition_id, 0x0, 0x0, oem_misc_img_whitelist, WHITELIST_VALID_ENTRIES(oem_misc_img_whitelist), OEM_MISC_STR },{PBL_MEDIA, SECBOOT_QTI_MISC_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, TRUE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, multi_image_qti_partition_id, multi_image_qti_recovery_partition_id, 0x0, 0x0, qti_misc_img_whitelist, WHITELIST_VALID_ENTRIES(qti_misc_img_whitelist), QTI_MISC_STR },{PBL_MEDIA, SECBOOT_AOP_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, aop_pre_procs, NULL, NULL, NULL, aop_partition_id, aop_recovery_partition_id, 0x0, 0x0, aop_img_whitelist, WHITELIST_VALID_ENTRIES(aop_img_whitelist), AOP_STR },{PBL_MEDIA, SECBOOT_QSEE_DEVCFG_SW_TYPE,CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, qsee_devcfg_image_partition_id, qsee_devcfg_recovery_partition_id, 0x0, 0x0, devcfg_img_whitelist, WHITELIST_VALID_ENTRIES(devcfg_img_whitelist), QSEE_DEVCFG_STR },{PBL_MEDIA, SECBOOT_QSEE_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL, qsee_post_procs, NULL, NULL, qsee_partition_id, qsee_recovery_partition_id, 0x0, 0x0, qsee_img_whitelist, WHITELIST_VALID_ENTRIES(qsee_img_whitelist), QSEE_STR },{PBL_MEDIA, SECBOOT_SEC_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, TRUE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, secdata_partition_id, NULL, 0x0, 0x0, sec_img_whitelist, WHITELIST_VALID_ENTRIES(sec_img_whitelist), SEC_STR },{PBL_MEDIA, SECBOOT_CPUCPFW_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, cpucpfw_partition_id, cpucpfw_recovery_partition_id, 0x0, 0x0, cpucpfw_img_whitelist, WHITELIST_VALID_ENTRIES(cpucpfw_img_whitelist), CPUCPFW_STR },{PBL_MEDIA, SECBOOT_QHEE_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL, NULL, NULL, NULL, qhee_partition_id, qhee_recovery_partition_id, 0x0, 0x0, qhee_img_whitelist, WHITELIST_VALID_ENTRIES(qhee_img_whitelist), QHEE_STR },{PBL_MEDIA, SECBOOT_SBL_SW_TYPE, CONFIG_IMG_ELF, BOOT_ELF_LOADER_SYNC_LOAD_SYNC_HASH, FALSE, TRUE, TRUE, FALSE, TRUE, NULL, qsee_jump_func, NULL, appsbl_post_procs, NULL, appsbl_load_metadata, sbl1_partition_id, sbl1_recovery_partition_id, SCL_XBL_CORE_CODE_BASE, 0x0, xbl_core_img_whitelist, WHITELIST_VALID_ENTRIES(xbl_core_img_whitelist), APPSBL_STR },{MEDIA_TYPE_MAX, }
};
开始跳转QSEE
/* Executing QSEE from SBL1 */
static bl_error_boot_type qsee_jump_func(boot_handle config_context_handle)
{bl_error_boot_type status = BL_ERR_NONE;bl_shared_data_type *bl_shared_data_ptr = NULL;boot_pmic_if_type *pmic_if = NULL;boot_power_if_type *power_if = NULL;boot_edk2_cache_if_type *edk2_cache_if = NULL;xblconfig_status_type xcfg_status;do{status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_BL_SHARED_DATA, (void **)&bl_shared_data_ptr);if(status != BL_ERR_NONE){break;}status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_EDK2_CACHE_INTERFACE, (void**)&edk2_cache_if);if(status != BL_ERR_NONE || edk2_cache_if == NULL){break;}/* Flush the cache before entering QSEE */edk2_cache_if->WriteBackInvalidateDataCacheRange((void *)Image$$SBL1_CODE$$Base, Image$$SBL1_DATA_ZI$$End-Image$$SBL1_CODE$$Base);edk2_cache_if->WriteBackInvalidateDataCacheRange((void *)SCL_SBL1_DDR_BASE, SCL_SBL1_DDR_SIZE);status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_PMIC_INTERFACE, (void **)&pmic_if);if(status != BL_ERR_NONE) {break;}status = boot_config_context_get_ptr(config_context_handle, CONFIG_CONTEXT_POWER_INTERFACE, (void **)&power_if);if(status != BL_ERR_NONE){break;}pmic_if->pm_vib_off();power_if->aop_mini_dump_init();status = boot_minidump_register_regions(config_context_handle); if(status != BL_ERR_NONE){break;}/* De-initialize XBL Config Lib*/xcfg_status = xblconfig_deinit();memcpy(&sbl_qsee_interface_ddr, &(bl_shared_data_ptr->qsee_interface), sizeof(boot_qsee_interface));edk2_cache_if->WriteBackInvalidateDataCacheRange((void *)&sbl_qsee_interface_ddr, sizeof(boot_qsee_interface));/* De-initialize the boot logger */sbl1_boot_logger_deinit(config_context_handle);/* De-init hardware. This must be done after sbl1_logger_deinit()This is also used to turn off VMEM memory clocks. So ensure the api code/buffersare not in memory if it is being used. */sbl1_hw_deinit(config_context_handle);edk2_cache_if->WriteBackInvalidateDataCache();/* clearing the continuous boot failure count which is stored in IMEM */if (boot_shared_imem_cookie_ptr != NULL){boot_shared_imem_cookie_ptr->boot_fail_count = 0;}/* "Exit" bootloader and enter QSEE context. */if (sbl1_get_current_el() == EL_1) {boot_fastcall_tz_no_rsp(TZ_SBL_END_MILESTONE, TZ_SBL_END_MILESTONE_PARAM_ID,(uint32)(&sbl_qsee_interface_ddr),(uint32)(sizeof(sbl_qsee_interface_ddr)), 0,0);}/*Must not reach here*/while(1);}while(FALSE);return status;
}