438 lines
11 KiB
NASM
438 lines
11 KiB
NASM
;; @file
|
|
; This is the code that supports IA32 CPU architectural protocol
|
|
;
|
|
;******************************************************************************
|
|
;* Copyright (c) 2015, Insyde Software Corporation. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
page ,132
|
|
title CPU ARCHITECTURAL PEI ASSEMBLY HOOKS
|
|
;------------------------------------------------------------------------------
|
|
;
|
|
; Copyright (c) 1999 - 2011, Intel Corporation. All rights reserved.<BR>
|
|
; This software and associated documentation (if any) is furnished
|
|
; under a license and may only be used or copied in accordance
|
|
; with the terms of the license. Except as permitted by such
|
|
; license, no part of this software or documentation may be
|
|
; reproduced, stored in a retrieval system, or transmitted in any
|
|
; form or by any means without the express written consent of
|
|
; Intel Corporation.
|
|
;
|
|
; Module Name:
|
|
;
|
|
; CpuAsm.asm
|
|
;
|
|
; Abstract:
|
|
;
|
|
; Assembly code that supports IA32 CPU architectural Ppi
|
|
;
|
|
;------------------------------------------------------------------------------
|
|
|
|
.686p
|
|
.model flat
|
|
|
|
.data
|
|
ExternalVectorTablePtr DD ? ; Table of call backs
|
|
CommonInterruptEntry DD CommonEntry ; Address of CommonEntry
|
|
Idtr DW ? ; FWORD for IDT register
|
|
Idtr1 DD ? ; MUST BE IMMEDIATELY AFTER Idtr
|
|
|
|
EXTRN _mErrorCodeFlag:DWORD ; Error code flags for exceptions
|
|
|
|
.stack
|
|
.code
|
|
.MMX
|
|
.XMM
|
|
|
|
UINT8 TYPEDEF BYTE
|
|
UINT16 TYPEDEF WORD
|
|
UINT32 TYPEDEF DWORD
|
|
UINT64 TYPEDEF QWORD
|
|
UINTN TYPEDEF UINT32
|
|
|
|
;---------------------------------------;
|
|
; _InitializeIdt ;
|
|
;----------------------------------------------------------------------------;
|
|
;
|
|
; Protocol prototype
|
|
; InitializeIdt (
|
|
; IN EFI_CPU_INTERRUPT_HANDLER TableStart,
|
|
; IN UINTN *IdtTablePtr,
|
|
; IN UINT16 IdtLimit
|
|
; )
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; Creates an IDT table starting at IdtTablPtr. It has IdtLimit/8 entries.
|
|
; Table is initialized to intxx where xx is from 00 to number of entries or
|
|
; 100h, whichever is smaller. After table has been initialized the LIDT
|
|
; instruction is invoked.
|
|
;
|
|
; TableStart is the pointer to the callback table and is not used by
|
|
; InitializedIdt but by commonEntry. CommonEntry handles all interrupts,
|
|
; does the context save and calls the callback entry, if non-NULL.
|
|
; It is the responsibility of the callback routine to do hardware EOIs.
|
|
;
|
|
; Arguments:
|
|
;
|
|
; TableStart - Pointer to interrupt callback table
|
|
;
|
|
; IdtTablePtr - Pointer to IDT table
|
|
;
|
|
; IdtLimit - IDT Table limit = number of interrupt entries * 8
|
|
;
|
|
; Returns:
|
|
;
|
|
; Nothing
|
|
;
|
|
;
|
|
; Input: [ebp][0] = Original ebp
|
|
; [ebp][4] = Return address
|
|
; [ebp][8] = TableStart
|
|
; [ebp][0c] = *IdtTablePtr
|
|
; [ebp][10] = IdtLimit
|
|
;
|
|
; Output: Nothing
|
|
;
|
|
; Destroys: Nothing
|
|
;-----------------------------------------------------------------------------;
|
|
|
|
_InitializeIdt proc near public
|
|
push ebp ; C prolog
|
|
mov ebp, esp
|
|
push edi
|
|
|
|
mov eax, [ebp+8] ; Get ExternalVectorTable Address
|
|
mov ExternalVectorTablePtr, eax
|
|
|
|
mov ax, [ebp+10h] ; Get IDT Table limit
|
|
dec ax
|
|
mov Idtr, ax
|
|
|
|
mov eax, [ebp+0ch] ; Get Start of IDT
|
|
mov Idtr1, eax
|
|
|
|
mov edi, OFFSET Idtr ; Load IDT register
|
|
lidt FWORD PTR es:[edi]
|
|
|
|
pop edi
|
|
pop ebp
|
|
ret
|
|
_InitializeIdt endp
|
|
|
|
;----------------------------------------------------------------------------;
|
|
;
|
|
; Protocol prototype
|
|
; None
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; These routines handle the individual interrupts. These routines always
|
|
; gain control on any interrupt or exception. They save EAX and place
|
|
; the interrupt number in EAX. CommonEntry is then jumped to.
|
|
; instruction is invoked.
|
|
;
|
|
; CommonEntry handles all interrupts,does the context save and calls the
|
|
; callback entry, if non-NULL. It is the responsibility of the callback
|
|
; routine to do hardware EOIs. Callbacks are entered into the table
|
|
; located at TableStart. Entries are modified by the InstallInterruptHandler
|
|
; and UninstallInterruptHandler protocols.
|
|
;
|
|
; Arguments to CommonEntry:
|
|
;
|
|
; EAX - Interrupt or exception number
|
|
;
|
|
; TableStart - Pointer to interrupt callback table
|
|
;
|
|
; Returns:
|
|
;
|
|
; Nothing
|
|
;
|
|
;
|
|
; Output: Nothing
|
|
;
|
|
; Destroys: Nothing
|
|
;-----------------------------------------------------------------------------;
|
|
|
|
TemplateStart:
|
|
push eax
|
|
|
|
;mov eax, 0nnh (nn stands for vector number, which will be fixed at runtime
|
|
DB 0b8h
|
|
VectorNumber:
|
|
DD 00h
|
|
|
|
jmp dword ptr [CommonInterruptEntry];
|
|
TemplateEnd:
|
|
|
|
CommonEntry:
|
|
|
|
;---------------------------------------;
|
|
; _CommonEntry ;
|
|
;----------------------------------------------------------------------------;
|
|
; The follow algorithm is used for the common interrupt routine.
|
|
; Entry from each interrupt with a push eax and eax=interrupt number
|
|
|
|
;
|
|
; +---------------------+
|
|
; + EFlags +
|
|
; +---------------------+
|
|
; + CS +
|
|
; +---------------------+
|
|
; + EIP +
|
|
; +---------------------+
|
|
; + Error Code +
|
|
; +---------------------+
|
|
; + EAX / Vector Number +
|
|
; +---------------------+
|
|
; + EBP +
|
|
; +---------------------+ <-- EBP
|
|
;
|
|
|
|
cli
|
|
;
|
|
; All interrupt handlers are invoked through interrupt gates, so
|
|
; IF flag automatically cleared at the entry point
|
|
;
|
|
cmp eax, 32 ; Intel reserved vector for exceptions?
|
|
jae NoErrorCode
|
|
bt cs:_mErrorCodeFlag, eax
|
|
jc @F
|
|
|
|
NoErrorCode:
|
|
;
|
|
; Push a dummy error code on the stack
|
|
; to maintain coherent stack map
|
|
;
|
|
push [esp]
|
|
mov dword ptr [esp + 4], 0
|
|
@@:
|
|
push ebp
|
|
mov ebp, esp
|
|
|
|
;
|
|
; Align stack to make sure that EFI_FX_SAVE_STATE_IA32 of EFI_SYSTEM_CONTEXT_IA32
|
|
; is 16-byte aligned
|
|
;
|
|
and esp, 0fffffff0h
|
|
sub esp, 12
|
|
|
|
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
|
push dword ptr [ebp + 4] ; EAX
|
|
push ecx
|
|
push edx
|
|
push ebx
|
|
lea ecx, [ebp + 24]
|
|
push ecx ; ESP
|
|
push dword ptr [ebp] ; EBP
|
|
push esi
|
|
push edi
|
|
|
|
mov [ebp + 4], eax ; save vector number
|
|
|
|
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
|
mov eax, ss
|
|
push eax
|
|
movzx eax, word ptr [ebp + 16]
|
|
push eax
|
|
mov eax, ds
|
|
push eax
|
|
mov eax, es
|
|
push eax
|
|
mov eax, fs
|
|
push eax
|
|
mov eax, gs
|
|
push eax
|
|
|
|
;; UINT32 Eip;
|
|
push dword ptr [ebp + 12]
|
|
|
|
;; UINT32 Gdtr[2], Idtr[2];
|
|
sub esp, 8
|
|
sidt fword ptr [esp]
|
|
sub esp, 8
|
|
sgdt fword ptr [esp]
|
|
|
|
;; UINT32 Ldtr, Tr;
|
|
xor eax, eax
|
|
str ax
|
|
push eax
|
|
sldt ax
|
|
push eax
|
|
|
|
;; UINT32 EFlags;
|
|
push dword ptr [ebp + 20]
|
|
|
|
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
|
mov eax, cr4
|
|
or eax, 208h
|
|
mov cr4, eax
|
|
push eax
|
|
mov eax, cr3
|
|
push eax
|
|
mov eax, cr2
|
|
push eax
|
|
xor eax, eax
|
|
push eax
|
|
mov eax, cr0
|
|
push eax
|
|
|
|
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
|
mov eax, dr7
|
|
push eax
|
|
mov eax, dr6
|
|
push eax
|
|
mov eax, dr3
|
|
push eax
|
|
mov eax, dr2
|
|
push eax
|
|
mov eax, dr1
|
|
push eax
|
|
mov eax, dr0
|
|
push eax
|
|
|
|
;; FX_SAVE_STATE_IA32 FxSaveState;
|
|
sub esp, 512
|
|
mov edi, esp
|
|
db 0fh, 0aeh, 00000111y ;fxsave [edi]
|
|
|
|
;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
|
|
cld
|
|
|
|
;; UINT32 ExceptionData;
|
|
push dword ptr [ebp + 8]
|
|
|
|
;; call into exception handler
|
|
mov ebx, [ebp + 4]
|
|
mov eax, ExternalVectorTablePtr
|
|
mov eax, [eax + ebx * 4]
|
|
or eax, eax ; NULL?
|
|
je nonNullValue;
|
|
|
|
;; Prepare parameter and call
|
|
mov edx, esp
|
|
push edx
|
|
push ebx
|
|
call eax
|
|
add esp, 8
|
|
|
|
nonNullValue:
|
|
cli
|
|
;; UINT32 ExceptionData;
|
|
add esp, 4
|
|
|
|
;; FX_SAVE_STATE_IA32 FxSaveState;
|
|
mov esi, esp
|
|
db 0fh, 0aeh, 00001110y ; fxrstor [esi]
|
|
add esp, 512
|
|
|
|
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
|
;; Skip restoration of DRx registers to support in-circuit emualators
|
|
;; or debuggers set breakpoint in interrupt/exception context
|
|
add esp, 4 * 6
|
|
|
|
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
|
pop eax
|
|
mov cr0, eax
|
|
add esp, 4 ; not for Cr1
|
|
pop eax
|
|
mov cr2, eax
|
|
pop eax
|
|
mov cr3, eax
|
|
pop eax
|
|
mov cr4, eax
|
|
|
|
;; UINT32 EFlags;
|
|
pop dword ptr [ebp + 20]
|
|
|
|
;; UINT32 Ldtr, Tr;
|
|
;; UINT32 Gdtr[2], Idtr[2];
|
|
;; Best not let anyone mess with these particular registers...
|
|
add esp, 24
|
|
|
|
;; UINT32 Eip;
|
|
pop dword ptr [ebp + 12]
|
|
|
|
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
|
;; NOTE - modified segment registers could hang the debugger... We
|
|
;; could attempt to insulate ourselves against this possibility,
|
|
;; but that poses risks as well.
|
|
;;
|
|
pop gs
|
|
pop fs
|
|
pop es
|
|
pop ds
|
|
pop dword ptr [ebp + 16]
|
|
pop ss
|
|
|
|
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
|
pop edi
|
|
pop esi
|
|
add esp, 4 ; not for ebp
|
|
add esp, 4 ; not for esp
|
|
pop ebx
|
|
pop edx
|
|
pop ecx
|
|
pop eax
|
|
|
|
mov esp, ebp
|
|
pop ebp
|
|
add esp, 8
|
|
iretd
|
|
|
|
|
|
;---------------------------------------;
|
|
; _GetTemplateAddressMap ;
|
|
;----------------------------------------------------------------------------;
|
|
;
|
|
; Protocol prototype
|
|
; GetTemplateAddressMap (
|
|
; INTERRUPT_HANDLER_TEMPLATE_MAP *AddressMap
|
|
; );
|
|
;
|
|
; Routine Description:
|
|
;
|
|
; Return address map of interrupt handler template so that C code can generate
|
|
; interrupt handlers, and dynamically do address fix.
|
|
;
|
|
; Arguments:
|
|
;
|
|
;
|
|
; Returns:
|
|
;
|
|
; Nothing
|
|
;
|
|
;
|
|
; Input: [ebp][0] = Original ebp
|
|
; [ebp][4] = Return address
|
|
;
|
|
; Output: Nothing
|
|
;
|
|
; Destroys: Nothing
|
|
;-----------------------------------------------------------------------------;
|
|
_GetTemplateAddressMap proc near public
|
|
push ebp ; C prolog
|
|
mov ebp, esp
|
|
pushad
|
|
|
|
mov ebx, dword ptr [ebp+08h]
|
|
mov dword ptr [ebx], TemplateStart
|
|
mov dword ptr [ebx+4h], TemplateEnd - TemplateStart
|
|
|
|
; if code in Template is updated, the value fills into the 3rd parameter
|
|
; also needs update
|
|
mov dword ptr [ebx+8h], VectorNumber - TemplateStart
|
|
|
|
popad
|
|
pop ebp
|
|
ret
|
|
_GetTemplateAddressMap endp
|
|
|
|
END
|
|
|