分析核心原始碼,裝置樹

2021-08-08 18:10:51 字數 3981 閱讀 6444

u-boot需要將裝置樹在記憶體中的儲存位址傳給核心。該樹主要由三大部分組成:頭(header)、結構塊(

structure block

)、字串塊(

strings block

)。裝置樹在記憶體中的儲存布局圖如下

1.1 頭(

1.2 結構塊(

struct block

扁平裝置樹結構塊是線性化的樹形結構,和字串塊一起組成了裝置樹的主體,以節點形式儲存目標板的裝置資訊

在結構塊中,節點起始標誌為32位常值巨集of_dt_begin_node,節點結束標誌為巨集of_dt_end_node

子節點定義在節點結束標誌前。乙個節點的基本結構如下所示:

(1). 節點起始標誌of_dt_begin_node(即0x0000_0001);

(2). 節點路徑或者節點單元名(version < 3以及節點路徑表示,version > 16時以節點單元名表示);

(3). 填充位元組保證四位元組對齊;

(4). 節點屬性。

每個屬性以常值巨集of_dt_prop 開始,後面依次為屬性值的位元組長度、屬性名在字串塊中的偏移值,屬性值及位元組對齊填充段;

(5). 如果存在子節點,則定義子節點

(6). 節點結束標誌of_dt_end_node(即0x0000_0002)。

歸納起來,乙個節點可以概括為以of_dt_begin_node開始,節點路徑、屬性列表、子節點列表以及of_dt_end_node結束的序列,每乙個子節點自身也是類似的結構。

1.3 字串塊(strings block)

為了節省空間,對於那些屬性名,尤其是很多屬性名是重複冗餘出現的,提取出來單獨存放到字串塊。這個塊中包含了很多有結束標誌的屬性名字串。 在裝置樹的結構塊中儲存了這些字串的偏移位址,因為可以很容易的查詢到屬性名字串。字串塊的引入節省嵌入式系統較為緊張的儲存空間。

1.4 裝置樹原始碼 dts 表示

裝置樹原始碼檔案(.dts)以可讀可編輯的文字形式描述系統硬體配置裝置樹,支援 c/c++方式的注釋,該結構有乙個唯一的根節點「/」,每個節點都有自己的名字並可以包含多個子節點。裝置樹的資料格式遵循了 open firmware ieee standard 1275。這個裝置樹中有很多節點,每個節點都指定了節點單元名稱。每乙個屬性後面都給出相應的值。以雙引號引出的內容為 ascii 字串,以尖括號給出的是 32 位的16進製制值。這個樹結構是啟動 linux 核心所需節點和屬性簡化後的集合,包括了根節點的基本模式資訊、cpu 和物理記憶體布局,它還包括通過/chosen 節點傳遞給核心的命令列引數資訊。

1.5 machine_desc結構

核心提供了乙個重要的結構體struct machine_desc ,這個結構體在核心移植中起到相當重要的作用,核心通過machine_desc結構體來控制系統體系架構相關部分的初始化。machine_desc結構體通過machine_start巨集來初始化,在**中, 通過在mian->setup_arch中呼叫setup_machine_fdt來獲取。

1.6 裝置節點結構體

1.7 屬性結構體

三、裝置樹初始化及解析

分析linux核心的原始碼,可以看到其對扁平裝置樹的解析流程如下

(1)首先在核心入口處將從u-boot傳遞過來的映象基位址。

(2)通過呼叫early_init_dt_scan()函式來獲取核心前期初始化所需的bootargs,cmd_line等系統引導引數。

(3)根據bootargs,cmd_line等系統引導引數進入start_kernel()函式,進行核心的第二階段初始化。

(4)呼叫unflatten_device_tree()函式來解析dtb檔案,構建乙個由device_node結構連線而成的單項鍊表,並使用全域性變數

of_allnodes

指標來儲存這個鍊錶的頭指標。

(5)核心呼叫of提供的api函式獲取of_allnodes鍊錶資訊來初始化核心其他子系統、裝置等

原始碼如下

在init目錄下的main.c中的start_kernel函式中

進入這個setup_arch

其餘**先省略

檢視setup_machine_fdt函式

這裡呼叫了early_init_dt_scan_nodes函式

來看看這個函式

看看這個fdt_next_node函式

上面還有乙個很重要的地方

這裡,這裡對這個initial_boot_parems進行賦值,這裡這個指標指向了裝置樹的虛擬起始位址

在這裡進行偏移,詳細資訊看這裡的**

chosen屬性

chosen 節點並不代表乙個真實的裝置,只是作為乙個為韌體和作業系統之間傳遞資料的地方,比如引導引數。chosen 節點裡的資料也不代表硬體。通常,chosen 節點在.dts 原始檔中為空,並在啟動時填充。在我們的示例系統中,韌體可以往 chosen 節點新增以下資訊:

chosen ;

1.2 根節點"/"

裝置樹有且僅有乙個根節點,即「/」,根節點下包含很多子節點,例入下圖,根節點為"/",根節點的子節點為"chosen",根節點的屬性包含"compatible","#address-cells","#size-cells","interrupt-parent"等。屬性model指明了目標板平台或模組的名稱,屬性compatible值指明和目標板為同一系列的相容的開發板名稱。對於大多數32位平台,屬性#address-cells和#size-cells的值一般為1。#address-cells = <1>; 1表示位址32位,2表示位址64位。#size-cells = <1>;1表示rangs的每部分佔乙個cell,依此類推  ;

}所以本函式就是讀取根節點的"#address-cells","#size-cells"屬性

1.3 memory節點

memory節點用於描述目標板上物理記憶體範圍,一般稱作/memory節點,可以有乙個或多個。當有多個節點時,需要後跟單元位址予以區分;只有乙個單元位址時,可以不寫單元位址,預設為0。此節點包含板上物理記憶體的屬性,一般要指定device_type(固定為"memory")和reg屬性。其中reg的屬性值以《起始位址 空間大小》的形式給出,如下示例中目標板記憶體起始位址為0x80000000,大小為0x20000000位元組。 

memory ;

在看看解析裝置樹這一塊

核心原始碼樹

目錄 描述arch 包含和硬體體系結構相關的 每種平台佔乙個相應的目錄。和32位pc相關的 存放在i386目錄下,其中比較重要的包括kernel 核心核心部分 mm 記憶體管理 math emu 浮點單元 lib 硬體相關工具函式 boot 引導程式 pci pci匯流排 和power cpu相關狀...

構造核心原始碼樹

編寫驅動程式時,需要核心原始碼樹的支援。核心原始碼樹時從核心源 編譯得到的。下面開始構造核心源 的步驟。以ubuntu為例子 注意 原始碼樹核心的版本要和驅動程式執行的目標平台的核心版本一致 apt cache search linux source 搜尋核心版本 tar xvf linux sou...

Linux核心 fork 原始碼分析

核心版本 linux 4.4.18 原始碼位置 這裡 接著 呼叫copy process 它設定了程序描述符以及子程序所需的任何其他核心資料結構。ftrace graph init task 初始化ftrace,核心追蹤函式呼叫。rt mutex init task 初始化鎖。copy creds ...