BootLoader

BootLoader

操作系統内核小程序
Boot Loader是在操作系統内核運行之前運行的一段小程序。[1]通過這段小程序,我們可以初始化硬件設備、建立内存空間的映射圖,從而将系統的軟硬件環境帶到一個合适的狀态,以便為最終調用操作系統内核準備好正确的環境。
    中文名:啟動裝載 外文名:Boot Loader 别名: 應用:嵌入式操作系統

簡介

BootLoader是系統加電啟運行的第一段軟件代碼,回憶一下PC的體系結構我們可以知道,PC機中的引導加載程序由BIOS(其本質就是一段固件程序)和位于硬盤MBR中的引導程序一起組成。BIOS在完成硬件檢測和資源分配後,将硬盤MBR中的引導程序讀到系統的RAM中,然後将控制權交給引導程序。引導程序的主要運行任務就是将内核映象從硬盤上讀到RAM中然後跳轉到内核的入口點去運行,也即開始啟動操作系統。

而在嵌入式系統中,通常并沒有像BIOS那樣的固件程序(有的嵌入式系統也會内嵌一段短小的啟動程序),因此整個系統的加載啟動任務就完全由BootLoader來完成.比如在一個基于ARM7TDMI core的嵌入式系統中,系統在上電或複位時都從地址0x00000000開始執行.而在這個地址處安排的通常就是系統的BootLoader程序。

簡單地說BootLoader就是在操作系統内核或用戶應用程序運行之前運行的一段小程序。通過這段小程序,我們可以初始化硬件設備、建立内存空間的映射圖(有的CPU沒有内存映射功能如S3C44B0),從而将系統的軟硬件環境帶到一個合适的狀态,以便為最終調用操作系統内核或用戶應用程序準備好正确的環境。對于一個嵌入式系統來說,可能有的包括操作系統,有的小型系統也可以隻包括應用程序,但是在這之前都需要BootLoader為它準備一個正确的環境。通常,BootLoader是依賴于硬件而實現的,特别是在嵌入式領域,為嵌入式系統建立一個通用的BootLoader是很困難的。

反過來,大部分Bootloader仍然具有很多共性,某些Bootloader也能夠支持多種體系結構的嵌入式系統。例如,U-Boot就同時支持PowerPC、ARM、MIPS和X86等體系結構,支持的闆子有上百種。通常,它們都能夠自動從存儲介質上啟動,都能夠引導操作系統啟動,并且大部分都可以支持串口和以太網接口。

種類

嵌入式系統世界已經有各種各樣的Bootloader,種類劃分也有多種方式。除了按照處理器體系結構不同劃分以外,還有功能複雜程度的不同。

首先區分一下“Bootloader”和“Monitor”的概念。嚴格來說,“Bootloader”隻是引導設備并且執行主程序的固件;而“Monitor”還提供了更多的命令行接口,可以進行調試、讀寫内存、燒寫Flash、配置環境變量等。“Monitor”在嵌入式系統開發過程中可以提供很好的調試功能,開發完成以後,就完全設置成了一個“Bootloader”。所以,習慣上大家把它們統稱為Bootloader。

表列出了Linux的開放源碼引導程序及其支持的體系結構。表中給出了X86 ARM PowerPC體系結構的常用引導程序,并且注明了每一種引導程序是不是“Monitor”。

X86

X86的工作站和服務器上一般使用LILO和GRUB。LILO是Linux發行版主流的Bootloader。不過Redhat Linux發行版已經使用了GRUB,GRUB比LILO有更有好的顯示界面,使用配置也更加靈活方便。在某些X86嵌入式單闆機或者特殊設備上,會采用其他Bootloader,例如:rolo。這些Bootloader可以取代BIOS的功能,能夠從FLASH中直接引導Linux啟動。現在ROLO支持的開發闆已經并入U-Boot,所以U-Boot也可以支持X86平台。

ARM

