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

news2024/12/25 15:12:39

【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;
}






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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

shell脚本之循环语句

循环语句 循环含义 将某代码段重复运行多次&#xff0c;通常有进入循环的条件和退出循环的条件 for循环语句 一般知道循环次数使用for循环 第一类 格式1&#xff1a; for名称 in 取值次数;do;done; 格式2&#xff1a; for 名称 in {取值列表} do done# 打印20次 for i i…

docker安装redis7-分片集群

说明 系统&#xff1a;CentOS7.9 redis&#xff1a;7.0.5 因资源有限所有节点部署在一台宿主机上&#xff0c;总共启动6个redis实例&#xff0c;实例对应端口分别从6380-6385&#xff0c;文章中给的有执行脚本&#xff0c;方便配置redis和操作redis实例 下载镜像 docker …

JVM的元空间了解吗?

笔者近期在面试的时候被问到了这个问题&#xff0c;元空间也是Java8当时的一大重大革新&#xff0c;之前暑期实习求职的时候有专门看过&#xff0c;但是近期秋招的时候JVM相关的内容确实有点生疏了&#xff0c;故在此进行回顾。 结构 首先&#xff0c;我们应了解JVM的堆结构&a…

c++——引用(语法、引用特性、常引用、函数返回值引用和指针与引用的不同点)

c中的引用 一、引用 1、引用的概念&#xff1a;给变量取别名。 形式&#xff1a;原类型名& 别名 引用实体旧名&#xff1b; 2、特性&#xff1a; ①引用定义时必须初始化 ②引用一旦初始化之后就不能再改变引用的指向 ③不能引用NULL ④&再等号的左边为引用&…

FPGA原理与结构——ROM IP的使用与测试

一、前言 本文介绍Block Memory Generator v8.4 IP核 实现ROM&#xff0c;在学习一个IP核的使用之前&#xff0c;首先需要对于IP核的具体参数和原理有一个基本的了解&#xff0c;具体可以参考&#xff1a; FPGA原理与结构——块RAM&#xff08;Block RAM,BRAM&#xff09;http…

04_18内存反碎片技术,什么时候适合进行内存碎片整理

前言 内存碎片分为内部碎片和外部碎片&#xff0c;内部碎片指内存页里面的碎片&#xff0c;外部碎片指空闲的内存页分散&#xff0c;很难找到一组物理地址连续的空间内存页&#xff0c;无法满足超过一页的内存分配请求。 虚拟可移动区域 可移动区域&#xff08;ZONE_MOVABLE…

