从设备树(dtb格式数据)中解析出bootargs

2023-11-10

1、函数调用关系

start_kernel
	setup_arch
		setup_machine_fdt
			early_init_dt_scan_nodes	//遍历设备树的节点,解析出重要的信息用于内核启动
				of_scan_flat_dt		//解析设备树的节点
					early_init_dt_scan_chosen	//用于解析chosen节点的函数
					
	//函数调用
	of_scan_flat_dt(early_init_dt_scan_chosen, boot_command_line);

(1)调用of_scan_flat_dt()函数遍历dtb的所有节点;
(2)将每个节点都调用early_init_dt_scan_chosen()函数进行解析,判断是不是chosen节点;
(3)如果是chosen节点,就解析处bootargs属性并保存到boot_command_line变量中;

2、dtb中bootargs的来源

(1)内核启动参数bootargs保存在设备树的chosen节点的bootargs属性;
(2)bootargs数据可以是在dts源文件中定义,也可以是uboot启动内核时传递给内核;
(3)优先级:uboot传递的bootargs参数优先级高于dts中定义的bootargs;
(4)如果是uboot传递的bootargs,在内核解压缩阶段就会调用atags_to_fdt()函数将tag中的bootargs参数转换成dtb的格式,写进dtb数据中;

3、of_scan_flat_dt()函数

int __init of_scan_flat_dt(int (*it)(unsigned long node,const char *uname, int depth,
				     void *data), void *data)
{
	//dtb数据的地址,也就是根节点的地址
	const void *blob = initial_boot_params;
	
	const char *pathp;
	int offset, rc = 0, depth = -1;
	if (!blob)
		return 0;

	//从根节点遍历dtb中每个节点,返回的offset就是每个节点的地址
	for (offset = fdt_next_node(blob, -1, &depth);
	     offset >= 0 && depth >= 0 && !rc;
	     offset = fdt_next_node(blob, offset, &depth)) {

		//解析出节点名称
		pathp = fdt_get_name(blob, offset, NULL);
		if (*pathp == '/')
			pathp = kbasename(pathp);

		//回调函数:解析节点
		rc = it(offset, pathp, depth, data);
	}
	return rc;
}

(1)此时设备树还是dtb格式的二进制数据,从dtb格式中解析节点和属性有提供专有函数,具体怎么解析出来的不用关心;
(2)blob:dtb数据的启动地址,也是根节点的地址;
(3)offset:表示节点的地址相对于根节点的偏移量,也是节点数据所在地址;
(4)depth:代表节点相对于根节点的深度,比如根节点深度是0,/chosen节点是1;
(5)it:是传递进来的设备树节点的解析函数,需要解析什么消息就传递进来相应的节点解析函数;

early_init_dt_scan_chosen()函数