ARM處理器的芯片商很多,所以每種芯片的開發闆都有自己的Bootloader。結果ARM bootloader也變得多種多樣。最早有為ARM720處理器的開發闆的固件,又有了armboot,StrongARM平台的blob,還有S3C2410處理器開發闆上的vivi等。現在armboot已經并入了U-Boot,所以U-Boot也支持ARM/XSCALE平台。U-Boot已經成為ARM平台事實上的标準Bootloader。

PowerPC

PowerPC平台的處理器有标準的Bootloader,就是ppcboot。PPCBOOT在合并armboot等之後,創建了U-Boot,成為各種體系結構開發闆的通用引導程序。U-Boot仍然是PowerPC平台的主要Bootloader。

MIPS

MIPS公司開發的YAMON是标準的Bootloader,也有許多MIPS芯片商為自己的開發闆寫了Bootloader。現在,U-Boot也已經支持MIPS平台。

SH

SH平台的标準Bootloader是sh-boot。Redboot在這種平台上也很好用。

m68k

M68K平台沒有标準的Bootloader。Redboot能夠支持m68k系列的系統。值得說明的是Redboot,它幾乎能夠支持所有的體系結構,包括MIPS、SH、M68K等體系結構。Redboot是以eCos為基礎,采用GPL許可的開源軟件工程。

作用原理

Boot Loader所支持的CPU和嵌入式闆

每種不同的CPU體系結構都有不同的Boot Loader。有些Boot Loader 也支持多種體系結構的CPU,比如U-Boot就同時支持ARM體系結構和MIPS體系結構。除了依賴于CPU的體系結構外,Boot Loader實際上也依賴于具體的嵌入式闆級設備的配置。這也就是說,對于兩塊不同的嵌入式闆而言,即使它們是基于同一種CPU而構建的,要想讓運行在一塊闆子上的Boot Loader程序也能運行在另一塊闆子上,通常也都需要修改Boot Loader的源程序。

Boot Loader的安裝媒介(Installation Medium)

系統加電或複位後,所有的CPU通常都從某個由CPU制造商預先安排的地址上取指令。比如,基于ARM7TDMI core的CPU在複位時通常都從地址0x00000000取它的第一條指令。而基于CPU構建的嵌入式系統通常都有某種類型的固态存儲設備(比如:ROM、EEPROM或FLASH等)被映射到這個預先安排的地址上。因此在系統加電後,CPU将首先執行Boot Loader程序。

用來控制Boot Loader 的設備或機制

主機和目标機之間一般通過串口建立連接,Boot Loader 軟件在執行時通常會通過串口來進行I/O,比如:輸出打印信息到串口,從串口讀取用戶控制字符等。

Boot Loader 的啟動過程是單階段(Single Stage)還是多階段(Multi-Stage)

通常多階段的Boot Loader能提供更為複雜的功能,以及更好的可移植性。從固态存儲設備上啟動的。

BootLoader與主機之間進行文件傳輸所用的通信設備及協議程,也即啟動過程可以分為stage1和 stage2兩部分。而至于在stage1和stage2具體完成哪些任務将在下面幾篇讨論。

Boot Loader的操作模式(Operation Boot Loader大多都是2階段的啟動過Mode)。

構成組件

BootLoader主要由以下兩部分組成。

OEM startup code

這部分代碼是在BootLoader中最先被執行的。它的主要功能是初始化最小範圍的硬件設備,比如設置CPU工作頻率、關閉看門狗、設置cache、設置RAM的刷新率、填寫内存控制寄存器(通知CPU有效的數據總線引腳數)等。由于系統剛剛啟動,不适合使用複雜的高級語言,因此這部分代碼主要由彙編程序完成。在彙編程序段設置完堆棧後,就跳轉到C語言的Main函數入口(位于/eboot/main.c);

Main code

這部分代碼由C語言實現,是BLCOMMON代碼的一部分,它可以用來執行比較複雜的操作。比如檢測内存和Flash的有效性、檢測外部設備接口、檢測串口并且向已經連接的主機發送調試信息、通過串口等待命令、啟動網絡接口、建立内存映射等彙編無法完成的工作。

Main code包含以下代碼段:

(1)Image download代碼段

(2)Image的下載可以通過以下接口:

