sbl1启动代码分析

FROM:http://blog.csdn.net/modianwutong/article/details/46334595

 

 

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 modeabt 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

SBL1LOGBUFSECTION

Base)  

 

#defineSBL1_LOG_BUF_SIZE     1472

 

#defineSBL1_LOG_META_INFO_START    (&Image

SBL1LOGMETAINFOSECTION

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中是不能访问的,在msm8974pro.dts中有如下定义:

&memory_hole {

qcom,memblock-remove = <0x04600000 0x8c00000

                        0x0fa00000 0x500000>; /* Address and size of the hole */

};

明显能够看到0xfa00000-0xff00000存在一个内存空洞,这部分内存由SBL1使用,如果想在kernel中查看sbl1的log信息,就需要在LK中把这块内存挖出来;

 

meta info数据结构定义如下,这个数据结构的主要目的是记录log的起始地址,当前位置,buf大小等,实现ring buffer功能:

structboot_log_meta_info

{

  uint8 *log_buf_start;           // 指向log buf起始地址

  uint8 *log_buf_ptr;                     // 指向log buf当前地址

  uint32 log_buf_size;                     // 指示log buf大小

  uint32 log_buf_init;               // 指示log buf是否已经初始化

 

  uint32 ref_time;                            // 参考时间

  uint32 start_time;                   // 启动时间

  uint32 stopwatch_locked;

};

 

2)初始化并保存log

sbl1_boot_logger_init() :

// meta info的首地址赋给log_meta_info_ptr

boot_log_set_meta_info(init_data->meta_info_start);

-> log_meta_info_ptr= (struct boot_log_meta_info *)addr;

 

// 初始化并保存log到相应的buf

boot_log_init_ram(init_data);

// 初始化元数据结构

-> log_meta_info_ptr->log_buf_size= init_data->log_buffer_size;   // logbuf大小

-> log_meta_info_ptr->log_buf_start= init_data->log_buffer_start;  // logbuf起始地址

-> log_meta_info_ptr->log_buf_ptr= init_data->log_buffer_start;    //log buf当前地址

-> log_meta_info_ptr->log_buf_init= TRUE;

// 清空log buf

-> qmemset(log_meta_info_ptr->log_buf_ptr,0x0, init_data->log_buffer_size);

// 保存log

-> boot_log_ram_put_string(NEWLINE,NEWLINE_LEN);   //换行

-> boot_log_ram_put_string(LEGEND_HEADER,HEADER_LEN);    //log头信息

-> boot_log_ram_put_string(NEWLINE,NEWLINE_LEN);   //换行

-> boot_log_ram_put_string(LEGEND_KEY,KEY_LEN);     //打印log信息

-> boot_log_ram_put_string(NEWLINE,NEWLINE_LEN);   //换行

 

// boot_log_ram_put_string函数实现

boot_log_ram_put_string()

-> qmemcpy(log_meta_info_ptr->log_buf_ptr,str, len);             // 拷贝logbuf

-> log_meta_info_ptr->log_buf_ptr+= len;                         // 当前log buf指针向后移动len长度

 

串口初始化详见boot_log_init_uart();

 

3)输出log

boot_log_message("SBL1,Start");

-> uint32current_timestamp = boot_get_time();   // 获取时间戳

-> boot_log_message_ram(message,current_timestamp, LOG_MSG_TYPE_BOOT);       // 输出logram

-> boot_log_message_uart(message,current_timestamp, LOG_MSG_TYPE_BOOT);       // 输出loguart

 

4)log格式

Format: Log Type - Time(microsec) - Message

 

Log Type   B - since boot (excluding boot rom) 

D – delta

 

使用boot_log_message()显示的是开机时间:

boot_log_message("scatterload_region&& ram_init, Start");

 

使用boot_log_stop_timer()boot_log_stop_timer()会显示Delta时间,即start/stop间隔的时间:

boot_log_start_timer();

boot_log_stop_timer("scatterload_region&& ram_init, Delta");

 

如下:

B -    125904 - scatterload_region &&ram_init, Start

D -        30 - scatterload_region &&ram_init, Delta

 

