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.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 &copy_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);
}