oeminit.asm

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· 汇编 代码 · 共 390 行

ASM
390
字号
;-------------------------------------------------------------------------------
;
;   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
;   ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
;   THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
;   PARTICULAR PURPOSE.
;   Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.
;
;-------------------------------------------------------------------------------
.486p

PAGE_SIZE EQU 1000h
PAGE_ATTRIB_RW      EQU 000001100011b
PAGE_ATTRIB_RW_NOCACHE  EQU 000001111011b
PAGE_ATTRIB_RO_USER EQU 000000100101b
PAGE_ATTRIB_RW_USER EQU 000001100111b

PageRange MACRO Start, NumPages, Attrib
        LOCAL CurPhys
        .ERRNZ Start AND (PAGE_SIZE-1)
        CurPhys = Start
        REPEAT NumPages
            dd  CurPhys OR Attrib
            CurPhys = CurPhys + PAGE_SIZE
        ENDM
        ENDM

LIN_TO_PHYS_OFFSET EQU 80000000h

OFFSET32 EQU <OFFSET FLAT:>

PageTbl SEGMENT PAGE READONLY USE32 'PageTbl'
;
; These page tables are cacheable, and global if the processor
; supports global pages.
MapRam00 LABEL DWORD
        PageRange 00000000h, 400h, PAGE_ATTRIB_RW
MapRam04 LABEL DWORD
        PageRange 00400000h, 400h, PAGE_ATTRIB_RW
MapRam08 LABEL DWORD
        PageRange 00800000h, 400h, PAGE_ATTRIB_RW
MapRam0C LABEL DWORD
        PageRange 00C00000h, 400h, PAGE_ATTRIB_RW
MapRam10 LABEL DWORD
        PageRange 01000000h, 400h, PAGE_ATTRIB_RW
MapRam14 LABEL DWORD
        PageRange 01400000h, 400h, PAGE_ATTRIB_RW
MapRam18 LABEL DWORD
        PageRange 01800000h, 400h, PAGE_ATTRIB_RW
MapRam1C LABEL DWORD
        PageRange 01C00000h, 400h, PAGE_ATTRIB_RW
MapRamGEnd LABEL DWORD  ; End of area global page area
;
; These page tables are non-cacheable.  We also don't
; make them global, to minimize TLB clutter.
MapRam00NC LABEL DWORD
        PageRange 00000000h, 400h, PAGE_ATTRIB_RW_NOCACHE
MapRam04NC LABEL DWORD
        PageRange 00400000h, 400h, PAGE_ATTRIB_RW_NOCACHE
MapRam08NC LABEL DWORD
        PageRange 00800000h, 400h, PAGE_ATTRIB_RW_NOCACHE
MapRam0CNC LABEL DWORD
        PageRange 00C00000h, 400h, PAGE_ATTRIB_RW_NOCACHE
MapRam10NC LABEL DWORD
        PageRange 01000000h, 400h, PAGE_ATTRIB_RW_NOCACHE
MapRam14NC LABEL DWORD
        PageRange 01400000h, 400h, PAGE_ATTRIB_RW_NOCACHE
MapRam18NC LABEL DWORD
        PageRange 01800000h, 400h, PAGE_ATTRIB_RW_NOCACHE
MapRam1CNC LABEL DWORD
        PageRange 01C00000h, 400h, PAGE_ATTRIB_RW_NOCACHE
; page table additions for CodeTest
MapCodeTest LABEL DWORD
        PageRange 0DE000000h, 400h, PAGE_ATTRIB_RW
MapCodeTestNC LABEL DWORD
        PageRange 0DE000000h, 400h, PAGE_ATTRIB_RW_NOCACHE

PageTbl ENDS

_DATA SEGMENT DWORD USE32 PUBLIC 'DATA'

; This GDT is only used by _RebootHandler to set the correct GDT during the warm reboot path

GDT_Data LABEL DWORD
        db      0,    0,   0,   0,   0,         0,         0,   0 ; First GDT entry always unused
CS_FLAT_SEL EQU ($-GDT_Data)
        db      0FFh, 0FFh, 00h, 00h, 00h, 10011010b, 11001111b, 00h ; Code
DS_FLAT_SEL EQU ($-GDT_Data)
        db      0FFh, 0FFh, 00h, 00h, 00h, 10010010b, 11001111b, 00h ; Data
GDT_TABLE_SIZE = $ - OFFSET GDT_Data

GDTPtr LABEL FWORD
        dw      GDT_TABLE_SIZE - 1  ; Limit of 0 = 1 byte
        dd      OFFSET GDT_Data
