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

本文探讨了eboot.bin与eboot.nb0之间的区别,重点在于pTOC结构体的作用及其如何影响全局变量的初始化过程。通过romimage.exe工具解析了pTOC的有效值来源,并详细介绍了eboot.nb0如何利用pTOC完成自我初始化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

<think>嗯,用户的问题是关于如何创建或编辑GeekOS项目0的Bochs配置文件,也就是.bochsrc文件。首先,我需要回忆一下Bochs模拟器的配置方法,以及GeekOS项目中的具体要求。 根据引用[3]中的信息,Bochs的配置文件类似于BIOS设置,需要指定硬件参数和启动顺序。用户可能已经安装了Bochs,但需要针对project0进行配置。接下来,我需要确定正确的配置内容,确保模拟器能够正确加载GeekOS内核。 然后,引用[2]提到在项目0中需要修改.bochsrc文件,但具体步骤可能没有详细说明。用户可能需要知道在哪里创建这个文件,如何编写配置选项,比如设置硬盘映像、内存大小、启动设备等。 另外,用户可能遇到的问题包括路径设置错误、配置语法不正确,或者启动顺序不对。需要提醒用户检查路径是否正确,特别是如果项目文件存放在特定目录下,比如/home或者用户自定义的目录。 还需要考虑用户的操作系统环境,比如是否在Linux下工作,使用哪些命令来创建和编辑文件。例如,使用touch创建文件,nano或vim编辑文件。 可能还需要引用项目文档中的示例配置,确保用户使用的选项与GeekOS的要求一致,比如megs、romimage、vgaromimage、boot等参数。 最后,验证步骤很重要,用户运行Bochs后如果出现黑屏或错误,需要检查配置文件是否正确,日志信息是否有提示错误的地方。例如,引用[3]提到配置错误可能导致无法启动,所以需要指导用户如何排查这些问题。</think>### 创建或编辑 GeekOS Project0 的 Bochs 配置文件 #### 1. **配置文件位置** - Bochs 模拟器通过读取 `.bochsrc` 文件完成硬件配置。该文件通常位于项目根目录下(例如 `/geekos/project0`)[^3]。 - 若文件不存在,需手动创建;若已存在,可直接修改。 #### 2. **配置文件内容** 以下是针对 GeekOS Project0 的典型配置模板: ```ini # Bochs 基础配置 megs: 32 # 分配32MB内存 romimage: file=$BXSHARE/BIOS-bochs-latest, address=0xf0000 vgaromimage: file=$BXSHARE/VGABIOS-lgpl-latest floppy_bootsig_check: disabled=0 # 硬盘配置 ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=disk, path="hdd.img", mode=flat, cylinders=40, heads=16, spt=63 # 启动设置 boot: disk # 从硬盘启动 log: bochslog.txt # 生成日志文件 display_library: x # 使用X11图形界面 panic: action=report error: action=report info: action=report debug: action=ignore ``` #### 3. **关键参数说明** - `path="hdd.img"`:需替换为项目实际硬盘镜像路径(例如 `/project0/hdd.img`)[^2]。 - `megs: 32`:GeekOS 推荐最小内存配置。 - `boot: disk`:确保系统从包含内核的硬盘镜像启动。 #### 4. **操作步骤** - **创建文件**: ```bash touch .bochsrc nano .bochsrc # 或使用vim/其他编辑器 ``` - **验证配置**: ```bash bochs -f .bochsrc -q # -f指定配置文件,-q跳过启动菜单 ``` #### 5. **常见问题排查** - **路径错误**:若提示 `hdd.img not found`,检查镜像文件路径是否与 `path` 参数一致。 - **权限问题**:使用 `chmod` 确保镜像文件可读。 - **配置语法**:冒号后需保留空格(如 `megs: 32` 而非 `megs:32`)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值