【SA8295P 源码分析】06 - SA8295P XBL Loader 阶段 sbl1_main_ctl 函数代码分析

【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                    = 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

1.2 boot\QcomPkg\XBLDevPrg\ModuleEntryPoint.S:跳转 sbl1_entry 函数

ModuleEntryPoint.S 的主要工作如下:

  1. 获取当前的运行环境,保存在 x4 寄存器中, CurrentEL : 0xC=EL3; 0x8=EL2; 0x4=EL1
  2. 第一个传参X0APPS_PBL 传入的共享数据地址,将 x0的值保存到X19 寄存器中
  3. 禁止所有中断,对应的指令为 asm{ msr daifset, #DAIF_WR_INT_BITS(禁止中断) ; isb(清除指令流水线) }
  4. 关闭所有的CachesMMU
  5. 关闭 指令缓存 功能
  6. 关闭 TLB 页缓存 功能
  7. 恢复x9的值 (APPS_PBL 传入的共享数据地址) 到x0 中,作为第一个传参,传入sbl1_entry
  8. 跳转到 sbl1_entry 函数,传参为 x0APPS_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

1.3 XBLLoaderLib\sbl1_Aarch64.s:跳转 sbl1_main_ctl 函数

sbl1_Aarch64.s 主要工作:

  1. x0 传参保存到 x7 寄存器中,它是 APPS_PBL 传入的共享数据地址 pbl_shared_data_pointer
  2. 将 栈指针寄存器 sp 配置为0
  3. 禁止 CacheMMUexception 异常处理功能,关闭 TLB 页缓存,禁止CPU的指令和数据cache功能
  4. SCTLR_EL1 寄存器的 MMU 位(0x1)、Cache位(0x4)、Stack Alignment Check位(0x8)清零
  5. 配置异常向量表:将 sbl1_vector_table 异常向量表的地址 保存在 X0 寄存器中,然后写入 VBAR_EL1 异常向量表寄存器中
  6. 设置FPEN bit20bit 21 ,不捕获 FP 和高级 SIMD 指令
  7. 读取中断状态寄存器ISR_EL1的值到 X0中,通过 ISR_EL1_A_BIT 位来检查是否有pending的异常,如果有则进入死循环
  8. 开启外部中止功能:在指令获取失败(指令中止)或数据访问失败(数据中止)时会生成中止
  9. 配置Stack 栈地址,SBL的栈大小默认为12kb, 定义在 \boot\boot_images\boot\QcomPkg\SocPkg\Library\DevPrgDLib\sbl1.ld
  10. 使能 指令Cache 缓存功能
  11. 设置PXNSPAN位,SPAN位用于设置EL1EL2的异常
  12. 初始化栈内存、配置栈为16字节对齐
  13. 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

汇总下,在汇编代码中,主要做了四件事,如下:

  1. 禁止 CPU 的中断、CacheMMUTLB 功能
  2. 初始化中断向量表 VBAR_EL1 = &sbl1_vector_table
  3. 开启外部中止功能:在指令获取失败(指令中止)或数据访问失败(数据中止)时会生成中止
  4. 初始化栈
  5. 跳转进入 C 函数 sbl1_main_ctl()

二、XBL Loader C代码分析

在这里插入图片描述

2.1 XBLLoaderLib\sbl1_mc.c:入口函数 sbl1_main_ctl(), SBL1(XBL Loader环境初始化)

sbl1_main_ctl() 主要工作如下:

  1. 记录 sbl1 开始运行的时间,保存在 sbl_start_time
  2. 初始化 DAL 层(Device Abstraction Layer)的 堆head内存,大小为207kb (0x33C00)
  3. 初始化 DAL 层(Device Abstraction Layer,位于硬件与应用层之间,DAL API定义在DDI文件中,应用层调用DDI接口使用驱动提供的服务)
  4. 初始化 boot_config_context 保存在 config_context_handle中, memory_mgr_dal=config_context_handle->mem_if
  5. 配置 ConfigContext 参数,将 Context IDContext interface 接口 绑定在一起
  6. 获取 CONFIG_CONTEXT_CLK_INTERFACE 对应的 clk 接口指针 保存在 clk_if
  7. 调用 clk_if->Clock_DebugInit() 函数初始化clock, QREF,PLL, LPASS
  8. 初始化栈溢出保护 (SSP) 功能机制的参数 __stack_chk_guard 为一个随机数
    主要作用是,在调用子函数时,将__stack_chk_guard的值存入栈顶,然后在函数返回之前取出栈顶的值,
    __stack_chk_guard比较,如果一致则说明栈数据没有被破坏,继续返回运行母函数
    如果比较不一致,说明出现了栈溢出,则直接调用__stack_chk_fail()函数宕机
  9. 获取 CONFIG_CONTEXT_MEMORY_MGR_INTERFACE 对应的 mem 接口指针 保存在 mem_if
  10. pbl_shared 的数据保存在 sbl1_pbl_shared_data 中,处理pbl传入的数据后保存在 sbl_verified_info
  11. pbl_shared->pbl_flash_shared_data中保存了启动设备的boot_device信息,将其保存在 ConfigContext的CONFIG_CONTEXT_BOOT_DEVICE
  12. 调用 mem_if->malloc 申请 media_if 的内存,用于保存 media_interface_if 的接口
  13. media_interface_if 的接口地址保存在 config_contextCONFIG_CONTEXT_BOOT_MEDIA_INTERFACE
  14. 初始化 SBL memory map 内存表
  15. 获取CONFIG_CONTEXT_BUSYWAIT_INTERFACE 对应的 busywait接口指针 保存在busywait_if
  16. 初始化busywait模块, 获取HWIO QTimer的地址 和 QTimerfreq,后面uart 串口需要用到
  17. 初始化共享imem boot_shared_imem
  18. 读取SMEM缓冲区数据进行初始化XBL_Core chip info driver芯片信息驱动程序,它是在XBL Loader阶段PlatformInfo填充的,如chip idchip serial
  19. 获取CONFIG_CONTEXT_BOOT_STATS_INTERFACE 对应的 boot_stats接口指针 保存在boot_stats_if中,初始化 boot_statistics_obj 结构体中的 time 统计信息
  20. 初始化 boot logger, 将 boot loggerlogger_uart_if 绑定在一起,这样 log 就可以通过 uart 口打印出来
  21. 打印串口 logboot 的相关属性,如下:
    第一句logFormat: Log Type - Time(microsec) - Message - Optional Info
    第二句logLog 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
  22. 如果配置了 debug cookie, 则会停留在此处等待 JTag 调试器的接入
  23. 获取CONFIG_CONTEXT_DDR_INFO_INTERFACE对应的 ddr接口指针 保存在 di_if 中, 然后初始化DDR
    主要是申请了 boot_ddr_info 类型的内存,指针保存在 ddr_info_ptr->mem_ifdi_ptr->mem_if
  24. 初始化 QSEE 接口,为后续SBL1跳转到QSEE 做准备
  25. 初始化 Temperature Sensor温度传感器,通过Tsens_Init() 配置使能PMICPS_HOLD reset功能,这样我们就可以通过PS_HOLD来做 warm reset
    初始化QUSB2,配置 High Speed QUSB2 PHY到无驱动模式,为 dload 下载做准备
  26. SBL1 (XBL Loader)阶段即将结束,解析sbl1_config_table,加载 SMSSXBL Configshrmapdpsblramdumpdload)、aopQSEE DevcfgQSEEsecdataQHEE, 最终返回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() */


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

  1. smss_partition_id
  2. XBLConfig_partition_id
  3. shrm_partition_id
  4. apdp_partition_id
  5. sbl1_partition_id:执行 sbl1_dload_entry() 进入下载模式
  6. multi_image_partition_id
  7. multi_image_qti_partition_id
  8. aop_partition_id
  9. qsee_devcfg_image_partition_id
  10. qsee_partition_id
  11. secdata_partition_id
  12. cpucpfw_partition_id
  13. qhee_partition_id
  14. 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;
}






