ARM Linux启动过程分析

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

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

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

资源描述

ARMLinux启动过程分析赵楠本章学习目标:了解Linux结构及平台属性了解bootloader的相关知识熟悉并掌握启动过程摘要:从嵌入式系统到超级服务站,嵌入式Linux的可移植性使得我们可以在各种电子产品上看到它的身影。Linux是一个完整通用的Unix类分布式操作系统,它的结构紧凑、功能强、效率高、可移植性好且在Internet上可自由取用。对于不同体系结构的处理器来说Linux的启动过程也有所不同。本文以S3C2410ARM处理器为例,详细分析了系统上电后bootloader的执行流程及ARMLinux的启动过程。关键词:ARMLinuxbootloader启动过程Abstract:fromtheembeddedsystemtosuperservicestation,embeddedLinuxportabilityallowsustovariouselectronicproductsintheformofseeingit.LinuxisacompletegeneralUnixclassdistributedoperatingsystem,it'sstructurecompact,thefunctionisstrong,highefficiency,goodportabilityandintheInternetcanbefreetotake.FordifferentsystemstructureoftheprocessoristhestartoftheLinuxprocessisalsodifferent.BasedontheARMprocessorS3C2410asanexample,thepaperanalysessystemaftertheexecutionflowofelectricbootloaderandARMLinuxstart-upprocess.Keywords:ARMLinuxbootloaderstart-upprocess1.引言Linux最初是由瑞典赫尔辛基大学的学生LinusTorvalds在1991年开发出来的,之后在GNU的支持下,Linux获得了巨大的发展。虽然Linux在桌面PC机上的普及程度远不及微软的Windows操作系统,但它的发展速度之快、用户数量的日益增多,也是微软所不能轻视的。从嵌入式系统到超级服务站,Linux已获得广泛的应用。Linux是一个完整通用的Unix类分布式操作系统,它的结构紧凑、功能强、效率高、可移植性好且在Internet上可自由取用。Linux和Unix操作系统一样,操作系统的主要功能集中在内核,内核中包含进程管理、文件管理、设备管理和网络管理等部分。近些年来Linux在嵌入式领域的迅猛发展,更是给Linux注入了新的活力。2.1内核结构及平台相关性本文以分析的内核版本为2.6.9。当我们使用tar命令将linux-2.6.9.tar.bz2解开时,内核源代码被放到了linux-2.6.9/目录中。Linux内核各功能文件分别存放在linux-2.6.9/目录下的相应子目录中。Linux操作系统可以工作在多种不同硬件平台上,如80x86CPU系列(80386以上)、SUNsparc64和arm26等。为了让Linux体现优良的可移植性,Linux内核代码针对不同的硬件平台包含有对应的启动和初始化程序。这些程序处于arch/子目录中。用户完全可以根据自己的需要,从内核代码中各取所需,即时编译和更换系统内核,这也是Linux操作系统获得世界各地网络爱好者普遍支持的主要原因。鉴于绝大部分Linux应用于Intel80x86系列平台,所以本文也仅限对Linux在80x86系列平台的启动过程进行分析。本文所要探讨的启动程序位于arch/i386/boot/目录,系统的启动过程主要由bootsect.s、setup.s和head.s等3个汇编程序完成。其中bootloader是系统启动或复位以后执行的第一段代码,它主要用来初始化处理器及外设,然后调用Linux内核。Linux内核在完成系统的初始化之后需要挂载某个文件系统做为根文件系统(RootFilesystem)。根文件系统是Linux系统的核心组成部分,它可以做为Linux系统中文件和数据的存储区域,通常它还包括系统配置文件和运行应用软件所需要的库。应用程序可以说是嵌入式系统的“灵魂”,它所实现的功能通常就是设计该嵌入式系统所要达到的目标。如果没有应用程序的支持,任何硬件上设计精良的嵌入式系统都没有实用意义。从以上分析我们可以看出bootloader和Linux内核在嵌入式系统中的关系和作用。Bootloader在运行过程中虽然具有初始化系统和执行用户输入的命令等作用,但它最根本的功能就是为了启动Linux内核。在嵌入式系统开发的过程中,很大一部分精力都是花在bootloader和Linux内核的开发或移植上。如果能清楚的了解bootloader执行流程和Linux的启动过程,将有助于明确开发过程中所需的工作,从而加速嵌入式系统的开发过程。而这正是本文的所要研究的内容。3.Bootloader3.1Bootloader的概念和作用Bootloader是嵌入式系统的引导加载程序,它是系统上电后运行的第一段程序,其作用类似于PC机上的BIOS。在完成对系统的初始化任务之后,它会将非易失性存储器(通常是Flash或DOC等)中的Linux内核拷贝到RAM中去,然后跳转到内核的第一条指令处继续执行,从而启动Linux内核。由此可见,bootloader和Linux内核有着密不可分的联系,要想清楚的了解Linux内核的启动过程,我们必须先得认识bootloader的执行过程,这样才能对嵌入式系统的整个启过程有清晰的掌握。3.2Bootloader的执行过程不同的处理器上电或复位后执行的第一条指令地址并不相同,对于ARM处理器来说,该地址为0x00000000。对于一般的嵌入式系统,通常把Flash等非易失性存储器映射到这个地址处,而bootloader就位于该存储器的最前端,所以系统上电或复位后执行的第一段程序便是bootloader。而因为存储bootloader的存储器不同,bootloader的执行过程也并不相同,下面将具体分析。嵌入式系统中广泛采用的非易失性存储器通常是Flash,而Flash又分为NorFlash和NandFlash两种。它们之间的不同在于:NorFlash支持芯片内执行(XIP,eXecuteInPlace),这样代码可以在Flash上直接执行而不必拷贝到RAM中去执行。而NandFlash并不支持XIP,所以要想执行NandFlash上的代码,必须先将其拷贝到RAM中去,然后跳到RAM中去执行。实际应用中的bootloader根据所需功能的不同可以设计得很复杂,除完成基本的初始化系统和调用Linux内核等基本任务外,还可以执行很多用户输入的命令,比如设置Linux启动参数,给Flash分区等;也可以设计得很简单,只完成最基本的功能。但为了能达到启动Linux内核的目的,所有的bootloader都必须具备以下功能:1.初始化RAM因为Linux内核一般都会在RAM中运行,所以在调用Linux内核之前bootloader必须设置和初始化RAM,为调用Linux内核做好准备。初始化RAM的任务包括设置CPU的控制寄存器参数,以便能正常使用RAM以及检测RAM大小等。2.初始化串口串口在Linux的启动过程中有着非常重要的作用,它是Linux内核和用户交互的方式之一。Linux在启动过程中可以将信息通过串口输出,这样便可清楚的了解Linux的启动过程。虽然它并不是bootloader必须要完成的工作,但是通过串口输出信息是调试bootloader和Linux内核的强有力的工具,所以一般的bootloader都会在执行过程中初始化一个串口做为调试端口。3.检测处理器类型Bootloader在调用Linux内核前必须检测系统的处理器类型,并将其保存到某个常量中提供给Linux内核。Linux内核在启动过程中会根据该处理器类型调用相应的初始化程序。4.设置Linux启动参数Bootloader在执行过程中必须设置和初始化Linux的内核启动参数。目前传递启动参数主要采用两种方式:即通过structparam_struct和structtag(标记列表,taggedlist)两种结构传递。structparam_struct是一种比较老的参数传递方式,在2.4版本以前的内核中使用较多。从2.4版本以后Linux内核基本上采用标记列表的方式。但为了保持和以前版本的兼容性,它仍支持structparam_struct参数传递方式,只不过在内核启动过程中它将被转换成标记列表方式。标记列表方式是种比较新的参数传递方式,它必须以ATAG_CORE开始,并以ATAG_NONE结尾。中间可以根据需要加入其他列表。Linux内核在启动过程中会根据该启动参数进行相应的初始化工作。5.调用Linux内核映像Bootloader完成的最后一项工作便是调用Linux内核。如果Linux内核存放在Flash中,并且可直接在上面运行(这里的Flash指NorFlash),那么可直接跳转到内核中去执行。但由于在Flash中执行代码会有种种限制,而且速度也远不及RAM快,所以一般的嵌入式系统都是将Linux内核拷贝到RAM中,然后跳转到RAM中去执行。不论哪种情况,在跳到Linux内核执行之前CUP的寄存器必须满足以下条件:r0=0,r1=处理器类型,r2=标记列表在RAM中的地址。4.启动过程分析主要对bootsect.s、setup.s和head.s的工作机理做了较为详细的阐述。4.1bootsect模块分析bootsect.s代码是磁盘引导块程序,驻留在引导盘的引导扇区(0磁道,0磁头,第1扇区)。在PC加电ROMBIOS自检后,bootsect.s由BIOS自动加载到内存0x7C00处,然后将自己移到内存0x90000处。图2代码显示了bootsect.s的移动过程,其中#BOOTSEG为0x7C00,#INITSEG为0x9000。接下来,程序利用BIOS中断,INT0x13将setup模块从磁盘第2个扇区开始读到0x90200开始处,共读4个扇区。如果读出错误,则CF标志置位,程序复位驱动器,并重试。加载setup模块后,程序利用中断取磁盘驱动器参数,并将中断返回的每磁道扇区数保存在变量sectors中。然后程序将system模块加载到内存0x10000处。加载system模块期间,显示“Loadingsystem⋯”信息。为了提高加载速度,只要可能,就每次加载整条磁道的数据。从磁盘读取一次数据后,程序就比较当前所读段是否就是系统数据末端所处的段(#ENDSEG),如果不是,就跳转至ok1_read标号处继续读数据。最后,程序向软驱控制卡的驱动端口0x3f2写0,关闭软驱电动机。程序运行jmpi0,SETUPSEG,跳转到0x9020:0000处,CPU开始执行setup模块。图2bootsect移动代码4.2setup模块分析setup.s首先利用ROMBIOS中断读取机器系统参数(光标位置、扩展内存数、硬盘参数表等),并将这些数据保存到内存0x90000开始的位置(覆盖掉了bootsect程序)。这些参数将被内核中相关程序使用,例如设备驱动程序集中的ttyio.c。随后系统进入保护模式运行。CPU在实模式下运行,寻址一个内存地址主要是使用段基址和段内偏移值,段值被存放在段寄存器中;而在保护模式运行方式下,段寄存器中存放的是一个描述表中某项的索引值。索引值指定的描述符项中含有需要寻址的内存段的基地址、段的最大长度值和段的访问级别等信息。和实模式下的寻址相比,段寄存器值换成了段描述符项索引。接下来,程序关闭中断,将system模块整体向内存低端移动0x1000。每次移动0x8000字,循环执行8次。

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

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

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

×
保存成功