Boot Loader

Boot Loader 是在作業系統核心運行之前運行的一段小程式。通過這段小程式,我們可以初始化硬體設備、建立記憶體空間的映射圖,從而將系統的軟硬體環境帶到一個合適的狀態,以便為最終調用作業系統核心準備好正確的環境。通常,Boot Loader 是嚴重地依賴於硬體而實現的,特別是在嵌入式世界。因此,在嵌入式世界裡建立一個通用的 Boot Loader 幾乎是不可能的。儘管如此,我們仍然可以對 Boot Loader 歸納出一些通用的概念來,以指導用戶特定的 Boot Loader 設計與實現。

作用原理

⒈ 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 軟體在執行時通常會通過串口來進行輸入、輸出,比如:輸出列印信息到串口,從串口讀取用戶控制字元等。

⒋ Boot Loader 的啟動過程

BootLoader 的啟動過程可分為單階段(Single-Stage)和多階段(Multi-Stage)兩種。通常多階段的Boot Loader 具有更複雜的功能,更好的可移植性。從固態存儲設備上啟動的Boot Loader 大多採用兩階段,即啟動過程可以分為 stage1和stage2:stage1完成初始化硬體,為stage2準備記憶體空間,並將stage2複製到記憶體中,設定堆疊,然後跳轉到stage2。

⒌ Boot Loader 的操作模式 (Operation Mode)

大多數Boot Loader都包含兩種不同的操作模式。啟動載入模式和下載模式。

(1)啟動載入(Boot loading)模式:這種模式也稱為“自主”模式,也即Boot Loader從目標機上的某個固態存儲設備上將作業系統載入到RAM中運行,整個過程並沒有用戶的介入。這種模式是Boot Loader的正常工作模式。

(2)下載(Down loading)模式:在這種模式下目標機上的Boot Loader將通過串口連線或網路連線等通信手段從主機下載檔案。從主機下載的檔案通常首先被Boot Loader保存到目標機的RAM中然後再被Boot Loader寫到目標機上的固態存儲設備中。

⒍ Boot Loader 與主機之間進行檔案傳輸所用的通信設備及協定

分為兩種情況。一種是目標機使用串口與主機相連。這時的傳輸協定通常是xmodem/ymodem/zmodem中的一種。第二種可以用網路連線的方式傳輸檔案,這時使用的協定多為tftp。

解析

網上關於Linux的BOOTLOADER文章不少了,但是大都是vivi,blob等比較龐大的程式,讀起來不太方便,編譯出的檔案也比較大,而且更多的是面向開發用的引導代碼,做成產品時還要裁減,這一定程度影響了開發速度,對初學者學習開銷也比較大,在此分析一種簡單的BOOTLOADER,是在三星公司提供的2410 BOOTLOADER上稍微修改後的結果,編譯出來的檔案大小不超過4k,希望對大家有所幫助.

重要概念

COMPRESSED KERNEL and DECOMPRESSED KERNEL

壓縮後的KERNEL,按照文檔資料,現在不提倡使用DECOMPRESSED KERNEL,而要使用COMPRESSED KERNEL,它包括了解壓器.因此要在ram分配時給壓縮和解壓的KERNEL提供足夠空間,這樣它們不會相互覆蓋.

當執行指令跳轉到COMPRESSED KERNEL後,解壓器就開始工作,如果解壓器探測到解壓的代碼會覆蓋掉COMPRESSED KERNEL,那它會直接跳到COMPRESSED KERNEL後存放數據,並且重新定位KERNEL,所以如果沒有足夠空間,就會出錯.

Jffs2 File System

可以使armlinux套用中產生的數據保存在FLASH上,我的板子還沒用到這個.

RAMDISK

使用RAMDISK可以使ROOT FILE SYSTEM在沒有其他設備的情況下啟動.一般有兩種載入方式,最常用的一種是,把COMPRESSED RAMDISK IMAGE放到指定地址,然後由BOOTLOADER把這個地址通過啟動參數的方式ATAG_INITRD2傳遞給KERNEL.具體看代碼分析.

啟動參數(摘自IBM developer)

