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 + -
显示快捷键?