A 题国际旅游网络的大数据分析-详细解析与代码答案(2023 年全国高校数据统计与调查分析挑战赛

请你们进行数据统计与调查分析&#xff0c;使用附件中的数据&#xff0c;回答下列问题&#xff1a; ⚫ 问题 1: 请进行分类汇总统计&#xff0c;计算不同国家 1995 年至 2020 年累计旅游总人数&#xff0c;从哪个国家旅游出发的人数最多&#xff0c;哪个国家旅游到达的人数最多…

【JavaEE】面向切面编程AOP是什么-Spring AOP框架的基本使用

【JavaEE】Spring AOP&#xff08;1&#xff09; 文章目录 【JavaEE】Spring AOP&#xff08;1&#xff09;1. Spring AOP 是什么1.1 AOP 与 Spring AOP1.2 没有AOP的世界是怎样的1.3 AOP是什么 2. Spring AOP 框架的学习2.1 AOP的组成2.1.1 Aspect 切面2.1.2 Pointcut 切点2.1…

微人事 部门管理 模块 (十五)

部门管理的树展示和搜索 数据展示页是个树&#xff0c;我们一次性把数据加载出来也可以通过点一次id加载查询出来出来子部门&#xff0c;我们用一次拿到说有json数据加载出来 数据不多可以用递归&#xff0c;数据很多就用懒加载的方式 由于子部门比较深就不适合&#xff0c;权…

# 59. python的类与对象-更新

[目录] 文章目录 59. python的类与对象-更新1.面向对象编程2.什么是类3.什么是对象4.如何描述对象5.对象的属性和方法6.Python中的类7.type()函数查看数据类型8.类在Python中的应用9.总结 【正文】 59. python的类与对象-更新 1.面向对象编程 本节内容特别抽象&#xff0c;初…

Web3和去中心化:互联网的下一个演化阶段

文章目录 Web3和去中心化的定义Web3&#xff1a;去中心化&#xff1a; 为什么Web3和去中心化如此重要&#xff1f;数据隐私和安全&#xff1a;去中心化的创新&#xff1a;去除中间商&#xff1a; Web3和去中心化的应用领域去中心化金融&#xff08;DeFi&#xff09;&#xff1a…

wustojc2003求整数均值

#include <stdio.h> int main() {int a,b,c,d;double A;scanf("%d%d%d%d",&a,&b,&c,&d);A(double)((abcd)/4.0);//强转成doubleprintf("Sum %d\n",abcd);printf("Average %.2lf",A);return 0;}

C++笔记之基类指针动态地指向某一个子类情况列举

C笔记之基类指针动态地指向某一个子类情况列举 code review! 文章目录 C笔记之基类指针动态地指向某一个子类情况列举1.基本的多态示例2.基类中的成员函数可以设置为纯虚函数3.将基本示例修改为使用智能指针并在堆上实例化子类4.父类指针指向基类后&#xff0c;可以去调用只有…

【JUC系列-01】深入理解JMM内存模型的底层实现原理

一&#xff0c;深入理解JMM内存模型 1&#xff0c;什么是可见性 在谈jmm的内存模型之前&#xff0c;先了解一下并发并发编程的三大特性&#xff0c;分别是&#xff1a;可见性&#xff0c;原子性&#xff0c;有序性。可见性指的就是当一个线程修改某个变量的值之后&#xff0c…

shell脚本之sed

sed sed 即 Stream EDitor&#xff0c;和 vi 不同&#xff0c;sed是行编辑器 基本用法 sed [选项] 自身脚本用法 [支持输入标准输入管道] 常用选项&#xff1a;-n 不输出模式空间内容到屏幕&#xff0c;即不自动打印-e 多点编辑-f FILE 从指定文件中读取编辑脚本-r, -E 使用…

【TypeScript】内置对象

JavaScript 中很多内置对象&#xff0c;可以直接在 TypeScript 中当做定义好了的类型。 ECMAScript 的内置对象 Boolean、Number、String、RegExp、Date、Error、XMLHttpRequest 等 let num: Number new Number(1) let date: Date new Date() let reg: RegExp new RegExp(…

WTF Langchain极简入门: 03. 数据连接

加载文档 langchain提供多种文档加载器&#xff0c;支持多种格式、来源的文件。可以从本地存储系统加载文件&#xff0c;也可以从网上加载远端文件。想了解LangChain所支持的所有文档加载器&#xff0c;请参考Document Loaders。 在本系列课程中&#xff0c;我们将使用最基本…

Docker 搭建 LNMP + Wordpress(详细步骤)

目录 一、项目模拟 1. 项目环境 2. 服务器环境 3.任务需求 二、Linux 系统基础镜像 三、Nginx 1. 建立工作目录 2. 编写 Dockerfile 脚本 3. 准备 nginx.conf 配置文件 4. 生成镜像 5. 创建自定义网络 6. 启动镜像容器 7. 验证 nginx 四、Mysql 1.…

快速学习GO语言总结

备注&#xff1a;本博客将自己初步学习GO的总结进行分享&#xff0c;希望大家通过本博客可以在短时间内快速掌握GO的基本程序编码能力&#xff0c;如有错误请留言指正&#xff0c;谢谢&#xff01; 一、初步了解Go语言 &#xff08;一&#xff09;Go语言诞生的主要问题和目标…

shell脚本——expect脚本免交互

目录 一.Here Document 1.1.定义 1.2.多行重定向 二.expect实现免交互 2.1.基础免交互改密码 2.2.expect定义 2.3.expect基本命令 2.4.expect实现免交互ssh主机 一.Here Document 1.1.定义 使用I/O重定向的方式将命令列表提供给交互式程序&#xff0c;是标准输 入的一…