① A. Parallel port I/O接口。這是通過主機和目标機的并口之間的數據傳輸來完成下載工作。具體實現代碼,讀者可以參考/kernel/hal/mdppfs.c文件;

② Ethernet port I/O接口。這是通過主機和目标機的網絡接口之間的數據傳輸來完成下載工作。具體實現代碼,讀者可以參考WINCE420/public/common/oak/DRIVE|RS/ETHDBG/EBOOT文件夾;

③ Debug serial I/O接口。這是通過主機和目标機的串口之間的數據傳輸來完成下載工作。利用串口來傳輸的缺點非常明顯,那就是速度太慢;

通過事先Flash write代碼将鏡像文件固化入Flash。隻要BootLoader被設計成能從Flash加載鏡像文件,本選項就可以使用。

啟動方式

網絡啟動方式

這種方式開發闆不需要配置較大的存儲介質,跟無盤工作站有點類似。但是使用這種啟動方式之前,需要把Bootloader安裝到闆上的EPROM或者Flash中。Bootloader通過以太網接口遠程下載Linux内核映像或者文件系統。第4章介紹的交叉開發環境就是以網絡啟動方式建立的。這種方式對于嵌入式系統開發來說非常重要。使用這種方式也有前提條件,就是目标闆有串口、以太網接口或者其他連接方式。串口一般可以作為控制台,同時可以用來下載内核影像和RAMDISK文件系統。串口通信傳輸速率過低,不适合用來挂接NFS文件系統。所以以太網接口成為通用的互連設備,一般的開發闆都可以配置10M以太網接口。

對于PDA等手持設備來說,以太網的RJ-45接口顯得大了些,而USB接口,特别是USB的迷你接口,尺寸非常小。對于開發的嵌入式系統,可以把USB接口虛拟成以太網接口來通訊。這種方式在開發主機和開發闆兩端都需要驅動程序。

另外,還要在服務器上配置啟動相關網絡服務。Bootloader下載文件一般都使用TFTP網絡協議,還可以通過DHCP的方式動态配置IP地址。DHCP/BOOTP服務為Bootloader分配IP地址,配置網絡參數,然後才能夠支持網絡傳輸功能。如果Bootloader可以直接設置網絡參數,就可以不使用DHCP。TFTP服務為Bootloader客戶端提供文件下載功能,把内核映像和其他文件放在/tftpboot目錄下。這樣Bootloader可以通過簡單的TFTP協議遠程下載内核映像到内存。

磁盤啟動方式

傳統的Linux系統運行在台式機或者服務器上,這些計算機一般都使用BIOS引導,并且使用磁盤作為存儲介質。如果進入BIOS設置菜單,可以探測處理器、内存、硬盤等設備,可以設置BIOS從軟盤、光盤或者某塊硬盤啟動。也就是說,BIOS并不直接引導操作系統。那麼在硬盤的主引導區,還需要一個Bootloader。這個Bootloader可以從磁盤文件系統中把操作系統引導起來。

Linux傳統上是通過LILO(LInux LOader)引導的,後來又出現了GNU的軟件GRUB(GRand Unified Bootloader)。這2種Bootloader廣泛應用在X86的Linux系統上。你的開發主機可能就使用了其中一種,熟悉它們有助于配置多種系統引導功能。LILO軟件工程是由Werner Almesberger創建,專門為引導Linux開發的。現在LILO的維護者是John Coffman,最新版本下載站點:。LILO有詳細的文檔,例如LILO套件中附帶使用手冊和參考手冊。此外,還可以在LDP的“LILO mini-HOWTO”中找到LILO的使用指南。

GRUB是GNU計劃的主要bootloader。GRUB最初是由Erich Boleyn為GNU Mach操作系統撰寫的引導程序。後來有Gordon Matzigkeit和Okuji Yoshinori接替Erich的工作,繼續維護和開發GRUB。GRUB的網站http://www.gnu.org/software/grub/上有對套件使用的說明文件,叫作《GRUB manual》。GRUB能夠使用TFTP和BOOTP或者DHCP通過網絡啟動,這種功能對于系統開發過程很有用。除了傳統的Linux系統上的引導程序以外,還有其他一些引導程序,也可以支持磁盤引導啟動。例如:LoadLin可以從DOS下啟動Linux;還有ROLO、LinuxBIOS,U-Boot也支持這種功能。

