【原創】關於WinCE中bootloader:nboot/eboot的那點事兒

預備文章:

//-----------------------------------------------------------------------//

S3C2410&&WINCE6.0&&NBOOT

WinCE6.0的EBOOT概要

By: cnblogs-HJB

//-----------------------------------------------------------------------//

nk.bin和nk.nb0文件格式分析

By:Gooogleman

//-----------------------------------------------------------------------//

wince2秒快速啓動TOC分析

By:gliethttp

//-----------------------------------------------------------------------//

eboot, TOC,NK 地址跳轉的問題

By:CSDN-fan227

//-----------------------------------------------------------------------//

Wince bootloader和內核定製

By:kernel

//-----------------------------------------------------------------------//

2440從NANDFlash啓動之bootloader運行以前

By:rightsoft

//-----------------------------------------------------------------------//

NBOOT不能加載CE系統

By:驅動開發網-fishly_0

//-----------------------------------------------------------------------//

Nboot程序詳細分析

Nboot和Eboot中的虛擬地址與物理地址的關係

By:昔日之ID:formerman

//-----------------------------------------------------------------------//

【原創】關於WinCE中config.bib的問題

By:Mercury

//-----------------------------------------------------------------------//

好了,下面進入正文。昨天我們一起先看了下config.bib。於是我們就想更進一步。來在仔細研究下到底bootloader是有哪些事兒呢?

於是我們就找了上面的一些文章來看看。首先我們看HJB大牛的文章。文章很清晰的告訴了我們wince6.0下如何操作bootloader,下面我們再說一次,本人非常笨,不多說兩邊記不住,所以大家就忍受吧。首先系統要運行,需要一個引導程序,在以前有NOR flash,友善系列的開發板就是帶NOR這個東東,然後伴隨的是有一個vivisuper的loader,這裏我們不去細談這個,現在主流是nandflash,所以,對應的有一個nandflash的boot,我們叫他nboot,那我們再來看ARM,我們拿Samsung這個arm來做例子,在HJB大牛的文章中提及了,ARM自身有一個4K的空間來存儲應到程序,所以在上電之後通過一系列的配置,將nboot加載到ARM 4k的空間裏去執行,nboot就開始對系統的nandflash,內存,USB等等只要是你想初始化的設備進行一個初始化,這裏的初始化程度就看你自己寫的初始化程序了,按需所設計。接下來是nboot的重要使命,去叫eboot或者直接叫nk,然後結束自己的生命週期。

這裏要特別說的是,在上一篇文章完結後,有個朋友問我nboot怎麼去找到nk或者eboot在nandflash裏的地址啊?這個問題一下也把我問懵了。百思不得其解,看nboot的程序裏面到處都是什麼loadaddress,或者是jumpaddress之類的東西,以爲那個就是,後來根據以上一些文章的閱讀發現,其實那些地址只是SDRAM和ARM直接一個虛擬和實際物理地址。根本不是nandflash裏的地址。

那如何去從nandflash裏面找到我們要的eboot或者image呢?這個時候被我們忽略的TOC蹦出來了,大叫道那些東西都是我扒的。這個時候我們就仔細來看看gliethttp的文章,關於wince TOC啓動的文章,這裏gliethttp給我們詳細介紹了兩個結構體:TOC和_IMAGE_DESCRIPTOR,具體這兩個結構體的分析我們這裏也貼出來,給這兩扒東西的留個紀念,並給出一些註釋,註釋來自gliethttp,具體如下:

   1:  


typedef struct

_TOC
   2:  


{
   3:  


//和CSW中的認證域類似,只用來驗證接下去內容的合法

   4:  


DWORD dwSignature;
   5:  


//包含image的索引(我的是1)、啓動delay時間、ip地址、MAC地址和掩碼等

   6:  


BOOT_CFG BootCfg;
   7:  


//用來描述3個之多的ce內核image數組,我用的是id[1]

   8:  


IMAGE_DESCRIPTOR id[MAX_TOC_DESCRIPTORS];
   9:  


CHAININFO chainInfo;
  10:  


} TOC, *PTOC; // 512 字節

  11:  


 
  12:  


typedef struct
_IMAGE_DESCRIPTOR
  13:  