5)可变参数log

  高通原始代码中的boot_log_message()函数只支持一个参数,使用下面的patch,可以使该函数除了有一个fmt固定参数外,后面跟的参数的个数和类型是可变的,实际调用时可以使用以下形式:

 boot_log_message(“%d”, i); 

boot_log_message(“%s”, str);

 

diff --gita/core/boot/secboot3/src/boot_logger.c b/core/boot/secboot3/src/boot_logger.c

index 9f3b8d2..94c95cc100755

---a/core/boot/secboot3/src/boot_logger.c

+++b/core/boot/secboot3/src/boot_logger.c

@@ -45,6 +45,10 @@when       who        what, where, why

 #include "boot_logger_timer.h"

 #include "boot_logger_uart.h"

 

+#include<string.h>

+#include<stdio.h>

+#include<stdlib.h>

+#include<stdarg.h>

 /*=============================================================================

 

             LOCAL DEFINITIONS AND DECLARATIONSFOR MODULE

@@ -247,9 +251,16 @@void boot_log_set_ref_time(uint32 ref_time)

 *   None

 *

 */

-voidboot_log_message(char *message)

+voidboot_log_message(char *fmt, ...)

 {

   uint32 current_timestamp = boot_get_time();

+  char message[256];

+

+  va_list ap;

+  va_start(ap, fmt);

+  vsnprintf(message, sizeof(message), fmt, ap);

+  va_end(ap);

+

   /*Logs message with time stamp in ram, mustbe initialized first.*/

   boot_log_message_ram(message,current_timestamp, LOG_MSG_TYPE_BOOT);

   /* Transmit the message with time stamp */

diff --gita/core/boot/secboot3/src/boot_logger.h b/core/boot/secboot3/src/boot_logger.h

index 3d7d5e0..74c5127100755

---a/core/boot/secboot3/src/boot_logger.h

+++b/core/boot/secboot3/src/boot_logger.h

@@ -291,7 +291,7 @@ voidboot_log_set_ref_time(uint32 ref_time);

 *   None

 *

 */

-voidboot_log_message(char *);

+voidboot_log_message(char *fmt, ...);

 

如果不想打patch,又想输出可变参数的话,也可以把参数直接打到字符串里面,方法如下:

static charerror_message[BOOT_ERROR_MSG_LEN];

snprintf(error_message,BOOT_ERROR_MSG_LEN,  \

             "Error code %lx at %s Line%lu", err_code, filename_ptr, line);

boot_log_message(error_message);

 

6)相关文件

sbl1_mc.c

boot_logger.c

boot_logger_timer.c

boot_logger_uart.c

 

4. 重定位中断向量表和数据段

1)重定位中断向量表

  中断向量表定义了ARM CPU发生各种异常时的跳转地址;重定位中断向量表的目的就是要使用sbl1定义的中断向量表替换PBL定义的中断向量表;

staticboot_scatterload_data_type sbl1_scatterload_data =

{

  (uint8*)&Load

SBL1INDIRECTVECTBL

Base,  /* load_region_base */

 

  (uint8*)&Image

SBL1INDIRECTVECTBL

Base, /* image_region_base */

 

 &Image

SBL1INDIRECTVECTBL

Length        /* image_region_len */

 

};

 

(uint8*)&Load

SBL1INDIRECTVECTBL

Base         // 中断向量表加载时地址

 

(uint8*)&Image

SBL1INDIRECTVECTBL

Base        // 中断向量表运行时地址

 

&Image

SBL1INDIRECTVECTBL

Length                     // 中断向量表长度

 

 

加载时地址表示程序的存放地址,运行时地址表示程序运行时的绝对地址,查看符号表能够找到这两个地址;SBL1是在L2 cache中运行的,此处需要把中断向量表搬到OCIMEM中;

SBL1_INDIRECT_VEC_TBL  (((0xFE800000 +0x0005000)+0x0001000-(0x20))-(0x20)) (0x20)}

 

// 重定位中断向量表 -- 中断向量表将被搬到0xFE805FC0

boot_scatterload_region(&sbl1_scatterload_data);

