⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 init.asm

📁 WinCE5.0部分核心源码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
        ; get the address of KData
        mov     eax, OFFSET32 _KData
        call    PaFromVa
        ; (eax) = PA of KData
        mov     dword ptr [eax+OFFSET_MEM_FOR_PT], SYSTEM_PAGES; MemForPT = memeory used for system pages
        mov     dword ptr [eax+OFFSET_CPU_CAP], edi  ; save CPU capability bits

        ; setup esp to use KStack (physical here)
        mov     esp, eax
        sub     esp, 4                          ; esp = &KData - 4 == &KSTack

        ; save the VA of OEMAddressTable onto stack
        mov     eax, esi
        call    VaFromPa                        ; (eax) = VA of OEMAddressTable upon return
        mov     dword ptr [esp], eax            ; save address of OEMAddressTable on stack
                                                ; NOTE: since push is pre-decrement, the conent
                                                ;       won't be over-written by "push" operation

        ; Figure out pTOC->ulRamFree
        mov     eax, OFFSET32 _pTOC             ; (eax) = VA of &pTOC
        call    PaFromVa                        ; (eax) = PA of &pTOC

        mov     eax, dword ptr [eax]            ; (eax) = VA of pTOC
        call    PaFromVa                        ; (eax) = PA of pTOC
        
        mov     eax, dword ptr [eax+OFFSET_ULRAMFREE] ; (eax) = VA free RAM
        push    eax                             ; save the VA of Page Directory onto stack
        call    PaFromVa                        ; (eax) = PA of free RAM

        ; (eax) = PA of the beginning of the free RAM
        ; 1st pages of Free RAM is going to be used as Page Directory
        mov     ebx, eax                        ; (ebx) = PA of Page Directory
        mov     edx, edi                        ; (edx) = cpu capability bits

        ; clear the system pages
        cld
        mov     ecx, ZERO_BLOCK_SIZE / 4
        mov     edi, ebx
        xor     eax, eax
        rep     stosd

        ; (edx) = CPU capaibility
        test    edx, CPUID_PSE
        jnz     short Use4MPage

        ;
        ; no 4M page support, use 4k pages
        ;
        
        ; calculate size for Page Tables
        mov     ecx, esi                        ; (ecx) = OEMPageTable
        xor     edi, edi                        ; size init to 0

cntNext:
        add     edi, [ecx+8]                    ; (edi) = accumulated size

        ; round up to multiple of 4M
        add     edi, 0003fffffh                 ; round up to multiple of 4M
        and     edi, 0ffc00000h                 ; 
        
        add     ecx, 12                         ; (ecx) = next OEMPageTable Entry
        cmp     dword ptr [ecx], 0
        jne     short cntNext
        
        ; (edi) = total memory sizes

        shr     edi, 9                          ; (edi) = size of page tables
                                                ;       = (size / 4M) * 2 * PAGE_SIZE

        ; update KData.nMemForPT
        mov     eax, OFFSET32 _KData            ; (eax) = VA of KData
        call    PaFromVa
        add     dword ptr [eax+OFFSET_MEM_FOR_PT], edi ; update KData.nMemForPT

        mov     edx, ebx                        ; (edx) = PA of free RAM
        add     edx, SYSTEM_PAGES               ; skip the system pages
        mov     eax, esi                        ; (eax) = OEMPageTable
NextTable4K:
        Call    FillPD4K                        ; fill the page talbe for one entry
        mov     ecx, dword ptr [eax+8]          ; (ecx) = size of the entry
        shr     ecx, 9                          ; (ecx) = size of page tables for this entry
                                                ;       = (size / 4M) * 2 * PAGE_SIZE
        add     edx, ecx                        ; (edx) = next page table entry
        add     eax, 12                         ; (eax) = next OEMPageTableEntry
        cmp     dword ptr [eax], 0
        jne     short NextTable4K

        jmp     short DoneSettingPD


