版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、1目錄TOC o 1-5 h z HYPERLINK l bookmark0 1vxworks映像類型1可加載的映像類型(vxwoks)1 HYPERLINK l bookmark6 vxworks映像啟動(dòng)順序1可加載型vxworks映像啟動(dòng)順序2 HYPERLINK l bookmark8 基于ROM的vxworks映像啟動(dòng)順序2 HYPERLINK l bookmark10 基于ROM駐留型vxworks映像啟動(dòng)順序3 HYPERLINK l bookmark12 BSP基礎(chǔ)知識(shí)4 HYPERLINK l bookmark14 BSP的定義4 HYPERLINK l bookmark16
2、BSP的功能4 HYPERLINK l bookmark18 BSP的組成4 HYPERLINK l bookmark20 BSP的啟動(dòng)5 HYPERLINK l bookmark22 4.1BSP的啟動(dòng)流程5 HYPERLINK l bookmark30 romlnit.s:romlnit()函數(shù)6 HYPERLINK l bookmark34 bootInit.c:romStart()函數(shù)14 HYPERLINK l bookmark40 bootConfig.c分析24 HYPERLINK l bookmark52 sysLib.s:sysInit()函數(shù)27 HYPERLINK l b
3、ookmark58 usrconfig.c:usrInit()函數(shù)28 HYPERLINK l bookmark60 usrconfig.c:usrRoot()函數(shù)29 HYPERLINK l bookmark66 總結(jié)32 1VxWorks及BSP啟動(dòng)流程與順序李守軒摘要:本文首先介紹vxworks映像的類型及各類型vxworks映像的啟動(dòng)順序;然后介紹BSP的啟動(dòng)流程與初始化順序。關(guān)鍵詞:vxworks映像;BSP啟動(dòng);代碼分析vxworks映像類型對(duì)于vxworks映像的啟動(dòng)情況,從根本上看,在初始化和裝載vxworks映像的過程中,處理器所執(zhí)行的步驟在邏輯上是一樣的。對(duì)于有些處理器可能
4、需要增加一些額外的步驟,而另一些處理器可能會(huì)省略掉某些步驟。當(dāng)構(gòu)造vxworks映像時(shí),根據(jù)需要可以構(gòu)造不同類型的映像,系統(tǒng)把這些映像劃分成以下三種類型。1.1可加載的映像類型(vxwoks)可加載型映像的執(zhí)行需要通過引導(dǎo)代碼把它裝載到目標(biāo)機(jī)RAM中,然后才開始執(zhí)行。而引導(dǎo)代碼分為兩種:(1)引導(dǎo)代碼固化在ROM或FLASH中;(2)引導(dǎo)代碼是一個(gè)獨(dú)立的vxworks應(yīng)用;引導(dǎo)代碼通常也是一種vxworks映像,也被稱為引導(dǎo)映像。它的作用就是把包含應(yīng)用的vxworks映像裝入到RAM中。引導(dǎo)映像可能在ROM/FLASH中執(zhí)行,也可能在RAM中執(zhí)行?;赗OM的映像類型(vxworks_Rom&
5、vxwoks_RomCompress)基于ROM的vxworks映像在執(zhí)行前首先把自己從ROM/FLASH中裝載到RAM中,這種類型的映像通常在啟動(dòng)階段較慢,但在執(zhí)行階段比ROM駐留型要快?;赗OM駐留映像類型(vxwoks_RomResident)ROM駐留型映像在啟動(dòng)時(shí)把數(shù)據(jù)段拷貝到目標(biāo)機(jī)RAM中,這種類型的映像在啟動(dòng)階段比較快,當(dāng)RAM空間比較小的時(shí)候通常使用它。在嵌入式應(yīng)用中通常會(huì)使用該類型的映像,然而,它在目標(biāo)機(jī)上執(zhí)行的速度要比其他類型要慢,原因是CPU訪問ROM比訪問RAM要慢。vxworks映像啟動(dòng)順序在目標(biāo)機(jī)加電啟動(dòng)時(shí)發(fā)生的順序啟動(dòng)事件是一個(gè)典型vxworks映像需要執(zhí)行的功
6、能。所有類型的vxworks映像在初始化階段啟動(dòng)順序是一樣的,處理器通過“jump”跳轉(zhuǎn)指令跳轉(zhuǎn)到ROM或Flash中引導(dǎo)帶代碼入口處,這段引導(dǎo)代碼所要執(zhí)行的操作包括:(1)關(guān)中斷;(2)初始化目標(biāo)機(jī)內(nèi)存;(3)裝載適當(dāng)?shù)膙xworks映像段;(4)跳轉(zhuǎn)到設(shè)置目標(biāo)機(jī)為靜止?fàn)顟B(tài)的代碼處。不同類型的vxworks映像啟動(dòng)順序略有不同,下面介紹vxworks映像的啟動(dòng)順序。可加載型vxworks映像啟動(dòng)順序ROM/Flash引導(dǎo)帶程序RAMROM引導(dǎo)程序、.Vxworks映像引導(dǎo)程序LOCAL_MEM_LOCAL_ADRSRAM_LOW_ADRSFREE_RAM_ADRSRAM_HIGH_ADRS圖
7、2.1可加載型vxworks映像啟動(dòng)順序可加載型vxworks映像引導(dǎo)的詳細(xì)過程如下:(1)數(shù)據(jù)段和代碼段的裝入。系統(tǒng)加電后執(zhí)行引導(dǎo)帶代碼,首先把引導(dǎo)代碼的代碼段和數(shù)據(jù)段從ROM或Flash里裝入RAM中。此時(shí)需要考慮下列情況:壓縮型引導(dǎo)代碼,這種類型的引導(dǎo)代碼在拷貝時(shí),需要對(duì)它進(jìn)行解壓縮;非壓縮型引導(dǎo)代碼,這種類型的引導(dǎo)代碼直接進(jìn)行拷貝即可;駐留型引導(dǎo)代碼,這種類型的引導(dǎo)代碼在拷貝時(shí),僅僅拷貝它的數(shù)據(jù)段。(2)vxworks映像的裝入。引導(dǎo)代碼執(zhí)行后,把vxworks映像裝入到RAM中,然后跳轉(zhuǎn)到vxworks映像裝入點(diǎn)。(3)系統(tǒng)初始化。執(zhí)行靜態(tài)鏈接在vxworks映像里的系統(tǒng)初始化代碼,
8、最終完成系統(tǒng)初始化操作。2.2基于ROM的vxworks映像啟動(dòng)順序ROM/Flash引導(dǎo)帶程序RAMLOCAL_MEM_LOCAL_ADRSRAM_LOW_ADRS基于ROM的VxWorks映像Vxworks映像FREE_RAM_ADRS圖2.2基于ROM的VxWorks映像啟動(dòng)順序基于ROM的vxworks映像啟動(dòng)詳細(xì)過程如下:VxWorks映像的裝入。系統(tǒng)加電后執(zhí)行引導(dǎo)帶代碼,首先把VxWorks映像的代碼段和數(shù)據(jù)段從ROM或Flash里裝入RAM中。此時(shí)需要考慮下列情況:壓縮型VxWorks映像,這種類型的VxWorks映像在拷貝時(shí),需要對(duì)它進(jìn)行解壓操作;非壓縮型VxWorks映像,這
9、種類型的VxWorks映像直接進(jìn)行拷貝操作;控制權(quán)轉(zhuǎn)移。VxWorks映像被裝入后,系統(tǒng)控制權(quán)轉(zhuǎn)移給RAM中的vxworks映像的初始化代碼。系統(tǒng)初始化。執(zhí)行靜態(tài)鏈接在vxworks映像里的系統(tǒng)初始化代碼,最終完成系統(tǒng)初始化操作。2.3基于ROM駐留型vxworks映像啟動(dòng)順序ROM/FlashRAMLOCAL_MEM_LOCAL_ADRSRAM_LOW_ADRSFREE_RAM_ADRS圖2.3基于ROM駐留型的VxWorks映像啟動(dòng)順序基于ROM駐留型的vxworks映像啟動(dòng)詳細(xì)過程如下:(1)VxWorks映像數(shù)據(jù)段的裝入。系統(tǒng)加電后執(zhí)行引導(dǎo)帶代碼,首先把VxWorks映像的數(shù)據(jù)段從RO
10、M或Flash里裝入RAM中。(2)控制權(quán)轉(zhuǎn)移。VxWorks映像數(shù)據(jù)段被裝入后,系統(tǒng)控制權(quán)轉(zhuǎn)移給ROM或Flash中的vxworks映像的初始化代碼。(3)系統(tǒng)初始化。執(zhí)行ROM或Flash中的靜態(tài)鏈接在vxworks映像里的系統(tǒng)初始化代碼,最終完成系統(tǒng)初始化操作。3BSP基礎(chǔ)知識(shí)BSP是VxWorks的一個(gè)重要組成部分,在目標(biāo)機(jī)加電后,首先執(zhí)行的代碼就是BSP,可以說VxWorks的啟動(dòng)流程就是BSP的啟動(dòng)流程。BSP的定義BSP(boardsupportpackage)即板級(jí)支持包,是介于底層硬件環(huán)境和VxWorks之間的一個(gè)軟件接口。BSP的功能BSP主要功能是系統(tǒng)加電后初始化目標(biāo)機(jī)硬
11、件、初始化操作系統(tǒng)及提供部分硬件的驅(qū)動(dòng)程序。具體如下。(1)初始化。CPU初始化。初始化CPU內(nèi)部寄存器。目標(biāo)機(jī)初始化。初始化控制芯片的寄存器,為整個(gè)軟件系統(tǒng)提供底層硬件環(huán)境的支持。系統(tǒng)資源初始化。為操作系統(tǒng)及系統(tǒng)的正常運(yùn)行做準(zhǔn)備,進(jìn)行資源初始化。(2)使VxWorks能夠訪問硬件驅(qū)動(dòng)程序。主要是指BSP包含部分必要的設(shè)備驅(qū)動(dòng)程序和相關(guān)設(shè)備的初始化操作。(3)在VxWorks系統(tǒng)中,集成了與硬件相關(guān)的軟件和部分硬件無關(guān)的軟件。BSP的組成開發(fā)板上電后首先跑的就是BSP的代碼,BSP主要由源文件、頭文件、派生文件Makefile文件組成BSP包含的具體文件請(qǐng)參考相關(guān)資料BSP在Tornado安裝
12、目錄中的位置如圖3.1中所示。hostTornado主機(jī)駐留工具Tornadoshare共享XDR代碼Target.Vxworks系統(tǒng)、BSPh(VxWorks頭文件)idllib(VxWorks庫(kù)文件)proj(tornado工程文件)src(VxWorks部分源代碼)unsupported(工具、驅(qū)動(dòng)程序)config(配置和構(gòu)造VxWorks的文件)一all(通用配置文件)bspname(針對(duì)不同CPU的班級(jí)支持包)圖3.1tornado目錄結(jié)構(gòu)4BSP的啟動(dòng)下面首先給出BSP的啟動(dòng)流程,然后對(duì)啟動(dòng)過程執(zhí)行的函數(shù)進(jìn)行具體分析,這是本文的重點(diǎn)和難點(diǎn),是建立在作者自己理解角度和深度基礎(chǔ)之上的
13、。4.1BSP的啟動(dòng)流程BSP的啟動(dòng)流程如圖3.2所示,從代碼執(zhí)行的角度描述了BSP的啟動(dòng)過程及啟動(dòng)過程中先后調(diào)用函數(shù)的功能。rominit.s:romInit初始化CPU,初始化RA控制器,檢測(cè)內(nèi)存及大小bootInit.c:romStart將ROM中的程序搬移到RAM中bootConfig.c:usrInit初始化Cache庫(kù)、VEC、系統(tǒng)硬件、wind內(nèi)核、啟動(dòng)usrRootJbootConfig.c:usrRoot初始化內(nèi)存、系統(tǒng)時(shí)鐘、I/O和文件系統(tǒng)、標(biāo)準(zhǔn)輸入輸出及出錯(cuò)、異常處理、log任務(wù)、ELF文件格式支持bootConfig.c:autoboot延時(shí)7秒,以默認(rèn)參數(shù)啟動(dòng)boot
14、Config.c:bootLoad加載VxWorks的ELF文件并轉(zhuǎn)向它進(jìn)行重啟bootConfig.c:bootCmdLoop啟動(dòng)命令行用于配置VxWorks啟動(dòng)參數(shù)usrConfig.c:sysInit初始化CPU及l(fā)2cache、stackJusrConfig.c:usrInit初始化cache、VEC、異常消息、硬件、wind內(nèi)核、啟動(dòng)usrRootusrConfig.c:usrRoot用戶可定義的系統(tǒng)根任務(wù)圖3.2BSP啟動(dòng)流程圖BSP的啟動(dòng)過程分析從BSP的啟動(dòng)流程圖中可以看出BSP啟動(dòng)過程中先后執(zhí)行的函數(shù),上面對(duì)這些函數(shù)進(jìn)行詳細(xì)描述。4.2.1romlnit.s:romlnit(
15、)函數(shù)romlnit()函數(shù)的功能romlnit()函數(shù)與包含在romlnit.s文件中,且用匯編語言編寫。它是系統(tǒng)加電后首先執(zhí)行的代碼,也是所有從ROM/FLASH啟動(dòng)的VxWorks映像的入口點(diǎn)。它執(zhí)行目標(biāo)機(jī)最小的初始化操作及調(diào)用romStart()函數(shù),其它硬件初始化操作推遲到sysHwInit()函數(shù)中進(jìn)行。romInit()函數(shù)必須包含下列功能:(1)屏蔽處理器中斷及處理器復(fù)位;(2)初始化內(nèi)存系統(tǒng);(3)初始化堆棧指針和其它寄存器,開始執(zhí)行romStart()函數(shù)及傳遞啟動(dòng)類型。冷啟動(dòng)與熱啟動(dòng)冷啟動(dòng)。所謂冷啟動(dòng)是指硬件環(huán)境通過加電啟動(dòng)。在romInit()函數(shù)中需要保存系統(tǒng)啟動(dòng)類型
16、,啟動(dòng)類型的宏定義為BOOT_COLD。熱啟動(dòng)。所謂熱啟動(dòng)是通過調(diào)用reboot()、Ctrl+X或異常中斷重新啟動(dòng)目標(biāo)機(jī)系統(tǒng)。實(shí)際上這些操作是把控制權(quán)傳遞給ROM中的監(jiān)控函數(shù)sysToMonitor(),這個(gè)函數(shù)包含在sysLib.c文件中,如執(zhí)行sysToMonitor(2),則系統(tǒng)執(zhí)行熱啟動(dòng)。代碼分析(1)X86硬件相關(guān)知識(shí)IDT是中斷描述表,是由門描述符組成的一個(gè)數(shù)組,每個(gè)門描述符對(duì)應(yīng)一個(gè)中斷/異常向量,其可以保存在內(nèi)存中的任何位置,CPU通過訪問IDTR寄存器獲取IDT的位置。IDTR寄存器的長(zhǎng)度為48位,其中包括保存IDT的32位線性地址和16位的大小。對(duì)于IDTR寄存器的操作包括
17、兩個(gè)指令:一個(gè)是LIDT,另一個(gè)是SIDT。LIDT用來將指定IDT所在線性地址和其長(zhǎng)度裝入LDTR寄存器;而SIDT則是將IDTR寄存器的內(nèi)容讀出。從實(shí)模式切換到保護(hù)模式之前,必須將基址和限長(zhǎng)的值用指令LGDT裝入GDTR,一旦系統(tǒng)切換到保護(hù)模式,則表所在的物理地址就不再改變,同時(shí)立即啟用全局描述表,IDT表的基址用指令I(lǐng)DTR。32位控制器CR0的0位為保護(hù)允許位PE(protectedenable),用于啟動(dòng)保護(hù)模式,pe=1,保護(hù)模式啟動(dòng);pe=0,實(shí)模式下運(yùn)行。實(shí)模式進(jìn)入保護(hù)模式的步驟:初始化段描述符一準(zhǔn)備并加載GDTR打開地址線A20設(shè)置CR0寄存器,進(jìn)入保護(hù)模式一跳轉(zhuǎn)32位代碼段
18、。A20地址線的激活請(qǐng)查閱相關(guān)資料。上述相關(guān)知識(shí)是作者在理解代碼過程中了解的,當(dāng)然與硬件相關(guān)的知識(shí)很多,詳細(xì)請(qǐng)查閱相關(guān)資料。(3)代碼分析從作者理解的角度給出了romInit()函數(shù)的流程圖,如圖4.1所示。具體的代碼分下如下:包含C的4個(gè)頭文件。vxWorks.h為系統(tǒng)頭文件sysLib.h為系統(tǒng)提供給BSP的頭文件config.h是BSP的頭文件Asm.h是系統(tǒng)頭號(hào)文件開始數(shù)據(jù)段。以下內(nèi)容出現(xiàn)在數(shù)據(jù)段里.globlcopyright_wind_river.longcopyright_wind_river/*thefirstin.data*/.globlromwait.globl_romIn
19、it.globl_sdata等等申明全局變量_romlnit和_sdata等冷啟動(dòng)熱啟動(dòng)圖4.1romlnit()函數(shù)流程圖定義一個(gè)以0結(jié)尾的字符串startofdata”。這個(gè)串出現(xiàn)在數(shù)據(jù)段的第一個(gè)無名變量之后.text.align16.text開始代碼段,以下內(nèi)容出現(xiàn)在代碼段里。.align16使對(duì)齊編譯器進(jìn)行填充,使得下一條指令出現(xiàn)在能被16整除的地址上。對(duì)齊可使CPU取指令快一點(diǎn)。進(jìn)入rominit處:Cli關(guān)中斷jmpcold跳轉(zhuǎn)到cold處。這是段內(nèi)相對(duì)跳轉(zhuǎn)。balign16在32-bit代碼前加這樣的前綴可以讓它變?yōu)?6-bit代碼;在16-bit代碼前可以變?yōu)?2-bit代碼進(jìn)
20、入romWarmHigh處:Cli關(guān)中斷movlSP_ARG1(%esp),%ebx把esp+SP_ARG1偏移處的值賦予ebx寄存器jmpwarm跳轉(zhuǎn)到warm處。這是段內(nèi)相對(duì)跳轉(zhuǎn).balign16在32-bit代碼前加這樣的前綴可以讓它變?yōu)?6-bit代碼;在16-bit代碼前可以變?yōu)?2-bit代碼進(jìn)入romWarmLow處:cli關(guān)中斷cld清方向標(biāo)志movl$RAM_LOW_ADRS,%esi/*把RAM_LOW_ADRS地址賦給esimovl$ROM_TEXT_ADRS,%edi/*把RAM_LOW_ADRS地址賦給edimovl$ROM_SIZE,%ecx/*把RAM_size地
21、址賦給ecxshrl$2,%ecx/*ecx右移兩位256字節(jié)變成64個(gè)雙字repmovsl循環(huán)執(zhí)行esi-edi真到ecx=0movlSP_ARG1(%esp),%ebx把esp+SP_ARG1偏移處的值賦予ebx寄存器jmpwarm/*jumptowarm*/.asciiCopyright1984-2002WindRiverSystems,Inc.balign16,0 x90cold:/cold處.byte0 x67,0 x66與blign16功能相同lidt%cs:(romldtr-romlnit)將中斷和量表加載到cs:(romldtr-romlnit)處.byte0 x67,0 x6
22、6與blign16功能相同lgdt%cs:(romGdtr-romlnit)將斷描述表加載到cs:(romGdtr-romlnit)處mov%cr0,%eax/*moveCR0toEAX*/.byte0 x66or$0 x00000001,%eax/*nextinsthas32bitoperand*/*setthePEbit*/mov%eax,%cr0/*moveEAXtoCR0*/以上代碼的作用是將控制寄存器crO的PE位置1jmpromInit1/*跳轉(zhuǎn)到rominit1處。Rominit1:進(jìn)入rominit1處.byte0 x66/*nextinsthas32bitoperand*/m
23、ov$0 x0010,%eax/*setdatasegment0 x10is3rdone*/mov%ax,%ds/*setDS*/mov%ax,%es/*setES*/mov%ax,%fs/*setFS*/mov%ax,%gs/*setGS*/mov%ax,%ss/*setSS*/.byte0 x66/*nextinsthas32bitoperand*/mov$ROM_STACK,%esp/*setlowermemstackpointer*/.byte0 x67,0 x66/*nextinsthas32bitoperand*/ljmp$0 x08,$ROM_TEXT_ADRS+romInit2
24、-romInit現(xiàn)在已進(jìn)入保護(hù)模式。然而各個(gè)段寄存器的值,以及它們的高速緩存寄存器中的值還是實(shí)模式下的。把DS,ES,FS,GS,SS寄存器設(shè)為0 x0010,即指向GDT的第2項(xiàng)(從0開始),DPL=0。它們都指向一個(gè)段。把堆棧指針esp設(shè)為ROM_STACK,由于CS還是以前的值,意味著目前代碼段的屬性還是16-bit代碼。所以使用指令前綴以執(zhí)行32-bit代碼。執(zhí)行一個(gè)遠(yuǎn)程段間跳轉(zhuǎn)修改CS。CS的新值為0 x08,即GDT的第1項(xiàng),DPL=0。修改CS時(shí)它的高速緩存寄存器也會(huì)自動(dòng)更新。romIDT(InterruptDescriptionTable),中斷描述符表,空的。romGdtr:
25、.word0 x0027.longROM_TEXT_ADRS+ROM_GDT/設(shè)置段描述表的大小及基地址balign16,0 x90romGdt:段描述表/*0(selector=0 x0000):Nulldescriptor*/.word0 x0000.word0 x0000.byte0 x00.byte0 x00.byte0 x00.byte0 x00/*1(selector=0 x0008):Codedescriptor*/.word0 xffff/*limit:xffff*/段界限低16位.word0 x0000/*base:xxxx0000*/基地址低16位.byte0 x00/*b
26、ase:xx00 xxxx*/基地址中間8位.byte0 x9a/段屬性.byte0 xcf/段屬性含段界限高4位.byte0 x00/*base:基地址高8位/*2(selector=0 x0010):Datadescriptor*/.word0 xffff/*limit:xffff*/.word0 x0000/*base:xxxx0000*/.byte0 x00/*base:xx00 xxxx*/.byte0 x92/*Datar/w,Present,DPL0*/.byte0 xcf/*limit:fxxxx,PageGra,32bit*/.byte0 x00/*base:00 xxxxx
27、x*/*3(selector=0 x0018):Codedescriptor,forthenestinginterrupt*/.word0 xffff/*limit:xffff*/.word0 x0000/*base:xxxx0000*/.byte0 x00/*base:xx00 xxxx*/.byte0 x9a/*Codee/r,Present,DPL0*/.byte0 xcf/*limit:fxxxx,PageGra,32bit*/.byte0 x00/*base:00 xxxxxx*/*4(selector=0 x0020):Codedescriptor,forthenestingint
28、errupt*/.word0 xffff/*limit:xffff*/.word0 x0000/*base:xxxx0000*/.byte0 x00/*base:xx00 xxxx*/.byte0 x9a/*Codee/r,Present,DPL0*/.byte0 xcf/*limit:fxxxx,PageGra,32bit*/.byte0 x00/*base:00 xxxxxx*/.balign16,0 x90romlnit2:進(jìn)入rominit2處cli關(guān)中斷movl$ROM_STACK,%esp設(shè)置esp成rom_stack0 x8000h#ifdefined(TGT_CPU)&defi
29、ned(SYMMETRIC_IO_MODE)movl$MP_N_CPU,%eaxlockincl(%eax)#endif定義TGT_CPU和SYMMETRIC_IO_MODE#ifdefINCLUDE_WINDML/*WindML+VesaBIOSinitialization*/Movl$VESA_BIOS_DATA_PREFIX,%ebx/*moveBIOSprefixaddrtoEBX*/movl$VESA_BIOS_KEY_1,(%ebx)/*storeBIOS*/addl$4,%ebx/*incrementEBX*/movlmovl*/$VESA_BIOS_KEY_2,(%ebx)/*
30、storeDATA*/*loadECXwithnBytestocopy$VESA_BIOS_DATA_SIZE,%ecxshrl$2,%ecx/*getnLongstocopy*/movl$0,%esi/*loadESIwithsourceaddr*/movl$VESA_BIOS_DATA_ADDRESS,%edi/*loadEDIwithdestaddr*/repmovsl/*copyBIOSdatatoVRAM*/#endif/*INCLUDE_WINDML*/*/定義INCLUDE_WINDML并初始化VesaBIOS#ifndefINCLUDE_IACSFLcallFUNC(romA2
31、0on)/*enableA20*/cmpl$0,%eax/*isA20enabled?*/jneromInitHlt/*no:jumpromInitHlt*/#endif定義INCLUDE_IACSFLwarm:/進(jìn)入warm處ARCH_REGS_INIT/*初始化DR0-7標(biāo)志位寄存器*/#if(CPU=PENTIUM)|(CPU=PENTIUM2)|(CPU=PENTIUM3)|(CPU=PENTIUM4)xorl%eax,%eax/*zeroEAX*/movl%eax,%cr4#endif如果是奔騰系列初將cr4清零movl$romGdtr,%eax加載前面的romGdt表subl$FU
32、NC(romInit),%eaxaddl$ROM_TEXT_ADRS,%eaxpushl%eaxcallFUNC(romLoadGdt)movl$STACK_ADRS,%esp/*initialisethestackpointer*/movl$ROM_TEXT_ADRS,%esi/*getsrcaddr(ROM_TEXT_ADRS)movl$romInit,%edi/*getdstaddr(romInit)*/cmpl%esi,%edi/*issrcanddstsame?*/jeromInit4如果rom_text_adrs和rominit處相同的話就跳轉(zhuǎn)到rominit4處執(zhí)行movl$FU
33、NC(end),%ecx/*getendaddr*/subl%edi,%ecx/*getnBytestocopy*/ shrl$2,%ecx/*getnLongstocopy*/cld/*clearthedirectionbit*/rep/*repeatnextinstECXtime*/movsl如果rom_text_adrs和rominit處不相同的話將rom_text_adrs處拷貝至(end-rominit)處romlnit4:進(jìn)入rominit4處xorl%ebp,%ebpebp清零pushl$0popfl/清標(biāo)志寄存器pushl%ebxebx進(jìn)棧movl$FUNC(romStart)
34、,%eax/*jumptoromStart*/call*%eax/跳轉(zhuǎn)到romStart處執(zhí)下一步。romInitHlt:pushl%eaxcallFUNC(romEaxShow)/調(diào)用romEaxShow顯示eax寄存器的內(nèi)容hltjmpromInitHlt死循環(huán),當(dāng)機(jī)/調(diào)用romwait等待/*向64h寄存器寫入dlh*/.balignl6,0 x90FUNC_LABEL(romA20on)/進(jìn)入romA20on處:打開a20以擴(kuò)大尋址范圍空間callFUNC(romWait)movl$0 xdl,%eaxoutb%al,$0 x64callFUNC(romWait)movl$0 xdf,
35、%eaxoutb%al,$0 x60callFUNC(romWait)movl$0 xff,%eaxoutb%al,$0 x64callFUNC(romWait)向64h寄存器寫入ffh*/調(diào)用romwait等待/*EnableA20*/向60h寄存器寫入dfh*/調(diào)用romwait等待movl$0 x000000,%eax/*Checkifitworked*/movl$0 xl00000,%edxpushl(%eax)pushl(%edx)movl$0 x0,(%eax)movl$0 x0,(%edx)movl$0 x0l234567,(%eax)l3cmpl$0 x01234567,(%e
36、dx)popl(%edx)popl(%eax)jneromA20on0以上代碼是檢查A20地址線是否打開,就是檢查000000h和100000是否相同,即當(dāng)超過20位時(shí)看看會(huì)不會(huì)和第0位時(shí)相同,如果不相同說明打開了A20地址線。否則沒打開。嘗試別一種方法打開/*anotherwaytoenableA20*/movl$0 x02,%eaxoutb%al,$0 x92/向92H寄存器寫入02xorl%ecx,%ecxecx清零romA20onl:接著上面向92H寄存器寫入02后inb$0 x92,%alandb$0 x02,%alloopzromA20onl/確保92H為02movl$0 x000
37、000,%eax/*Checkifitworked*/movl$0 xl00000,%edxpushl(%eax)pushl(%edx)movl$0 x0,(%eax)movl$0 x0,(%edx)movl$0 x0l234567,(%eax)cmpl$0 x0l234567,(%edx)popl(%edx)popl(%eax)jneromA20on0movl$0 xdeaddead,%eax/*error,cantenableA20*/ret以上代碼是檢查A20地址線是否打開,就是檢查000000h和l00000是否相同,即當(dāng)超過20位時(shí)看看會(huì)不會(huì)和第0位時(shí)相同,如果不相同說明打開了A20
38、地址線。否則沒打開。不再嘗試無法打開A20romA20on0:xorl%eax,%eaxret/成功打開A20同進(jìn)EAX清零.balignl6,0 x90FUNC_LABEL(romLoadGdt)movlSP_ARGl(%esp),%eaxlgdt(%eax)movw$0 x00l0,%ax/*aselector0 xl0is3rdone*/ movw%ax,%dsmovw%ax,%esmovw%ax,%fsmovw%ax,%gsmovw%ax,%ssret把DS,ES,FS,GS,SS寄存器設(shè)為0 x0010,即指向GDT的第2項(xiàng)(從0開始),DPL=O。它們都指向一個(gè)段。FUNC_LAB
39、EL(romWait)/等待狀態(tài)xorl%ecx,%ecxecx清零romWait0:movl$0 x64,%edx/*Checkifitisreadytowrite*/inb%dx,%alandb$2,%alloopnzromWait0/確保64h寄存器的值為02ret.balign16,0 x90同上一次FUNC_LABEL(romEaxShow)/顯示eax寄存器的內(nèi)容/*showEAXregisterinyourdisplaydeviceavailable*/retbootlnit.c:romStart()函數(shù)romStart()函數(shù)的功能romStart()函數(shù)包含在bootlnit
40、.c文件中,且用C語言編寫。它是系統(tǒng)最先執(zhí)行的第一個(gè)C語言程序,為ROM映像執(zhí)行必要的代碼重定位、解壓和RAM初始化操作。其具體操作如下:拷貝適當(dāng)?shù)腞OM映像段到RAM中;清理沒有被使用的那部分內(nèi)存(冷啟動(dòng)時(shí));執(zhí)行解壓操作(如果需要);調(diào)用預(yù)內(nèi)核的通用初始化程序usrInit()。romStart()函數(shù)相關(guān)知識(shí)(1)ROM的布局。如圖4.2所示。壓縮型映像區(qū)ROM_BASE_ADRS+ROMSIZEbinArrayEndbinArrayStart圖4.2ROM布局非壓縮型映像區(qū)ROM_TEXT_ADRSROM_BASE_ADRS從上圖中可以發(fā)現(xiàn)壓縮型映像和非壓縮型映像處于不同的ROM空間。
41、(2)RAM的布局。如圖4.3所示。從圖4.3中可以發(fā)現(xiàn)用戶保留區(qū)處于RAM空間的頂端和底部,映像重新定位區(qū)位于保留堆棧區(qū)的上面。sysPhyMemTop()SYS_MEM_TOP用戶保留區(qū)冷啟動(dòng)填充為0ROM型映像重新定位區(qū)RAM_DST_ADRS保留堆棧區(qū)冷啟動(dòng)填充為0用戶保留區(qū)SYS_MEM_BOTTOMLOCAL_MEM_LOCAL_ADRS圖4.3RAM布局3.代碼分析(1)代碼綜述bootrom有三種類型:ROM_RESIDENT、UMCOMPRESS和COMPRESS。第一種是一直運(yùn)行在rom中的映象,只把data段拷貝到ram里面;第二種是非壓縮方式的映象,data段和text
42、段都要拷貝到ram里面,并在ram里面運(yùn)行;第三種是壓縮方式的映象,生成的時(shí)候編譯器會(huì)把除掉romInit.s和bootInit.c之外的目標(biāo)文件壓縮并匯編成一個(gè)bootrom.Z.s,最后和romInit.o,bootInit.o,version.o進(jìn)行鏈接,生成bootrom映象。所以它也是要全部拷貝到ram中,且必須要進(jìn)行壓縮的工作。而這些工作基本上都是在bootInit.c中進(jìn)行的。bootInit.c里面主要就是romStart()這個(gè)函數(shù),讓我們來分析一下它。它的入口參數(shù)是startType,是一個(gè)啟動(dòng)類型標(biāo)志,如BOOT_CLEAR、BOOT_NORMAL等,這在后面清內(nèi)存時(shí)會(huì)用
43、到。函數(shù)一開始定義了一個(gè)函數(shù)指針變量absEntry,它最后指向的就是ursInit()或compressedEntry()函數(shù)。接下來就是對(duì)三種bootrom映象類型進(jìn)行不同的操作,下面我們以arm為例來分別說明。ROM_RESIDENT:它要拷貝的只是data段。直接調(diào)用“copyLongs(UINT*)(etext+4),(UINT*)RESIDENT_DATA,(UINT)edata-(UINT)RESIDENT_DATA)/sizeof(long)”來實(shí)現(xiàn)。這時(shí)系統(tǒng)是運(yùn)行在rom上的,鏈接器把所有的函數(shù)都定位在rom空間上,所以調(diào)用copyLongs時(shí)沒有計(jì)算偏移,而拷貝的目標(biāo)地址是
44、RESIDENT_DATA對(duì)于arm而言RESIDENT_DATA就是sdata,這是在romlnit.s中定義的。通過objdumparm這個(gè)工具可以看到sdata定位在RAM_HIGH_ADRS+0 x4這個(gè)位置上。而etext+4則是rom上data段的起始地址。這樣,完成data段的拷貝。然后如果startType為冷啟動(dòng),那么清零SYS_MEM_BOTTOM到棧底(RESIDENT_DATA-STACK_SE)以及data段結(jié)束之后(edata到SYS_MEM_TOP)的內(nèi)存空間。然后將函數(shù)開始定義的指針absEntry指向usrlnit(在rom中):absEntry=(FUNCP
45、TR)usrlnit;并帶上startType跳過去運(yùn)行:(absEntry)(startType),完成。UMCOMPRESS:一開始它將text段和data段都拷貝到ram中:(FUNCPTR)ROM_OFFSET(copyLongs)(ROM_TEXT_ADRS,(UINT)romInit,ROM_COPY_SIZE/sizeof(long)。這時(shí)的ROM_TEXT_ADRS就是代碼段在rom上的開始位置,而romInit則是由鏈接器定位到了RAM_HIGH_ADRS的地址上,所以這時(shí)的確是按我們常規(guī)的思路拷貝的。并且由于copyLongs函數(shù)是定位到ram空間的,所以要計(jì)算它在rom上
46、的偏移ROM_OFFSET(copyLongs)。然后象ROM_RESIDENT樣,它也要清零棧底(romInit-STACK_SAVE)以下和映象之上(SYS_MEM_TOP-(romInit+ROM_COPY_SIZE)的內(nèi)存空間。然后將函數(shù)開始定義的指針absEntry指向usrlnit(在ram中):absEntry=(FUNCPTR)usrInit;并帶上startType跳過去運(yùn)行:(absEntry)(startType),完成。COMPRESS:開始的時(shí)候把從ROM_TEXT_ADRS起始的長(zhǎng)度為romInit到binArrayStart的內(nèi)容拷貝到romInit位置上。注意,
47、由于romInit被鏈接器定位到RAM_LOW_ADRS的位置上,這時(shí)相當(dāng)于把romInit.o、bootInit.o和version.。的內(nèi)容拷貝到了RAM_LOW_ADRS上。然后和UMCOMPRESS一樣清零棧底(romInit-STACK_SAVE)以下的內(nèi)存空間,不同之處是它接下來清除binArrayStart之上(SYS_MEM_TOP-binArrayStart)的內(nèi)存空間:fillLongs(UINT*)binArrayStart,(UINT)SYS_MEM_TOP-(UINT)binArrayStart)/sizeof(long),0)。然后調(diào)用解壓程序inflate將在ro
48、m上的(binArrayEnd-binArrayStart)之間的內(nèi)容解壓到RAM_DST_ADRS(RAM_HIGH_ADRS)的位置上:binArrayStart(absUncompress)(UCHAR*)ROM_OFFSET(binArrayStart),(UCHAR*)RAM_DST_ADRS,&binArrayEnd-binArrayStart)。這樣,解完壓后函數(shù)compressedEntry()剛好就在RAM_DST_ADRS(RAM_HIGH_ADRS)的位置上,所以接下來將指針absEntry指向它:absEntry=(FUNCPTR)RAM_DST_ADRS。最后帶上st
49、artType跳過去運(yùn)行:(absEntry)(startType),完成。壓縮的ROMablelinage的啟動(dòng)標(biāo)準(zhǔn)的bootioni程序A(2)代碼分析代碼中針對(duì)不同類型的ROM程序有不同的copy類型,不同的CPU有不同的地址轉(zhuǎn)換,RAM清零與最后的入口函數(shù)也有所不同。具體的代碼分析如下:Bootinit.里面主要看romstart這個(gè)函數(shù)。實(shí)現(xiàn)把rom中的內(nèi)容拷貝到ram中去,同時(shí)把把ram其它未用的部分清零,對(duì)于壓縮的rom在必要時(shí)還要進(jìn)行解壓。這段代碼由前面的rominit.s跳轉(zhuǎn)到這來的。ROMANDRAMMEMORYLAYOUT,Examplememorylayoutfora1
50、-megabyteboard:0 x00100000=LOCAL_MEM_SIZE=sysMemTop()|RAM|0filled|1=(romInit+ROM_COPY_SIZE)orbinArrayStart|ROMimage|0 x00090000=RAM_HIGH_ADRS|STACK_SAVE|0 x00080000=0.5Megabytes|0filled|1|0 x00001000=RAM_ADRS&RAM_LOW_ADRS1|excvectors,bpanchor,excmsg,bootline|0 x00000000=LOCAL_MEM_LOCAL_ADRS|ROM|0 xf
51、f8xxxxx=binArrayStart|0 xff800008=ROM_TEXT_ADRS0 xff800000=ROM_BASE_ADRS在時(shí)入romstart之前先是定義了一些變量SYS_MEM_TOP,SYS_MEM_BOTTOM,BINARRAYEND_ROUNDOFF等等。再接下來就是聲明了一些系統(tǒng)函數(shù),再接下來又是定義了romstart相關(guān)的定義如:RESIDENT_DATA=RAM_DST_ADRS(mips)/定義體系結(jié)構(gòu)特殊信息=壓縮映象最終重定位的地址RESIDENT_DATA=wrs_kernel_data_startRAM_DST_ADRS=RAM_HIGH_ADR
52、S/壓縮映象最終重定位的地址=拷貝引導(dǎo)映象的入口地址ROM_TEXT_ADRS=(UINT)romInit)ROM_BASE_ADRS=(UINT)romInit)引導(dǎo)rom的入口地址ROM_COPY_SIZE=(ROM_SIZE-(ROM_TEXT_ADRS-ROM_BASE_ADRS)ROM_OFFSET(adr)=(UINT)adr-(UINT)romInit)+ROM_TEXT_ADRS)/rom-ram時(shí)涉及到計(jì)算偏移地址函數(shù)接著又聲明了三個(gè)函數(shù)拷貝rom-ram函數(shù):copyLongs()往ram填零函數(shù):fillLongs()比較函數(shù):checkLongs()voidromSta
53、rt(FASTintstartType/*啟動(dòng)類形*/它的入口參數(shù)是startType,是一個(gè)啟動(dòng)類型標(biāo)志,如BOOT_CLEAR、BOOTNORMAL等,這在后面清內(nèi)存時(shí)會(huì)用到。)#if(CPU_FAMILY=SPARC)|(CPU_FAMILY=MIPS)|(CPU_FAMILY=I80X86)|(CPU_FAMILY=PPC)|(CPU_FAMILY=ARM)volatile/*toforceabsoluteadressing*/注釋:volatile關(guān)鍵字的作用是使編譯器不對(duì)被指定的變量做優(yōu)化,這樣可以確保該變量每次被取到新的值。Volatile經(jīng)常用來修飾全局的或者靜態(tài)的或者在多任務(wù)
54、環(huán)境下允許被改變的變量。#endif/*(CPU_FAMILY=SPARC)*/FUNCPTRabsEntry;函數(shù)一開始定義了一個(gè)函數(shù)指針變量absEntry,它最后指向的就是usrlnit()或compressedEntry()函數(shù)#if(CPU_FAMILY=ARM)&(!defined(ROM_RESIDENT)&!defined(BOOTCODE_IN_RAM)VOIDFUNCPTRramfillLongs=fillLongs;/*forcecalltoRAM*/#definefillLongs(a,b,c)ramfillLongs(a,b,c)#endif/*(CPU_FAMILY
55、=ARM)*/#if(CPU_FAMILY=MC680X0)&!defined(ROM_RESIDENT)&!defined(BOOTCODE_IN_RAM)volatileVOIDFUNCPTRromcopyLongs=©Longs;/*forcecalltoROM*/#definecopyLongsromcopyLongs#endif/*(CPU_FAMILY=MC680X0)*/*CopyfromROMtoRAM,minusthecompressedimageifcompressedbootROMwhichreliesonbinArrayappearinglastinDATAse
56、gment.*/#ifdefROM_RESIDENT/*IfROMresidentcode,thencopyonlydatasegmentfromROMtoRAM,initializememoryandjumptousrInit.*/#if(CPU_FAMILY=SPARC)copyLongs(UINT*)(etext+8),(UINT*)RESIDENT_DATA,#else/*對(duì)于ROM_RESIDENT,則只拷貝數(shù)據(jù)段到ram。因?yàn)橄到y(tǒng)在ROM中運(yùn)行,所有函數(shù)被定位到ROM空間。所以copyLongs沒有計(jì)算偏移量。RESIDENT_DATA就是sdata,被LD定位到RAM_HIGH_
57、ADRS。又定義為wrs_kernel_data_start。etext則是ROM上的data起始位置。則直接拷貝ROM上的data數(shù)據(jù)到RAM上的RAM_HIGH_ADRS.*/copyLongs(UINT*)etext,(UINT*)RESIDENT_DATA/*RAM_HIGH_ADRS*/,#endif(UINT)wrs_kernel_data_end-(UINT)RESIDENT_DATA)/sizeof(long);#else/*ROM_RESIDENT*/#ifdefUNCOMPRESS#if(CPU_FAMILY=MIPS)/*copytexttouncachedlocatio
58、nstoavoidproblemswithcopybackcaches*/(FUNCPTR)ROM_OFFSET(copyLongs)(ROM_TEXT_ADRS,(UINT)K0_TO_K1(romInit),ROM_COPY_SIZE/sizeof(long);#else/*CPU_FAMILY=MIPS*/*對(duì)于不是ROM_RESIDENT,并且沒有被壓縮,則拷貝代碼段和數(shù)據(jù)段到ram.因?yàn)橄到y(tǒng)在RAM中運(yùn)行,所以copyLongs函數(shù)是定位到ram空間的,所以要計(jì)算ROM的偏移量。ROM_TEXT_ADRS就是代碼段在rom上的開始位置。romlnit則是由鏈接器定位到了RAM_HIG
59、H_ADRS的地址上。*/(FUNCPTR)ROM_OFFSET(copyLongs)(ROM_TEXT_ADRS,(UINT)romInit,ROM_COPY_SIZE/sizeof(long);#endif/*CPU_FAMILY=MIPS*/#else/*UNCOMPRESS*/#if(CPU_FAMILY=MIPS)/*copytexttouncachedlocationstoavoidproblemswithcopybackcachescopytheentiredatasegmentbecausethereisnowaytoensurethatbinArrayisthelastthi
60、nginthedatasegmentbecauseofGPrelativeaddressing*/(FUNCPTR)ROM_OFFSET(copyLongs)(ROM_TEXT_ADRS,(UINT)K0_TO_K1(romInit),(UINT)wrs_kernel_data_end-(UINT)romInit)/sizeof(long);#else/*CPU_FAMILY=MIPS*/*對(duì)于不是ROM_RESIDENT但是被壓縮.要分開拷貝。因?yàn)橄到y(tǒng)在RAM中運(yùn)行,所以copyLongs函數(shù)是定位到ram空間的,所以要計(jì)算ROM的偏移量。開始的時(shí)候把從ROM_TEXT_ADRS起始的長(zhǎng)度為
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 金融學(xué)點(diǎn)鈔培訓(xùn)
- 厲行節(jié)約從我做起倡議書范文5篇
- 軍訓(xùn)生活的心得體會(huì)10篇
- 朱自清匆匆閱讀心得10篇
- 《朝花夕拾》讀后感
- 智能工廠規(guī)劃培訓(xùn)
- 成功話題作文15篇
- 方案策劃范文匯編10篇
- 大衛(wèi)科波菲爾讀后感(15篇)
- 文員類實(shí)習(xí)報(bào)告
- 第一單元測(cè)試基礎(chǔ)卷-【中職專用】2024-2025學(xué)年語文同步單元基礎(chǔ)卷(高教版2023基礎(chǔ)模塊下冊(cè)) (解析版)
- 危險(xiǎn)作業(yè)清單
- 2023年盛京銀行校園招聘人員筆試上岸歷年典型考題與考點(diǎn)剖析附帶答案詳解
- 合成生物學(xué)應(yīng)用于新藥開發(fā)
- 酒店運(yùn)營(yíng)管理 智慧樹知到期末考試答案章節(jié)答案2024年山東青年政治學(xué)院
- 單病種管理理論知識(shí)考核試題及答案
- 鉛鋅礦礦山供電系統(tǒng)設(shè)計(jì)與節(jié)能改造研究
- DZ∕T 0211-2020 礦產(chǎn)地質(zhì)勘查規(guī)范 重晶石、毒重石、螢石、硼(正式版)
- 啟航計(jì)劃培訓(xùn)總結(jié)與反思
- 《電力工程電纜防火封堵施工工藝導(dǎo)則》
- 變電站隱患排查治理總結(jié)報(bào)告
評(píng)論
0/150
提交評(píng)論