系列文章汇总见:《【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
好,话不多说,我们开始分析代码吧:
从 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 = 0x00010005
BASE_NAME = XBLLoader
FILE_GUID = BD4CC3FB-4872-DDC9-2CE9-AF999D7B9264
MODULE_TYPE = USER_DEFINED
VERSION_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
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=EL1
EL1_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
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_pointer
MOV x7, x0
// 2. 将 栈指针寄存器 配置为0, sp = 0
MOV X0, #0
MOV SP, X0
// 3. 禁止 Cache、MMU 和 exception异常处理功能,关闭 TLB 页缓存,禁止CPU的指令和数据cache功能
DSB SY // 清除CPU数据流水线
ISB SY // 清除CPU指令流水线
TLBI VMALLE1 // TLB invalidate
IC IALLU // Invalidate cache to PoU
DSB 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 fault
ORR 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 INSTRUCTIONS
MRS X0, CPACR_EL1
ORR X0, X0, #0X300000
MSR CPACR_EL1, X0
ISB SY // 清除CPU指令流水线
// 7. 读取中断状态寄存器ISR_EL1的值到 X0中,通过 ISR_EL1_A_BIT 位来检查是否有pending的异常,如果有则进入死循环
MRS X0, ISR_EL1
AND X0, X0, #ISR_EL1_A_BIT
CBNZ 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 //开启Dbg
MSR DAIFClr, #INT_A_BIT
isb
// 9. 配置Stack 栈地址,SBL的栈大小默认为12kb, 定义在 \boot\boot_images\boot\QcomPkg\SocPkg\Library\DevPrgDLib\sbl1.ld 中
LDR x0, = Image$$SBL1_STACK_BASE$$Pointer
MOV SP, x0
// 10. 使能 指令Cache 缓存功能
// Enable instruction cache
MRS X0, SCTLR_EL1
ORR X0,X0, #I_BIT
// 11. 设置PXN的SPAN位,用于设置EL1或EL2的异常 SET SPAN bit for PXNSET SPAN bit for PXN
ORR X0,X0, #CTRL_SPAN_BIT
MSR SCTLR_EL1, X0
// 12. 初始化栈内存、配置栈为16字节对齐
LDR x0, = Image$$SBL1_STACK$$Base
LDR x1, = Image$$SBL1_STACK$$Length
BIC x1, x1, #0xF
MOV x2, #0 // used as counter
write_16bytes_loop:
stp xzr,xzr,[x0], #0x10 // 将 xzr=xzr, [0]=0x10 往栈底写入#0x10
add x2, x2, #0x10 // x2 += 0x10, increment by 16 bytes
cmp x1, x2 // 判断 x1 == x2 ?
b.ne write_16bytes_loop
sbl1_entry_init_stack:
// 13. 将 x7寄存器的值 保存到 X0中,将它以参数传递入sbl1_main_ctl中,它是APPS_PBL传入的共享数据地址 pbl_shared_data_pointer
MOV w0, w7 // mov x0, x7
BL sbl1_main_ctl
// For safety
BL boot_loop_here // never returns
汇总下,在汇编代码中,主要做了四件事,如下:
CPU
的中断、Cache
、MMU
、TLB
功能VBAR_EL1 = &sbl1_vector_table
C
函数 sbl1_main_ctl()
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_if
status = 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_imem
boot_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: Off
boot_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.c
status = 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_init
status = 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,启动 TrustZone
status = sbl1_config_process_bl(config_context_handle, sbl1_config_table);
} while (FALSE);
error_if.error_handler(__FILE_BASENAME__, __LINE__, status);
} /* sbl1_main_ctl() */
考虑到文章篇幅,本文先写到这,后续的内容,请见下篇文章,谢谢!
解析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/buffers
are 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;
}