bootz启动 Linux内核涉及do_bootm_linux 函数

news2024/11/17 2:31:46

一.  bootz启动Linux

uboot 启动Linux内核使用bootz命令。当然还有其它的启动命令,例如,bootm命令等等。

本文只分析 bootz命令启动 Linux内核的过程中涉及的几个重要函数。具体分析  do_bootm_linux函数执行过程。

本文继上一篇文章,地址如下:

bootz启动 Linux内核涉及 bootm_os_get_boot_func 函数-CSDN博客

二.   bootz 启动 Linux 内核涉及函数

2.  do_bootm_linux 函数

经过前面的分析,我们知道了 do_bootm_linux 函数就是最终启动 Linux 内核的函数,此函数定

义在文件 arch/arm/lib/bootm.c,函数内容如下:

int do_bootm_linux(int flag, int argc, char * const argv[],
		   bootm_headers_t *images)
{
	/* No need for those on ARM */
	if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
		return -1;

	if (flag & BOOTM_STATE_OS_PREP) {
		boot_prep_linux(images);
		return 0;
	}

	if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
		boot_jump_linux(images, flag);
		return 0;
	}

	boot_prep_linux(images);
	boot_jump_linux(images, flag);
	return 0;
}

do_bootm_linux 函数:

第13行,如果参数flag等于BOOTM_STATE_OS_GO或者BOOTM_STATE_OS_FAKE_GO ,就行 boot_jump_linux 函数。

boot_selected_os 函数在调用 do_bootm_linux 时,会将 flag 设置为 BOOTM_STATE_OS_GO。


第 14 行,执行函数 boot_jump_linux,此函数定义在文件 arch/arm/lib/bootm.c 中,函数内容如下:

static void boot_jump_linux(bootm_headers_t *images, int flag)
{
#ifdef CONFIG_ARM64
..........
#else
	unsigned long machid = gd->bd->bi_arch_number;
	char *s;
	void (*kernel_entry)(int zero, int arch, uint params);
	unsigned long r2;
	int fake = (flag & BOOTM_STATE_OS_FAKE_GO);

	kernel_entry = (void (*)(int, int, uint))images->ep;

	s = getenv("machid");
	if (s) {
		if (strict_strtoul(s, 16, &machid) < 0) {
			debug("strict_strtoul failed!\n");
			return;
		}
		printf("Using machid 0x%lx from environment\n", machid);
	}

	debug("## Transferring control to Linux (at address %08lx)" \
		"...\n", (ulong) kernel_entry);
	bootstage_mark(BOOTSTAGE_ID_RUN_OS);
	announce_and_cleanup(fake);

	if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
		r2 = (unsigned long)images->ft_addr;
	else
		r2 = gd->bd->bi_boot_params;

.............
			kernel_entry(0, machid, r2);
	}
#endif
}

3~5 行之间的代码,是 64 ARM 芯片对应的代码, Cortex-A7 32 位芯片,因此用不到。

6 行,变量 machid 保存机器 ID

如果不使用设备树,这个机器 ID 会被传递给 Linux 内核,Linux 内核会在自己的机器 ID 列表里面查找是否存在与 uboot 传递进来的 machid 匹配的项目,如果存在就说明 Linux 内核支持这个机器,则 Linux 就会启动!

如果使用设备树的话,这个 machid 就无效了,设备树文件中存有一个“兼容性”这个属性,Linux 内核会比较“兼容性”属性的值(字符串)来查看是否支持这个机器。

第 8 行, kernel_entry 函数,名字“内核_ 进入”,说明此函数是进入 Linux 内核的,也 就是最终的大 boos !!
此函数有三个参数: zero arch params
第一个参数 zero 同样为 0
二个参数为机器 ID
第三个参数 ATAGS 或者设备树 (DTB) 首地址, ATAGS 是传统的方法,用 于传递一些命令行信息,如果使用设备树的话就要传递设备树 (DTB)
12 行,获取 kernel_entry 函数,函数 kernel_entry 并不是 uboot 定义的,而是 Linux 核定义的。
Linux 内核镜像文件的第一行代码就是函数 kernel_entry ,而 images->ep 保存着 Linux 内核镜像的起始地址,起始地址保存的正是 Linux 内核第一行代码!
26 行,调用 announce_and_cleanup函数, 来打印一些信息并做一些清理工作,此函数定 义在文件 arch/arm/lib/bootm.c 中,函数内容如下:
static void announce_and_cleanup(int fake)
{
	printf("\nStarting kernel ...%s\n\n", fake ?
		"(fake run for tracing)" : "");
	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_HANDOFF, "start_kernel");