本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/82771.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Communication Channels

沟通渠道 n * (n - 1) / 2 你1 相关方3 4 4 * 3 / 2 6 你1 相关方3 相关方1 5 5 * 4 / 2 10 人越多&#xff0c;沟通渠道越多&#xff0c;沟通成本理论越高

Roxy-Wi 命令执行漏洞复现

漏洞描述 Roxy-WI是开源的一款用于管理 Haproxy、Nginx 和 Keepalived 服务器的 Web 界面 Roxy-WI 6.1.1.0 之前的版本存在安全漏洞,该漏洞源于系统命令可以通过 subprocess_execute 函数远程运行,远程攻击者利用该漏洞可以执行远程代码。 免责声明 技术文章仅供参考,任…

jstack(Stack Trace for Java)Java堆栈跟踪工具

jstack&#xff08;Stack Trace for Java&#xff09;Java堆栈跟踪工具 jstack&#xff08;Stack Trace for Java&#xff09;命令用于生成虚拟机当前时刻的线程快照&#xff08;一般称为threaddump或者javacore文件&#xff09;。 线程快照就是当前虚拟机内每一条线程正在执…

使用预制体画刷在游戏场景中快速布置预制体、粒子特效等

有时候在使用tilemap的时候&#xff0c;会希望在场景中添加更复杂的对象。 在2d-extras中&#xff0c;加入了预制件笔刷&#xff08;Prefab Brush&#xff09;&#xff0c;可以将游戏物体预制体作为瓦片&#xff0c;来方便的在游戏场景中快速的绘制。可以自动适应游戏物体的位置…

