14.Bootloader设计思路
在前面,已经了解了很多裸机的知识,也建立了一个测试汇编代码的工程。这些工作其实是为这里来学习Bootloader做铺垫的。
这一节的索引:图1-1:
图1-1
第一分区:存放的当然是u-boot
第二个分区:存放着u-boot要传给系统内核的参数
第三个分区:是系统内核(kernel)
第四个分区:则是根文件系统
Bootloader的作用:
其实Bootloader主要的必须的作用只有一个:就是把操作系统映像文件拷贝到RAM中去,然后跳转到它的入口处去执行,我们称之为启动加载模式,该过程没有用户的介入,是它正常工作的模式。它的步骤如下:
Stage1:
1. 硬件设备初始化。为stage2的执行及随后内核的执行准备好基本的硬件环境
2. 为加载stage2 准备ram空间。为了获得更好的执行速度,通常吧stage2加载到ram中执行
3. 复制stage2的代码到ram中
4. 设置好堆栈
5. 跳转到stage2的c程序入口
Stage2:
1. 初始化本阶段要使用的硬件设备
2. 检测系统内存映射
3. 将内核映像和根文件系统映像从flash读到ram中
4. 为内核设置启动参数
5. 调用内核
图1-2:Bootloader映射
U-Boot是用于多种嵌入式CPU( MIPS、x86、ARM等)的bootloader程序,U-Boot不仅支持嵌入式Linux系统的引导,还支持VxWorks, QNX等多种嵌入式操作系统。
U-Boot,全称 Universal Boot Loader,是遵循GPL条款的开放源码项目。从FADSROM、8xxROM、PPCBOOT逐步发展演化而来。其源码目录、编译形式与Linux内核很相似,事实上,不少U-Boot源码就是根据相应的Linux内核源程序进行简化而形成的,尤其是一些设备的驱动程序,这从U-Boot源码的注释中能体现这一点。
目录结构:
* board 目标板相关文件,主要包含SDRAM、FLASH驱动;
* common 独立于处理器体系结构的通用代码,如内存大小探测与故障检测;
* cpu 与处理器相关的文件。如mpc8xx子目录下含串口、网口、LCD驱动及中断初始化等文件;
* driver 通用设备驱动,如CFI FLASH驱动(目前对INTEL FLASH支持较好)
* doc U-Boot的说明文档;
* examples可在U-Boot下运行的示例程序;如hello_world.c,timer.c;
* include U-Boot头文件;尤其configs子目录下与目标板相关的配置头文件是移植过程中经常要修改的文件;
* lib_xxx 处理器体系相关的文件,如lib_ppc, lib_arm目录分别包含与PowerPC、ARM体系结构相关的文件;
* net 与网络功能相关的文件目录,如bootp,nfs,tftp;
* post 上电自检文件目录。尚有待于进一步完善;
* rtc RTC驱动程序;
* tools 用于创建U-Boot S-RECORD和BIN镜像文件的工具;
主要功能:
U-Boot可支持的主要功能列表:
*系统引导支持NFS挂载、RAMDISK(压缩或非压缩)形式的根文件系统;支持NFS挂载、从FLASH中引导压缩或非压缩系统内核;
* 基本辅助功能强大的操作系统接口功能;可灵活设置、传递多个关键参数给操作系统,适合系统在不同开发阶段的调试要求与产品发布,尤以Linux支持最为强劲;支持目标板环境参数多种存储方式,如FLASH、NVRAM、EEPROM;
* CRC32校验可校验FLASH中内核、RAMDISK镜像文件是否完好;
* 设备驱动串口、SDRAM、FLASH、以太网、LCD、NVRAM、EEPROM、键盘、USB、PCMCIA、PCI、RTC等驱动支持;
* 上电自检功能SDRAM、FLASH大小自动检测;SDRAM故障检测;CPU型号;
* 特殊功能XIP内核引导;
工作模式:
U-Boot的工作模式有启动加载模式和下载模式。启动加载模式是Bootloader的正常工作模式,嵌入式产品发布时,Bootloader必须工作在这种模式下,Bootloader将嵌入式操作系统从FLASH中加载到SDRAM中运行,整个过程是自动的。下载模式就是Bootloader通过某些通信手段将内核映像或根文件系统映像等从PC机中下载到目标板的FLASH中。用户可以利用Bootloader提供的一些命令接口来完成自己想要的操作。
启动流程:
大多数BootLoader都分为stage1和stage2两大部分,U-boot也不例外。依赖于cpu体系结构的代码(如设备初始化代码等)通常都放在stage1且可以用汇编语言来实现,而stage2则通常用C语言来实现,这样可以实现复杂的功能,而且有更好的可读性和移植性。
1、 stage1(start.s代码结构)
U-boot的stage1代码通常放在start.s文件中,它用汇编语言写成,其主要代码部分如下:
(1) 定义入口。由于一个可执行的image必须有一个入口点,并且只能有一个全局入口,通常这个入口放在rom(Flash)的0x0地址,因此,必须通知编译器以使其知道这个入口,该工作可通过修改连接器脚本来完成。
(2)设置异常向量(exception vector)。
(3)设置CPU的速度、时钟频率及中断控制寄存器。
(4)初始化内存控制器 。
(5)将rom中的程序复制到ram中。
(6)初始化堆栈 。
(7)转到ram中执行,该工作可使用指令ldrpc来完成。
2、 stage2(C语言代码部分)
lib_arm/board.c中的start armboot是C语言开始的函数,也是整个启动代码中C语言的主函数,同时还是整个u-boot(armboot)的主函数,该函数主要完成如下操作:
(1)调用一系列的初始化函数。
(2)初始化flash设备。
(3)初始化系统内存分配函数。
(4)如果目标系统拥有nand设备,则初始化nand设备。
(5)如果目标系统有显示设备,则初始化该类设备。
(6)初始化相关网络设备,填写ip,c地址等。
(7)进入命令循环(即整个boot的工作循环),接受用户从串口输入的命令,然后进行相应的工作。
图1-2:Bootloader映射
图1-2:Bootloader映射内存
上面就是Bootloader的基础知识。
体验U-Boot:
U-Boot的工作模式有两种:自主模式和开发模式。
自主模式:就是开发板一上电,会启动bootloader,而bootloader会初始化好硬件然后自动启动Linux内核。在这整个过程中不需要人为的干预。这就是自主模式。产品的最后模式。
开发模式:在进行内核开发的时候,不可能每一次对内核进行修改的时候都要烧写到NandFlash里面进行测试,因为很容易把NandFlash损坏。所以采用开发模式。在开发模式里可以通过U-boot提供的命令,通过网络,把内核下载到内存当中来进行调试,调试没问题了之后再烧写到内存当中,把U-boot设置为自主模式。这才是正确的操作。如下:
可以通过help来查看U-boot提供的命令:
U-Boot 1.1.6 (Sep 25 2012 - 10:09:14) for SMDK6410
****************************************
** u-boot 1.1.6 **
** Updated for OK6410 TE6410 Board **
** Version (2012-09-23) **
** OEM: Forlinx Embedded **
** Web: http://www.witech.com.cn **
****************************************
CPU: S3C6410 @532MHz
Fclk = 532MHz, Hclk = 133MHz, Pclk = 66MHz, Serial = CLKUART (SYNC Mode)
Board: SMDK6410
DRAM: 256 MB
Flash: 0 kB
NAND: 2048 MB
In: serial
Out: serial
Err: serial
Hit any key to stop autoboot: 0
###################### User Menu for OK6410#####################
[1] Format the nand flash
[2] Burn image from USB
[3] configure the lcd size
[4] Boot the system
[5] Reboot the u-boot
[6] Exit to command line
-----------------------------Select---------------------------------
Enter your Selection:6
SMDK6410 # help
? - alias for 'help'
base - print or set address offset
bdinfo - print Board Info structure
bootelf - Boot from an ELF image in memory
bootm - boot application image from memory
bootp - boot image via network using BootP/TFTP protocol
bootvx - Boot vxWorks from an ELF image
branch - enable or disable branch prediction
cmp - memory compare
cp - memory copy
crc32 - checksum calculation
date - get/set/reset date & time
dcache - enable or disable data cache
dnw - initialize USB device and ready to receive for Windows server (specific)
echo - echo args to console
erase - erase FLASH memory
exit - exit script
fatinfo - print information about filesystem
fatload - load binary file from a dos filesystem
fatls - list files in a directory (default /)
flinfo - print FLASH memory information
go - start application at address 'addr'
help - print online help
icache - enable or disable instruction cache
imls - list all images found in flash
itest - return true/false on integer compare
loadb - load binary file over serial line (kermit mode)
loads - load S-Record file over serial line
loady - load binary file over serial line (ymodem mode)
loop - infinite loop on address range
md - memory display
mm - memory modify (auto-incrementing)
movi - moviNAND sub-system
mtest - simple RAM test
mw - memory write (fill)
nand - NAND sub-system
nboot - boot from NAND device
nfs - boot image via network using NFS protocol
nm - memory modify (constant address)
ping - send ICMP ECHO_REQUEST to network host
printenv- print environment variables
protect - enable or disable FLASH write protection
rarpboot- boot image via network using RARP/TFTP protocol
reset - Perform RESET of the CPU
saveenv - save environment variables to persistent storage
setenv - set environment variables
sleep - delay execution for some time
test - minimal test like /bin/sh
tftpboot- boot image via network using TFTP protocol
usb - USB sub-system
version - print monitor version
SMDK6410 #
通过Source Insight软件来查看U-boot工程:
这里,我是在Redhat 6.4里安装了wine软件,然后通过wine软件把Source Insight安装到了Redhat 6.4里面。这里顺便提一下wine的安装过程,和Source Insight的安装过程:
确保你的Redhat 6.4能上网,然后执行运行:yum install wine即可。
我已经安装好了,所以会提示:
这样就安装好了wine,接下来是安装Source Insight。
在Source Insight.exe的目录下执行:wine Si35Setup.exe即可执行安装,安装方法跟windows的一样的。如下图:
点击Agree,进入下图:
一直下一步直到完成。即可。
安装好了之后,选择Applications->Wine->Programs->Source Insight 3->Source Insight 3.5,即可启动Source Insight。如下图:
Source Insight界面:
在新建工程之前,要全部可以导入汇编.S和.s文件:
在工具栏里找到Options->Document Options:
在左上角的Document Type里选择C Source File:
可以看到上面的右边的File filter里只有c和h文件,这里需要导入.S和.s汇编文件。修改之后为:
最后点击Close键即可。
如果字体不合适,可以点击左边的Screen Fonts键进行修改即可。很是简单。
新建工程:
注意,如果点工具栏没反应,点击右上角的□,把软件的界面扩大或者缩小即可。
然后选择工具栏的Project->New Project:
然后修改你的工程名,和工程存放的位置:
点击OK会进入到下图:然后选择Configuration里的Project has its own configuration file。
然后点OK,进入选择U-boot的过程代码:
然后点击Add All,等待导入完成即可。这样就新建好了U-boot的工程。
导入完成:
查看start.S:
这样就完成了导入:
接下来为了方便查看,完全适应Source Insight的强大查看代码的功能,需要对代码进行同步。同步的操作很简单,直接点中间那本书形状的图标,会出现一个提示,直接确定即可,就进入了同步,同步完成之后点击这书状的图标,会出现:
接下来可以试试它的强大代码阅读功能,搜索.global:
它会列出搜索到的标识:然后选择你要查看的标识,点击右边的Jump就可以直接跳转到该标识处。
这样就跳转到了想要找的标识处。这样是不是很方便阅读代码。
当我们在看代码的时候,想看看函数的实现等。可以直接点击函数,会在下面同时显示函数的实现代码:
你看,上面我点击了abortboot_keyed(bootdelay);会在下面同时显示他的实现代码。双击下面实现代码。会跳转到实现的函数文件的界面:
这里演示的知识Source Insight的强大代码阅读功能的一小部分,接下来就是苦练,见识真面目的开始了。