.............
	cleanup_before_linux();
}

3 行,在启动 Linux 之前输出 “ Starting kernel ... ” 信息,所打印信息如下:

7 行,调用 cleanup_before_linux 函数做一些清理工作。

回到 boot_jump_linux函数:
28~31 行是设置寄存器 r2 的值?
为什么要设置 r2 的值呢?Linux 内核一开始是汇编代码,因此, kernel_entry函数就是个汇编函 数。向汇编函数传递参数要使用 r0 r1 r2( 参数数量不超过 3 个的时候 ) ,所以 r2 寄存器就是 kernel_entry 函数的第三个参数。

28 行,如果使用设备树的话,r2 应该是设备树的起始地址,而设备树地址保存在 images

ftd_addr 成员变量中。

30 行,如果不使用设备树的话, r2 应该是 uboot 传递给 Linux 的参数起始地址,也就 是环境变量 bootargs 的值。

34 行,调用 kernel_entry 函数进入 Linux 内核,此行将一去不复返, uboot 的使命也就 完成了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1082745.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue3 + element Plus实现表格根据关键字合并行,并实现行的增删改操作

根据关键字合并表格 1.实现初始化表格2.实现添加班级与学生的功能3.添加的弹窗4.删除班级5.删除学生 首先看最终实现的效果 1.实现初始化表格 <template><div class"main-page"><div class"flex-end"><div class"public-search…

Service Weaver:以单体形式编码,以微服务形式部署

分布式应用的主流架构模式演化为微服务架构已经有些年头了。微服务、DevOps、持续交付和容器技术(k8s)是构成最初云原生概念[1]的核心要素。它们相生相拌&#xff0c;共同演进&#xff0c;并推动了云计算全面进入云原生时代。 云原生应用普遍采用微服务架构&#xff0c;遗留的单…

阿里云r7服务器内存型CPU采用

阿里云服务器ECS内存型r7实例是第七代内存型实例规格族&#xff0c;CPU采用第三代Intel Xeon可扩展处理器&#xff08;Ice Lake&#xff09;&#xff0c;基频2.7 GHz&#xff0c;全核睿频3.5 GHz&#xff0c;计算性能稳定&#xff0c;CPU内存比1:8&#xff0c;2核16G起步&#…

HBase 表如何按照某表字段排序后顺序存储的方法?

首先需要明白HBase表的排序规则&#xff1a; &#xff08;1&#xff09;rowkey排序&#xff08;字典排序&#xff09;——升序 &#xff08;2&#xff09;Column排序&#xff08;字典排序&#xff09;——升序 &#xff08;3&#xff09;时间戳排序——降序 rowkey 字典序排序…

DeskHIL桌面级仿真测试平台

硬件在环测试系统&#xff0c;一直是汽车电子功能测试的重要工具。随着测试工程师对硬件在环系统的要求越来越高&#xff0c;对其高集成性、便携性的需求也愈发强烈。由于硬件在环系统设计复杂、定制化程度高等因素&#xff0c;成本一直居高不下&#xff0c;因此&#xff0c;市…

C++基础入门学习笔记

问题1&#xff1a;什么是 C 中的多态&#xff1f;如何实现多态&#xff1f; 回答1&#xff1a;C 中的多态是指同一种类型的实体&#xff0c;可以在不同的情况下表现出不同的行为。实现多态的方式有两种&#xff1a;虚函数和模板函数。虚函数是在基类中声明为虚函数的函数&…

c++视觉处理---仿射变换和二维旋转变换矩阵的函数

仿射变换cv::warpAffine cv::warpAffine 是OpenCV中用于执行仿射变换的函数。仿射变换是一种线性变换&#xff0c;可用于执行平移、旋转、缩放和剪切等操作。下面是 cv::warpAffine 函数的基本用法&#xff1a; cv::warpAffine(src, dst, M, dsize, flags, borderMode, borde…

嵌入式Linux裸机开发(七)UART串口、IIC、SPI通信

系列文章目录 文章目录 系列文章目录前言UART串口通信介绍UART配置 IIC介绍I.MX6U 的 I2C SPI介绍I.MX6U ECSPI 结语 前言 大概学完这三种通信后&#xff0c;之后就先去学系统移植&#xff0c;其他的先暂时放下 UART串口通信 介绍 串口全称叫做串行接口&#xff0c;通常也叫…

Maven创建父子工程详解

引言 在微服务盛行的当下&#xff0c;我们创建的工程基本都是父子工程&#xff0c;我们通过父工程来引入jar&#xff0c;定义统一的版本号等&#xff0c;这样我们在子工程中就可以直接引用后使用了&#xff0c;而不需要去重复的声明版本号等&#xff0c;这样会更方便对整个项目…

