第221行檢查fdt指針是否為空并且調(diào)用early_init_dt_verify函數(shù),該函數(shù)代碼位于drivers/of/fdt.c,這個函數(shù)算是of模塊(還記得么?是open firmware的縮寫)的第一個函數(shù),復(fù)制代碼如下:
1060
1061 bool __init early_init_dt_verify(void *params)
1062 {
1063 if (!params)
1064 return false;
1065
1066 /* check device tree validity */
1067 if (fdt_check_header(params))
1068 return false;
1069
1070 /* Setup flat device-tree pointer */
1071 initial_boot_params = params;
1072 of_fdt_crc32 = crc32_be(~0, initial_boot_params,
1073 fdt_totalsize(initial_boot_params));
1074 return true;
1075 }
early_init_dt_verify首先檢查fdt頭部的合法性,然后設(shè)置fdt全局變量以及計算crc。這個 initial_boot_params變量后邊在訪問設(shè)備樹的時候還會用到。繼續(xù)看前邊第224行,of_flat_dt_match_machine 函數(shù)算是of模塊的第二個函數(shù)吧,在分析這個函數(shù)前,我們首先分析���個函數(shù)的第二個參數(shù)arch_get_next_mach,這是一個函數(shù)指針,arm架構(gòu)的實(shí)現(xiàn)位于arch/arm/kernel/devtree.c,復(fù)制代碼如下:
190 static const void * __init arch_get_next_mach(const char *const **match)
191 {
192 static const struct machine_desc *mdesc = __arch_info_begin;
193 const struct machine_desc *m = mdesc;
194
195 if (m >= __arch_info_end)
196 return NULL;
197
198 mdesc++;
199 *match = m->dt_compat;
200 return m;
201 }
這個函數(shù)很簡單,注意的是mdesc是靜態(tài)局部變量,第一次調(diào)用指向__arch_info_begin,后邊每次調(diào)用都mdesc++,如果超過了__arch_info_end就返回NULL。以上代碼說明在__arch_info_begin和__arch_info_end兩個地址之間存儲著多個machine_desc變量(也可能是一個),該函數(shù)遍歷這些變量,通過match參數(shù)返回所有machine_desc結(jié)構(gòu)體的 dt_compat變量指針。問題是__arch_info_begin和__arch_info_end地址是怎么來的呢?在arch/arm /kernel/vmlinux.lds.S連接腳本中定義了.arch.info.init段,__arch_info_begin和 __arch_info_end地址分別是該段的首尾地址。
188 .init.arch.info : {
189 __arch_info_begin = .;
190 *(.arch.info.init)
191 __arch_info_end = .;
192 }
那么.init.arch.info段的內(nèi)容怎么來的呢?這就要參考DT_MACHINE_START和MACHINE_END宏了,arm架構(gòu)的定義在arch/arm/include/asm/mach/arch.h文件,如下所示:
94 #define DT_MACHINE_START(_name, _namestr) \
95 static const struct machine_desc __mach_desc_##_name \
96 __used \
97 __attribute__((__section__(".arch.info.init"))) = { \
98 .nr = ~0, \
99 .name = _namestr,
100
101 #endif
從該宏代碼看出他定義了一個machine_desc類型的靜態(tài)局部變量,該變量位于.arch.info.init段中。參考arch/arm /mach-exynos/exynos.c中如下代碼,以下代碼在.arch.info.init段定義了一個名字為 __mach_desc_EXYNOS_DT,類型為machine_desc的靜態(tài)局部變量,并且該變量的dt_compat字符串矩陣中有"samsung,exynos5420"的字符串。
277 static char const *const exynos_dt_compat[] __initconst = {
278 "samsung,exynos3",
279 "samsung,exynos3250",
280 "samsung,exynos4",
281 "samsung,exynos4210",
282 "samsung,exynos4212",
283 "samsung,exynos4412",
284 "samsung,exynos4415",
285 "samsung,exynos5",
286 "samsung,exynos5250",
287 "samsung,exynos5260",
288 "samsung,exynos5420",
289 "samsung,exynos5440",
290 NULL
291 };
319 DT_MACHINE_START(EXYNOS_DT, "SAMSUNG EXYNOS (Flattened Device Tree)")
320 /* Maintainer: Thomas Abraham
321 /* Maintainer: Kukjin Kim
322 .l2c_aux_val = 0x3c400001,
323 .l2c_aux_mask = 0xc20fffff,
324 .smp = smp_ops(exynos_smp_ops),
325 .map_io = exynos_init_io,
326 .init_early = exynos_firmware_init,
327 .init_irq = exynos_init_irq,
328 .init_machine = exynos_dt_machine_init,
329 .init_late = exynos_init_late,
330 .dt_compat = exynos_dt_compat,
331 .reserve = exynos_reserve,
332 .dt_fixup = exynos_dt_fixup,
333 MACHINE_END
我們已經(jīng)知道了get_next_compat指針的具體實(shí)現(xiàn)了,現(xiàn)在繼續(xù)看of_flat_dt_match_machine。從第 732行開始的循環(huán)就是遍歷.arch.info.init段中所有的dt_compat變量,然后通過of_flat_dt_match計算一個分?jǐn)?shù),并且尋找那個分?jǐn)?shù)最小的。
713 /**
714 * of_flat_dt_match_machine - Iterate match tables to find matching machine.
715 *
716 * @default_match: A machine specific ptr to return in case of no match.
717 * @get_next_compat: callback function to return next compatible match table.
718 *
719 * Iterate through machine match tables to find the best match for the machine
720 * compatible string in the FDT.
721 */
722 const void * __init of_flat_dt_match_machine(const void *default_match,
723 const void * (*get_next_compat)(const char * const**))
724 {
725 const void *data = NULL;
726 const void *best_data = default_match;
727 const char *const *compat;
728 unsigned long dt_root;
729 unsigned int best_score = ~1, score = 0;
730
731 dt_root = of_get_flat_dt_root();
732 while ((data = get_next_compat(&compat))) {
733 score = of_flat_dt_match(dt_root, compat);
734 if (score > 0 && score < best_score) {
735 best_data = data;
736 best_score = score;
737 }
738 }
....
759 return best_data;
760 }
761
2015職稱計算機(jī)考試書PowerPoint2007中 .. 定價:¥45 優(yōu)惠價:¥42 更多書籍 | |
2015年全國職稱計算機(jī)考試教材(2007模 .. 定價:¥225 優(yōu)惠價:¥213 更多書籍 |