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

轉自:https://blog.csdn.net/ooonebook/article/details/52797211

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

[kernel 啓動流程] 前篇——vmlinux.lds分析
[kernel 啓動流程] (第一章)概述
[kernel 啓動流程] (第二章)第一階段之——設置SVC、關閉中斷
[kernel 啓動流程] (第三章)第一階段之——proc info的獲取
[kernel 啓動流程] (第四章)第一階段之——dtb的驗證
[kernel 啓動流程] (第五章)第一階段之——臨時內核頁表的創建
[kernel 啓動流程] (第六章)第一階段之——打開MMU
[kernel 啓動流程] (第七章)第一階段之——跳轉到start_kernel
建議參考文檔:

ARMV7官方數據手冊
ARM的CP15協處理器的寄存器
================================================

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

1、kernel啓動流程第一階段簡單說明
arch/arm/kernel/head.S

kernel入口地址對應stext
ENTRY(stext)
1
第一階段要做的事情,也就是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的工作完成。
————————————————
版權聲明:本文爲CSDN博主「ooonebook」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/ooonebook/article/details/52797211

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章