[kernel 启动流程] (第四章)第一阶段之——dtb的验证
来源:互联网 发布:在端口23:连接失败 编辑:程序博客网 时间:2024/05/21 10:23
本文是基于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)
第一阶段要做的事情,也就是stext的实现内容
- 设置为SVC模式,关闭所有中断
- 获取CPU ID,提取相应的proc info
- 验证tags或者dtb
- 创建页表项
- 配置r13寄存器,也就是设置打开MMU之后要跳转到的函数。
- 使能MMU
- 跳转到start_kernel,也就是跳转到第二阶段
本文要介绍的是“验证tags或者dtb的合法性”的部分。因为现在基本上很少使用atags,所以这里我们只说dtb的部分。
2、疑问
主要带着以下几个问题去理解
- dtb是什么?为什么要验证dtb的合法性?
- 如何验证dtb的合法性?
3、对应代码实现
__HEADENTRY(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结构如下
3、dtb header结构如下:
其中,magic是一个固定的值,0xd00dfeed(大端)或者0xedfe0dd0(小端)。
以s5pv210-tiny210.dtb为例:
执行”hexdump -C s5pv210-tiny210.dtb | more”命令
@:dts$ hexdump -C s5pv210-tiny210.dtb | more00000000 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 @不匹配,跳到12: ret lr @ atag/dtb pointer is ok,直接返回,此时r2存放了dtb的地址1: mov r2, #0@错误返回,此时,r2上是0 ret lrENDPROC(__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的工作完成。
- [kernel 启动流程] (第四章)第一阶段之——dtb的验证
- [kernel 启动流程] (第四章)第一阶段之——dtb的验证
- [kernel 启动流程] (第三章)第一阶段之——proc info的获取
- [kernel 启动流程] (第五章)第一阶段之——临时内核页表的创建
- [kernel 启动流程] (第三章)第一阶段之——proc info的获取
- [kernel 启动流程] (第五章)第一阶段之——临时内核页表的创建
- [kernel 启动流程] (第二章)第一阶段之——设置SVC、关闭中断
- [kernel 启动流程] (第六章)第一阶段之——打开MMU
- [kernel 启动流程] (第七章)第一阶段之——跳转到start_kernel
- [kernel 启动流程] (第二章)第一阶段之——设置SVC、关闭中断
- [kernel 启动流程] (第六章)第一阶段之——打开MMU
- [kernel 启动流程] (第七章)第一阶段之——跳转到start_kernel
- Linux kernel启动流程第一阶段
- [uboot] uboot启动kernel篇(二)——bootm跳转到kernel的流程
- [uboot] uboot启动kernel篇(二)——bootm跳转到kernel的流程
- 本文整理了ARM Linxu启动流程的第一阶段——内核自解压
- uboot第一阶段启动流程
- kernel的启动流程分析(未完)
- Bezier曲线原理及实现代码(c++)
- 运用表单制作简单网易页面
- C/C++在调试程序时运行代码行数与实际不一致
- 设计模式之观察者模式
- iOS 原生扫描二维码 ----扫描有效区域的问题
- [kernel 启动流程] (第四章)第一阶段之——dtb的验证
- Mysql数据库主从配置
- 【FAQ】命令行如何刷新gradle依赖缓存?
- 搭建高可用的MongoDB集群
- Mysql-spring事务回滚
- Error: run custom shell script
- js基础:数据类型,变量命名规范、
- CSS 基础(004_外边距)
- 浅谈C/C++内存泄露及其检测工具