第七章BootLoader实例剖析.docx
《第七章BootLoader实例剖析.docx》由会员分享,可在线阅读,更多相关《第七章BootLoader实例剖析.docx(16页珍藏版)》请在冰点文库上搜索。
![第七章BootLoader实例剖析.docx](https://file1.bingdoc.com/fileroot1/2023-5/18/e908bb58-c0eb-4f4f-9799-c8b036d9df3e/e908bb58-c0eb-4f4f-9799-c8b036d9df3e1.gif)
第七章BootLoader实例剖析
第七章BootLoader实例剖析
7.1BootLoader概述
BootLoader:
引导加载程序,就是在操作系统内核运行之前运行的一段小程序。
通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。
BootLoader包括固化在固件(firmware)中的boot代码(可选)和外部的BootLoader两大部分。
大多数BootLoader都包含两种不同的操作模式:
"启动加载"模式和"下载"模式,这种区别仅对于开发人员才有意义。
但从最终用户的角度看,BootLoader的作用就是用来加载操作系统,而并不存在所谓的启动加载模式与下载工作模式的区别。
启动加载(Bootloading)模式:
这种模式也称为"自主"(Autonomous)模式。
也即BootLoader从目标机上的某个固态存储设备上将操作系统加载到RAM中运行,整个过程并没有用户的介入。
这种模式是BootLoader的正常工作模式,因此在嵌入式产品发布的时侯,BootLoader显然必须工作在这种模式下。
下载(Downloading)模式:
在这种模式下,目标机上的BootLoader将通过串口连接或网络连接等通信手段从主机(Host)下载文件,比如:
下载内核映像和根文件系统映像等。
从主机下载的文件通常首先被BootLoader保存到目标机的RAM中,然后再被BootLoader写到目标机上的FLASH类固态存储设备中。
BootLoader的这种模式通常在第一次安装内核与根文件系统时被使用;此外,以后的系统更新也会使用BootLoader的这种工作模式。
工作于这种模式下的BootLoader通常都会向它的终端用户提供一个简单的命令行接口。
7.2ARM7教学平台BIOS剖析
7.2.1简介
ARM7教学平台BIOS就是FS44B0Xbios--BIOSFORFS44B0X,是优龙公司专门为FS44B0X开发板提供的。
作为系统启动的引导模块,FS44B0Xbios只支持三星公司的S3C44B0X(ARM7)处理器,不支持多种处理器结构,同时功能结构简单。
7.2.2结构功能分析
FS44B0Xbios因为功能简单,而且只针对一种处理器,所以结构也十分简单。
源码包里只有相应的*.c、*.s源文件,只有一个文件夹是存放头文件的。
没有分层和有关体系等复杂的结构。
现就源文件作用说明一下:
39VF160.C提供对FLASH39VF160的驱动,包括设备ID、擦除、编程、读等操作。
ARP.C提供对简单TCP/IP协议中间层的支持。
BOOT.S中断向量表,S3C44B0X是不可以remap的,为了运行有中断的程序,我们要把中断向量表烧写到flash里的零地址处。
CONSOLE.C提供对S3C44B0X串口的驱动,包括串口的读写、设置等。
CTEL_SET.C提供对S3C44B0X上的RTC的驱动,包括RTC的读写、设置等。
ETH.C提供对RTL8019网卡的驱动。
ICMP.C提供对简单TCP/IP协议中间层的支持。
IP.C提供对简单TCP/IP协议中间层的支持。
MAC.C提供对RTL8019网卡MAC层的驱动。
MAIN.C主函数,在此调用各种驱动支持,完成FS44B0Xbios的功能。
SKBUFF.C对收发缓冲区进行操作,给TCP/IP协议提供服务。
SYSINIT.S对S3C44B0X进行初始化,完成处理器的相关寄存器的配置工作。
TFTP.C提供tftp协议通信功能,供TCP/IP使用。
TFTPMAIN.C由上层应用程序调用,启动tftp通信功能,供下载文件、内核使用。
TFTPPUT.C提供tftp协议通信功能,供TFTP.C使用。
UDP.C提供对简单TCP/IP协议中间层的支持。
UTILS.C提供一些常用函数,如内存拷贝、设置、字符串比较等功能。
VECTOR.S整个程序的入口模块
根据上面的分析,可以看出FS44B0Xbios的功能十分简单,只提供了串口通信、网口通信、FLASH操作、实时时钟。
下面列出FS44B0Xbios提供的命令:
{"help","showhelp",Help},
{"?
","=help",Help},
{"date","showorsetcurrentdate",GetDate},
{"time","showorsetcurrenttime",GetTime},
{"setweek","setweekday",SetWeek},
{"clock","showsystemrunningclock",SysClock},
{"setmclk","setsystemrunningclock",ChgSysMclk},
{"setbaud","setbaudrate",ChgBaudRate},
{"load","loadfiletomemory",LoadFile2Mem},
{"comload","loadfilefromserialport",LoadFromUart},
{"prog","programflash",ProgFlash},
{"boot","bootfromflash",BootLoader},
{"ap","autoloadimageflieandprogramflash",AutoProgFlash},
{"copy","copyflashfromsrctodstaddress",CopyFlash},
{"ipcfg","showorsetIPaddress",SetIPAddr},
{"run","runfromram",RunProgram},
{"move","movedatafromflashtoram",MoveFlashToRam},
7.2.3移植
FS44B0Xbios是优龙公司专门为他们的FS44B0X开发板提供的。
它只持三星公司的S3C44B0X(ARM7)处理器,不支持多种处理器结构,因此移植只能在具有相同处理器的开发板上进行。
根据开发板上的硬件配置不同,修改相应的硬件驱动程序。
根据上面功能分析,FS44B0Xbios现在只对FLASH39VF160、RTL8019网卡、S3C44B0X串口、S3C44B0X上的RTC提供驱动支持,RAM配置为8M的SDRAM。
需要修改的地方:
(1)如果你的开发板使用其它型号的FLASH,可根据文件39VF160.C和39VF160.H进行移植,注意要修改MAIN.C里面FLASH的大小,现大小为#define__ROM_SIZE0x200000。
(2)如果你的开发板使用不同的RAM,就要修改SYSINIT.S里的存储器配置参数。
此BIOS的运行地址为0XC7C0000,可在ADS中修改。
7.3U-Boot移植过程剖析
7.3.1简介
U-Boot是DasU-Boot的简称,它的前身是PPCBOOT,PPCBOOT自2.0版本后就改名为
U-BOOT,由denx软件中心依照GPL发布的公共软件,作为系统启动的引导装载模块,U-Boot支持多种处理器架构,如:
PowerPC(MPC5xx,MPC8xx,MPC82xx,MPC7xx,MPC74xx,4xx),
ARM(ARM7,ARM9,StrongARM,Xscale),MIPS(4Kc,5Kc),x86等。
U-Boot目前的最高版本
是U-Boot-1.1.2,大家可以到上查看
U-Boot的最新信息和下载。
7.3.2结构分析
U-Boot的功能非常强大,已经相当于一个小的OS,因此里面的结构比较复杂,由于采用分层结构,它里面的体系结构还是十分清晰的。
现在就源码包下面的文件夹作简单的分析,不涉及下一级的文件夹。
分析采用的U-Boot-1.1.1的版本,其结构分析如下:
board:
包含多种目标系统,主要是和目标系统板相关的代码定义,例如我所用到
的文件board/snds100/smdk4110.c中有关于处理器的I/O端口定义等操作,还有文件board/snds100/flash.c,关于目标系统板上FLASH的操作。
common:
该目录下主要包含与处理器无关的功能,例如U-Boot的命令处理,环境
变量的设置等
CPU:
与CPU有关的功能,例如:
cpu/s3c44b0/serial.c是s3c44b0自带串口的驱动,
cpu/mpc8260/ether_fcc.c是FCC网口的驱动等
disk:
主要是磁盘驱动处理的代码
doc:
主要是一些readme文档,用处不是太大
driver:
主要是一些设备驱动,如rtl8139.c是8139网卡的驱动等
dtt:
针对温度设备的驱动,如ds1621.c是ds1621温度芯片的驱动等
examples:
主要是一些应用例子,如hello_world.c,timer.c等
fs:
文件系统的支持
include:
U-Boot头文件,需要修改的文件如include/configs/Snds100.h等
lib_generic:
公共的库目录,包含CRC校验,压缩,打印显示等功能
lib_ppc:
和PowerPC系列有关的功能,如lib_ppc/board.c文件中的初始化功能
lib_arm:
和ARM系列有关的功能,如lib_arm/board.c文件中的初始化功能
net:
U-Boot对网络协议的支持,主要支持bootp/rarp和tftp协议
post:
目标系统板上电复位自检功能
rtc:
硬件实时时钟的驱动
tools:
用来生成U-Boot镜像的一些工具
7.3.3功能分析
U-Boot的功能很强大,除了完成基本的系统启动和下载功能外,还可以完成很多其他的功能,这一点大家可以通过在U-Boot的命令行中输入“help”或者“?
”来得到:
?
-aliasfor'help'
askenv-getenvironmentvariablesfromstdin
autoscr-runscriptfrommemory
base-printorsetaddressoffset
bdinfo-printBoardInfostructure
boot-bootdefault,i.e.,run'bootcmd'
bootd-bootdefault,i.e.,run'bootcmd'
bootm-bootapplicationimagefrommemory
bootp-bootimagevianetworkusingBootP/TFTPprotocol
brginfo-printBaudRateGenerator(BRG)registers
carinfo-printClocksandResetregisters
chpart-changeactivepartition
cmp-memorycompare
coninfo-printconsoledevicesandinformations
cp-memorycopy
crc32-checksumcalculation
dcache-enableordisabledatacache
dhcp-invokeDHCPclienttoobtainIP/bootparams
dmainfo-printSDMA/IDMAregisters
echo-echoargstoconsole
erase-eraseFLASHmemory
fccinfo-printFCCregisters
flinfo-printFLASHmemoryinformation
fsinfo-printinformationaboutfilesystems
fsload-loadbinaryfilefromafilesystemimage
go-startapplicationataddress'addr'
help-printonlinehelp
i2cinfo-printI2Cregisters
icache-enableordisableinstructioncache
icinfo-printInterruptControllerregisters
icrc32-checksumcalculation
iloop-infinitelooponaddressrange
imd-i2cmemorydisplay
iminfo-printheaderinformationforapplicationimage
imls-listallimagesfoundinflash
imm-i2cmemorymodify(auto-incrementing)
imw-memorywrite(fill)
in-readdatafromanIOport
inm-memorymodify(constantaddress)
iopinfo-printI/OPortregisters
iopset-setI/OPortregisters
iprobe-probetodiscovervalidI2Cchipaddresses
irqinfo-printinformationaboutIRQs
isdram-printSDRAMconfigurationinformation
loadb-loadbinaryfileoverserialline(kermitmode)
loads-loadS-Recordfileoverserialline
loop-infinitelooponaddressrange
ls-listfilesinadirectory(default/)
mccinfo-printMCCregisters
md-memorydisplay
memcinfo-printMemoryControllerregisters
mii-MIIutilitycommands
mm-memorymodify(auto-incrementing)
mtest-simpleRAMtest
muxinfo-printCPMMultiplexingregisters
mw-memorywrite(fill)
nm-memorymodify(constantaddress)
out-writedatumtoIOport
ping-sendICMPECHO_REQUESTtonetworkhost
printenv-printenvironmentvariables
protect-enableordisableFLASHwriteprotection
rarpboot-bootimagevianetworkusingRARP/TFTPprotocol
reset-PerformRESEToftheCPU
run-runcommandsinanenvironmentvariable
saveenv-saveenvironmentvariablestopersistentstorage
saves-saveS-Recordfileoverserialline
sccinfo-printSCCregisters
setenv-setenvironmentvariables
siinfo-printSerialInterface(SI)registers
sitinfo-printSystemIntegrationTimers(SIT)registers
siuinfo-printSystemInterfaceUnit(SIU)registers
sleep-delayexecutionforsometime
smcinfo-printSMCregisters
spiinfo-printSerialPeripheralInterface(SPI)registers
tftpboot-bootimagevianetworkusingTFTPprotocol
version-printmonitorversion
在命令列表里面的这些命令,有一些并没有完成,所以只是提供一个接口,如果用户需
要,可以自己编写命令代码来实现它的功能。
在这里,我介绍几个常用的功能:
printenv:
主要用于打印环境变量的值
=>printenv打印所有环境变量的值
=>printenvname…打印某一个环境变量的值
setenv:
设置环境变量的值
=>setenvnamevalue将环境变量“name”的值设置为“value”
md:
用于显示存储器中某段地址的值
=>md0x06000000显示我的目标系统中ApplicationFlash中的值
tftpboot:
用于通过TFTP从主机上下载内核镜像文件
=>tftpboot0x100000pImage从主机下载pImage文件放到地址0x100000处
bootm:
从某一地址启动应用镜像
=>bootm0x100000从0x100000处开始运行镜像
boot:
运行环境变量bootcmd中的命令
=>printenvbootcmd
=>bootcmd=tftpboot0x100000pImage;bootm可以有多条命令,用分号隔开
=>boot首先运行“tftpboot0x100000pImage”,然后运行“bootm”
help[command…]:
显示某一命令的用法
=>helpgo
goaddr[arg...]
-startapplicationataddress'addr'
passing'arg'asarguments
7.3.4移植
7.3.4.1U-Boot代码移植
前面分析,U-Boot支持多种处理器架构和目标系统板架构,如果你的开发板和处理器在U-Boot里面都有,那么直接使用即可。
如果没有完全相同的,U-Boot里面包含了很多种目标系统板的类型,为了减小移植的工作量,应该选择一种和自己目标板相近的板类型,这里使用优龙提供的基于S3C44B0处理器的开发板作为例子,开发板配置如下:
CPU:
S3C44b0
NORFLASH:
8MBit,AMDAm29LV800BT
SDRAM:
16M,连接在CPU的NGCS6和NGCS7上
RTL8019(10/100M)网卡
在U-Boot里面的目标系统板smdk4110也是使用S3C44B0处理器,AMD的Am29LV160BB,所以选择SMDK4110作为移植参考目标板。
下面我们根据自己的目标系统板配置修改U-Boot包中的代码文件,进行U-Boot的移植。
修改目标系统FLASH驱动文件./board/smdk4110/flash.c
(1)修改flash的初始化
smdk4110使用AMD的Am29LV160BB,我们使用AMD的Am29LV800BT
flash_info[i].flash_id=
(AMD_MANUFACT&FLASH_VENDMASK)|
(AMD_ID_LV160B&FLASH_TYPEMASK);
改为flash_info[i].flash_id=
(AMD_MANUFACT&FLASH_VENDMASK)|
(AMD_ID_LV800T&FLASH_TYPEMASK);
两个flash的扇区结构不一样
for(j=0;j{
if(j<=3)
{
/*1stoneis16KB*/
if(j==0)
{
flash_info[i].start[j]=flashbase+0;
}
/*2ndand3rdareboth8KB*/
if((j==1)||(j==2))
{
flash_info[i].start[j]=flashbase+0x4000+(j-1)*0x2000;
}
/*4th32KB*/
if(j==3)
{
flash_info[i].start[j]=flashbase+0x8000;
}
}
else
{
flash_info[i].start[j]=flashbase+(j-3)*MAIN_SECT_SIZE;
}
}
改为
for(j=0;j{
if(j>15)
{
/*1stoneis16KB*/
if(j==16)
{
flash_info[i].start[j]=flashbase+(j-1)*MAIN_SECT_SIZE+0x8000;
}
/*2ndand3rdareboth8KB*/
if(j==17)
{
flash_info[i].start[j]=flashbase+(j-2)*MAIN_SECT_SIZE+0xa000;
}
/*4th32KB*/
if(j==18)
{
flash_info[i].start[j]=flashbase+(j-3)*MAIN_SECT_SIZE+0xc000;
}
}
else
{
flash_info[i].start[j]=flashbase+j*MAIN_SECT_SIZE;
}
}
(2)修改flash信息打印
case(AMD_ID_LV160B