[kernel 啓動流程] (第四章)第一階段之——dtb的驗證

本文是基於arm平臺。例子都是以tiny210(s5pv210 armv7)爲基礎的。
[kernel 啓動流程]系列

建議參考文檔

================================================

零、說明

本文是《[kernel 啓動流程] (第一章)概述》的延伸,
閱讀本文前建議先閱讀《[kernel 啓動流程] (第一章)概述》

1、kernel啓動流程第一階段簡單說明

arch/arm/kernel/head.S

  • kernel入口地址對應stext
ENTRY(stext)
  • 第一階段要做的事情,也就是stext的實現內容

    • 設置爲SVC模式,關閉所有中斷
    • 獲取CPU ID,提取相應的proc info
    • 驗證tags或者dtb
    • 創建頁表項
    • 配置r13寄存器,也就是設置打開MMU之後要跳轉到的函數。
    • 使能MMU
    • 跳轉到start_kernel,也就是跳轉到第二階段

本文要介紹的是“驗證tags或者dtb的合法性”的部分。因爲現在基本上很少使用atags,所以這裏我們只說dtb的部分。

2、疑問

主要帶着以下幾個問題去理解

  • dtb是什麼?爲什麼要驗證dtb的合法性?
  • 如何驗證dtb的合法性?

3、對應代碼實現

    __HEAD
ENTRY(stext)
    /*
     * r1 = machine no, r2 = atags or dtb,
     * r8 = phys_offset, r9 = cpuid, r10 = procinfo
     */
    bl  __vet_atags

一、DTB說明

這部分建議直接參考wowo的dtb的文章
Device Tree(一):背景介紹
Device Tree(二):基本概念
Device Tree(三):代碼分析
簡單說明,dtb裏面存放了各種硬件信息,如果dtb有問題,會導致後續開機過程中讀取的設備信息有問題而導致無法開機。

二、如何驗證了一個dtb是否合法

1、原理說明
在生成dtb的時候會在頭部上添加一個幻數magic,而驗證dtb是否合法主要也就是看這個dtb的magic是否和預期的值一致。
2、dtb結構如下

結構體如下
DTB header
alignment gap
memory reserve map
alignment gap
device-tree structure
alignment gap
device-tree string

3、dtb header結構如下:

結構體如下
magic
totalsize
off_dt_struct
off_dt_strings
off_mem_rsvmap
version
……

其中,magic是一個固定的值,0xd00dfeed(大端)或者0xedfe0dd0(小端)。
以s5pv210-tiny210.dtb爲例:
執行”hexdump -C s5pv210-tiny210.dtb | more”命令

@:dts$ hexdump -C s5pv210-tiny210.dtb | more
00000000  d0 0d fe ed 00 00 5a cc  00 00 00 38 00 00 58 14  |......Z....8..X.|
00000010  00 00 00 28 00 00 00 11  00 00 00 10 00 00 00 00  |...(............|

可以看到dtb的前面4個字節就是0xd00dfeed,也就是magic。
綜上,我們只要提取待驗證dtb的地址上的數據的前四個字節,與0xd00dfeed(大端)或者0xedfe0dd0(小端)進行比較,如果匹配的話,就說明對應待驗證dtb就是一個合法的dtb。

三、代碼分析

具體就是分析__vet_atags的實現。
通過《[kernel 啓動流程] (第一章)概述》,我們已經知道r2上存放的是dtb的地址指針,而代碼中所要做的,就是要通過這個地址指針,獲取前四個字節,去和dtb應有的幻數,也就是0xd00dfeed(大端)或者0xedfe0dd0(小端)進行比較。匹配的話,則說明這是一個合法的dtb。
代碼如下(省略了驗證atags的部分):
arch/arm/kernel/head-common.S

__vet_atags:
    tst    r2, #0x3            @ aligned?保證dtb的地址是四字節對齊的
    bne    1f

    ldr    r5, [r2, #0]    @獲取dtb的前四個字節,存放在r5寄存器中
#ifdef CONFIG_OF_FLATTREE
    ldr    r6, =OF_DT_MAGIC    @ is it a DTB?,獲取dtb的幻數,0xd00dfeed(大端)或者0xedfe0dd0(小端)
    cmp    r5, r6    @前四個字節和幻數進行對比
    beq    2f    @匹配,則說明是一個合法的dtb文件,跳到2
#endif
    bne    1f @不匹配,跳到1

2:    ret    lr                @ atag/dtb pointer is ok,直接返回,此時r2存放了dtb的地址

1:    mov    r2, #0@錯誤返回,此時,r2上是0
    ret    lr
ENDPROC(__vet_atags)

DTB的幻數,也就是OF_DT_MAGIC定義如下:
arch/arm/kernel/head-common.S

#ifdef CONFIG_CPU_BIG_ENDIAN
#define OF_DT_MAGIC 0xd00dfeed
#else
#define OF_DT_MAGIC 0xedfe0dd0 /* 0xd00dfeed in big-endian */
#endif

綜上,驗證dtb的工作完成。

發佈了48 篇原創文章 · 獲贊 118 · 訪問量 23萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章