-> qmemcpy(boot_scatterload_data->image_region_base,

              boot_scatterload_data->load_region_base,

              (uint32)boot_scatterload_data->image_region_len );

 

2)重定位数据段

staticboot_ram_init_data_type sbl1_ram_init_data =

{

  (uint8*)&Load

SBL1DATARW

Base,      /* load_rw_base */

 

  (uint8*)&Image

SBL1DATARW

Base,     /* image_rw_base */

 

  &Image

SBL1DATARW

Length,          /* image_rw_len */

 

  (uint8*)&Image

SBL1DATAZI

Base,        /* image_zi_base */

 

  &Image

SBL1DATAZI

ZI$$Length       /* image_zi_len */

 

};

 

(uint8*)&Load

SBL1DATARW

Base             // 已初始化数据段加载地址

 

(uint8*)&Image

SBL1DATARW

Base           // 已初始化数据段运行地址

 

&Image

SBL1DATARW

Length                   // 已初始化数据段长度

 

(uint8*)&Image

SBL1DATAZI

Base              // 未初始化数据段加载地址

 

&Image

SBL1DATAZI

ZI$$Length               // 未初始化数据段运行地址

 

 

SBL1_DATA_RW +0x0 ALIGN0x1000

{

    * (+RW)

}

 

SBL1_DATA_ZIImageLimit(SBL1_DATA_RW)

{

    //Explicitly add only hotplug module's ZIto non DDR ZI, all other file system code should

    //allocate ZI in DDR

    fs_hotplug*.o (+ZI)

    * (BOOT_INTERNAL_HEAP)

    * (+ZI)

}

 

  只读(RO)数据段用于存放全局常量(const),已初始化(RW)数据段用于存放已初始化的全局变量,未初始化(ZI)数据段用于存放未初始化的全局变量;

 

// 重定位数据段

boot_ram_init(&sbl1_ram_init_data);

// 重定位已初始化数据段

-> qmemcpy( boot_ram_init_data->image_rw_base,

             boot_ram_init_data->load_rw_base,

              (uint32)boot_ram_init_data->image_rw_len);

// 清除未初始化数据段

-> qmemset(boot_ram_init_data->image_zi_base,

             0,

             (uint32)boot_ram_init_data->image_zi_len);

5. 关闭watchdog

1)数据结构

typedef enum

{

   PM_OFF,        // 关闭watchdog

   PM_ON,         // 打开watchdog

   PM_INVALID

}pm_on_off_type;

 

typedef enum      //reset类型

{

  PM_PON_RESET_CFG_WARM_RESET,

  PM_PON_RESET_CFG_NORMAL_SHUTDOWN,

  … …

}pm_pon_reset_cfg_type;

 

2)关闭watchdog

pm_pon_wdog_enable(0,PM_OFF);

-> pm_pon_wdog_init();

-> data = (enable ==PM_ON) ? 0xFF : 0;

-> pm_spmi_lite_write_byte_mask(PMIC_A_SLAVEID_PRIM,pon_wdog_reg.reset_ctl2_addr,

                               pon_wdog_reg.reset_en_mask,data, 0);

 

3)配置watchdog

pm_pon_wdog_cfg(unsignedpmic_device_index,

uint32 s1_timer,             // 配置s1 timer

uint32 s2_timer,             // 配置s2 timer

pm_pon_reset_cfg_type reset_cfg_type)  // 配置reset类型

4)相关文件

pm_pon.h

pm_pon_wdog.c

6. 初始化Shared IMEM

  SHAREDIMEM是驻留在OCIMEM里面的共享内存,分为BOOT,USB,CDT,EFS,HLOS,UNUSED几个部分,SHARED IMEM可以用来在sbl1,lk,kernel之间传递共享数据,BOOT SHARED IMEM的地址和大小如下:

#define SHARED_IMEM_BOOT_BASE       (0xFE805000)

#define SHARED_IMEM_BOOT_SIZE        (0xC8)

 

1)boot_shared_imem_cookie_ptr指向boot shared imem的首地址,其结构如下:

structboot_shared_imem_cookie_type

