Uboot的前尘后事

Uboot作为引导Linux Kernel启动的引导程序,从其开始被加载到DDR到bootdelay时间到执行bootcmd环境变量中的命令(bootm)从而结束生命,其一生都在为启动kernel而服务。

先说一下它的主要作用:

1.提供一个shell命令行,用以设定环境变量,执行各种命令,来影响kernel启动运行过程

2.必要的硬件初始化工作,如对内存DDR、系统时钟、串口等硬件的初始化

3.向kernel传参,以引导内核正常启动

4.将内核从启动介质中重定位到DDR中运行

.......(目前就想到这些,以后会补充)

再说一下它运行时的阶段,分为两步:

第一阶段是前16K大小,主要为汇编代码:soc上电后其内部irom内固化的代码会做一些初始化设置工作,如判断出启动介质的类型(emmc、nand、sd、inand)后初始化启动介质,初步设置系统时钟,然后从启动介质中将uboot的前16k加载到soc内部iram中运行,这前16k代码会初始化串口、DDR等硬件,然后从启动介质中将uboot整个加载到DDR中运行(重定位)。

第二阶段是整个uboot,主要为c代码:第一部分将uboot加载到DDR中后,uboot就在ddr中运行进入第二阶段,主要负责硬件的初始化、环境变量的设置以及向内核传参等工作。

小结一下:第一阶段注重SoC内部、第二阶段注重SoC外部Board内部

最后说下它启动内核的四个步骤:

第一步:将内核搬移到DDR中(内核重定位)
第二步:校验内核格式、CRC等(检验内核是zImage/uImage)
第三步:准备传参(tag形式传参)
第四步:跳转执行内核

补充一点关于uboot启动内核时的一些小细节。

1.内核最初被编译连接成elf格式的二进制可执行文件,这种文件可以再操作系统环境下直接运行,但无法被烧录,且文件占内存很大。因此需要对原始的elf文件进行处理操作(主要是压缩)形成image镜像文件,image文件再进一步处理(进一步压缩,且将头校验信息放到镜像头部)形成zImage镜像文件,这个文件才是最终被烧录运行的镜像文件(注意在zImage最头部还要添加未经压缩的解压缩代码,用来将之前压缩的内核代码解压开来)。

2.可见uboot要启动内核首先要对zImage文件进行解压缩,解压缩代码就添加在zImage的最开始处,且这段解压缩代码未被压缩,可供uboot直接调用,去压缩zImage中后面那部分被压缩的真正的内核程序。

3.uboot向内核传参时是通过cpu的特殊功能寄存器r0、r1、r2进行的,即调用函数:thekernel(0,machid,bd->bi_boot_params),三个参数分别存入r0、r1、r2中。第一个参数是默认参数0,第二个是设备机器码,内核校验用,第三个是uboot传给kernel的参数所在的内存地址,内核从该地址处可取出uboot传递的参数。

猜你喜欢

转载自blog.csdn.net/weixin_39330853/article/details/81503020