Linux中Locate命令查找不全

Locate locate(locate) 命令用来查找文件或目录。 locate命令要比find -name快得多&#xff0c;原因在于它不搜索具体目录&#xff0c;而是搜索一个数据库/var/lib/mlocate/mlocate.db 。这个数据库中含有本地所有文件信息。Linux系统会自动创建这个数据库&#xff0c;并且每天…

【ElasticSearch】深入探索 DSL 查询语法,实现对文档不同程度的检索,以及对搜索结果的排序、分页和高亮操作

文章目录 前言一、Elasticsearch DSL Query 的分类二、全文检索查询2.1 match 查询2.2 multi_match 查询 三、精确查询3.1 term 查询3.2 range 查询 四、地理坐标查询4.1 geo_bounding_box 查询4.2 geo_distance 查询 五、复合查询5.1 function score 查询5.2 boolean 查询 六、…

2023年中国溶瘤病毒药物上市产品、研发现状及行业市场规模前景[图]

溶瘤病毒&#xff08;Oncolyticvirus&#xff09;&#xff0c;是一类具有复制能力的肿瘤杀伤型病毒&#xff0c;溶瘤病毒根据所采用的毒株类型可以被分为天然病毒株&#xff08;野生型病毒株&#xff09;和基因改造病毒株两类&#xff0c;溶瘤病毒的种类也从最初的疱疹病毒发展…

使用c++视觉处理----canny 边缘检测、sobel边缘检测、scharr 滤波边缘检测

使用c视觉处理canny 边缘检测、sobel边缘检测、scharr 滤波边缘检测 #include <opencv2/opencv.hpp>int main() {// 读取图像cv::Mat image cv::imread("1.jpg", cv::IMREAD_GRAYSCALE); // 转为灰度图像if (image.empty()) {std::cerr << "无法加…

网络-网络状态网络速度

文章目录 前言一、网络状态二、网络速度 前言 本文主要记录如何监听网络状态和网络速度。 一、网络状态 获取当前网络状态: navigator.onLine // true:在线 false:离线监听事件&#xff1a;online&#xff08;联网&#xff09; 和 offline&#xff08;断网&#xff09; windo…

全国A级旅游景区清单数据(2023年更新)

全国A级旅游景区清单数据&#xff08;2023年更新&#xff09; 1.样本量&#xff1a;14847条 2.来源&#xff1a;政府公布资料 3.指标&#xff1a;景区名称、等级、所属省份、所属城市、所属区县、地址、当前等级评定时间、相关文件发布时间、坐标(GCJ02)Lng、坐标(GCJ02)Lat…

【Redis实战】分布式锁

分布式锁 synchronized只能保证单个JVM内部的线程互斥&#xff0c;不能保证集群模式下的多个JVM的线程互斥。 分布式锁原理 每个JVM内部都有自己的锁监视器&#xff0c;但是跨JVM&#xff0c;就会有多个锁监视器&#xff0c;就会有多个线程获取到锁&#xff0c;不能实现多JV…

分享一份关于 Rust 编程的学习指南

Rust是一种现代的系统级编程语言&#xff0c;以其注重内存安全、性能和并发性而闻名。学习Rust可以是一段有回报的旅程&#xff0c;为您打开构建强大高效应用的机会。无论您是经验丰富的开发者还是完全的初学者&#xff0c;本指南将通过精选的资源和技巧帮助您踏上Rust编程之旅…

【angular】实现简单的angular国际化(i18n)

文章目录 目标过程运行参考 目标 实现简单的angular国际化。本博客实现中文版和法语版。 将Hello i18n!变为中文版&#xff1a;你好 i18n!或法语版:Bonjour l’i18n !。 过程 创建一个项目&#xff1a; ng new i18nDemo在集成终端中打开。 添加本地化包&#xff1a; ng a…

景联文科技:3D点云标注应用场景和专业平台

3D点云技术之所以得到广泛发展和应用&#xff0c;主要是因为它能够以一种直观、真实和全面的方式来表示和获取现实世界中的三维信息。 3D点云的优势&#xff1a; 真实感和立体感&#xff1a;3D点云数据能够呈现物体的真实感和立体感&#xff0c;使观察者能够更直观地理解物体的…

Springboot整合阿里云OSS进行上传单个图片,多个图片,删除图片功能

1. 导入OSS依赖 <!-- 阿里云oss依赖 --><dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.10.2</version></dependency> 2. 进行OSS配置 package com.example.sushe…