高通平臺dtb文件的加載過程

高通平臺對dts的兩種打包方式

zImage-dtb

直接和kernel編譯在一起,生成zImage-dtb,dtb的位置在kernel起始地址偏移0x2C的位置,然後和kernel一起打包到bootimage裏。

dt.img

獨立編譯出dt.img, 然後打包到bootimage裏。

zImage-dtb方式

zImage-dtb的編譯

dtb怎麼編譯進bootimage的?
makefile文件分析

.config 文件裏生成的內容如下

CONFIG_ARCH_MSM8916=y

CONFIG_ARCH_MSM8937=y

CONFIG_ARCH_MSM8917=y

CONFIG_ARCH_MSM8920=y

CONFIG_ARCH_MSM8940=y

CONFIG_ARCH_MSM8953=y

kernel/msm-3.18/arch/arm/boot/dts/qcom/Makefile

(只要這些arch定義了 這些dtb文件都會被包含進去)

dtb-$(CONFIG_ARCH_MDMCALIFORNIUM) += mdmcalifornium-sim.dtb \

mdmcalifornium-rumi.dtb \

mdmcalifornium-v1.1-nand-mtp.dtb \

mdmcalifornium-v1.1-nand-dualwifi-mtp.dtb



dtb-$(CONFIG_ARCH_MSM8937) += msm8937-rumi.dtb \

msm8937-pmi8950-cdp.dtb \

.......

apq8037-pmi8950-mtp.dtb \

apq8037-pmi8937-mtp.dtb



dtb-$(CONFIG_ARCH_MSM8917) += msm8917-rumi.dtb \

apq8017-pmi8937-cdp.dtb \

msm8917-qgp-tmo.dtb \

msm8917-pmi8937-qrd-sku5.dtb

.config 文件裏生成的內容如下

CONFIG_USE_OF=y

CONFIG_ATAGS=y

# CONFIG_DEPRECATED_PARAM_STRUCT is not set

CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=y

CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES=

kernel/msm-3.18/arch/arm/boot/Makefile

DTB_NAMES := $(subst $\",,$(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES))

ifneq ($(DTB_NAMES),)

DTB_LIST := $(addsuffix .dtb,$(DTB_NAMES))

else

DTB_LIST := $(dtb-y)

endif

DTB_OBJS := $(addprefix $(obj)/dts/qcom/,$(DTB_LIST))

因爲CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE_NAMES 這個爲空,

所以

DTB_LIST := $(dtb-y)

DTB_OBJS := $(obj)/dts/qcom/$(dtb-y)

需要編譯zImage-dtb

# Default target when executing plain make

ifeq ($(CONFIG_XIP_KERNEL),y)
KBUILD_IMAGE := xipImage

else ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y)

KBUILD_IMAGE := zImage-dtb

else

KBUILD_IMAGE := zImage

endif



$(obj)/Image: vmlinux FORCE

$(call if_changed,objcopy)

@$(kecho) ' Kernel: $@ is ready'



$(obj)/compressed/vmlinux: $(obj)/Image FORCE

$(Q)$(MAKE) $(build)=$(obj)/compressed $@



$(obj)/zImage: $(obj)/compressed/vmlinux FORCE

$(call if_changed,objcopy)

@$(kecho) ' Kernel: $@ is ready'



$(obj)/zImage-dtb: $(obj)/zImage $(DTB_OBJS) FORCE

$(call if_changed,cat)

@echo ' Kernel: $@ is ready'

可以看出zImage-dtb 依賴於 $(obj)/zImage $(DTB_OBJS)

%.dtb: | scripts

$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) $(boot)/dts/$@



dtbs: scripts

$(Q)$(MAKE) $(build)=$(boot)/dts MACHINE=$(MACHINE) dtbs

$(foreach DIR, $(DTSSUBDIR), $(Q)$(MAKE) $(build)=$(boot)/dts/$(DIR) MACHINE=$(MACHINE) dtbs)



zImage-dtb: vmlinux scripts dtbs

$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) DTSSUBDIR=$(DTSSUBDIR) $(boot)/$@

二進制文件查看

查看kernel的二進制文件,查看0x2C位置的值,此處存放的值是第一個dtb文件的偏移地址
kernel偏移0x2C的值
從圖中可以看出dtb所在的地址爲0x008e7db0 + 0x800 = 0x008e85b0
在這裏插入圖片描述
0x008e85b0地址可以看到magic 0xd00dfeed(大端)

0x008e85b0 + 0x0002bef5 = 0x009144A5爲下一個dtb的起始地址
在這裏插入圖片描述
0x009144A5地址可以看到新的dtb開始,看到magic 0xd00dfeed(大端)

lk的加載過程代碼分析

app\aboot\aboot.c

