uboot启动代码详解

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

·1引言在专用的嵌入式板子运行GNU/Linux系统已经变得越来越流行。一个嵌入式Linux系统从软件的角度看通常可以分为四个层次:1.引导加载程序。固化在固件(firmware)中的boot代码,也就是BootLoader,它的启动通常分为两个阶段。2.Linux内核。特定于嵌入式板子的定制内核以及内核的启动参数。3.文件系统。包括根文件系统和建立于Flash内存设备之上文件系统,rootfs。4.用户应用程序。特定于用户的应用程序。有时在用户应用程序和内核层之间可能还会包括一个嵌入式图形用户界面。常用的嵌入式GUI有:MicroWindows和MiniGUI等。引导加载程序是系统加电后运行的第一段软件代码。回忆一下PC的体系结构我们可以知道,PC机中的引导加载程序由BIOS(其本质就是一段固件程序)和位于硬盘MBR中的OSBootLoader(比如,LILO和GRUB等)一起组成。BIOS在完成硬件检测和资源分配后,将硬盘MBR中的BootLoader读到系统的RAM中,然后将控制权交给OSBootLoader。BootLoader的主要运行任务就是将内核映象从硬盘上读到RAM中,然后跳转到内核的入口点去运行,也即开始启动操作系统。而在嵌入式系统中,通常并没有像BIOS那样的固件程序(注,有的嵌入式CPU也会内嵌一段短小的启动程序),因此整个系统的加载启动任务就完全由BootLoader来完成。比如在一个基于ARM7TDMIcore的嵌入式系统中,系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的BootLoader程序。·2bootloader简介应用程序文件系统操作系统内核BootLoader简单地说,BootLoader(引导加载程序)就是在操作系统内核运行之前运行的一段小程序,它的作用就是加载操作系统,它是系统加电后运行的第一段软件代码。通过这段代码实现硬件的初始化,建立内存空间的映射图,为操作系统内核准备好硬件环境并引导内核的启动。如上图所示的那样在设备的启动过程中bootloader位于最底层,首先被运行来引导操作系统运行,很容易可以看出bootloader是底层程序所以它的实现严重地依赖于硬件,特别是在嵌入式世界。因此,在嵌入式世界里建立一个通用的BootLoader几乎是不可能的。尽管如此,一些功能强大、支持硬件环境较多的BootLoader也被广大的使用者和爱好者所支持,从而形成了一些被广泛认可的、较为通用的的bootloader实现。2.1BootLoader所支持的CPU和嵌入式板每种不同的CPU体系结构都有不同的BootLoader。有些BootLoader也支持多种体系结构的CPU,比如U-Boot就同时支持ARM体系结构和MIPS体系结构。除了依赖于CPU的体系结构外,BootLoader实际上也依赖于具体的嵌入式板级设备的配置。这也就是说,对于两块不同的嵌入式板而言,即使它们是基于同一种CPU而构建的,要想让运行在一块板子上的BootLoader程序也能运行在另一块板子上,通常也都需要修改BootLoader的源程序。2.2BootLoader的安装媒介(InstallationMedium)系统加电或复位后,所有的CPU通常都从某个由CPU制造商预先安排的地址上取指令。比如,基于ARM7TDMIcore的CPU在复位时通常都从地址0x00000000取它的第一条指令。而基于CPU构建的嵌入式系统通常都有某种类型的固态存储设备(比如:ROM、EEPROM或FLASH等)被映射到这个预先安排的地址上。因此在系统加电后,CPU将首先执行BootLoader程序。下图1就是一个同时装有BootLoader、内核的启动参数、内核映像和根文件系统映像的固态存储设备的典型空间分配结构图:图1固态存储设备的典型空间分配结构2.3BootLoader的启动过程:单阶段(SingleStage)/多阶段(Multi-Stage)通常多阶段的BootLoader能提供更为复杂的功能,以及更好的可移植性。从固态存储设备上启动的BootLoader大多都是2阶段的启动过程,也即启动过程可以分为stage1和stage2两部分。而至于在stage1和stage2具体完成哪些任务将在下面讨论。2.4BootLoader的操作模式(OperationMode)大多数BootLoader都包含两种不同的操作模式:启动加载模式和下载模式,这种区别仅对于开发人员才有意义。但从最终用户的角度看,BootLoader的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。启动加载(Bootloading)模式:这种模式也称为自主(Autonomous)模式。也即BootLoader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。这种模式是BootLoader的正常工作模式,因此在嵌入式产品发布的时侯,BootLoader显然必须工作在这种模式下。下载(Downloading)模式:在这种模式下,目标机上的BootLoader将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:下载内核映像和根文件系统映像等。从主机下载的文件通常首先被BootLoader保存到目标机的RAM中,然后再被BootLoader写到目标机上的FLASH类固态存储设备中。BootLoader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用BootLoader的这种工作模式。工作于这种模式下的BootLoader通常都会向它的终端用户提供一个简单的菜单界面或命令行接口来接收要执行的操作。像Blob或U-Boot等这样功能强大的BootLoader通常同时支持这两种工作模式,而且允许用户在这两种工作模式之间进行切换。比如,Blob在启动时处于正常的启动加载模式,但是它会延时10秒等待终端用户按下任意键而将blob切换到下载模式。如果在10秒内没有用户按键,则blob继续启动Linux内核。2.5常见的BootLoaderU-BOOT:U-Boot是DasU-Boot的简称,其含义是UniversalBootLoader,是遵循GPL条款的开放源码项目。uboot是一个庞大的公开源码的软件。它支持一些系列的arm体系,包含常见的外设的驱动,是一个功能强大的板极支持包。vivi:vivi是韩国mizi公司开发的bootloader,适用于ARM9处理器。Vivi也有两种工作模式:启动加载模式和下载模式。启动加载模式可以在一段时间后(这个时间可更改)自行启动linux内核,这是vivi的默认模式。如果修改或更新需要进入下载模式,在下载模式下,vivi为用户提供一个命令行接口通过接口可以使用vivi提供的一些命令,来实现flash的烧写、管理、操作mtd分区信息、启动系统等功能。2.6U-BOOT的目录结构目录说明board和开发板相关的文件,每一个开发板都以一个子目录出现在当前目录中,比如:smdk2410。该子目录中存放于开发板相关的配置文件,如makefile和U-Boot.lds。其中包含SDRAM初始化代码、Flash底层驱动、板级初始化文件。config.mk定义了TEXT_BASE是代码在内存的真实地址common与体系结构无关的文件,实现各种命令的C文件。该文件主要实现uboot命令行下支持的命令,每一条命令都对应一个文件。例如bootm命令对应就是cmd_bootm.c。cpu与特定CPU架构相关目录,每一款uboot下支持的CPU在该目录下对应一个子目录,比如arm920t。每个CPU子目录中都包括cpu.c和interrupt.c、start.S。cpu.c初始化CPU、设置指令Cache和数据Cache等interrupt.c设置系统的各种中断和异常start.S是U-boot启动时执行的第一个文件,它主要做早期系统初始化,代码重定向和设置系统堆栈diskDisk分区处理代码,对磁盘的支持doc文档目录,uboot有非常完整的文档driversUboot支持的设备驱动程序都放在该目录,例如各种网卡、支持CFI的Flash、串口、USB等fs支持的文件系统,目前支持cramfs、fat、fdos、jffs2和registerfsinclude头文件,还有对各种硬件平台支持的汇编文件,系统配置文件和对文件系统支持的文件等。该目录下的configs目录有与开发板相关的配置文件,如smdk2410.h。该目录下的asm目录有与CPU体系结构相关的头文件,比如arm对应的就是asm-arm。net与网络协议栈相关的代码,BOOTP协议、TFTP协议、RARP和NFS文件系统的实现等lib_xxx与ARM体系结构相关的库文件。如与arm相关的库放在lib_arm中tools生成uboot的工具,如mkimage,crc等等·3BootLoader的主要任务与典型结构框架从操作系统的角度看,BootLoader的总目标就是正确地调用内核来执行。另外,由于BootLoader的实现依赖于CPU的体系结构,因此大多数BootLoader都分为stage1和stage2两大部分。依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的。而stage2则通常用C语言来实现,这样可以实现给复杂的功能,而且代码会具有更好的可读性和可移植性。以u-boot为例,它启动过程的两个阶段(stage)如下:·第一阶段(stage1)cpu/arm920t/start.S依赖于CPU体系结构的代码(如设备初始化代码等),一般用汇编语言来实现。主要进行以下方面的设置:设置ARM进入SVC模式、禁止IRQ和FIQ、关闭看门狗、屏蔽所有中断。设置时钟(FCLK,HCLK,PCLK)、清空I/Dcache、清空TLB、禁止MMU和cache、配置内存控制器、为搬运代码做准备、搬移uboot映像到RAM中(使用copy_loop实现)、分配堆栈、清空bss段(使用clbss_l实现)。最后通过ldrpc,_start_armboot跳转到第二阶段。·第二阶段(stage2)lib_arm/board.c该阶段主要都是用C语言来实现。start_armboot()进行一系列初始化(cpu,板卡,中断,串口,控制台等),开启I/Dcache。初始化FLASH,根据系统配置执行其他初始化操作。打印LOG,使能中断,获取环境变量,初始化网卡。最后进入main_loop()函数。综上所述,可简单的归纳两个阶段的功能如下:·第一阶段的功能:硬件设备初始化加载U-Boot第二阶段代码到RAM空间设置好栈跳转到第二阶段代码入口·第二阶段的功能:初始化本阶段使用的硬件设备检测系统内存映射将内核从Flash读取到RAM中为内核设置启动参数调用内核U-Boot启动第一阶段流程如下:3.1u-boot的stage1详细分析uboot的第一阶段设计的非常巧妙,几乎都是用汇编语言实现的。首先我们来看一下它的链接脚本(u-boot-1.1.6\board\smdk2410\u-boot.lds),通过它我们可以知道它整个程序的各个段是怎么存放的。它定义了整个程序编译之后的连接过程,决定了一个可执行程序的各个段的存储位置。/*指定输出可执行文件是elf格式,32位ARM指令,小端*/OUTPUT_FORMAT(elf32-littlearm,elf32-littlearm,elf32-littlearm)/*指定输出可执行文件的平台架构为ARM架构*/OUTPUT_ARCH(arm)/*指定输出可执行文件的起始代码段为_start*/ENTRY(_start)SECTIONS{.=0x00000000;//入口地址.=ALIGN(4);//四字节对齐.text://代码段,上面3行标识是不

1 / 50
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功