Flash啟動方式

大多數嵌入式系統上都使用Flash存儲介質。Flash有很多類型,包括NOR Flash、NAND Flash和其他半導體盤。其中,NOR Flash(也就是線性Flash)使用最為普遍。NOR Flash可以支持随機訪問,所以代碼是可以直接在Flash上執行的。Bootloader一般是存儲在Flash芯片上的。另外,Linux内核映像和RAMDISK也可以存儲在Flash上。通常需要把Flash分區使用,每個區的大小應該是Flash擦除塊大小的整數倍。

Bootloader一般放在Flash的底端或者頂端,這要根據處理器的複位向量設置。要使Bootloader的入口位于處理器上電執行第一條指令的位置。

接下來分配參數區,這裡可以作為Bootloader的參數保存區域。再下來内核映像區。Bootloader引導Linux内核,就是要從這個地方把内核映像解壓到RAM中去,然後跳轉到内核映像入口執行。然後是文件系統區。如果使用Ramdisk文件系統,則需要Bootloader把它解壓到RAM中。如果使用JFFS2文件系統,将直接挂接為根文件系統。最後還可以分出一些數據區,這要根據實際需要和Flash大小來考慮了。

這些分區是開發者定義的,Bootloader一般直接讀寫對應的偏移地址。到了Linux内核空間,可以配置成MTD設備來訪問Flash分區。但是,有的Bootloader也支持分區的功能,例如:Redboot可以創建Flash分區表,并且内核MTD驅動可以解析出redboot的分區表。除了NOR Flash,還有NAND Flash、Compact Flash、DiskOnChip等。這些Flash具有芯片價格低,存儲容量大的特點。但是這些芯片一般通過專用控制器的I/O方式來訪問,不能随機訪問,因此引導方式跟NOR Flash也不同。在這些芯片上,需要配置專用的引導程序。通常,這種引導程序起始的一段代碼就把整個引導程序複制到RAM中運行,從而實現自舉啟動,這跟從磁盤上啟動有些相似。

操作模式

大多數BootLoader都包含兩種不同的操作模式。“啟動加載”模式和“下載”模式,這種區别僅對于開發人員才有意義。但從最終用戶的角度看,BootLoader的作用就是用來加載操作系統,而并不存在所謂的啟動加載模式與下載工作模式的區别。

啟動加載(Boot loading)模式:這種模式也稱為“自主”(Autonomous)模式,也即BootLoader從目标機上的某個固态存儲設備上将操作系統加載到RAM中運行,整個過程并沒有用戶的介入。這種模式是BootLoader的正常工作模式。因此在嵌入式産品發布的時候,BootLoader顯然必須工作在這種模式下。

下載(Down loading)模式:在這種模式下目标機上的BootLoader将通過串口連接或網絡連接等通信手段從主機下載文件,比如:下載應用程序、數據文件、内核映像等.從主機下載的文件通常首先被BootLoader保存到目标機的RAM中然後再被BootLoader寫到目标機上的固态存儲設備中。BootLoader的這種模式通常在系統更新時使用。工作于這種模式下的BootLoader通常都會向它的終端用戶提供一個簡單的命令行接口。

在教學系統中提供的BootLoader中沒有實現自主模式,可以通過修改代碼來實現該功能。BootLoader與主機之間進行文件傳輸所用的通信設備及協議。

最常見的情況就是,目标機上的BootLoader通過串口與主機之間進行文件傳輸,傳輸可以簡單的采用直接數據收發,當然在串口上也可以采用xmode/ymode/zmode協議以及在以太網上采用TPTP協議。

此外,在論及這個話題時,主機方所用的軟件也要考慮。比如,在通過以太網連接和TFTP協議來下載文件時,主機方必須有一個軟件用來提供TFTP服務。

