嵌入式系统的BootLoader
- 格式:doc
- 大小:92.50 KB
- 文档页数:11
嵌入式系统中Bootloader 的设计与实现马学文1,朱名日1,2,程小辉1 (1. 桂林工学院电子与计算机系,桂林541004;2.中南大学信息物理工程学院,长沙410083)—97—作者所承研的项目中硬件平台是基于ARM7TDMIRISC 内核的三星公司S3C4510B 微处理器,采用的嵌入式Linux 系统为uCLinux。
系统有64MB SDRAM, 其地址从0x 0800.0000 ~0x0bff.ffff, 还有32MB Flash, 其地址从0x0c00.0000~0x0dff.ffff。
32MB Flash 具体规划如下:从0x0c00.0000 开始的第1 个1MB 放Bootloader,从0x0c10.0000开始的2MB放Linux kernel, 从0x0c30.0000开始的余下部分都给rootdisk。
64MB SDRAM 启动后的具体程序分布示意图如图2 所示。
图2 64MB SDRAM 的程序分布示意图Bootloader 一般有几个文件组成。
先是START.s,也是唯一的一个汇编程序,其余的都是C 语言写成的,START.s主要用来初始化堆栈:_start:ldr r1,=StackInit /* r1 是参数字符串的地址*/ldr sp,[r1]int main().equ StackInitValue,_end_data+0x1000/* 在连结脚本中指定4K __end_data*/StackInit:.long StackInitValue.global JumpToKernelJumpToKernel: /*拷贝内核的代码*/mov pc, r0 /*获得Kernel 地址*/.global JumpToKernel0x /*用来扩展内核*/JumpToKernel0x: /*拷贝获得的扩展内核*/mov r8, r0mov r0, r1mov r1, r2mov r2, r3mov r3, r4mov pc, r8.section“.data.boot”.section“.bss.boot”其中main 函数的C 语言实现过程如下:int main(){U32 *pSource, *pDestin, count;U8 countDown, bootOption;U32 delayCount;U32 fileSize, i;char c;char *pCmdLine;char *pMem;init(); /*初始化Flash 控制器和CPU 时钟*/EUARTinit(); /*串口初始化*/EUARTputString("\n\n Linux Bootloader\n"); /*打印信息*/ EUARTputString((U8 *)cmdLine); /*command_line 支持, 用于定制内核*/EUARTputString("\n\n");用command_line 可以给内核传一些参数,自己定制内核的行为。
文章标题:深入探讨STC8 Bootloader 例程1.引言在嵌入式系统设计和开发中,Bootloader 例程扮演着至关重要的角色。
STC8系列单片机作为一种常用的嵌入式芯片,其Bootloader 例程更是备受关注。
本文将深入探讨STC8 Bootloader 例程,从概念到实践,带您全面了解这一重要的技术。
2. 什么是Bootloader 例程Bootloader 例程,简称Bootloader,是一种在嵌入式系统中用于引导程序和初始化硬件的特殊程序。
在STC8单片机中,Bootloader 例程具有独特的设计和功能,可以实现固件更新、自主程序下载等重要功能。
考虑到STC8单片机在各类应用中广泛应用,Bootloader 例程的设计与应用显得尤为重要。
3. STC8 Bootloader 例程的特点STC8 Bootloader 例程具有以下几个突出的特点:- 稳定可靠:STC8 Bootloader 例程经过严格测试和验证,具有良好的稳定性和可靠性,可以满足各类应用的需求。
- 高度定制:STC8 Bootloader 例程支持用户自定义设置,可以根据具体应用的需求进行灵活配置,满足不同场景的需求。
- 易于集成:STC8 Bootloader 例程提供了完善的API接口和文档说明,方便用户在实际项目中快速集成和应用。
- 安全性保障:STC8 Bootloader 例程采用了多重安全机制,保障固件更新和程序下载的安全性,有效防止恶意攻击和非法篡改。
4. 深入探讨STC8 Bootloader 例程的实现在实际项目中,如何针对STC8 Bootloader 例程进行实现和优化是一个关键问题。
首先需要考虑Bootloader例程的整体架构和设计思路,具体包括Bootloader程序的存储器分配、引导流程设计、固件更新机制等方面。
其次需要考虑如何与应用程序进行有效的通信和数据传输,确保Bootloader 例程与用户程序的无缝衔接。
嵌入式linux系统的启动流程
嵌入式Linux系统的启动流程一般包括以下几个步骤:
1.硬件初始化:首先会对硬件进行初始化,例如设置时钟、中
断控制等。
这一步骤通常是由硬件自身进行初始化,也受到系统的BIOS或Bootloader的控制。
2.Bootloader引导:接下来,系统会从存储介质(如闪存、SD
卡等)的Bootloader区域读取引导程序。
Bootloader是一段程序,可以从存储介质中加载内核镜像和根文件系统,它负责进行硬件初始化、进行引导选项的选择,以及加载内核到内存中。
3.Linux内核加载:Bootloader会将内核镜像从存储介质中加载到系统内存中。
内核镜像是包含操作系统核心的一个二进制文件,它由开发者编译并与设备硬件特定的驱动程序进行连接。
4.内核初始化:一旦内核被加载到内存中,系统会进入内核初
始化阶段。
在这个阶段,内核会初始化设备驱动程序、文件系统、网络协议栈等系统核心。
5.启动用户空间:在内核初始化完毕后,系统将启动第一个用
户空间进程(init进程)。
init进程会读取并解析配置文件(如
/etc/inittab)来决定如何启动其他系统服务和应用程序。
6.启动其他系统服务和应用程序:在用户空间启动后,init进
程会根据配置文件启动其他系统服务和应用程序。
这些服务和应用程序通常运行在用户空间,提供各种功能和服务。
以上是嵌入式Linux系统的基本启动流程,不同的嵌入式系统可能会有一些差异。
同时,一些特定的系统也可以添加其他的启动流程步骤,如初始化设备树、加载设备固件文件等。
式操作系统的镜像,包括使用外设端口如以太网、USB、串口、并口从开发计算机上下载,也可以从本地存储设备如FLASH、CF卡、DOC或硬盘读取镜像并且跳转执行。
在开发调试Windows CE系统的过程中,最常见的方法是通过以太网口从开发计算机下载操作系统镜像到目标设备,这种类型的BootLoader有一个专门的名字叫做Eboot,E就是Ethernet的首字母。
DeviceEmulator的BootLoader就是一个典型的Eboot。
除Eboot外,比较常见的还有使用串口端口、以Serial的首字母命名的Sboot,以及专用于PC原理机型的BiosLoader等。
1.2微软建议Windows CE的BootLoader所应实现的功能微软建议Windwos CE的Bootloader所应实现的功能主要有以下6项。
(1)Windows CE的BootLoader应该存放在嵌入式设备的非可易失的存储设备中,比如Flash存储器。
此外如果硬件支持的话,最好还应该对BootLoader所在的Flash存储块实行加锁(locking)以保护它在运行过程中不被破坏。
(2)BootLoader应该在加载Windows CE操作系统镜像的过程中对加载进度、状态及错误消息等信息进行提示输出,这一般通过一个目标嵌入式设备与开发PC的串口端口连接来实现。
(3)用户在开发Windows CE的BootLoader时,应该尽可能地利用微软所提供的支持库里的功能函数。
这样做不仅可以减小开发的工作量,也是为了保证所开发的BootLoader的软件质量。
(4)Windows CE的BootLoader不仅应该可以加载操作系统的镜像,也应该有能力加载BootLoader自身的镜像文件。
不仅是下载到嵌入式系统的RAM内存,还应该能够将操作系统的或者BootLoader自身的镜像写入系统的非可易失存储器中。
③2④(5)Windows CE的BootLoader应该有能力对所加载的镜像(操作系统的或者BootLoader 自身的)的数据执行校验,并且开发者要注意在校验完全通过之前不得将镜像的任何数据写入系统的非可易失存储器中。
设计与应用计算机测量与控制.2009.17(2) Computer Measurement &Control ・389・中华测控网收稿日期:2008-07-03; 修回日期:2008-08-13。
基金项目:陕西省自然科学基金(2007F29);陕西省科技攻关项目(2007K04-01)。
作者简介:袁 磊(1983-),男,湖南衡阳人,硕士生,主要从事嵌入式系统方向的研究。
朱怡安(1960-),安徽人,教授,博导,主要从事嵌入式计算,移动计算方向的研究。
文章编号:1671-4598(2009)02-0389-03 中图分类号:TP36812 文献标识码:A嵌入式系统BootLoader 设计与实现袁 磊,朱怡安,兰 婧(西北工业大学计算机学院,陕西西安 710072)摘要:如何根据开发板的硬件资源,设计bootloader (引导加载程序)是嵌入式系统设计的重点与难点;通过分析系统的硬件组成,对bootloader 的功能,特点,结构及其主要任务进行了研究,对比分析了intel pxa250和intel pxa270的主要异同,以加载linux 操作系统内核为例,针对intel pxa270&linux 嵌入式系统开发平台,提出了一种利用uboot 实现bootloader 的软件设计与实现的新方法,从而成功引导加载操作系统内核;该设计具有一定的通用性,可广泛地应用到其他的处理器及其应用系统中;同时,详细阐述了uboot 的执行流程及其移植方法。
关键词:引导加载程序;PXA270;嵌入式系统;U -boot ;嵌入式linuxDesign and Implementation of BootLoader in embedded systemYuan Lei ,Zhu Y ian ,Lan Jing(College of Computer Science ,Northwestern Polytechnical University ,Xi πan 710072,China )Abstract :How to develop Bootloader on t he basis of specific hardware platform is a key point and difficulty of embedded system design.The paper do research on t he function ,character ,architecture and main tasks of bootloader t hrough analysing to t he organizition of system hardware.It compares t he main diferences and similarities between intel pxa250and intel pxa270.Taking loading linux operation system kernal as a example ,it introduces a new met hod on how to design and implement bootloader on t he basis of intel pxa270&linux embedded system platform.So as to sucessfully loading t he operation system kernel.The design has some flexibility and can be used to ot her proces 2sors and applications system easily.At t he same time ,it introduces how t he uboot is executed and how to transplant t he U -boot to PXA270in particular.K ey w ords :boot loader ;PXA270;embedded system ;U -boot ;embedded linux0 引言PXA270是Intel 公司生产的一款基于ARM9内核的32位RISC 芯片。
Bootloader的概念和作用(1)Bootloader的概念和作用Bootloader是嵌入式系统的引导加载程序,它是系统上电后运行的第一段程序,其作用类似于 PC 机上的 BIOS。
在完成对系统的初始化任务之后,它会将非易失性存储器(通常是 Flash或 DOC 等)中的Linux 内核拷贝到 RAM 中去,然后跳转到内核的第一条指令处继续执行,从而启动 Linux 内核。
由此可见,bootloader 和 Linux 内核有着密不可分的联系,要想清楚的了解 Linux内核的启动过程,我们必须先得认识 bootloader的执行过程,这样才能对嵌入式系统的整个启过程有清晰的掌握。
(2)Bootloader的执行过程不同的处理器上电或复位后执行的第一条指令地址并不相同,对于 ARM 处理器来说,该地址为 0x00000000。
对于一般的嵌入式系统,通常把 Flash 等非易失性存储器映射到这个地址处,而bootloader就位于该存储器的最前端,所以系统上电或复位后执行的第一段程序便是 bootloader。
而因为存储 bootloader的存储器不同,bootloader的执行过程也并不相同,下面将具体分析。
嵌入式系统中广泛采用的非易失性存储器通常是 Flash,而 Flash 又分为 Nor Flash 和Nand Flash 两种。
它们之间的不同在于: Nor Flash 支持芯片内执行(XIP, eXecute In Place),这样代码可以在Flash上直接执行而不必拷贝到RAM中去执行。
而Nand Flash并不支持XIP,所以要想执行 Nand Flash 上的代码,必须先将其拷贝到 RAM中去,然后跳到 RAM 中去执行。
实际应用中的 bootloader根据所需功能的不同可以设计得很复杂,除完成基本的初始化系统和调用 Linux 内核等基本任务外,还可以执行很多用户输入的命令,比如设置 Linux 启动参数,给Flash 分区等;也可以设计得很简单,只完成最基本的功能。
Bootloader学习笔记一.what is bootloader?Bootloader是一种独立的程序,类似于Application程序,尽管体积小,但具备启动代码、中断、主程序(Boot_main函数)和操作系统(可选)等“全部五脏”。
百度百科的词条解释:Bootloader是在加电后执行的第一段代码,完成CPU及相关硬件的初始化后,将操作系统映像或固化的嵌入式应用程序装载到内存,并跳转到操作系统空间启动运行。
下面是学习bootloader的系统路线:1.了解bootloader的定义:Bootloader是嵌入式系统在启动时执行的第一段代码,它完成硬件初始化,加载操作系统或固件。
2.掌握bootloader的工作原理:当系统开机时,CPU执行的是bootloader的代码,它读取存储设备(如硬盘,U盘,SD卡等)中的操作系统镜像或固件,加载到内存中,并进行跳转。
3.了解常见的bootloader的类型:如U-Boot,Grub等,并了解它们的特点和适用场景。
4.学习bootloader的开发:包括硬件初始化,文件系统的读取,代码的跳转等。
5.掌握bootloader的应用:比如系统升级,系统恢复等。
二.为什么需要bootloader?Bootloader是用于启动操作系统的引导程序,它是计算机启动过程中的第一个执行的程序。
需要Bootloader的原因有以下几点:1.引导操作系统:Bootloader负责读取和加载操作系统,并将控制权转交给操作系统。
2.进行硬件初始化:Bootloader初始化计算机硬件,确保操作系统能够正确识别和使用硬件。
3.提供系统恢复选项:Bootloader可以提供系统恢复选项,例如进入安全模式或恢复到原始配置。
4.实现多操作系统启动:Bootloader可以用于启动多个操作系统,例如通过引导菜单选择启动Windows或Linux操作系统。
因此,Bootloader是计算机启动过程中不可或缺的一部分,它起到了重要的辅助作用。
嵌入式系统Boot Loader 技术内幕(3)在boot loader 程序的设计与实现中,没有什么能够比从串口终端正确地收到打印信息能更令人激动了。
此外,向串口终端打印信息也是一个非常重要而又有效的调试手段。
但是,我们经常会碰到串口终端显示乱码或根本没有显示的问题。
造成这个问题主要有两种原因:(1) boot loader 对串口的初始化设置不正确。
(2) 运行在host 端的终端仿真程序对串口的设置不正确,这包括:波特率、奇偶校验、数据位和停止位等方面的设置。
此外,有时也会碰到这样的问题,那就是:在boot loader 的运行过程中我们可以正确地向串口终端输出信息,但当boot loader 启动内核后却无法看到内核的启动输出信息。
对这一问题的原因可以从以下几个方面来考虑:(1) 首先请确认你的内核在编译时配置了对串口终端的支持,并配置了正确的串口驱动程序。
(2) 你的boot loader 对串口的初始化设置可能会和内核对串口的初始化设置不一致。
此外,对于诸如s3c44b0x 这样的CPU,CPU 时钟频率的设置也会影响串口,因此如果boot loader 和内核对其CPU 时钟频率的设置不一致,也会使串口终端无法正确显示信息。
(3) 最后,还要确认boot loader 所用的内核基地址必须和内核映像在编译时所用的运行基地址一致,尤其是对于uClinux 而言。
假设你的内核映像在编译时用的基地址是0xc0008000,但你的boot loader 却将它加载到0xc0010000处去执行,那么内核映像当然不能正确地执行了。
Boot Loader 的设计与实现是一个非常复杂的过程。
如果不能从串口收到那激动人心的uncompressing linux.................. done, booting the kernel 内核启动信息,恐怕谁也不能说:嗨,我的boot loader 已经成功地转起来了!。
paper @ (投稿专用) 2006年第11期Microcontrollers &Embedded Systems 33 3本课题为华南理工大学教学研究支持项目。
在B o o t l o a d e r 中实现嵌入式系统自动升级3■华南理工大学 邵新颜蔡梅琳 摘 要在嵌入式系统中,对内核或文件系统进行升级,一般是将目标板连接到主机,通过J TA G 口、串口或网口来完成升级过程。
本文讨论一种更为方便的升级方法,即在Bootloader 中通过CF 存储卡升级系统。
嵌入式系统中的Bootloader 通常用于引导操作系统,本文描述了如何通过增强Bootloader 的功能,实现对嵌入式系统的自动升级。
关键词Bootloader嵌入式系统CF 存储卡 自动升级 嵌入式系统由硬件和软件两部分组成,软件部分主要包括Bootloader 、内核和文件系统。
Bootloader 是硬件系统加电所运行的第1段软件代码,但在嵌入式系统中一般没有像PC 中的BIOS 那样的固件,因此整个系统的加载过程全部是由Bootloader 来完成的。
系统在上电或复位时通常都从地址0x00000000处开始执行,而在这个地址处安排的通常就是系统的Bootloader 。
Bootloader 的主要任务包括:初始化最基本的硬件;将Bootloader 本身拷贝到RAM 中运行;将内核拷贝到RAM 中并调用内核等。
通常在嵌入式系统中,首先通过J T A G 接口将Boot 2loader 烧写到目标板的Flash 中,然后在Bootloader 中,将内核映像文件和文件系统映像文件通过串口和网络下载并烧写到Flash 中。
若需对内核或文件系统升级,则按照上述方法重新烧写新的映像文件,直接覆盖原来的映像文件。
上述方法中,一方面必须将目标板和主机通过串口线和网线相连接,另一方面通过串口或网络下载映像文件,速度很慢。
本实验通过扩充Bootloader 功能,实现了通过CF 存储卡对内核或文件系统映像文件的自动升级,对需要经常为内核或文件系统升级的嵌入式系统来说,克服了传统升级方法的局限,简化了升级方法,提高了升级速度。
bootloader详细介绍Bootloader对于计算机系统来说,从开机上电到操作系统启动需要⼀个引导过程。
嵌⼊式Linux系统同样离不开引导程序,这个引导程序就叫作Bootloader。
6.1.1 Bootloader介绍Bootloader是在操作系统运⾏之前执⾏的⼀段⼩程序。
通过这段⼩程序,我们可以初始化硬件设备、建⽴内存空间的映射表,从⽽建⽴适当的系统软硬件环境,为最终调⽤操作系统内核做好准备。
对于嵌⼊式系统,Bootloader是基于特定硬件平台来实现的。
因此,⼏乎不可能为所有的嵌⼊式系统建⽴⼀个通⽤的Bootloader,不同的处理器架构都有不同的Bootloader。
Bootloader不但依赖于CPU的体系结构,⽽且依赖于嵌⼊式系统板级设备的配置。
对于2块不同的嵌⼊式板⽽⾔,即使它们使⽤同⼀种处理器,要想让运⾏在⼀块板⼦上的Bootloader程序也能运⾏在另⼀块板⼦上,⼀般也都需要修改Bootloader 的源程序。
反过来,⼤部分Bootloader仍然具有很多共性,某些Bootloader也能够⽀持多种体系结构的嵌⼊式系统。
例如,U-Boot就同时⽀持PowerPC、ARM、MIPS和X86等体系结构,⽀持的板⼦有上百种。
通常,它们都能够⾃动从存储介质上启动,都能够引导操作系统启动,并且⼤部分都可以⽀持串⼝和以太⽹接⼝。
本章将对各种Bootloader总结分类,分析它们的共同特点。
以U-Boot为例,详细讨论Bootloader的设计与实现。
6.1.2 Bootloader的启动Linux系统是通过Bootloader引导启动的。
⼀上电,就要执⾏Bootloader来初始化系统。
可以通过第4章的Linux启动过程框图回顾⼀下。
系统加电或复位后,所有CPU都会从某个地址开始执⾏,这是由处理器设计决定的。
⽐如,X86的复位向量在⾼地址端,ARM处理器在复位时从地址0x00000000取第⼀条指令。
本文出自“李云”博客/831344/181630在嵌入式系统当中你可能经常听到bootloader(引导加载器)这一词,bootloader是指什么呢?在我们日常经常接触的东西中是不是有与bootloader的作用或是概念相似的呢?有一点我一定猜得到,你现在正在用计算机看这篇文章。
如果你稍微熟悉计算机的组成,你一定知道BIOS(Basic Input/Output System)。
BIOS在计算机中就是用来启动计算系统的,在完成一定的硬件初始化工作以及人机交互后,它加载位于硬盘中的操作系统,并最终运行操作系统。
嵌入式系统中的bootloader与BIOS的作用就是相类似的,也是完成对于处理器相关的硬件资源进行初始化后,最后加载通常是存放在FLASH中的应用程序,当然在嵌入式系统当中操作系统与应用程序一般是在同一个可执行文件中的,这与我们的电脑有很大的不同。
BIOS与bootloader有相同之处,比如:1)完成处理器正常最小系统的初始化。
最小系统的概念通过举个例比较容易让人明白,比如对于我们的计算机,通常在初始化时不需要用到以太网,因此,在最小化系统中就不包括以太网卡的初始化,对其的初始化完全可以放到操作系统中去做,而不是在BIOS中。
相类似的是,在嵌入式系统中,我们通常不需要在初始化的过程中用到USB设备,那么对于USB设备的初始化就不需要包含在最小系统中,而可以在被bootloader加载的应用程序中去初始化它。
2)两者在最后都得加载其它的程序,并将运行权交给被加载的程序。
对于BIOS,其所加载的程序通常是操作系统,当然,如果你正在安装系统那么BIOS所加载的可能是位于光盘中安装程序。
对于loader,其加载的是一个可执行程序,这一可执行程序包括实时操作系统(有的也不是实时操作系统)和我们的应用程序。
3)如果BIOS或是bootloader程序太大,通常都会采用压缩技术对其进行压缩。
对于BIOS,其肯定会采用压缩技术进行压缩,因为BIOS随着计算机行业的飞速发展而越来越复杂,比如,以前的BIOS不需要支持USB的鼠标和键盘,但现在就得支持了,这就意味着BIOS要有USB鼠标和键盘的驱动程序。
嵌入式软件Bootloader设计与移植王小妮【期刊名称】《电脑开发与应用》【年(卷),期】2015(000)001【摘要】嵌入式电子产品由于其专用性的特性,使得与硬件相关的软件需要经过移植才能使用。
如何设计与移植设备开机第一个运行的代码引导程序Bootloader 尤为重要。
不同内核开发平台的Bootloader均需要重新修改及烧写。
在此介绍了嵌入式软件分类、引导程序分类、Bootloader功能、设计方法,并分析U-Boot 工作机制、移植具体方法。
%Because of its specificity of embedded electronic products, software related with hardware needs portability before use. How to design and transplant Bootloader which is the first code of device boot program is particularly important. Bootloader of different kernel development platforms need to modify and write. The embedded software classification, bootstrap program classification, function of Bootloader, program design method is introduced, and the working mechanism of U-Boot and the important method is analyzed.【总页数】3页(P11-13)【作者】王小妮【作者单位】北京信息科技大学理学院,北京 100192【正文语种】中文【中图分类】TP311.1【相关文献】1.基于Bootloader的嵌入式软件通用更新机制 [J], 孙立新2.μCLinux操作系统的移植及Bootloader程序设计 [J], 刘彦兰3.基于Bootloader的可靠嵌入式软件远程更新机制 [J], 王恒;王颋;王泉;李勇4.基于Windows CE的BootLoader架构设计与移植 [J], 陈才;马连伟5.嵌入式软件可移植性设计技术 [J], 王业流;王强因版权原因,仅展示原文概要,查看原文内容请购买。
bootloader:嵌入式BootLoader技术内幕疯狂代码 / ĵ:http://NetworkProgramming/Article33523.html、引言 ;在专用嵌入式板子运行 ;GNU/Linux ;系统已经变得越来越流行个嵌入式 ;Linux ;系统从软件角度看通常可以分为四个层次: ;1. ;引导加载包括固化在固件(firmware)中 ;boot ;代码(可选)和 ;Boot ;Loader ;两大部分 ;2. ;Linux ;内核特定于嵌入式板子定制内核以及内核启动参数 ;3. ;文件系统包括根文件系统和建立于 ;Flash ;内存设备之上文件系统通常用 ;ram ;disk ;来作为 ;root ;fs ;4. ;用户应用特定于用户应用有时在用户应用和内核层之间可能还会包括个嵌入式图形用户界面常用嵌入式 ;GUI ;有:MicroWindows ;和 ;MiniGUI ;懂 ;引导加载是系统加电后运行第段软件代码回忆下 ;PC ;体系结构我们可以知道PC ;机中引导加载由 ;BIOS(其本质就是段固件)和位于硬盘 ;MBR ;中 ;OSBoot ;Loader(比如LILO ;和 ;GRUB ;等)起组成BIOS ;在完成硬件检测和资源分配后将硬盘 ;MBR ;中 ;Boot ;Loader ;读到系统 ;RAM ;中然后将控制权交给 ;OS ;Boot ;LoaderBoot ;Loader ;主要运行任务就是将内核映象从硬盘上读到 ;RAM ;中然后跳转到内核入口点去运行也即开始启动操作系统 ;而在嵌入式系统中通常并没有像 ;BIOS ;那样固件(注有嵌入式 ;CPU ;也会内嵌段短小启动)因此整个系统加载启动任务就完全由 ;Boot ;Loader ;来完成比如在个基于 ;ARM7TDMI ;core ;嵌入式系统中系统在上电或复位时通常都从地址 ;0x00000000 ;处开始执行而在这个地址处安排通常就是系统 ;Boot ;Loader ; ;本文将从 ;Boot ;Loader ;概念、Boot ;Loader ;主要任务、Boot ;Loader ;框架结构以及Boot ;Loader ;安装等四个方面来讨论嵌入式系统 ;Boot ;Loader ;二、 ;Boot ;Loader ;概念 ;简单地说Boot ;Loader ;就是在操作系统内核运行之前运行段小通过这段小程序我们可以化硬件设备、建立内存空间映射图从而将系统软硬件环境带到个合适状态以便为最终操作系统内核准备好正确环境 ;通常Boot ;Loader ;是严重地依赖于硬件而实现特别是在嵌入式世界因此在嵌入式世界里建立个通用 ;Boot ;Loader ;几乎是不可能尽管如此我们仍然可以对 ;Boot ;Loader ;归纳出些通用概念来以指导用户特定 ;Boot ;Loader ;设计与实现 ;1. ;Boot ;Loader ;所支持 ;CPU ;和嵌入式板 ;每种不同 ;CPU ;体系结构都有不同 ;Boot ;Loader有些 ;Boot ;Loader ;也支持多种体系 结构 ;CPU比如 ;U-Boot ;就同时支持 ;ARM ;体系结构和MIPS ;体系结构除了依赖于 ;CPU 体系结构外Boot ;Loader ;实际上也依赖于具体嵌入式板级设备配置这也就是说对于两块不同嵌入式板而言即使它们是基于同种 ;CPU ;而构建要想让运行在块板子上 ;Boot ;Loader ;也能运行在另块板子上通常也都需要修改 ;Boot ;Loader ;源 ;2. ;Boot ;Loader ;安装媒介(Installation ;Medium) ;系统加电或复位后所有 ;CPU ;通常都从某个由 ;CPU ;制造商预先安排地址上取指令比如基于 ;ARM7TDMI ;core ; ;CPU ;在复位时通常都从地址 ;0x00000000 ;取它第条指 令而基于 ;CPU ;构建嵌入式系统通常都有某种类型固态存储设备(比如:ROM、EEPRO M ;或 ;FLASH ;等)被映射到这个预先安排地址上因此在系统加电后CPU ;将首先执行 ;B oot ;Loader ; ;下图1就是个同时装有 ;Boot ;Loader、内核启动参数、内核映像和根文件系统映像固态存储设备典型空间分配结构图 ;" align=absMiddle>/RTOS/UploadFiles_RTOS/200511/20051130030711799.g ;图1 ;固态存储设备典型空间分配结构3. ;用来控制 ;Boot ;Loader ;设备或机制 ;主机和目标机之间般通过串口建立连接Boot ;Loader ;软件在执行时通常会通过串口来进行 ;I/O比如:输出打印信息到串口从串口读取用户控制等 ;4. ;Boot ;Loader ;启动过程是单阶段(Single ;Stage)还是多阶段(Multi-Stage) ;通常多阶段 ;Boot ;Loader ;能提供更为复杂功能以及更好可移植性从固态存储设备上启动 ;Boot ;Loader ;大多都是 ;2 ;阶段启动过程也即启动过程可以分为 ;stage ;1和 ;stage ;2 ;两部分而至于在 ;stage ;1 ;和 ;stage ;2 ;具体完成哪些任务将在下面几篇讨论 ;5. ;Boot ;Loader ;操作模式 ;(Operation ;Mode) ;大多数 ;Boot ;Loader ;都包含两种不同操作模式:"启动加载"模式和"下载"模式这种区别仅对于开发人员才有意义但从最终用户角度看Boot ;Loader ;作用就是用来加载操作系统而并不存在所谓启动加载模式与下载工作模式区别 ;启动加载(Boot ;loading)模式:这种模式也称为"自主"(Autonomous)模式也即 ;Boo t ;Loader ;从目标机上某个固态存储设备上将操作系统加载到 ;RAM ;中运行整个过程并没有用户介入这种模式是 ;Boot ;Loader ;正常工作模式因此在嵌入式产品发布时侯Boot ;Loader ;显然必须工作在这种模式下 ;下载(Downloading)模式:在这种模式下目标机上 ;Boot ;Loader ;将通过串口连接或网络连接等通信手段从主机(Host)下载文件比如:下载内核映像和根文件系统映像等从主机下载文件通常首先被 ;Boot ;Loader ;保存到目标机 ;RAM ;中然后再被 ;Boot ; Loader ;写到目标机上FLASH ;类固态存储设备中Boot ;Loader ;这种模式通常在第次安装内核与根文件系统时被使用;此外以后系统更新也会使用 ;Boot ;Loader ;这种工作模式工作于这种模式下 ;Boot ;Loader ;通常都会向它终端用户提供个简单命令行接口 ;像 ;Blob ;或 ;U-Boot ;等这样功能强大 ;Boot ;Loader ;通常同时支持这两种工作模式而且 允许用户在这两种工作模式之间进行切换比如Blob ;在启动时处于正常启动加载模式但是它会延时 ;10 ;秒等待终端用户按下任意键而将 ;blob ;切换到下载模式如果在 ;10 ;秒内没有用户按键则 ;blob ;继续启动 ;Linux ;内核 ;6. ;BootLoader ;与主机之间进行文件传输所用通信设备及协议 ;最常见情况就是目标机上 ;Boot ;Loader ;通过串口与主机之间进行文件传输传输协议通常是 ;xmodem/ymodem/zmodem ;协议中种但是串口传输速度是有限因此通过以太网连接并借助 ;TFTP ;协议来下载文件是个更好选择 ;此外在论及这个话题时主机方所用软件也要考虑比如在通过以太网连接和 ;TFTP ;协议来下载文件时主机方必须有个软件用来提供 ;TFTP ;服务在讨论了 ;BootLoader ;上述概念后下面我们来具体看看 ;BootLoader ;应该完成哪些任务--------------------------------------------------------------------------------由 ;lefthand05 ;在 ;05-08-2004 ;16:04 ;发表: ;嵌入式BootLoader技术内幕(二)三、Boot ;Loader ;主要任务与典型结构框架 ;在继续本节讨论之前首先我们做个假定那就是:假定内核映像与根文件系统映像都被加载到 ;RAM ;中运行之所以提出这样个假设前提是在嵌入式系统中内核映像与根文件系统映像也可以直接在 ;ROM ;或 ;Flash ;这样固态存储设备中直接运行但这种 做法无疑是以运行速度牺牲为代价从操作系统角度看Boot ;Loader ;总目标就是正确地内核来执行 ;另外由于 ;Boot ;Loader ;实现依赖于 ;CPU ;体系结构因此大多数 ;Boot ;Loader ;都分 为 ;stage1 ;和 ;stage2 ;两大部分依赖于 ;CPU ;体系结构代码比如设备化代码等通常都放在 ;stage1 ;中而且通常都用汇编语言来实现以达到短小精悍目而 ;stage2 ;则通常用C语言来实现这样可以实现给复杂功能而且代码会具有更好可读性和可移植性 ;Boot ;Loader ; ;stage1 ;通常包括以下步骤(以执行先后顺序):·硬件设备化·为加载 ;Boot ;Loader ; ;stage2 ;准备 ;RAM ;空间·拷贝 ;Boot ;Loader ; ;stage2 ;到 ;RAM ;空间中·设置好堆栈·跳转到 ;stage2 ; ;C ;入口点Boot ;Loader ; ;stage2 ;通常包括以下步骤(以执行先后顺序):·化本阶段要使用到硬件设备·检测系统内存映射(memory ;map)·将 ;kernel ;映像和根文件系统映像从 ;flash ;上读到 ;RAM ;空间中·为内核设置启动参数·内核 ;3.1 ;Boot ;Loader ; ;stage1 ;3.1.1 ;基本硬件化 ;这是 ;Boot ;Loader ;开始就执行操作其目是为 ;stage2 ;执行以及随后 ;kernel执行准备好些基本硬件环境它通常包括以下步骤(以执行先后顺序): ;1.屏蔽所有中断为中断提供服务通常是 ;OS ;设备驱动责任因此在 ;Boot ;Loader ;执行全过程中可以不必响应任何中断中断屏蔽可以通过写 ;CPU ;中断屏蔽寄存器 或状态寄存器(比如 ;ARM ; ;CPSR ;寄存器)来完成 ;2.设置 ;CPU ;速度和时钟频率 ;3.RAM ;化包括正确地设置系统内存控制器功能寄存器以及各内存库控制寄存器等 ;4.化 ;LED典型地通过 ;GPIO ;来驱动 ;LED其目是表明系统状态是 ;OK ;还是 ;Error如果板子上没有 ;LED那么也可以通过化 ;UART ;向串口打印 ;Boot ;Loader ; Logo ;信息来完成这点 ;5. ;关闭 ;CPU ;内部指令/数据 ;cache ;3.1.2 ;为加载 ;stage2 ;准备 ;RAM ;空间 ;为了获得更快执行速度通常把 ;stage2 ;加载到 ;RAM ;空间中来执行因此必须为加载 ; Boot ;Loader ; ;stage2 ;准备好段可用 ;RAM ;空间范围 ;由于 ;stage2 ;通常是 ;C ;语言执行代码因此在考虑空间大小时除了 ;stage2 ;可执行映象 大小外还必须把堆栈空间也考虑进来此外空间大小最好是 ;memory ;page ;大小(通常是 ;4KB)倍数般而言1M ; ;RAM ;空间已经足够了具体地址范围可以任意安排比如 ;blob ;就将它 ;stage2 ;可执行映像安排到从系统 ;RAM ;起始地址 ;0xc0200000 ;开始 ;1M ;空间内执行但是将 ;stage2 ;安排到整个 ;RAM ;空间最顶 ;1MB(也即(RamEnd-1M B) ;- ;RamEnd)是种值得推荐方法 ;为了后面叙述方便这里把所安排 ;RAM ;空间范围大小记为:stage2_size(字节)把起始地址和终止地址分别记为:stage2_start ;和 ;stage2_end(这两个地址均以 ;4 ;字节 边界对齐)因此: ;stage2_end=stage2_start+stage2_size另外还必须确保所安排地址范围确确是可读写 ;RAM ;空间因此必须对你所安排地址范围进行测试具体测试方法可以采用类似于 ;blob ;方法也即:以 ;memory ;page ;为被测试单位测试每个 ;memory ;page ;开始两个字是否是可读写为了后面叙述方便我们记这个检测算法为:test_mempage其具体步骤如下: ;1.先保存 ;memory ;page ;开始两个字内容 ;2.向这两个字中写入任意数字比如:向第个字写入 ;0x55第 ;2 ;个字写入 ;0xaa3.然后立即将这两个字内容读回显然我们读到内容应该分别是 ;0x55 ;和 ;0xaa如果不是则说明这个 ;memory ;page ;所占据地址范围不是段有效 ;RAM ;空间 ;4.再向这两个字中写入任意数字比如:向第个字写入 ;0xaa第 ;2 ;个字中写入 ;0x55 ;5.然后立即将这两个字内容立即读回显然我们读到内容应该分别是 ;0xaa ;和 ;0x55如果不是则说明这个 ;memory ;page ;所占据地址范围不是段有效 ;RAM ;空间;6.恢复这两个字原始内容测试完毕 ;为了得到段干净 ;RAM ;空间范围我们也可以将所安排 ;RAM ;空间范围进行清零操作 ;3.1.3 ;拷贝 ;stage2 ;到 ;RAM ;中 ;拷贝时要确定两点:(1) ;stage2 ;可执行映象在固态存储设备存放起始地址和终止地址 ;(2) ;RAM ;空间起始地址 ;3.1.4 ;设置堆栈指针 ;sp ;堆栈指针设置是为了执行 ;C ;语言代码作好准备通常我们可以把 ;sp ;值设置为(stage2_end-4)也即在 ;3.1.2 ;节所安排那个 ;1MB ; ;RAM ;空间最顶端(堆栈向下生长)此外在设置堆栈指针 ;sp ;之前也可以关闭 ;led ;灯以提示用户我们准备跳转到 ;stage2经过上述这些执行步骤后系统物理内存布局应该如下图2所示 ;3.1.5 ;跳转到 ;stage2 ; ;C ;入口点 ;在上述切都就绪后就可以跳转到 ;Boot ;Loader ; ;stage2 ;去执行了比如在 ;ARM ;系统中这可以通过修改 ;PC ;寄存器为合适地址来实现 ;" align=absMiddle>/RTOS/UploadFiles_RTOS/200511/20051130030711934.g图2 ;bootloader ; ;stage2 ;可执行映象刚被拷贝到 ;RAM ;空间时系统内存布局3.2 ;Boot ;Loader ; ;stage2 ;正如前面所说stage2 ;代码通常用 ;C ;语言来实现以便于实现更复杂功能和取得更好代码可读性和可移植性但是与普通 ;C ;语言应用不同是在编译和链接 ;bootloader ;这样时我们不能使用 ;glibc ;库中任何支持其原因是显而易见这就给我们带来个问题那就是从那里跳转进 ; ;呢?直接把 ; ;起始地址作为整个 ;stage2 ;执行映像入口点或许是最直接想法但是这样做有两个缺点:1)无法通过 ;传递参数;2)无法处理 ; ;返回情况种更为巧妙方法是利用 ;trampoline(弹簧床)概念也即用汇编语言写段trampoline ;小并将这段 ;trampoline ;小来作为 ;stage2 ;可执行映象执行入口点然后我们可以在 ;trampoline ;汇编小中用 ;CPU ;跳转指令跳入 ; ;中去执行;而当;返回时CPU ;执行路径显然再次回到我们 ;trampoline ;简而言之这种方法思想就是:用这段 ;trampoline ;小来作为 ; ;外部包裹(external ;wrapper) ;下面给出个简单 ;trampoline ;示例(来自blob): ;.text.globl ;_trampoline_trampoline:bl ;/* ; ; ;ever ;s ;we ;just ;call ;it ;again ;*/b ;_trampoline可以看出当 ; ;返回后我们又用条跳转指令重新执行 ;trampoline ;――当然也就重新执行 ; ;这也就是 ;trampoline(弹簧床)词意思所在 ;3.2.1化本阶段要使用到硬件设备 ;这通常包括:(1)化至少个串口以便和终端用户进行 ;I/O ;输出信息;(2)化计时器等在化这些设备之前也可以重新把 ;LED ;灯点亮以表明我们已经进入 ;;执行 ;设备化完成后可以输出些打印信息名字串、版本号等 ;3.2.2 ;检测系统内存映射(memory ;map) ;所谓内存映射就是指在整个 ;4GB ;物理地址空间中有哪些地址范围被分配用来寻址系统 ; RAM ;单元比如在 ;SA-1100 ;CPU ;中从 ;0xC000,0000 ;开始 ;512M ;地址空间被用作系统 ;RAM ;地址空间而在 ;Samsung ;S3C44B0X ;CPU ;中从 ;0x0c00,0000 ;到 ;0x1000,0000 之间 ;64M ;地址空间被用作系统 ;RAM ;地址空间虽然 ;CPU ;通常预留出大段足够地址空间给系统 ;RAM但是在搭建具体嵌入式系统时却不定会实现 ;CPU ;预留全部 ;RAM ;地址空间也就是说具体嵌入式系统往往只把 ;CPU ;预留全部 ;RAM ;地址空间中部分映射到 ;RAM ;单元上而让剩下那部分预留 ;RAM ;地址空间处于未使用状态由于上述这个事实因此 ;Boot ;Loader ; ;stage2 ;必须在它想干点什么 ;(比如将存储在 ; flash ;上内核映像读到 ;RAM ;空间中) ;之前检测整个系统内存映射情况也即它必须知道 ;CPU ;预留全部 ;RAM ;地址空间中哪些被真正映射到 ;RAM ;地址单元哪些是处于 ;"u nused" ;状态 ;(1) ;内存映射描述 ;可以用如下数据结构来描述 ;RAM ;地址空间中段连续(continuous)地址范围: ;typedef ;struct ;memory_area_struct ;{u32 ;start; ;/* ;the ;base ;address ;of ;the ;memory ;region ;*/u32 ;size; ;/* ;the ; ;number ;of ;the ;memory ;region ;*/;used;} ;memory_area_t;这段 ;RAM ;地址空间中连续地址范围可以处于两种状态之:(1)used=1则说明这段连续地址范围已被实现也即真正地被映射到 ;RAM ;单元上(2)used=0则说明这段连续地址范围并未被系统所实现而是处于未使用状态 ;基于上述 ;memory_area_t ;数据结构整个 ;CPU ;预留 ;RAM ;地址空间可以用个 ;memory _area_t ;类型来表示如下所示: ;memory_area_t ;memory_map[NUM_MEM_AREAS] ;= ;{[0 ;... ;(NUM_MEM_AREAS ;- ;1)] ;= ;{.start ;= ;0,.size ;= ;0,.used ;= ;0},};(2) ;内存映射检测 ;下面我们给出个可用来检测整个 ;RAM ;地址空间内存映射情况简单而有效算法: ;/* ;化 ;*/for(i ;= ;0; ;i ;< ;NUM_MEM_AREAS; ;i)memory_map[i].used ;= ;0;/* ;first ;write ;a ;0 ;to ;all ;memory ;locations ;*/for(addr ;= ;MEM_START; ;addr ;< ;MEM_END; ;addr ; ;PAGE_SIZE)* ;(u32 ;*)addr ;= ;0;for(i ;= ;0, ;addr ;= ;MEM_START; ;addr ;< ;MEM_END; ;addr ; ;PAGE_SIZE) ;{ /** ;检测从基地址 ;MEM_START+i*PAGE_SIZE ;开始,大小为* ;PAGE_SIZE ;地址空间是否是有效RAM地址空间*/3.1.2节中算法test_mempage;;( ;current ;memory ;page ;isnot ;a ;valid ;ram ;page) ;{/* ;no ;RAM ;here ;*/(memory_map[i].used ;)i;continue;}/** ;当前页已经是个被映射到 ;RAM ;有效地址范围* ;但是还要看看当前页是否只是 ;4GB ;地址空间中某个地址页别名?*/(* ;(u32 ;*)addr ;!= ;0) ;{ ;/* ;alias? ;*//* ;这个内存页是 ;4GB ;地址空间中某个地址页别名 ;*/;( ;memory_map[i].used ;)i;continue;}/** ;当前页已经是个被映射到 ;RAM ;有效地址范围* ;而且它也不是 ;4GB ;地址空间中某个地址页别名*/;(memory_map[i].used ; ;0) ;{memory_map[i].start ;= ;addr;memory_map[i].size ;= ;PAGE_SIZE;memory_map[i].used ;= ;1;} ; ;{memory_map[i].size ; ;PAGE_SIZE;}} ;/* ;end ;of ;for ;(…) ;*/在用上述算法检测完系统内存映射情况后Boot ;Loader ;也可以将内存映射详细信息打印到串口 ;3.2.3 ;加载内核映像和根文件系统映像 ;(1) ;规划内存占用布局 ;这里包括两个方面:(1)内核映像所占用内存范围;(2)根文件系统所占用内存范围在规划内存占用布局时主要考虑基地址和映像大小两个方面 ;对于内核映像般将其拷贝到从(MEM_START+0x8000) ;这个基地址开始大约1MB大小内存范围内(嵌入式 ;Linux ;内核般都不操过 ;1MB)为什么要把从 ;MEM_START ;到 ;MEM _START+0x8000 ;这段 ;32KB ;大小内存空出来呢?这是 ;Linux ;内核要在这段内存中放置些全局数据结构如:启动参数和内核页表等信息 ;而对于根文件系统映像则般将其拷贝到 ;MEM_START+0x0010,0000 ;开始地方如果用 Ramdisk ;作为根文件系统映像则其解压后大小般是1MB ;(2)从 ;Flash ;上拷贝 ;由于像 ;ARM ;这样嵌入式 ;CPU ;通常都是在统内存地址空间中寻址 ;Flash ;等固态存储设备因此从 ;Flash ;上读取数据与从 ;RAM ;单元中读取数据并没有什么不同用个简单循环就可以完成从 ;Flash ;设备上拷贝映像工作: ;while(count) ;{*dest ;= ;*src; ;/* ;they ;are ;all ;aligned ;with ;word ;boundary ;*/count ;-= ;4; ;/* ; ;number ;*/};3.2.4 ;设置内核启动参数 ;应该说在将内核映像和根文件系统映像拷贝到 ;RAM ;空间中后就可以准备启动 ;Linux ;内核了但是在内核之前应该作步准备工作即:设置 ;Linux ;内核启动参数Linux ;2.4.x ;以后内核都期望以标记列表(tagged ;list)形式来传递启动参数启动参数标记列表以标记 ;ATAG_CORE ;开始以标记 ;ATAG_NONE ;结束每个标记由标识被传递参 数 ;tag_header ;结构以及随后参数值数据结构来组成数据结构 ;tag ;和 ;tag_header定义在 ;Linux ;内核源码/asm/up.h ;头文件中: ;/* ;The ;list ;ends ;with ;an ;ATAG_NONE ;node. ;*/# ;ATAG_NONE ;0x00000000struct ;tag_header ;{u32 ;size; ;/* ;注意这里size是字数为单位 ;*/u32 ;tag;};……struct ;tag ;{struct ;tag_header ;hdr;union ;{struct ;tag_core ;core;struct ;tag_mem32 ;mem;struct ;tag_videotext ;videotext;struct ;tag_ramdisk ;ramdisk;struct ;tag_initrd ;initrd;struct ;tag_serialnr ;serialnr;struct ;tag_revision ;revision;struct ;tag_videolfb ;videolfb;struct ;tag_cmdline ;cmdline;/** ;Acorn ;specic*/struct ;tag_acorn ;acorn;/** ;DC21285 ;specic*/struct ;tag_memclk ;memclk;} ;u;};在嵌入式 ;Linux ;系统中通常需要由 ;Boot ;Loader ;设置常见启动参数有:ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、ATAG_INITRD等比如设置 ;ATAG_CORE ;代 码如下: ;params ;= ;(struct ;tag ;*)BOOT_PARAMS;params->hdr.tag ;= ;ATAG_CORE;params->hdr.size ;= ;tag_size(tag_core);params->u.core.flags ;= ;0;params->u.core.pagesize ;= ;0;params->u.core.rootdev ;= ;0;params ;= ;tag_next(params);其中BOOT_PARAMS ;表示内核启动参数在内存中起始基地址指针 ;params ;是个 ;str uct ;tag ;类型指针宏 ;tag_next ;将以指向当前标记指针为参数计算紧临当前标记下个标记起始地址注意内核根文件系统所在设备ID就是在这里设置下面是设置内存映射情况示例代码: ;for(i ;= ;0; ;i ;< ;NUM_MEM_AREAS; ;i) ;{(memory_map[i].used) ;{params->hdr.tag ;= ;ATAG_MEM;params->hdr.size ;= ;tag_size(tag_mem32);params->u.mem.start ;= ;memory_map[i].start;params->u.mem.size ;= ;memory_map[i].size;params ;= ;tag_next(params);}}可以看出在 ;memory_map[]中每个有效内存段都对应个 ;ATAG_MEM ;参数标记 ;Linux ;内核在启动时可以以命令行参数形式来接收信息利用这点我们可以向内核提供那些内核不能自己检测硬件参数信息或者重载(override)内核自己检测到信息比如我们用这样个命令行参数串"console=ttyS0,115200n8"来通知内核以 ;ttyS0作为控制台且串口采用 ;"115200bps、无奇偶校验、8位数据位"这样设置下面是段设置内核命令行参数串示例代码: ;char ;*p;/* ;eat ;leading ;white ;space ;*/for(p ;= ;commandline; ;*p ; ;' ;'; ;p);/* ;skip ;non-existent ;command ;lines ;so ;the ;kernel ;will ;still* ;use ;its ;default ;command ;line.*/(*p ; ;'\0');params->hdr.tag ;= ;ATAG_CMDLINE;params->hdr.size ;= ;((struct ;tag_header) ;+ ;strlen(p) ;+ ;1 ;+ ;4) ;>> ;2;strcpy(params->u.cmdline.cmdline, ;p);params ;= ;tag_next(params);请注意在上述代码中设置 ;tag_header ;大小时必须包括串终止符'\0'此外还要将字节数向上圆整4个字节 ;tag_header ;结构中size ;成员表示是字数 ;下面是设置 ;ATAG_INITRD ;示例代码它告诉内核在 ;RAM ;中什么地方可以找到 ;initrd ;映象(压缩格式)以及它大小: ;params->hdr.tag ;= ;ATAG_INITRD2;params->hdr.size ;= ;tag_size(tag_initrd);params->u.initrd.start ;= ;RAMDISK_RAM_BASE;params->u.initrd.size ;= ;INITRD_LEN;params ;= ;tag_next(params);下面是设置 ;ATAG_RAMDISK ;示例代码它告诉内核解压后 ;Ramdisk ;有多大(单位是K B): ;params->hdr.tag ;= ;ATAG_RAMDISK;params->hdr.size ;= ;tag_size(tag_ramdisk);params->u.ramdisk.start ;= ;0;params->u.ramdisk.size ;= ;RAMDISK_SIZE; ;/* ;请注意单位是KB ;*/params->u.ramdisk.flags ;= ;1; ;/* ;automatically ;load ;ramdisk ;*/params ;= ;tag_next(params);最后设置 ;ATAG_NONE ;标记结束整个启动参数列表: ;;void ;up_end_tag(void){params->hdr.tag ;= ;ATAG_NONE;params->hdr.size ;= ;0;}3.2.5 ;内核 ;Boot ;Loader ; ;Linux ;内核方法是直接跳转到内核第条指令处也即直接跳转到MEM_START+0x8000 ;地址处在跳转时下列条件要满足: ;1. ;CPU ;寄存器设置:·R0=0;@R1=机器类型 ;ID;关于 ;Machine ;Type ;Number可以参见 ;linux/arch/arm/tools/mach -types@R2=启动参数标记列表在 ;RAM ;中起始基地址; ;2. ;CPU ;模式:·必须禁止中断(IRQs和FIQs);·CPU ;必须 ;SVC ;模式; ;3. ;Cache ;和 ;MMU ;设置:·MMU ;必须关闭;·指令 ;Cache ;可以打开也可以关闭;·数据 ;Cache ;必须关闭; ;如果用 ;C ;语言可以像下列示例代码这样来内核: ;void ;(*theKernel)( ;zero, ; ;arch, ;u32 ;params_addr)= ;(void ;(*)(, ;, ;u32))KERNEL_RAM_BASE;……theKernel(0, ;ARCH_NUMBER, ;(u32) ;kernel_params_start);注意theKernel应该永远不返回如果这个返回则说明出错--------------------------------------------------------------------------------由 ;lefthand05 ;在 ;05-08-2004 ;16:05 ;发表: ;嵌入式BootLoader技术内幕(三)四、 ;关于串口终端 ;在 ;boot ;loader ;设计与实现中没有什么能够比从串口终端正确地收到打印信息能 更令人激动了此外向串口终端打印信息也是个非常重要而又有效调试手段但是我们经常会碰到串口终端显示乱码或根本没有显示问题造成这个问题主要有两种原 因:(1) ;boot ;loader ;对串口化设置不正确(2) ;运行在 ;host ;端终端仿真对串口设置不正确这包括:波特率、奇偶校验、数据位和停止位等方面设置 ;此外有时也会碰到这样问题那就是:在 ;boot ;loader ;运行过程中我们可以正确地 向串口终端输出信息但当 ;boot ;loader ;启动内核后却无法看到内核启动输出信息对 这问题原因可以从以下几个方面来考虑: ;(1) ;首先请确认你内核在编译时配置了对串口终端支持并配置了正确串口驱动程序 ;(2) ;你 ;boot ;loader ;对串口化设置可能会和内核对串口化设置不致此外对于诸如 ;s3c44b0x ;这样 ;CPUCPU ;时钟频率设置也会影响串口因此如果 ;boot ;loader ;和内核对其 ;CPU ;时钟频率设置不致也会使串口终端无法正确显示信息(3) ;最后还要确认 ;boot ;loader ;所用内核基地址必须和内核映像在编译时所用运行基地址致尤其是对于 ;uClinux ;而言假设你内核映像在编译时用基地址是 ;0xc0 008000但你 ;boot ;loader ;却将它加载到 ;0xc0010000 ;处去执行那么内核映像当然不 能正确地执行了 ;五、 ;结束语 ;Boot ;Loader ;设计与实现是个非常复杂过程如果不能从串口收到那激动人心 ;"uncompressing ;linux.................. ;done, ;booting ;the ;kernel……"2008-12-12 16:00:14疯狂代码 /。
嵌入式系统的BootLoader3.1 BootLoader概述一个嵌入式Linux系统从软件的角度看通常分为4个层次:引导加载程序、Linux内核、文件系统、用户应用程序。
引导加载程序是系统加电后运行的第一段代码。
大家熟悉的PC中的引导程序一般由BIOS和位于MBR的操作系统BootLoader(例如LILO或者GRUB)一起组成。
然而在嵌入式系统中通常没有像BIOS那样的固件程序,因此整个系统的加载启动任务就完全由BootLoader来完成。
在嵌入式Linux中,引导加载程序即等效为BootLoader。
简单地说,BootLoader就是在操作系统内核运行前执行的一段小程序。
通过这段小程序,我们可以初始化必要的硬件设备,创建内核需要的一些信息并将这些信息通过相关机制传递给内核,从而将系统的软硬件环境带到一个合适的状态,最终调用操作系统内核,真正起到引导和加载内核的作用。
BootLoader是依赖于硬件实现的,特别是在嵌入式系统中。
不同体系结构需求的BootLoader是不同的,除了体系结构,BootLoader还依赖于具体的嵌入式板级设备的配置。
也就是说,对于两块不同的嵌入式板而言,即使它们基于相同的CPU构建,运行在其中一块电路板上的BootLoader,未必能够运行在另一块电路开发板上。
Bootloader的启动过程可以是单阶段的,也可以是多阶段的。
大多数单阶段的BootLoader应用于简单的系统,比如没有操作系统的系统。
通常多阶段的Bo otLoader能提供更为复杂的功能以及更好的可移植性。
从固态存储设备上启动的BootLoader大多数是两阶段的启动过程,也就是启动过程可以分为stage 1和stage 2两部分。
依赖于CPU体系结构的代码,比如设备初始化代码等,通常都放在stage1中,而且通常都用汇编语言来实现,以达到短小精悍的目的。
而stage2则通常用C语言来实现,这样可以实现更复杂的功能,而且代码会具有更好的可读性和可移植性。
大多数BootLoader都包含两种不同的操作模式:启动加载(Boot loading)模式和下载(Down loading)模式,这种区别仅对于开发人员才有意义。
但从最终用户的角度看,BootLoader的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。
(1)启动加载模式:这种模式也称为自主(Autonomous)模式,即BootLoa der从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程没有用户的介入。
这种模式是BootLoader的正常工作模式。
因此在嵌入式产品发布的时候,BootLoader显然必须工作在这种模式下。
(2)下载模式:在这种模式下,目标机上的BootLoader将通过串口连接或网络连接等通信手段从主机上下载文件,比如下载应用程序、数据文件、内核映像等。
从主机下载的文件通常首先被BootLoader保存到目标机的RAM中然后再被BootLoader写到目标机上的固态存储设备中,BootLoader的这种模式通常在系统更新时使用。
工作于这种模式下的BootLoader通常都会向它的终端用户提供一个简单的命令行接口,比如U-Boot、Blob、VIVI等。
3.2 常用的嵌入式Linux BootLoader从上一节的内容可以了解到BootLoader是嵌入式系统中非常重要的一部分,也是系统运行工作的必要组成部分。
在嵌入式系统中常见的BootLoader有以下几种。
3.2.1 U-BootU-Boot是德国DENX小组开发的用于多种嵌入式CPU的BootLoader程序,它可以运行在基于PowerPC、ARM、MIPS等多种嵌入式开发板上。
从http://u-boo /或ftp://ftp.denx. de/pub/u-boot/站点都可以下载U-Bo ot的源代码,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(Real Time Clock,实时时钟)驱动程序;● tools用于创建U-Boot S-RECORD和BIN镜像文件的工具。
3.2.2 VIVIVIVI是由韩国MIZI公司开发的专门用于ARM产品线的一种BootLoader。
因为VIVI 目前只支持使用串口和主机通信,所以必须使用一条串口电缆来连接目标板和主机。
VIVI的源代码下载地址为:/developer/s3c 2410x/download/vivi.html,VIVI一般有如下作用。
(1)把内核(kernel)从Flash复制到RAM,然后启动它;(2)初始化硬件;(3)下载程序并写入Flash;(4)检测目标板。
vivi.tar.bz2源代码包解压后的目录结构如下所示:# tree –L 1.|-- COPYING|-- CVS|-- Documentation|-- Makefile|-- Rules.make|-- arch|-- drivers|-- include|-- init|-- lib|-- scripts|-- test`-- util10 directories, 3 files其中VIVI主要目录介绍如下。
● CVS存放CVS工具相关的文件;● Docu mentation 存放一些使用VIVI的帮助文档;● arch存放一些平台相关的代码文件;● drivers存放VIVI相关的驱动代码;● include存放所有VIVI源码的头文件;● init存放VIVI初始化代码;● lib存放VIVI实现的库函数文件;● scripts存放VIVI脚本配置文件;● test存放一些测试代码文件;● util存放一些NAND Flash烧写image相关的工具实现代码。
3.2.3 BlobBlob是Boot Loader Object的缩写,是一款功能强大的BootLoader。
其源码在http://sourceforge. net/projects/blob上可以获取。
Blob最初是由Ja n-Derk Bakker和Erik Mouw两人为一块名为LART(Linux Advanced Radio Te rminal)的开发板写的,该板使用的处理器是StrongARM SA-1100,现在Blob 已经被成功地移植到许多基于ARM的CPU上。
3.2.4 RedBootRedBoot是一个专门为嵌入式系统定制的引导启动工具,最初由Redhat开发,它是基于eCos(Embedded Configurable Operating System)的硬件抽象层,同时它继承了eCos的高可靠性、简洁性、可配置性和可移植性等特点。
Re dBoot集Bootloader、调试、Flash烧写于一体,支持串口、网络下载,执行嵌入式应用程序。
既可以用在产品的开发阶段(调试功能),也可以用在最终的产品上(Flash更新、网络启动)。
RedBoot支持下载和调试应用程序,开发板可以通过BOOTP/DHCP协议动态配置IP地址,支持跨网段访问。
用户可以通过tft p协议下载应用程序和image,或者通过串口用x-modem/y-modem下载。
RedBoo t支持用GDB(the GNU debugger)通过串口或者网卡调试嵌入式程序,可对gc c编译的程序进行源代码级的调试。
相比于简易jtag调试器,它可靠、高速(C PU的cache打开后,通过网卡tftp下载能达到1Mbps,GDB下载的速度能达到2 Mbps)、稳定,用户可通过串口或网卡,以命令行的形式管理Flash上的image,下载image到Flash。
动态配置RedBoot启动的各种参数、启动脚本,上电后R edBoot可自动从Flash或tftp服务器上下载应用程序执行。
在http://source /redboot站点可以下载RedBoot源码,同时可以了解更多的关于RedB oot的详细信息,它在嵌入式系统应用中非常广泛。
3.2.5 ARMbootARMboot是一个以ARM或StrongARM 为内核CPU的嵌入式系统的BootLoade r固件程序,该软件的主要目标是使新的平台更容易被移植并且尽可能地发挥其强大性能。
它只基于ARM固件,但是它支持多种类型的启动,比如Flash,网络下载通过bootp、dhcp、tftp等。
它也是开源项目,可以从http://www.source /projects/armboot网站获得最新的ARMboot源码和详细资料,它在A RM处理器方面应用非常广泛。
3.2.6 DIYDIY(Do It Yourself),即自己制作。
以上U-Boot、VIVI、Blob、RedBoo t和ARMboot等成熟工具移植起来简单快捷,但同时它们都存在着一定的局限性,首先是因为它们是面向大部分硬件的工具,所以说在功能上要满足大部分硬件的需求,但一般情况下我们只需要与特定的开发板相关的实现代码,其他型号开发板的实现代码对它来说是没有用的,所以通常它们的代码量较大。
其次它们在使用上不够灵活,比如在这些工具上添加自己的特有功能相对比较困难,因为必须熟悉该代码的组织关系,以及了解它的配置编译等文件。
用DIY的方式自己编写针对目标板的BootLoader不但代码量短小,同时灵活性很大,最重要的是将来容易维护。
所以在实际嵌入式产品开发时大都选择DIY的方式编写BootLoader。
3.3 基于S3C2410开发板的BootLoader实现本节将以实例讲述基于S3C2410开发板的BootLoader的具体实现,主要分两个方面进行介绍,一是介绍基于U-Boot的移植,二是介绍DIY方式开发Boot Loader。