在調用核心之前,應該作一步準備工作,即:設定 Linux 核心的啟動參數。Linux 2.4.x 以後的核心都期望以標記列表(tagged list)的形式來傳遞啟動參數。啟動參數標記列表以標記 ATAG_CORE 開始,以標記 ATAG_NONE 結束。每個標記由標識被傳遞參數的 tag_header 結構以及隨後的參數值數據結構來組成。數據結構 tag 和 tag_header 定義在 Linux 核心源碼的include/asm/setup.h 頭檔案中.

在嵌入式 Linux 系統中,通常需要由 BOOTLOADER 設定的常見啟動參數有:ATAG_CORE、ATAG_MEM、ATAG_CMDLINE、ATAG_RAMDISK、ATAG_INITRD等。

(注)參數也可以用COMMANDLINE來設定,在我的BOOTLOADER里,我兩種都用了.

開發環境

CPU:S3C2410,BANK6上有64M的SDRAM(兩塊),BANK0上有32M NOR FLASH,串口當然是逃不掉的.這樣,按照數據手冊,地址分配如下:

0x4000_0000開始是4k的片內DRAM.

0x0000_0000開始是32M FLASH 16bit寬度

0x3000_0000開始是64M SDRAM 32bit寬度

注意:控制暫存器中的BANK6和BANK7部分必須相同.

0x4000_0000(片內DRAM)存放4k以內的BOOTLOADER IMAGE

0x3000_0100開始存放啟動參數

0x3120_0000 存放COMPRESSED KERNEL IMAGE

0x3200_0000 存放COMPRESSED RAMDISK

0x3000_8000 指定為DECOMPRESSED KERNEL IMAGE ADDRESS

0x3040_0000 指定為DECOMPRESSED RAMDISK IMAGE ADDRESS

開發環境:Redhat Linux,armgcc toolchain,armlinux KERNEL

如何建立armgcc的編譯環境:建議使用toolchain,而不要自己去編譯armgcc,偶試過好多次,都以失敗告終.

先下載arm-gcc 3.3.2 toolchain

將arm-linux-gcc-3.3.2.tar.bz2 解壓到 /toolchain

# tar jxvf arm-linux-gcc-3.3.2.tar.bz2

# mv /usr/local/arm/3.3.2 /toolchain

在makefile 中在把arch=arm CROSS_COMPILE設定成toolchain的路徑

還有就是INCLUDE = -I ../include -I /root/my/usr/local/arm/3.3.2/include.,否則庫函式就不能用了

啟動方式

可以放在FLASH里啟動,或者用Jtag仿真器.由於使用NOR FLASH,根據2410的手冊,片內的4K DRAM在不需要設定便可以直接使用,而其他存儲器必須先初始化,比如告訴memory controller,BANK6里有兩塊SDRAM,數據寬度是32bit,= =.否則memory control會按照復位後的默認值來處理存儲器.這樣讀寫就會產生錯誤.

所以第一步,通過仿真器把執行代碼放到0x4000_0000,(在編譯的時候,設定TEXT_BAS

E=0x40000000)

第二步,通過 AxD把linux KERNEL IMAGE放到目標地址(SDRAM)中,等待調用

第三步,執行BOOTLOADER代碼,從串口得到調試數據,引導armlinux

代碼分析

講了那么多執行的步驟,是想讓大家對啟動有個大概印象,接著就是BOOTLOADER內部的代碼分析了,BOOTLOADER文章內容網上很多,我這裡精簡了下,刪除了不必要的功能.

BOOTLOADER一般分為2部分,彙編部分和c語言部分,彙編部分執行簡單的硬體初始化,C部分負責複製數據,設定啟動參數,串口通信等功能.

BOOTLOADER的生命周期:

⒈ 初始化硬體,比如設定UART(至少設定一個),檢測存儲器= =.

⒉ 設定啟動參數,這是為了告訴核心硬體的信息,比如用哪個啟動界面,波特率 = =.

⒊ 跳轉到Linux KERNEL的首地址.

⒋ 消亡

同時在linux中 GRUB(GRand Unified Bootloader)是一個系統默認自帶的多重啟動管理器。它可以在多個作業系統共存時選擇引導哪個系統。儘管引導作業系統看上去是件平凡且瑣碎的任務,但它實際上很重要。如果引導裝入器不能很好地完成工作或者不具有彈性,那么就可能鎖住系統或者無法引導計算機……

相關詞條

相關搜尋

熱門詞條

聯絡我們