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
)
;
}
CE5.0 - romimage.exe如何填充eboot.bin中的pTOC特殊指针生成.nb0
最新推荐文章于 2025-08-19 18:52:07 发布
4124

被折叠的 条评论
为什么被折叠?



