UBOOT学习总结

时间:2024-05-19 20:21:26

1. UBOOT的主要功能

UBOOT的主要任务是初始化硬件(如:串口,内存),然后将内核从Flash中读到RAM中,然后跳转到内核的入口点去运行,也就是启动操作系统。

 

UBOOTBIOS的差异:PC机的引导程序由BIOS和位于硬盘MBR中的引导程序(GRUBLILO)一起组成。BIOS在完成硬件检测和资源分配后,将硬盘中的引导程序(GRUB/LILO)读到系统内存中然后将控制权交给引导程序。引导程序的组要任务是将内核从硬盘读到内存,然后跳转到内核的入口点去运行。

传统的个人电脑上面BIOS会有一个int19软件中断功能,在初始化完成后,BIOS会进入int19中断,寻找启动介质,如软盘,光盘,硬盘,flash或者网络等等,读取第一个扇区的内容到内存的0000:7C00处,跳入这个地址执行。这里int19就是一个bootloader,启动引导器。所以BIOS具有Boot Loader的功能。当然,目前的BIOS功能已经被扩充了很多,例如电源管理方面的ACPI接口,USB驱动PXE网络引导功能,硬盘加密,TPM接口,BIOS配置界面,BIOS自动恢复等等。

 

2. 零地址跳转

下面介绍一下系统上电后如何跳转到程序执行的第一条指令。系统上电后,所有的处理器通常都从处理器制造商预先安排的地址开始执行。如X86处理器复位后一般在4G-8字节处,而ARM处理器一般是在0x00000000起开始执行。

3. UBOOT执行的2stage

UBOOT的执行分为两个阶段,第一个阶段stage1主要使用汇编语言编写,第二个阶段stage2主要使用C语言编写。

 

UBOOT stage1阶段的主要任务:

1)系统复位转入UBOOTstage1入口点

2)设置异常向量

3)设置CPU的速率、时钟频率及终端控制寄存器

4)初始化内存控制器

5)拷贝UB00Tstage2代码到RAM空间

6)设置堆栈、初始化数据段

 

UBOOT stage2阶段的主要任务:

1)跳转到stage2C入口点

2)初始化Flash设备

3)初始化系统内存

4)初始化NAND、显示、网络设备等

5)kernel和根文件系统从flash读到RAM

6)设定内核启动参数并调用内核

4. UBOOT的CPU寻址空间映射图

 UBOOT学习总结UBOOT学习总结

 

4. UBOOT各目录结构介绍

Board目录

和开发板有关的文件。每一个开发板都以一个子目录出现在当前目录中,比如:SMDK2410,子目录中存放与开发板相关的文件,主要包含SDRAMFLASH、网卡驱动等

 

Common目录

实现UBOOT支持的命令。

 

Cpu目录

与特定CPU架构相关的代码,每一款UBOOT下支持的CPU在该目录下对应一个子目录,比如有子目录arm920t等。每个子目录中都包括cpu.cinterrupt.cstart.S

 

Disk目录

对磁盘的支持。

 

Doc目录

UBOOT的说明文档。

 

Drivers目录

UBOOT支持的设备驱动程序都放在该目录,比如各种网卡、支持CFIFLASH、串口、USB总线等。

 

Examples目录

可在UBOOT下运行的示例程序, 如:hello_world.ctimer.c等。

 

Fs目录

文件系统的支持:如:cramfsfatfdosjffs2registers等。

 

Include目录

UBOOT使用的头文件,该目录下configs目录有与开发板相关的配置头文件,如smdk2410.h。该目录下的asm目录有与CPU体系结构相关的头文件。

 

Net目录

与网络协议栈相关的文件,如:bootpnfstftp等协议的实现。

 

Post目录

上电自检文件目录

 

Tools目录

生成UBOOT的工具,如mkimagecrc等等。

 

UBOOTstage1代码通常放在cpu/xxxx/start.S文件中,他用汇编语言写成。

UBOOTstage2代码通常放在lib_xxxx/board.c文件中,他用c语音写成。

 

5. UBOOT的编译

设置好交叉编译环境,参见文档《1建立交叉编译环境》