Use4MPage:
        ;
        ; with 4M page support, use 4M page
        ; (edx) = CPU capability bits

        ; figure out PDE bits
        mov     eax, edx                        ; (eax) = cpu capability bits
        mov     edx, PDE_PS                     ; (edx) = support 4M page bit for PDE
        test    eax, CPUID_PGE                  ; support global page?
        jz      short SetupPDE4M
        or      edx, PDE_G

SetupPDE4M:
        ; setup page directory
        mov     eax, esi
NextTable4M:
        Call    FillPD4M
        add     eax, 12                         ; (eax) = next OEMPageTableEntry
        cmp     dword ptr [eax], 0
        jne     short NextTable4M


.586p

CR4_PSE         EQU     010H
CR4_PGE         EQU     080H

        mov     ecx, CR4_PSE                    ; 4M page enabled
        test    edx, PDE_G                      ; support global page?
        jz      short SetupCr4
        
        ; yes, support Global Page
        or      ecx, CR4_PGE

SetupCr4:
        ; update CR4
        mov     eax, cr4
        or      eax, ecx
        mov     cr4, eax
.486p

DoneSettingPD:

        cld
        
        ; Setup value in  Syscall page
        mov     edi, ebx                        ;
        add     edi, SYSPAGE_SYSCALL            ; (edi) = PA of Syscall page
        mov     eax, 20cd20cdh                  ; (eax) = int 0x20 x 2
        mov     ecx, 1024                       ; fill syscall page with int 0x20 instructions
        rep     stosd

        ; Setup value in  SyscallDir
        mov     edi, ebx                        ;
        add     edi, SYSPAGE_SYSCALLDIR         ; (edi) = PA of Syscall page directory
        mov     edx, edi                        ; (edx) = PA of Syscall page directory
        mov     eax, ebx                        
        add     eax, SYSPAGE_SYSCALL+PAGE_ATTRIB_RO_USER  ; (eax) = Page directory entry of Syscall page directory
        mov     ecx, 1024                       ; every entry in SyscallDir point to to same Page (syscall page)
        rep     stosd

        ; setup page directory for syscall dir
        add     edx, PAGE_ATTRIB_RO_USER        ; (edx) = page directory entry for syscall directory
        mov     DWORD PTR [ebx][0FFCh], edx     ; setup global page directory
        
        ;
        ; Create the identity-mapped addresses (physical = linear), because
        ; Pentium-II requires that once paging is enabled, the next instruction
        ; must come from the same address as if paging wasn't enabled.
        ;       
        ; First, the mapping for the eip register.
        ;
        mov     eax, OFFSET32 PagingEnabled
        call    PaFromVa                
        mov     edi, eax                        ; (edi)  = PA of PageEnabled

        ; Next, the mapping for the gdt.
        sub     esp, 8
        sgdt    [esp]
        mov     eax, dword ptr 2[esp]
        add     esp, 8

        ; (eax) = PA of gdtBase                 ; save PA of gdtbase
        push    eax

        ;
        ; the value for gdtBase is 0xffffffff!!!!
        ; not a physical address at all
        ;
      
        ;call    VaFromPa                        ; (eax) = VA of gdtbase
        sub     eax, LIN_TO_PHYS_OFFSET

        mov     ecx, OFFSET32 PagingEnabled     ; (ecx) = VA of PageEnabled
        mov     edx, edi                        ; (edx) = PA of PageEnabled

        pop     edi                             ; (edi) = PA of gdtbase
        
        ;
        ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        ; !!! from here on, esi no longer points to OEMAddressTable
        ; !!! ANY CALL after this TO PaFromVa / VaFromPa will FAIL
        ; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        ;
        mov     esi, eax                        ; (esi) = VA of gdtbase

        ;
        ; ECX = current linear addr, EDX = current physical addr.
        ;
        shr     ecx, 22                 ; Which 4MB?
        shl     ecx, 2                  ; DWORD index
        shr     edx, 22                 ; Which 4MB?
        shl     edx, 2                  ; DWORD index

        ;
        ; ESI = linear gdtbase, EDI = physical gdtbase.
        ;
        shr     esi, 22                 ; Which 4MB?
        shl     esi, 2                  ; DWORD index
        shr     edi, 22                 ; Which 4MB?
        shl     edi, 2                  ; DWORD index

        ;
        ; Save off the original page directory entry for the physical address.
        ;
        push    DWORD PTR [ebx][edx]
        push    DWORD PTR [ebx][edi]
        ;
        ; Copy the page directory entry for the current linear 
        ; address to the physical address.
        ;
        mov     eax, DWORD PTR [ebx][ecx]
        and     eax, not PDE_G          ; only works if PDE_G implies PDE_PS
        mov     DWORD PTR [ebx][edx], eax
        mov     eax, DWORD PTR [ebx][esi]
        and     eax, not PDE_G          ; only works if PDE_G implies PDE_PS
        mov     DWORD PTR [ebx][edi], eax
        ;
        ; Get the saved values off the stack.
        ;
        mov     cr3, ebx
        pop     ebx                     ; Original pde value for gdtbase
        pop     ebp                     ; Original pde value for PagingEnabled
        ;
        ; We are now identity-mapped, okay to enable paging.
        ;
        mov     esi, OFFSET32 PagingEnabled
        mov     eax, cr0
        or      eax, PG_MASK OR WP_MASK ; enable paging & write-protection for Ring0
        and     eax, not 060000000h     ; clear cache disable & cache write-thru bits
        align   16
        mov     cr0, eax
        jmp     esi
        align   4
