Windows CE 6.0 启动过程分析(2)

来源:互联网 发布:数据分析师考试报名费 编辑:程序博客网 时间:2024/05/17 00:09
3、KernelStart函数主要作用:
◆完成OEMAddressTable表中的物理地址到虚拟地址和虚拟地址到物理地址之间的映射;
◆对存储器页表和内核参数区存储空间(RAM或DRAM)进行清零处理。
◆读出CPU的ID号,内核需要根据该ID决定ARM的MMU处理,因为ARMV6和ARMV6之前的ARM处理器的MMU处理过程有所区别;
◆设置并开启MMU和Cache,因为在Startup函数关闭MMU和Cache;
◆设置ARM处理器工作模式的SP指针,ARM处理器共用7种不同的工作模式(USER、FIQ、IRQ、Supervisor、Abort、 Undefined、System),除用户模式(USER)和系统模式(System)之外,其他5种工作模式都有具有特定的SP指针寄存器(ARM处理器称其为影子寄存器);
◆读取内核启动所需要的KDataStruct结构体;
◆调用ARMInit函数重新定位Windows CE内核参数pTOC和初始化OEMInitGlobals全局变量;
◆利用mov pc, r12指令跳转到kernel.dll的入口位置,即NKStartup函数中。
$(_PRIVATEROOT)WINCEOS/COREOS/NK/LDR/ARM/armstart.s
LEAF_ENTRY KernelStart
    mov r11, r0 ;(r11) = &OEMAddressTable (save pointer)
    mov r1, r11 ;(r1) = &OEMAddressTable (2nd argument to VaFromPa)
    bl VaFromPa
    mov r6, r0 ;(r6) = VA of OEMAddressTable
    ; convert base of PTs to Physical address
    ldr r4, =PTs ;(r4) = virtual address of FirstPT
    mov r0, r4 ;(r0) = virtual address of FirstPT
    mov r1, r11 ;(r1) = &OEMAddressTable (2nd argument to PaFromVa)
    bl VaFromPa
    mov r10, r0 ;(r10) = ptr to FirstPT (physical)
    ; Zero out page tables & kernel data page
    mov r0, #0 ;(r0-r3) = 0''''s to store
    mov r1, #0
    mov r2, #0
    mov r3, #0
    mov r4, r10 ; (r4) = first address to clear
    add r5, r10, #KDEnd-PTs ; (r5) = last address + 1