引導加載程序是系統加電後運行的第一段代碼。我們熟悉的PC中的引導程序一般由BIOS和位于MBR的OS bootloader(例如LILO或者GRUB)一起組成。然而在嵌入式系統中通常沒有像BIOS那樣的固件程序(有的嵌入式CPU有),因此整個系統的加載啟動任務就完全由bootloader來完成。在嵌入式Linux中,引導加載程序即等效為bootloader。

安裝位置

Boot loader就是在操作系統内核運行之前運行的一段小程序。通過這段小程序,可以初始化硬件設備、建立内存空間的映射圖,從而将系統的軟硬件環境帶到一個合适的狀态,以便為最終調用操作系統内核準備好正确的環境。

系統加電或複位後,所有的CPU通常都從某個預先安排的地址上取指令。例如,基于ARM7TDMI core 的CPU在複位時通常都從地址0x00000000取它的第一條指令。而基于CPU構建的嵌入式系統通常都有某種類型的固态存儲設備(比如:ROM、EEPROM、或Flash等)被映射到這個預先安排的地址上。因此在系統加電後,CPU将首先執行Bootloader程序。通常總是将Boot Loader安裝在嵌入式系統的存儲設備的最前端。

固态存儲設備的空間劃分(地址從低到高順序):Bootloader,Bootloader參數,内核映像,根文件系統映像。

bootloader是依賴于硬件而實現的,特别是在嵌入式系統中。不同的體系結構需求的bootloader是不同的;除了體系結構,bootloader還依賴于具體的嵌入式闆級設備的配置。也就是說,對于兩塊不同的嵌入式闆而言,即使它們基于相同的CPU構建,運行在其中一塊電路闆上的bootloader,未必能夠運行在另一塊電路開發闆上。

Bootloader的啟動過程可以是單階段的,也可以是多階段的。通常多階段的bootloader能提供更為複雜的功能,以及更好的可移植性。從固态存儲設備上啟動的bootloader大多數是二階段的啟動過程,也即啟動過程可以分為stage1和stage2兩部分。

編寫步驟

第一步:要進行相關硬件的初使化,比如在at91rm9200這塊嵌入式闆子上(以後都使用這一款芯片,主要是我對這款芯片比較熟悉,嘿嘿),大概要做接下來的幾方面的工作,其一:将CPU模式切換進系統模式,關閉系統中斷,關閉看門狗,根據具體情況進行内存内存内存的正式叫法是内存儲器,以此來與外存儲器區分開。CPU也稱為中央處理器,是電子計算機的主要設備之一。其功能主要是解釋計算機指令以及處理計算機軟件中的數據。所謂的計算機的可編程性主要是指對CPU的編程。CPU是計算機中的核心配件,隻有火柴盒那麼大,幾十張紙那麼厚,但它卻是一台計算機的運算核心和控制核心。計算機中所有操作都由CPU負責讀取指令,對指令譯碼并執行指令的核心部件。

CPU、内部存儲器和輸入/輸出設備是電子計算機的三大核心部件。物理上它安裝在計算機内部,通常安裝在主闆上,所以稱為内存。它的作用是供暫時存儲處理器需要處理的數據或處理後的結果,可見内存是計算機處理器的工作空間。它是處理器運行的程序和數據必須駐留于其中的一個臨時存儲區域,是計算機十分重要的部件。區域映射,初始化内存控制區,包括所使用的内存條的相關參數,刷新頻率等,其二:設定系統運行頻率,包括使用外部晶振晶振晶振:即所謂石英晶體諧振器和石英晶體時鐘振蕩器的統稱。不過由于在消費類電子産品中,諧振器用的更多,所以一般的概念中把晶振就等同于諧振器理解了。

後者就是通常所指鐘振,設置CPU頻率,設置總線總線總線是将信息以一個或多個源部件傳送到一個或多個目的部件的一組傳輸線。通俗的說,就是多個部件間的公共連線,用于在各個部件之間傳輸信息。人們常常以MHz表示的速度來描述總線頻率。頻率,設置外部設備所采用的頻率等。其三:設置系統中斷相關,包括定時器,定時器是裝有時段或時刻控制機構的開關裝置。它有一個頻率穩定的振蕩源,通過齒輪傳動或集成電路分頻計數,當将時間累加到預置數值時,或指示到預置的時刻處,定時器即發送信号控制執行機構。