{

  uint32 dload_magic_1;          /* 这两个魔数用于检测是否要进入dload模式 */

  uint32 dload_magic_2;

 

  uint32 shared_imem_magic;  /* 这个魔数表示shared imem是否已经初始化(0xC1F8DB40) */

 

  uint32 uefi_ram_dump_magic;

 

  uint32 etb_buf_addr;             /* 指向ramdump buffer,在kernel中执行初始化 */

 

  uint32 *l2_cache_dump_buff_ptr;

 

  uint32 ddr_training_cookie;

 

  uint32 rpm_sync_cookie;

 

  uint32 abnormal_reset_occurred;

 

  uint32 reset_status_register;

 

/ * 下面可添加新的cookie,但是不要改变已经存在的cookies的顺序 */

};

 

2)检查dload_magic值,决定是否进入dload模式:

boot_dload_check()

-> boot_dload_entry()        // 检测Magic Number

  -> if ( boot_shared_imem_cookie_ptr !=NULL &&

      boot_shared_imem_cookie_ptr->dload_magic_1 == SBL_DLOAD_MAGIC_NUM_1&&

       boot_shared_imem_cookie_ptr->dload_magic_2== SBL_DLOAD_MAGIC_NUM_2 )

          return TRUE;

7. 解析PBL共享数据

 sbl1_main_ctl()函数只有一个参数pbl_shared,这是一个指针,指向pbl共享数据结构,在sbl1中使用sbl1_retrieve_shared_info_from_pbl(pbl_shared)解析pbl共享数据,将数据拷贝到sbl1的地址空间,下面我们先看看在解析过程中常用的几个数据结构:

1)PBL共享数据结构

typedef structboot_pbl_shared_data_type

{

  /* Fields below are filled in byinitialization function */

  uint32        pbl_version;

  uint32        *pbl_page_tbl_base;

  uint32        pbl_page_tbl_size;

  uint8          *boot_stack_base;

  uint32        boot_stack_size;

 

  /* The region of memory required by PBLshared data. */

  uint8          *shared_section_base;

  uint32        shared_section_size;

 

  uint32        pbl_enter_timestamp;

  uint32        pbl_exit_timestamp;

 

  /* Apps proc clock speed set up in PBL */

  uint32        proc_clk_speed;

 

  /* Fields below are filled in by flashmodule. This is a pointer that points to a structure in PBL

* scratch memory. SBL needs to make its own deepcopy of this structure */

  boot_flash_shared_dev_info_type     *flash_shared_data;

 

  /* Fields below are filled in by auth module*/

  pbl_secboot_shared_info_type        *secboot_shared_data;

  /* Fields below are filled in by loadermodule. */

  boot_sbl_header_type               *sbl_hdr;

 

  /* Pointer to base of indirect vector table*/

  uint32                              *pbl_indirect_vec_tbl_base;

 

  /* Pointer to RPM PBL / APPs PBL shared data*/

  boot_rpm_apps_shared_data_type    *rpm_apps_shared_data;

}boot_pbl_shared_data_type;

 

2)SBL共享数据结构

typedef structboot_sbl_if_shared_info_type

{

  /* Pointer to data structure passed byPBL                 */

  boot_pbl_shared_data_type              *pbl_shared_data;

  /* Pointer to system partition table                       */

  void                                  *sys_partition_pointer;   

 

  /* Pointer to RPM PBL / APPs PBL shared data */

  boot_rpm_apps_shared_data_type        *rpm_apps_shared_data;

 

  /* Pointer to DDR info */

  sbl_if_shared_ddr_device_info_type             *ddr_shared_info;

  /* Pointer to the boot logger's meta infostructure*/

  void                                   *boot_logger_meta_info;

  /*pointer to the configuration data tableinfo structure*/

  void                                  *config_data_table_info;

  /*pointer to sdcc device information*/

  void                                  *sdcc_boot_device_info;

  /* Rollback prevention version information */

  uint32 failsafe_image_max_version;

  uint32 non_failsafe_image_max_version;

 

  /* Pointer pointing to next availablelocation to store image hash block. */

  uint32 *next_avail_tpm_hash_blk_ptr;

  

  /* Pointer to the base of L1 page table */

  uint32 *mmu_l1_pagetable_base;

 

}boot_sbl_if_shared_info_type;

 

