Linux-uboot-学习笔记(学习笔记(8):):uboot启动内核启动内核
Linux-uboot-学习笔记(学习笔记(8):):uboot启动内核启动内核
uboot启动时,在执行到启动时,在执行到theKernel指针时即跳转到内核执行,也就标志着指针时即跳转到内核执行,也就标志着uboot的结束。在此之前的结束。在此之前uboot要进行内核启动的最后准备:从内核镜像的部署位置将内核搬移到要进行内核启动的最后准备:从内核镜像的部署位置将内核搬移到DDR中,中,
校验内核格式,准备内核传的参数,跳转到校验内核格式,准备内核传的参数,跳转到theKernel去执行内核。去执行内核。
一、一、uboot内核是什么内核是什么
内核实质上是一个大的、复杂的“裸机程序”,和uboot、和其他裸机程序并没有本质区别。
区别就是操作系统运行起来后在软件上分为内核层和应用层内核层和应用层,分层后两层的权限不同权限不同,内存访问和设备操作的管理上更加精细(内核可以随便访问各种硬件,而应用程序只能被限制
的访问硬件和内存地址)。
直观来看:uboot的镜像是u-boot.bin,linux系统的镜像是zImage,这两个东西其实都是两个裸机程序镜像。从系统的启动角度来讲,内核其实就是一个大的复杂点裸机程序。
uboot是无条件启动的,从零开始启动的。而内核是不能开机自动完全从零开始启动的,内核启动要别人帮忙。uboot要帮助内核实现重定位(从要帮助内核实现重定位(从SD卡到卡到DDR),),uboot还要给内核还要给内核
提供启动参数。提供启动参数。
二、特定的分区部署二、特定的分区部署
一个完整的软件+硬件的嵌入式系统,静止时(未上电时)bootloader、kernel、rootfs等必须的软件都以镜像的形式存储在启动介质中以镜像的形式存储在启动介质中(X210中是iNand/SD卡);运行时都是在在DDR
内存中运行的内存中运行的,与存储介质无关。上面2个状态都是稳定状态,第3个状态是动态过程,即从静止态到运行态的过程,也就是启动过程。
动态启动过程就是一个从动态启动过程就是一个从SD卡逐步搬移到卡逐步搬移到DDR内存,并且运行启动代码进行相关的硬件初始化和软件架构的建立,最终达到运行时稳定状态。内存,并且运行启动代码进行相关的硬件初始化和软件架构的建立,最终达到运行时稳定状态。
静止时u-boot.bin zImage rootfs都在SD卡中,他们不可能随意存在SD卡的任意位置,因此需要对SD卡进行一个分区,然后将各种镜像各自存在各自的分区中,这样在启动过程中
uboot、内核等就知道到哪里去找谁。(uboot和kernel中的分区表必须一致,同时和SD卡的实际使用的分区要一致)
uboot在第一阶段中进行重定位时将第二阶段(整个uboot镜像)加载到DDR的0xc3e00000地址处,这个地址就是uboot的链接地址。
内核也有类似要求,uboot启动内核时将内存从SD卡读取放到DDR中(其实就是个重定位的过程),不能随意放置,必须放在内核的链接地址处,否则启动不起来。譬如我们使用的
内核链接地址是0x30008000。
三、三、uboot内核启动过程内核启动过程
1. 启动内核第一步:加载内核到启动内核第一步:加载内核到DDR中中
uboot要启动内核,分为2个步骤:第一步是将内核镜像从启动介质中加载到第一步是将内核镜像从启动介质中加载到DDR中,第二步是去中,第二步是去DDR中启动内核镜像中启动内核镜像。(内核代码根本就没考虑重定位,因为内核知道会有uboot之
类的把自己加载到DDR中链接地址处的,所以内核直接就是从链接地址处开始运行的内核直接就是从链接地址处开始运行的)
内核镜像最初在SD卡的kernel分区分区,因此在内核启动前需要从SD卡的kernel分区读取内和镜像(zImage-qt)并加载到DDR中。
通过uboot指令读取:movi read kernel 30008000
通过tftp加载:tftp 0x30008000 zImage-qt(加载前要将zImage-qt放到tftpboot文件夹下)
加载完成后,通过指令启动内核:bootm 0x30008000
最终结果要的是内核镜像到DDR中特定地址即可,不管内核镜像是怎么到DDR中的。以上2种方式各有优劣。产品出厂时会设置为从SD卡中启动(客户不会还要搭建tftp服务器才能
用···);tftp下载远程启动这种方式一般用来开发下载远程启动这种方式一般用来开发。
2. 启动内核第二步:校验内核格式启动内核第二步:校验内核格式
首先说明内核镜像大概有三种版本:Image、、zImage和和uImage。
linux内核经过编译后也会生成一个elf格式的可执行程序,叫vmlinux或或vmlinuz,这个就是原始的未经任何处理加工的原版内核elf文件;嵌入式系统部署时烧录的一般不是这个
vmlinuz/vmlinux,而是要用objcopy工具去制作成烧录镜像格式(就是u-boot.bin这种,但是内核没有.bin后缀),经过制作加工成烧录镜像的文件就叫Image(制作把78M大的精简成
了7.5M,因此这个制作烧录镜像主要目的就是缩减大小,节省磁盘)。
实际上linux的作者们觉得Image还是太大了所以对Image进行了压缩,并且在image压缩后的文件的前端附加了一部分解压缩代码(这部分未经压缩)前端附加了一部分解压缩代码(这部分未经压缩)。构成了一个压缩格式的镜像就
叫zImage。
uboot为了启动linux内核,还发明了一种内核格式叫uImage。uImage是由zImage加工得到的,uboot中有一个工具,可以将zImage加工生成uImage。注意:uImage不关linux内核的
事,linux内核只管生成zImage即可,uboot中的中的mkimage工具再去由工具再去由zImage加工生成加工生成uImage来给来给uboot启动启动。这个加工过程其实就是在这个加工过程其实就是在zImage前面加上前面加上64字节的字节的uImage的头信息的头信息
即可。即可。
do_bootm函数中一直到397行的after_header_check这个符号处,都是在进行镜像的头部信息校验镜像的头部信息校验。校验时就要根据不同种类的image类型进行不同的校验。所以do_bootm函数的核
心就是去分辨传进来的image到底是什么类型,然后按照这种类型的头信息格式去校验。校验通过则进入下一步准备启动内核;如果校验失败则认为镜像有问题,所以不能启动。
((1))zImage启动启动
对于zImage的魔数,如果校验成功了,则通过zImage的格式启动。因此我们可以查看zImage的内容,看看魔数所在的位置与检测时的方法是否对应。