{
  14:  


DWORD dwVersion; //編譯時的版本號

  15:  


DWORD dwSignature; //“EBOOT”或“CFSH”等

  16:  


UCHAR ucString[IMAGE_STRING_LEN];
            //描述字符串:如"eboot.nb0"之類


  17:  


DWORD dwImageType; //image的類型nk.nb0爲0x04

  18:  


DWORD dwTtlSectors; //image文件用到的NAND的扇區總數

  19:  


DWORD dwLoadAddress; //image加載時的虛擬地址

  20:  


DWORD dwJumpAddress; //image加載完成後的跳轉地址

  21:  


SG_SECTOR sgList[MAX_SG_SECTORS];
          //image的段描述,包括起始扇區號和所需扇區數目


  22:  


ULONG dwStoreOffset;
} IMAGE_DESCRIPTOR, *PIMAGE_DESCRIPTOR;

這兩個相依爲命的結構體是扒eboot和image的罪魁禍首。他們到底是怎麼扒的呢,在gliethttp文中介紹道:並不需要一次性將所有nk.nb0數據都加載到內存,應該按需加載,那就是ce的鏡像文件image“按需加載”[“段式加載”]方式,TOC就是用來描述ce內核鏡像文件image的xipkernel段核心結構體,我們只需加載核文件xipkernel就能正常啓動進入wince界面。

好了,到此爲止我們搞清楚了原理了,那內存SDRAM和ARM之間的地址又回到了重要的位置,我們怎麼去設定這個地址呢?首先我們可以看下最新的mini2440 nboot的寫法,首先是給出幾個固定的地址,也就是原始的物理地址和起始地址,一般的情況下大家可以在oemaddrtab_cfg.inc中的對照表中找到SDRAM的地址映射,一般情況下是類似如下的描述:

   1:  

DCD 0x80000000, 0x30000000, 64
   2:  

; 64 MB DRAM BANK 6

好了,這完成了第一步,第二步我們來寫個比較簡單的小程序,如何把虛擬地址轉換成實際物理地址呢,這裏又回到mini2440的最新5.0代碼或者6.0代碼中,有一句這樣的話,寫的很好:

 

   1:  


#define
VIRTUAL_TO_PHYSICAL(va) ( ( (va>0x8c000000) ? (va-0xc000000) : (va) ) - VA_BASE + _RAM_STARTADDRESS )

這裏作出了一個判斷,保證了地址的大小。同時也轉換了地址。

這樣一來我們知道如何在兩個地址之間轉換了,不過這個事情其實是在內存管理單元沒有工作的情況下要用一下。當MMU工作了這個事情按照常理是交給MMU處理了.這些都是後話,我們繼續看,有了TOC有了地址轉換的工具,那地址到底在哪裏呢?

現在我們在來看看gooogleman的文章,做wince開發驅動的應該都會用pb自帶的一個命令行,這個是很好用的,有的時候makeimg啊,notepad一個什麼文件什麼的,很方便,這裏gooogleman帶我們回憶了一個非常重要,但是又往往被我們忽略的一個命令:viewbin,有了這個東東,我們可以仔細的看看我們要引導的eboot.bin或者nk.bin的起始地址是多少了。方法很簡單,直接viewbin nk.bin或者viewbin eboot.bin就可以了。起始地址,長度以及開始位置都列的很清晰,而這些個信息我們在TOC扒的時候已經全然送到他們該送的地方去了,系統自己該JUMP的也就JUMP過去,該Lunch的也就去Lunch過去,最新的會自己Run過去,呵呵這個完全看自己寫的了。都是一樣,無非是用一個指針指去那個地址,下面給個參考例子,我們就RUN過去,首先定義下怎麼個run法:

首先初始化一下我們的run

   1:  


#define
DOWNLOAD_ADDRESS 0x30138000
   2:  


void

(*run)(void
)=(void
(*)(void
))(DOWNLOAD_ADDRESS);

然後我們通過TOC給run加速,一般是在char ReadImageFromNand(unsigned int dwEntry)這個函數中

   1:  


run = (void
(*)(void
))(pToc->id[dwEntry].dwJumpAddress ? VIRTUAL_TO_PHYSICAL(pToc->id[dwEntry].dwJumpAddress) :

最後我們要在main函數裏run起來

   1:  


if
(run) run();

這句話說的很好聽,如果想跑你就跑吧。

好了。到此爲止該run到eboot了就去run eboot了,該run image就去run image了。

這裏補充下,其實eboot也是一樣,eboot起來也就是去run image,這個看設計的要求來定,理論是一樣的。

其他的文章對nboot+eboot+image模式進行了詳細的闡述,大家可以自己閱讀,這裏不多說了。

祝賀大家run的愉快。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章