CE5.0 - romimage.exe如何填充eboot.bin中的pTOC特殊指针生成.nb0
eboot.bin和eboot.nb0的差別就是
eboot.bin中沒有填充pTOC結(jié)構(gòu)體,必須使用parser解釋器[類似于romimage.exe luther.gliethttp]將全局變量數(shù)據(jù)段解壓釋放到運行時使用的地址才行,
eboot.nb0中經(jīng)過romimage.exe填充了pTOC結(jié)構(gòu)體,所以eboot.nb0可以自己將自己用到的全局量通過KernelRelocate()函數(shù)進行解壓釋放,這就是為什么
eboot.nb0比eboot.bin的size大的原因[luther.gliethttp].
eboot.nb0是一個包含全局變量初始化pTOC結(jié)構(gòu)體的文件,所以當(dāng)eboot.nb0啟動時就可以通過BootloaderMain()==>KernelRelocate(pTOC)來
實現(xiàn)eboot.nb0自己初始化自己定義的全局變量的工作,其實KernelRelocate就相當(dāng)于ADS啟動匯編中對如下四個section的操作:[luther.gliethttp]
Image$$RO$$Limit
Image$$RW$$Base
Image$$ZI$$Base
Image$$ZI$$Limit
但是我們在源程序中只能找到pTOC的定義ROMHDR * volatile const pTOC = (ROMHDR *)-1;根本找不到對它進行賦值的任何操作,無論是.s匯編還是任何宏中,
那pTOC又是從哪里得到了有效的數(shù)值的呢?這就是我們下面繼續(xù)討論的問題,一切疑惑都可以從romimage.exe中獲得答案.[luther.gliethttp]
romimage.exe源碼位于WINCE500/PRIVATE/WINCEOS/COREOS/NK/TOOLS/ROMIMAGE/ROMIMAGE目錄下,
C:/WINCE500/PRIVATE/WINCEOS/COREOS/NK/TOOLS/ROMIMAGE/ROMIMAGE/module.cpp|118| if(token == "pTOC"){
void Module::check_special_symbol(string token, DWORD o32_section, DWORD offset, MemoryList &memory_list){
??? ...
??? if(is_kernel()){
??????? if(token == "pTOC"){
//我們在eboot源碼PLATFORM/SMDK2440A/Src/Bootloader/Eboot_usb/blcommon.c中定義了該符號,如下:
//ROMHDR * volatile const pTOC = (ROMHDR *)-1; // Gets replaced by RomLoader with real address
//記錄pTOC指針?biāo)谖恢肹luther.gliethttp]
????????? m_TOC_offset = offset + m_load_offset; // doesn't get load offset added, because only compared with rva later
????????? LAST_PASS_PRINT printf("Found pTOC at %08x/n", m_TOC_offset);
??????? }
??????? if(needs_signing()){
????????? if(token == "OEMIoControl")
??????????? s_oem_io_control = offset + m_初始化c代碼定義的非0值全局變量[luther.gliethttp]load_offset - page_size();
??????? }
??????? ...
??? }
??? ...
}
bin.cpp|87| kernel->write_TOC_ptr(romhdr_offset);
bool write_bin(AddressList &hole_list, CopyList ©_list,
??????????????? ModuleList &module_list, FileList &file_list,
??????????????? MemoryList &memory_list, MemoryList &reserve_list,
??????????????? ModuleList::iterator &kernel, Config &config, MemoryList::iterator xip_mem){
??? ...
??? // write toc into kernel
??? if(xip_mem->is_kernel() && kernel->is_kernel())
??????? kernel->write_TOC_ptr(romhdr_offset);//將romimage.exe計算后的toc起始地址存入pTOC 指針?biāo)谔?這樣eboot.nb0中的pTOC指針就指向了romhdr_offset這個有效空間[luther.gliethttp].
??? ...
}
初始化c代碼定義的非0值全局變量[luther.gliethttp]
void Module::write_TOC_ptr(DWORD addr){
? assert(is_kernel());
? if(!m_TOC_offset){
??? fprintf(stderr, "Error: Found NULL or missing TOC pointer for %s/n", m_name.c_str());
??? exit(1);
? }
?
// *(DWORD *)(m_o32_list[0].data.ptr() + m_TOC_offset - page_size()) = addr;
? *(DWORD *)rva2ptr(m_TOC_offset) = addr;//等效于eboot.nb0中執(zhí)行pTOC = (void*)addr;[luther.gliethttp]
}
來看看eboot.nb0是怎么使用pTOC來初始化eboot.bin定義的全局變量的:
main
==>BootloaderMain()
==>KernelRelocate(pTOC)
typedef struct COPYentry {
??? ULONG ulSource; // copy source address
??? ULONG ulDest; // copy destination address
??? ULONG ulCopyLen; // copy length
??? ULONG ulDestLen; // copy destination length
??????????????????????????????????? // (zero fill to end if > ulCopyLen)
} COPYentry;
//
// KernelRelocate: move global variables to RAM
//
static BOOL KernelRelocate (ROMHDR *const pTOC)
{
??? ULONG loop;
??? COPYentry *cptr;
??? if (pTOC == (ROMHDR *const) -1)
??? {
??????? return (FALSE); // spin forever!
??? }
??? // This is where the data sections become valid... don't read globals until after this
??? // 就像這句話描述的一樣,只有執(zhí)行完該函數(shù)之后,全局變量所在地址處才有了真實的全局變量數(shù)值,
??? // 所以只有執(zhí)行完該函數(shù)之后,我們才能夠訪問全局變量[luther.gliethttp]
??? for (loop = 0; loop < pTOC->ulCopyEntries; loop++)
??? {
//ulCopyOffset為若干個COPYentry結(jié)構(gòu)體的內(nèi)存偏移地址
//COPYentry為全局變量描述結(jié)構(gòu)體
//其中ulDest為全局變量被使用時的目的地址
//其中ulSource為全局變量被壓縮存儲在ROM中的起始地址
//其中ulCopyLen為全局變量真實個數(shù)長度
//其中ulDestLen為期望全局變量長度
//ulDestLen一定>=ulCopyLen
//如果ulDestLen大于ulCopyLen,那么說明,該region的全局變量除了有非0數(shù)據(jù)之外
//還存在ulDestLen減去ulCopyLen字節(jié)的清0數(shù)據(jù)空間[lutehr.gliethttp]
//其實KernelRelocate就相當(dāng)于ADS中如下匯編代碼:
/* add r2, pc,#-(8+.-CInitData) ; @ where to read values (relative)
??? ldmia r2, {r0, r1, r3, r4}
??
??? cmp r0, r1 ; Check that they are different
??? beq EndRW
LoopRW 初始化c代碼定義的非0值全局變量[luther.gliethttp]
??? cmp r1, r3 ; Copy init data
??? ldrcc r2, [r0], #4
??? strcc r2, [r1], #4
??? bcc LoopRW
EndRW
??? mov r2, #0
LoopZI 初始化c代碼未定義的全局變量或者強行指定為0值的全局變量[luther.gliethttp]
??? cmp r3, r4 ; Zero init
??? strcc r2, [r3], #4
??? bcc LoopZI
?
??? b EndInitC
??????????????
CInitData
???? IMPORT |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)
??? IMPORT |Image$$RW$$Base| ; Base of RAM to initialise
??? IMPORT |Image$$ZI$$Base| ; Base and limit of area
??? IMPORT |Image$$ZI$$Limit| ; Top of zero init segment
??
??? DCD |Image$$RO$$Limit| ; End of ROM code (=start of ROM data)
???? DCD |Image$$RW$$Base| ; Base of RAM to initialise
???? DCD |Image$$ZI$$Base| ; Base and limit of area
???? DCD |Image$$ZI$$Limit| ; Top of zero init segment
*/
??????? cptr = (COPYentry *)(pTOC->ulCopyOffset + loop*sizeof(COPYentry));
??????? if (cptr->ulCopyLen)
??????????? memcpy((LPVOID)cptr->ulDest,(LPVOID)cptr->ulSource,cptr->ulCopyLen);
??????? if (cptr->ulCopyLen != cptr->ulDestLen)
??????????? memset((LPVOID)(cptr->ulDest+cptr->ulCopyLen),0,cptr->ulDestLen-cptr->ulCopyLen);
??? }
??? return (TRUE);
}
?
本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/chinesedragon2010/archive/2010/10/09/5929007.aspx
《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀總結(jié)
以上是生活随笔為你收集整理的CE5.0 - romimage.exe如何填充eboot.bin中的pTOC特殊指针生成.nb0的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WINCE6.0+S3C2443的启动过
- 下一篇: NK.bin和NK.nb0学习