高通平台dtb文件的加载过程
高通平台dtb文件的加载过程
- 高通平台对dts的两种打包方式
- zImage-dtb
- dt.img
- zImage-dtb方式
- zImage-dtb的编译
- 二进制文件查看
- lk的加载过程代码分析
- dt.img方式
- dt.img的编译
- dt.img的构造
- lk的加载过程代码分析
- 小结
高通平台对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=yCONFIG_ARCH_MSM8937=yCONFIG_ARCH_MSM8917=yCONFIG_ARCH_MSM8920=yCONFIG_ARCH_MSM8940=yCONFIG_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.dtbdtb-$(CONFIG_ARCH_MSM8937) += msm8937-rumi.dtb \msm8937-pmi8950-cdp.dtb \.......apq8037-pmi8950-mtp.dtb \apq8037-pmi8937-mtp.dtbdtb-$(CONFIG_ARCH_MSM8917) += msm8917-rumi.dtb \apq8017-pmi8937-cdp.dtb \
…
msm8917-qgp-tmo.dtb \msm8917-pmi8937-qrd-sku5.dtb
.config 文件里生成的内容如下
CONFIG_USE_OF=yCONFIG_ATAGS=y# CONFIG_DEPRECATED_PARAM_STRUCT is not setCONFIG_BUILD_ARM_APPENDED_DTB_IMAGE=yCONFIG_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))elseDTB_LIST := $(dtb-y)endifDTB_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 makeifeq ($(CONFIG_XIP_KERNEL),y)
KBUILD_IMAGE := xipImageelse ifeq ($(CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE),y)KBUILD_IMAGE := zImage-dtbelseKBUILD_IMAGE := zImageendif$(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文件的偏移地址
从图中可以看出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;elsememcpy((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_iduint32_t foundry_id;uint32_t chip_serial;uint32_t platform_version;//board_soc_versionuint32_t platform_hw;//board_hardware_id()uint32_t platform_subtype;//board_hardware_subtypeuint32_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_subtypeuint32_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
endifDTBTOOL := $(HOST_OUT_EXECUTABLES)/dtbTool$(HOST_EXECUTABLE_SUFFIX)INSTALLED_DTIMAGE_TARGET := $(PRODUCT_OUT)/dt.imgpossible_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:
- Magic (8B)
- kernel size (4B)
- kernel addr (4B)
- ramdisk size (4B)
- ramdisk addr (4B)
- 2ndary size (4B)
- 2ndary addr (4B)
- tags addr (4B)
- page size (4B)
- unused #1 (4B) (zero in standard Android)
- unused #2 (4B) (zero in standard Android)
- product name (16B)
- kernel cmdline (512B)
- 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方式做了兼容,可以同时识别这两种方式。
高通平台dtb文件的加载过程相关推荐
- extjs5(03--项目中文件的加载过程)
上一节中用sencha工具自动创建了一个项目,并且可以在浏览器中查看.现在我们来看看js类加载过程.如下图所示: 1、首先:浏览器中输入 localhost:1841 ,调用 index.html; ...
- EXE文件的加载过程
一个microsoft的.exe程序文件的启动过程 2009-06-16 14:54 2101人阅读 评论(0) 收藏 举报 microsoftmfcwindowsshelldll数据结构 学习win ...
- 浏览器加载一个页面过程,本地的html文件的加载过程
打开一个本地文件 读取返回给网页 import flask app=flask.Flask(__name__) @app.route('/index') def miaomiao():with ope ...
- 高通平台msm8953 Linux DTS(Device Tree Source)设备树详解之二(DTS设备树匹配过程)
本系列导航: 高通平台8953 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇) 高通平台8953 Linux DTS(Device Tree Source ...
- ELF文件的加载和动态链接过程
本文的目的:大家对于Hello World程序应该非常熟悉,随便使用哪一种语言,即使还不熟悉的语言,写出一个Hello World程序应该毫不费力,但是如果让大家详细的说明这个程序加载和链接的过程,以 ...
- 高通平台msm8909 LK 实现LCD 兼容
前段时间小米出现红米note2 换屏门,现在我们公司也要上演了:有两个供应商提供不同IC 的LCD panel. 软件区分的办法是读取LCD IC 的ID 寄存器,下面解析高通平台LK中LCD兼容的过 ...
- 高通平台modem部分mbn文件的OTA和PDC升级方法
高通平台modem部分mbn文件的OTA和PDC升级方法 最近需要采用一种移动物联网卡,发现在apns-conf.xml增加了对应apn信息后,部分设备采用新的xml就可以支持新卡,但部分设备还不行, ...
- 高通about.html 文件,高通平台UEFI有关介绍
高通平台UEFI有关介绍 背景 我需要在高通平台上学习点亮LCD,目前通过同事在别的平台的配置代码,我已经将kernel部分的屏幕点亮了:剩余的工作量就在BP侧,也就是系统刚开机的那一段时间.在开发过 ...
- 高通平台8953 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇)
本系列导航: 高通平台8953 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇) 高通平台8953 Linux DTS(Device Tree Source ...
最新文章
- linux apache 手动安装教程,linux下手动安装apache
- (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致...
- win10 配置 maven_home 一会儿成功一会儿失败_在macbook上运行移动硬盘里的win10和macos...
- springboot参数检验,Assert使用
- linux脚本语言求累加和,Linux Shell脚本语言与数学表达式
- Gamma阶段第八次scrum meeting
- java反射jdk1.8,Java基础----jdk1.8 反射实验
- dnf最新地图编号2020_2020手游崛起端游没落?网易新端游好玩刺激能搬砖,网友:妙...
- C#实现邮件发送的功能
- python使用opencv保存视频_Pythone OpenCV学习笔记之:视频文件读取与保存
- CSS按钮动画(四)
- 【三维路径规划】基于matlab人工势场算法无人机三维路径规划【含Matlab源码 168期】
- 菜鸟也疯狂,易语言自绘控件__按钮篇,用所有者自绘方式实现
- ORL人脸数据库matlab,orl ORL人脸数据库,用于图形图像处理,对新接触MATLAB的人来说是一个很好用而且比较简单 238万源代码下载- www.pudn.com...
- 在图片上涂鸦(其实就是乱画 O(∩_∩)O)
- JAVA开发---微信文章留言功能实现
- Linux下的关闭防火墙
- 【BZOJ3875】[Ahoi2014Jsoi2014]骑士游戏 SPFA优化DP
- mysql 连续登录天数
- Jenkins CI服务器搭建及Maven私服Nexus