boot loader 就是在作業系統核心運行之前運行的一段小程式。通過這段小程式,我們可以初始化硬體設備、建立記憶體空間的映射圖,從而將系統的軟硬體環境帶到一個合適的狀態,以便為最終調用作業系統核心準備好正確的環境。通常,boot loader 是嚴重地依賴於硬體而實現的,特別是在嵌入式世界。因此,在嵌入式世界裡建立一個通用的 boot loader 幾乎是不可能的。儘管如此,我們仍然可以對 boot loader 歸納出一些通用的概念來,以指導用戶特定的 boot loader 設計與實現。
操作模式,兼容性能,安裝媒介,程式流程,原理,
操作模式
大多數 boot loader 都包含兩種不同的操作模式:"啟動載入"模式和"下載"模式,這種區別僅對於開發人員才有意義。但從最終用戶的角度看,boot loader 的作用就是用來載入作業系統,而並不存在所謂的啟動載入模式與下載工作模式的區別。 啟動載入(boot loading)模式:這種模式也稱為"自主"(autonomous)模式。也即 boot loader 從目標機上的某個固態存儲設備上將作業系統載入到 ram 中運行,整個過程並沒有用戶的介入。這種模式是 boot loader 的正常工作模式,因此在嵌入式產品發布的時侯,boot loader 顯然必須工作在這種模式下。 下載(downloading)模式:在這種模式下,目標機上的 boot loader 將通過串口連線或網路連線等通信手段從主機(host)下載檔案,比如:下載核心映像和根檔案系統映像等。從主機下載的檔案通常首先被 boot loader 保存到目標機的 ram 中,然後再被 boot loader 寫到目標機上的flash 類固態存儲設備中。boot loader 的這種模式通常在第一次安裝核心與根檔案系統時被使用;此外,以後的系統更新也會使用 boot loader 的這種工作模式。工作於這種模式下的 boot loader 通常都會向它的終端用戶提供一個簡單的命令行接口。 像 blob 或 u-boot 等這樣功能強大的 boot loader 通常同時支持這兩種工作模式,而且允許用戶在這兩種工作模式之間進行切換。比如,blob 在啟動時處於正常的啟動載入模式,但是它會延時 10 秒等待終端用戶按下任意鍵而將 blob 切換到下載模式。如果在 10 秒內沒有用戶按鍵,則 blob 繼續啟動 linux 核心。
兼容性能
每種不同的 cpu 體系結構都有不同的 boot loader。有些 boot loader 也支持多種體系結構的 cpu,比如 u-boot 就同時支持 arm 體系結構和mips 體系結構。除了依賴於 cpu 的體系結構外,boot loader 實際上也依賴於具體的嵌入式板級設備的配置。這也就是說,對於兩塊不同的嵌入式板而言,即使它們是基於同一種 cpu 而構建的,要想讓運行在一塊板子上的 boot loader 程式也能運行在另一塊板子上,通常也都需要修改 boot loader 的源程式。
安裝媒介
系統加電或復位後,所有的 cpu 通常都從某個由 cpu 製造商預先安排的地址上取指令。比如,基於 arm7tdmi core 的 cpu 在復位時通常都從地址 0x00000000 取它的第一條指令。而基於 cpu 構建的嵌入式系統通常都有某種類型的固態存儲設備(比如:rom、eeprom 或 flash 等)被映射到這個預先安排的地址上。因此在系統加電後,cpu 將首先執行 boot loader 程式。 下圖就是一個同時裝有 boot loader、核心的啟動參數、核心映像和根檔案系統映像的固態存儲設備的典型空間分配結構圖。
圖 固態存儲設備的典型空間分配結構
圖 固態存儲設備的典型空間分配結構
程式流程
系統上電復位後, 在完成各種初始化配置後首先判斷0x500地址單元中值是否為0xff, 如果是,則說明系統從未下載過用戶程式, 系統會一直運行boot loader程式等待pc 機傳送下載命令; 如果0x500中的值不是0xff, 則說明系統中已經下載過用戶程式了, 這時候根據0x500中的值來設定定時器t imer2的初值並開始計時, 如果uart2 在指定的自舉周期內未接收到pc 機發來的下載命令(說明系統不需要下載程式), 系統會自動跳出boo tloader程式而去運行已有的用戶代碼, 如果uart2在自舉周期內接收到了下載命令, boo tloader程式會進入循環狀態等待pc機傳送數據。如圖所示。
圖 程式流程圖。 如前文所述, pc 機傳送的數據是從. hex 檔案中提取的, pc機首先傳送擴展地址部分, 下位機接收保存後會繼續等待接收32個指令字( 96位元組)並保存到ram 中, 然後根據接收到的地址擦除flash 存儲器中的1行, 擦除flash 是通過調用彙編函式e rasemem來進行的, 函式原型如下: mov# 0x4041, nvmcon ; 使nvmcon 暫存器為擦除flash模式 mov # 0x55, w 0 movw0, nvmkey mov # 0xaa, w0 movw 0, nvmkey ; 將0x55、0xaa 寫入密鑰暫存器 bsetnvmcon, #wr ; 開始擦除 nop nop return 擦除flash存儲器的一行後需要把接收到的32個指令字寫入到flash 存儲器寫鎖存器中, 這一過程可以通過函式w ritelatch 實現, 函式原型如下: movw0, tblpag ; 寫表暫存器 tb lw tlw3, 1] tb lw thw2, 1] ; 寫入鎖存器 return 這一步完成之後就可以將接收到的32個指令字寫入flash 存儲器了, 其方法與擦除flash 類似, 寫完一行後向pc 機傳送應答。待flash 存儲器全部寫完之後, pc 機會傳送表示結束下載的命令, 下位機接收後退出boo tloader程式, 進入新的用戶程式繼續運行, 從而完成整個線上自編程過程。
圖 程式流程圖。 如前文所述, pc 機傳送的數據是從. hex 檔案中提取的, pc機首先傳送擴展地址部分, 下位機接收保存後會繼續等待接收32個指令字( 96位元組)並保存到ram 中, 然後根據接收到的地址擦除flash 存儲器中的1行, 擦除flash 是通過調用彙編函式e rasemem來進行的, 函式原型如下: mov# 0x4041, nvmcon ; 使nvmcon 暫存器為擦除flash模式 mov # 0x55, w 0 movw0, nvmkey mov # 0xaa, w0 movw 0, nvmkey ; 將0x55、0xaa 寫入密鑰暫存器 bsetnvmcon, #wr ; 開始擦除 nop nop return 擦除flash存儲器的一行後需要把接收到的32個指令字寫入到flash 存儲器寫鎖存器中, 這一過程可以通過函式w ritelatch 實現, 函式原型如下: movw0, tblpag ; 寫表暫存器 tb lw tlw3, 1] tb lw thw2, 1] ; 寫入鎖存器 return 這一步完成之後就可以將接收到的32個指令字寫入flash 存儲器了, 其方法與擦除flash 類似, 寫完一行後向pc 機傳送應答。待flash 存儲器全部寫完之後, pc 機會傳送表示結束下載的命令, 下位機接收後退出boo tloader程式, 進入新的用戶程式繼續運行, 從而完成整個線上自編程過程。
原理
bootloader相當於pc主機板上的b ios, 是最底層的引導軟體。boo tloader是一段固化在嵌入式系統目標系統rom或者是諸如flash 等非易失存儲器中的一段程式, 它的主要作用就是引導作業系統或用戶程式的運行。系統上電後boo tloader將首先接管系統, 在進行一些最基本的上電自檢後, bootloader將對系統的硬體進行初始化, 為引導作業系統作好準備, 接下來, bootloader需要將作業系統的代碼拷貝到主存儲器的特定地址, 最後boot loader將控制權交給作業系統, 由作業系統完成接下來的工作;在不含作業系統的系統中, bootloader可以完成這樣一些操作: 分配程式存儲空間; 重新映射復位和中斷向量; 將程式代碼從片外載入到程式區, 執行時再將代碼載入到ram 中以便快速執行; 檢測是否需要下載新的用戶代碼, 若需要則通過某種通信方式接收新代碼並將其寫入指定程式存儲空間中, 若不需要, 則執行原有用戶代碼。