uboot中启动linux内核的函数——do_bootm_linux函数解析

2023-10-29

1、do_bootm_linux函数解析

do_bootm_linux函数是专门启动linux内核的,包括以下功能:
(1)确认当前的机器码,可以从全局变量gd或者环境变量machid中获取,其中环境变量machid的优先级高于gd中的机器码;
(2)计算出内核的入口地址;
(3)准备给内核的传参;不清楚uboot给内核传参的看博客:《uboot中命令体系详解》
(4)协处理器的相关操作,为启动内核初始化环境;
(5)启动内核;

2、启动内核入口的传参

(1)theKernel (0, machid, bd->bi_boot_params);
theKernel 是函数指针,指向内核的入口地址,也就是内核将要执行的第一句代码。其中要传三个参数,第一个参数固定为0,第二个参数是机器码,第三个参数是uboot传给内核参数所在的首地址。
(2)机器码
机器码可以算作是一块板子的id,嵌入式设备是高度定制的,内核也是可以高度裁剪的,所以每个版本的内核只能支持移植过开发板。在内核中维护有个表格,里面记录了支持的开发板的id,也就是机器码,如果启动内核时传入的机器码没有在表格中找到,说明内核不支持该开发板,启动失败。

3、do_bootm_linux函数源码

	#define CONFIG_BOOTARGS    	"console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3"
	
	void do_bootm_linux (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[],
				 bootm_headers_t *images)
	{
		ulong	initrd_start, initrd_end;
		ulong	ep = 0;
		bd_t	*bd = gd->bd;
		char	*s;
		int	machid = bd->bi_arch_number; //从全局变量gd中获取机器码
		void	(*theKernel)(int zero, int arch, uint params);
		int	ret;

	#ifdef CONFIG_CMDLINE_TAG
		//对应宏:CONFIG_BOOTARGS,bootargs是启动内核的传的参数
		char *commandline = getenv ("bootargs"); 
	#endif

		/* find kernel entry point */
		if (images->legacy_hdr_valid) {
			ep = image_get_ep (&images->legacy_hdr_os_copy); //得到内核的入口地址
		} else {
			puts ("Could not find kernel entry point!\n");
			goto error;
		}
		//theKernel 是函数指针,指向内核的入口地址
		theKernel = (void (*)(int, int, uint))ep;
		
		//从环境变量获取机器码,这里可以看出环境变量里的机器码优先级高于全局变量gd里的机器码
		s = getenv ("machid"); 
		if (s) {
			machid = simple_strtoul (s, NULL, 16);
			printf ("Using machid 0x%x from environment\n", machid);
		}

		ret = boot_get_ramdisk (argc, argv, images, IH_ARCH_ARM, //虚拟内存盘相关
				&initrd_start, &initrd_end);
		if (ret)
			goto error;

		show_boot_progress (15);

		debug ("## Transferring control to Linux (at address %08lx) ...\n",
			   (ulong) theKernel);
			   
	/*	下面都是在准备给内核的传参     */
	#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
		defined (CONFIG_CMDLINE_TAG) || \
		defined (CONFIG_INITRD_TAG) || \
		defined (CONFIG_SERIAL_TAG) || \
		defined (CONFIG_REVISION_TAG) || \
		defined (CONFIG_LCD) || \
		defined (CONFIG_VFD) || \
		defined (CONFIG_MTDPARTITION)
		setup_start_tag (bd); //传递给内核参数的起始tag结构体
	#ifdef CONFIG_SERIAL_TAG
		setup_serial_tag (&params);
	#endif
	#ifdef CONFIG_REVISION_TAG
		setup_revision_tag (&params);
	#endif
	#ifdef CONFIG_SETUP_MEMORY_TAGS
		setup_memory_tags (bd);
	#endif
	#ifdef CONFIG_CMDLINE_TAG
		setup_commandline_tag (bd, commandline);
	#endif
	#ifdef CONFIG_INITRD_TAG
		if (initrd_start && initrd_end)
			setup_initrd_tag (bd, initrd_start, initrd_end);
	#endif
	#if defined (CONFIG_VFD) || defined (CONFIG_LCD)
		setup_videolfb_tag ((gd_t *) gd);
	#endif

	#ifdef CONFIG_MTDPARTITION
		setup_mtdpartition_tag();
	#endif
		//传递给内核参数的结束tag结构体
		setup_end_tag (bd);
	#endif

		/* we assume that the kernel is in place */
		printf ("\nStarting kernel ...\n\n");

	#ifdef CONFIG_USB_DEVICE
		{
			extern void udc_disconnect (void);
			udc_disconnect ();
		}
	#endif

		/*启动内核前的设置,主要是协处理器的相关操作,包括关iCache和dCache等*/
		cleanup_before_linux ();
		
		/*这句是真正启动内核的语句,到此uboot的使命就结束了;
			theKernel是内核的入口地址,也就是内核执行的第一句代码;
			第1个参数固定为0,第2个参数是机器码,第3个参数是传递给内存的传参tag的首地址*/
		theKernel (0, machid, bd->bi_boot_params);
		/* does not return */
		return;

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

uboot中启动linux内核的函数——do_bootm_linux函数解析 的相关文章

  • 如何使用 sed 仅删除双空行?

    我找到了这个问题和答案 https stackoverflow com questions 4651591 howto use sed to remove only triple empty lines关于如何删除三重空行 但是 我只需要对
  • 信号处理程序有单独的堆栈吗?

    信号处理程序是否有单独的堆栈 就像每个线程都有单独的堆栈一样 这是在 Linux C 环境中 来自 Linux 手册页signal 7 http kernel org doc man pages online pages man7 sign
  • PHP 致命错误:未找到“MongoClient”类

    我有一个使用 Apache 的网站 代码如下 当我尝试访问它时 我在 error log 中收到错误 PHP Fatal Error Class MongoClient not found 以下是可能错误的设置 但我认为没有错误 php i
  • 如何更改 Ubuntu 14.04 上的 php-cli 版本?

    我是 Linux 新手 在篡改时破坏了一些 php 设置 如果我执行一个包含以下内容的 php 脚本 phpinfo 它显示 php 版本为 5 6 但通过命令行 如果我运行php v它返回 7 0 版本 我想让两个版本匹配 我怎样才能修复
  • QFileDialog::getSaveFileName 和默认的 selectedFilter

    我有 getSaveFileName 和一些过滤器 我希望当用户打开 保存 对话框时选择其中之一 Qt 文档说明如下 可以通过将 selectedFilter 设置为所需的值来选择默认过滤器 我尝试以下变体 QString selFilte
  • 为什么我收到的数据包数据大小大于mss?

    我在两台 PC 上使用 ifconfig ethX mtu 300 修改了 MTU 并使用 netperf 测试网络 我用 WireShark 嗅探了 SYN 数据包中的 MSS 260 但我得到了一些大于 260 的数据包 为什么 嗅探器
  • 在 Mac OS X 上构建 Linux 内核

    我正在做一个修改Linux内核的项目 我有一台桌面 Linux 机器 在上面构建内核没有问题 不过 我要去旅行 我想在途中工作 我只有一台 MacBook 当我尝试构建 Linux 内核时 它抱怨说elf h was not found 我
  • Bash 解析和 shell 扩展

    我对 bash 解析输入和执行扩展的方式感到困惑 对于输入来说 hello world 作为 bash 中的参数传递给显示其输入内容的脚本 我不太确定 Bash 如何解析它 Example var hello world displaywh
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 为什么 Linux perf 使用事件 l1d.replacement 来处理 x86 上的“L1 dcache misses”?

    在英特尔 x86 上 Linux用途 https stackoverflow com a 52172985 149138事件l1d replacements来实施其L1 dcache load misses event 该事件定义如下 计数
  • Linux中的CONFIG_OF是什么?

    我看到它在很多地方被广泛使用 但不明白在什么场景下我需要使用它 What is 配置 OF OF 的全名是什么 打开固件 这是很久以前发明的 当时苹果公司正在生产基于 PowerPC CPU 的笔记本电脑 而 Sun Microsystem
  • 无法从 jenkins 作为后台进程运行 nohup 命令

    更新 根据下面的讨论 我编辑了我的答案以获得更准确的描述 我正在尝试从詹金斯运行 nohup 命令 完整的命令是 nohup java jar home jar server process 0 35 jar prod gt gt var
  • Linux中的定时器类

    我需要一个计时器来以相对较低的分辨率执行回调 在 Linux 中实现此类 C 计时器类的最佳方法是什么 有我可以使用的库吗 如果您在框架 Glib Qt Wx 内编写 那么您已经拥有一个具有定时回调功能的事件循环 我认为情况并非如此 如果您
  • 使用 sed 更新 xml 属性(Windows + cygwin 和 Linux)?

    我需要使用 sed 命令对 xml 文件进行更新 但我在这方面遇到了麻烦 它需要在 Windows 使用 cygwin 和 Linux 上运行 XML 具有以下元素
  • fopen 不返回

    我在 C 程序中使用 fopen 以只读模式 r 打开文件 但就我而言 我观察到 fopen 调用没有返回 它不返回 NULL 或有效指针 执行在 fopen 调用时被阻止 文件补丁绝对正确 我已经验证过 并且不存在与权限相关的问题 任何人
  • 域套接字“sendto”遇到“errno 111,连接被拒绝”

    我正在使用域套接字从另一个进程获取值 就像 A 从 B 获取值一样 它可以运行几个月 但最近 A 向 B 发送消息时偶尔会失败 出现 errno 111 连接被拒绝 我检查了B域套接字绑定文件 它是存在的 我也在另一台机器上做了一些测试 效
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • arm64和armhf有什么区别?

    Raspberry Pi Type 3 具有 64 位 CPU 但其架构不是arm64 but armhf 有什么区别arm64 and armhf armhf代表 arm hard float 是给定的名称Debian 端口 https
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • 无法使用 wget 在 CentOS 机器上安装 oracle jdk

    我想在CentOS上安装oracle java jdk 8 我无法安装 java jdk 因为当我尝试使用命令安装 java jdk 时 root ADARSH PROD1 wget no cookies no check certific

随机推荐

  • js实现多选,全选,反选的功能

    需求 在前端页面实现一个多选的模块 我们可以全选 不选 多选 反选 思路 需要按钮或者是多选框 最主要的是什么 能获取到四个等待选择的对象 足球 篮球这些 还有一个 被选中的状态是什么 没有被选中的状态又是什么 通过查阅手册 第三项 che
  • 没有网关可以互相通信_网络知识,分分钟通俗了解网关、DNS、子网掩码、MAC地址、DHCP...

    弱电智能化工程2018 什么是网关 DNS 子网掩码 它有什么作用 确实 我们平时在网络中总是在不断的提到网关 却很少真正的去了解它 一 什么是网关 1 什么是网关 网关是一种充当转换重任的计算机系统或设备 在使用不同的通信协议 数据格式或
  • 电学基本概念

    电压 电流 电阻 功率 交流 直流 电压 电流 电阻功率之间关系
  • 如何简单理解概率分布函数和概率密度函数?

    本篇文章是在 应该如何理解概率分布函数和概率密度函数 的基础上整理来的 非常感谢原作者 目录 1 先从离散型随机变量和连续性随机变量说起 2 离散型随机变量的概率函数 概率分布和分布函数 2 1 概率函数和概率分布 2 1 1 概率函数 2
  • MyBatis分页PageHelper和RowBounds区别

    测试机器 笔记本 win7 cpu i5 4210M 8G内存 测试数据 单表 181w数据 mybatis常用分页组件PageHelper和RowBounds 1 性能对比 2 原理分析 PageHelper 物理分页 通过拦截器加 li
  • 用chrony使两台机器之间同步时间

    用chrony使两台机器之间同步时间 chrony服务部署 两台机器 a 第一台机器从阿里云同步时间 第二台机器从第一台机器同步时间 b 第一台服务器使用系统时间作为第二台服务器的时钟源 第一台服务器层级设置为6 a 在第一台机器的 etc
  • [Qt] [adb] Qt中通过adb给手机发送指令

    Qt中给手机发送adb指令 需要通过QProcess类来操作 通过adb device获取设备连接状态 void DeviceInfo findDevice 发送adb指令 QProcess processFindDev gt start
  • 固态硬盘usb测试软件,固态硬盘检测修复坏道三级OP设置软件HDAT2 5.3 ISO版

    HDAT2是用于测试或诊断硬盘 SSD和USB设备的程序 这里分享的是iso版 更新日期是2016年11月 你必须把它用ultraiso做成U盘启动盘 启动电脑后在dos环境下使用 这里介绍的主要功能是修复ssd的坏道 也就是Secure
  • 创建一个自定义插件,实现一个登录页面

    运行结果如下 话不多说 直接开整 div div
  • 05【掌握】 SpringBoot 清空Redis所有缓存

    package top yangbuyi system controller import org springframework beans factory annotation Autowired import org springfr
  • css3顺时,CSS3(transforms)

    transforms 主要包括了两个属性 transform 只可以转换 由盒子模型定位的元素 而根据经验也就是 具备了display block这个属性 由盒子模型定位元素 transform 指定作用在元素上的变形 取值为空格分隔的一些
  • Spring Cloud灰度部署

    1 背景 灰度部署 在我们系统发布生产环境时 有时为了确保新的服务逻辑没有问题 会让一小部分特定的用户来使用新的版本 比如客户端的内测版本 而其余的用户使用旧的版本 那么这个在Spring Cloud中该如何来实现呢 负载均衡组件使用 Sp
  • 【安卓学习之工具学习】网络通信测试工具-socket/post/get

    在安卓开发中 网络请求基本上都有用到 有时候我们通信出现问题 我们不知道是服务端问题还是客户端问题 就可以使用第三方的工具来测试 以保证能更好的确定出现bug的方向 当然也有时候接手别人开发的app 但又不知道里面的通信协议 也可以通过这个
  • Visio制图拷贝到word文档中显示不全、只显示一行

    问题描述 Visio 2016绘制技术流程图完毕 拷贝到Word 2016中时 只显示一行 最底部部分 上面其他部分只能看到最外边边框其他部分侵入上方文本区 且不显示 解决方案 选中要插入的行 设置行间距为1 5倍 我的问题是解决了 欢迎补
  • NVDLA系列之C-model:cvif<100>

    NV NVDLA cvif cpp pdp2cvif wr req b transport void NV NVDLA cvif pdp2cvif wr req b transport int ID nvdla dma wr req t p
  • JDBC中对url的一些理解

    大家都知道 用java来连接数据库 一般都是class forName 然后用DriverManager来生成一个Connection 生成Connection的method为 DriverManager getConnection 其中里
  • STM32_USART 串口通讯

    STM32 USART 串口通讯 通信方式的分类 按照通信方式分类 按照数据传送方向分类 通信接口及其说明如下图所示 STM32的串口通信 引脚接线 串口通讯的过程 串口发送数据 串口接收数据 USART中断请求 通信方式的分类 按照通信方
  • 【数据库1】mysql,DDL/DML/DQL,外键约束/多表/子查询,事务/连接池

    文章目录 1 mysql安装 存储 集合 内存 临时 IO流 硬盘 持久化 1 1 服务端 双击mysql installer community 5 6 22 0 msi 1 2 客户端 命令行输入mysql u 实际是如下安装路径的bi
  • 计算机怎么把硬盘分成几个,如何把电脑的一个盘的容量分给另外一个盘

    把电脑中的一个分区闲置容量分去给另外一个分区 今天就来分享如何把其中一个分区的闲置容量分去另外一个分区 以我的操作为例子 如我要把 F盘 的闲置2G空间 分给 G盘 如图所示 F盘是 4 99GB 的容量 G盘是 2 99GB 的容量 首先
  • uboot中启动linux内核的函数——do_bootm_linux函数解析

    1 do bootm linux函数解析 do bootm linux函数是专门启动linux内核的 包括以下功能 1 确认当前的机器码 可以从全局变量gd或者环境变量machid中获取 其中环境变量machid的优先级高于gd中的机器码