;------------------------------------------------------------------------------ ;\r
-; Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+; Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>\r
; This program and the accompanying materials\r
; are licensed and made available under the terms and conditions of the BSD License\r
; which accompanies this distribution. The full text of the license may be found at\r
\r
.data\r
\r
-CommonEntryAddr DD CommonInterruptEntry\r
-\r
-EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions\r
+EXTRN mDoFarReturnFlag:DWORD ; Do far return flag\r
\r
.code\r
\r
+ALIGN 8\r
+\r
;\r
; exception handler stub table\r
;\r
-Exception0Handle:\r
- push 0\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception1Handle:\r
- push 1\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception2Handle:\r
- push 2\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception3Handle:\r
- push 3\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception4Handle:\r
- push 4\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception5Handle:\r
- push 5\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception6Handle:\r
- push 6\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception7Handle:\r
- push 7\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception8Handle:\r
- push 8\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception9Handle:\r
- push 9\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception10Handle:\r
- push 10\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception11Handle:\r
- push 11\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception12Handle:\r
- push 12\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception13Handle:\r
- push 13\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception14Handle:\r
- push 14\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception15Handle:\r
- push 15\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception16Handle:\r
- push 16\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception17Handle:\r
- push 17\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception18Handle:\r
- push 18\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception19Handle:\r
- push 19\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception20Handle:\r
- push 20\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception21Handle:\r
- push 21\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception22Handle:\r
- push 22\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception23Handle:\r
- push 23\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception24Handle:\r
- push 24\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception25Handle:\r
- push 25\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception26Handle:\r
- push 26\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception27Handle:\r
- push 27\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception28Handle:\r
- push 28\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception29Handle:\r
- push 29\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception30Handle:\r
- push 30\r
- jmp dword ptr [CommonEntryAddr]\r
-Exception31Handle:\r
- push 31\r
- jmp dword ptr [CommonEntryAddr]\r
+AsmIdtVectorBegin:\r
+REPEAT 32\r
+ db 6ah ; push #VectorNum\r
+ db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum\r
+ push eax\r
+ mov eax, CommonInterruptEntry\r
+ jmp eax\r
+ENDM\r
+AsmIdtVectorEnd:\r
+\r
+HookAfterStubBegin:\r
+ db 6ah ; push\r
+VectorNum:\r
+ db 0 ; 0 will be fixed\r
+ push eax\r
+ mov eax, HookAfterStubHeaderEnd\r
+ jmp eax\r
+HookAfterStubHeaderEnd:\r
+ pop eax\r
+ sub esp, 8 ; reserve room for filling exception data later\r
+ push [esp + 8]\r
+ xchg ecx, [esp] ; get vector number\r
+ bt mErrorCodeFlag, ecx\r
+ jnc @F\r
+ push [esp] ; addition push if exception data needed\r
+@@:\r
+ xchg ecx, [esp] ; restore ecx\r
+ push eax\r
\r
;----------------------------------------------------------------------------;\r
; CommonInterruptEntry ;\r
;----------------------------------------------------------------------------;\r
; The follow algorithm is used for the common interrupt routine.\r
; Entry from each interrupt with a push eax and eax=interrupt number\r
-\r
+; Stack:\r
+; +---------------------+\r
+; + EFlags +\r
+; +---------------------+\r
+; + CS +\r
+; +---------------------+\r
+; + EIP +\r
+; +---------------------+\r
+; + Error Code +\r
+; +---------------------+\r
+; + Vector Number +\r
+; +---------------------+\r
+; + EBP +\r
+; +---------------------+ <-- EBP\r
CommonInterruptEntry PROC PUBLIC\r
cli\r
+ pop eax\r
;\r
; All interrupt handlers are invoked through interrupt gates, so\r
; IF flag automatically cleared at the entry point\r
;\r
\r
;\r
- ; Calculate vector number\r
- ;\r
- ; Get the return address of call, actually, it is the\r
- ; address of vector number.\r
+ ; Get vector number from top of stack\r
;\r
xchg ecx, [esp]\r
- and ecx, 0FFFFh\r
+ and ecx, 0FFh ; Vector number should be less than 256\r
cmp ecx, 32 ; Intel reserved vector for exceptions?\r
jae NoErrorCode\r
bt mErrorCodeFlag, ecx\r
;\r
xchg ecx, [esp]\r
\r
- ;\r
- ; Fall through to join main routine code\r
- ; at ErrorCodeAndVectorOnStack\r
- ;\r
-@@:\r
- jmp @B\r
-\r
ErrorCodeAndVectorOnStack:\r
push ebp\r
mov ebp, esp\r
and esp, 0fffffff0h\r
sub esp, 12\r
\r
+ sub esp, 8\r
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
+ push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
+\r
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;\r
push eax\r
push ecx\r
push eax\r
\r
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;\r
+ mov eax, 1\r
+ push ebx ; temporarily save value of ebx on stack\r
+ cpuid ; use CPUID to determine if FXSAVE/FXRESTOR and DE\r
+ ; are supported\r
+ pop ebx ; retore value of ebx that was overwritten by CPUID\r
mov eax, cr4\r
- or eax, 208h\r
+ push eax ; push cr4 firstly\r
+ test edx, BIT24 ; Test for FXSAVE/FXRESTOR support\r
+ jz @F\r
+ or eax, BIT9 ; Set CR4.OSFXSR\r
+@@:\r
+ test edx, BIT2 ; Test for Debugging Extensions support\r
+ jz @F\r
+ or eax, BIT3 ; Set CR4.DE\r
+@@:\r
mov cr4, eax\r
- push eax\r
mov eax, cr3\r
push eax\r
mov eax, cr2\r
;; FX_SAVE_STATE_IA32 FxSaveState;\r
sub esp, 512\r
mov edi, esp\r
+ test edx, BIT24 ; Test for FXSAVE/FXRESTOR support.\r
+ ; edx still contains result from CPUID above\r
+ jz @F\r
db 0fh, 0aeh, 07h ;fxsave [edi]\r
+@@:\r
\r
;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear\r
cld\r
\r
;; FX_SAVE_STATE_IA32 FxSaveState;\r
mov esi, esp\r
+ mov eax, 1\r
+ cpuid ; use CPUID to determine if FXSAVE/FXRESTOR\r
+ ; are supported\r
+ test edx, BIT24 ; Test for FXSAVE/FXRESTOR support\r
+ jz @F\r
db 0fh, 0aeh, 0eh ; fxrstor [esi]\r
+@@:\r
add esp, 512\r
\r
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;\r
pop ecx\r
pop eax\r
\r
+ pop dword ptr [ebp - 8]\r
+ pop dword ptr [ebp - 4]\r
mov esp, ebp\r
pop ebp\r
add esp, 8\r
+ cmp dword ptr [esp - 16], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler\r
+ jz DoReturn\r
+ cmp dword ptr [esp - 20], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag\r
+ jz ErrorCode\r
+ jmp dword ptr [esp - 16]\r
+ErrorCode:\r
+ sub esp, 4\r
+ jmp dword ptr [esp - 12]\r
+\r
+DoReturn:\r
+ cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET\r
+ jz DoIret\r
+ push [esp + 8] ; save EFLAGS\r
+ add esp, 16\r
+ push [esp - 8] ; save CS in new location\r
+ push [esp - 8] ; save EIP in new location\r
+ push [esp - 8] ; save EFLAGS in new location\r
+ popfd ; restore EFLAGS\r
+ retf ; far return\r
+\r
+DoIret:\r
iretd\r
\r
CommonInterruptEntry ENDP\r
\r
;---------------------------------------;\r
-; _GetTemplateAddressMap ;\r
+; _AsmGetTemplateAddressMap ;\r
;----------------------------------------------------------------------------;\r
-; \r
+;\r
; Protocol prototype\r
-; GetTemplateAddressMap (\r
+; AsmGetTemplateAddressMap (\r
; EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap\r
; );\r
-; \r
+;\r
; Routine Description:\r
-; \r
+;\r
; Return address map of interrupt handler template so that C code can generate\r
; interrupt table.\r
-; \r
+;\r
; Arguments:\r
-; \r
-; \r
-; Returns: \r
-; \r
+;\r
+;\r
+; Returns:\r
+;\r
; Nothing\r
;\r
-; \r
+;\r
; Input: [ebp][0] = Original ebp\r
; [ebp][4] = Return address\r
-; \r
+;\r
; Output: Nothing\r
-; \r
+;\r
; Destroys: Nothing\r
;-----------------------------------------------------------------------------;\r
-GetTemplateAddressMap proc near public\r
+AsmGetTemplateAddressMap proc near public\r
push ebp ; C prolog\r
mov ebp, esp\r
pushad\r
\r
- mov ebx, dword ptr [ebp+08h]\r
- mov dword ptr [ebx], Exception0Handle\r
- mov dword ptr [ebx+4h], Exception1Handle - Exception0Handle\r
- \r
+ mov ebx, dword ptr [ebp + 08h]\r
+ mov dword ptr [ebx], AsmIdtVectorBegin\r
+ mov dword ptr [ebx + 4h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32\r
+ mov dword ptr [ebx + 8h], HookAfterStubBegin\r
+\r
popad\r
pop ebp\r
ret\r
-GetTemplateAddressMap ENDP\r
-\r
+AsmGetTemplateAddressMap ENDP\r
+\r
+;-------------------------------------------------------------------------------------\r
+; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);\r
+;-------------------------------------------------------------------------------------\r
+AsmVectorNumFixup proc near public\r
+ mov eax, dword ptr [esp + 8]\r
+ mov ecx, [esp + 4]\r
+ mov [ecx + (VectorNum - HookAfterStubBegin)], al\r
+ ret\r
+AsmVectorNumFixup ENDP\r
END\r