uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

step1:

通过cpu分支找到U-boot.lds链接文件查看uboot启动入口为_start,这个入口在CPU分支下的start.S文件里面,其中第二个红框为uboot参数保存位置和标记uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

step2

打开start.S文件可以找到上面提的uboot启动入口标记_start这个地方就是uboot开始运行的地方

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

接着往下找,找到从汇编跳转到C代码的入口函数start_armboot,至此uboot启动的第一阶段完成,后面进入C代码部分

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

step3

在arch/arm/lib/下找到board.c文件并找到上述的C代码入口函数start_armboot,接下来就是uboot的第二阶段的初始化

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

初始化完成后,进入命令处理主循环

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

命令处理循环里处理的就是我们平时登录uboot打印出来的这些参数信息

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

其中红框部分为启动芯片时等待我们进入命令行所读秒的时间,当没有键盘输入时执行if里面的任务也就是加载kernel

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

在时间读秒完成前,当有按键输入时跳过上面的任务进入uboot命令行处理我们输入的命令,uboot所有的命令处理都依赖于下面的这个函数

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

step4

继续看kernel加载流程,在uboot启动我们没有就行任何操作时,将会读取bootcmd参数然后处理,下面我们进入run_command看实现过程

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

在run_command函数里面具体实现流程是:依次为获取一行字符串命令,查找命令,最后执行;这里的执行命令实际上是调用的do_bootm函数,函数在common下的cmd_bootm.c文件

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

具体怎么跳转调用的这个函数实际是通过U_BOOT_CMD这个宏来实现的,uboot命令都是通过这个宏将参数保存到flash的,

上面的操作在查找到参数后返回的实际是U_BOOT_CMD里面的结构体,而cmdtp->cmd所对应的函数实际就是下图中的do_bootm

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

step5

展开do_bootm函数,我们可以看到下面就是读取kernel的函数入口,具体实现不介绍无非就是读取flash然后解压,返回images这个结构体,里面包含了启动kernel需要的相关信息

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

最后do_bootm通过下面的接口跳转到do_bootm_linux函数执行,此函数就是kernel启动前uboot做最后的准备

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

其中boot_os是一个函数指针数组,里面保存了各种CPU所对应的kernel启动接口

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

step5

do_bootm_linux函数首先会去读取booargs里的参数最终将这些参数传递给kernel,同时会将kernel运行启动的第一个函数的地址传递给thekernel这个变量

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

最后uboot做推出前的准备,然后带着uboot传递给kernel参数执行theKernel这个函数,实际也就是kernel的第一个运行函数

uboot启动kernel的主线流程(基于hisi u-boot-2010.06)

至此uboot彻底执行完成退出,接下来由kernel主演!

本文只是理清楚uboot的运行流程,其中各个功能实现可以查看源码或网上查阅都能找到!