18 stmia r4!, {r0-r3}
    stmia r4!, {r0-r3}
    cmp r4, r5
    blo %B18
    ; read the architecture information
    bl GetCpuId
    mov r5, r0 LSR #16 ; r5 >>= 16
    and r5, r5, #0x0000000f ; r5 &= 0x0000000f == architecture id
    add r4, r10, #HighPT-PTs ; (r4) = ptr to high page table
    cmp r5, #ARMv6 ; v6 or later?
    ; ARMV6_MMU
    orrge r0, r10, #PTL2_KRW + PTL2_SMALL_PAGE + ARMV6_MMU_PTL2_SMALL_XN
    ; (r0) = PTE for 4K, kr/w u-/- page, uncached unbuffered,
    nonexecutable
    ; PRE ARMV6_MMU;
    orrlt r0, r10, #PTL2_KRW + (PTL2_KRW << 2) + (PTL2_KRW << 4) + (PTL2_KRW << 6)
    ;Need to replicate AP bits into all 4 fields
    orrlt r0, r0, #PTL2_SMALL_PAGE + PREARMV6_MMU_PTL2_SMALL_XN
    ;(r0) = PTE for 4K, kr/w u-/- page, uncached unbuffered,
    nonexecutable
   str r0,[r4, #0xD0*4] ;store the entry into 4 slots to map 16K of primary page table
    add r0,r0, #0x1000 ;step on the physical address
    str r0,[r4, #0xD1*4]
    add r0,r0, #0x1000 ;step on the physical address
    str r0,[r4, #0xD2*4]
    add r0,r0, #0x1000 ;step on the physical address
    str r0,[r4, #0xD3*4]
    add r8,r10, #ExceptionVectors-PTs ;(r8) = ptr to vector page
    orr r0,r8, #PTL2_SMALL_PAGE ;construct the PTE (C=B=0)
    cmp r5,#ARMv6 ;v6 or later?
    ; ARMV6_MMU
    orrge r0, r0, #PTL2_KRW
    ; PRE ARMV6_MMU
    orrlt r0, r0, #PTL2_KRW + (PTL2_KRW << 2) + (PTL2_KRW << 4) + (PTL2_KRW << 6)
    ; Need to replicate AP bits into all 4 fields for pre-V6 MMU
    str r0,[r4, #0xF0*4] ;store entry for exception stacks and vectors
    ;other 3 entries now unused
    add r9,r10,#KPage-PTs ;(r9) = ptr to kdata page
    orr r0,r9,#PTL2_SMALL_PAGE ;(r0)=PTE for 4K (C=B=0)
    ; ARMV6_MMU (condition codes still set)
    orrge r0, r0, #PTL2_KRW_URO ; No subpage access control, so we must set this all to kr/w+ur/o
    ; PRE ARMV6_MMU
    orrlt r0, r0, #(PTL2_KRW << 0) + (PTL2_KRW << 2) + (PTL2_KRW_URO << 4)
    ;(r0) = set perms kr/w kr/w kr/w+ur/o r/o
    str r0, [r4, #0xFC*4] ;store entry for kernel data page
    orr r0,r4, #PTL1_2Y_TABLE ;(r0) = 1st level PTE for high memory section
    add r1, r10, #0x4000
    str r0, [r1, #-4] ; store PTE in last slot of 1st level table
    add r10, r10, #0x2000 ; (r10) = ptr to 1st PTE for "unmapped space"
    mov r0, #PTL1_SECTION
    orr r0, r0, #PTL1_KRW ;(r0)=PTE for 0: 1MB (C=B=0, kernel r/w)
20 mov r1, r11 ;(r1) = ptr to OEMAddressTable array (physical)
25 ldr r2,[r1],#4 ;(r2) = virtual address to map Bank at
    ldr r3,[r1],#4 ;(r3) = physical address to map from
    ldr r4,[r1],#4 ;(r4) = num MB to map
    cmp r4,#0 ;End of table?
    beq %F29
    ldr r12, =0x1FF00000
    and r2, r2, r12 ;VA needs 512MB, 1MB aligned.
    ldr r12, =0xFFF00000
    and r3, r3, r12 ;PA needs 4GB, 1MB aligned.
    add r2, r10, r2, LSR #18
    add r0, r0, r3 ;(r0) = PTE for next physical page
28 str r0, [r2],#4
    add r0, r0, #0x00100000 ;(r0) = PTE for next physical page
    sub r4, r4, #1 ;Decrement number of MB left
    cmp r4, #0
    bne %B28 ;Map next MB
    bic r0, r0,#0xF0000000 ;Clear Section Base Address Field
    bic r0, r0, #0x0FF00000 ;Clear Section Base Address Field
    b %B25 ;Get next element
29
    sub r10, r10, #0x2000 ;(r10) = restore address of 1st level page table
    ldr r12, =0xFFF00000 ;(r12) = mask for section bits
    and r1, pc, r12 ;physical address of where we are
    ;NOTE: we assume that the KernelStart function never spam
    across 1M boundary.
    orr r0, r1, #PTL1_SECTION
    orr r0, r0, #PTL1_KRW ;(r0) = PTE for 1M for current physical address, C=B=0, kernel r/w
    add r7, r10, r1, LSR #18 ;(r7) = 1st level PT entry for the identity map
    ldr r8, [r7] ;(r8) = saved content of the 1st-level PT
    str r0, [r7] ;create the identity map
    mov r1, #1
    mtc15 r1, c3 ;Setup access to domain 0 and clear other
    mtc15 r10, c2 ;setup translation base (physical of 1st level PT)
    mov r0, #0
    mcr p15, 0, r0, c8, c7, 0 ;Flush the I&D TLBs
    mfc15 r1, c1
    orr r1, r1, #0x007F ;changed to read-mod-write for ARM920 Enable: MMU, Align, DCache, WriteBuffer
    cmp r5, #ARMv6 ;r5 still set
   ; ARMV6_MMU
    orrge r1, r1, #0x3000 ;vector adjust, ICache
    orrge r1, r1, #1<<23 ;V6-format page tables
    orrge r1, r1, #ARMV6_U_BIT ;V6-set U bit, let A bit control unalignment support
    ; PRE ARMV6_MMU
    orrlt r1, r1, #0x3200 ;vector adjust, ICache, ROM protection
    ldr r0, VirtualStart
    cmp r0, #0 ;make sure no stall on "mov pc,r0" below
    mtc15 r1, c1 ;enable the MMU & Caches
    mov pc, r0 ;& jump to new virtual address
    nop
    VStart ldr r2, =FirstPT ;(r2) = VA of 1st level PT
    sub r7, r7, r10 ;(r7) = offset into 1st-level PT
    str r8, [r2, r7] ;restore the temporary identity map
    mcr p15, 0, r0, c8, c7, 0 ;Flush the I&D TLBs
    ; setup stack for each modes: current mode = supervisor mode
    ldr sp, =KStack
    add r4, sp, #KData-KStack ;(r4) = ptr to KDataStruct
    ; setup ABORT stack
    mov r1, #ABORT_MODE:OR:0xC0
    msr cpsr_c, r1 ;switch to Abort Mode w/IRQs disabled
    add sp, r4, #AbortStack-KData
    ; setup IRQ stack
    mov r2, #IRQ_MODE:OR:0xC0
    msr cpsr_c, r2 ;switch to IRQ Mode w/IRQs disabled
    add sp, r4, #IntStack-KData
    ; setup FIQ stack
    mov r3, #FIQ_MODE:OR:0xC0
    msr cpsr_c, r3 ;switch to FIQ Mode w/IRQs disabled
    add sp, r4, #FIQStack-KData
    ; setup UNDEF stack
    mov r3, #UNDEF_MODE:OR:0xC0
    msr cpsr_c, r3 ;switch to Undefined Mode w/IRQs disabled
    mov sp, r4 ;(sp_undef) = &KData
    ; switch back to Supervisor mode
    mov r0, #SVC_MODE:OR:0xC0
    msr cpsr_c, r0 ;switch to Supervisor Mode w/IRQs disabled
    ldr sp, =KStack
    ; continue initialization in C
    add r0, sp, #KData-KStack ;(r0) = ptr to KDataStruct
    str r6, [r0, #pAddrMap] ;store VA of OEMAddressTable in KData
    bl ARMInit ;call C function to perform the rest of initializations
    ; upon return, (r0) = entry point of kernel.dll
    mov r12, r0
    ldr r0, =KData
    mov pc, r12 ;jump to entry of kernel.dll
    VirtualStart DCD VStart
ENTRY_END KernelStart