;------------------------------------------------------------------------------ | |
;* | |
;* Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR> | |
;* This program and the accompanying materials | |
;* are licensed and made available under the terms and conditions of the BSD License | |
;* which accompanies this distribution. The full text of the license may be found at | |
;* http://opensource.org/licenses/bsd-license.php | |
;* | |
;* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
;* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
;* | |
;* efi32.asm | |
;* | |
;* Abstract: | |
;* | |
;------------------------------------------------------------------------------ | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; Now in 32-bit protected mode. | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
.486 | |
.model flat | |
.stack | |
.code | |
org 21000h | |
DEFAULT_HANDLER_SIZE EQU INT1 - INT0 | |
JmpCommonIdtEntry macro | |
; jmp commonIdtEntry - this must be hand coded to keep the assembler from | |
; using a 8 bit reletive jump when the entries are | |
; within 255 bytes of the common entry. This must | |
; be done to maintain the consistency of the size | |
; of entry points... | |
db 0e9h ; jmp 16 bit relative | |
dd commonIdtEntry - $ - 4 ; offset to jump to | |
endm | |
Start: | |
mov ax,bx ; flat data descriptor in BX | |
mov ds,ax | |
mov es,ax | |
mov fs,ax | |
mov gs,ax | |
mov ss,ax | |
mov esp,0001ffff0h | |
call ClearScreen | |
; Populate IDT with meaningful offsets for exception handlers... | |
sidt fword ptr [Idtr] ; get fword address of IDT | |
mov eax, offset Halt | |
mov ebx, eax ; use bx to copy 15..0 to descriptors | |
shr eax, 16 ; use ax to copy 31..16 to descriptors | |
mov ecx, 78h ; 78h IDT entries to initialize with unique entry points (exceptions) | |
mov esi, [offset Idtr + 2] | |
mov edi, [esi] | |
@@: ; loop through all IDT entries exception handlers and initialize to default handler | |
mov word ptr [edi], bx ; write bits 15..0 of offset | |
mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT | |
mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present | |
mov word ptr [edi+6], ax ; write bits 31..16 of offset | |
add edi, 8 ; move up to next descriptor | |
add bx, DEFAULT_HANDLER_SIZE ; move to next entry point | |
loop @b ; loop back through again until all descriptors are initialized | |
;; at this point edi contains the offset of the descriptor for INT 20 | |
;; and bx contains the low 16 bits of the offset of the default handler | |
;; so initialize all the rest of the descriptors with these two values... | |
; mov ecx, 101 ; there are 100 descriptors left (INT 20 (14h) - INT 119 (77h) | |
;@@: ; loop through all IDT entries exception handlers and initialize to default handler | |
; mov word ptr [edi], bx ; write bits 15..0 of offset | |
; mov word ptr [edi+2], 20h ; SYS_CODE_SEL from GDT | |
; mov word ptr [edi+4], 0e00h OR 8000h ; type = 386 interrupt gate, present | |
; mov word ptr [edi+6], ax ; write bits 31..16 of offset | |
; add edi, 8 ; move up to next descriptor | |
; loop @b ; loop back through again until all descriptors are initialized | |
;; DUMP location of IDT and several of the descriptors | |
; mov ecx, 8 | |
; mov eax, [offset Idtr + 2] | |
; mov eax, [eax] | |
; mov edi, 0b8000h | |
; call PrintDword | |
; mov esi, eax | |
; mov edi, 0b80a0h | |
; jmp OuterLoop | |
;; | |
;; just for fun, let's do a software interrupt to see if we correctly land in the exception handler... | |
; mov eax, 011111111h | |
; mov ebx, 022222222h | |
; mov ecx, 033333333h | |
; mov edx, 044444444h | |
; mov ebp, 055555555h | |
; mov esi, 066666666h | |
; mov edi, 077777777h | |
; push 011111111h | |
; push 022222222h | |
; push 033333333h | |
; int 119 | |
mov esi,022000h ; esi = 22000 | |
mov eax,[esi+014h] ; eax = [22014] | |
add esi,eax ; esi = 22000 + [22014] = Base of EFILDR.C | |
mov ebp,[esi+03ch] ; ebp = [22000 + [22014] + 3c] = NT Image Header for EFILDR.C | |
add ebp,esi | |
mov edi,[ebp+034h] ; edi = [[22000 + [22014] + 3c] + 30] = ImageBase | |
mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint | |
add eax,edi ; eax = ImageBase + EntryPoint | |
mov dword ptr [EfiLdrOffset],eax ; Modify far jump instruction for correct entry point | |
mov bx,word ptr[ebp+6] ; bx = Number of sections | |
xor eax,eax | |
mov ax,word ptr[ebp+014h] ; ax = Optional Header Size | |
add ebp,eax | |
add ebp,018h ; ebp = Start of 1st Section | |
SectionLoop: | |
push esi ; Save Base of EFILDR.C | |
push edi ; Save ImageBase | |
add esi,[ebp+014h] ; esi = Base of EFILDR.C + PointerToRawData | |
add edi,[ebp+00ch] ; edi = ImageBase + VirtualAddress | |
mov ecx,[ebp+010h] ; ecs = SizeOfRawData | |
cld | |
shr ecx,2 | |
rep movsd | |
pop edi ; Restore ImageBase | |
pop esi ; Restore Base of EFILDR.C | |
add bp,028h ; ebp = ebp + 028h = Pointer to next section record | |
dec bx | |
cmp bx,0 | |
jne SectionLoop | |
movzx eax, word ptr [Idtr] ; get size of IDT | |
inc eax | |
add eax, dword ptr [Idtr + 2] ; add to base of IDT to get location of memory map... | |
push eax ; push memory map location on stack for call to EFILDR... | |
push eax ; push return address (useless, just for stack balance) | |
db 0b8h | |
EfiLdrOffset: | |
dd 000401000h ; Offset of EFILDR | |
; mov eax, 401000h | |
push eax | |
ret | |
; db "**** DEFAULT IDT ENTRY ***",0 | |
align 02h | |
Halt: | |
INT0: | |
push 0h ; push error code place holder on the stack | |
push 0h | |
JmpCommonIdtEntry | |
; db 0e9h ; jmp 16 bit reletive | |
; dd commonIdtEntry - $ - 4 ; offset to jump to | |
INT1: | |
push 0h ; push error code place holder on the stack | |
push 1h | |
JmpCommonIdtEntry | |
INT2: | |
push 0h ; push error code place holder on the stack | |
push 2h | |
JmpCommonIdtEntry | |
INT3: | |
push 0h ; push error code place holder on the stack | |
push 3h | |
JmpCommonIdtEntry | |
INT4: | |
push 0h ; push error code place holder on the stack | |
push 4h | |
JmpCommonIdtEntry | |
INT5: | |
push 0h ; push error code place holder on the stack | |
push 5h | |
JmpCommonIdtEntry | |
INT6: | |
push 0h ; push error code place holder on the stack | |
push 6h | |
JmpCommonIdtEntry | |
INT7: | |
push 0h ; push error code place holder on the stack | |
push 7h | |
JmpCommonIdtEntry | |
INT8: | |
; Double fault causes an error code to be pushed so no phony push necessary | |
nop | |
nop | |
push 8h | |
JmpCommonIdtEntry | |
INT9: | |
push 0h ; push error code place holder on the stack | |
push 9h | |
JmpCommonIdtEntry | |
INT10: | |
; Invalid TSS causes an error code to be pushed so no phony push necessary | |
nop | |
nop | |
push 10 | |
JmpCommonIdtEntry | |
INT11: | |
; Segment Not Present causes an error code to be pushed so no phony push necessary | |
nop | |
nop | |
push 11 | |
JmpCommonIdtEntry | |
INT12: | |
; Stack fault causes an error code to be pushed so no phony push necessary | |
nop | |
nop | |
push 12 | |
JmpCommonIdtEntry | |
INT13: | |
; GP fault causes an error code to be pushed so no phony push necessary | |
nop | |
nop | |
push 13 | |
JmpCommonIdtEntry | |
INT14: | |
; Page fault causes an error code to be pushed so no phony push necessary | |
nop | |
nop | |
push 14 | |
JmpCommonIdtEntry | |
INT15: | |
push 0h ; push error code place holder on the stack | |
push 15 | |
JmpCommonIdtEntry | |
INT16: | |
push 0h ; push error code place holder on the stack | |
push 16 | |
JmpCommonIdtEntry | |
INT17: | |
; Alignment check causes an error code to be pushed so no phony push necessary | |
nop | |
nop | |
push 17 | |
JmpCommonIdtEntry | |
INT18: | |
push 0h ; push error code place holder on the stack | |
push 18 | |
JmpCommonIdtEntry | |
INT19: | |
push 0h ; push error code place holder on the stack | |
push 19 | |
JmpCommonIdtEntry | |
INTUnknown: | |
REPEAT (78h - 20) | |
push 0h ; push error code place holder on the stack | |
; push xxh ; push vector number | |
db 06ah | |
db ( $ - INTUnknown - 3 ) / 9 + 20 ; vector number | |
JmpCommonIdtEntry | |
ENDM | |
commonIdtEntry: | |
pushad | |
mov ebp, esp | |
;; | |
;; At this point the stack looks like this: | |
;; | |
;; eflags | |
;; Calling CS | |
;; Calling EIP | |
;; Error code or 0 | |
;; Int num or 0ffh for unknown int num | |
;; eax | |
;; ecx | |
;; edx | |
;; ebx | |
;; esp | |
;; ebp | |
;; esi | |
;; edi <------- ESP, EBP | |
;; | |
call ClearScreen | |
mov esi, offset String1 | |
call PrintString | |
mov eax, [ebp + 32] ;; move Int number into EAX | |
cmp eax, 19 | |
ja PrintDefaultString | |
PrintExceptionString: | |
shl eax, 2 ;; multiply by 4 to get offset from StringTable to actual string address | |
add eax, offset StringTable | |
mov esi, [eax] | |
jmp PrintTheString | |
PrintDefaultString: | |
mov esi, offset IntUnknownString | |
; patch Int number | |
mov edx, eax | |
call A2C | |
mov [esi + 1], al | |
mov eax, edx | |
shr eax, 4 | |
call A2C | |
mov [esi], al | |
PrintTheString: | |
call PrintString | |
mov esi, offset String2 | |
call PrintString | |
mov eax, [ebp+44] ; CS | |
call PrintDword | |
mov al, ':' | |
mov byte ptr [edi], al | |
add edi, 2 | |
mov eax, [ebp+40] ; EIP | |
call PrintDword | |
mov esi, offset String3 | |
call PrintString | |
mov edi, 0b8140h | |
mov esi, offset StringEax ; eax | |
call PrintString | |
mov eax, [ebp+28] | |
call PrintDword | |
mov esi, offset StringEbx ; ebx | |
call PrintString | |
mov eax, [ebp+16] | |
call PrintDword | |
mov esi, offset StringEcx ; ecx | |
call PrintString | |
mov eax, [ebp+24] | |
call PrintDword | |
mov esi, offset StringEdx ; edx | |
call PrintString | |
mov eax, [ebp+20] | |
call PrintDword | |
mov esi, offset StringEcode ; error code | |
call PrintString | |
mov eax, [ebp+36] | |
call PrintDword | |
mov edi, 0b81e0h | |
mov esi, offset StringEsp ; esp | |
call PrintString | |
mov eax, [ebp+12] | |
call PrintDword | |
mov esi, offset StringEbp ; ebp | |
call PrintString | |
mov eax, [ebp+8] | |
call PrintDword | |
mov esi, offset StringEsi ; esi | |
call PrintString | |
mov eax, [ebp+4] | |
call PrintDword | |
mov esi, offset StringEdi ; edi | |
call PrintString | |
mov eax, [ebp] | |
call PrintDword | |
mov esi, offset StringEflags ; eflags | |
call PrintString | |
mov eax, [ebp+48] | |
call PrintDword | |
mov edi, 0b8320h | |
mov esi, ebp | |
add esi, 52 | |
mov ecx, 8 | |
OuterLoop: | |
push ecx | |
mov ecx, 8 | |
mov edx, edi | |
InnerLoop: | |
mov eax, [esi] | |
call PrintDword | |
add esi, 4 | |
mov al, ' ' | |
mov [edi], al | |
add edi, 2 | |
loop InnerLoop | |
pop ecx | |
add edx, 0a0h | |
mov edi, edx | |
loop OuterLoop | |
mov edi, 0b8960h | |
mov eax, [ebp+40] ; EIP | |
sub eax, 32 * 4 | |
mov esi, eax ; esi = eip - 32 DWORD linear (total 64 DWORD) | |
mov ecx, 8 | |
OuterLoop1: | |
push ecx | |
mov ecx, 8 | |
mov edx, edi | |
InnerLoop1: | |
mov eax, [esi] | |
call PrintDword | |
add esi, 4 | |
mov al, ' ' | |
mov [edi], al | |
add edi, 2 | |
loop InnerLoop1 | |
pop ecx | |
add edx, 0a0h | |
mov edi, edx | |
loop OuterLoop1 | |
; wbinvd ; Ken: this intruction does not support in early than 486 arch | |
@@: | |
jmp @b | |
; | |
; return | |
; | |
mov esp, ebp | |
popad | |
add esp, 8 ; error code and INT number | |
iretd | |
PrintString: | |
push eax | |
@@: | |
mov al, byte ptr [esi] | |
cmp al, 0 | |
je @f | |
mov byte ptr [edi], al | |
inc esi | |
add edi, 2 | |
jmp @b | |
@@: | |
pop eax | |
ret | |
;; EAX contains dword to print | |
;; EDI contains memory location (screen location) to print it to | |
PrintDword: | |
push ecx | |
push ebx | |
push eax | |
mov ecx, 8 | |
looptop: | |
rol eax, 4 | |
mov bl, al | |
and bl, 0fh | |
add bl, '0' | |
cmp bl, '9' | |
jle @f | |
add bl, 7 | |
@@: | |
mov byte ptr [edi], bl | |
add edi, 2 | |
loop looptop | |
;wbinvd | |
pop eax | |
pop ebx | |
pop ecx | |
ret | |
ClearScreen: | |
push eax | |
push ecx | |
mov al, ' ' | |
mov ah, 0ch | |
mov edi, 0b8000h | |
mov ecx, 80 * 24 | |
@@: | |
mov word ptr [edi], ax | |
add edi, 2 | |
loop @b | |
mov edi, 0b8000h | |
pop ecx | |
pop eax | |
ret | |
A2C: | |
and al, 0fh | |
add al, '0' | |
cmp al, '9' | |
jle @f | |
add al, 7 | |
@@: | |
ret | |
String1 db "*** INT ",0 | |
Int0String db "00h Divide by 0 -",0 | |
Int1String db "01h Debug exception -",0 | |
Int2String db "02h NMI -",0 | |
Int3String db "03h Breakpoint -",0 | |
Int4String db "04h Overflow -",0 | |
Int5String db "05h Bound -",0 | |
Int6String db "06h Invalid opcode -",0 | |
Int7String db "07h Device not available -",0 | |
Int8String db "08h Double fault -",0 | |
Int9String db "09h Coprocessor seg overrun (reserved) -",0 | |
Int10String db "0Ah Invalid TSS -",0 | |
Int11String db "0Bh Segment not present -",0 | |
Int12String db "0Ch Stack fault -",0 | |
Int13String db "0Dh General protection fault -",0 | |
Int14String db "0Eh Page fault -",0 | |
Int15String db "0Fh (Intel reserved) -",0 | |
Int16String db "10h Floating point error -",0 | |
Int17String db "11h Alignment check -",0 | |
Int18String db "12h Machine check -",0 | |
Int19String db "13h SIMD Floating-Point Exception -",0 | |
IntUnknownString db "??h Unknown interrupt -",0 | |
StringTable dd offset Int0String, offset Int1String, offset Int2String, offset Int3String, | |
offset Int4String, offset Int5String, offset Int6String, offset Int7String, | |
offset Int8String, offset Int9String, offset Int10String, offset Int11String, | |
offset Int12String, offset Int13String, offset Int14String, offset Int15String, | |
offset Int16String, offset Int17String, offset Int18String, offset Int19String | |
String2 db " HALT!! *** (",0 | |
String3 db ")",0 | |
StringEax db "EAX=",0 | |
StringEbx db " EBX=",0 | |
StringEcx db " ECX=",0 | |
StringEdx db " EDX=",0 | |
StringEcode db " ECODE=",0 | |
StringEsp db "ESP=",0 | |
StringEbp db " EBP=",0 | |
StringEsi db " ESI=",0 | |
StringEdi db " EDI=",0 | |
StringEflags db " EFLAGS=",0 | |
Idtr df 0 | |
org 21ffeh | |
BlockSignature: | |
dw 0aa55h | |
end |