📄 init.asm
字号:
;
; Copyright (c) Microsoft Corporation. All rights reserved.
;
;
; This source code is licensed under Microsoft Shared Source License
; Version 1.0 for Windows CE.
; For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
;
;-------------------------------------------------------------------------------
;
;
;-------------------------------------------------------------------------------
.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
PDE_PS EQU 080H
PDE_G EQU 100h
CPUID_PSE EQU 0008H
CPUID_PGE EQU 2000H
SYSTEM_PAGES EQU 4000h ; 4 system pages:
; offset within SYSTEM_PAGES
SYSPAGE_PAGEDIR EQU 0 ; Page Directory: 1 page
SYSPAGE_ADDRTABLE EQU 1000h ; space to save OEMAddressTable: 1 page
SYSPAGE_SYSCALL EQU 2000h ; Syscall Page: 1 page
SYSPAGE_SYSCALLDIR EQU 3000h ; Syscall Page Dir: 1 page
ZERO_BLOCK_SIZE EQU 2000h ; page needs to be zero'd (page directory and shadwo)
KGDT_R0_CODE EQU 8h
KGDT_R0_DATA EQU 10h
PG_MASK EQU 80000000h
WP_MASK EQU 00010000h
LIN_TO_PHYS_OFFSET EQU 80000000h
OFFSET32 EQU <OFFSET FLAT:>
OFFSET_MEM_FOR_PT EQU 02a8h ; offset into _KDATA for nMemForPT field
OFFSET_CPU_CAP EQU 02ach ; offset into _KDATA for dwCpuCap field
; -- must match nkx86.h
OFFSET_ULRAMFREE EQU 24 ; offset into pTOC for ulRamFree field
EFLAGS_IF_BIT EQU 9 ; bit 9 of EFLAGS is IF bit
;-------------------------------------------------------------------------------
; Kernel Data Segment ; KStack, Page Directory, KPage, Page Table pool
;-------------------------------------------------------------------------------
.KDATA segment para public 'STACK'
public _KDBase
public _KStack
public _KData
public _CurMSec, _DiffMSec
db 1000h dup (?) ; reserve an extra page for the debugger
_KDBase db 07fch dup (?) ; 2k Kernel Stack
_KStack dd ?
_KData db 0088h dup (?) ; 2k KData
_CurMSec dd ?
_DiffMSec dd ?
db (800h - ($ - _KData)) dup (?)
.KDATA ends
;-------------------------------------------------------------------------------
;-------------------------------------------------------------------------------
_TEXT segment para public 'TEXT'
extrn _SystemInitialization:near
extrn _KernelInit:near
extrn _Reschedule:near
extrn _SafeIdentifyCpu:near
extrn _pTOC:near
public _NullSection
align 4
_NullSection dd 512 dup (0)
;-------------------------------------------------------------------------------
; Figure out Virtual Address of a Physical Address
;
; uses ecx, edx (uses registers per calling convention allowed)
;
; (esi) = ptr to OEMAddressTable
; (eax) = PA
;
; On return
; (eax) = VA
;-------------------------------------------------------------------------------
VaFromPa PROC NEAR
mov edx, esi ; (edx) = &OEMAddressTable[0]
TestNextPa:
cmp dword ptr [edx+8], 0 ; last entry?
je short PaNotFound ; entry not found
mov ecx, dword ptr [edx+4] ; (ecx) = OEMAddressTable[i].paddr
cmp eax, ecx ; Is (PA >= OEMAddressTable[i].paddr)?
jb short NextPa ; go to next entry if not
add ecx, dword ptr [edx+8] ; (ecx) = OEMAddressTable[i].paddr + OEMAddressTable[i].size
cmp eax, ecx ; Is (PA < OEMAddressTable[i].paddr + OEMAddressTable[i].size)?
jb short PaFound ; Found if it's true
NextPa:
add edx, 12 ; i ++
jmp short TestNextPa ; test next entry
PaNotFound:
jmp short PaNotFound ; not much we can do if can't find the mapping
; spin forever
PaFound:
sub eax, dword ptr [edx+4] ; PA -= PAStart
add eax, dword ptr [edx] ; PA += VAStart
ret
VaFromPa ENDP
;-------------------------------------------------------------------------------
; Figure out Physical Address of a Virtual Address
;
; uses ecx, edx (uses registers per calling convention allowed)
;
; (esi) = ptr to OEMAddressTable
; (eax) = VA
;
; On return
; (eax) = PA
;-------------------------------------------------------------------------------
PaFromVa PROC NEAR
mov edx, esi ; (edx) = &OEMAddressTable[0]
TestNextVa:
mov ecx, dword ptr [edx] ; (ecx) = OEMAddressTable[i].vaddr
test ecx, ecx ; last entry?
jz short VaNotFound ; entry not found
cmp eax, ecx ; Is (VA >= OEMAddressTable[i].vaddr)?
jb short NextVa ; go to next entry if not
add ecx, dword ptr [edx+8] ; (ecx) = OEMAddressTable[i].vaddr + OEMAddressTable[i].size
cmp eax, ecx ; Is (VA < OEMAddressTable[i].vaddr + OEMAddressTable[i].size)?
jb short VaFound ; Found if it's true
NextVa:
add edx, 12 ; i ++
jmp short TestNextVa ; test next entry
VaNotFound:
jmp short VaNotFound ; not much we can do if can't find the mapping
; spin forever
VaFound:
sub eax, dword ptr [edx] ; VA -= VAStart
add eax, dword ptr [edx+4] ; VA += PAStart
ret
PaFromVa ENDP
;
; Fill PageDirectory of an OEMAddressTable entry using 4M pages
; On Entry
; (eax) = PA of an OEMAddressTable Entry
; (ebx) = PA of Page Directory
; (edx) = PDE capability bits (PDE_PS and PDE_G)
;
;
; !!! All Reigsters preserved !!!
;
FillPD4M PROC NEAR
pushad
mov esi, dword ptr[eax] ; (esi) = VA of region
shr esi, 20 ; (esi) = offset into the Page Directory
add esi, ebx ; (esi) = ptr to Page Directory cached entry
mov edi, esi
add edi, 0200h ; (edi) = ptr to Page Directory uncached entry
mov ecx, dword ptr [eax+8] ; (ecx) = size of the region
add ecx, 0003fffffh ; round up to multiple of 4M
and ecx, 0ffc00000h ;
; DEBUGCHK (ecx != 0)
or edx, dword ptr [eax+4] ; (edx) = PA | Capability BITs
mov eax, edx
or edx, PAGE_ATTRIB_RW ; (edx) = PDE entry for 1st 4M (cached)
or eax, PAGE_ATTRIB_RW_NOCACHE ; (eax) = PDE entry value for 1st 4M (uncached)
Next4M:
mov dword ptr [esi], edx ; setup one cached entry
mov dword ptr [edi], eax ; setup one uncached entry
add esi, 4 ; (esi) = ptr to next PDE (cached)
add edi, 4 ; (edi) = ptr to next PDE (uncached)
add edx, 0400000h ; (edx) = PDE entry value for next 4M (cached)
add eax, 0400000h ; (eax) = PDE entry value for next 4M (uncached)
sub ecx, 0400000h ; decrement size by 4M
jg short Next4M
popad
ret
FillPD4M ENDP
; Fill a secondary page table (2 actually, cached and uncached) + the page directory entry
; (ebx) = PA to map to
; (edx & ~0xfff) = PA of Page table (2 consective pages, one for cached, one for uncached)
; NOTE: Low bit of edx might be set, MUST clear it before using it
;
; !!! ALL REGITSTERS PRESERVED !!!
;
FillPTE PROc NEAR
pushad
mov eax, ebx
or eax, PAGE_ATTRIB_RW ; (eax) = page entry value (cached)
or ebx, PAGE_ATTRIB_RW_NOCACHE ; (ebx) = page entry value (uncached)
and edx, 0fffff000h ; (edx) = Page table for cached mapping
; the low bits might contain gargage when passed in
mov esi, edx ; (esi) = Page table
add esi, PAGE_SIZE ; (esi) = Page Table for uncached mapping
mov ecx, 1024 ; (ecx) = counter (1024 entries)
NextPTE:
mov dword ptr [edx], eax
mov dword ptr [esi], ebx
add edx, 4
add esi, 4
add eax, PAGE_SIZE
add ebx, PAGE_SIZE
dec ecx
jne short NextPTE
popad
ret
FillPTE ENDP
;
; Fill PageDirectory/PageTable of an OEMAddressTable entry using 4K pages
; On Entry
; (eax) = PA of an OEMAddressTable Entry
; (ebx) = PA of Page Directory
; (edx) = PageTables enough to map this region
;
; !!! All Reigsters preserved !!!
;
FillPD4K PROC NEAR
pushad
mov ecx, dword ptr [eax+8] ; (ecx) = size of the region
add ecx, 0003fffffh ; round up to multiple of 4M
and ecx, 0ffc00000h ;
; DEBUGCHK (ecx != 0)
mov esi, dword ptr [eax] ; (esi) = VA of region
shr esi, 20 ; (esi) = offset into the Page Directory
add esi, ebx ; (esi) = ptr to Page Directory cached entry
mov edi, esi
add edi, 0200h ; (edi) = ptr to Page Directory uncached entry
mov ebx, dword ptr [eax+4] ; (ebx) = PA of the region
or edx, PAGE_ATTRIB_RW ; (edx) = PDE entry for 1st 4M (cached)
mov eax, edx
add eax, PAGE_SIZE ; (edx, eax) are PT for (cached, uncached) addresses
Next4MPT:
; arguments to FillPTE:
; (edx & ~0xfff) == Page Table address for 2 consective pages
; (ebx) == PA to map to
call FillPTE ; fill the page tables
; NOTE: FillPTE perserves all registers
mov dword ptr [esi], edx ; setup one cached entry
mov dword ptr [edi], eax ; setup one uncached entry
add esi, 4 ; (esi) = ptr to next PDE (cached)
add edi, 4 ; (edi) = ptr to next PDE (uncached)
add ebx, 0400000h ; (ebx) = PA of the next 4M
add edx, PAGE_SIZE*2 ; (edx) = PDE entry value for next 4M (cached)
add eax, PAGe_SIZE*2 ; (eax) = PDE entry value for next 4M (uncached)
sub ecx, 0400000h ; decrement size by 4M
jg short Next4MPT
popad
ret
FillPD4K ENDP
;-------------------------------------------------------------------------------
; (esi) = PA of OEMAddressTable
; o each entry is of the format ( VA, PA, cbSize )
; o cbSize must be multiple of 4M
; o last entry must be (0, 0, 0)
; o must have at least one non-zero entry
; (edi) = CPU capability bits
;
; throughout this function
; (ebx) = PA of Page Directory
; (esi) = PA of OEMAddressTable
;-------------------------------------------------------------------------------
_KernelInitialize PROC NEAR PUBLIC
; xor edi, edi ; uncomment this line to force 4K page, useful for debugging
; set KData.nMemForPT to 0 first
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -