<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > Linux bootloader 編寫方法

          Linux bootloader 編寫方法

          作者: 時間:2011-02-25 來源:網(wǎng)絡(luò) 收藏

          對于移植 linux 到其它開發(fā)板的人來說,編寫 boot loader 是一個不可避免的過程。對于學(xué)習(xí)linux的人來講,編寫 bootloader 也是一個很有挑戰(zhàn)性的工作。本文通過對 linux引導(dǎo)協(xié)議進行分析,詳細闡述了如何編寫一個可以在 i386 機器上引導(dǎo) 2.4.20內(nèi)核的基本的bootloader。


          1.概述

          linux運行在保護模式下,但是當(dāng)機器啟動復(fù)位的時候卻處于實模式下。所以寫bootloader做的工作也是在實模式之下的。

          linux的內(nèi)核有多種格式,老式的zImage和新型的bzImage。它們之間最大的差別是對于內(nèi)核體積大小的限制。由于zImage內(nèi)核需要放在實模式1MB的內(nèi)存之內(nèi),所以其體積受到了限制。目前采用的內(nèi)核格式大多為bzImage,這種格式?jīng)]有1MB內(nèi)存限制。本文以下部分主要以bzImage為例進行分析。

          2.bzImage格式內(nèi)核的結(jié)構(gòu)

          bzImage內(nèi)核從前向后分為3個部分,前512字節(jié)被稱為bootsect,這就是軟盤引導(dǎo)linux時用到的bootloader,如果不從軟盤引導(dǎo),這部分就沒有用,其中存儲了一些編譯時生成的內(nèi)核啟動選項的默認(rèn)值。從512個字節(jié)開始的512*n個字節(jié)稱為setup部分,這是linux內(nèi)核的實模式部分,這部分在實模式下運行,主要功能是為保護模式的linux內(nèi)核啟動準(zhǔn)備環(huán)境。這個部分最后會切換進入保護模式,跳轉(zhuǎn)到保護模式的內(nèi)核執(zhí)行。最后的部分就是保護模式的內(nèi)核,也就是真正意義上的linux內(nèi)核。其中n的大小可以從bootsect后半部得到,詳細地址可以參閱linux boot protocol。

          3.引導(dǎo)過程概述

          第一步,打開冰箱門;第二步把大象放到冰箱里……不要笑,過程就是這么簡單。首先需要把linux內(nèi)核的setup部分拷貝到9020H:0開始的地址,然后把保護模式內(nèi)核拷貝到1MB開始的地址,然后根據(jù)Linux Boot Protocol 2.03的內(nèi)容設(shè)定參數(shù)區(qū)的內(nèi)容,基地址就是9000H:0,最后使用一條ljmp $0x9020,$0跳轉(zhuǎn)到setup段,剩下的事情就是linux自己的了^_^,果然簡單吧!

          4.THE LINUX/I386 BOOT PROTOCOL

          這個就是我們引導(dǎo)linux所使用的協(xié)議,它的位置在:Documetation/i386/boot.txt中。里面詳細的寫了引導(dǎo)linux所需要知道的一切知識,對于其它體系結(jié)構(gòu)的CPU,也一定存在著類似的東東,仿照本文的方法就可以了。

          5.細節(jié)一:基本引導(dǎo)參數(shù)

          當(dāng)然我們不指定任何參數(shù)linux內(nèi)核也可以啟動,但是這樣有可能啟動進入一個我們不支持的framebuffer模式,導(dǎo)致沒有任何屏幕顯示;也可能mount了錯誤的根分區(qū)失敗,導(dǎo)致No Init Found的kernel panic。所以我們必須要指定一些東西。

          如果你像我一樣是一個懶人,那么可以直接把bootsect拷到9000H:0的位置,使用軟盤引導(dǎo)時它會把自己復(fù)制到這個地方的,這里面有些默認(rèn)的設(shè)置,詳情請見boot.txt。

          首先是root的位置,這里bootsect_pos指向的是9000H:0的地址。


          bootsect_pos[0x1fc] = root_minor;
          bootsect_pos[0x1fd] = root_major;


          其中root_minor和root_major分別是root的主設(shè)備號和次設(shè)備號。

          當(dāng)前顯示模式:


          bootsect_pos[0x1fa] = 0xff;
          bootsect_pos[0x1fb] = 0xff;


          這兩個數(shù)值相當(dāng)于引導(dǎo)參數(shù)vga=0xHHH的值,兩個0xff代表文本模式。


          bootsect_pos[0x210] = 0xff;


          這是在設(shè)定你的bootloader的類型,其實只要不是0就行,因為0代表的loader太舊無法引導(dǎo)新的內(nèi)核,setup發(fā)現(xiàn)這個后就會停下來。按照規(guī)范你應(yīng)該寫成0xff,這表示未知的boot loader,如果你的bootloader已經(jīng)得到了一個官方分配的type id,那就寫上自己的數(shù)值。

          6.細節(jié)二:如何加載內(nèi)核

          如果你現(xiàn)在的環(huán)境是一無所有,那么必須使用bios中斷或者ATA指令去讀硬盤了,不過如果你手中如果有基本的DOS系統(tǒng),那么就可以使用DOS的程序了。為了能夠操作整個4GB的地址空間,我使用了WATCOM C寫了個小程序讀內(nèi)核,不過你可以仿照bootsect里面的做法,在實模式中讀一部分,然后進入到保護模式拷貝到1MB以上,然后再從實模式讀一部分……需要注意1:9000H:0也是DOS占用的地址空間,所以讀完內(nèi)核后就不要返回DOS了,否則會有問題;

          注意2:一定保證是純DOS,不要加載HIMEM或者EMM386這樣的東西,它們會使上面的引導(dǎo)過程失敗。loadlin倒是可以來者通吃幾乎所有的DOS,不過它的作者也是這方面的大牛,對DOS下的內(nèi)存管理非常的熟悉。我們現(xiàn)在研究這些古老的東西很難找資料了,況且我們是在寫bootloader,不是DOS killer^_^。

          7.引導(dǎo)時的高級功能

          1)initrd

          initrd是啟動時的一個小虛擬盤,一般用它來實現(xiàn)模塊化的內(nèi)核。引導(dǎo)initrd的方法主要有兩個要點:
          第一,把initrd讀入內(nèi)存,我們可以仿照大多數(shù)boot loader的方法把它放在內(nèi)存的最高端;
          第二,設(shè)定initrd的起始位置和長度

          bootsect_pos[0x218]開始的4個字節(jié)放的是起始物理地址,bootsect_pos[0x21c]開始的4個字節(jié)放的是initrd的長度。

          2)command_line支持

          用command_line你可以給內(nèi)核傳一些參數(shù),自己定制內(nèi)核的行為。我是這樣做的,首先把command_line放在9900H:0的地址里,然后把9900H:0的物理地址存放在bootsect_pos[0x228]開始的4個字節(jié)里面。注意一定是物理地址,所以你應(yīng)該放99000H這個數(shù),然后內(nèi)核就會識別你的command_line了。

          8.結(jié)束語

          寫本文的目的主要是為了用最少的語言和最短的時間說明bootloader的原理,真正的權(quán)威資料還是要看linux內(nèi)核源碼和boot.txt文件。我曾經(jīng)寫過一個例子loaderx,使用WATCOM C和TASM,WATCOM C是一個可以在DOS下生成能訪問4GB物理地址程序的C編譯器,里面也有詳細的注釋和文檔說明??梢詮南旅娴牡刂废螺d:loaderx.tar.gz

          linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)


          評論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();