PagingEnabled:
        wbinvd                          ; clear out the cache
        ;
        ; Switch to virtual addressing for the stack and save of all these registers.
        ;
        mov     esp, OFFSET32 _KStack
        mov     eax, dword ptr [esp]    ; retrieve VA of OEMAddressTable
        mov     ecx, dword ptr [esp-4]  ; retrieve VA of Page Directory
        push    edx     ; eip pde index
        push    ebp     ; eip pde value
        push    edi     ; gdt pde index
        push    ebx     ; gdt pde value

        push    0
        popfd

        mov     ebx, ecx                ; (ebx) = VA of Page Directory
        push    ebx                     ; arg1 - VA of PageDir
        push    eax                     ; arg0 - VA of OEMAddressTable
        call    _SystemInitialization   ; Load new gdtr, among other things.
        add     sp, 8                   ; pop the arguments
        ;
        ; Restore the original page directory entry for the physical addresses.
        ; We cannot restore these PDEs until _SystemInitialization has reloaded
        ; gdtr.
        ;
        pop     eax                             ; gdt pde value
        pop     edx                             ; gdt pde index
        mov     DWORD PTR [ebx][edx], eax       ; Restore GDT phys addr mapping
        pop     eax                             ; PagingEnabled pde value
        pop     edx                             ; PagingEnalbled pde index
        mov     DWORD PTR [ebx][edx], eax       ; Restore PaginEnabled phys addr mapping
        ;
        ; Flush the tlb, since we are unmapping.
        ;
        mov     eax, cr3                        ; Flush the TLB
        mov     cr3, eax

        call    _SafeIdentifyCpu
        call    _KernelInit
        xor     edi, edi
        jmp     _Reschedule

_KernelInitialize ENDP


;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
_INTERRUPTS_ON proc NEAR PUBLIC
        sti
        ret
_INTERRUPTS_ON endp



;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
_INTERRUPTS_OFF proc NEAR PUBLIC
        cli
        ret
_INTERRUPTS_OFF endp

;-------------------------------------------------------------------------------
; INTERRUPTS_ENABLE - enable/disable interrupts based on arguemnt and return current status
;-------------------------------------------------------------------------------
_INTERRUPTS_ENABLE proc NEAR PUBLIC
        mov     ecx, [esp+4]            ; (ecx) = argument
        pushfd
        pop     eax                     ; (eax) = current flags
        shr     eax, EFLAGS_IF_BIT      ; 
        and     eax, 1                  ; (eax) = 0 if interrupt was disabled, 1 if enabled
        
        test    ecx, ecx                ; enable or disable?

        jne     short _INTERRUPTS_ON

        ; disable interrupt
        cli
        ret
_INTERRUPTS_ENABLE endp


_TEXT ENDS 

        END
        

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -