1 ;------------------------------------------------------------------------------ ;
2 ; Copyright (c) 2012 - 2015, Intel Corporation. All rights reserved.<BR>
3 ; This program and the accompanying materials
4 ; are licensed and made available under the terms and conditions of the BSD License
5 ; which accompanies this distribution. The full text of the license may be found at
6 ; http://opensource.org/licenses/bsd-license.php.
8 ; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 ; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 ; ExceptionHandlerAsm.Asm
17 ; IA32 CPU Exception Handler
21 ;------------------------------------------------------------------------------
27 ; CommonExceptionHandler()
29 CommonExceptionHandler PROTO C
33 EXTRN mErrorCodeFlag:DWORD ; Error code flags for exceptions
34 EXTRN mDoFarReturnFlag:DWORD ; Do far return flag
41 ; exception handler stub table
45 db 6ah ; push #VectorNum
46 db ($ - AsmIdtVectorBegin) / ((AsmIdtVectorEnd - AsmIdtVectorBegin) / 32) ; VectorNum
48 mov eax, CommonInterruptEntry
56 db 0 ; 0 will be fixed
58 mov eax, HookAfterStubHeaderEnd
60 HookAfterStubHeaderEnd:
62 sub esp, 8 ; reserve room for filling exception data later
64 xchg ecx, [esp] ; get vector number
65 bt mErrorCodeFlag, ecx
67 push [esp] ; addition push if exception data needed
69 xchg ecx, [esp] ; restore ecx
72 ;----------------------------------------------------------------------------;
73 ; CommonInterruptEntry ;
74 ;----------------------------------------------------------------------------;
75 ; The follow algorithm is used for the common interrupt routine.
76 ; Entry from each interrupt with a push eax and eax=interrupt number
78 ; +---------------------+
80 ; +---------------------+
82 ; +---------------------+
84 ; +---------------------+
86 ; +---------------------+
88 ; +---------------------+
90 ; +---------------------+ <-- EBP
91 CommonInterruptEntry PROC PUBLIC
95 ; All interrupt handlers are invoked through interrupt gates, so
96 ; IF flag automatically cleared at the entry point
100 ; Get vector number from top of stack
103 and ecx, 0FFh ; Vector number should be less than 256
104 cmp ecx, 32 ; Intel reserved vector for exceptions?
106 bt mErrorCodeFlag, ecx
113 ; +---------------------+
115 ; +---------------------+
117 ; +---------------------+
119 ; +---------------------+
121 ; +---------------------+ <-- ESP
124 ; ECX - Vector Number
128 ; Put Vector Number on stack
133 ; Put 0 (dummy) error code on stack, and restore ECX
135 xor ecx, ecx ; ECX = 0
138 jmp ErrorCodeAndVectorOnStack
144 ; +---------------------+
146 ; +---------------------+
148 ; +---------------------+
150 ; +---------------------+
152 ; +---------------------+
154 ; +---------------------+ <-- ESP
157 ; ECX - Vector Number
161 ; Put Vector Number on stack and restore ECX
165 ErrorCodeAndVectorOnStack:
171 ; +---------------------+
173 ; +---------------------+
175 ; +---------------------+
177 ; +---------------------+
179 ; +---------------------+
181 ; +---------------------+
183 ; +---------------------+ <-- EBP
187 ; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
194 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
195 push 0 ; clear EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
197 ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
202 lea ecx, [ebp + 6 * 4]
204 push dword ptr [ebp] ; EBP
208 ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
211 movzx eax, word ptr [ebp + 4 * 4]
223 mov eax, [ebp + 3 * 4]
226 ;; UINT32 Gdtr[2], Idtr[2];
249 mov eax, [ebp + 5 * 4]
252 ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
254 push ebx ; temporarily save value of ebx on stack
255 cpuid ; use CPUID to determine if FXSAVE/FXRESTOR and DE
257 pop ebx ; retore value of ebx that was overwritten by CPUID
259 push eax ; push cr4 firstly
260 test edx, BIT24 ; Test for FXSAVE/FXRESTOR support
262 or eax, BIT9 ; Set CR4.OSFXSR
264 test edx, BIT2 ; Test for Debugging Extensions support
266 or eax, BIT3 ; Set CR4.DE
278 ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
292 ;; FX_SAVE_STATE_IA32 FxSaveState;
295 test edx, BIT24 ; Test for FXSAVE/FXRESTOR support.
296 ; edx still contains result from CPUID above
298 db 0fh, 0aeh, 07h ;fxsave [edi]
301 ;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
304 ;; UINT32 ExceptionData;
305 push dword ptr [ebp + 2 * 4]
307 ;; Prepare parameter and call
310 mov edx, dword ptr [ebp + 1 * 4]
314 ; Call External Exception Handler
316 mov eax, CommonExceptionHandler
321 ;; UINT32 ExceptionData;
324 ;; FX_SAVE_STATE_IA32 FxSaveState;
327 cpuid ; use CPUID to determine if FXSAVE/FXRESTOR
329 test edx, BIT24 ; Test for FXSAVE/FXRESTOR support
331 db 0fh, 0aeh, 0eh ; fxrstor [esi]
335 ;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
336 ;; Skip restoration of DRx registers to support in-circuit emualators
337 ;; or debuggers set breakpoint in interrupt/exception context
340 ;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
343 add esp, 4 ; not for Cr1
352 pop dword ptr [ebp + 5 * 4]
355 ;; UINT32 Gdtr[2], Idtr[2];
356 ;; Best not let anyone mess with these particular registers...
360 pop dword ptr [ebp + 3 * 4]
362 ;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
363 ;; NOTE - modified segment registers could hang the debugger... We
364 ;; could attempt to insulate ourselves against this possibility,
365 ;; but that poses risks as well.
371 pop dword ptr [ebp + 4 * 4]
374 ;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
377 add esp, 4 ; not for ebp
378 add esp, 4 ; not for esp
384 pop dword ptr [ebp - 8]
385 pop dword ptr [ebp - 4]
389 cmp dword ptr [esp - 16], 0 ; check EXCEPTION_HANDLER_CONTEXT.OldIdtHandler
391 cmp dword ptr [esp - 20], 1 ; check EXCEPTION_HANDLER_CONTEXT.ExceptionDataFlag
393 jmp dword ptr [esp - 16]
396 jmp dword ptr [esp - 12]
399 cmp mDoFarReturnFlag, 0 ; Check if need to do far return instead of IRET
401 push [esp + 8] ; save EFLAGS
403 push [esp - 8] ; save CS in new location
404 push [esp - 8] ; save EIP in new location
405 push [esp - 8] ; save EFLAGS in new location
406 popfd ; restore EFLAGS
412 CommonInterruptEntry ENDP
414 ;---------------------------------------;
415 ; _AsmGetTemplateAddressMap ;
416 ;----------------------------------------------------------------------------;
419 ; AsmGetTemplateAddressMap (
420 ; EXCEPTION_HANDLER_TEMPLATE_MAP *AddressMap
423 ; Routine Description:
425 ; Return address map of interrupt handler template so that C code can generate
436 ; Input: [ebp][0] = Original ebp
437 ; [ebp][4] = Return address
442 ;-----------------------------------------------------------------------------;
443 AsmGetTemplateAddressMap proc near public
448 mov ebx, dword ptr [ebp + 08h]
449 mov dword ptr [ebx], AsmIdtVectorBegin
450 mov dword ptr [ebx + 4h], (AsmIdtVectorEnd - AsmIdtVectorBegin) / 32
451 mov dword ptr [ebx + 8h], HookAfterStubBegin
456 AsmGetTemplateAddressMap ENDP
458 ;-------------------------------------------------------------------------------------
459 ; AsmVectorNumFixup (*NewVectorAddr, VectorNum, *OldVectorAddr);
460 ;-------------------------------------------------------------------------------------
461 AsmVectorNumFixup proc near public
462 mov eax, dword ptr [esp + 8]
464 mov [ecx + (VectorNum - HookAfterStubBegin)], al
466 AsmVectorNumFixup ENDP