_DATA ENDS

        ASSUME  CS: FLAT, DS: FLAT, SS: FLAT

_TEXT SEGMENT para public 'TEXT'
_CpuIdTrap6Handler PROC NEAR                ; COMDAT
    ; Emulate an unsupported CPUID that generates an invalid opcode exception.
    add     dword ptr [esp], 2
    xor     eax, eax
    xor     ebx, ebx
    xor     ecx, ecx
    xor     edx, edx
    iretd
_CpuIdTrap6Handler ENDP

_IdentifyCpu PROC NEAR                  ; COMDAT
    push    ebx
    cli
    sub     esp, 8
    sidt    FWORD PTR [esp]
    mov     ecx, DWORD PTR [esp+4]
    push    DWORD PTR [ecx+48]
    push    DWORD PTR [ecx+52]
    mov     eax, OFFSET32 _CpuIdTrap6Handler
    sub     eax, LIN_TO_PHYS_OFFSET
    mov     WORD PTR [ecx+48], ax
    shr     eax, 16
    mov     WORD PTR [ecx+54], ax
    ; Set up the selector and gate type since the IDT has not yet been set up.
    push     cs
    pop     eax
    mov     WORD PTR [ecx+50], ax
    mov     WORD PTR [ecx+52], 08E00h
    xor     eax, eax
    DB      00fH
    DB      0a2H
    cmp     ebx, 756e6547H
    jne     SHORT cpuid_trap
    cmp     edx, 49656e69H
    jne     SHORT cpuid_trap
    cmp     ecx, 6c65746eH
    jne     SHORT cpuid_trap
    cmp     eax, 1
    jb      SHORT cpuid_trap
    mov     eax, 1
    DB      00fH
    DB      0a2H
cpuid_result:
    jmp     SHORT cpuid_store
cpuid_trap:
    mov     eax, 400H
    xor     ebx, ebx
    xor     ecx, ecx
    xor     edx, edx
    jmp     SHORT cpuid_result
cpuid_store:
    mov     ecx, DWORD PTR [esp+12]
    pop     DWORD PTR [ecx+52]
    pop     DWORD PTR [ecx+48]
    add     esp, 8
    mov     eax, edx
    pop     ebx
    ret     0
_IdentifyCpu ENDP

_OEMInitPageTable PROC NEAR PUBLIC
        pushad
        ;
        ; Do we have large pages?
        call    _IdentifyCpu
CPUID_PSE EQU   0008H
CPUID_PGE EQU   2000H
CPUID_PGE_BIT EQU 13
PDE_PS  EQU     080H
PDE_PWT EQU     008H
PDE_PCD EQU     010H
PTE_G   EQU     100H    ; Global page -- do not flush
PTE_G_BIT EQU   8
        push    eax
        and     eax, CPUID_PSE
        jz      use_4k_pages
        ;
        ; CPU supports 4Mb pages, so we definitely want to use them.
        pop     eax             ; Get CPU feature bits
        and     eax, CPUID_PGE  ; Global pages?
        shr     eax, CPUID_PGE_BIT ; 1 or 0
        push    eax
        shl     eax, PTE_G_BIT  ; PDE_G or 0
        or      eax, PAGE_ATTRIB_RW or PDE_PS ; Make permission bits
        mov     DWORD PTR [ebx][0800h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0804h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0808h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][080Ch], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0810h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0814h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0818h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][081Ch], eax
; NOTENOTE -- shouldn't alias cacheable and uncacheable with speculative
; execution.
        and     eax, 0fffH
        or      eax, PDE_PWT or PDE_PCD
        mov     DWORD PTR [ebx][0A00h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0A04h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0A08h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0A0Ch], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0A10h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0A14h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0A18h], eax
        add     eax, 00400000h
        mov     DWORD PTR [ebx][0A1ch], eax
        pop     ecx             ; 1 iff CPUID_PGE
CR4_PGE_BIT EQU 7
CR4_PSE EQU     010H
        shl     ecx, CR4_PGE_BIT
        or      ecx, CR4_PSE
.586p
        mov     eax, cr4
        or      eax, ecx
        mov     cr4, eax
.486p
OEMIPTDone:
        popad
    ret

use_4k_pages:
        mov DWORD PTR [ebx][800h], OFFSET32 MapRam00 + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][804h], OFFSET32 MapRam04 + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][808h], OFFSET32 MapRam08 + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][80Ch], OFFSET32 MapRam0C + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][810h], OFFSET32 MapRam10 + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][814h], OFFSET32 MapRam14 + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][818h], OFFSET32 MapRam18 + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][81Ch], OFFSET32 MapRam1C + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
