在上一篇博文中主要描述了启动流程,及代码执行流程,并重点介绍了一下我重点关注的部分。这个sbl部分也算有点庞大,我们没有精力也没有必要去分析全部,所以接下来就来分析一下sbl1中另外几个需要格外关注的部分:
1 |
boot_images\core\boot\secboot3\hw\msm8916\boot_cdt_array.c // config_data_table配置表定义 |
对于CDT,boot程序主要有如下动作:
#sbl1
boot_updat_config_data_table(boot_images\core\boot\secboot3\src\boot_config_emmc.c)
#lk
dev_tree_get_entry_info(bootable\bootloader\lk\platform\msm_shared\dev_tree.c)
#boot_images\core\api\systemdrivers\DDIChipInfo.h
DALCHIPINFO_ID_APQ8026 = 199,
DALCHIPINFO_ID_MSM8926 = 200,
DALCHIPINFO_ID_MSM8326 = 205,
DALCHIPINFO_ID_MSM8916 = 206,
DALCHIPINFO_ID_MSM8994 = 207,
#boot_images\core\api\systemdrivers\PlatformInfoDefs.h
DALPLATFORMINFO_TYPE_SURF = 0x01, /**< Target is a SURF device. */
DALPLATFORMINFO_TYPE_CDP = DALPLATFORMINFO_TYPE_SURF, /**< Target is a CDP (aka SURF) device. */
DALPLATFORMINFO_TYPE_MTP_MSM = 0x08, /**< Target is a MSM MTP device. */
DALPLATFORMINFO_TYPE_QRD = 0x0B, /**< Target is a QRD device. */
#kernel\arch\arm\boot\dts\qcom\msm8916-cdp.dts
/ {
model = "Qualcomm Technologies, Inc. MSM 8916 CDP";
compatible = "qcom,msm8916-cdp", "qcom,msm8916", "qcom,cdp";
qcom,board-id = <1 0>;// id为0x01则为cdp设备,与下cdt描述xml中对应
};
#kernel\arch\arm\boot\dts\qcom\msm8916-mtp.dts
/ {
model = "Qualcomm Technologies, Inc. MSM 8916 MTP";
compatible = "qcom,msm8916-mtp", "qcom,msm8916", "qcom, mtp";
qcom,board-id = <8 0>; // id为0x08则为mtp设备
};
#kernel\arch\arm\boot\dts\qcom\msm8916-qrd.dts
/ {
model = "Qualcomm Technologies, Inc. MSM 8916 QRD";
compatible = "qcom,msm8916-qrd", "qcom,msm8916", "qcom, qrd";
qcom,board-id = <11 0>; // id为0x0b则为qrd设备
};
dt.img的格式,参考dtbtool.txt和bootable\bootloader\lk\platform\msm_shared\smem.h
#boot_images\core\boot\secboot3\scripts\jedec_lpddr3_single_channel.xml
<device id="cdb0">
<props name="platform_id" type="DALPROP_ATTR_TYPE_BYTE_SEQ">
/*byte0 - platform id版本
byte1 - platform id,因此此为mtp设备
byte2 - platform id硬件版本*/
0x03, 0x08, 0x01, 0x00, 0x00, 0x00, end
</props>
</device>
...
上述xml中设备对应的结构体包如下:
typedef PACKED struct
{
uint8 nVersion;
uint8 nPlatform; //平台id,用于高通不同平台,不能修改。
uint8 nHWVersionMajor; //硬件版本号
uint8 nHWVersionMinor;
uint8 nSubtype; // 默认为0,可以用来区分项目
uint8 nNumKVPS;
PlatformInfoKVPSCDTType aKVPS[];
} PlatformInfoCDTType;
在上一篇博文分析的sbl执行流程中,有两个和platform info有关的两个关键函数,如下:
此函数主要初始化配置数据表,如果eeprom/emmc中存在cdt,则更新编译时链入的cdt表。
#boot_images\core\boot\secboot3\src\boot_config_data.c
void boot_config_data_table_init(bl_shared_data_type* bl_shared_data)
{
char bootlog_buffer[BOOT_LOG_TEMP_BUFFER_SIZE];
uint32 bytes_read = 0;
/* Reset the flash byte counter so the number of bytes read from flash
can be retreived later. */
boot_statistics_reset_flash_byte_counter();
boot_log_message("boot_config_data_table_init, Start");
boot_log_start_timer();
/*populate configuration data table's info*/
config_data_table_info.size = config_data_table_size;
config_data_table_info.cdt_ptr = config_data_table; // 定义在boot_cdt_array.c
boot_update_config_data_table(&config_data_table_info);
/*put a pointer to the table info into sbl shared data so next sbl can access it*/
bl_shared_data->sbl_shared_data->config_data_table_info = &config_data_table_info;
/* Retreive the number of bytes read from flash via boot statistics. */
bytes_read = boot_statistics_get_flash_byte_counter();
/* Convert CDT size to string for boot logger. */
snprintf(bootlog_buffer,
BOOT_LOG_TEMP_BUFFER_SIZE,
"(%d Bytes)",
bytes_read);
boot_log_stop_timer_optional_data("boot_config_data_table_init, Delta",
bootlog_buffer);
}
config_data_table定义了与上xml文件对应的配置表,存储在memory,用于初始化cdt,如此表存在则此表数据为最终数据。源码如下:
# boot_images\core\boot\secboot3\hw\msm8916\boot_cdt_array.c
uint8 config_data_table[CONFIG_DATA_TABLE_MAX_SIZE] =
{
/* Header */
0x43, 0x44, 0x54, 0x00,
0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00,
/* Meta data */
0x16, 0x00, 0x06, 0x00,
0x1C, 0x00, 0x88, 0x01,
/* Block data */
#ifdef BOOT_PRE_SILICON
#ifdef FEATURE_RUMI_BOOT
0x03, 0x0F, 0x01, 0x00, 0x00, 0x00,
#else
0x03, 0x10, 0x01, 0x00, 0x00, 0x00,
#endif
#else
0x03, 0x0B, 0x01, 0x00, 0x00, 0x00,// platform id 等信息
#endif
....
uint32 config_data_table_size = 420; // cdt表size
此函数主要解析cdt表获得sw-platform id,调用platform id api并传送指针到获得的id,然后调用hw_init_smem存储platform id到SMEM。
#boot_images\core\boot\secboot3\hw\msm8909\sbl1\sbl1_mc.c
void sbl1_hw_platform_smem(bl_shared_data_type* bl_shared_data)
{
.......
struct cdt_info *cdt_info_ptr = (struct cdt_info *)
bl_shared_data->sbl_shared_data->config_data_table_info;
/*get a pointer to platform id data from configuration data table*/
platform_id_cdb_ptr =
boot_get_config_data_block(cdt_info_ptr->cdt_ptr,
CONFIG_DATA_BLOCK_INDEX_V1_PLATFORM_ID,
&platform_id_len);
if(platform_id_cdb_ptr != NULL)
{
eResult = boot_DAL_DeviceAttachEx(NULL,
DALDEVICEID_PLATFORMINFO,
DALPLATFORMINFO_INTERFACE_VERSION,
&phPlatform);
if (eResult == DAL_SUCCESS)
{
/*call the following API to store the platform id to DAL and SMEM*/
boot_DalPlatformInfo_CDTConfigPostDDR(phPlatform, platform_id_cdb_ptr);
boot_DAL_DeviceDetach(phPlatform);
}
}
}
platform info中的platform id十分重要,lk、kernel中dts都是根据platform id及subtype id等platform info来匹配的。lk和kernel中涉及到的主要函数和代码路径如下:
#lk
/*ootable\bootloader\lk\platform\msm_shared\smem.h */
enum platform_subtype
/*bootable\bootloader\lk\platform\msm_shared\board.c */
static void platform_detect()
uint32_t board_hardware_subtype(void)
uint32_t board_hardware_id()
/*bootable\bootloader\lk\platform\msm_shared\dev_tree.c*/
int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info)
#kernel
kernel\arch\arm\kernel\setup.c
kernel\arch\arm\boot\dts\qcom
当我们在项目开发时就可以同cdt这些信息来配置不同项目,如下:
-------------------------------------------------------------
sbl1 platform subtype_id boot_cdt_array.c
-------------------------------------------------------------
lk 匹配dts dev_tree.c
-------------------------------------------------------------
kernel 通过传入dts地址创建设备 setup.c
-------------------------------------------------------------
ddr相关的东西我很少动, 也就不深入分析了,列出几个关键函数,如果需要深入了解的话再分析。ddr初始化主要涉及3个函数,见如下load_qsee_pre_procs函数指针数组:
boot_procedure_func_type load_qsee_pre_procs[] =
{
/* Save reset register logs */
boot_save_reset_register_log,
/* Initialize the flash device */
boot_flash_init,
/* Copy the configure data table from eeprom */
boot_config_data_table_init, // 函数一 : 加载配置表
/* Store platform id */
sbl1_hw_platform_pre_ddr,
/* Configure ddr parameters based on eeprom CDT table data. */
sbl1_ddr_set_params, // 函数二:配置ddr
/* Initialize DDR */
(boot_procedure_func_type)sbl1_ddr_init, // 函数三:初始化ddr
/*----------------------------------------------------------------------
Run deviceprogrammer if compiling the deviceprogrammer_ddr image.
----------------------------------------------------------------------*/
boot_deviceprogrammer_ddr_main,
/* Initialize SBL1 DDR ZI region, relocate boot log to DDR */
sbl1_post_ddr_init,
sbl1_hw_init_secondary,
/* DDR training */
(boot_procedure_func_type)sbl1_wait_for_ddr_training,
/* Initialize SBL1 DDR ZI region, relocate page table to DDR */
sbl1_post_ddr_training_init,
/* Zero out QSEE and QHEE region if needed. This MUST be done before
boot_dload_dump_security_regions executes for security reasons. */
sbl1_cleanse_security_regions,
/* Backup QSEE and QHEE region for ramdumps taken after SBL has executed */
boot_dload_dump_security_regions,
/* Check to see if DLOAD mode needs to be entered */
boot_dload_check,
/* Last entry in the table. */
NULL
};