linux内核启动文档翻译(i386)
本文檔的翻譯是基于linux內核版本2.6.11.1的,本人英語超難,但是由于學習linux內核代碼也硬著頭皮看英文文檔,看的過程中感覺能夠學到許多東西所以決定發點時間把這篇翻譯下來了,里面很很多的不準確希望大家糾正和指導。希望共同探討和學習,這也是自己學習linux源代碼的一部分內容,接下來會有更多關于這方面的知識和大家分享,包括詳細的內核運行原理和超詳細的內核代碼注釋,期待和大家分享學習過程中的點點滴滴。每天成長一點點嘛!這篇文章雖然不長,但也發了我一天的時間,主要還是因為我英文太差的緣故吧。文章中翻譯不當之處或錯誤還請大家提出來以便我盡快改正和學習。
寫在前面的一點知識:
ramdisk一個作用就是用來解決boot過程中mount根文件系統的“先有雞還是先有蛋”的問題的。
一般來說,根文件系統在形形色色的存儲設備上,不同的設備又要不同的硬件廠商的驅動,比如intel的南橋自然需要intel的ide/sata驅動,VIA的南橋需要VIA的ide/sata驅動,根文件系統也有不同的文件系統的可能,比如ubuntu發行版可能一般用ext3,suse可能就不是了,不同的文件系統也需要不同的文件系統模塊;假如把所有驅動/模塊都編譯進內核,那自然沒問題,但是這樣就違背了“內核”的精神或本質,所以一般來說驅動/模塊都駐留在根文件系統本身上/lib/modules/xxx,那么“雞蛋”問題就來了,現在要mount根文件系統卻需要根文件系統上的模塊文件,怎么辦?于是,就想出ramdisk,內核總是能安裝ramdisk的,然后把所有可能需要的驅動/模塊都放在ramdisk上,首先,讓內核將ramdisk當作根文件系統來安裝,然后再用這個根文件系統上的驅動來安裝真正的根文件系統,就將這個矛盾問題解決了.
ramdisk還舉出一個作用,現在的發行版在boot時一般都是圖形界面的,那么,ramdisk就可以放framebuffer驅動和一些圖片來做這種簡單的動畫。
說明:文章中的“命令行”都應該是“命令行參數”更好吧。從下面開始是英文和我翻譯中文的對照。
THELINUX/I386BOOTPROTOCOL(Linux/I386啟動協議)
----------------------------
H.PeterAnvin<hpa@zytor.com>(作者郵箱)
Lastupdate2002-01-01(最后更新時間2002-01-01)
Onthei386platform,theLinuxkernelusesarathercomplicatedbootconvention.Thishasevolvedpartiallyduetohistoricalaspects,aswellasthedesireintheearlydaystohavethekernelitselfbeabootableimage,thecomplicatedPCmemorymodelandduetochangedexpectationsinthePCindustrycausedbytheeffectivedemiseofreal-modeDOSasamainstreamoperatingsystem.
在i386平臺,linux內核使用了一個相當復雜的啟動協議。這個特別的演變是由于歷史各個方面,在早期的愿望是內核本身是可引導的鏡像,復雜的PC機內存模型和由于期望改變在個人計算機產業中有效的終止實模式DOS而作為主流的操作系統。
Currently,fourversionsoftheLinux/i386bootprotocolexist.
當前,四種版本的Linux/i386啟動協議存在。
Oldkernels: zImage/Imagesupportonly.Someveryearlykernelsmaynotevensupportacommandline.
老的內核:zImage/Image格式僅僅被支持。一些非常早的內核甚至可能不支持命令行。
Protocol2.00: (Kernel1.3.73)AddedbzImageandinitrdsupport,aswellasaformalizedwaytocommunicatebetweenthebootloaderandthekernel.setup.Smaderelocatable,althoughthetraditionalsetupareastillassumedwritable.
協議2.00:(Kernel1.3.73)增加了bzImage和initrd支持,以及引導加載程序和內核之間的通信的正式方式。setup.S作出可重定位,盡管傳統setup區域仍假定可寫。
Protocol2.01: (Kernel1.3.76)Addedaheapoverrunwarning.
協議2.01:(Kernel1.3.76)添加堆溢出警告
Protocol2.02: (Kernel2.4.0-test3-pre3)Newcommandlineprotocol.Lowertheconventionalmemoryceiling. Nooverwriteofthetraditionalsetuparea,thusmakingbootingsafeforsystemswhichusetheEBDAfromSMMor32-bitBIOSentrypoints.zImagedeprecatedbutstillsupported.
協議2.02:(Kernel2.4.0-test3-pre3)新的命令行協議。降低常規的內存上限。傳統setup區域不能重寫,從而使安全的啟動系統,使用從SMM(SystemManagementMode系統管理模式)或32位BIOS入口點EBDA(ExtendedBIOSDataArea可擴展的BIOS數據區域)。zImage不贊成但是仍然支持。
Protocol2.03: (Kernel2.4.18-pre1)Explicitlymakesthehighestpossibleinitrdaddressavailabletothebootloader.
協議2.03:(Kernel2.4.18-pre1)明白地安排最高initrd地址可用引導裝入過程
****MEMORYLAYOUT(內存布局)
Thetraditionalmemorymapforthekernelloader,usedforImageor
zImagekernels,typicallylookslike:
傳統的內核裝載內存映射,使用ImageorzImage內核,典型地看起來像:
| |
0A0000 +------------------------+
|ReservedforBIOS | Donotuse.ReservedforBIOSEBDA.(不使用。為BIOSEBDA保留)
09A000 +------------------------+
|Stack/heap/cmdline | Forusebythekernelreal-modecode.(實模式內核代碼使用)
098000 +------------------------+
|Kernelsetup | Thekernelreal-modecode.(實模式內核代碼)
090200 +------------------------+
|Kernelbootsector | Thekernellegacybootsector.(內核啟動扇區)
090000 +------------------------+
|Protected-modekernel| Thebulkofthekernelimage.(保護模式,大的內核映像)
010000 +------------------------+
|Bootloader | <-Bootsectorentrypoint0000:7C00(啟動裝載進入點0000:7c00)
001000 +------------------------+
|ReservedforMBR/BIOS|(為MBR(masterbootrecord主引導記錄)BIOS保留)
000800 +------------------------+
|TypicallyusedbyMBR|(典型被MBR使用)
000600 +------------------------+
|BIOSuseonly |(僅僅被BIOS使用)
000000 +------------------------+
WhenusingbzImage,theprotected-modekernelwasrelocatedto0x100000("highmemory"),andthekernelreal-modeblock(bootsector,setup,andstack/heap)wasmaderelocatabletoanyaddressbetween0x10000andendoflowmemory.
當使用bzImage,保護模式內核是移動到0x100000(“高內存”),實模式模塊(bootsector,setup,andstack/heap)被裝載到地址0x10000到最低內存的結尾的任何地方。
Unfortunately,inprotocols2.00and2.01thecommandlineisstillrequiredtoliveinthe0x9XXXXmemoryrange,andthatmemoryrangeisstilloverwrittenbytheearlykernel.The2.02protocolresolvesthatproblem.
幸運地,在協議2.00和2.01中命令行仍然被要求存在0x9XXXXX內存區域,那段內存區域仍然被早期內核重寫。2.02協議解決了那個問題。
Itisdesirabletokeepthe"memoryceiling"--thehighestpointinlowmemorytouchedbythebootloader--aslowaspossible,sincesomenewerBIOSeshavebeguntoallocatesomeratherlargeamountsofmemory,calledtheExtendedBIOSDataArea,nearthetopoflowmemory. Thebootloadershouldusethe"INT12h"BIOScalltoverifyhowmuchlowmemoryisavailable.
期望保持內存上限--在低內存的最高點被引導加載程序接觸--盡可能的低,因為一些新的BIOSes已經開始分配一些相當大的內存數量,叫做可擴展BIOS的數據區域,在低內存的頂端附近。引導加載程序應該使用"INT12h"BIOS中斷調用確定有多大的低內存是可利用的。
Unfortunately,ifINT12hreportsthattheamountofmemoryistoolow,thereisusuallynothingthebootloadercandobuttoreportanerrortotheuser.Thebootloadershouldthereforebedesignedtotakeupaslittlespaceinlowmemoryasitreasonablycan.ForzImageoroldbzImagekernels,whichneeddatawrittenintothe
0x90000segment,thebootloadershouldmakesurenottousememoryabovethe0x9A000point;toomanyBIOSeswillbreakabovethatpoint.
幸運地,如果INT12h中斷調用報告內存總量太少,則通常沒有引導加載程序能啟動并且報告一個錯誤給用戶。因此引導加載程序應該被設計在低內存占用盡量少量的空間。因為zImage或老的bzImage內核,需要數據被寫在0x90000段處,引導加載程序應該確保不使用高于0x9A000點的內存;太多的BIOSes將破壞那個點以上的內存。
****THEREAL-MODEKERNELHEADER(實模式內核開頭)
Inthefollowingtext,andanywhereinthekernelbootsequence,"asector"refersto512bytes.Itisindependentoftheactualsectorsizeoftheunderlyingmedium.
在下面的文本中,在內核啟動順序的任何地方,“一個扇區”是指512字節。它是下面媒介的實際扇區大小的獨立(意思不依賴具體的存儲介質,一個扇區都是指512字節)。
ThefirststepinloadingaLinuxkernelshouldbetoloadthereal-modecode(bootsectorandsetupcode)andthenexaminethefollowingheaderatoffset0x01f1.Thereal-modecodecantotalupto32K,althoughthebootloadermaychoosetoloadonlythefirsttwosectors(1K)andthenexaminethebootupsectorsize.
第一步在裝載一個linux內核應該被裝載實模式代碼(bootsector和setup代碼)然后檢查接下來在偏移0x01f1處的header代碼。實模式代碼能達到32K,但是引導加載程序可能選擇裝載僅僅開始的兩個扇區(1K)然后檢查啟動扇區的大小。
Theheaderlookslike:
Header看起來像:
Offset(偏移量)Proto(協議)Name(名字)Meaning(意思)
/Size(大小)
01F1/1 ALL setup_sects Thesizeofthesetupinsectors
(所有)(setup設置扇區的大小)
01F2/2 ALL root_flags Ifset,therootismountedreadonly
如果被設置,root被只讀掛載
01F4/2 ALL syssize DONOTUSE-forbootsect.Suseonly
不使用-僅僅被bootsect.S使用
01F6/2 ALL swap_dev DONOTUSE-obsolete
(不使用-已不用的)
01F8/2 ALL ram_size DONOTUSE-forbootsect.Suseonly
不使用-僅僅被bootsect.S使用
01FA/2 ALL vid_mode Videomodecontrol
視頻模式控制
01FC/2 ALL root_dev Defaultrootdevicenumber
默認的根設備號
01FE/2 ALL boot_flag 0xAA55magicnumber
0xAA55魔法數字
0200/2 2.00+ jump Jumpinstruction
2.00以上 跳轉指令
0202/4 2.00+ header Magicsignature"HdrS"
魔法信號"HdrS"
0206/2 2.00+ version Bootprotocolversionsupported
協議版本 啟動協議版本支持
0208/4 2.00+ realmode_swtch Bootloaderhook(seebelow)
實模式轉換 引導裝載程序鉤子(看下面)
020C/2 2.00+ start_sys Theload-lowsegment(0x1000)(obsolete)
開始系統段 低裝載段0x1000(已過時)
020E/2 2.00+ kernel_version Pointertokernelversionstring
內核版本 指向內核版本字符串
0210/1 2.00+ type_of_loader Bootloaderidentifier
裝載類型 引導裝載程序標志
0211/1 2.00+ loadflags Bootprotocoloptionflags
裝載標志 引導協議可選標志
0212/2 2.00+ setup_move_size Movetohighmemorysize(usedwithhooks)
Setup移動大小 移動到高內存大小(使用鉤子)
0214/4 2.00+ code32_start Bootloaderhook(seebelow)
32位代碼啟動 引導裝載程序鉤子(看下面)
0218/4 2.00+ ramdisk_image initrdloadaddress(setbybootloader)
Ramdisk鏡像 initrd(初始化跟設備)裝載地址(被引導裝載程序設置)
021C/4 2.00+ ramdisk_size initrdsize(setbybootloader)
Ramdisk大小 initrd大小(被引導裝載程序設置)
0220/4 2.00+ bootsect_kludge DONOTUSE-forbootsect.Suseonly
不使用-僅僅被bootsect.S使用
0224/2 2.01+ heap_end_ptr Freememoryaftersetupend
2.01以上 堆結束指針 setup結束以后是自由內存
0226/2 N/A pad1 Unused
0228/4 2.02+ cmd_line_ptr 32-bitpointertothekernelcommandline
2.02以上 命令行參數指針 32位指向內核命令行參數
022C/4 2.03+ initrd_addr_max Highestlegalinitrdaddress
2.03以上 initrd最大地址 最高合法的initrd地址
Forbackwardscompatibility,ifthesetup_sectsfieldcontains0,therealvalueis4.
為了后面的兼容性,如果setup_sects區域包含0,真實的值是4。
Ifthe"HdrS"(0x53726448)magicnumberisnotfoundatoffset0x202,thebootprotocolversionis"old".Loadinganoldkernel,thefollowingparametersshouldbeassumed:
如果"HdrS"(0x53726448)魔法數字沒有在偏移0x202處被找到,啟動協議版本是“老的”。裝載一個老的內核,下面的參數應該被假設:
Imagetype=zImage 映像內核=zImage
initrdnotsupportedinitrd不被支持
Real-modekernelmustbelocatedat0x90000.實模式內核必須位于0x90000
Otherwise,the"version"fieldcontainstheprotocolversion,e.g.protocolversion2.01willcontain0x0201inthisfield.Whensettingfieldsintheheader,youmustmakesureonlytosetfieldssupportedbytheprotocolversioninuse.
否則,“version”區域包含協議版本,例如協議本版2.01將包含0x0201在這個區域。當設置區域在header中時,你必須確保僅僅設置區域被使用的協議版本所支持。
The"kernel_version"field,ifsettoanonzerovalue,containsapointertoanull-terminatedhuman-readablekernelversionnumberstring,less0x200.Thiscanbeusedtodisplaythekernelversiontotheuser.Thisvalueshouldbelessthan(0x200*setup_sects).Forexample,ifthisvalueissetto0x1c00,thekernelversionnumberstringcanbefoundatoffset0x1e00inthekernelfile.Thisisavalidvalueifandonlyifthe"setup_sects"fieldcontainsthevalue14orhigher.
"kernel_version"字段,如果被設置為一個非零值,包含一個指向(NULL)空結束的人可讀的內核版本數字字符串,小于0x200。這個能夠被使用顯示內核版本給用戶看。這個值應該小于(0x200*setup的扇區數)。例如,如果這個值被設置為0x1c00,內核版本數字字符串能夠被找到在內核文件偏移0x1e00處。如果并且僅僅如果"setup_sects"字段包含值14或更高這是一個有效值
Mostbootloaderswillsimplyloadthekernelatitstargetaddressdirectly.Suchbootloadersdonotneedtoworryaboutfillinginmostofthefieldsintheheader.Thefollowingfieldsshouldbefilledout,however:
大多數引導裝載程序將簡單直接的裝載內核到它的目的地址。這樣引導裝載程序不需要擔心在header填充很多的字段。然而,下面的字段應該被填充:
vid_mode:PleaseseethesectiononSPECIALCOMMANDLINEOPTIONS.
視頻模式:請看特殊的命令行可選部分
type_of_loader:裝載類型
Ifyourbootloaderhasanassignedid(seetablebelow),enter0xTVhere,whereTisanidentifierforthebootloaderandVisaversionnumber.Otherwise,enter0xFFhere.
如果你的引導裝載程序有一個被指派的id(看下面的表格),進入0xTV這兒,T是一個引導裝載程序的標志符,V是一個版本數字。否則,進入0xFF這兒。
Assignedbootloaderids:指派的引導裝載程序(以下9種)
0LILO
1Loadlin
2bootsect-loader
3SYSLINUX
4EtherBoot
5ELILO
7GRuB
8U-BOOT
Pleasecontact<hpa@zytor.com>ifyouneedabootloaderIDvalueassigned.
請聯系<hpa@zytor.com>如果你需要一個引導裝載程序被指派的ID值
loadflags,heap_end_ptr:裝載標志,堆結束指針
Iftheprotocolversionis2.01orhigher,entertheoffsetlimitofthesetupheapintoheap_end_ptrandsetthe0x80bit(CAN_USE_HEAP)ofloadflags.heap_end_ptrappearstoberelativetothestartofsetup(offset0x0200).
如果協議版本是2.01或更高,設置setup堆棧的限制到heap_end_ptr(堆結束指針)處和設置0x80位(能夠使用堆棧)標志。heap_end_ptr(堆結束指針)顯示相對setup的開始(偏移0x0200)。
setup_move_size:setup移動的大小
Whenusingprotocol2.00or2.01,iftherealmodekernelisnotloadedat0x90000,itgetsmovedtherelaterintheloadingsequence.Fillinthisfieldifyouwantadditionaldata(suchasthekernelcommandline)movedinadditiontothereal-modekernelitself.
當使用協議2.00或2.01,如果實模式內核是不裝載在0x90000,它在加載序號以后被移動那里。如果你需要額外的數據(例如內核命令行)被移動,那么填充這個字段增加到實模式內核自身。
ramdisk_image,ramdisk_size:內存盤映像,內存盤大小
Ifyourbootloaderhasloadedaninitialramdisk(initrd),setramdisk_imagetothe32-bitpointertotheramdiskdataandtheramdisk_sizetothesizeoftheramdiskdata.
如果你的引導裝載程序已經裝載一個初始化的內存盤(initrd),設置內存盤映像(ramdisk_image)為一個32位指針指向內存盤數據和設置內存盤大小(ramdisk_size)為內存盤數據的大小。
Theinitrdshouldtypicallybelocatedashighinmemoryaspossible,asitmayotherwisegetoverwrittenbytheearlykernelinitializationsequence. However,itmustneverbelocatedabovetheaddressspecifiedintheinitrd_addr_maxfield. Theinitrdshouldbeatleast4Kpagealigned.
初始化的內存盤(initrd)應該典型地位于盡可能的高的內存,因為它可能被早的內核初始化序列覆蓋寫。然而,它必須從來不位于在專門化的initrd_addr_max字段以上的地址。初始化的內存盤(initrd)應該被設置至少4K頁對齊。
cmd_line_ptr:命令行指針
Iftheprotocolversionis2.02orhigher,thisisa32-bitpointertothekernelcommandline.Thekernelcommandlinecanbelocatedanywherebetweentheendofsetupand0xA0000.Fillinthisfieldevenifyourbootloaderdoesnotsupportacommandline,inwhichcaseyoucanpointthistoanemptystring(orbetteryet,tothestring"auto".)Ifthisfieldisleftatzero,thekernelwillassumethatyourbootloaderdoesnotsupportthe2.02+protocol.
如果協議是2.02或更高,這是一個32位指針指向內核命令行。內核命令行能位于setup結束至0xA0000的任何地方。填充這個字段雖然你的引導裝載程序不支持一個命令行,它能使你這個字段指向一個空字符串(或更好,是一個“auto”字符串)如果這個字段被留下在零,內核將假設你的引導裝載程序不支持2.02以上的協議。
ramdisk_max:內存盤最大
Themaximumaddressthatmaybeoccupiedbytheinitrdcontents.Forbootprotocols2.02orearlier,thisfieldisnotpresent,andthemaximumaddressis0x37FFFFFF.(Thisaddressisdefinedastheaddressofthehighestsafebyte,soifyourramdiskisexactly131071310722byteslongandthisfieldis0x37FFFFFF,youcanstartyourramdiskat0x37FE0000.)
可能被初始化內存盤內容占用的最大地址。對于引導協議2.02或更早,這個字段是不存在的,并且最大地址是0x37FFFFFF。(這個地址被定義為最高的安全字節,因此如果你的內存盤確切的131072字節長并且這個區域是0x37FFFFFF,你能開始你的內存盤在0x37FE0000)。
****THEKERNELCOMMANDLINE內核命令行
Thekernelcommandlinehasbecomeanimportantwayforthebootloadertocommunicatewiththekernel.Someofitsoptionsarealsorelevanttothebootloaderitself,see"specialcommandlineoptions"below.
內核命令行已近是改變引導裝載程序和內核通信的一種重要方式。一些它的可選項也是有關于引導裝載程序自身的,看下面的“特殊的命令行可選項”。
Thekernelcommandlineisanull-terminatedstringupto255characterslong,plusthefinalnull.
內核命令行是一個NULL(空)終止的加上最后的null到達255個字符長度的字符串。
Ifthebootprotocolversionis2.02orlater,theaddressofthekernelcommandlineisgivenbytheheaderfieldcmd_line_ptr(seeabove.)
如果引導協議版本是2.02或更晚,內核的命令行地址被header字段cmd_line_ptr給出(看上面)。
Iftheprotocolversionis*not*2.02orhigher,thekernelcommandlineisenteredusingthefollowingprotocol:
如果協議版本不是2.02或更高,內核命令行被輸入使用下面的協議:
Atoffset0x0020(word),"cmd_line_magic",enterthemagicnumber0xA33F.
在偏移0x0020(字),“cmd_line_magic”,輸入魔法數字0xA33F。
Atoffset0x0022(word),"cmd_line_offset",entertheoffsetofthekernelcommandline(relativetothestartofthereal-modekernel).
在偏移0x0022(字),"cmd_line_offset",輸入內核命令行的偏移量(與實模式內核開始有關)
Thekernelcommandline*must*bewithinthememoryregioncoveredbysetup_move_size,soyoumayneedtoadjustthisfield.
內核命令行必須在被setup_move_size內存區域大小覆蓋以內,因此你可能需要調整這個字段。
****SAMPLEBOOTCONFIGURATION引導程序配置樣例
Asasampleconfiguration,assumethefollowinglayoutoftherealmodesegment:
作為一個樣例配置,假設實模式段有下面的布局:
0x0000-0x7FFF Realmodekernel實模式內核
0x8000-0x8FFF Stackandheap棧和堆
0x9000-0x90FF Kernelcommandline內核命令行
Suchabootloadershouldenterthefollowingfieldsintheheader:
如此一個引導裝載程序應該進入下面字段,在header中。
unsignedlongbase_ptr; /*baseaddressforreal-modesegment*/實模式的段地址
if(setup_sects==0){
setup_sects=4;
}
if(protocol>=0x0200){
type_of_loader=<typecode>;
if(loading_initrd){
ramdisk_image=<initrd_address>;
ramdisk_size=<initrd_size>;
}
if(protocol>=0x0201){
heap_end_ptr=0x9000-0x200;
loadflags|=0x80;/*CAN_USE_HEAP*/
}
if(protocol>=0x0202){
cmd_line_ptr=base_ptr+0x9000;
}else{
cmd_line_magic =0xA33F;
cmd_line_offset=0x9000;
setup_move_size=0x9100;
}
}else{
/*Veryoldkernel*/
cmd_line_magic =0xA33F;
cmd_line_offset=0x9000;
/*AveryoldkernelMUSThaveitsreal-modecode
loadedat0x90000*/一個老的內核必須有它的實模式代碼裝載在0x90000
if(base_ptr!=0x90000){
/*Copythereal-modekernel*/復制實模式內核
memcpy(0x90000,base_ptr,(setup_sects+1)*512);
/*Copythecommandline*/復制命令行
memcpy(0x99000,base_ptr+0x9000,256);
base_ptr=0x90000; /*Relocated*/重映射
}
/*Itisrecommendedtoclearmemoryuptothe32Kmark*/它要求清除內存到32K標志
memset(0x90000+(setup_sects+1)*512,0,
(64-(setup_sects+1))*512);
}
****LOADINGTHERESTOFTHEKERNEL(裝載剩余的內核部分)
Thenon-real-modekernelstartsatoffset(setup_sects+1)*512inthekernelfile(again,ifsetup_sects==0therealvalueis4.)Itshouldbeloadedataddress0x10000forImage/zImagekernelsand0x100000forbzImagekernels.
非實模式內核開始在內核文件偏移(setup_sects+1)*512處(重復一下,如果setup_sects==0真實值是4)。作為Image/zImage它應該被裝載在地址0x10000,作為bzImage它應該被裝載在地址0x100000
ThekernelisabzImagekerneliftheprotocol>=2.00andthe0x01bit(LOAD_HIGH)intheloadflagsfieldisset:
如果協議大于等于2.00并且在裝載標志(loadflags)字段的0x01位(高裝載)被設置,則內核是一個bzImage(大模式內核)。
is_bzImage=(protocol>=0x0200)&&(loadflags&0x01);//偽代碼表示
load_address=is_bzImage?0x100000:0x10000;//偽代碼表示
NotethatImage/zImagekernelscanbeupto512Kinsize,andthususetheentire0x10000-0x90000rangeofmemory.Thismeansitisprettymucharequirementforthesekernelstoloadthereal-modepartat
0x90000.bzImagekernelsallowmuchmoreflexibility.
注意thatImage/zImage(小模式內核)能夠到達512K大小,因此使用整個0x10000-0x90000內存區域。這意味著對這些內核它是相當多的要求來裝載實模式部分在0x90000。bzImage內核允許更多的靈活性。
****SPECIALCOMMANDLINEOPTIONS(特殊的命令行可選項)
Ifthecommandlineprovidedbythebootloaderisenteredbytheuser,theusermayexpectthefollowingcommandlineoptionstowork.Theyshouldnormallynotbedeletedfromthekernelcommandlineeven
thoughnotallofthemareactuallymeaningfultothekernel.BootloaderauthorswhoneedadditionalcommandlineoptionsforthebootloaderitselfshouldgetthemregisteredinDocumentation/kernel-parameters.txttomakesuretheywillnotconflictwithactualkerneloptionsnoworinthefuture.
如果被引導裝載程序提供的命令行被用戶輸入,用戶可能期望根據下面的命令行的可選項來運行。通常不應該從內核命令行刪除他們,即使不是所有的他們對內核來說都有實際上的意義。針對引導裝載程序自身的需要額外的命令行可選項的引導裝載程序作者應該從注冊在Documentation/kernel-parameters.txt這個文件中得到他們,來確保他們將不會和現在或將來的實際的內核可選項產生沖突。
vga=<mode>VGA=《模式》(也就是顯卡模式配置)
<mode>hereiseitheraninteger(inCnotation,eitherdecimal,octal,orhexadecimal)oroneofthestrings
"normal"(meaning0xFFFF),"ext"(meaning0xFFFE)or"ask"(meaning0xFFFD).Thisvalueshouldbeenteredintothevid_modefield,asitisusedbythekernelbeforethecommandlineisparsed.
<模式>這兒不是一個整數(在C語言中的記號,不是十進制,八進制,就是十六進制)就是一個字符串“正常”(0xFFFF代表的意義),“ext”(0xFFFE代表的意義),“ask”(0xFFFD代表的意義)。這個值應該被輸入視頻模式(vid_mode)字段,在命令行被解析以前被內核使用。
mem=<size>
<size>isanintegerinCnotationoptionallyfollowedbyK,MorG(meaning<<10,<<20or<<30).Thisspecifiestheendofmemorytothekernel.Thisaffectsthepossibleplacementofaninitrd,sinceaninitrdshouldbeplacednearendofmemory.Notethatthisisanoptionto*both*thekernelandthebootloader!
在C語言的表示<size>是隨意地跟著K,M或G的一個整數(意思左移10,20,30位),這指定內核的內存末端。這可能影響的地方是一個初始化的內存盤(initrd),因為初始化的內存盤(initrd)應該被放置在內存末端的附近。注意在內核(kernel)和引導裝載程序(bootloader)都是一個可選項。
initrd=<file>
Aninitrdshouldbeloaded.Themeaningof<file>isobviouslybootloader-dependent,andsomebootloaders(e.g.LILO)donothavesuchacommand.
這個初始化的內存盤應該被裝載。<file>的意思明顯是依賴于引導裝載程序(bootloader),并且一些引導裝載程序(bootloader)(像LILO)沒有如此的一個命令。
Inaddition,somebootloadersaddthefollowingoptionstotheuser-specifiedcommandline:
另外,一些啟動裝載程序增加以下選擇項到用戶指定的命令行:
BOOT_IMAGE=<file>
Thebootimagewhichwasloaded.Again,themeaningof<file>isobviouslybootloader-dependent.
被裝載的引導鏡像。再一次,<file>的意思明顯是依賴于引導裝載程序(bootloader)。
Auto(自動)
Thekernelwasbootedwithoutexplicituserintervention.
內核被引導沒有明顯的用戶交互。
Iftheseoptionsareaddedbythebootloader,itishighlyrecommendedthattheyarelocated*first*,beforetheuser-specifiedorconfiguration-specifiedcommandline.Otherwise,"init=/bin/sh"getsconfusedbythe"auto"option.
如果這些選擇項由啟動裝載程序增加,在用戶指定或配置指定的命令行之前我們極力推薦他們是被第一個被找出的。否則,“init=/bin/sh”由“自動”選項拒絕。
****RUNNINGTHEKERNEL運行內核
Thekernelisstartedbyjumpingtothekernelentrypoint,whichislocatedat*segment*offset0x20fromthestartoftherealmodekernel.Thismeansthatifyouloadedyourreal-modekernelcodeat0x90000,thekernelentrypointis9020:0000.
內核跳轉到位于的內核入口點被啟動的,從實模式內核開始的地址處段偏移0x20。這意味著如果您加載您的實時模式內核代碼在0x90000,內核入口點是9020:0000。
Atentry,ds=es=ssshouldpointtothestartofthereal-modekernelcode(0x9000ifthecodeisloadedat0x90000),spshouldbesetupproperly,normallypointingtothetopoftheheap,andinterruptsshouldbedisabled.Furthermore,toguardagainstbugsinthekernel,itisrecommendedthatthebootloadersetsfs=gs=ds=es=ss.
在入口,ds=es=ss應該指向實模式內核代碼開始的地方(如果代碼被裝載在ox90000處就是0x9000),SP(堆棧指針)的開始應該適當地設定,通常指向堆的頂端,并且所有的中斷應該被禁止。此外,為了在內核控制產生錯誤(bugs),建議啟動裝載程序設置fs=gs=ds=es=ss。
Inourexamplefromabove,wewoulddo:
在來至上面我們的例程,我們應該做:
/*Note:inthecaseofthe"old"kernelprotocol,base_ptrmustbe==0x90000atthispoint;seetheprevioussamplecode*/
注意:在老內核協議的情況下,在base_ptr這一點必須是在0x90000,看以前樣例代碼
seg=base_ptr>>4;
cli(); /*Enterwithinterruptsdisabled!*/禁止中斷
/*Setupthereal-modekernelstack*/建立實模式內核堆棧
_SS=seg;
_SP=0x9000; /*LoadSPimmediatelyafterloadingSS!*/在裝載了SS(堆棧段)以后立即裝載堆棧指針(SP)
_DS=_ES=_FS=_GS=seg;
jmp_far(seg+0x20,0); /*Runthekernel*/運行內核
Ifyourbootsectoraccessesafloppydrive,itisrecommendedtoswitchoffthefloppymotorbeforerunningthekernel,sincethekernelbootleavesinterruptsoffandthusthemotorwillnotbeswitchedoff,especiallyiftheloadedkernelhasthefloppydriverasademand-loadedmodule!
如果您的引導扇區訪問(軟盤)磁盤驅動器,推薦在運行內核之前關閉馬達。因為內核引導停止中斷,因此電機將不會關閉,特別是如果在加載的內核有軟盤驅動程序作為需求加載的模塊!
****ADVANCEDBOOTTIMEHOOKS先進的啟動時間掛鉤
Ifthebootloaderrunsinaparticularlyhostileenvironment(suchasLOADLIN,whichrunsunderDOS)itmaybeimpossibletofollowthestandardmemorylocationrequirements.Suchabootloadermayusethefollowinghooksthat,ifset,areinvokedbythekernelattheappropriatetime.Theuseofthesehooksshouldprobablybe
consideredanabsolutelylastresort!
如果你的引導裝載程序運行在一個特別的不穩定的環境中(例如LOADIN,運行在DOS之下)它可能不能按照標準內存位置的要求。因為一個引導裝載程序可能使用下面那樣的鉤子,如果設置,被內核在合適的時間調用。使用這些鉤子可能應考慮一個絕對最后的手段。
IMPORTANT:Allthehooksarerequiredtopreserve%esp,%ebp,%esiand%ediacrossinvocation.
重要:所有在調用的鉤子要求保護esp寄存器,ebp寄存器,esi寄存器和edi寄存器
realmode_swtch:實模式切換
A16-bitrealmodefarsubroutineinvokedimmediatelybeforeenteringprotectedmode.ThedefaultroutinedisablesNMI,soyourroutineshouldprobablydoso,too.
在進入保護模式以前16位實模式遠子程序立即調用。默認例程禁止NMI(不可屏蔽中斷),因此你的例程也應該可能這樣做。
code32_start:32位代碼開始
A32-bitflat-moderoutine*jumped*toimmediatelyafterthetransitiontoprotectedmode,butbeforethekernelisuncompressed.Nosegments,exceptCS,aresetup;youshouldsetthemuptoKERNEL_DS(0x18)yourself.
在過渡到保護模式以后立即跳轉到一個32位的線性平板模式運行路線,但是在內核被解壓之前。除了CS代碼段是沒有段被建立;你應該建立你自己的內核數據段(KERNEL_DS)(0x18)。
Aftercompletingyourhook,youshouldjumptotheaddressthatwasinthisfieldbeforeyourbootloaderoverwroteit.
在完成您的勾子以后,您應該跳到在這個字段的地址,在您的啟動裝載程序重寫它之前。
<!--EndFragment-->總結
以上是生活随笔為你收集整理的linux内核启动文档翻译(i386)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【翻译】用纸质电路增加开源的包容性
- 下一篇: 服务注册与发现框架discovery源码