GitHub 开启 2FA 双重身份验证的方法

最近收到GitHub官方发来的邮件&#xff0c;全是英文的&#xff0c;如图&#xff1a; 使用邮箱翻译插件&#xff0c;进行翻译&#xff0c;哦&#xff0c;原来是要我进行2FA注册&#xff0c;如果不注册&#xff0c;GitHub的访问将收到限制&#xff0c;所以还是得注册一下 然后怎…

【Redis基础篇】浅谈分布式系统(一)

一、浅谈分布式系统 1. 单机架构&#xff1a;只有一台服务器&#xff0c;这个服务器负责所有的工作。 如果遇到了服务器不够的场景怎么处理? 开源&#xff1a;增加更多的硬件资源节流&#xff1a;软件上的优化&#xff0c;优化代码等…一台服务器资源使用有限&#xff0c;就…

无涯教程-PHP - 常量声明

常量值不能更改。默认情况下&#xff0c;常量区分大小写。按照约定&#xff0c;常量标识符始终为大写。与变量不同&#xff0c;您不需要具有"$"的常量。 constant 函数 如名称所示&#xff0c;此函数将返回常量的值。 当您要检索常量的值但不知道其名称时&#xf…

WebGL的剪裁空间

推荐&#xff1a;使用NSDT场景编辑器助你快速搭建可二次编辑的3D应用场景 什么是WebGL的剪裁空间 WebGL的剪裁空间&#xff08;Clipping Space&#xff09;是在图形渲染过程中处理视图体积裁剪的一种特定空间。它是指定义在3D世界坐标系和屏幕窗口之间的虚拟空间&#xff0c;用…

宝塔部署Java+Vue前后端分离项目经验总结

前言 之前部署服务器都是在Linux环境下自己一点一点安装软件&#xff0c;听说用宝塔傻瓜式部署更快&#xff0c;这次浅浅尝试了一把。 确实简单&#xff01; 1、 买服务器 咋买服务器略&#xff0c;记得服务器装系统就装 Cent OS 7系列即可&#xff0c;我装的7.6。 2、创建…

