《Linux内核深度解析》--U-Boot内核引导与初始化
[复制链接]
本帖最后由 dirty 于 2024-12-31 21:09 编辑
本篇学习与笔记梳理U-Boot内核引导与初始化。
处理器上电以后,首先执行引导程序,引导程序把内核加载到内存,然后执行内核内核初始化完成以后,启动用户空间的第一个进程。
处理器在上电时自动把程序计数器设置为处理器厂商设计的某个固定值,对于ARM64处理器,这个固定值是0。处理器的内存管理单元(Memory Management Unit,MMU)负责把虚拟地址转换为物理地址。嵌入式设备通常使用NOR闪存作为只读存储器来存放引导程序。NOR闪存的容量比较小,最小读写单位是字节,程序可以直接在芯片内执行。从物理地址0开始的一段物理地址空间被分配给 NOR 闪存。
引导程序
嵌入式设备通常使用 U-Boot 作为引导程序。U-Boot(Universal Boot Loader)是德国DENX软件工程中心开发的引导程序,是遵循GPL条款的开源项目。下面是U-Boot获取地址,U-Boot资源可在GitLab克隆获取https://source.denx.de/u-boot/u-boot.git ,可以看到一直有更新和维护。
鉴于该书出于2017年,选用当时U-Boot版本,这里引用@beyond_笑谈网友u-boot-2017.09.tar,也可以在上面history里搜寻查找。我们在Ubuntu下解压,tar -xvpjf u-boot-2017.09.tar.bz2,解压后如下:
ARM64 处理器的 U-Boot 程序的执行过程,入口是文件“archarm/cfarmv8/start.S”定义的标号 start。
这里对照 U-Boot源码与书籍,书籍中关键地方代码作了中文注释,且源文件路径也会在代码讲解前表明,很是便于读者阅读理解。上面可以看到,标号 start 是 U-Boot程序的入口,直接跳转到标号reset 执行。
第二阶段程序加载器。U-Boot 分为 SPL 和正常的 U-Boot程序两个部分,如果想要编译为 SPL,需要开启配置宏CONPIG_SPL_BUILD。SPL是“Secondary Program Loader”的简称,即第二阶段程序加载器,第二阶段是相对于处理器里面的只读存储器中的固化程序来说的,处理器启动时最先执行的是只读存储器中的固化程序。
U-Boot 程序初始化完成后,准备处理命令,这是通过数组 init sequencer的最后一个函数 run main loop实现的。
上面讲了内核引导,下面是内核初始化部分。
内核初始化
内核初始化分为汇编语言部分和C语言部分。
汇编语言部分,ARM64架构的内核的入口是标号_head,直接跳转到标号stext。
内核初始化的C语言部分入口是函数start kermel,函数 start_kernel首先初始化基础设施,即初始化内核的各个子系统,然后调用函数rest_init。
init 进程
init 进程是用户空间的第一个进程,负责启动用户程序。Linux系统常用的imnit程序有sysvinit、busybox init、upstart、systemd和 procd。
通过资源准备与对照概述梳理学习,对内核引导与初始化有了整体认识和进一步深入了解。代码部分主要涉及使用汇编语言,会略有些晦涩,参考书籍代码解说和流程说明,加强认识与理解,对细节部分可以按需研究理解。整体来说,对深入了解Linux内核很有助益。
|