[转] Linux 3.10 ARM Device Tree 的初始化
[转] Linux 3.10 ARM Device Tree 的初始化
本文代码均来自标准 linux kernel 3.10,可以到这里下载 https://www.kernel.org/
以 arch/arm/mach-msm/board-dt-8960.c 为例,在该文件中的 msm_dt_init 函数的作用就是利用 dt(device tree)结构初始化 platform device。
static void __init msm_dt_init(void)
{
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
}
of_platform_populate 实现在 drivers/of/platform.c,是 OF 的标准函数。
int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent)
{
struct device_node *child;
int rc = ;
root = root ? of_node_get(root) : of_find_node_by_path("/");
if (!root)
return -EINVAL;
for_each_child_of_node(root, child) {
rc = of_platform_bus_create(child, matches, lookup, parent, true);
if (rc)
break;
}
of_node_put(root);
return rc;
}
其中of_platform_populate 函数的注释写得很明白:“Populate platform_devices from device tree data”。但是这个“device tree data”又是从那里来的呢?
在 of_platform_populate 中如果 root 为 NULL,则将 root 赋值为根节点,这个根节点是用 of_find_node_by_path 取到的。
struct device_node *of_find_node_by_path(const char *path)
{
struct device_node *np = of_allnodes;
unsigned long flags;
raw_spin_lock_irqsave(&devtree_lock, flags);
for (; np; np = np->allnext) {
if (np->full_name && (of_node_cmp(np->full_name, path) == )
&& of_node_get(np))
break;
}
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
}
在这个函数中有一个很关键的全局变量:of_allnodes,它的定义是在 drivers/of/base.c 里面。
struct device_node *of_allnodes;
这应该所就是那个所谓的“device tree data”了。它应该指向了 device tree 的根节点。问题又来了,这个 of_allnodes 又是咋来的呢?
既然如此,我们来看看 kernel 初始化的代码(init/main.c),大部分代码与本主题无关用 ... 代替。
asmlinkage void __init start_kernel(void)
{
...
setup_arch(&command_line);
...
}
这个 setup_arch 就是各个架构自己的设置函数(arch 是 architecture 的缩写),哪个参与了编译就调用哪个,在本文中应当是 arch/arm/kernel/setup.c 中的 setup_arch。
同样,无关的代码以 ... 代替。
void __init setup_arch(char **cmdline_p)
{
...
mdesc = setup_machine_fdt(__atags_pointer);
...
unflatten_device_tree();
...
}
看到了吧,setup_machine_fdt,其中 fdt 的 f 就是扁平(flat) 的意思。这个时候 DTB 只是加载到内存中的 .dtb 文件而已,这个文件中不仅包含数据结构,还包含了一些文件头等信息,kernel 需要从这些信息中获取到数据结构相关的信息,然后再生成设备树。这个函数的调用还有个参数 __atags_pointer,看名字似乎这是一个指针,干 嘛的呢?以后再说,先进入函数看看。
/* kernel/arch/arm/kernel/devtree.c */
struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
{
...
devtree = phys_to_virt(dt_phys);
...
initial_boot_params = devtree;
...
}
现在有点意思了,phys_to_virt 字面上的意思是物理地址转换成虚拟地址,那就是说 __atags_pointer 是一个物理地址,这就印证了我们的猜测,__atags_pointer 的确是一个指针,再看变量 devtree 它指向了一个 struct boot_param_header 结构体。随后 kernel 把这个指针赋给了全局变量 initial_boot_params。也就是说以后 kernel 会是用这个指针指向的数据去初始化 device tree。
struct boot_param_header {
__be32 magic; /* magic word OF_DT_HEADER */
__be32 totalsize; /* total size of DT block */
__be32 off_dt_struct; /* offset to structure */
__be32 off_dt_strings; /* offset to strings */
__be32 off_mem_rsvmap; /* offset to memory reserve map */
__be32 version; /* format version */
__be32 last_comp_version; /* last compatible version */
/* version 2 fields below */
__be32 boot_cpuid_phys; /* Physical CPU id we're booting on */
/* version 3 fields below */
__be32 dt_strings_size; /* size of the DT strings block */
/* version 17 fields below */
__be32 dt_struct_size; /* size of the DT structure block */
};
看这个结构体,很像之前所说的文件头,有魔数、大小、数据结构偏移量、版本等等,kernel 就应该通过这个结构获取数据,并最终生成设备树。现在回到 setup_arch,果然在随后的代码中有这么一个函数
/* kernel/drivers/of/fdt.c */
void __init unflatten_device_tree(void)
{
__unflatten_device_tree(initial_boot_params, &of_allnodes,
early_init_dt_alloc_memory_arch);
...
}
看见了吧,of_allnodes 就是在这里赋值的,device tree 也是在这里建立完成的。__unflatten_device_tree 函数我们就不去深究了,推测其功能应该就是解析数据、申请内存、填充结构等等。
到此为止,device tree 的初始化就算完成了,在以后的启动过程中,kernel 就会依据这个 dt 来初始化各个设备。但是还有一个小问题,那就是在 setup_arch 函数中 __atags_pointer 从何而来。全局搜索这个变量,结构在 arch/arm/kernel/head-common.S 中发现了它的踪迹。
#define ATAG_CORE 0x54410001
...
__mmap_switched:
adr r3, __mmap_switched_data
ldmia {r4, r5, r6, r7}
...
THUMB( ldr sp, [r3, #] )
...
str r2, [r6] @ Save atags pointer
...
__mmap_switched_data:
...
.long __atags_pointer @ r6
...
arm 汇编不懂,大概能看出来给 __atags_pointer 赋值的过程(‘@’之后是注释)。
[转] Linux 3.10 ARM Device Tree 的初始化的更多相关文章
- 由MTK平台 mtkfb 设备注册疑问引发的知识延伸--ARM Device Tree
问题: 在kernel-3.10\drivers\misc\mediatek\videox\mt6735\mtkfb.c里面int __init mtkfb_init(void) 有看到 platfo ...
- linux驱动开发—基于Device tree机制的驱动编写
前言Device Tree是一种用来描述硬件的数据结构,类似板级描述语言,起源于OpenFirmware(OF).在目前广泛使用的Linux kernel 2.6.x版本中,对于不同平台.不同硬件,往 ...
- The Linux usage model for device tree data
Linux and the Device Tree The Linux usage model for device tree data Author: Grant Likely grant.like ...
- Linux device tree 简要笔记
第一.DTS简介 在嵌入式设备上,可能有不同的主板---它们之间差异表现在主板资源不尽相同,比如I2C.SPI.GPIO等接口定义有差别,或者是Timer不同,等等.于是这就产生了BSP的一个 ...
- ARM Linux 3.x的设备树(Device Tree)
http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1. ...
- 【转】 ARM Linux 3.x的设备树(Device Tree)
1. ARM Device Tree起源 http://blog.csdn.net/21cnbao/article/details/8457546 Linus Torvalds在2011年3月1 ...
- 【转】ARM Linux 3.x的设备树(Device Tree)
原文网址:http://blog.csdn.net/21cnbao/article/details/8457546 1. ARM Device Tree起源 Linus Torvalds在201 ...
- ARM Linux 3.x的设备树(Device Tree)【转】
转自:http://blog.csdn.net/21cnbao/article/details/8457546 宋宝华 Barry Song <21cnbao@gmail.com> 1. ...
- ARM Linux 3.x的设备树(Device Tree)
1. ARM Device Tree起源 Linus Torvalds在2011年3月17日的ARM Linux邮件列表宣称“this whole ARM thing is a f*cking pai ...
随机推荐
- vsftpd文件虚拟用户搭建
关于vsftpd的原理这里就不多说了,下面红色部分有单独标出,突出显示,意思是这里的东西有额外的配置,全文的配置一定要跟着第二步的配置来,不要过程中随便改变参数,除非你看得懂,好了直接上配置过程 1. ...
- 利用scrapy-client发布爬虫的远程服务器
一.环境准备 远程服务器必须装有scapyd,我们使用的机器必须有scrapy-client(我这里是windows),并确保这两者正常安装并启动. 二.客户端准备上传 首先进入到爬虫项目的根文件夹: ...
- centos7安装多媒体播放器SMPlayer
转自:https://wiki.centos.org/TipsAndTricks/MultimediaOnCentOS7 http://blog.chinaunix.net/xmlrpc.php?r= ...
- 用gdb理解C宏(#和##)
在Unix/Linux内核代码以及GNU libc源代码中,有两个C的宏被广泛使用. 例如: /* glibc-2.25/sysdeps/powerpc/powerpc64/sysdep.h */ # ...
- 入门系列之使用fail2ban防御SSH服务器的暴力破解攻击
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由SQL GM发表于云+社区专栏 介绍 对于SSH服务的常见的攻击就是暴力破解攻击--远程攻击者通过不同的密码来无限次地进行登录尝试.当 ...
- HighChart 体验之旅 (后台传递JSON参数和数据的方法)
转自:http://www.cnblogs.com/daviddai/archive/2013/04/12/Highchart.html 官网:http://www.highcharts.com/ 中 ...
- 【LeetCode题解】530_二分搜索树的最小绝对值差
目录 [LeetCode题解]530_二分搜索树的最小绝对值差 描述 方法一.中序遍历二分搜索树 思路 Java 代码 Python 代码 [LeetCode题解]530_二分搜索树的最小绝对值差 描 ...
- [PY3]——IO——pathlib
pathlib.Path() from pathlib import Path p=Path("/test2") Path.cwd() print(p.cwd()) /py3 Pa ...
- CSS3 图标神器 => content:"我是特殊符号"
基本形状 ▲ 9650 25B2 ► 9658 25BA ► 9658 25BA ▼ 9660 25BC ◄ 9668 25C4 ❤ 10084 2764 ✈ 9992 2708 ★ 9733 260 ...
- 数据适配:DataAdapter对象概述
DataAdapter对象可用于执行数据库的命令操作,含有四个不同的操作命令,分别如下: SelectCommand:用来选取数据源中的记录: InsertCommand:用来向数据源中新插入一条 ...