css 实现svg动态图标效果

效果演示&#xff1a; 实现思路&#xff1a;主要是通过css的stroke相关属性来设置实现的。 html代码: <svgt"1692441666814"class"icon"viewBox"0 0 1024 1024"version"1.1"xmlns"http://www.w3.org/2000/svg"p-id"…

游戏msvcr120.dll丢失怎样修复?msvcr120.dll丢失常见原因

在尝试运行某些游戏时&#xff0c;我遇到了“msvcr120.dll丢失”的错误提示。经过一番调查和尝试&#xff0c;我成功地解决了这个问题。msvcr120.dll是Visual C Redistributable Package的一部分&#xff0c;它包含了许多运行Windows应用程序所需的库和函数。当游戏或其他应用程…

The internal rate of return (IRR)

内部收益率 NPV(Net Present Value)_spencer_tseng的博客-CSDN博客

电商项目part04 微服务拆分

微服务架构拆分 微服务介绍 英文:https://martinfowler.com/articles/microservices.html 中文:http://blog.cuicc.com/blog/2015/07/22/microservices 微服务拆分时机 如下场景是否需要进行微服务拆分&#xff1f; 代码维护困难&#xff0c;几百人同时开发一个模块&…

Java之接口

作者简介&#xff1a; zoro-1&#xff0c;目前大一&#xff0c;正在学习Java&#xff0c;数据结构等 作者主页&#xff1a; zoro-1的主页 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f496; Java之接口 接口的概念语法规则接口特性接口使用案…

16----公式

本节我们来学习如何在markdown中打印公式 Markdown是一种轻量级标记语言&#xff0c;常用于撰写文档、博客和论坛帖子。虽然Markdown本身并不支持数学公式&#xff0c;但可以使用一些扩展来实现公式的显示。在支持公式扩展的 Markdown 解析器中&#xff0c;我们可以使用 Katex …

openstack搭建

1 设置root密码&#xff1a;sudo passwd root 2 网络配置&#xff1a;虚拟机安装是选择nat映射&#xff0c;系统安装成功后直接配置vmnet8的地址段即可&#xff08;操作系统正常安装即可&#xff0c;虚拟机内存大于4G即可&#xff09;&#xff1b; 3 安装ssh 在命令行输入 “su…

【微信小程序】下拉刷新功能实现

微信小程序开发系列 文章目录 前言一、onPullDownRefresh函数二、实现1.开启下拉刷新2.监听下拉事件 前言 在开发微信小程序中经常会需要下拉页面进行更新要页面数据的功能&#xff0c;微信小程序提供了onPullDownRefresh函数。该函数作用是监听用户下拉动作。 一、onPullDown…

Web会话技术

会话:用户打开浏览器&#xff0c;访问web服务器的资源&#xff0c;会话建立&#xff0c;直到有一方断开连接&#xff0c;会话结束。在一次会话中可以包含多次请求和响应 会话跟踪:一种维护浏览器状态的方法&#xff0c;服务器需要识别多次请求是否来自于同一浏览器&#xff0c;…

char *str,char str,char * str和char str的区别

1.char *str是一个指向字符或字符串的指针&#xff0c;总是指向一个字符的起始地址&#xff0c;例如 char *str "Hello"; cout << *str << endl; // 输出&#xff1a;H cout << str << endl; // 输出&#xff1a;Hello str "World…

V2board缓存投毒漏洞复现

1.什么是缓存投毒 缓存投毒&#xff08;Cache poisoning&#xff09;&#xff0c;通常也称为域名系统投毒&#xff08;domain name system poisoning&#xff09;&#xff0c;或DNS缓存投毒&#xff08;DNS cache poisoning&#xff09;。它是利用虚假Internet地址替换掉域名系…