3)Bootloader共享数据结构

typedef structbl_shared_data_type

  /* Data shared from previous SBL */

  struct boot_sbl_if_shared_info_type         *sbl_shared_data;

 

  /* Pointer to next stage of bootloaderprocess */

  sbl_exit_ptr_type                           exit_ptr;

 

  /* Target-specific shared data structure, ifany */

  struct bl_shared_data_target_type           *target;

 

} bl_shared_data_type;

 

4)把pbl共享数据拷贝到sbl1的地址空间

sbl1_retrieve_shared_info_from_pbl(pbl_shared);

-> qmemcpy(&sbl1_pbl_shared_data, pbl_shared, sizeof(sbl1_pbl_shared_data) );   

-> sbl1_shared_data.pbl_shared_data= &sbl1_pbl_shared_data;

-> bl_shared_data.sbl_shared_data= &sbl1_shared_data;

8. 硬件初始化

 sbl1_hw_init()主要是针对PMIC,执行一系列的检查和初始化操作,pm_device_init()是主函数,其定义在pm_sbl_boot.c,包括如下操作:

1)pm_validate_pon

  检查是否插USB或DC 触发的冷启动,如果是的话,检查USB或DC输入电压,是否低压(UV)或过压(OV),电压在范围内的话,执行启动,否则关机;

 

2)pm_version_detect

  查询PMIC版本信息;

 

3)pm_pon_init

  在pm_pon.c的开头位置定义了一堆reset相关的寄存器,如pon_kpdpwr_reg,pon_resin_reg,pon_ps_hold_reg等,pm_pon_init就是根据PMIC的版本信息修正这些寄存器的值;

 

4)pm_pwr_key_detected

  检查按键事件;

 

5)pm_sbl_config

为sbl1配置PMIC寄存器,pm_sbl_seq对的定义在pm_config_target_sbl_sequence.c,如下:

pm_sbl_seq [ ] =

{

   // MODE - DUMMY: 1

   //sid data  base_addr  offset reg_op  rev_id_op  rev_id

   { 0,    0x51,     0x100,   0x004,   PM_SBL_WRITE,       EQUAL, REV_ID_COMMON},  //1    

   { 4,    0x51,     0x100,   0x004,   PM_SBL_WRITE,       EQUAL, REV_ID_COMMON},  //2    

  

   // MODE - WATCHDOG_EN: 2

   //sid data  base_addr  offset reg_op  rev_id_op  rev_id

   { 0,    0x01,     0x800,   0x058,   PM_SBL_WRITE,       GREATER_OR_EQUAL,    0x03000000},

   { 0,    0x00,     0x800,   0x057,   PM_SBL_WRITE,       GREATER_OR_EQUAL,    0x03000000},

   …

}

 

6)pm_device_post_init

  配置S1/S2 Timer及行为等;

9. 执行sbl1_config_table中定义的入口程序

 sbl1_config_table中定义了TZ,RPM,WDT,APPSBL等目标依赖的操作,可以是进入TZ执行初始化或跳转,或者通知RPM load FW;

 

boot_config_process_bl(&bl_shared_data,SBL1_IMG, sbl1_config_table);

-> boot_do_procedures(boot_config_entry->pre_procs);   //执行pre_procs函数列表

-> boot_load_elf_image();                                                        // 加载 elf image

-> (boot_config_entry->exec_func)(bl_shared_data);        // 执行exec_func

-> boot_do_procedures(boot_config_entry->post_procs); // 执行post_procs函数列表

-> (boot_config_entry->jump_func)(bl_shared_data);        // 执行jump_func

10. TZ相关操作

TZ相关的操作包括进入TZ之前的准备工作,进入TZ并初始化执行环境,及从TZ退出以后的相关操作;

1)load_tz_pre_procs

a)初始化memory map

sbl1_populate_initial_mem_map();

memory map可以参考sbl_initial_memory_map结构体;

 

b)初始化eMMC flash设备

boot_flash_init()

-> boot_flash_target_init()

 

c)更新tz,rpm等image的partition id

boot_set_partition_id()

 

