首先在aboot.c里的
int boot_linux_from_mmc(void)
{
struct boot_img_hdr *hdr = (void*) buf;
#if DEVICE_TREE
struct dt_table *table;
struct dt_entry dt_entry;
unsigned dt_table_offset;
uint32_t dt_actual;
uint32_t dt_hdr_size;
unsigned char *best_match_dt_addr = NULL;
#endif
uhdr = (struct boot_img_hdr *)EMMC_BOOT_IMG_HEADER_ADDR;
if (!memcmp(uhdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
dprintf(INFO, "Unified boot method!\n");
hdr = uhdr;
goto unified_boot;
}
#if DEVICE_TREE
dt_actual = ROUND_TO_PAGE(hdr->dt_size, page_mask);
imagesize_actual = (page_size + kernel_actual + ramdisk_actual + dt_actual);
#endif
#ifndef DEVICE_TREE
if (check_aboot_addr_range_overlap(hdr->tags_addr, MAX_TAGS_SIZE))
{
dprintf(CRITICAL, "Tags addresses overlap with aboot addresses.\n");
return -1;
}
#endif
#if DEVICE_TREE
if(hdr->dt_size) {
dt_table_offset = ((uint32_t)image_addr + page_size + kernel_actual + ramdisk_actual + second_actual); //计算地址
table = (struct dt_table*) dt_table_offset;
if (dev_tree_validate(table, hdr->page_size, &dt_hdr_size) != 0) {
dprintf(CRITICAL, "ERROR: Cannot validate Device Tree Table \n");
return -1;
}
/* Find index of device tree within device tree table */
if(dev_tree_get_entry_info(table, &dt_entry) != 0){
dprintf(CRITICAL, "ERROR: Getting device tree address failed\n");
return -1;
}
if (is_gzip_package((unsigned char *)dt_table_offset + dt_entry.offset, dt_entry.size))
{
unsigned int compressed_size = 0;
out_addr += out_len;
out_avai_len -= out_len;
dprintf(SPEW, "decompress dtb start\n");
rc = decompress((unsigned char *)dt_table_offset + dt_entry.offset,
dt_entry.size, out_addr, out_avai_len,
&compressed_size, &dtb_size);
if (rc)
{
dprintf(CRITICAL, "decompress dtb failed!!!\n");
ASSERT(0);
}
dprintf(SPEW, "decompressed dtb finished.\n");
best_match_dt_addr = out_addr;
} else {
best_match_dt_addr = (unsigned char *)dt_table_offset + dt_entry.offset;
dtb_size = dt_entry.size;
}
/* Validate and Read device device tree in the tags_addr */
if (check_aboot_addr_range_overlap(hdr->tags_addr, dtb_size))
{
dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
return -1;
}
memmove((void *)hdr->tags_addr, (char *)best_match_dt_addr, dtb_size);
} else {
/* Validate the tags_addr */
if (check_aboot_addr_range_overlap(hdr->tags_addr, kernel_actual))
{
dprintf(CRITICAL, "Device tree addresses overlap with aboot addresses.\n");
return -1;
}
/*
* If appended dev tree is found, update the atags with
* memory address to the DTB appended location on RAM.
* Else update with the atags address in the kernel header
*/
void *dtb;
dtb = dev_tree_appended((void*)(image_addr + page_size),
hdr->kernel_size, dtb_offset,
(void *)hdr->tags_addr);
if (!dtb) {
dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
return -1;
}
}
#endif
再看其中的dev_tree.c
int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info)
{
uint32_t i;
unsigned char *table_ptr = NULL;
struct dt_entry dt_entry_buf_1;
struct dt_entry *cur_dt_entry = NULL;
struct dt_entry *best_match_dt_entry = NULL;
struct dt_entry_v1 *dt_entry_v1 = NULL;
struct dt_entry_v2 *dt_entry_v2 = NULL;
struct dt_entry_node *dt_entry_queue = NULL;
struct dt_entry_node *dt_node_tmp1 = NULL;
struct dt_entry_node *dt_node_tmp2 = NULL;
uint32_t found = 0;
if (!dt_entry_info) {
dprintf(CRITICAL, "ERROR: Bad parameter passed to %s \n",
__func__);
return -1;
}
table_ptr = (unsigned char *)table + DEV_TREE_HEADER_SIZE;
cur_dt_entry = &dt_entry_buf_1;
best_match_dt_entry = NULL;
dt_entry_queue = (struct dt_entry_node *)
malloc(sizeof(struct dt_entry_node));
if (!dt_entry_queue) {
dprintf(CRITICAL, "Out of memory\n");
return -1;
}
list_initialize(&dt_entry_queue->node);
dprintf(INFO, "DTB Total entry: %d, DTB version: %d\n", table->num_entries, table->version);
for(i = 0; found == 0 && i < table->num_entries; i++)
{
memset(cur_dt_entry, 0, sizeof(struct dt_entry));
switch(table->version) {
//这里主要完成对cur_dt_entry赋值
case DEV_TREE_VERSION_V1:
dt_entry_v1 = (struct dt_entry_v1 *)table_ptr;
cur_dt_entry->platform_id = dt_entry_v1->platform_id;
cur_dt_entry->variant_id = dt_entry_v1->variant_id;
cur_dt_entry->soc_rev = dt_entry_v1->soc_rev;
cur_dt_entry->board_hw_subtype = (dt_entry_v1->variant_id >> 0x18);
cur_dt_entry->pmic_rev[0] = board_pmic_target(0);
cur_dt_entry->pmic_rev[1] = board_pmic_target(1);
cur_dt_entry->pmic_rev[2] = board_pmic_target(2);
cur_dt_entry->pmic_rev[3] = board_pmic_target(3);
cur_dt_entry->offset = dt_entry_v1->offset;
cur_dt_entry->size = dt_entry_v1->size;
table_ptr += sizeof(struct dt_entry_v1);
break;
default:
dprintf(CRITICAL, "ERROR: Unsupported version (%d) in DT table \n",
table->version);
free(dt_entry_queue);
return -1;
}
/* DTBs must match the platform_id, platform_hw_id, platform_subtype and DDR size.
* The satisfactory DTBs are stored in dt_entry_queue
*/
platform_dt_absolute_match(cur_dt_entry, dt_entry_queue); //这里要进行匹配选择dtsi文件
}
best_match_dt_entry = platform_dt_match_best(dt_entry_queue);
if (best_match_dt_entry) {
*dt_entry_info = *best_match_dt_entry;
found = 1;
}
if (found != 0) {
dprintf(INFO, "Using DTB entry 0x%08x/%08x/0x%08x/%u for device 0x%08x/%08x/0x%08x/%u\n",
dt_entry_info->platform_id, dt_entry_info->soc_rev,
dt_entry_info->variant_id, dt_entry_info->board_hw_subtype,
board_platform_id(), board_soc_version(),
board_target_id(), board_hardware_subtype());
if (dt_entry_info->pmic_rev[0] == 0 && dt_entry_info->pmic_rev[0] == 0 &&
dt_entry_info->pmic_rev[0] == 0 && dt_entry_info->pmic_rev[0] == 0) {
dprintf(SPEW, "No maintain pmic info in DTB, device pmic info is 0x%0x/0x%x/0x%x/0x%0x\n",
board_pmic_target(0), board_pmic_target(1),
board_pmic_target(2), board_pmic_target(3));
} else {
dprintf(INFO, "Using pmic info 0x%0x/0x%x/0x%x/0x%0x for device 0x%0x/0x%x/0x%x/0x%0x\n",
dt_entry_info->pmic_rev[0], dt_entry_info->pmic_rev[1],
dt_entry_info->pmic_rev[2], dt_entry_info->pmic_rev[3],
board_pmic_target(0), board_pmic_target(1),
board_pmic_target(2), board_pmic_target(3));
}
return 0;
}
dprintf(CRITICAL, "ERROR: Unable to find suitable device tree for device (%u/0x%08x/0x%08x/%u)\n",
board_platform_id(), board_soc_version(),
board_target_id(), board_hardware_subtype());
list_for_every_entry(&dt_entry_queue->node, dt_node_tmp1, dt_node, node) {
/* free node memory */
dt_node_tmp2 = dt_node_tmp1->node.prev;
dt_entry_list_delete(dt_node_tmp1);
dt_node_tmp1 = dt_node_tmp2;
}
free(dt_entry_queue);
return -1;
}
再看
static int platform_dt_absolute_match(struct dt_entry *cur_dt_entry, struct dt_entry_node *dt_list)
{
uint32_t cur_dt_hlos_ddr;
uint32_t cur_dt_hw_platform;
uint32_t cur_dt_hw_subtype;
uint32_t cur_dt_msm_id;
dt_node *dt_node_tmp = NULL;
/* Platform-id
* bit no |31 24|23 16|15 0|
* |reserved|foundry-id|msm-id|
*/
cur_dt_msm_id = (cur_dt_entry->platform_id & 0x0000ffff);
cur_dt_hw_platform = (cur_dt_entry->variant_id & 0x000000ff);
cur_dt_hw_subtype = (cur_dt_entry->board_hw_subtype & 0xff);
/* Determine the bits 10:8 to check the DT with the DDR Size */
cur_dt_hlos_ddr = (cur_dt_entry->board_hw_subtype & 0x700);
/* 1. must match the msm_id, platform_hw_id, platform_subtype and DDR size
* soc, board major/minor, pmic major/minor must less than board info
* 2. find the matched DTB then return 1
* 3. otherwise return 0
*/
if((cur_dt_msm_id == (board_platform_id() & 0x0000ffff)) &&
//(cur_dt_hw_platform == board_hardware_id()) &&
(cur_dt_hw_platform == g_ASUS_DT_ID) && //通常都是这个地方来修改,如果你要选择的话,可以在别的地方定义好g_ASUS_DT_ID ,比如下面的
switch(ASUS_PRJ_ID)
{
case PRJ_ZC552KL:
ASUS_DT_ID = ZC552KL_DT;
break;
case PRJ_ZD552KL:
ASUS_DT_ID = ZD552KL_DT;
break;
case PRJ_ZS550KL:
ASUS_DT_ID = ZS550KL_DT;
break;
default:
dprintf(INFO,"[ERROR] NO This Project ID!!\n");
break;
}
//这样,可以选择其中一个dtsi文件,根据之前的文章的dts文件里的qcom,board-id= <21 0>来匹配
(cur_dt_hw_subtype == board_hardware_subtype()) &&
(cur_dt_hlos_ddr == (target_get_hlos_subtype() & 0x700)) &&
(cur_dt_entry->soc_rev <= board_soc_version()) &&
((cur_dt_entry->variant_id & 0x00ffff00) <= (board_target_id() & 0x00ffff00)) &&
((cur_dt_entry->pmic_rev[0] & 0x00ffff00) <= (board_pmic_target(0) & 0x00ffff00)) &&
((cur_dt_entry->pmic_rev[1] & 0x00ffff00) <= (board_pmic_target(1) & 0x00ffff00)) &&
((cur_dt_entry->pmic_rev[2] & 0x00ffff00) <= (board_pmic_target(2) & 0x00ffff00)) &&
((cur_dt_entry->pmic_rev[3] & 0x00ffff00) <= (board_pmic_target(3) & 0x00ffff00))) {
dt_node_tmp = dt_entry_list_init();
memcpy((char*)dt_node_tmp->dt_entry_m,(char*)cur_dt_entry, sizeof(struct dt_entry));
dprintf(CRITICAL, "select device tree id(%d). \n",g_ASUS_DT_ID);
dprintf(SPEW, "Add DTB entry %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
dt_node_tmp->dt_entry_m->platform_id, dt_node_tmp->dt_entry_m->variant_id,
dt_node_tmp->dt_entry_m->board_hw_subtype, dt_node_tmp->dt_entry_m->soc_rev,
dt_node_tmp->dt_entry_m->pmic_rev[0], dt_node_tmp->dt_entry_m->pmic_rev[1],
dt_node_tmp->dt_entry_m->pmic_rev[2], dt_node_tmp->dt_entry_m->pmic_rev[3],
dt_node_tmp->dt_entry_m->offset, dt_node_tmp->dt_entry_m->size);
insert_dt_entry_in_queue(dt_list, dt_node_tmp);
return 1;
}
return 0;
}