boot_linux_from_mmc
dt_size = hdr->dt_size;
if(dt_size) {

}else{
dtb = dev_tree_appended()
}

void *dev_tree_appended(void *kernel, uint32_t kernel_size, uint32_t dtb_offset, void *tags)
{
	if (dtb_offset)
		app_dtb_offset = dtb_offset;
	else
		memcpy((void*) &app_dtb_offset, (void*) (kernel + DTB_OFFSET), sizeof(uint32_t));	
		....
			while (((uintptr_t)dtb + sizeof(struct fdt_header)) < (uintptr_t)kernel_end) {
		struct fdt_header dtb_hdr;
		uint32_t dtb_size;

		/* the DTB could be unaligned, so extract the header,
		 * and operate on it separately */
		memcpy(&dtb_hdr, dtb, sizeof(struct fdt_header));
		if (fdt_check_header((const void *)&dtb_hdr) != 0 ||
		    fdt_check_header_ext((const void *)&dtb_hdr) != 0 ||
		    ((uintptr_t)dtb + (uintptr_t)fdt_totalsize((const void *)&dtb_hdr) < (uintptr_t)dtb) ||
			((uintptr_t)dtb + (uintptr_t)fdt_totalsize((const void *)&dtb_hdr) > (uintptr_t)kernel_end))
			break;
		dtb_size = fdt_totalsize(&dtb_hdr);

		dev_tree_compatible(dtb, dtb_size, dt_entry_queue);

		/* goto the next device tree if any */
		dtb += dtb_size;
	}

	best_match_dt_entry = platform_dt_match_best(dt_entry_queue);
	if (best_match_dt_entry){
		bestmatch_tag = (void *)best_match_dt_entry->offset;
		bestmatch_tag_size = best_match_dt_entry->size;
		dprintf(INFO, "Best match DTB tags %u/%08x/0x%08x/%x/%x/%x/%x/%x/%x/%x\n",
			best_match_dt_entry->platform_id, best_match_dt_entry->variant_id,
			best_match_dt_entry->board_hw_subtype, best_match_dt_entry->soc_rev,
			best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
			best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
			best_match_dt_entry->offset, best_match_dt_entry->size);
		dprintf(INFO, "Using pmic info 0x%0x/0x%x/0x%x/0x%0x for device 0x%0x/0x%x/0x%x/0x%0x\n",
			best_match_dt_entry->pmic_rev[0], best_match_dt_entry->pmic_rev[1],
			best_match_dt_entry->pmic_rev[2], best_match_dt_entry->pmic_rev[3],
			board_pmic_target(0), board_pmic_target(1),
			board_pmic_target(2), board_pmic_target(3));
	}
	.......................
	return NULL;
}

其中DTB_OFFSET的定義爲0x2C,與上一節的圖相對應。
根據偏移值找到dtb的位置,然後對每個dtb進行解析,找到最匹配的那個dtb,這個是有dev_tree_compatible(dtb, dtb_size, dt_entry_queue);函數來實現的。

dev_tree_compatible(void *dtb, uint32_t dtb_size, struct dt_entry_node *dtb_list)
platform_dt_absolute_match(cur_dt_entry, dtb_list)

dev_tree_compatible會調用platform_dt_absolute_match來判斷

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_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(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;
}

board_platform_id() board_hardware_id() board_hardware_subtype() target_get_hlos_subtype() board_soc_version()board_target_id()
幾乎都來自board結構體

struct board_data {
	uint32_t platform;  //board_platform_id
	uint32_t foundry_id;
	uint32_t chip_serial;
	uint32_t platform_version;//board_soc_version
	uint32_t platform_hw;//board_hardware_id()
	uint32_t platform_subtype;//board_hardware_subtype
	uint32_t target;//board_target_id()
	uint32_t baseband;
	struct board_pmic_data pmic_info[MAX_PMIC_DEVICES];
	uint32_t platform_hlos_subtype;//target_get_hlos_subtype即board_hlos_subtype
	uint32_t num_pmics;
	uint32_t pmic_array_offset;
	struct board_pmic_data *pmic_info_array;
};

