1391 lines
40 KiB
NASM
1391 lines
40 KiB
NASM
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;
|
||
|
;; singldr0.asm - X86 Portion of Singularity Boot Loader
|
||
|
;;
|
||
|
;; Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
;;
|
||
|
;; Notes:
|
||
|
;; This file has three main purposes.
|
||
|
;; 1) Initialize context for the 16-bit C++ boot loader
|
||
|
;; (BootPhase0 -> BootPhase1).
|
||
|
;; 2) Manage the transition from 16-bit real to 32-bit protected mode
|
||
|
;; (BootPhase2 -> BootPhase3 -> undump).
|
||
|
;; 3) Manage the transition from 32-bit protected to 16-bit real mode
|
||
|
;; (StopPhase0 -> StopPhase1 -> StopPhase2 -> StopPhase3).
|
||
|
;;
|
||
|
;; In addition, this file provides a few helper functions used by the
|
||
|
;; 16-bit loader code in singldr.cpp.
|
||
|
;;
|
||
|
;; Since there is only one .asm function (BiosDiskRead) specific to the
|
||
|
;; disk boot process, it is in here too
|
||
|
;;
|
||
|
;; The three-function-in-one PModeTransfer routine is also located here
|
||
|
;; in order to ensure it links correctly, since it has mixed 16-bit and
|
||
|
;; 32-bit portions
|
||
|
;;
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;
|
||
|
.model tiny, c
|
||
|
.686p
|
||
|
.mmx
|
||
|
.xmm
|
||
|
|
||
|
.xlist
|
||
|
.list
|
||
|
|
||
|
OPTION SCOPED
|
||
|
|
||
|
DEBUG_BOOT EQU 0
|
||
|
DEBUG_VESA_MODES EQU 0
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;
|
||
|
;; Bartok Types
|
||
|
;;
|
||
|
|
||
|
uint8 TYPEDEF BYTE
|
||
|
uint16 TYPEDEF WORD
|
||
|
uint32 TYPEDEF DWORD
|
||
|
uint64 TYPEDEF QWORD
|
||
|
|
||
|
int8 TYPEDEF BYTE
|
||
|
int16 TYPEDEF WORD
|
||
|
int32 TYPEDEF DWORD
|
||
|
int64 TYPEDEF QWORD
|
||
|
|
||
|
bool TYPEDEF BYTE
|
||
|
bartok_char TYPEDEF WORD
|
||
|
|
||
|
intptr TYPEDEF DWORD
|
||
|
uintptr TYPEDEF DWORD
|
||
|
|
||
|
uintPtr STRUCT 4
|
||
|
value uintptr ?
|
||
|
uintPtr ENDS
|
||
|
|
||
|
intPtr STRUCT 4
|
||
|
value intptr ?
|
||
|
intPtr ENDS
|
||
|
|
||
|
PTR_uintptr TYPEDEF PTR uintptr
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;
|
||
|
;; Other Types
|
||
|
;;
|
||
|
|
||
|
GDTDesc STRUCT
|
||
|
GDT_limit dw 0
|
||
|
GDT_base1 dw 0
|
||
|
GDT_base2 db 0
|
||
|
GDT_access db 0
|
||
|
GDT_limacc db 0
|
||
|
GDT_base3 db 0
|
||
|
GDTDesc ENDS
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;
|
||
|
|
||
|
_TEXT32 segment para public use32 'CODE' ; this segment contains all 32-bit
|
||
|
include halclass.inc
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;
|
||
|
;; Macros
|
||
|
;;
|
||
|
|
||
|
CONSOLE_WRITE macro loc,value
|
||
|
push edx
|
||
|
mov edx, loc
|
||
|
mov ah, 01fh
|
||
|
mov al, value
|
||
|
mov [edx], ax
|
||
|
pop edx
|
||
|
endm
|
||
|
|
||
|
|
||
|
LOAD_EAX_FLAT MACRO reg
|
||
|
xor eax,eax
|
||
|
mov ax,reg
|
||
|
shl eax,4
|
||
|
ENDM
|
||
|
|
||
|
OPERAND_SIZE_OVERLOAD MACRO
|
||
|
uint8 066h
|
||
|
ENDM
|
||
|
|
||
|
MOV_EAX_CR4 MACRO
|
||
|
uint8 00fh
|
||
|
uint8 020h
|
||
|
uint8 0e0h
|
||
|
ENDM
|
||
|
|
||
|
MOV_CR4_EAX MACRO
|
||
|
uint8 00fh
|
||
|
uint8 022h
|
||
|
uint8 0e0h
|
||
|
ENDM
|
||
|
|
||
|
LEA_EAX_REALATIVE MACRO target
|
||
|
call @pusheip
|
||
|
@pusheip:
|
||
|
pop eax
|
||
|
add eax, target - @pusheip
|
||
|
ENDM
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;
|
||
|
;; 16-bit code segment
|
||
|
;;
|
||
|
|
||
|
_TEXT segment public use16 'CODE' ; this segment contains all 16-bit
|
||
|
|
||
|
EXTRN BootPhase1:NEAR
|
||
|
EXTRN StopPhase3:NEAR
|
||
|
EXTRN MpBootPhase1:NEAR
|
||
|
.data
|
||
|
|
||
|
PUBLIC MpStartupLock
|
||
|
MpStartupLock dw 1
|
||
|
|
||
|
.code
|
||
|
|
||
|
ORG 100h
|
||
|
BootPhase0 PROC NEAR
|
||
|
|
||
|
; if we are booting from PXE, the stack holds the return address and the
|
||
|
; !PXE address, and es:bx is the PXENV+ address. CS:IP=0000:7c00
|
||
|
;
|
||
|
; if we are booting from HD/CD, the stack holds a null return address, the
|
||
|
; boot signature ("CD" or "HD"), and the boot drive. CS:IP=5000:7c00
|
||
|
|
||
|
; First, we will move the IP to 100h, and CS to X7b0, where x=0 or x=5
|
||
|
; this lets us build this as a DOS .com file
|
||
|
|
||
|
mov ax, cs
|
||
|
add ax, 07b0h
|
||
|
push ax
|
||
|
push OFFSET begin
|
||
|
retf ; really returns to next statement.
|
||
|
|
||
|
begin:
|
||
|
|
||
|
; if we booted off of the Hard Disk or CD, we're now at 57b0:0100
|
||
|
; relocate this segment to 07b0:1000
|
||
|
|
||
|
cmp ax, 07b0h ; ax holds cs
|
||
|
je ConfigNetboot ; if cs is already 07b0, this was a net boot
|
||
|
|
||
|
; relocate from 57b0:0100 to 07b0:0100
|
||
|
mov ax, 07c0h
|
||
|
mov es, ax
|
||
|
xor di, di ; es:di points to 07c0:0000
|
||
|
mov ax, cs
|
||
|
add ax, 010h
|
||
|
mov ds, ax
|
||
|
xor si, si ; ds:si points to 57c0:0000
|
||
|
mov ecx, 04000h
|
||
|
rep movsd ; transfer 4000h DWORDS (64KB)
|
||
|
|
||
|
; since we are here, this wasn't a PXE boot. set the stack appropriately:
|
||
|
pop eax ; pop the return address for a disk boot
|
||
|
pop ebx ; pop the boot device signature
|
||
|
pop edx ; pop the boot drive
|
||
|
push edx ; on a disk boot, we set the PXE! address to diskid
|
||
|
push eax ; put the return address back on the stack
|
||
|
|
||
|
pushw 07b0h
|
||
|
push OFFSET relocated
|
||
|
retf ; jump to the 'relocated' block
|
||
|
|
||
|
ConfigNetboot:
|
||
|
push es ; ebx holds the PXENV+ address
|
||
|
push bx
|
||
|
pop ebx
|
||
|
xor edx, edx ; on a PXE boot, the bootdriveid=0
|
||
|
|
||
|
relocated:
|
||
|
mov ax, cs
|
||
|
mov ds, ax ; set FS=GS=DS=CS for TINY model.
|
||
|
mov fs, ax
|
||
|
mov gs, ax
|
||
|
|
||
|
pop eax ; pop the return address.
|
||
|
pop ecx ; pop the !PXE address.
|
||
|
push ecx ; return !PXE address. (arg0)
|
||
|
push eax ; push the return address. (ret)
|
||
|
|
||
|
push ss ;
|
||
|
push sp ;
|
||
|
pop ebp ; get the stack pointer.
|
||
|
|
||
|
mov ax, ds ; move the stack to cs:fff0h
|
||
|
mov ss, ax
|
||
|
mov ax, 0fff0h
|
||
|
mov sp, ax
|
||
|
|
||
|
push ebp ; push the old stack pointer.
|
||
|
push edx ; push the disk id (arg2)
|
||
|
push ebx ; push the PXENV+ address (arg1)
|
||
|
push ecx ; push the !PXE address (arg0)
|
||
|
call EnableA20
|
||
|
call BootPhase1
|
||
|
|
||
|
pop ecx ; pop the !PXE address
|
||
|
pop ecx ; pop the PXENV+ address
|
||
|
pop sp ; pop the old stack pointer.
|
||
|
pop ss
|
||
|
|
||
|
retf
|
||
|
BootPhase0 ENDP
|
||
|
|
||
|
; void IoSpaceWrite8(uint16 port, uint8 value);
|
||
|
; Called by 16-bit C++ code to access video registers.
|
||
|
PUBLIC IoSpaceWrite8
|
||
|
IoSpaceWrite8 PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
mov dx, [bp+4] ; dx = address segment
|
||
|
mov al, [bp+6] ; eax = value
|
||
|
out dx, al
|
||
|
pop bp
|
||
|
ret
|
||
|
IoSpaceWrite8 ENDP
|
||
|
|
||
|
; void IoSpaceWrite32(uint16 port, uint32 value);
|
||
|
; Called by 16-bit C++ code to access PCI config space.
|
||
|
PUBLIC IoSpaceWrite32
|
||
|
IoSpaceWrite32 PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
mov dx, [bp+4] ; dx = address segment
|
||
|
mov eax, [bp+6] ; eax = value
|
||
|
out dx, eax
|
||
|
pop bp
|
||
|
ret
|
||
|
IoSpaceWrite32 ENDP
|
||
|
|
||
|
; uint8 IoSpaceRead8(uint16 port);
|
||
|
; Called by 16-bit C++ code to access video registers.
|
||
|
PUBLIC IoSpaceRead8
|
||
|
IoSpaceRead8 PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
mov dx, [bp+4] ; dx = address segment
|
||
|
in al, dx
|
||
|
pop bp
|
||
|
ret
|
||
|
IoSpaceRead8 ENDP
|
||
|
|
||
|
; uint32 IoSpaceRead32(uint16 port);
|
||
|
; Called by 16-bit C++ code to access PCI config space.
|
||
|
PUBLIC IoSpaceRead32
|
||
|
IoSpaceRead32 PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
mov dx, [bp+4] ; dx = address segment
|
||
|
in eax, dx
|
||
|
mov edx, eax
|
||
|
shr edx, 16
|
||
|
pop bp
|
||
|
ret
|
||
|
IoSpaceRead32 ENDP
|
||
|
|
||
|
; uint16 BiosDiskRead(uint8 __far * addr, uint32 diskblock, uint16 blocks, uint16 driveid);
|
||
|
; Called by 16-bit C++ code to read from the disk (HD or CD) using extended int13h
|
||
|
PUBLIC BiosDiskRead
|
||
|
BiosDiskRead PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
pushad
|
||
|
|
||
|
mov dx, [bp+14] ; dl = drive #
|
||
|
mov eax, [bp+8] ; eax = LBA #
|
||
|
mov cx, [bp+12] ; ecx = count (# of sectors)
|
||
|
mov bx, [bp+6] ; bx = address segment
|
||
|
mov di, [bp+4] ; di = address offset
|
||
|
|
||
|
pushd 00
|
||
|
push eax ; push 64-bit sector address (top half always null)
|
||
|
|
||
|
push bx
|
||
|
push di ; push transfer address
|
||
|
|
||
|
push cx ; # sectors
|
||
|
pushw 0010h ; this request packet is 16 bytes
|
||
|
|
||
|
mov ah,42h ; extended read
|
||
|
mov si,sp ; set ds:si = address of params
|
||
|
int 13h ; perform the read
|
||
|
|
||
|
add sp, 10h ; clean the stack, discard the return code
|
||
|
|
||
|
popad
|
||
|
pop bp
|
||
|
ret
|
||
|
BiosDiskRead ENDP
|
||
|
|
||
|
; uint16 BiosDiskReadCHS(uint8 __far * addr, uint32 diskblock, uint16 driveid, uint16 sectors, uint16 secpertrack, uint16 numheads)
|
||
|
; Called by 16-bit C++ code to read from a Usb disk using CHS-style int13h
|
||
|
PUBLIC BiosDiskReadCHS
|
||
|
BiosDiskReadCHS PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
pushad
|
||
|
push es
|
||
|
|
||
|
mov eax, [bp+8] ; eax = 32-bit absolute sector number
|
||
|
|
||
|
xor edx,edx ; clear edx before long divide
|
||
|
xor ecx,ecx
|
||
|
mov cx,[bp+16] ; ecx = sectors per track
|
||
|
div ecx ; eax = track, edx = sector within track (0-62)
|
||
|
inc dl ; dl = sector within track (1-63)
|
||
|
mov cl,dl ; cl = sector within track
|
||
|
mov edx,eax
|
||
|
shr edx,16 ; dx:ax = track
|
||
|
xor ebx, ebx
|
||
|
mov bx, [bp+18]
|
||
|
div bx ; ax = cylinder (0-1023), dx = head (0-255)
|
||
|
xchg dl,dh ; dh = head
|
||
|
|
||
|
mov ch,al ; ch = bits 0-7 of cylinder
|
||
|
shl ah,6
|
||
|
or cl,ah ; bits 6-7 of cl = bits 8-9 of cylinder
|
||
|
|
||
|
mov ax, [bp+12]
|
||
|
mov dl, al ; dl = int13 unit #
|
||
|
|
||
|
mov bx, [bp+6]
|
||
|
mov es, bx ; es = address segment
|
||
|
mov bx, [bp+4] ; bx = address offset
|
||
|
|
||
|
mov ax, [bp+14] ; ax = number of sectors, let's hope it's less than 256!
|
||
|
mov ah, 02h ; read 1 sector
|
||
|
|
||
|
int 13h
|
||
|
|
||
|
pop es
|
||
|
popad
|
||
|
pop bp
|
||
|
ret
|
||
|
BiosDiskReadCHS ENDP
|
||
|
|
||
|
; void BootGetBiosInfo(Struct_Microsoft_Singularity_BootInfo __far * pInfo);
|
||
|
; Called by 16-bit C++ code to fill in portions of BootInfo.
|
||
|
PUBLIC BootGetBiosInfo
|
||
|
BootGetBiosInfo PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
mov es, [bp+6]
|
||
|
mov si, [bp+4] ; pInfo
|
||
|
|
||
|
push di
|
||
|
push cx
|
||
|
push dx
|
||
|
|
||
|
mov eax, SIZEOF Struct_Microsoft_Singularity_BootInfo
|
||
|
mov es:[si].Struct_Microsoft_Singularity_BootInfo._RecSize, eax
|
||
|
|
||
|
; Set Bios-related Information.
|
||
|
;
|
||
|
xor edx,edx
|
||
|
mov ax,0b101h
|
||
|
stc
|
||
|
int 1ah
|
||
|
jc skip_1A_B101
|
||
|
mov es, [bp+6]
|
||
|
mov si, [bp+4] ; pInfo
|
||
|
and eax, 0ffffh
|
||
|
mov es:[si].Struct_Microsoft_Singularity_BootInfo._PciBiosAX, eax
|
||
|
and ebx, 0ffffh
|
||
|
mov es:[si].Struct_Microsoft_Singularity_BootInfo._PciBiosBX, ebx
|
||
|
and ecx, 0ffh
|
||
|
mov es:[si].Struct_Microsoft_Singularity_BootInfo._PciBiosCX, ecx
|
||
|
mov es:[si].Struct_Microsoft_Singularity_BootInfo._PciBiosEDX, edx
|
||
|
skip_1A_B101:
|
||
|
|
||
|
; Save the IDT and PIC information.
|
||
|
xor ax, ax
|
||
|
mov dx, 0a0h
|
||
|
in al, dx
|
||
|
mov ah, al
|
||
|
mov dx, 020h
|
||
|
in al, dx
|
||
|
|
||
|
mov es:[si].Struct_Microsoft_Singularity_BootInfo._BiosPicMask, ax
|
||
|
sidt es:[si].Struct_Microsoft_Singularity_BootInfo._BiosIdtPtr._limit
|
||
|
|
||
|
pop dx
|
||
|
pop cx
|
||
|
pop di
|
||
|
|
||
|
pop bp
|
||
|
ret
|
||
|
BootGetBiosInfo ENDP
|
||
|
|
||
|
; void BootPhase2(Struct_Microsoft_Singularity_BootInfo *)
|
||
|
; Entered in 16-bit real mode.
|
||
|
; Transitions to 32-bit protected mode (to BootPhase3).
|
||
|
; Loads EDX = Struct_Microsoft_Singularity_BootInfo far *
|
||
|
PUBLIC BootPhase2
|
||
|
BootPhase2 PROC NEAR
|
||
|
|
||
|
push bp
|
||
|
xor ebp, ebp
|
||
|
mov bp, sp
|
||
|
mov ax, [bp+6]
|
||
|
mov bp, [bp+4] ; pBootInfo
|
||
|
mov ss, ax
|
||
|
|
||
|
; disable interrupts until kernel turns them back on.
|
||
|
cli
|
||
|
|
||
|
; prepare for jump to 32-bit protected mode.
|
||
|
; edx = physical address of Struct_Microsoft_Singularity_BootInfo.
|
||
|
;
|
||
|
mov edx, DWORD PTR [bp].Struct_Microsoft_Singularity_BootInfo._Info32
|
||
|
|
||
|
; set segments before switch
|
||
|
lgdt FWORD PTR [bp].Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPtr._limit
|
||
|
|
||
|
; Turn prot mode on, flush prefetch
|
||
|
mov eax, cr0
|
||
|
or eax, Struct_Microsoft_Singularity_X86_CR0_PE + Struct_Microsoft_Singularity_X86_CR0_NE
|
||
|
mov cr0, eax
|
||
|
|
||
|
jmp cont
|
||
|
cont:
|
||
|
|
||
|
; Load protected stack segment registers.
|
||
|
mov ax,Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtRS - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov ss,ax
|
||
|
mov esp,ebp
|
||
|
|
||
|
; push the 16:32 address onto the stack, then "return" to it.
|
||
|
push 0
|
||
|
push Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPC - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov eax, 07b00h + OFFSET BootPhase3
|
||
|
push eax
|
||
|
OPERAND_SIZE_OVERLOAD
|
||
|
retf
|
||
|
|
||
|
BootPhase2 ENDP
|
||
|
|
||
|
; StopPhase1
|
||
|
; Entered in 16-bit protected mode.
|
||
|
; Transitions to 16-bit real mode (StopPhase2).
|
||
|
; Passes through BootInfo __far * in ebx.
|
||
|
;
|
||
|
StopPhase1 PROC NEAR
|
||
|
; Turn off protected mode.
|
||
|
mov eax, cr0
|
||
|
and eax, NOT (Struct_Microsoft_Singularity_X86_CR0_PE + Struct_Microsoft_Singularity_X86_CR0_NE)
|
||
|
mov cr0, eax
|
||
|
|
||
|
db 0EAh ; JMP FAR PTR
|
||
|
dw offset StopPhase2 ; 07b0:StopPhase2
|
||
|
dw 07b0h
|
||
|
StopPhase1 ENDP
|
||
|
|
||
|
; StopPhase2
|
||
|
; Entered in 16-bit real mode. Shuts the machine down.
|
||
|
; Assumes BootInfo __far * is in ebx.
|
||
|
;
|
||
|
PUBLIC StopPhase2
|
||
|
StopPhase2 PROC NEAR
|
||
|
mov ax, 07b0h ; move the stack to 07b0:fff0h (17AF0)
|
||
|
mov ss, ax
|
||
|
mov ds, ax ; set DS=CS for TINY model.
|
||
|
mov es, ax ; set ES=CS for TINY model.
|
||
|
mov fs, ax ; set FS=CS for TINY model.
|
||
|
mov gs, ax ; set GS=CS for TINY model.
|
||
|
mov ax, 0fff0h
|
||
|
mov sp, ax
|
||
|
|
||
|
; Set ES:SI = BootInfo __far *.
|
||
|
mov si, bx
|
||
|
shr ebx, 16
|
||
|
mov es, bx
|
||
|
|
||
|
; Restore the PIC and BIOS IDT.
|
||
|
mov ax, es:[si].Struct_Microsoft_Singularity_BootInfo._BiosPicMask
|
||
|
mov dx, 0a0h
|
||
|
mov ah, al
|
||
|
out dx, al
|
||
|
mov ax, es:[si].Struct_Microsoft_Singularity_BootInfo._BiosPicMask
|
||
|
mov dx, 020h
|
||
|
out dx, al
|
||
|
|
||
|
lidt FWORD PTR es:[si].Struct_Microsoft_Singularity_BootInfo._BiosIdtPtr._limit
|
||
|
|
||
|
call StopPhase3
|
||
|
|
||
|
again:
|
||
|
jmp again
|
||
|
StopPhase2 ENDP
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
; empty_8042 -- wait for 8042 input buffer to drain
|
||
|
; al=0, z=0 => 8042 input buffer empty
|
||
|
; Uses:
|
||
|
; ax, flags
|
||
|
;
|
||
|
|
||
|
_8042_STATUS EQU 64h ; 8042 com port
|
||
|
_8042_DATA EQU 60h ; 8042 data port
|
||
|
_8042_BUF_FULL EQU 2 ; 8042 busy bit
|
||
|
|
||
|
empty_8042 PROC NEAR
|
||
|
sub cx,cx ; cx = 0, timeout loop counter
|
||
|
empty:
|
||
|
in al,_8042_STATUS ; read 8042 status port
|
||
|
jmp $+2
|
||
|
jmp $+2
|
||
|
jmp $+2
|
||
|
jmp $+2
|
||
|
and al,_8042_BUF_FULL ; test buffer full bit
|
||
|
loopnz empty
|
||
|
ret
|
||
|
empty_8042 ENDP
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
;EnableA20:
|
||
|
; Enables the A20 line for any machine. If the MachineType global variable
|
||
|
; is set to MCA, then it will call the EnableMcaA20 routine. If not, it
|
||
|
; will execute the ISA code for enabling the A20 line.
|
||
|
;
|
||
|
EnableA20 PROC NEAR
|
||
|
stc
|
||
|
mov ax, 2401h
|
||
|
int 15h ; Call BIOS Enable A20
|
||
|
jnc exit
|
||
|
|
||
|
mov ah,0dfh ; (AH) = Code for enable
|
||
|
|
||
|
; Enable or disable the A20 line (disable=dd, enable=df)
|
||
|
|
||
|
call empty_8042 ; ensure 8042 input buffer empty
|
||
|
jnz exit ; 8042 error return
|
||
|
|
||
|
mov al,0d1h ; 8042 cmd to write output port
|
||
|
out _8042_STATUS,al ; send cmd to 8042
|
||
|
call empty_8042 ; wait for 8042 to accept cmd
|
||
|
jnz exit ; 8042 error return
|
||
|
|
||
|
mov al,ah ; 8042 port data
|
||
|
out _8042_DATA,al ; output port data to 8042
|
||
|
call empty_8042
|
||
|
|
||
|
; We must wait for the a20 line to settle down, which (on an AT)
|
||
|
; may not happen until up to 20 usec after the 8042 has accepted
|
||
|
; the command. We make use of the fact that the 8042 will not
|
||
|
; accept another command until it is finished with the last one.
|
||
|
; The 0FFh command does a NULL 'Pulse Output Port'. Total execution
|
||
|
; time is on the order of 30 usec, easily satisfying the IBM 8042
|
||
|
; settling requirement.
|
||
|
;
|
||
|
mov al,0FFh ; Pulse Output Port (pulse no lines)
|
||
|
out _8042_STATUS,al ; send cmd to 8042
|
||
|
call empty_8042 ; wait for 8042 to accept cmd
|
||
|
exit:
|
||
|
ret
|
||
|
EnableA20 ENDP
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
; void Reset()
|
||
|
;
|
||
|
_CMOS_CTRL EQU 70h ; CMOS ctrl port
|
||
|
_CMOS_DATA EQU 71h ; CMOS data port
|
||
|
|
||
|
PUBLIC Reset
|
||
|
Reset PROC NEAR
|
||
|
mov al, 0bh ; Set up for control reg B
|
||
|
out _CMOS_CTRL, al
|
||
|
call empty_8042 ; stall
|
||
|
in al, _CMOS_DATA
|
||
|
and al, 0bfh ; Clear periodic interrupt enable.
|
||
|
out _CMOS_DATA, al
|
||
|
call empty_8042 ; stall
|
||
|
|
||
|
mov al, 0ah ; Set up for control reg A
|
||
|
out _CMOS_CTRL, al
|
||
|
call empty_8042 ; stall
|
||
|
in al, _CMOS_DATA
|
||
|
and al, 0f0h ; clear rate setting
|
||
|
or al, 006h
|
||
|
out _CMOS_DATA, al
|
||
|
|
||
|
mov al, 015h ; Set a "neutral" cmos address.
|
||
|
out _CMOS_CTRL, al
|
||
|
|
||
|
call empty_8042 ; ensure 8042 input buffer empty
|
||
|
mov al,0feh ; 8042 cmd to write output port
|
||
|
out _8042_STATUS,al ; send cmd to 8042
|
||
|
ret
|
||
|
Reset ENDP
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
; int GetSystemMap(SMAP_INFO __far *pDesc, uint32 __far *pNext)
|
||
|
;
|
||
|
PUBLIC BootGetSMAP
|
||
|
BootGetSMAP PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
|
||
|
push es
|
||
|
push esi
|
||
|
push edi
|
||
|
push ecx
|
||
|
push edx
|
||
|
push ebx
|
||
|
|
||
|
mov es, [bp+10]
|
||
|
mov di, [bp+8] ; pNext
|
||
|
mov ebx, es:[di]
|
||
|
|
||
|
mov es, [bp+6]
|
||
|
mov di, [bp+4] ; pDesc
|
||
|
|
||
|
mov eax, 0e820h
|
||
|
mov ecx, 20
|
||
|
mov edx, 534D4150h ; 'SMAP'
|
||
|
int 15h
|
||
|
|
||
|
mov es, [bp+10]
|
||
|
mov di, [bp+8] ; pNext
|
||
|
mov es:[di], ebx
|
||
|
|
||
|
pop ebx
|
||
|
pop edx
|
||
|
pop ecx
|
||
|
pop edi
|
||
|
pop esi
|
||
|
pop es
|
||
|
|
||
|
pop bp
|
||
|
ret
|
||
|
BootGetSMAP ENDP
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
; int BootCallVesa(uint16 ax, uint16 bx, uint16 cx, uint8 __far *pBuffer)
|
||
|
; ax = [bp+4]
|
||
|
; bx = [bp+6]
|
||
|
; cx = [bp+8]
|
||
|
; es:di = [bp+12/10]
|
||
|
;
|
||
|
if DEBUG_VESA_MODES
|
||
|
PUBLIC BootCallVesa
|
||
|
BootCallVesa PROC NEAR
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
|
||
|
push es
|
||
|
push esi
|
||
|
push edi
|
||
|
push ecx
|
||
|
push edx
|
||
|
push ebx
|
||
|
|
||
|
mov ax, [bp+4]
|
||
|
mov bx, [bp+6]
|
||
|
mov cx, [bp+8]
|
||
|
mov di, [bp+10] ; pNext
|
||
|
mov es, [bp+12]
|
||
|
|
||
|
int 10h
|
||
|
|
||
|
pop ebx
|
||
|
pop edx
|
||
|
pop ecx
|
||
|
pop edi
|
||
|
pop esi
|
||
|
pop es
|
||
|
|
||
|
pop bp
|
||
|
ret
|
||
|
BootCallVesa ENDP
|
||
|
endif
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
; void BootHalt(void)
|
||
|
;
|
||
|
PUBLIC BootHalt
|
||
|
BootHalt PROC NEAR
|
||
|
hlt
|
||
|
again: jmp again
|
||
|
ret
|
||
|
BootHalt ENDP
|
||
|
|
||
|
; void PModeTransfer(uint32 StartAddress, uint32 DestinationAddress, uint32 bytes);
|
||
|
; Entered in 16-bit real mode.
|
||
|
; Transitions to 32-bit protected mode and jumps to CopySector
|
||
|
; This is one of 3 functions that together comprise a single function call that moves from real to protected and back
|
||
|
;
|
||
|
; It appears that this can be done through the use of int15 AH=87h instead
|
||
|
; refer to http://www.ctyme.com/intr/rb-1527.htm for more information
|
||
|
;
|
||
|
|
||
|
PUBLIC PModeTransfer
|
||
|
PModeTransfer PROC NEAR
|
||
|
cli ; shut off interrupts
|
||
|
|
||
|
push bp
|
||
|
mov bp, sp
|
||
|
pushad
|
||
|
push ds
|
||
|
push es
|
||
|
push fs
|
||
|
push gs
|
||
|
|
||
|
mov ecx, [bp+12] ; # bytes to copy
|
||
|
mov edx, [bp+8] ; destination address
|
||
|
mov ebx, [bp+4] ; origin address
|
||
|
|
||
|
push dword ptr 0
|
||
|
popfd ; clear flags
|
||
|
|
||
|
xor ax,ax ; set the segments to null
|
||
|
mov gs,ax
|
||
|
mov es,ax
|
||
|
mov fs,ax
|
||
|
mov ss,ax
|
||
|
|
||
|
lgdt FWORD PTR [gdtptr1] ; load the GDT register
|
||
|
|
||
|
xor ax, ax
|
||
|
mov ds, ax ; set ds to null
|
||
|
|
||
|
mov eax, cr0 ; turn on protected mode
|
||
|
or al, Struct_Microsoft_Singularity_X86_CR0_PE
|
||
|
mov cr0, eax
|
||
|
|
||
|
; emit a 32-bit address intersegment jump
|
||
|
db 66h
|
||
|
db 0eah
|
||
|
dd offset _TEXT32:CopySector + 07b00h ; this is the 32-bit address of CopySector
|
||
|
dw offset codeSeg - offset nullSeg ; protected mode code segment = 08h
|
||
|
PModeTransfer ENDP
|
||
|
|
||
|
; this is the GDT we use for the PModeTransfer function
|
||
|
nullSeg GDTDesc <0, 0, 0, 0, 0, 0>
|
||
|
codeSeg GDTDesc <0FFFFh, 0h, 0h, 9ah, 0cfh, 0> ; flat 4GB code segment
|
||
|
dataSeg GDTDesc <0FFFFh, 0h, 0h, 92h, 0cfh, 0> ; flat 4GB data segment
|
||
|
codeSegR GDTDesc <0FFFFh, 07b00h, 000h, 09Ah, 000h, 000h> ; real mode code segment
|
||
|
dataSegR GDTDesc <0FFFFh, 07b00h, 000h, 092h, 000h, 000h> ; real mode data segment
|
||
|
gdtptr1 dw offset gdtptr1 - offset nullSeg
|
||
|
gdtptr2 dd offset nullSeg + 7b00h
|
||
|
|
||
|
; CopyReturn
|
||
|
; This is the 3rd piece of the real-protected-real jump (the 2nd piece is in the 32bit code seg)
|
||
|
CopyReturn PROC NEAR
|
||
|
|
||
|
; Turn off protected mode.
|
||
|
mov eax, cr0
|
||
|
and eax, NOT Struct_Microsoft_Singularity_X86_CR0_PE
|
||
|
mov cr0, eax
|
||
|
|
||
|
db 0EAh ; JMP FAR PTR to the next instruction
|
||
|
dw offset RealMode
|
||
|
dw 07b0h
|
||
|
|
||
|
RealMode:
|
||
|
; reset all segment registers:
|
||
|
mov ax, 07b0h
|
||
|
mov ss, ax
|
||
|
pop gs
|
||
|
pop fs
|
||
|
pop es
|
||
|
pop ds
|
||
|
|
||
|
sti ; reset interrupts and return to calling procedure
|
||
|
popad
|
||
|
pop bp
|
||
|
ret
|
||
|
CopyReturn ENDP
|
||
|
|
||
|
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
; void MpEnter(void)
|
||
|
;
|
||
|
; This function must be aligned on a 4KB boundary to be usable by IPI STARTUP.
|
||
|
; It should be the last 16-bit assembly function to avoid wasting space.
|
||
|
; NB: the entry point is 7c00 - 100 + ORG.
|
||
|
;
|
||
|
ORG 500h ; Base at 08000h. Must be 4KB aligned for IPI START.
|
||
|
PUBLIC MpEnter
|
||
|
MpEnter PROC NEAR
|
||
|
cli
|
||
|
mov ax, 07b0h ; Select data segment
|
||
|
mov ds, ax
|
||
|
|
||
|
spinlock:
|
||
|
cmp MpStartupLock, 0
|
||
|
je get_lock
|
||
|
pause
|
||
|
jmp spinlock
|
||
|
|
||
|
get_lock:
|
||
|
mov ax, 1
|
||
|
xchg ax, MpStartupLock
|
||
|
cmp ax, 0
|
||
|
jne spinlock
|
||
|
|
||
|
; Switch to tiny mode with same descriptors as uniprocessor and reuse
|
||
|
; real-mode stack.
|
||
|
mov ax, 07b0h
|
||
|
mov ds, ax ; set GS=FS=ES=DS=CS for TINY model.
|
||
|
mov es, ax
|
||
|
mov fs, ax
|
||
|
mov gs, ax
|
||
|
mov ss, ax
|
||
|
mov sp, 0fff0h
|
||
|
push ax
|
||
|
push OFFSET init_cpu
|
||
|
retf
|
||
|
|
||
|
init_cpu:
|
||
|
call MpBootPhase1 ; Point of no return
|
||
|
|
||
|
MpEnter ENDP
|
||
|
|
||
|
; void MpBootPhase2(Struct_Microsoft_Singularity_BootInfo __far *, Struct_Microsoft_Singularity_CpuInfo*)
|
||
|
; Entered in 16-bit real-mode and transitions to 32-bit Protected mode.
|
||
|
PUBLIC MpBootPhase2
|
||
|
MpBootPhase2 PROC NEAR
|
||
|
push bp
|
||
|
xor ebp, ebp
|
||
|
mov bp, sp
|
||
|
mov bx, [bp + 8] ; CpuInfo
|
||
|
mov ax, [bp + 6] ; segment(BootInfo)
|
||
|
mov bp, [bp + 4] ; bp + 4 = BootInfo
|
||
|
mov ss, ax
|
||
|
mov ds, ax
|
||
|
|
||
|
; disable interrupts until kernel turns them back on.
|
||
|
cli
|
||
|
|
||
|
; prepare for jump to 32-bit protected mode.
|
||
|
; edx = physical address of Struct_Microsoft_Singularity_BootInfo.
|
||
|
;
|
||
|
mov edx, DWORD PTR [bp].Struct_Microsoft_Singularity_BootInfo._Info32
|
||
|
|
||
|
; prepare segments
|
||
|
lgdt FWORD PTR [bx].Struct_Microsoft_Singularity_CpuInfo._GdtPtr._limit
|
||
|
|
||
|
; Turn protected mode on and jump to flush prefetch
|
||
|
mov eax, cr0
|
||
|
or eax, Struct_Microsoft_Singularity_X86_CR0_PE + Struct_Microsoft_Singularity_X86_CR0_NE
|
||
|
mov cr0, eax
|
||
|
jmp cont
|
||
|
cont:
|
||
|
; Load protected stack segment registers.
|
||
|
mov ax,Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtRS - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov ss,ax
|
||
|
mov esp,ebp
|
||
|
|
||
|
; push the 16:32 address onto the stack, then "return" to it.
|
||
|
push 0
|
||
|
push Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPC - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov eax, 07b00h + OFFSET MpBootPhase3
|
||
|
push eax
|
||
|
OPERAND_SIZE_OVERLOAD
|
||
|
retf
|
||
|
MpBootPhase2 ENDP
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
; 32-bit code segment
|
||
|
;
|
||
|
|
||
|
.686p
|
||
|
_TEXT32 segment para public use32 'CODE' ; this segment contains all 32-bit
|
||
|
assume cs:_TEXT32, ds:_TEXT32
|
||
|
|
||
|
; BootPhase3:
|
||
|
; Entered in 32-bit protected mode with paging disabled.
|
||
|
; Configures the segment registers and stack. Does not turn on paging.
|
||
|
; Transitions to the 32-bit loader (undump.cpp)
|
||
|
PUBLIC BootPhase3
|
||
|
BootPhase3 PROC NEAR
|
||
|
; edx = physical address of Struct_Microsoft_Singularity_BootInfo structure.
|
||
|
|
||
|
; load the 32-bit segment selectors.
|
||
|
mov bx, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPD - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov ds, bx
|
||
|
mov es, bx
|
||
|
mov ss, bx
|
||
|
mov bx, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPF - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov fs, bx
|
||
|
mov bx, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPG - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov gs, bx
|
||
|
|
||
|
; set the initial stack.
|
||
|
mov esp, Struct_Microsoft_Singularity_BootInfo_REAL_STACK
|
||
|
mov ebp, Struct_Microsoft_Singularity_BootInfo_REAL_PBOOTINFO
|
||
|
mov [ebp], edx
|
||
|
mov ebp, esp
|
||
|
|
||
|
; copy the undumper into place.
|
||
|
mov esi, DWORD PTR [edx].Struct_Microsoft_Singularity_BootInfo._Undump
|
||
|
mov edi, undump_dst
|
||
|
mov ecx, undump_siz
|
||
|
call memcopy
|
||
|
|
||
|
; Select the stack
|
||
|
mov esp, Struct_Microsoft_Singularity_BootInfo_REAL_STACK
|
||
|
|
||
|
; Enable super pages. note that MASM doesn't support the opcode
|
||
|
; for these instructions. so we are going to emit them manually
|
||
|
|
||
|
MOV_EAX_CR4
|
||
|
or eax, (Struct_Microsoft_Singularity_X86_CR4_PAE + Struct_Microsoft_Singularity_X86_CR4_PSE + Struct_Microsoft_Singularity_X86_CR4_PCE + Struct_Microsoft_Singularity_X86_CR4_OSFXSR)
|
||
|
MOV_CR4_EAX
|
||
|
|
||
|
;;; ifdef DOUBLE_FAULT_HANDLER
|
||
|
; Set the PDBR
|
||
|
mov eax, DWORD PTR [edx].Struct_Microsoft_Singularity_BootInfo._Pdpt32
|
||
|
mov cr3, eax
|
||
|
|
||
|
; Turn on paging.
|
||
|
mov eax, cr0
|
||
|
or eax, Struct_Microsoft_Singularity_X86_CR0_PG + Struct_Microsoft_Singularity_X86_CR0_WP
|
||
|
mov cr0, eax
|
||
|
|
||
|
jmp @reload_tlb
|
||
|
ALIGN 010h
|
||
|
@reload_tlb:
|
||
|
;;; endif
|
||
|
|
||
|
; Set the TSS selector
|
||
|
mov ax, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtTSS - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
ltr ax
|
||
|
|
||
|
; Set the IO privilege level to 3, so that ring-3 apps can disable
|
||
|
; interrupts. (TODO: eliminate CLI from ring-3 apps.)
|
||
|
pushfd
|
||
|
pop eax
|
||
|
or eax, Struct_Microsoft_Singularity_X86_EFlags_IOPL
|
||
|
push eax
|
||
|
popfd
|
||
|
|
||
|
; Set up the initial stack.
|
||
|
mov esp, Struct_Microsoft_Singularity_BootInfo_REAL_STACK
|
||
|
xor ecx, ecx
|
||
|
push ecx
|
||
|
push ecx
|
||
|
push ecx
|
||
|
push ecx
|
||
|
push ecx ; cpu = 0 (bsp)
|
||
|
push edx ; bootinfo
|
||
|
|
||
|
mov eax, undump_ent
|
||
|
call eax
|
||
|
|
||
|
BootPhase3 ENDP
|
||
|
|
||
|
; MpBootPhase3:
|
||
|
; Entered in 32-bit protected mode with paging disabled.
|
||
|
; Configures the segment registers and stack. Does not turn on paging.
|
||
|
; On entry edx contains the physical address of the BootInfo structure.
|
||
|
PUBLIC MpBootPhase3
|
||
|
MpBootPhase3 PROC NEAR
|
||
|
; load the 32-bit segment selectors.
|
||
|
mov bx, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPD - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov ds, bx
|
||
|
mov es, bx
|
||
|
mov ss, bx
|
||
|
mov bx, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPF - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov fs, bx
|
||
|
mov bx, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtPG - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov gs, bx
|
||
|
|
||
|
; locate pre-allocated kernel stack
|
||
|
imul eax, [edx].Struct_Microsoft_Singularity_BootInfo._MpCpuCount, SIZEOF Struct_Microsoft_Singularity_CpuInfo
|
||
|
add eax, Struct_Microsoft_Singularity_BootInfo._Cpu0
|
||
|
mov eax, DWORD PTR [edx + eax].Struct_Microsoft_Singularity_CpuInfo._KernelStack
|
||
|
|
||
|
; switch to kernel stack
|
||
|
mov esp, eax
|
||
|
mov ebp, eax
|
||
|
|
||
|
; Save cpu number as other starting CPU's will bump value
|
||
|
mov ecx, [edx].Struct_Microsoft_Singularity_BootInfo._MpCpuCount
|
||
|
|
||
|
mov [edx].Struct_Microsoft_Singularity_BootInfo._MpStatus32, Struct_Microsoft_Singularity_MpBootStatus_Phase3Entry
|
||
|
|
||
|
; Enable super pages. note that MASM doesn't support the opcode
|
||
|
; for these instructions. so we are going to emit them manually
|
||
|
MOV_EAX_CR4
|
||
|
or eax, (Struct_Microsoft_Singularity_X86_CR4_PAE + Struct_Microsoft_Singularity_X86_CR4_PSE + Struct_Microsoft_Singularity_X86_CR4_PCE + Struct_Microsoft_Singularity_X86_CR4_OSFXSR)
|
||
|
MOV_CR4_EAX
|
||
|
|
||
|
mov eax, DWORD PTR [edx].Struct_Microsoft_Singularity_BootInfo._Pdpt32
|
||
|
mov cr3, eax
|
||
|
|
||
|
; Turn on paging.
|
||
|
mov eax, cr0
|
||
|
or eax, Struct_Microsoft_Singularity_X86_CR0_PG + Struct_Microsoft_Singularity_X86_CR0_WP
|
||
|
mov cr0, eax
|
||
|
|
||
|
jmp @reload_tlb_mp
|
||
|
ALIGN 010h
|
||
|
@reload_tlb_mp:
|
||
|
|
||
|
; stack already has cpu number on it
|
||
|
push ecx ; cpu number
|
||
|
push edx ; bootinfo
|
||
|
mov eax, undump_ent
|
||
|
call eax
|
||
|
|
||
|
deadloop:
|
||
|
cli
|
||
|
hlt
|
||
|
jmp deadloop
|
||
|
|
||
|
MpBootPhase3 ENDP
|
||
|
|
||
|
; StopPhase0
|
||
|
; Entered in 32-bit protected mode with paging enabled..
|
||
|
; Turns off paging.
|
||
|
; Transitions to the 16-bit protected mode (StopPhase1)
|
||
|
; Loads BootInfo __far * into ebx.
|
||
|
PUBLIC StopPhase0
|
||
|
StopPhase0 PROC NEAR
|
||
|
; no intrs for a while
|
||
|
; Configures EBX = Struct_Microsoft_Singularity_BootInfo
|
||
|
cli
|
||
|
|
||
|
mov esp, Struct_Microsoft_Singularity_BootInfo_REAL_STACK
|
||
|
mov ebp, Struct_Microsoft_Singularity_BootInfo_REAL_PBOOTINFO
|
||
|
mov ebx, [ebp]
|
||
|
|
||
|
ifdef DEBUG_BOOT
|
||
|
mov edx, 0b8000h
|
||
|
mov ah, 01fh
|
||
|
mov al, '['
|
||
|
mov [edx], ax
|
||
|
|
||
|
mov edx, 0b8002h
|
||
|
mov ah, 01fh
|
||
|
mov al, '1'
|
||
|
mov [edx], ax
|
||
|
endif
|
||
|
|
||
|
; Set the IO privilege level to 0.
|
||
|
pushfd
|
||
|
pop eax
|
||
|
and eax, NOT Struct_Microsoft_Singularity_X86_EFlags_IOPL
|
||
|
push eax
|
||
|
popfd
|
||
|
|
||
|
; Turn off paging.
|
||
|
mov eax, cr0
|
||
|
and eax, NOT (Struct_Microsoft_Singularity_X86_CR0_PG + Struct_Microsoft_Singularity_X86_CR0_WP)
|
||
|
mov cr0, eax
|
||
|
|
||
|
; Flush and reset the TLB.
|
||
|
mov eax,0
|
||
|
mov cr3,eax
|
||
|
|
||
|
jmp reload_tlb
|
||
|
ALIGN 010h
|
||
|
reload_tlb:
|
||
|
|
||
|
; restore the segments to the 16-bit defaults from the Gdt
|
||
|
mov ebx, [ebx].Struct_Microsoft_Singularity_BootInfo._Info16
|
||
|
mov ax, Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtRS - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
mov ds, ax
|
||
|
mov es, ax
|
||
|
mov fs, ax
|
||
|
mov gs, ax
|
||
|
mov ss, ax
|
||
|
|
||
|
db 0EAh ; JMP FAR PTR
|
||
|
dd offset _TEXT:StopPhase1 ; RC:StopPhase1
|
||
|
dw Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtRC - Struct_Microsoft_Singularity_BootInfo._Cpu0._GdtNull
|
||
|
|
||
|
again:
|
||
|
jmp again
|
||
|
|
||
|
StopPhase0 ENDP
|
||
|
|
||
|
; Copy a memory region.
|
||
|
; [in] ds:si = pointer to source buffer.
|
||
|
; [in] es:di = pointer to destination buffer.
|
||
|
; [in] ecx = number of bytes to copy
|
||
|
;
|
||
|
memcopy PROC NEAR
|
||
|
jecxz done
|
||
|
cld
|
||
|
add ecx,3 ; Pad to DWORD
|
||
|
shr ecx,2 ; Shift ECX for count of dwords
|
||
|
rep movsd ; Copy the data.
|
||
|
done:
|
||
|
ret
|
||
|
memcopy ENDP
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;;;
|
||
|
;;; The IDT_ENTER building macros insure that each IDT target has
|
||
|
;;; an offset of form _IdtEnter + 0x10 * interrupt_number.
|
||
|
;;;
|
||
|
public IdtTarget
|
||
|
public IdtEnter0
|
||
|
public IdtEnter1
|
||
|
public IdtEnterN
|
||
|
|
||
|
IDT_TARGET_ARGS STRUCT 1
|
||
|
_ret uint32 ?
|
||
|
_edi uint32 ?
|
||
|
_esi uint32 ?
|
||
|
_ebp uint32 ?
|
||
|
_esp uint32 ?
|
||
|
_ebx uint32 ?
|
||
|
_edx uint32 ?
|
||
|
_ecx uint32 ?
|
||
|
_eax uint32 ?
|
||
|
_num uint32 ?
|
||
|
_err uint32 ?
|
||
|
_eip uint32 ?
|
||
|
_cs0 uint32 ?
|
||
|
_efl uint32 ?
|
||
|
IDT_TARGET_ARGS ENDS
|
||
|
|
||
|
IDT_ENTER_CLEAN MACRO num
|
||
|
push 0 ; No error
|
||
|
push num
|
||
|
jmp _IdtEnterBody
|
||
|
align 16
|
||
|
ENDM
|
||
|
|
||
|
IDT_ENTER_ERR MACRO num
|
||
|
push num
|
||
|
jmp _IdtEnterBody
|
||
|
align 16
|
||
|
ENDM
|
||
|
|
||
|
align 16
|
||
|
IdtEnter PROC NEAR
|
||
|
IdtEnter0 LABEL NEAR
|
||
|
IDT_ENTER_CLEAN 000h ; #DE Divide-by-Zero
|
||
|
IdtEnter1::
|
||
|
IDT_ENTER_CLEAN 001h ; #DB Debug Exception
|
||
|
IDT_ENTER_CLEAN 002h ; NMI Non-Maskable-Interrupt
|
||
|
IDT_ENTER_CLEAN 003h ; #BP Breakpoint
|
||
|
IDT_ENTER_CLEAN 004h ; #OF OVerflow
|
||
|
IDT_ENTER_CLEAN 005h ; #BR Bound-Range
|
||
|
IDT_ENTER_CLEAN 006h ; #UD Invalid Opcode
|
||
|
IDT_ENTER_CLEAN 007h ; #NM Device Not Available
|
||
|
IDT_ENTER_ERR 008h ; #DF Double Fault
|
||
|
IDT_ENTER_CLEAN 009h ; Unused (was x87 segment except)
|
||
|
IDT_ENTER_ERR 00ah ; #TS Invalid TSS
|
||
|
IDT_ENTER_ERR 00bh ; #NP Sgement Not Present
|
||
|
IDT_ENTER_ERR 00ch ; #SS Stack Exception
|
||
|
IDT_ENTER_ERR 00dh ; #GP General Protection
|
||
|
IDT_ENTER_ERR 00eh ; #PF Page Fault
|
||
|
IDT_ENTER_CLEAN 00fh ; Reserved
|
||
|
IDT_ENTER_CLEAN 010h ; #MF x87 Math Error
|
||
|
IDT_ENTER_ERR 011h ; #AC Alignment Check
|
||
|
IDT_ENTER_CLEAN 012h ; #MC Machine Check
|
||
|
IDT_ENTER_CLEAN 013h ; #XF SIMD Exception
|
||
|
|
||
|
_num = 014h ; 014h to 020h
|
||
|
WHILE _num LE 020h
|
||
|
IDT_ENTER_CLEAN _num
|
||
|
_num = _num + 1
|
||
|
ENDM
|
||
|
IdtEnterN::
|
||
|
|
||
|
_IdtEnterBody::
|
||
|
pushad
|
||
|
mov eax, cr2
|
||
|
push eax
|
||
|
|
||
|
LEA_EAX_REALATIVE IdtTarget
|
||
|
mov eax, [eax]
|
||
|
call eax
|
||
|
again: jmp again
|
||
|
|
||
|
align 4
|
||
|
IdtTarget::
|
||
|
dd 0
|
||
|
|
||
|
IdtEnter endp
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
|
||
|
if 1
|
||
|
; Print a DWORD to the screen
|
||
|
; [in] ebx = address of screen
|
||
|
; [in] eax = dword to print
|
||
|
; [in] ecx = trashed for temporary
|
||
|
;
|
||
|
printdw PROC NEAR
|
||
|
mov ecx, eax
|
||
|
shr ecx, 28
|
||
|
and ecx, 0fh
|
||
|
add ecx, 00f30h
|
||
|
cmp ecx, 00f3ah
|
||
|
jl print28
|
||
|
add ecx, 7h
|
||
|
print28:
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
mov ecx, eax
|
||
|
shr ecx, 24
|
||
|
and ecx, 0fh
|
||
|
add ecx, 00f30h
|
||
|
cmp ecx, 00f3ah
|
||
|
jl print24
|
||
|
add ecx, 7h
|
||
|
print24:
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
mov ecx, eax
|
||
|
shr ecx, 20
|
||
|
and ecx, 0fh
|
||
|
add ecx, 00f30h
|
||
|
cmp ecx, 00f3ah
|
||
|
jl print20
|
||
|
add ecx, 7h
|
||
|
print20:
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
mov ecx, eax
|
||
|
shr ecx, 16
|
||
|
and ecx, 0fh
|
||
|
add ecx, 00f30h
|
||
|
cmp ecx, 00f3ah
|
||
|
jl print16
|
||
|
add ecx, 7h
|
||
|
print16:
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
mov ecx, eax
|
||
|
shr ecx, 12
|
||
|
and ecx, 0fh
|
||
|
add ecx, 00f30h
|
||
|
cmp ecx, 00f3ah
|
||
|
jl print12
|
||
|
add ecx, 7h
|
||
|
print12:
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
mov ecx, eax
|
||
|
shr ecx, 08
|
||
|
and ecx, 0fh
|
||
|
add ecx, 00f30h
|
||
|
cmp ecx, 00f3ah
|
||
|
jl print08
|
||
|
add ecx, 7h
|
||
|
print08:
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
mov ecx, eax
|
||
|
shr ecx, 04
|
||
|
and ecx, 0fh
|
||
|
add ecx, 00f30h
|
||
|
cmp ecx, 00f3ah
|
||
|
jl print04
|
||
|
add ecx, 7h
|
||
|
print04:
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
mov ecx, eax
|
||
|
shr ecx, 00
|
||
|
and ecx, 0fh
|
||
|
add ecx, 00f30h
|
||
|
cmp ecx, 00f3ah
|
||
|
jl print00
|
||
|
add ecx, 7h
|
||
|
print00:
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
mov ecx, 00f20h
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
mov [ebx+0], ecx
|
||
|
add ebx, 2
|
||
|
|
||
|
ret
|
||
|
printdw ENDP
|
||
|
endif
|
||
|
|
||
|
|
||
|
; CopySector:
|
||
|
; Entered in 32-bit protected mode with paging disabled.
|
||
|
; this routine moves back into 16-bit code by going to CopyReturn
|
||
|
; on the way, we'll have it move ecx bytes from [ebx] to [edx]
|
||
|
CopySector PROC NEAR
|
||
|
|
||
|
; load the 32-bit segment selectors.
|
||
|
mov ax, dataSeg - nullSeg
|
||
|
mov ds, ax
|
||
|
mov es, ax
|
||
|
mov fs, ax
|
||
|
mov gs, ax
|
||
|
mov ss, ax
|
||
|
|
||
|
jecxz copydone
|
||
|
|
||
|
cld
|
||
|
add ecx,3 ; Pad ecx to DWORD
|
||
|
shr ecx,2 ; Shift ecx for count of dwords
|
||
|
|
||
|
mov esi, ebx
|
||
|
mov edi, edx
|
||
|
rep movsd
|
||
|
|
||
|
copydone:
|
||
|
; set the segment registers back to real mode selectors
|
||
|
mov ax, dataSegR - nullSeg
|
||
|
mov ds, ax
|
||
|
mov es, ax
|
||
|
mov fs, ax
|
||
|
mov gs, ax
|
||
|
mov ss, ax
|
||
|
|
||
|
; now return to 16-bit code...
|
||
|
db 0EAh ; emit a JMP FAR PTR
|
||
|
dd offset _TEXT:CopyReturn
|
||
|
dw codeSegR - nullSeg
|
||
|
|
||
|
CopySector ENDP
|
||
|
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
;
|
||
|
; 32-bit Code Generated by C Compiler
|
||
|
;
|
||
|
; Contains:
|
||
|
; undump_ent EQU 001112d5h
|
||
|
; undump_dst EQU 00111000h
|
||
|
; undump_siz EQU 00000480h
|
||
|
; undump_dat uint8 000h,080h,00bh,000h,030h,031h,032h,033h,...
|
||
|
;
|
||
|
PUBLIC undump_dat
|
||
|
include undump.asb
|
||
|
|
||
|
_TEXT32 ends
|
||
|
|
||
|
end BootPhase0
|
||
|
;
|
||
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; End of File.
|