高通平台dtb文件的加载过程「建议收藏」

高通平台dtb文件的加载过程「建议收藏」高通平台dtb文件的加载过程高通平台对dts的两种打包方式zImage-dtbdt.imgzImage-dtb方式zImage-dtb的编译二进制文件查看lk的加载过程代码分析dt.img方式dt.img的编译lk的加载过程新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyP…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

高通平台对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

Jetbrains全家桶1年46,售后保障稳定

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方式做了兼容,可以同时识别这两种方式。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/219594.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • Spring MVC面试题(2020最新版)[通俗易懂]

    Spring MVC面试题(2020最新版)[通俗易懂]文章目录概述什么是SpringMVC?简单介绍下你对SpringMVC的理解?SpringMVC的优点核心组件SpringMVC的主要组件?什么是DispatcherServlet什么是SpringMVC框架的控制器?SpringMVC的控制器是不是单例模式,如果是,有什么问题,怎么解决?工作原理请描述SpringMVC的工作流程?描述一下DispatcherServlet的工作…

  • android 学习资料[通俗易懂]

    android 学习资料[通俗易懂]■安卓在线源码http://androidxref.com/https://www.androidos.net.cn/sourcecode■AndroidMediaPlayer8.0a

  • Robots协议具体解释

    Robots协议具体解释

    2021年12月10日
  • navicat手动激活码【2021最新】

    (navicat手动激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.html…

  • pycharm入门教程(非常详细)_pipe使用教程

    pycharm入门教程(非常详细)_pipe使用教程1、汉化:把resources_zh.jar(自行下载)拷贝到PyCharm的安装目录下的lib目录,重启Pycharm即可。2、整体结构:3、常用功能介绍:(1)如何更换Python解释器:在文件->设置->项目:xxx下找到ProjectInterpreter。然后修改为你需要的Python解释器。注意这个地方一定要注意的是:在选择Python解释器的…

  • HashMap的数据结构

    前提:主要数据结构:数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端。数组数组存储区间是连续的,占用内存严重,故空间复杂的很大。但数组的二分查找时间复杂度小,为O(1);数组的特点是:寻址容易,插入和删除困难;链表链表存储区间离散,占用内存比较宽松,故空间复杂度很小,但时间复杂度很大,达O(N)。链表的特点是:寻址困难,插入和删除容易。哈希表那么我…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号