board在platform\msm_shared\board.c 文件裏賦值
board_init()
platform_detect()

			board.platform = board_info_v11.board_info_v3.msm_id;
			board.platform_version = board_info_v11.board_info_v3.msm_version;
			board.platform_hw = board_info_v11.board_info_v3.hw_platform;
			board.platform_subtype = board_info_v11.platform_subtype;
			/*
			 * fill in board.target with variant_id information
			 * bit no         |31  24 |23             16|15              8|7         0|
			 * board.target = |subtype|plat_hw_ver major|plat_hw_ver minor|hw_platform|
			 *
			 */

			board.target = (((board_info_v11.platform_subtype & 0xff) << 24) |
						   (((board_info_v11.platform_version >> 16) & 0xff) << 16) |
						   ((board_info_v11.platform_version & 0xff) << 8) |
						   (board_info_v11.board_info_v3.hw_platform & 0xff));

			board.foundry_id = board_info_v11.foundry_id;
			board.chip_serial = board_info_v11.chip_serial;
			board.num_pmics = board_info_v11.num_pmics;
			board.pmic_array_offset = board_info_v11.pmic_array_offset;
		}

		/* HLOS subtype
		 * bit no                        |31    20 | 19        16|15    13 |12      11 | 10          8 | 7     0|
		 * board.platform_hlos_subtype = |reserved | Boot device |Reserved | Panel     | DDR detection | subtype|
		 *                               |  bits   |             |  bits   | Detection |
		 */
		board.platform_hlos_subtype = (board_get_ddr_subtype() << 8) | (platform_get_boot_dev() << 16) | (platform_detect_panel() << 11);

根據代碼裏給的註釋,從smem裏獲得

platform_dt_absolute_match過程

