Winceにおける重位置決めpTOCについて話します。
26418 ワード
http://blog.chinaunix.net/u2/78978/showart_2251235.から回転して、作者に感謝します。
Ebootのmail.cファイルには次の文が必要です。
ROMHDR*const volatible pTOC=(ROMDR*)-1//Get replacced by romloader with real address.
この文の役割は、関数KernelRelocateにデータとコードの位置を再配置することです。
今ROMHDRの構造体に注目してください。typedef struct ROMHDR{ ULONG dll first ULONG dllast ULONG physfirst ULONG physlast ULONG nummods ULONG ulRAM Start ULONG ulRAM Free ULONG ulRAM End ULONG ulCopyEntries ULONG ulCopyOffset ULONG ulProfilLen ULONG ulProfileOffset; ULONG numfiles ULONG ulKernl Flags ULONG ulFSS RamPercent; ULONG ulDrivglobStart; ULONG ulDrivgloble; ULONG usCPU Type; ULONG usmiscFlags//miscellaneous flags PVOID pExtension; ULONG ul Tracking Start; ULONG ul Trackingle;ROMHDR;
ebootのboot loadermain関数にはROMHDR*volatile const pTOC=(ROMHDR*)-1があります。
Bootloaderは起動後、指定されたアドレスのramにカーネルをコピーすることが主な役割を果たします。bootコードはどのコードやデータを目的のアドレスにコピーする必要があるかを知っています。これは約束されたデータ構造に基づいてコピーされたものです。このデータ構造はROMDRです。ROMイメージが生まれたときはOS linkerで充填されています。
/Search for a valid ROMHDR.Thiscalback look s forsects that/ar 8 bytes long and ththat contain a“CECECE”signature.It then/enumerath all sectins looking for one whose ohose offset the the/MHfsetttttttttttttttttttttttthethe/thethethethethethe/thethethe/fofofoforerererererettttttttttttttttttttttttttttttttttttttttttttttttttttDR(unsigned_int 8*RomImage、DWORD FileSize、const CESectctheader*pSection){CESeSeSeSectHeadtersection HeaderLocal;if(!safeucopy(void*)§ion HeadLocal、(void*)psectiorictection、(void*Stortion)パフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスSeadLocal.Local、(Edededededededededededededededededestorororortion))パフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンス、(Entectitititictionation、(Entection)))SeSeSeSeSeSeSe{ return Continue Enumerating}unsigned_int 32 Contints Local[2];if(!safe cucopy(void*)&Contents Local[0]、(void*)&pSectic[1]、sizof((=Contntntntins Local){return ErorStopEEnteratmental;ift(Contents Local[0]==0 x 434545454545ininementttttttEEEEververververververververververververrerereretttttttttttttttttttttttttttttttttttttttttttttttttttttttEEEEEdedededeアクションヘッド(RomImage,FileSize,FindroMHDRFroomAddress)){/Enumerating completted success fully.Now…did we find a ROMHDR for our pSection?if(pROMDR){ return Success()else{ return Continue Enumerating;}return Errror_Stop Enumerating;
サービスはosイメージを不連続のromに入れることをサポートしています。またsdramは連続しなくてもいいです。この構造で一つ一つのmemoryを表示します。 typedef struct ROMChaingut{ struct ROMChaingut*pNext; ROMHDR*pTOC } ROMChaingut; これらの不連続なブロックをチェーンにします。具体的なドメインの意味はromimageと結合して*.bin/*.nb 0を生成する際に発生するlogファイルを見てください。例えばFirst DLL code Address:0400000 Last Dol code Address:0400 First Dol Address:020000 Last Dol Address Address000 Start of free RAM:8 c 0592000 End of RAM:8 c 100000 Number of Modules:1 Number of Copy Sectios:1 Copy Section Offset:8 c 03 ad84 FileSys 4 K Chunks/Mbyte:128<2 Mbte 128 2 2-4 Mbyte 0 4 4 4 4 4 Mbytate 0 4 4 4 4 4 4 4 4 4 4 Mbytytate 0 0 0>Tttttttttttttttttttttttttd 0 0 0 0 0 0 0 0 0 0 0>TTTtttttttttttttttttttttttttttttesed files size:0000
=================================================================================
romimage.exeはeboot.binの中のpTOC特殊ポインタをどのように充填しますか?
Ebootのmail.cファイルには次の文が必要です。
ROMHDR*const volatible pTOC=(ROMDR*)-1//Get replacced by romloader with real address.
この文の役割は、関数KernelRelocateにデータとコードの位置を再配置することです。
今ROMHDRの構造体に注目してください。typedef struct ROMHDR{ ULONG dll first ULONG dllast ULONG physfirst ULONG physlast ULONG nummods ULONG ulRAM Start ULONG ulRAM Free ULONG ulRAM End ULONG ulCopyEntries ULONG ulCopyOffset ULONG ulProfilLen ULONG ulProfileOffset; ULONG numfiles ULONG ulKernl Flags ULONG ulFSS RamPercent; ULONG ulDrivglobStart; ULONG ulDrivgloble; ULONG usCPU Type; ULONG usmiscFlags//miscellaneous flags PVOID pExtension; ULONG ul Tracking Start; ULONG ul Trackingle;ROMHDR;
ebootのboot loadermain関数にはROMHDR*volatile const pTOC=(ROMHDR*)-1があります。
Bootloaderは起動後、指定されたアドレスのramにカーネルをコピーすることが主な役割を果たします。bootコードはどのコードやデータを目的のアドレスにコピーする必要があるかを知っています。これは約束されたデータ構造に基づいてコピーされたものです。このデータ構造はROMDRです。ROMイメージが生まれたときはOS linkerで充填されています。
/Search for a valid ROMHDR.Thiscalback look s forsects that/ar 8 bytes long and ththat contain a“CECECE”signature.It then/enumerath all sectins looking for one whose ohose offset the the/MHfsetttttttttttttttttttttttthethe/thethethethethethe/thethethe/fofofoforerererererettttttttttttttttttttttttttttttttttttttttttttttttttttDR(unsigned_int 8*RomImage、DWORD FileSize、const CESectctheader*pSection){CESeSeSeSectHeadtersection HeaderLocal;if(!safeucopy(void*)§ion HeadLocal、(void*)psectiorictection、(void*Stortion)パフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンスSeadLocal.Local、(Edededededededededededededededededestorororortion))パフォーマンスパフォーマンスパフォーマンスパフォーマンスパフォーマンス、(Entectitititictionation、(Entection)))SeSeSeSeSeSeSe{ return Continue Enumerating}unsigned_int 32 Contints Local[2];if(!safe cucopy(void*)&Contents Local[0]、(void*)&pSectic[1]、sizof((=Contntntntins Local){return ErorStopEEnteratmental;ift(Contents Local[0]==0 x 434545454545ininementttttttEEEEververververververververververververrerereretttttttttttttttttttttttttttttttttttttttttttttttttttttttEEEEEdedededeアクションヘッド(RomImage,FileSize,FindroMHDRFroomAddress)){/Enumerating completted success fully.Now…did we find a ROMHDR for our pSection?if(pROMDR){ return Success()else{ return Continue Enumerating;}return Errror_Stop Enumerating;
サービスはosイメージを不連続のromに入れることをサポートしています。またsdramは連続しなくてもいいです。この構造で一つ一つのmemoryを表示します。 typedef struct ROMChaingut{ struct ROMChaingut*pNext; ROMHDR*pTOC } ROMChaingut; これらの不連続なブロックをチェーンにします。具体的なドメインの意味はromimageと結合して*.bin/*.nb 0を生成する際に発生するlogファイルを見てください。例えばFirst DLL code Address:0400000 Last Dol code Address:0400 First Dol Address:020000 Last Dol Address Address000 Start of free RAM:8 c 0592000 End of RAM:8 c 100000 Number of Modules:1 Number of Copy Sectios:1 Copy Section Offset:8 c 03 ad84 FileSys 4 K Chunks/Mbyte:128<2 Mbte 128 2 2-4 Mbyte 0 4 4 4 4 4 Mbytate 0 4 4 4 4 4 4 4 4 4 4 Mbytytate 0 0 0>Tttttttttttttttttttttttttd 0 0 0 0 0 0 0 0 0 0 0>TTTtttttttttttttttttttttttttttttesed files size:0000
=================================================================================
romimage.exeはeboot.binの中のpTOC特殊ポインタをどのように充填しますか?
eboot.bin eboot.nb0
eboot.bin pTOC , parser [ romimage.exe luther.gliethttp] ,
eboot.nb0 romimage.exe pTOC , eboot.nb0 KernelRelocate() ,
eboot.nb0 eboot.bin size .
eboot.nb0 pTOC , eboot.nb0 BootloaderMain()==>KernelRelocate(pTOC)
eboot.nb0 , KernelRelocate ADS section :
Image$$RO$$Limit
Image$$RW$$Base
Image$$ZI$$Base
Image$$ZI$$Limit
pTOC ROMHDR * volatile const pTOC = (ROMHDR *)-1; , .s ,
pTOC ? , romimage.exe .
romimage.exe WINCE500\PRIVATE\WINCEOS\COREOS\NK\TOOLS\ROMIMAGE\ROMIMAGE ,
C:\WINCE600\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
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
", 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 , eboot.nb0 pTOC romhdr_offset
...
}
c 0
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
", 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 pTOC = (void*)addr
}
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
// , , ,
// ,
for (loop = 0; loop < pTOC->ulCopyEntries; loop++)
{
//ulCopyOffset COPYentry
//COPYentry
// ulDest
// ulSource ROM
// ulCopyLen
// ulDestLen
//ulDestLen >=ulCopyLen
// ulDestLen ulCopyLen, , region 0
// ulDestLen ulCopyLen 0
// KernelRelocate 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
cmp r1, r3 ; Copy init data
ldrcc r2, [r0], #4
strcc r2, [r1], #4
bcc LoopRW
EndRW
mov r2, #0
LoopZI c 0
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);
}