IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> bootz启动linux内核 -> 正文阅读

[系统运维]bootz启动linux内核

分析完uboot启动流程,该篇分析bootz启动linux内核。如下图所示,bootz 命令的执行函数为 do_bootz,主要分为三个阶段:①bootz_start;②bootm_disable_interruptes;③do_bootm_states
在这里插入图片描述

1、bootz_start函数

bootz_start()主要分为四个阶段:① do_bootm_states();② images->ep;③ bootz_setup();④ bootm_find_images()
在这里插入图片描述
(1) do_bootm_states函数,用于执行 BOOTM_STATE_START 状态。事实上do_bootm_states函数有下面四种状态:

BOOTM_STATE_OS_PREP
BOOTM_STATE_OS_FAKE_GO
BOOTM_STATE_OS_GO
BOOTM_STATE_START

但是本阶段只执行执行 BOOTM_STATE_START 状态,该状态会调用bootm_start()函数,函数代码如下:

static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc,
		       char * const argv[])
{
	memset((void *)&images, 0, sizeof(images));//清空images
	images.verify = getenv_yesno("verify");//初始化verfify成员

	boot_start_lmb(&images);

	bootstage_mark_name(BOOTSTAGE_ID_BOOTM_START, "bootm_start");
	images.state = BOOTM_STATE_START;//设置状态为BOOTM_STATE_START

	return 0;
}

由代码可知,bootm_start()函数用于对images全局变量清零。
(2) images->ep = simple_strtoul(argv[0], NULL, 16);该行用于设置 images 的 ep 成员变量,也就是系统镜像的入口点,使用 bootz 命令启动系统的时候就会设置系统在 DRAM 中的存储位置,这个存储位置就是系统镜像的入口点,因此 images->ep=0X80800000。
(3) bootz_setup()函数,该函数用于判断当前的系统镜像文件是否为 Linux 的镜像文件,并且打印出镜像相关信息。
(4) bootm_find_images()函数,该函数中最重要的函数为boot_get_fdt()函数,用于查找设备树,然后将设备树起始地址和长度,写入到images的ft_addr和ft_len成员变量中。并且在使用 bootz 启动 Linux 的时候设备树存放在DRAM 中,因此 images.ft_addr=0X83000000,长度根据具体的设备树文件而定,如设备树文件长度为 0X8C81,则 images.ft_len=0X8C81。

2、bootm_disable_interrupts函数

bootm_disable_interrupts函数用于关闭中断

3、do_bootm_states函数

在执行do_bootm_states函数之前,先执行命令images.os.os = IH_OS_LINUX,表示要启动linux系统。do_bootm_states函数执行过程如下所示:
在这里插入图片描述
do_bootz 最后调用函数do_bootm_states,而在此之前bootz_start函数就调用过该函数,只不过执行的状态是BOOTM_STATE_START,剩下的三种状态将在该函数执行。

BOOTM_STATE_OS_PREP
BOOTM_STATE_OS_FAKE_GO//该状态由于没用使能TRACE功能,所以没有被执行
BOOTM_STATE_OS_GO

(1) bootm_os_get_boot_func函数,用于查找Linux内核启动函数。找到 Linux内核启动函数do_bootm_linux,赋值给boot_fn。
(2) boot_fn(BOOTM_STATE_OS_PREP, argc, argv, images);处理 BOOTM_STATE_OS_PREP 状态时,函数实际上是执行实际上是执行的 do_bootm_linux 函数,do_bootm_linux调用boot_prep_linux函数启动Linux之前做一些其他处理,比如在设备树的chosen节点下添加子节点bootargs,bootargs子节点存放bootargs环境变量。
(3)boot_selected_os函数,当状态处于BOOTM_STATE_OS_GO时,boot_selected_os被执行,由boot_selected_os第 5 个参数为 Linux 系统启动函数 do_bootm_linux,可知 boot_selected_os用于启动 Linux 内核。

int boot_selected_os(int argc, char * const argv[], int state,
	bootm_headers_t *images, boot_os_fn *boot_fn)

3.1 do_bootm_linux

do_bootm_linux 为最终启动 Linux 内核的函数,结合下面代码分析可知:当参数flag等于BOOTM_STATE_OS_GO或者BOOTM_STATE_OS_FAKE_GO的话就执行 boot_jump_linux 函数。 boot_selected_os 函数在调用 do_bootm_linux 的时候会将 flag设置为 BOOTM_STATE_OS_GO。

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;
}

执行函数 boot_jump_linux,该函数主要由三个阶段:
(1) kernel_entry,该函数有三个参数: zero, arch, params,第一个参数 zero 同样为 0;第二个参数为机器 ID; 第三个参数 ATAGS 或者设备树(DTB)首地址, ATAGS 是传统的方法,用于传递一些命令行信息,如果使用设备树的话就要传递设备树(DTB)。实际上通常使用设备树,故第三个参数最重要。并且kernel_entry 并不是 uboot 定义的,而是 Linux 内核定义的,Linux 内核镜像文件的第一行代码就是函数 kernel_entry,而 images->ep 保存着 Linux内核镜像的起始地址,起始地址保存的正是 Linux 内核第一行代码。

void (*kernel_entry)(int zero, int arch, uint params);
...
kernel_entry = (void (*)(int, int, uint))images->ep;

(2) announce_and_cleanup函数,用于输出Starting kernel,并且做一些清理工作。
(3) kernel_entry(0, machid, r2), 该函数启动Linux内核。

在这里插入图片描述

4、整体流程详细图

至此,uboot 启动Linux内核完成。事实上,uboot启动流程与bootz启动Linux内核看不懂对uboot移植也没有关系,了解就行,不必强求。最后附上bootz启动Linux内核全部流程图:
在这里插入图片描述

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-03-16 22:58:21  更:2022-03-16 23:00:19 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 1:34:17-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码