make mini2440_config  (mini2440_configMakefile中有定义)

make

6. UBOOT启动kernel

这里以mini2440作为一个例子进行说明。

mini2440中,由于u-boot.bin文件大小已经大于了0x40000,所以作者修改了ENVOFFSET。现在的Nand分区是这样的: 

uboot地址范围是0x0-0x60000,共384KB
uboot参数区地址范围是0x60000-0x80000,共128KB
kernel地址范围是0x80000-0x500000,共5MB


include/configs/mini2440.h中有nand分区的定义:

 UBOOT学习总结UBOOT学习总结

而在友善之臂的Supervivi定义的bootloader0x0-0x40000params0x40000-0x60000kernel0x60000-0x500000(友善之臂附带的linux kernel定义的地址和bootloader一致)。

如果u-boot是用supervivik选项将linux kernel传到nand flash的。那么,Kernel的地址就会和u-boot中的params冲突,导致U-boot无法引导内核。

解决办法:

修改linux kernel中对Nand的分区定义,使其与u-boot保持一致。kernelnand分区信息在arch/arm/mach-s3c2440/mach-mini2440.c中的名为friendly_arm_default_nand_part的结构体数组里。

如下图所示,为默认情况下,kernel中对Nand分区的定义:

 UBOOT学习总结UBOOT学习总结

根据U-bootnand分区配置,我们需要将其修改为如下所示:

 UBOOT学习总结UBOOT学习总结

回到Kernel根目录,执行make zImage命令,会重新生成/arch/arm/boot/zImage。现在又有一个问题:uboot目前只能支持uImage启动,不支持zImage启动,因此我们需要使用mkimage工具把zImage转换为uImage

我们可以通过两种方式获取到mkimage工具

1. uboot源码根目录下的tools目录下

2. 执行以下命令安装apt-get install uboot-mkimage

 

uImage是在zImage之前加上一个长度为0x40字节(64字节)的头部,来说明zImage这个映像文件的映象名、映像类型、加载地址、入口地址、生成时间、大小等信息。换句话说,如果直接从uImage0x40位置开始执行,zImageuImage没有任何区别。U-boot引导内核是通过bootm完成的,bootm加载uImage的时候,会先对uImage进行解压(去掉0x40字节的头部),解压地址为内核入口地址(由mkimage-e选项指定)。当解压完成时的uImage跟原zImage是完全相同的。

转换zImageuImage的命令如下所示:

mkimage -"linux-2.6.32.2" -A arm -O Linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage uImage

 

执行mkimage --help可以查看mkimage的帮助信息;

-A用于指定平台架构,我们的是arm平台

-O用于指定操作系统,我们的是Linux操作系统

-T用于指定映像类型,映像是内核镜像,指定为Kernel

-C用于指定压缩类型,此处我们不压缩,设为none

-a用于指定夹在地址,0x30008000

-e用于指定入口地址,uImage去除0x40字节的头部信息之后,即为zImage,这便是kernel的入口地址,指定为0x30008040

-d用于指定data文件,从内容上看,zImage不含格式信息,就是一个普通的数据文件,因此此处指的就是zImage

uImage即为输出文件名。

 

u-boot能引导的内核已经制作好了,接下来我们测试一下能否正常工作;

1执行usbslave 1 0x30008000  #通过usb线将uImage下载至内存0x30008000(在主机上执行dnw...)

2执行nand erase 0x80000 0x500000  #擦除此区域,nand使用之前需要先擦除,以便接下来将linux kernel保存到这个地址处。

3执行nand write 0x30008000 0x80000 0x500000  #从内存的0x30008000地址处开始拷贝0x500000字节的内容到nandflash0x80000地址处。

4修改u-boot引导参数UBOOT根据这些参数去加载内核)

setenv bootcmd 'nand read 0x30008000 0x80000 0x500000;bootm 0x30008000'

setenv bootargs 'noinitrd root=/dev/mtdblock3 initrd=/linuxrc console=ttySAC0'

saveenv

5重启开发板

nand启动u-boot然后引导内核启动

 

7. UBOOT代码详析

参见:https://www.cnblogs.com/lcw/p/3802644.html