static int platform_dt_absolute_match(struct dt_entry *cur_dt_entry, struct dt_entry_node *dt_list)
{
	/* 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_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));
		... ...
}

對比之前需要從dts裏將信息提取出來,主要是通過讀取三個屬性值然後提取

pmic_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,pmic-id", &len_pmic_id);
board_prop = (const char *)fdt_getprop(dtb, root_offset, "qcom,board-id", &len_board_id);

plat_prop = (const char *)fdt_getprop(dtb, root_offset, “qcom,msm-id”, &len_plat_id);

		board_data[i].variant_id = fdt32_to_cpu(((struct board_id *)board_prop)->variant_id);
		board_data[i].platform_subtype = fdt32_to_cpu(((struct board_id *)board_prop)->platform_subtype);
		dt_entry_array[k].board_hw_subtype = board_data[j].platform_subtype;
		platform_data[i].platform_id = fdt32_to_cpu(((struct plat_id *)plat_prop)->platform_id);
		platform_data[i].soc_rev = fdt32_to_cpu(((struct plat_id *)plat_prop)->soc_rev);
			pmic_data[i].pmic_version[0]= fdt32_to_cpu(((struct pmic_id *)pmic_prop)->pmic_version[0]);
			pmic_data[i].pmic_version[1]= fdt32_to_cpu(((struct pmic_id *)pmic_prop)->pmic_version[1]);
			pmic_data[i].pmic_version[2]= fdt32_to_cpu(((struct pmic_id *)pmic_prop)->pmic_version[2]);
			pmic_data[i].pmic_version[3]= fdt32_to_cpu(((struct pmic_id *)pmic_prop)->pmic_version[3]);

must match the msm_id, platform_hw_id, platform_subtype and DDR size
可見 msm_id, platform_hw_platform, platform_subtype and DDR size 這幾個需要完全匹配纔可以
cur_dt_msm_id = (cur_dt_entry->platform_id & 0x0000ffff);
來自"qcom,msm-id"

platform_hw_platform = (cur_dt_entry->variant_id & 0x000000ff);
來自 "qcom,board-id"

cur_dt_hw_subtype = (cur_dt_entry->board_hw_subtype & 0xff);
同樣來自 "qcom,board-id"

總之,最終會找到一個最合適的dtb,也有可能因爲配置不對找不到匹配的dtb文件。

由此可見,在dtb未匹配時,需要修改sbl裏的id,或者同步修改dts裏的board id,讓兩者匹配纔可以。

dt.img方式

dt.img的編譯

device\qcom\common\generate_extra_images.mk

#----------------------------------------------------------------------
# Generate device tree image (dt.img)
#----------------------------------------------------------------------
ifneq ($(strip $(TARGET_NO_KERNEL)),true)
ifeq ($(strip $(BOARD_KERNEL_SEPARATED_DT)),true)
ifeq ($(strip $(BUILD_TINY_ANDROID)),true)
include device/qcom/common/dtbtool/Android.mk
endif

DTBTOOL := $(HOST_OUT_EXECUTABLES)/dtbTool$(HOST_EXECUTABLE_SUFFIX)

INSTALLED_DTIMAGE_TARGET := $(PRODUCT_OUT)/dt.img

possible_dtb_dirs = $(KERNEL_OUT)/arch/$(TARGET_KERNEL_ARCH)/boot/dts/ $(KERNEL_OUT)/arch/arm/boot/dts/ $(KERNEL_OUT)/arch/arm/boot/
dtb_dir = $(firstword $(wildcard $(possible_dtb_dirs)))

define build-dtimage-target
    $(call pretty,"Target dt image: $(INSTALLED_DTIMAGE_TARGET)")
    $(hide) $(DTBTOOL) -o $@ -s $(BOARD_KERNEL_PAGESIZE) -p $(KERNEL_OUT)/scripts/dtc/ $(dtb_dir)
    $(hide) chmod a+r $@
endef

$(INSTALLED_DTIMAGE_TARGET): $(DTBTOOL) $(INSTALLED_KERNEL_TARGET)
	$(build-dtimage-target)

ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_DTIMAGE_TARGET)
ALL_MODULES.$(LOCAL_MODULE).INSTALLED += $(INSTALLED_DTIMAGE_TARGET)
endif
endif

可見是使用dtbtool
dtbtool代碼定義在device\qcom\common\dtbtool\dtbtool.c, 與這個文件同一目錄下的dtbtool.txt是對dtbtool的使用說明。

1.1) Android boot image Header:

  1. Magic (8B)
  2. kernel size (4B)
  3. kernel addr (4B)
  4. ramdisk size (4B)
  5. ramdisk addr (4B)
  6. 2ndary size (4B)
  7. 2ndary addr (4B)
  8. tags addr (4B)
  9. page size (4B)
  10. unused #1 (4B) (zero in standard Android)
  11. unused #2 (4B) (zero in standard Android)
  12. product name (16B)
  13. kernel cmdline (512B)
  14. id (8B)

1.2) Layout:
A) header (as above - 1 page)
B) kernel (n pages)
C) ramdisk (m pages)
D) second stage (o pages)
2) QC table of device tree
在這裏插入圖片描述

dt.img的構造

在這裏插入圖片描述
可以看出magic是QCDT,version是3,num_entries是0x89

可以看出offset是0x1800, size是0x26800 (0x1800+0x26800=0x28000)
在這裏插入圖片描述
0x28000是另一個dtb的開始
在這裏插入圖片描述

lk的加載過程代碼分析

int boot_linux_from_mmc(void)
{
...............
	if(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;
		}

		/* Its Error if, dt_hdr_size (table->num_entries * dt_entry size + Dev_Tree Header)
		goes beyound hdr->dt_size*/
		if (dt_hdr_size > ROUND_TO_PAGE(dt_size,hdr->page_size)) {
			dprintf(CRITICAL, "ERROR: Invalid Device Tree size \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(dt_entry.offset > (UINT_MAX - dt_entry.size)) {
			dprintf(CRITICAL, "ERROR: Device tree contents are Invalid\n");
			return -1;
		}

		/* Ensure we are not overshooting dt_size with the dt_entry selected */
		if ((dt_entry.offset + dt_entry.size) > dt_size) {
			dprintf(CRITICAL, "ERROR: Device tree contents are Invalid\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(INFO, "decompressing 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, "decompressing dtb failed!!!\n");
				ASSERT(0);
			}

			dprintf(INFO, "decompressing dtb: done\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) ||
			check_ddr_addr_range_bound(hdr->tags_addr, dtb_size))
		{
			dprintf(CRITICAL, "Device tree addresses are not valid\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) ||
			check_ddr_addr_range_bound(hdr->tags_addr, kernel_actual))
		{
			dprintf(CRITICAL, "Device tree addresses are not valid.\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 +
					patched_kernel_hdr_size),
				hdr->kernel_size, dtb_offset,
				(void *)hdr->tags_addr);
		if (!dtb) {
			dprintf(CRITICAL, "ERROR: Appended Device Tree Blob not found\n");
			return -1;
		}
	} 
....................
}

在這種情況下dt_size是非0的,走第一個分支,第二個分支是zImage-dtb那種方式使用的

int dev_tree_get_entry_info(struct dt_table *table, struct dt_entry *dt_entry_info)
	for(i = 0; found == 0 && i < table->num_entries; i++)
		platform_dt_absolute_match(cur_dt_entry, dt_entry_queue);
	best_match_dt_entry = platform_dt_match_best(dt_entry_queue);

調用關係如上,對每一個dt_entry調用platform_dt_absolute_match,找到最匹配的,匹配方法與zImage-dtb方式類似,不再贅述。

小結

device tree最終編譯成dtb文件,而高通平臺爲了讓一個bootimage支持多種不同的配置(甚至是不同的board,不同的平臺),將衆多的dtb文件一起同時編譯和打包。爲了區分匹配不同的平臺,高通平臺需要再sbl裏配置id,與device tree裏的qcom,pmic-id和qcom,board-id相呼應,這兩者需要匹配,才能實現dtb文件的正確加載,然後由lk傳遞給kernel。而dtb的識別是在lk裏實現的,lk代碼裏對dt.img方式和zImage-dtb方式做了兼容,可以同時識別這兩種方式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章