zoukankan      html  css  js  c++  java
  • CE5.0 romimage.exe如何填充eboot.bin中的pTOC特殊指针生成.nb0

    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);
    }

    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/chinesedragon2010/archive/2010/10/09/5929007.aspx

  • 相关阅读:
    C#(99):串口编程 System.IO.Ports.SerialPort类
    FastReport.Net的使用
    MongoDB(07):查询文档
    MongoDB(06):文档操作
    HIVE metastore Duplicate key name 'PCS_STATS_IDX' (state=42000,code=1061)
    RSync实现文件备份同步
    env: /etc/init.d/redis: Permission denied
    Multiple MySQL running but PID file could not be found
    centos 6.5卸载Mysql
    web应用性能测试-Tomcat 7 连接数和线程数配置
  • 原文地址:https://www.cnblogs.com/LoongEmbedded/p/5298873.html
Copyright © 2011-2022 走看看