;------------------------------------------------------------------------------ | |
;* | |
;* Copyright 2006, Intel Corporation | |
;* All rights reserved. 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. | |
;* | |
;* efi64.asm | |
;* | |
;* Abstract: | |
;* | |
;------------------------------------------------------------------------------ | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
; Now in 64-bit long 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 reletive | |
dd commonIdtEntry - $ - 4 ; offset to jump to | |
endm | |
Start: | |
mov esp,0001fffe8h ; make final stack aligned | |
; set OSFXSR and OSXMMEXCPT because some code will use XMM register | |
db 0fh | |
db 20h | |
db 0e0h | |
; mov rax, cr4 | |
bts eax, 9 | |
bts eax, 0ah | |
db 0fh | |
db 22h | |
db 0e0h | |
; mov cr4, rax | |
call ClearScreen | |
; Populate IDT with meaningful offsets for exception handlers... | |
mov eax, offset Idtr | |
sidt fword ptr [eax] ; 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 | |
; 63..32 of descriptors is 0 | |
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], 38h ; SYS_CODE64_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 | |
mov dword ptr [edi+8], 0 ; write bits 63..32 of offset | |
add edi, 16 ; 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], 38h ; SYS_CODE64_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 | |
; mov dword ptr [edi+8], 0 ; write bits 63..32 of offset | |
; add edi, 16 ; 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 PrintQword | |
; 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+030h] ; edi = [[22000 + [22014] + 3c] + 2c] = ImageBase (63..32 is zero, ignore) | |
mov eax,[ebp+028h] ; eax = [[22000 + [22014] + 3c] + 24] = EntryPoint | |
add eax,edi ; eax = ImageBase + EntryPoint | |
mov ebx, offset EfiLdrOffset | |
mov dword ptr [ebx],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 | |
db 66h | |
db 0ffh | |
db 0cbh | |
; dec bx | |
cmp bx,0 | |
jne SectionLoop | |
mov edx, offset Idtr | |
movzx eax, word ptr [edx] ; get size of IDT | |
db 0ffh | |
db 0c0h | |
; inc eax | |
add eax, dword ptr [edx + 2] ; add to base of IDT to get location of memory map... | |
xor ecx, ecx | |
mov ecx, eax ; put argument to RCX | |
db 48h | |
db 0c7h | |
db 0c0h | |
EfiLdrOffset: | |
dd 000401000h ; Offset of EFILDR | |
; mov rax, 401000h | |
db 50h | |
; push rax | |
; ret | |
db 0c3h | |
; 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: | |
push eax | |
push ecx | |
push edx | |
push ebx | |
push esp | |
push ebp | |
push esi | |
push edi | |
db 41h | |
db 50h | |
; push r8 | |
db 41h | |
db 51h | |
; push r9 | |
db 41h | |
db 52h | |
; push r10 | |
db 41h | |
db 53h | |
; push r11 | |
db 41h | |
db 54h | |
; push r12 | |
db 41h | |
db 55h | |
; push r13 | |
db 41h | |
db 56h | |
; push r14 | |
db 41h | |
db 57h | |
; push r15 | |
db 48h | |
mov ebp, esp | |
; mov rbp, rsp | |
;; | |
;; At this point the stack looks like this: | |
;; | |
;; Calling SS | |
;; Calling RSP | |
;; rflags | |
;; Calling CS | |
;; Calling RIP | |
;; Error code or 0 | |
;; Int num or 0ffh for unknown int num | |
;; rax | |
;; rcx | |
;; rdx | |
;; rbx | |
;; rsp | |
;; rbp | |
;; rsi | |
;; rdi | |
;; r8 | |
;; r9 | |
;; r10 | |
;; r11 | |
;; r12 | |
;; r13 | |
;; r14 | |
;; r15 <------- RSP, RBP | |
;; | |
call ClearScreen | |
mov esi, offset String1 | |
call PrintString | |
db 48h | |
mov eax, [ebp + 16*8] ;; move Int number into RAX | |
db 48h | |
cmp eax, 18 | |
ja PrintDefaultString | |
PrintExceptionString: | |
shl eax, 3 ;; multiply by 8 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 | |
db 48h | |
mov eax, [ebp+19*8] ; CS | |
call PrintQword | |
mov al, ':' | |
mov byte ptr [edi], al | |
add edi, 2 | |
db 48h | |
mov eax, [ebp+18*8] ; RIP | |
call PrintQword | |
mov esi, offset String3 | |
call PrintString | |
mov edi, 0b8140h | |
mov esi, offset StringRax ; rax | |
call PrintString | |
db 48h | |
mov eax, [ebp+15*8] | |
call PrintQword | |
mov esi, offset StringRcx ; rcx | |
call PrintString | |
db 48h | |
mov eax, [ebp+14*8] | |
call PrintQword | |
mov esi, offset StringRdx ; rdx | |
call PrintString | |
db 48h | |
mov eax, [ebp+13*8] | |
call PrintQword | |
mov edi, 0b81e0h | |
mov esi, offset StringRbx ; rbx | |
call PrintString | |
db 48h | |
mov eax, [ebp+12*8] | |
call PrintQword | |
mov esi, offset StringRsp ; rsp | |
call PrintString | |
db 48h | |
mov eax, [ebp+21*8] | |
call PrintQword | |
mov esi, offset StringRbp ; rbp | |
call PrintString | |
db 48h | |
mov eax, [ebp+10*8] | |
call PrintQword | |
mov edi, 0b8280h | |
mov esi, offset StringRsi ; rsi | |
call PrintString | |
db 48h | |
mov eax, [ebp+9*8] | |
call PrintQword | |
mov esi, offset StringRdi ; rdi | |
call PrintString | |
db 48h | |
mov eax, [ebp+8*8] | |
call PrintQword | |
mov esi, offset StringEcode ; error code | |
call PrintString | |
db 48h | |
mov eax, [ebp+17*8] | |
call PrintQword | |
mov edi, 0b8320h | |
mov esi, offset StringR8 ; r8 | |
call PrintString | |
db 48h | |
mov eax, [ebp+7*8] | |
call PrintQword | |
mov esi, offset StringR9 ; r9 | |
call PrintString | |
db 48h | |
mov eax, [ebp+6*8] | |
call PrintQword | |
mov esi, offset StringR10 ; r10 | |
call PrintString | |
db 48h | |
mov eax, [ebp+5*8] | |
call PrintQword | |
mov edi, 0b83c0h | |
mov esi, offset StringR11 ; r11 | |
call PrintString | |
db 48h | |
mov eax, [ebp+4*8] | |
call PrintQword | |
mov esi, offset StringR12 ; r12 | |
call PrintString | |
db 48h | |
mov eax, [ebp+3*8] | |
call PrintQword | |
mov esi, offset StringR13 ; r13 | |
call PrintString | |
db 48h | |
mov eax, [ebp+2*8] | |
call PrintQword | |
mov edi, 0b8460h | |
mov esi, offset StringR14 ; r14 | |
call PrintString | |
db 48h | |
mov eax, [ebp+1*8] | |
call PrintQword | |
mov esi, offset StringR15 ; r15 | |
call PrintString | |
db 48h | |
mov eax, [ebp+0*8] | |
call PrintQword | |
mov esi, offset StringSs ; ss | |
call PrintString | |
db 48h | |
mov eax, [ebp+22*8] | |
call PrintQword | |
mov edi, 0b8500h | |
mov esi, offset StringRflags ; rflags | |
call PrintString | |
db 48h | |
mov eax, [ebp+20*8] | |
call PrintQword | |
mov edi, 0b8640h | |
mov esi, ebp | |
add esi, 23*8 | |
mov ecx, 4 | |
OuterLoop: | |
push ecx | |
mov ecx, 4 | |
db 48h | |
mov edx, edi | |
InnerLoop: | |
db 48h | |
mov eax, [esi] | |
call PrintQword | |
add esi, 8 | |
mov al, ' ' | |
mov [edi], al | |
add edi, 2 | |
loop InnerLoop | |
pop ecx | |
add edx, 0a0h | |
mov edi, edx | |
loop OuterLoop | |
mov edi, 0b8960h | |
db 48h | |
mov eax, [ebp+18*8] ; RIP | |
sub eax, 8 * 8 | |
db 48h | |
mov esi, eax ; esi = rip - 8 QWORD linear (total 16 QWORD) | |
mov ecx, 4 | |
OuterLoop1: | |
push ecx | |
mov ecx, 4 | |
mov edx, edi | |
InnerLoop1: | |
db 48h | |
mov eax, [esi] | |
call PrintQword | |
add esi, 8 | |
mov al, ' ' | |
mov [edi], al | |
add edi, 2 | |
loop InnerLoop1 | |
pop ecx | |
add edx, 0a0h | |
mov edi, edx | |
loop OuterLoop1 | |
;wbinvd | |
@@: | |
jmp @b | |
; | |
; return | |
; | |
mov esp, ebp | |
; mov rsp, rbp | |
db 41h | |
db 5fh | |
; pop r15 | |
db 41h | |
db 5eh | |
; pop r14 | |
db 41h | |
db 5dh | |
; pop r13 | |
db 41h | |
db 5ch | |
; pop r12 | |
db 41h | |
db 5bh | |
; pop r11 | |
db 41h | |
db 5ah | |
; pop r10 | |
db 41h | |
db 59h | |
; pop r9 | |
db 41h | |
db 58h | |
; pop r8 | |
pop edi | |
pop esi | |
pop ebp | |
pop eax ; esp | |
pop ebx | |
pop edx | |
pop ecx | |
pop eax | |
db 48h | |
db 83h | |
db 0c4h | |
db 10h | |
; add esp, 16 ; error code and INT number | |
db 48h | |
db 0cfh | |
; iretq | |
PrintString: | |
push eax | |
@@: | |
mov al, byte ptr [esi] | |
cmp al, 0 | |
je @f | |
mov byte ptr [edi], al | |
db 0ffh | |
db 0c6h | |
; inc esi | |
add edi, 2 | |
jmp @b | |
@@: | |
pop eax | |
ret | |
;; RAX contains qword to print | |
;; RDI contains memory location (screen location) to print it to | |
PrintQword: | |
push ecx | |
push ebx | |
push eax | |
db 48h | |
db 0c7h | |
db 0c1h | |
dd 16 | |
; mov rcx, 16 | |
looptop: | |
db 48h | |
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 dq 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 | |
StringRax db "RAX=",0 | |
StringRcx db " RCX=",0 | |
StringRdx db " RDX=",0 | |
StringRbx db "RBX=",0 | |
StringRsp db " RSP=",0 | |
StringRbp db " RBP=",0 | |
StringRsi db "RSI=",0 | |
StringRdi db " RDI=",0 | |
StringEcode db " ECODE=",0 | |
StringR8 db "R8 =",0 | |
StringR9 db " R9 =",0 | |
StringR10 db " R10=",0 | |
StringR11 db "R11=",0 | |
StringR12 db " R12=",0 | |
StringR13 db " R13=",0 | |
StringR14 db "R14=",0 | |
StringR15 db " R15=",0 | |
StringSs db " SS =",0 | |
StringRflags db "RFLAGS=",0 | |
Idtr df 0 | |
df 0 | |
org 21ffeh | |
BlockSignature: | |
dw 0aa55h | |
end |