中斷,是否使用FIQ中斷,外部中斷等,還有就是中斷優先級設置,這裡隻實現兩個優先級,隻有時鐘中斷高一級,其它都一樣,而中斷向量初始化時都将這些中斷向量指向0x18處,并關閉這裡的所有中斷,如果闆子還接有諸如FLASH設備的話,還需要設置諸如FLASH相關操制寄存器,其四:需要關閉CACHE,到此為止,芯片相關内容就完成初始化了。

中斷向量表,ARM的中斷與PC機芯片的中斷向量表有一點差異,嵌入式設備為了簡單,當發生中斷時,由CPU直接跳入由0x0開始的一部分區域(ARM芯片自身決定了它中斷時就會跳入0x0開始的一片區域内,具體跳到哪個地址是由中斷的模式決定的,一般用到的就是複位中斷,FIQ,IRQ中斷,SWI中斷,指令異常中斷,數據異常中斷,預取指令異常中斷),而當CPU進入相應的由0x0開始的向量表中時,這就需要用戶自己編程接管中斷處理程序了,這就是需要用戶自己編寫中斷向量表,中斷向量表裡存放的就是一些跳轉指令,比如當CPU發生一個IRQ中斷時,就會自動跳入到0x18處,這裡就是用戶自己編寫的一個跳轉指令,假如用戶在此編寫了一條跳轉到0x20010000處的指令,那麼這個地址就是一個總的IRQ中斷處理入口,一個CPU可能有多個IRQ中斷,在這個總的入口處如何區分不同的中斷呢?就由用戶編程來決定了,具體實現請參見以後相關部分,中斷向量表的一般用一個vector.S文件,當然,如何命名那是你自己的喜愛,但有一點需要聲明,那就是在鍊接時一定要将它定位在0x0處。

設置堆棧,一般使用三個棧,一個是IRQ棧,一個是系統模式下的棧(系統模式下和用戶模式共享寄存器和内存空間,這主要是為了簡單),設置棧的目的主要是為了進行函數調用和局部變量的存放,不可能全用彙編,也不可能不用局部變量。将自己以後的代碼段和數據段全部拷貝至内存,并将BSS段清零。

進行串口,串口是計算機上一種非常通用的設備通信協議,大多數計算機包含兩個基于RS232的串口。串口同時也是儀器儀表設備的通信協議,并可用于獲取遠程采集設備的數據的初始化(主要是為了與用戶交互,進行與PC機的文件傳輸),FLASH的初始化這裡在FLASH中存放BOOT和内核),FLASH驅動的編寫(這裡的驅動有别于平常所說的驅動,由于FLASH不像SDRAM,隻要設定了相關控制器之後就可以直接讀寫指定地址的數據,對FLASH的寫操作是一塊一塊數據進行,而不是一個字節一個字節地寫,具體請查閱相關資料)。

等待一定的秒數,來接收用戶進行輸入,如果在指定的秒數内用戶未輸入任何字符,那麼BOOT就開始在FLASH中的指定位置(可以由自己指定,這麼做主要是為了簡單)讀取内核的所有數據到内存中(具體是内存中的什麼位置由自己指定,也可以采用Linux之類的做法,就是在内存的起始位置加上一個0x8000處),将跳轉到内核的第一條代碼處);如果用戶在指定的秒數内鍵入了字符(這主要是為了方便開發,如果開發定型之後完全可以不要這段代碼),那麼就在串口與用戶進行交互,接受用戶在串口輸入的命令,比如用戶要求下載文件在FLASH中指定的位置等,具體内容可參考U-BOOT之類的開源項目到這裡為止,BOOT部分已完成,這個BOOT非常簡單,僅僅隻是将PC機上傳下來的文件固化到FLASH中,然後再将FLASH中的操作系統内核部分加載進内存中,并将CPU的控制權交給操作系統。

相關詞條

相關搜索

其它詞條