uboot启动分析
uboot是一个操作系统引导程序,多用于嵌入式设备上linux操作系统的引导。它是一个裸机程序,启动流程对其他裸机系统的启动都具有参考意义。下面,我们一起学习一下uboot的启动流程。
uboot的启动流程如下图所示:

我们对启动流程进行分析时,首先需要分析其链接脚本uboot.lds,从中了解大概的镜像布局,来知道程序的入口,以及一些特殊的地址变量定义,段等。
uboot程序的最开始为_start,从_start开始,是中断向量表的定义,这是大多数嵌入式裸机程序的共识,它们总是以复位中断为入口,进入整个系统。在uboot的_start标号开始处,我们可以看到复位中断的中断处理程序入口b reset,这样就来到了reset复位程序处。
reset程序是系统启动或复位后执行的程序,因此,其第一步就是设置处理器为SVC,关闭FRQ和IRQ,以确定处理器的工作模式(SVC:处于特权模式,且有自己的影子寄存器;关中断:中断尚没有配置,防止程序中断引起的程序异常);第二步,立马就进行中断向量表的设置,使中断能够执行,这对用户来说是一个高优先级的配置任务;第三步,也是做一些需要尽快确定的系统状态,比如关闭MMU,TLBs,D-cache,打开I-cache等相关的操作,以及初始化栈指针使得C语言函数能够调用;这样,复位后基本的极简环境就设置好了,我们可以进一步执行uboot相关程序,进入_main。
_main就是uboot的进一步初始化了,其有了前面搭建的极简环境。第一步初始化早期malloc,gd全局数组(gd全局数组用于保存uboot的一些重要信息,例如镜像的开始地址,镜像的重装载地址,malloc地址等等,这在后面再详细展开说明),调用board_init_f来执行一系列的函数来初始化硬件和gd结构体。其中,硬件初始化主要是初始化RAM(SRAM,DDR),因为后面重定位uboot需要对RAM进行读写操作,是必要的初始化;其主要的就是进行gd结构体的初始化,完成了完整的内存布局,和其中各种变量的赋值。第二步就是对自己进行重定位,这一部分挺重要的,主要就是需要先将自己拷贝到重定位地址,然后修改.rel.dyn段的位置无关码,最后对环境进行重新配置。因为运行地址进行了变化,所以程序必须是位置无关的,在编译的时候加上-pie选项就可以将它编译成位置无关的,其会将程序中的绝对地址的地址都收集到一个特殊的段rel.dyn中,那么,在进行重定位的时候,只需将该段中记录的地址的数进行一个修改即可,详细过程在后文讲述。第三步,调用board_init_r函数来执行一系列函数,进行最终的uboot初始化,包括malloc,各种板级初始化等,最后调用run_main_loop,进入uboot命令行处理程序。
run_main_loop在开始时会进入倒计时,倒计时结束则会执行bootcmd环境变量中的命令,启动linux之类的系统;在倒计时被按键中断的话会进入cli_loop命令行处理程序,接收用户的指令执行。这部分就是uboot的用户应用功能了,启动流程就到此结束。
以上就是uboot启动流程的全部内容了,关于linux启动方面不属于启动流程的内容,是uboot实现的功能,在以后的文章中说明。下面,就上面提到的几个中间进行展开介绍。
gd全局变量
gd全局变量贯穿整个uboot启动,在前面的启动流程中我们看到了其中存储了重要的地址信息,暗含了内存布局,下面是它的结构体原型中的某些项,我们一起来体会一下它究竟是哪些内容:
typedef struct global_data {
bd_t *bd;
unsigned long flags;
unsigned int baudrate;
unsigned long cpu_clk; /*

本文详细阐述了UBOOT启动流程,包括链接脚本分析、中断向量表设置、内存布局初始化、全局数据gd的结构和作用,以及重定位过程,强调了位置无关代码和环境配置的重要性。

1万+

被折叠的 条评论
为什么被折叠?