; NOTENOTE -- shouldn't alias cacheable and uncacheable with speculative
; execution.
        mov DWORD PTR [ebx][0A00h], OFFSET32 MapRam00NC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][0A04h], OFFSET32 MapRam04NC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][0A08h], OFFSET32 MapRam08NC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][0A0Ch], OFFSET32 MapRam0CNC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][0A10h], OFFSET32 MapRam10NC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][0A14h], OFFSET32 MapRam14NC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][0A18h], OFFSET32 MapRam18NC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
    mov DWORD PTR [ebx][0A1Ch], OFFSET32 MapRam1CNC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
; AMC code: This sets up two 4MB mapping regions for CodeTest tags:
;
;    Virtual Address Region  =>  Physical Address Region
;    -------------------------------------------------------------
;    0xAF00'0000 - 0xAF3F'FFFF  =>  0xDE000000 - 0xDE3FFFFF (uncached)
;    0x8F00'0000 - 0x8F3F'FFFF  =>  0xDE000000 - 0xDE3FFFFF (cached)
        mov     DWORD PTR [ebx][08F0h], OFFSET32 MapCodeTest + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
        mov     DWORD PTR [ebx][0AF0h], OFFSET32 MapCodeTestNC + LIN_TO_PHYS_OFFSET + PAGE_ATTRIB_RW
        pop     eax             ; Get CPU feature bits
        jmp     OEMIPTDone

_OEMInitPageTable ENDP





LIN_TO_PHYS_MASK        EQU     7FFFFFFFh
PG_MASK                 EQU     80000000h
CD_MASK                 EQU     40000000h

extrn _dwRebootAddress:near
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
_RebootHandler PROC NEAR PUBLIC

        cli
        ;
        ; Get the linear address of the page directory.
        ;
        mov     ebx, cr3
        or      ebx, LIN_TO_PHYS_OFFSET

        ;
        ; Create the identity-mapped addresses (physical = linear)
        ;

        mov     ecx, OFFSET32 IdentityMapped
        mov     edx, ecx
        and     edx, LIN_TO_PHYS_MASK
        ;
        ; 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

        ;
        ; Copy the page directory entry for the current linear
        ; address to the physical address.
        ;
        mov     eax, DWORD PTR [ebx][ecx]
        mov     DWORD PTR [ebx][edx], eax

        ;
        ; Move execution to the identity-mapped physical address.
        ;
        mov     edx, OFFSET32 IdentityMapped
        and     edx, LIN_TO_PHYS_MASK
        jmp     edx

IdentityMapped:
        mov     edx, OFFSET32 PagingDisabled
        and     edx, LIN_TO_PHYS_MASK

        mov     eax, cr0
        and     eax, not PG_MASK        ; Disable paging
        or      eax, CD_MASK            ; Disable cache
        mov     cr0, eax                ; Apply new system settings

        wbinvd                          ; Flush the cache

        mov     ebx, cr3
        mov     cr3, ebx                ; Flush the TLB

        and     eax, not CD_MASK        ; Re-enable cache
        mov     cr0, eax                ; Apply new system settings

        jmp     edx                     ; Far jump to purge any prefetch state.

        align   4
PagingDisabled:
        ;
        ; Move the stack pointer to the physical address.
        ;
        mov     eax, esp
        and     eax, LIN_TO_PHYS_MASK
        mov     esp, eax

INITIAL_CR0     EQU     00000011h
INITIAL_CR3     EQU     00000000h
INITIAL_CR4     EQU     00000000h
INITIAL_EFLAGS  EQU     00007046h

        mov     eax, INITIAL_CR0
        mov     cr0, eax
        mov     eax, INITIAL_CR3
        mov     cr3, eax
.586p
        mov     eax, INITIAL_CR4
        mov     cr4, eax
.486p
        mov     eax, INITIAL_EFLAGS

        lgdt    FWORD PTR [GDTPtr]      ; Load the GDTR

        push    eax
        popfd

        ;
        ; Read from RAM the address we are jumping to.
        ;
        mov     edx, _dwRebootAddress
        and     edx, LIN_TO_PHYS_MASK
        mov     ebx, dword ptr [edx]
        and     ebx, LIN_TO_PHYS_MASK
        ;
        ; Jump to the first instruction.
        ;
        jmp     ebx


_RebootHandler ENDP

_OEMFlushCache PROC NEAR PUBLIC
    xor eax, eax
    pushad
;   cpuid
    DB      00fH
    DB      0a2H
    popad
    ret
_OEMFlushCache  ENDP

_TEXT ENDS

        END

⌨️ 快捷键说明

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