BootLoader引导加载程序2主要内容本章从以下四个方面来讨论嵌入式系统的BootLoader,包括:BootLoader的概念BootLoader的主要任务BootLoader的框架结构BootLoader的安装部分开源的bootloader3嵌入式Linux的软件层次在专用的嵌入式板子上运行GNU/Linux系统已变得越来越流行。一个嵌入式Linux系统从软件的角度看通常可以分为四个层次:1.引导加载程序。包括固化在固件(firmware)中的boot代码(可选)和BootLoader两大部分2.Linux内核。特定于嵌入式板子的定制内核及内核的启动参数4嵌入式Linux的软件层次(cont’d)3.文件系统。包括根文件系统和建立于Flash内存设备之上的文件系统通常用RAM-Disk来作为根文件系统4.用户应用程序。特定于用户的应用程序5嵌入式GUI有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面(GUI)。常用的嵌入式GUI有:MicroWindows和MiniGUI等。6引导加载程序引导加载程序是系统加电后运行的第一段软件代码例如PC机的引导加载程序,包括1.BIOS(其本质就是一段固件程序)2.位于硬盘MBR中的OSBootLoader比如LILO、GRUB等。BIOS的主要任务是1.进行硬件检测和资源分配2.将MBR中的OSBootLoader读到系统的RAM中3.将控制权交给OSBootLoaderBootLoader的主要运行任务是1.将内核映象从硬盘上读到RAM中2.跳转到内核的入口点去运行,也即启动操作系统。7引导加载程序(cont’d)在嵌入式系统中通常并没有像BIOS那样的固件程序注:有的嵌入式CPU也会内嵌一段短小的启动程序整个系统的加载启动任务完全由BootLoader来完成比如在一个基于ARM7TDMIcore的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序。8BootLoader的概念BootLoader是在操作系统内核运行之前运行的第一段小程序。初始化硬件设备建立内存空间的映射图将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。加载操作系统内核映象到RAM中,并将系统的控制权传递给它例如:Linux9通用的BootLoader在嵌入式世界里建立一个通用的BootLoader几乎是不可能的BootLoader对硬件的依赖性非常强,特别是在嵌入式系统世界中尽管如此,仍可对BootLoader归纳出一些通用的概念,以指导用户特定的BootLoader设计与实现。10支持的CPU和嵌入式板BootLoader依赖于1.CPU的体系结构不同的CPU体系结构都有不同的BootLoader有些BootLoader也支持多种CPU体系结构例如U-Boot同时支持ARM和MIPS体系结构2.具体的嵌入式板级设备的配置对于两块不同的嵌入式板,即使它们基于同一种CPU,要想让运行在一块板子上的BootLoader也能运行在另一块板子上,通常也都需要修改BootLoader源程序11BootLoader的安装媒介系统加电或复位后,所有的CPU通常都从某个由CPU制造商预先安排的地址上取指令。比如,基于ARM7TDMIcore的CPU在复位时通常都从地址0x00000000取它的第一条指令。基于CPU构建的嵌入式系统通常都有某种类型的固态存储设备被映射到这个预先安排的地址上。比如:ROM、EEPROM或FLASH等因此在系统加电后,CPU将首先执行BootLoader程序。12固态存储设备的典型空间分配结构图一个同时装有BootLoader、内核的启动参数、内核映像和根文件系统映像的固态存储设备的典型空间分配结构图KernelRootfilesystemBootloaderBootparameters13BootLoader的安装烧写bootloader程序一般通过jtag烧写需要jtag连接器和PC端的烧写程序14控制BootLoader的设备或机制主机和目标机之间一般通过串口建立连接BootLoader软件在执行时通常会通过串口来进行I/O,比如输出打印信息到串口从串口读取用户控制字符等。最常用的串口通信软件Linux:minicomWindows:附件中的超级终端15BootLoader的启动过程BootLoader的启动过程可以是单阶段(SingleStage)或一些只需完成很简单功能的bootloader可能是单阶段的多阶段(Multi-Stage)通常多阶段的BootLoader能提供更为复杂的功能,以及更好的可移植性从固态存储设备上启动的BootLoader大多都是2阶段的启动过程,也即启动过程可以分为stage1和stage2两部分16BootLoader的操作模式大多数BootLoader包含两种不同的操作模式启动加载(Bootloading)模式和下载(Downloading)模式这种区别仅对于开发人员才有意义从最终用户的角度看,BootLoader的作用就是加载操作系统,并不存在上述两种模式的区别17启动加载模式也称为自主(Autonomous)模式BootLoader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。这种模式是BootLoader的正常工作模式在嵌入式产品发布时,BootLoader必须工作在该模式下18下载模式目标机的BootLoader通过串口或网络等通信手段从主机(Host)下载文件比如内核映像和根文件系统映像HosttargetramtargetFLASH该模式的使用时机通常在第一次安装内核与根文件系统时被使用也用于此后的系统更新工作于该模式下的BootLoader通常都会向它的终端用户提供一个简单的命令行接口19BootLoader的操作模式(cont’d)一些功能强大的BootLoader通常1.同时支持这两种工作模式如Blob和U-Boot2.允许用户在这两种工作模式之间进行切换比如,Blob在启动时处于正常的启动加载模式,但是它会延时10秒等待终端用户按下任意键而将blob切换到下载模式。如果在10秒内没有用户按键,则blob继续启动Linux内核。20与bootloader两种模式相关的问题uClinux包编译好后,可根据需要编译出各种镜像文件也就是按照板子内存预定位置生成的二进制映象,一般是内核和文件系统的复合体常见有image.ram(常称为ram版内核)和image.rom(常称为rom版内核)通过在make时指定的不同编译选项生成21ram版内核一般不压缩,通过bootloader加载到目标板内存的指定位置,然后可用bootloader跳转过去就把uclinux引导启动了bootloader+ram版内核内核/驱动相关调试期间常用方式22rom版内核不严格的理解可以说是把bootloader+ram版烧写到flash内上电或reset后首先执行bootloader初始化硬件功能,然后把压缩的内核映象解压释放到sdram指定地址,接着自动引导内核,启动uclinux调试应用软件常用rom版镜像。23BootLoader与主机之间进行文件传输所用的通信设备及协议最常见通信设备是串口传输协议通常是xmodem、ymodem、zmodem之一。但串口传输的速度有限更好的选择是以太网使用TFTP协议主机方必须有一个软件提供TFTP服务24BootLoader的主要任务系统假设:内核映像与根文件系统映像都被加载到RAM中运行。尽管在嵌入式系统中它们也可直接运行在ROM或Flash这样的固态存储设备中。但这种做法无疑是以运行速度的牺牲为代价的。从操作系统的角度看,BootLoader的总目标就是正确地调用内核来执行。25BootLoader的典型结构框架由于BootLoader的实现依赖于CPU体系结构,大多数BootLoader都分为stage1和stage2两大部分Stage1依赖于CPU体系结构,如设备初始化代码通常用汇编语言实现,短小精悍Stage2通常用C语言可以实现复杂功能代码具有较好的可读性和可移植性26BootLoader的stage1Stage1直接运行在固态存储设备上,通常包括以下步骤硬件设备初始化为加载BootLoader的stage2准备RAM空间拷贝BootLoader的stage2到RAM空间中设置好堆栈跳转到stage2的C入口点27Stage1:硬件初始化这是BootLoader一开始就执行的操作目的:为stage2及kernel的执行准备好基本硬件环境通常包括1.屏蔽所有的中断为中断提供服务通常是OS或设备驱动程序的责任,在BootLoader阶段不必响应任何中断中断屏蔽可以通过写CPU的中断屏蔽寄存器或状态寄存器来完成比如ARM的CPSR寄存器28Stage1:硬件初始化(cont‘d)2.设置CPU的速度和时钟频率3.RAM初始化包括正确地设置系统中内存控制器的功能寄存器以及各CPU外的内存(MemoryBank)的控制寄存器等。4.初始化LED典型地,通过GPIO来驱动LED,其目的是表明系统的状态是OK还是Error。若板子上无LED,也可通过初始化UART向串口打印BootLoader的Logo字符信息来完成这一点。5.关闭CPU内部指令/数据cache29Stage1:为stage2准备RAM空间为获得更快的执行速度,通常stage2被加载到RAM中执行因此必须为加载stage2准备好一段可用的RAM空间空间大小,应考虑stage2可执行映象的大小+堆栈空间因为stage2通常是C语言代码此外,最好对齐到memorypage大小(通常是4KB)一般而言1MB已足够30Stage1:为stage2准备RAM空间具体的地址范围可以任意安排比如blob将它的stage2可执行映像安排系统的RAM中0xc0200000开始的1M空间内值得推荐的是可以将stage2安排到整个RAM空间的最顶1MB也即(RamEnd-1MB)开始处假设空间大小:stage2_size(字节)起始和终止地址分别为:stage2_start和stage2_end(均与4字节对齐)则有:stage2_end=stage2_start+stage2_size31Stage1:为stage2准备RAM空间必须确保所安排的地址范围的确为可读写的RAM空间,即必须进行有效性测试Blob的内存有效性测试方法:记为test_mempage:以内存页为被测单位,测试每个页面头两个字是否可读写32test_mempage1.保存被测页面头两个字的内容。2.向这两个字中写入任意的数字。比如:向第一个字写入0x55,第2个字写入0xaa。3.立即将这两个字的内容读回。应当与写入的内容一致,否则此页面地址范围不是一段有效的RAM空间4.再次向这两个字中写入任意的数字。比如:向第一个字写入0xaa,第2个字中写入0x55。5.立即将这两个字的内容读回。判断依据同36.恢复这两个字的原始内容。33Stage1:为stage2准备RAM空间测试结束后,为了得到一段干净的RAM空间范围,可以将所安排的RAM空间范围进行清零操作。34Stage1:拷贝stage2到RAM中拷贝时要确定:1.Stage2的可执行映象在固态存储设备的存放起始地址和终止地址2.RAM空间的起始地址35Stage1:设置堆栈指针sp对C语言编写的程序应当准备运行堆栈通常设置在上述1MBRAM空间的最顶端sp=(stage2_end-4)注:堆栈