1. sbl1.s -- 汇编启动文件
sbl1程序的入口点在0xF800_C000,从memory map可以看出此地址位于L2 cache中,所以sbl1实际上是运行在L2 cache上的;
1)设置中断向量表
中断向量表位于0xFE80_5FC0(OCIMEM),覆盖PBL的中断向量表
AREA SBL1_INDIRECT_VECTOR_TABLE, CODE, READWRITE
CODE32
unused_reset_vector
DCD 0x00000000
undefined_instruction_vector
DCD sbl1_undefined_instruction_nested_handler
swi_vector
DCD boot_swi_c_handler
prefetch_abort_vector
DCD sbl1_prefetch_abort_nested_handler
data_abort_vector
DCD sbl1_data_abort_nested_handler
reserved_vector
DCD boot_reserved_c_handler
irq_vector
DCD boot_irq_c_handler
fiq_vector
DCD boot_fiq_c_handler
2)代码入口点 -- SBL1_ENTRY
sbl1的汇编代码入口点在0xF800_C000,即L2 cache中;
AREA SBL1_ENTRY, CODE, READONLY, ALIGN=4
CODE32
ENTRY
sbl1_entry
; 进入SVC模式
msr CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
; 保存PBL传递进来的参数r0->r7
mov r7, r0
; 设置堆栈指针
ldr r0, =SCL_SBL1_STACK_BASE
mov r13, r0
; 为und mode和abt mode设置堆栈指针
msr CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit
mov r13, r0
msr CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit
mov r13, r0
; 返回到svc模式
msr CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit
; 恢复PBL参数r7->r0
mov r0, r7
; 跳转到C语言程序入口点sbl1_main_ctl
ldr r5, =sbl1_main_ctl
blx r5
2. sbl1_mc.c -- C语言启动文件
sbl1_main_ctl()是C语言程序的入口函数,在此以后我们就可以开始C语言之旅了。
1)sbl1_main_ctl() -- C语言程序入口点
a)初始化串口,并输出log
sbl1_boot_logger_init(&boot_log_data,pbl_shared);
boot_log_message("scatterload_region&& ram_init, Start");
b)重定位中断向量表和数据段
result =boot_scatterload_region(&sbl1_scatterload_data);
result =boot_ram_init(&sbl1_ram_init_data);
c)关闭watchdog
pm_pon_wdog_enable(0,PM_OFF);
d)重定位并初始化SHARED IMEM – 其基地址位于0xFE805000
sbl1_update_shared_imem_base();
boot_shared_imem_init(&bl_shared_data);
e)硬件初始化
sbl1_hw_init();
f)初始化TZ, RPM, WDT,最后跳转到APPSBL即lk
boot_config_process_bl(&bl_shared_data, SBL1_IMG,sbl1_config_table);
2)boot_config_process_bl()
遍历config table,并进入相应的子系统执行代码;
/* For every entry inthe boot configuration table */
for(curr_entry =boot_config_table; curr_entry->host_img_id != NONE_IMG; curr_entry++)
{
/* Process entries sequentially only forthe specific host_img */
if(curr_entry->host_img_id == host_img)
{
boot_config_process_entry(bl_shared_data,curr_entry);
}
}
3)boot_config_process_entry()
// 执行Pre- Procedures函数列表
boot_do_procedures(bl_shared_data,boot_config_entry->pre_procs);
// 加载并校验image
// 跳转到image的入口点,并开始执行
(boot_config_entry->exec_func)(bl_shared_data);
// 执行Post- Procedures函数列表
boot_do_procedures(bl_shared_data,boot_config_entry->post_procs);
// 跳转到image入口点执行程序,并且不再返回
(boot_config_entry->jump_func)(bl_shared_data);
3. 输出log
sbl1可以把log保存在ram中,或者直接输出到串口。Log格式可以是显示启动时间,或者是显示delta时间。Log最初是保存在L2 cache中,在DDR初始化完毕后,将会重定位到DDR中;
1)log存储位置
boot_log_data数据结构定义了log和meta info存储地址(a):
staticboot_log_init_data boot_log_data =
{
(void *)SBL1_LOG_BUF_START, // 0xF80599B0
SBL1_LOG_BUF_SIZE, // 0x5C0
(void *)SBL1_LOG_META_INFO_START, // 0xF8059970
SBL1_LOG_META_INFO_SIZE, // 0x40
NULL
};
#define SBL1_LOG_BUF_START (&Image$$SBL1_LOG_BUF_SECTION$$Base)
#defineSBL1_LOG_BUF_SIZE 1472
#defineSBL1_LOG_META_INFO_START (&Image$$SBL1_LOG_META_INFO_SECTION$$Base)
#defineSBL1_LOG_META_INFO_SIZE 64
在DDR初始化完成后,上述地址将会被重定位到DDR中(b):
static voidsbl1_move_boot_log_to_ddr()
{
/* Relocate boot logger buffer to DDR andcontinue to save log in DDR */
boot_log_relocate((void*)SCL_DDR_BOOT_LOG_META_INFO_BASE,
(void *)SCL_SBL1_DDR_BOOT_LOG_BUF_BASE,
SCL_SBL1_DDR_BOOT_LOG_BUF_SIZE,
(void*)SBL1_LOG_META_INFO_START,
(void *)SBL1_LOG_BUF_START,
SBL1_LOG_BUF_SIZE);
boot_log_data.log_buffer_start = (void *)SCL_SBL1_DDR_BOOT_LOG_BUF_BASE;
boot_log_data.log_buffer_size =SCL_SBL1_DDR_BOOT_LOG_BUF_SIZE;
boot_log_data.meta_info_start = (void *)SCL_DDR_BOOT_LOG_META_INFO_BASE;
}
上述用到的几个地址需要查看相应的scl文件获得(c),Log在L2 Cache中的存储地址如下:
// Reserve space for theboot logger's meta info data. -- 为meta log预留内存空间
SBL1_LOG_META_INFO_SECTION +0x0 EMPTY 64
// Reserve buffer spacefor the boot logger's log messages -- 为log预留内存空间
SBL1_LOG_BUF_SECTION +0x0 EMPTY 1472
Log在DDR中的存储地址如下:
SBL1_DDR_LOG_META_INFO_SECTION\
(((0x0FE00000 + 0x0088000) + 0x0008000) \
+ (0x0100000 - 0x0088000 - 0x0008000 - 64 - 1984))EMPTY 64
SBL1_DDR_LOG_BUF_SECTION\
((((0x0FE00000 +0x0088000) + 0x0008000) \
+ (0x0100000 - 0x0088000- 0x0008000 - 64 - 1984)) + 64) EMPTY 1984
我们大概算一下,Meta Info的起始地址在FEFF800的位置,而Log的起始地址在FEFF840,注意这两个地址在kernel中是不