void Launch(DWORD dwLaunchAddr)这个函数是在SMDK2440A\Src\Bootloader\Eboot\util.s(32)实现的
;******************************************************************************
INCLUDE kxarm.h
PHY_RAM_START EQU 0x30000000
VIR_RAM_START EQU 0x80000000
TEXTAREA
LEAF_ENTRY Launch
ldr r2, = PhysicalStart
ldr r3, = (VIR_RAM_START - PHY_RAM_START)
sub r2, r2, r3
mov r1, #0x0070 ; Disable MMU
mcr p15, 0, r1, c1, c0, 0
nop
mov pc, r2 ; Jump to PStart
nop
; MMU & caches now disabled.
PhysicalStart
mov r2, #0
mcr p15, 0, r2, c8, c7, 0 ; Flush the TLB
mov pc, r0 ; Jump to program we are launching.
根据C语言中void Launch(DWORD dwLaunchAddr),只有一个参数以及C和汇编函数调用的参数传递规则。
这个DWORD dwLaunchAddr应该传递给汇编中的r0。
但是我搞不明白这东西是怎么启动起来的。并且这个启动方法和优龙的有很大差别。
根据config.bib中的设置,这个内核开始的物理地址应该是)0x30200000
按照道理应该是直接运行PhysicalStart这个汇编段才能运行起来,但是怎么会在前面横插下面的代码呢?
ldr r2, = PhysicalStart
ldr r3, = (VIR_RAM_START - PHY_RAM_START)
sub r2, r2, r3
mov r1, #0x0070 ; Disable MMU
mcr p15, 0, r1, c1, c0, 0
nop
mov pc, r2 ; Jump to PStart
还有一个疑问,为什么eboot要在nboot之后开启MMU,但是在启动内核的时候又关闭MMU,不能在eboot把MMU都关闭吗?
这样做有什么好处?
------解决方案--------------------
问题的关键是在Disable MMU后必须在2条指令内执行mov pc操作,否则程序就跑飞
但是在真正跳转到NK地址前,还需要flush cache等操作
所以就先跳到PhysicalStart处,做完其他操作再跳到NK入口
------解决方案--------------------
- Assembly code
TEXTAREA LEAF_ENTRY Launch mov r10, r0 ; r0 : mov physical launch address bl INTERRUPTS_OFF ldr r1, =g_oalAddressTable ldr r0, =PhysicalStart mov r4, r0 bl PaFromVa ; find physical address of PhysicalStart cmp r0, #-1 ; found? movne r4, r0 ; yes, save real address mov r1, #0x0070 ; Disable MMU mcr p15, 0, r1, c1, c0, 0 ; MMU & caches now disabled. // excute nop ; // decode mov pc, r4 ; Jump to PStart // patch nopPhysicalStart mov r1, #0 mcr p15, 0, r1, c8, c7, 0 ; Flush the TLB mov pc, r10 ; Jump to program we are launching. ENTRY_END