/*define GUID for TZ*/

struct hotplug_guidtz_partition_id =

     /*{A053AA7F-40B8-4B1C-BA08-2F68AC71A4F4}*/

      { 0xA053AA7F, 0x40B8, 0x4B1C, { 0xBA,0x08, 0x2F, 0x68, 0xAC, 0x71, 0xA4, 0xF4 } };

 

/*define GUID for RPM*/     

struct hotplug_guidrpm_partition_id =

     /*{098DF793-D712-413D-9D4E-89D711772228}*/

      { 0x098DF793, 0xD712, 0x413D, { 0x9D,0x4E, 0x89, 0xD7, 0x11, 0x77, 0x22, 0x28 } };

     

/*define GUID for wdogdebug image*/     

struct hotplug_guidwdt_partition_id =

     /*{D4E0D938-B7FA-48C1-9D21-BC5ED5C4B203}*/

      { 0xD4E0D938, 0xB7FA, 0x48C1, { 0x9D,0x21, 0xBC, 0x5E, 0xD5, 0xC4, 0xB2, 0x03 } };

     

/*define GUID for DDRparams partiton*/     

struct hotplug_guidddr_params_partition_id =

     /*{20A0C19C-286A-42FA-9CE7-F64C3226A794}*/

      { 0x20A0C19C, 0x286A, 0x42FA, { 0x9C,0xE7, 0xF6, 0x4C, 0x32, 0x26, 0xA7, 0x94 } };

 

/*define GUID foralternate APPSBL*/     

struct hotplug_guidappsbl_alt_partition_id =

      /*{C33D54D0-B1D2-4A2D-AC19-8A465FC99AFC}*/

      { 0xC33D54D0, 0xB1D2, 0x4A2D, { 0xAC,0x19, 0x8A, 0x46, 0x5F, 0xC9, 0x9A, 0xFC } };  

 

  下面的操作主要是解析CDTTable,并利用解析出来的参数执行初始化操作,CDTTable包括PlatformInfoDDRParameter信息:

d)初始化CDT Table

boot_config_data_table_init()

-> config_data_table_info.size= config_data_table_size;

-> config_data_table_info.cdt_ptr= config_data_table;

 

更新CDT Table:      

如果emmc或eeprom中找到cdt,则更新cdt table;

boot_update_config_data_table(&config_data_table_info);

-> boot_flash_configure_target_image(cdt_partition_id);    //Setup for load CDT image

-> boot_flash_dev_open_image(GEN_IMG);                      // Create flash translation i/f to copy image

-> boot_flash_trans_read(trans_if,cdt_buf, 0, sizeof(cdt_buf))                     // Read CDT header

-> ((structcdt_header *)cdt_buf)->magic != CONFIG_DATA_MAGIC             // 检查读到的数据是否是CDT

 

保存CDT Table:

bl_shared_data->sbl_shared_data->config_data_table_info= &config_data_table_info;

 

e)保存platform id

解析cdt table中的platform相关信息:

sbl1_hw_platform_pre_ddr()

 

f)配置ddr参数

解析cdt table中的DDR配置信息:

sbl1_ddr_set_params()

-> boot_ddr_set_params()

 

g)初始化DDR

sbl1_ddr_init()

-> boot_ddr_initialize_device()

-> HAL_SDRAM_Init()

  -> HAL_SDRAM_Ram_Size_Detection()              // 检测ddr大小

      ->HAL_SDRAM_Read_MR(interface, SDRAM_CS0, 0x5);   // 获取ddr厂商信息

         -> HAL_SDRAM_Read_MR(interface,SDRAM_CS1, 0x8); // 获取ddr大小信息

-> boot_ddr_test()      ;      // 运行ddr测试

 

h)重定位页表和sbl1_dload_entry

sbl1_post_ddr_data_init()

-> sbl1_relocate_page_table_to_ddr();   //重定位页表

-> sbl_dload_entry =sbl1_dload_entry;  // 更新dload entry,此后发生异常系统将进入Normal Download

 

默认情况下sbl1_dload_entry()会进入pbl emergency dload模式:

void(*sbl_dload_entry)(void) = boot_dload_transition_pbl_forced_dload;

 