int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
				     int depth, void *data)
{
	int l;
	const char *p;

	pr_debug("search \"chosen\", depth: %d, uname: %s\n", depth, uname);

	//节点的深度要为1,数据不能使NULL,同时节点名字是"chosen"或者 "chosen@0"
	if (depth != 1 || !data ||
	    (strcmp(uname, "chosen") != 0 && strcmp(uname, "chosen@0") != 0))
		return 0;

	//解析initrd相关
	early_init_dt_check_for_initrd(node);

	/* 从chosen节点中解析出bootargs属性 */
	p = of_get_flat_dt_prop(node, "bootargs", &l);
	if (p != NULL && l > 0)
		strlcpy(data, p, min((int)l, COMMAND_LINE_SIZE));	//将bootargs拷贝到data中

	//下面的代码就是从chosen节点中解析不到bootargs,采用默认的bootargs
#ifdef CONFIG_CMDLINE
#if defined(CONFIG_CMDLINE_EXTEND)
	strlcat(data, " ", COMMAND_LINE_SIZE);
	strlcat(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#elif defined(CONFIG_CMDLINE_FORCE)
	strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#else
	/* No arguments from boot loader, use kernel's  cmdl*/
	if (!((char *)data)[0])
		strlcpy(data, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
#endif
#endif /* CONFIG_CMDLINE */

	pr_debug("Command line is: %s\n", (char*)data);

	/* break now */
	return 1;
}

(1)判断传进来的节点是不是chosen节点,如果是则解析出bootargs,并保存到data中(也就是boot_command_line);
(2)如果找不到chosen节点,或者chosen节点的bootargs属性是空,则使用默认的CONFIG_CMDLINE;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从设备树(dtb格式数据)中解析出bootargs 的相关文章

随机推荐

  • 【Typescript】ts中的静态属性和静态方法

    Typescript中的静态属性和静态方法 在ts中使用静态属性和方法 需要有static关键字 且在静态方法里只能用静态属性 举两个栗子 在es5中 function Person this run1 function 实例方法 实例化后
  • 特征缩放(归一化处理)

    在我们面对多维特征问题的时候 我们要保证这些特征都具有相近的尺度 这将帮助梯度下降算法更快地收敛 以房价问题为例 假设我们使用两个特征 房屋的尺寸和房间的数量 尺寸的值为 0 2000平方英尺 而房间数量的值则是0 5 以两个参数分别为横纵
  • 带有 OpenCV.js 的 ESP32-CAM Web 服务器:颜色识别和跟踪

    本教程介绍了使用 ESP32 摄像头网络服务器环境的 OpenCV js 和 OpenCV 工具 例如 我们将构建一个简单的 ESP32 摄像头网络服务器 其中包括对移动物体的颜色检测和跟踪 本教程绝不是对 OpenCV 可以提供给 ESP
  • 学乐高机器人还是学习少儿编程

    学乐高机器人还是学习少儿编程 对于很多的家长来说 孩子的学习一直都是他们非常关心和重视的一件事情 很多的家长在给孩子选择学习课程的时候 也是非常的耐心的 他们会给孩子选择一些能够有利于孩子成长的课程 就拿现在很多的家长想要孩子去学习机器人编
  • 生成树协议实验报告_“网络工程师培训”基础教程:OSPF协议及配置

    OSPF协议概述 OSPF 是 Open Shortest Path First 即 开放最短路由优先协议 的缩写 它是 IETF 组织开发的一个基于链路状态的自治系统内部路由协议 在IP 网络上 它通过收集和传递自治系统的链路状态来动态地
  • 牛客网Verilog刷题——VL54

    牛客网Verilog刷题 VL54 题目 答案 题目 实现一个深度为8 位宽为4bit的双端口RAM 数据全部初始化为0000 具有两组端口 分别用于读数据和写数据 读写操作可以同时进行 当读数据指示信号read en有效时 通过读地址信号
  • ffmpeg命令行map参数的使用

    介绍 理解 map参数的最好办法就是想像一下怎么去告诉ffmpeg你要从源文件中选择 拷贝哪个流到输出文件 输出文件的stream顺序取决于在命令行中 map的参数顺序 下面有一些例子 默认 默认操作 没有指定map参数 比如 ffmpeg
  • IR2104电机驱动

    目录 一 IR2104的引脚定义 二 IR2104的内部原理 三 半桥驱动原理分析 四 全桥驱动原理分析 五 电感电流回流路径的建立 六 自举电容容值的计算与自举二极管选型 七 mos管发热可能的问题 八 推荐阅读 一 IR2104的引脚定
  • R语言中如何进行PCA分析?利用ggplot和prcomp绘制基因表达量分析图

    学习笔记的主要内容是在R语言中利用ggplot2进行PCA分析和绘图 包括简单分析与操作流程 对比不同方式得到的结果差异 提供脚本代码供练习 PCA分析的原理 在处理基因差异表达数据时 有时候需要分析其中因素的影响最大 判断结果的关系 这个
  • InstructGPT:彻底改变人工智能驱动的语言模型

    目录 什么是InstructGPT 人工智能驱动的语言模型的演变 InstructGPT 模型与 GPT 3 相比如何 通过 OpenAI API 访问 InstructGPT 1 访问platform openai com并创建或登录您的
  • Linux中select poll和epoll的区别

    原文地址 http www cnblogs com bigwangdi p 3182958 html 在Linux Socket服务器短编程时 为了处理大量客户的连接请求 需要使用非阻塞I O和复用 select poll和epoll是Li
  • Node.js Modules 模块

    模块 https nodejs org docs v9 2 0 api modules html Node js has a simple module loading system In Node js files and modules
  • 美国移动网络运营商:是时候关闭 3G 了

    整理 祝涛 出品 CSDN ID CSDNnews 你的手机现在正使用什么样的网络服务呢 是4G还是5G呢 如果美国地区的用户依然停留在3G 他们可能需要在手机服务提供商关闭3G网络之前升级 以避免失去服务 美国联邦通信委员会 Federa
  • 华为OD机试 -扑克牌大小(C++ & Java & JS & Python)

    描述 扑克牌游戏大家应该都比较熟悉了 一副牌由54张组成 含3 A 2各4张 小王1张 大王1张 牌面从小到大用如下字符和字符串表示 其中 小写joker表示小王 大写JOKER表示大王 3 4 5 6 7 8 9 10 J Q K A 2
  • 联想Y9000X Opencore引导黑苹果Catalina10.15.6安装教程

    Y9000X 2020黑苹果安装教程 非商业用途 仅用于自己记录学习研究 Y9000X Opencore 安装双硬盘双系统教程 电脑配置 前期准备 安装流程 1 写入U盘镜像 2 更换EFI文件 3 磁盘分区 4 系统安装 5 将U盘中的E
  • [c++]opencv 鼠标响应函数传入外部参数(图像)问题

    参考博客 https blog csdn net my lord article details 53927865 https blog csdn net aiyueyueaoe article details 118192972 http
  • C语言开发MicroPython模块(添加module)

    MicroPython添加模块框架模式相对简单 只需要按照定义好的固定框架就可以添加模块 module 一 向固件里面添加module 1 1 编写mymodule c文件 在ports esp32文件夹下新建一个文件mymodule c
  • 域/AD域

    域 定义 域模型是针对大型网络的管理需求设计的 域就是共享用户账号 计算机账号和安全策略的计算机集合 组成 域网络的组成 一般情况下 有三种计算机 域控制器 上存储着Active Directoy 成员服务器 负责提供邮件 数据库 DHCP
  • Flink学习22:窗口的划分

    1 简介 主要有2种窗口 一个基于时间窗口 一个是基于数量窗口 时间窗口中起止时间是 左闭右开 2 时间概念 2 1 事件生成时间 EventTime 指的是数据在设备上产生的时间 这种模式下 不管数据何时到达或者顺序如何 都能得到一致的结
  • 从设备树(dtb格式数据)中解析出bootargs

    1 函数调用关系 start kernel setup arch setup machine fdt early init dt scan nodes 遍历设备树的节点 解析出重要的信息用于内核启动 of scan flat dt 解析设备