CE5.0 - romimage.exe如何填充eboot.bin中的pTOC特殊指针生成.nb0

原文出处:http://blog.csdn.net/Embeddedfly


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大的原因[ luther. gliethttp] . 

eboot. nb0是一个包含全局变量初始化pTOC结构体 的文件, 所以当eboot. nb0启动时就可以通过BootloaderMain( ) = = > KernelRelocate( pTOC) 来
实现eboot. nb0自己初始化自己定义的全局变量的工作, 其实KernelRelocate就相当于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又是从哪里得到了有效的数值的呢?这就是我们下面继续讨论的问题, 一 切疑惑都可以从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指针所在位置[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 & 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这个有效空间[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中执行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

    // 就像这句话描述的一样,只有执行完该函数之后,全局变量所在地址处才有了真实的全局变量数值,

    // 所以只有执行完该函数之后,我们才能够访问全局变量[luther.gliethttp]

    for ( loop = 0; loop < pTOC- > ulCopyEntries; loop+ + ) 
    { 
//ulCopyOffset为若干个COPYentry结构体的内存 偏移地址

//COPYentry为全局变量描述结构体

//其中ulDest为全局变量被使用时的目的地址

//其中ulSource为全局变量被压缩存储在ROM中的起始地址

//其中ulCopyLen为全局变量真实个数长度

//其中ulDestLen为期望全局变量长度

//ulDestLen一定>=ulCopyLen

//如果ulDestLen大于ulCopyLen,那么说明,该 region的全局变量除了有非0数据之外

//还存在ulDestLen减去ulCopyLen字节的清0数据空 间[lutehr.gliethttp]

//其实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值全局变量[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 ) ; 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值