更新入口点以后,sbl1_dload_entry()会进入sbl1 normal dload模式:

sbl_dload_entry =sbl1_dload_entry;

 

i)硬件初始化

sbl1_hw_init_secondary()

-> boot_pm_driver_init()

-> boot_pm_oem_init()

-> boot_dload_is_dload_mode_set()      //检测是否是dload mode

-> boot_pm_vib_on()               // 打开震动

-> boot_clock_init()            // 初始化clock

 

j)检测是否需要进入pbl edl模式

检测USB D+是否接地,如果接地则进入emergency dload模式

boot_check_for_pbl_dload()

 

2)tz_exec_func

退出bootloader,并进入tz执行环境:

bl_shared_data->exit_ptr= (sbl_exit_ptr_type) boot_get_elf_entry_address();     // 获取tz image入口点

 

((void(*)())(bl_shared_data->exit_ptr))          // 退出bootloader,进入tz

(bl_shared_data->sbl_shared_data->pbl_shared_data->secboot_shared_data,NULL);

 

3)load_tz_post_procs

检测是否需要进入dload模式

boot_dload_check()

-> boot_dload_entry()               // 检测是否需要进入dload模式

-> boot_enable_led(TRUE);      //如果需要,显示指示灯

-> sbl_dload_entry();                // 如果需要,进入dload模式

 

11. RPM相关操作

1)rpm_load_cancel

Dload模式则不加载rmp image:

return(boot_boolean)(boot_dload_is_dload_mode_set() == TRUE

 

2)load_rpm_pre_procs

重新初始化共享内存:

boot_cache_set_memory_barrier()

boot_smem_debug_init()

boot_smem_init()

 

3)load_rpm_post_procs

a)设置rpm入口点

boot_init_rpm_entry_addr()

 

b)通知rpm跳转到rpm fw

sbl1_notify_rpm_to_jump()

 

c)执行ddr检测

 

sbl1_wait_for_ddr_training()

sbl1_post_ddr_training_init()

 

d)在smem中保存pon status

boot_smem_store_pon_status()

 

e)初始化并配置GPIO

SBL1中的GPIO配置请参考:systemdrivers/tlmm/config/msm8974/TLMMChipset.xml

sbl1_tlmm_init()

 

f)在smem中保存platform id

sbl1_hw_platform_smem()

-> PlatformInfo_CDTConfigPostDDR()

  -> PlatformInfo_InitSMem()

    -> pSMem->ePlatformType =DALPLATFORMINFO_TYPE_MTP_MSM;

12. WDT相关操作

1)wdt_exec_func

退出bootloader,并进入tz执行环境:

bl_shared_data->exit_ptr= (sbl_exit_ptr_type) boot_get_elf_entry_address();     // 获取image入口点

 

((void(*)())(bl_shared_data->exit_ptr))          // 退出bootloader,进入wdt

(bl_shared_data->sbl_shared_data->pbl_shared_data->secboot_shared_data,NULL);

 

13. APPSBL相关操作

1)load_appsbl_post_procs

a)检查efs文件系统,执行备份或恢复功能

fsc,modemst1,modemst2及fsg分区使用efs文件系统;

sbl1_efs_handle_cookies()

 

b)等待RPM启动完成,并设置好相应的cookie信息

sbl1_rpm_sync()

 

c)烧写fuse

sbl1_update_sbl1_rollback_fuse()

sbl1_update_all_rollback_fuses()

sbl1_qfprom_test()

 

2)appsbl_jump_func

关闭振动器等:

boot_pm_vib_off();

sbl1_boot_logger_deinit()

sbl1_hw_deinit()

 

进入tz通知sbl1结束,并从tz跳转到appsbl:

sbl1_signal_tz_sbl_done()

-> boot_flash_configure_target_image(appsbl_partition_id);

-> boot_load_image_header(GEN_IMG,&appsbl_header);

-> boot_fastcall_tz_2arg(TZ_SBL_END_MILESTONE,

appsbl_header.image_dest_ptr,                        // appsbl入口点

(appsbl_header.image_size & 0x3FFFFFFF));  //image size

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值