MdeModulePkg: Remove X86 ASM and S files
NASM has replaced ASM and S files. 1. Remove ASM from all modules. 2. Remove S files from the drivers only. 3. https://bugzilla.tianocore.org/show_bug.cgi?id=881 After NASM is updated, S files can be removed from Library. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
This commit is contained in:
parent
13688930ae
commit
6d614649ab
|
@ -5,7 +5,7 @@
|
|||
# PPI to discover and dispatch the DXE Foundation and components that are
|
||||
# needed to run the DXE Foundation.
|
||||
#
|
||||
# Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
|
@ -43,8 +43,6 @@
|
|||
X64/VirtualMemory.c
|
||||
Ia32/DxeLoadFunc.c
|
||||
Ia32/IdtVectorAsm.nasm
|
||||
Ia32/IdtVectorAsm.asm
|
||||
Ia32/IdtVectorAsm.S
|
||||
|
||||
[Sources.X64]
|
||||
X64/VirtualMemory.h
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
#/** @file
|
||||
#
|
||||
# IDT vector entry.
|
||||
#
|
||||
# Copyright (c) 2007 - 2009, 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.
|
||||
#
|
||||
#**/
|
||||
|
||||
.text
|
||||
.code32
|
||||
|
||||
|
||||
.p2align 3
|
||||
ASM_GLOBAL ASM_PFX(AsmGetVectorTemplatInfo)
|
||||
ASM_GLOBAL ASM_PFX(AsmVectorFixup)
|
||||
/*
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
; Template of IDT Vector Handlers.
|
||||
;
|
||||
;-----------------------------------------------------------------------
|
||||
*/
|
||||
VectorTemplateBase:
|
||||
pushl %eax
|
||||
.byte 0x6a # push #VectorNum
|
||||
VectorNum:
|
||||
.byte 0
|
||||
movl CommonInterruptEntry, %eax
|
||||
jmp *%eax
|
||||
VectorTemplateEnd:
|
||||
|
||||
|
||||
ASM_PFX(AsmGetVectorTemplatInfo):
|
||||
movl 4(%esp), %ecx
|
||||
movl $VectorTemplateBase, (%ecx)
|
||||
movl $(VectorTemplateEnd - VectorTemplateBase), %eax
|
||||
ret
|
||||
|
||||
ASM_PFX(AsmVectorFixup):
|
||||
movl 8(%esp), %eax
|
||||
movl 4(%esp), %ecx
|
||||
movb %al, (VectorNum - VectorTemplateBase)(%ecx)
|
||||
ret
|
||||
|
||||
/*
|
||||
; The follow algorithm is used for the common interrupt routine.
|
||||
|
||||
;
|
||||
; +---------------------+ <-- 16-byte aligned ensured by processor
|
||||
; + Old SS +
|
||||
; +---------------------+
|
||||
; + Old RSP +
|
||||
; +---------------------+
|
||||
; + RFlags +
|
||||
; +---------------------+
|
||||
; + CS +
|
||||
; +---------------------+
|
||||
; + RIP +
|
||||
; +---------------------+
|
||||
; + Error Code +
|
||||
; +---------------------+
|
||||
; + Vector Number +
|
||||
; +---------------------+
|
||||
*/
|
||||
|
||||
CommonInterruptEntry:
|
||||
cli
|
||||
1:
|
||||
jmp 1b
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
;/** @file
|
||||
;
|
||||
; IDT vector entry.
|
||||
;
|
||||
; Copyright (c) 2007 - 2008, 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.
|
||||
;
|
||||
;**/
|
||||
|
||||
.686p
|
||||
.model flat,C
|
||||
.code
|
||||
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
; Generic IDT Vector Handlers for the Host.
|
||||
;
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
ALIGN 8
|
||||
PUBLIC AsmGetVectorTemplatInfo
|
||||
PUBLIC AsmVectorFixup
|
||||
|
||||
PUBLIC AsmVectorFixup
|
||||
|
||||
@VectorTemplateBase:
|
||||
push eax
|
||||
db 6ah ; push #VectorNumber
|
||||
@VectorNum:
|
||||
db 0
|
||||
mov eax, CommonInterruptEntry
|
||||
jmp eax
|
||||
@VectorTemplateEnd:
|
||||
|
||||
|
||||
AsmGetVectorTemplatInfo PROC
|
||||
mov ecx, [esp + 4]
|
||||
mov [ecx], @VectorTemplateBase
|
||||
mov eax, (@VectorTemplateEnd - @VectorTemplateBase)
|
||||
ret
|
||||
AsmGetVectorTemplatInfo ENDP
|
||||
|
||||
|
||||
AsmVectorFixup PROC
|
||||
mov eax, dword ptr [esp + 8]
|
||||
mov ecx, [esp + 4]
|
||||
mov [ecx + (@VectorNum - @VectorTemplateBase)], al
|
||||
ret
|
||||
AsmVectorFixup ENDP
|
||||
|
||||
|
||||
;---------------------------------------;
|
||||
; CommonInterruptEntry ;
|
||||
;---------------------------------------;
|
||||
; The follow algorithm is used for the common interrupt routine.
|
||||
|
||||
;
|
||||
; +---------------------+ <-- 16-byte aligned ensured by processor
|
||||
; + Old SS +
|
||||
; +---------------------+
|
||||
; + Old RSP +
|
||||
; +---------------------+
|
||||
; + RFlags +
|
||||
; +---------------------+
|
||||
; + CS +
|
||||
; +---------------------+
|
||||
; + RIP +
|
||||
; +---------------------+
|
||||
; + Error Code +
|
||||
; +---------------------+
|
||||
; + Vector Number +
|
||||
; +---------------------+
|
||||
|
||||
CommonInterruptEntry PROC
|
||||
cli
|
||||
|
||||
jmp $
|
||||
CommonInterruptEntry ENDP
|
||||
|
||||
END
|
||||
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
# This is a standalone Boot Script Executor. Standalone means it does not
|
||||
# depends on any PEI or DXE service.
|
||||
#
|
||||
# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials are
|
||||
|
@ -40,14 +40,10 @@
|
|||
[Sources.X64]
|
||||
X64/SetIdtEntry.c
|
||||
X64/S3Asm.nasm
|
||||
X64/S3Asm.asm
|
||||
X64/S3Asm.S
|
||||
|
||||
[Sources.Ia32]
|
||||
IA32/SetIdtEntry.c
|
||||
IA32/S3Asm.nasm
|
||||
IA32/S3Asm.asm
|
||||
IA32/S3Asm.S
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
## @file
|
||||
#
|
||||
# Copyright (c) 2010, 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.
|
||||
#
|
||||
##
|
||||
|
||||
#-----------------------------------------
|
||||
#VOID
|
||||
#AsmTransferControl (
|
||||
# IN UINT32 S3WakingVector,
|
||||
# IN UINT32 AcpiLowMemoryBase
|
||||
# );
|
||||
#-----------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(AsmTransferControl)
|
||||
ASM_PFX(AsmTransferControl):
|
||||
# S3WakingVector :DWORD
|
||||
# AcpiLowMemoryBase :DWORD
|
||||
pushl %ebp
|
||||
movl %esp,%ebp
|
||||
leal LABLE, %eax
|
||||
pushl $0x28 # CS
|
||||
pushl %eax
|
||||
movl 8(%ebp),%ecx
|
||||
shrdl $20,%ecx,%ebx
|
||||
andl $0xf,%ecx
|
||||
movw %cx,%bx
|
||||
movl %ebx, jmp_addr
|
||||
lret
|
||||
LABLE:
|
||||
.byte 0xb8,0x30,0 # mov ax, 30h as selector
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
movw %ax,%fs
|
||||
movw %ax,%gs
|
||||
movw %ax,%ss
|
||||
movl %cr0, %eax # Get control register 0
|
||||
.byte 0x66
|
||||
.byte 0x83,0xe0,0xfe # and eax, 0fffffffeh ; Clear PE bit (bit #0)
|
||||
.byte 0xf,0x22,0xc0 # mov cr0, eax ; Activate real mode
|
||||
.byte 0xea # jmp far @jmp_addr
|
||||
jmp_addr:
|
||||
.long 0
|
||||
|
||||
ASM_GLOBAL ASM_PFX(AsmTransferControl32)
|
||||
ASM_PFX(AsmTransferControl32):
|
||||
jmp ASM_PFX(AsmTransferControl)
|
||||
|
||||
# dummy
|
||||
ASM_GLOBAL ASM_PFX(AsmTransferControl16)
|
||||
ASM_PFX(AsmTransferControl16):
|
||||
ASM_GLOBAL ASM_PFX(AsmFixAddress16)
|
||||
ASM_PFX(AsmFixAddress16):
|
||||
.long 0
|
||||
ASM_GLOBAL ASM_PFX(AsmJmpAddr32)
|
||||
ASM_PFX(AsmJmpAddr32):
|
||||
.long 0
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
;; @file
|
||||
; This is the assembly code for transferring to control to OS S3 waking vector
|
||||
; for IA32 platform
|
||||
;
|
||||
; Copyright (c) 2006, 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.
|
||||
;
|
||||
;;
|
||||
.586P
|
||||
.model flat,C
|
||||
.code
|
||||
|
||||
PUBLIC AsmFixAddress16
|
||||
PUBLIC AsmJmpAddr32
|
||||
|
||||
;-----------------------------------------
|
||||
;VOID
|
||||
;AsmTransferControl (
|
||||
; IN UINT32 S3WakingVector,
|
||||
; IN UINT32 AcpiLowMemoryBase
|
||||
; );
|
||||
;-----------------------------------------
|
||||
|
||||
AsmTransferControl PROC
|
||||
; S3WakingVector :DWORD
|
||||
; AcpiLowMemoryBase :DWORD
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
lea eax, @F
|
||||
push 28h ; CS
|
||||
push eax
|
||||
mov ecx, [ebp + 8]
|
||||
shrd ebx, ecx, 20
|
||||
and ecx, 0fh
|
||||
mov bx, cx
|
||||
mov [@jmp_addr], ebx
|
||||
retf
|
||||
@@:
|
||||
DB 0b8h, 30h, 0 ; mov ax, 30h as selector
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
mov eax, cr0 ; Get control register 0
|
||||
DB 66h
|
||||
DB 83h, 0e0h, 0feh ; and eax, 0fffffffeh ; Clear PE bit (bit #0)
|
||||
DB 0fh, 22h, 0c0h ; mov cr0, eax ; Activate real mode
|
||||
DB 0eah ; jmp far @jmp_addr
|
||||
@jmp_addr DD ?
|
||||
|
||||
AsmTransferControl ENDP
|
||||
|
||||
AsmTransferControl32 PROC
|
||||
jmp AsmTransferControl
|
||||
AsmTransferControl32 ENDP
|
||||
|
||||
; dummy
|
||||
AsmTransferControl16 PROC
|
||||
AsmFixAddress16 DD ?
|
||||
AsmJmpAddr32 DD ?
|
||||
AsmTransferControl16 ENDP
|
||||
|
||||
END
|
|
@ -1,130 +0,0 @@
|
|||
## @file
|
||||
# This is the assembly code for transferring to control to OS S3 waking vector
|
||||
# for X64 platform
|
||||
#
|
||||
# Copyright (c) 2006 - 2013, 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.
|
||||
#
|
||||
##
|
||||
|
||||
ASM_GLOBAL ASM_PFX(AsmTransferControl)
|
||||
ASM_PFX(AsmTransferControl):
|
||||
# rcx S3WakingVector :DWORD
|
||||
# rdx AcpiLowMemoryBase :DWORD
|
||||
lea _AsmTransferControl_al_0000(%rip), %eax
|
||||
movq $0x2800000000, %r8
|
||||
orq %r8, %rax
|
||||
pushq %rax
|
||||
shrd $20, %ecx, %ebx
|
||||
andl $0x0f, %ecx
|
||||
movw %cx, %bx
|
||||
movl %ebx, jmp_addr(%rip)
|
||||
lret
|
||||
_AsmTransferControl_al_0000:
|
||||
.byte 0x0b8, 0x30, 0 # mov ax, 30h as selector
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
movl %eax, %ss
|
||||
movq %cr0, %rax
|
||||
movq %cr4, %rbx
|
||||
.byte 0x66
|
||||
andl $0x7ffffffe, %eax
|
||||
andb $0xdf, %bl
|
||||
movq %rax, %cr0
|
||||
.byte 0x66
|
||||
movl $0x0c0000080, %ecx
|
||||
rdmsr
|
||||
andb $0xfe, %ah
|
||||
wrmsr
|
||||
movq %rbx, %cr4
|
||||
.byte 0x0ea # jmp far jmp_addr
|
||||
jmp_addr:
|
||||
.long 0
|
||||
|
||||
ASM_GLOBAL ASM_PFX(AsmTransferControl32)
|
||||
ASM_PFX(AsmTransferControl32):
|
||||
# S3WakingVector :DWORD
|
||||
# AcpiLowMemoryBase :DWORD
|
||||
pushq %rbp
|
||||
movl %esp,%ebp
|
||||
.byte 0x8d, 0x05 # lea eax, AsmTransferControl16
|
||||
ASM_GLOBAL ASM_PFX(AsmFixAddress16)
|
||||
ASM_PFX(AsmFixAddress16):
|
||||
.long 0
|
||||
pushq $0x28 # CS
|
||||
pushq %rax
|
||||
lret
|
||||
|
||||
ASM_GLOBAL ASM_PFX(AsmTransferControl16)
|
||||
ASM_PFX(AsmTransferControl16):
|
||||
.byte 0xb8,0x30,0 # mov ax, 30h as selector
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
movw %ax,%fs
|
||||
movw %ax,%gs
|
||||
movw %ax,%ss
|
||||
movq %cr0, %rax # Get control register 0
|
||||
.byte 0x66
|
||||
.byte 0x83,0xe0,0xfe # and eax, 0fffffffeh ; Clear PE bit (bit #0)
|
||||
.byte 0xf,0x22,0xc0 # mov cr0, eax ; Activate real mode
|
||||
.byte 0xea # jmp far AsmJmpAddr32
|
||||
ASM_GLOBAL ASM_PFX(AsmJmpAddr32)
|
||||
ASM_PFX(AsmJmpAddr32):
|
||||
.long 0
|
||||
|
||||
ASM_GLOBAL ASM_PFX(PageFaultHandlerHook)
|
||||
ASM_PFX(PageFaultHandlerHook):
|
||||
pushq %rax # save all volatile registers
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
# save volatile fp registers
|
||||
addq $-0x68, %rsp
|
||||
stmxcsr 0x60(%rsp)
|
||||
movdqa %xmm0, 0x0(%rsp)
|
||||
movdqa %xmm1, 0x10(%rsp)
|
||||
movdqa %xmm2, 0x20(%rsp)
|
||||
movdqa %xmm3, 0x30(%rsp)
|
||||
movdqa %xmm4, 0x40(%rsp)
|
||||
movdqa %xmm5, 0x50(%rsp)
|
||||
|
||||
addq $-0x20, %rsp
|
||||
call ASM_PFX(PageFaultHandler)
|
||||
addq $0x20, %rsp
|
||||
|
||||
# load volatile fp registers
|
||||
ldmxcsr 0x60(%rsp)
|
||||
movdqa 0x0(%rsp), %xmm0
|
||||
movdqa 0x10(%rsp), %xmm1
|
||||
movdqa 0x20(%rsp), %xmm2
|
||||
movdqa 0x30(%rsp), %xmm3
|
||||
movdqa 0x40(%rsp), %xmm4
|
||||
movdqa 0x50(%rsp), %xmm5
|
||||
addq $0x68, %rsp
|
||||
|
||||
testb %al, %al
|
||||
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax # restore all volatile registers
|
||||
jnz L1
|
||||
jmpq *ASM_PFX(mOriginalHandler)(%rip)
|
||||
L1:
|
||||
addq $0x08, %rsp # skip error code for PF
|
||||
iretq
|
|
@ -1,135 +0,0 @@
|
|||
;; @file
|
||||
; This is the assembly code for transferring to control to OS S3 waking vector
|
||||
; for X64 platform
|
||||
;
|
||||
; Copyright (c) 2006 - 2012, 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.
|
||||
;
|
||||
;;
|
||||
|
||||
EXTERN mOriginalHandler:QWORD
|
||||
EXTERN PageFaultHandler:PROC
|
||||
|
||||
.code
|
||||
|
||||
PUBLIC AsmFixAddress16
|
||||
PUBLIC AsmJmpAddr32
|
||||
|
||||
AsmTransferControl PROC
|
||||
; rcx S3WakingVector :DWORD
|
||||
; rdx AcpiLowMemoryBase :DWORD
|
||||
lea eax, @F
|
||||
mov r8, 2800000000h
|
||||
or rax, r8
|
||||
push rax
|
||||
shrd ebx, ecx, 20
|
||||
and ecx, 0fh
|
||||
mov bx, cx
|
||||
mov [@jmp_addr], ebx
|
||||
retf
|
||||
@@:
|
||||
DB 0b8h, 30h, 0 ; mov ax, 30h as selector
|
||||
mov ds, eax
|
||||
mov es, eax
|
||||
mov fs, eax
|
||||
mov gs, eax
|
||||
mov ss, eax
|
||||
mov rax, cr0
|
||||
mov rbx, cr4
|
||||
DB 66h
|
||||
and eax, ((NOT 080000001h) AND 0ffffffffh)
|
||||
and bl, NOT (1 SHL 5)
|
||||
mov cr0, rax
|
||||
DB 66h
|
||||
mov ecx, 0c0000080h
|
||||
rdmsr
|
||||
and ah, NOT 1
|
||||
wrmsr
|
||||
mov cr4, rbx
|
||||
DB 0eah ; jmp far @jmp_addr
|
||||
@jmp_addr DD ?
|
||||
AsmTransferControl ENDP
|
||||
|
||||
AsmTransferControl32 PROC
|
||||
; S3WakingVector :DWORD
|
||||
; AcpiLowMemoryBase :DWORD
|
||||
push rbp
|
||||
mov ebp, esp
|
||||
DB 8dh, 05h ; lea eax, AsmTransferControl16
|
||||
AsmFixAddress16 DD ?
|
||||
push 28h ; CS
|
||||
push rax
|
||||
retf
|
||||
AsmTransferControl32 ENDP
|
||||
|
||||
AsmTransferControl16 PROC
|
||||
DB 0b8h, 30h, 0 ; mov ax, 30h as selector
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
mov ss, ax
|
||||
mov rax, cr0 ; Get control register 0
|
||||
DB 66h
|
||||
DB 83h, 0e0h, 0feh ; and eax, 0fffffffeh ; Clear PE bit (bit #0)
|
||||
DB 0fh, 22h, 0c0h ; mov cr0, eax ; Activate real mode
|
||||
DB 0eah ; jmp far AsmJmpAddr32
|
||||
AsmJmpAddr32 DD ?
|
||||
AsmTransferControl16 ENDP
|
||||
|
||||
PageFaultHandlerHook PROC
|
||||
push rax ; save all volatile registers
|
||||
push rcx
|
||||
push rdx
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
; save volatile fp registers
|
||||
add rsp, -68h
|
||||
stmxcsr [rsp + 60h]
|
||||
movdqa [rsp + 0h], xmm0
|
||||
movdqa [rsp + 10h], xmm1
|
||||
movdqa [rsp + 20h], xmm2
|
||||
movdqa [rsp + 30h], xmm3
|
||||
movdqa [rsp + 40h], xmm4
|
||||
movdqa [rsp + 50h], xmm5
|
||||
|
||||
add rsp, -20h
|
||||
call PageFaultHandler
|
||||
add rsp, 20h
|
||||
|
||||
; load volatile fp registers
|
||||
ldmxcsr [rsp + 60h]
|
||||
movdqa xmm0, [rsp + 0h]
|
||||
movdqa xmm1, [rsp + 10h]
|
||||
movdqa xmm2, [rsp + 20h]
|
||||
movdqa xmm3, [rsp + 30h]
|
||||
movdqa xmm4, [rsp + 40h]
|
||||
movdqa xmm5, [rsp + 50h]
|
||||
add rsp, 68h
|
||||
|
||||
test al, al
|
||||
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax ; restore all volatile registers
|
||||
jnz @F
|
||||
jmp mOriginalHandler
|
||||
@@:
|
||||
add rsp, 08h ; skip error code for PF
|
||||
iretq
|
||||
PageFaultHandlerHook ENDP
|
||||
|
||||
END
|
|
@ -9,7 +9,7 @@
|
|||
# This external input must be validated carefully to avoid security issue like
|
||||
# buffer overflow, integer overflow.
|
||||
#
|
||||
# Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions
|
||||
|
@ -39,8 +39,6 @@
|
|||
[Sources]
|
||||
X64/X64Entry.c
|
||||
X64/PageFaultHandler.nasm
|
||||
X64/PageFaultHandler.asm
|
||||
X64/PageFaultHandler.S
|
||||
Common/CapsuleCoalesce.c
|
||||
|
||||
[Packages]
|
||||
|
|
|
@ -1,81 +0,0 @@
|
|||
## @file
|
||||
# This is the assembly code for page fault handler hook.
|
||||
#
|
||||
# Copyright (c) 2015, 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.
|
||||
#
|
||||
##
|
||||
|
||||
ASM_GLOBAL ASM_PFX(PageFaultHandlerHook)
|
||||
ASM_PFX(PageFaultHandlerHook):
|
||||
addq $-0x10, %rsp
|
||||
# save rax
|
||||
movq %rax, 0x08(%rsp)
|
||||
|
||||
# pushq %rax # save all volatile registers
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %r8
|
||||
pushq %r9
|
||||
pushq %r10
|
||||
pushq %r11
|
||||
# save volatile fp registers
|
||||
# 68h + 08h(for alignment)
|
||||
addq $-0x70, %rsp
|
||||
stmxcsr 0x60(%rsp)
|
||||
movdqa %xmm0, 0x0(%rsp)
|
||||
movdqa %xmm1, 0x10(%rsp)
|
||||
movdqa %xmm2, 0x20(%rsp)
|
||||
movdqa %xmm3, 0x30(%rsp)
|
||||
movdqa %xmm4, 0x40(%rsp)
|
||||
movdqa %xmm5, 0x50(%rsp)
|
||||
|
||||
addq $-0x20, %rsp
|
||||
call ASM_PFX(PageFaultHandler)
|
||||
addq $0x20, %rsp
|
||||
|
||||
# load volatile fp registers
|
||||
ldmxcsr 0x60(%rsp)
|
||||
movdqa 0x0(%rsp), %xmm0
|
||||
movdqa 0x10(%rsp), %xmm1
|
||||
movdqa 0x20(%rsp), %xmm2
|
||||
movdqa 0x30(%rsp), %xmm3
|
||||
movdqa 0x40(%rsp), %xmm4
|
||||
movdqa 0x50(%rsp), %xmm5
|
||||
addq $0x70, %rsp
|
||||
|
||||
popq %r11
|
||||
popq %r10
|
||||
popq %r9
|
||||
popq %r8
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
# popq %rax # restore all volatile registers
|
||||
|
||||
addq $0x10, %rsp
|
||||
|
||||
# rax returned from PageFaultHandler is NULL or OriginalHandler address
|
||||
# NULL if the page fault is handled by PageFaultHandler
|
||||
# OriginalHandler address if the page fault is not handled by PageFaultHandler
|
||||
testq %rax, %rax
|
||||
|
||||
# save OriginalHandler address
|
||||
movq %rax, -0x10(%rsp)
|
||||
# restore rax
|
||||
movq -0x08(%rsp), %rax
|
||||
|
||||
jz L1
|
||||
|
||||
# jump to OriginalHandler
|
||||
jmpq *-0x10(%rsp)
|
||||
|
||||
L1:
|
||||
addq $0x08, %rsp # skip error code for PF
|
||||
iretq
|
|
@ -1,87 +0,0 @@
|
|||
;; @file
|
||||
; This is the assembly code for page fault handler hook.
|
||||
;
|
||||
; Copyright (c) 2015, 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.
|
||||
;
|
||||
;;
|
||||
|
||||
EXTERN PageFaultHandler:PROC
|
||||
|
||||
.code
|
||||
|
||||
PageFaultHandlerHook PROC
|
||||
add rsp, -10h
|
||||
; save rax
|
||||
mov [rsp + 08h], rax
|
||||
|
||||
;push rax ; save all volatile registers
|
||||
push rcx
|
||||
push rdx
|
||||
push r8
|
||||
push r9
|
||||
push r10
|
||||
push r11
|
||||
; save volatile fp registers
|
||||
; 68h + 08h(for alignment)
|
||||
add rsp, -70h
|
||||
stmxcsr [rsp + 60h]
|
||||
movdqa [rsp + 0h], xmm0
|
||||
movdqa [rsp + 10h], xmm1
|
||||
movdqa [rsp + 20h], xmm2
|
||||
movdqa [rsp + 30h], xmm3
|
||||
movdqa [rsp + 40h], xmm4
|
||||
movdqa [rsp + 50h], xmm5
|
||||
|
||||
add rsp, -20h
|
||||
call PageFaultHandler
|
||||
add rsp, 20h
|
||||
|
||||
; load volatile fp registers
|
||||
ldmxcsr [rsp + 60h]
|
||||
movdqa xmm0, [rsp + 0h]
|
||||
movdqa xmm1, [rsp + 10h]
|
||||
movdqa xmm2, [rsp + 20h]
|
||||
movdqa xmm3, [rsp + 30h]
|
||||
movdqa xmm4, [rsp + 40h]
|
||||
movdqa xmm5, [rsp + 50h]
|
||||
add rsp, 70h
|
||||
|
||||
pop r11
|
||||
pop r10
|
||||
pop r9
|
||||
pop r8
|
||||
pop rdx
|
||||
pop rcx
|
||||
;pop rax ; restore all volatile registers
|
||||
|
||||
add rsp, 10h
|
||||
|
||||
; rax returned from PageFaultHandler is NULL or OriginalHandler address
|
||||
; NULL if the page fault is handled by PageFaultHandler
|
||||
; OriginalHandler address if the page fault is not handled by PageFaultHandler
|
||||
test rax, rax
|
||||
|
||||
; save OriginalHandler address
|
||||
mov [rsp - 10h], rax
|
||||
; restore rax
|
||||
mov rax, [rsp - 08h]
|
||||
|
||||
jz @F
|
||||
|
||||
; jump to OriginalHandler
|
||||
jmp qword ptr [rsp - 10h]
|
||||
|
||||
@@:
|
||||
add rsp, 08h ; skip error code for PF
|
||||
iretq
|
||||
PageFaultHandlerHook ENDP
|
||||
|
||||
END
|
|
@ -6,7 +6,7 @@
|
|||
# provides debug-agent to periodically gain control during operation of the machine to
|
||||
# check for asynchronous commands form the host.
|
||||
#
|
||||
# Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2006 - 2018, 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
|
||||
|
@ -42,8 +42,6 @@
|
|||
Ia32/PlDebugSupport.h
|
||||
Ia32/PlDebugSupportIa32.c
|
||||
Ia32/AsmFuncs.nasm
|
||||
Ia32/AsmFuncs.S
|
||||
Ia32/AsmFuncs.asm
|
||||
|
||||
[Sources.X64]
|
||||
Ia32/DebugSupport.h
|
||||
|
@ -51,8 +49,6 @@
|
|||
X64/PlDebugSupport.h
|
||||
X64/PlDebugSupportX64.c
|
||||
X64/AsmFuncs.nasm
|
||||
X64/AsmFuncs.S
|
||||
X64/AsmFuncs.asm
|
||||
|
||||
[Sources.IPF]
|
||||
Ipf/PlDebugSupport.h
|
||||
|
|
|
@ -1,407 +0,0 @@
|
|||
#/**@file
|
||||
# Low leve IA32 specific debug support functions.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#**/
|
||||
|
||||
ASM_GLOBAL ASM_PFX(OrigVector)
|
||||
ASM_GLOBAL ASM_PFX(InterruptEntryStub)
|
||||
ASM_GLOBAL ASM_PFX(StubSize)
|
||||
ASM_GLOBAL ASM_PFX(CommonIdtEntry)
|
||||
ASM_GLOBAL ASM_PFX(FxStorSupport)
|
||||
|
||||
ASM_PFX(StubSize): .long ASM_PFX(InterruptEntryStubEnd) - ASM_PFX(InterruptEntryStub)
|
||||
ASM_PFX(AppEsp): .long 0x11111111 # ?
|
||||
ASM_PFX(DebugEsp): .long 0x22222222 # ?
|
||||
ASM_PFX(ExtraPush): .long 0x33333333 # ?
|
||||
ASM_PFX(ExceptData): .long 0x44444444 # ?
|
||||
ASM_PFX(Eflags): .long 0x55555555 # ?
|
||||
ASM_PFX(OrigVector): .long 0x66666666 # ?
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# BOOLEAN
|
||||
# FxStorSupport (
|
||||
# void
|
||||
# )
|
||||
#
|
||||
# Abstract: Returns TRUE if FxStor instructions are supported
|
||||
#
|
||||
ASM_GLOBAL ASM_PFX(FxStorSupport)
|
||||
ASM_PFX(FxStorSupport):
|
||||
#
|
||||
# cpuid corrupts ebx which must be preserved per the C calling convention
|
||||
#
|
||||
push %ebx
|
||||
mov $0x1,%eax
|
||||
cpuid
|
||||
mov %edx,%eax
|
||||
and $0x1000000,%eax
|
||||
shr $0x18,%eax
|
||||
pop %ebx
|
||||
ret
|
||||
#------------------------------------------------------------------------------
|
||||
# void
|
||||
# Vect2Desc (
|
||||
# DESCRIPTOR * DestDesc,
|
||||
# void (*Vector) (void)
|
||||
# )
|
||||
#
|
||||
# Abstract: Encodes an IDT descriptor with the given physical address
|
||||
#
|
||||
|
||||
ASM_GLOBAL ASM_PFX(Vect2Desc)
|
||||
ASM_PFX(Vect2Desc):
|
||||
push %ebp
|
||||
mov %esp,%ebp
|
||||
mov 0xc(%ebp),%eax
|
||||
mov 0x8(%ebp),%ecx
|
||||
mov %ax,(%ecx)
|
||||
movw $0x20,0x2(%ecx)
|
||||
movw $0x8e00,0x4(%ecx)
|
||||
shr $0x10,%eax
|
||||
mov %ax,0x6(%ecx)
|
||||
leave
|
||||
ret
|
||||
|
||||
ASM_GLOBAL ASM_PFX(InterruptEntryStub)
|
||||
ASM_PFX(InterruptEntryStub):
|
||||
mov %esp,0x0 # save stack top
|
||||
mov $0x0,%esp # switch to debugger stack
|
||||
push $0x0 # push vector number - will be modified before installed
|
||||
jmp ASM_PFX(CommonIdtEntry) # jump CommonIdtEntry
|
||||
ASM_GLOBAL ASM_PFX(InterruptEntryStubEnd)
|
||||
ASM_PFX(InterruptEntryStubEnd):
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# CommonIdtEntry
|
||||
#
|
||||
# Abstract: This code is not a function, but is the common part for all IDT
|
||||
# vectors.
|
||||
#
|
||||
ASM_GLOBAL ASM_PFX(CommonIdtEntry)
|
||||
ASM_PFX(CommonIdtEntry):
|
||||
##
|
||||
## At this point, the stub has saved the current application stack esp into AppEsp
|
||||
## and switched stacks to the debug stack, where it pushed the vector number
|
||||
##
|
||||
## The application stack looks like this:
|
||||
##
|
||||
## ...
|
||||
## (last application stack entry)
|
||||
## eflags from interrupted task
|
||||
## CS from interrupted task
|
||||
## EIP from interrupted task
|
||||
## Error code <-------------------- Only present for some exeption types
|
||||
##
|
||||
##
|
||||
|
||||
|
||||
## The stub switched us to the debug stack and pushed the interrupt number.
|
||||
##
|
||||
## Next, construct the context record. It will be build on the debug stack by
|
||||
## pushing the registers in the correct order so as to create the context structure
|
||||
## on the debug stack. The context record must be built from the end back to the
|
||||
## beginning because the stack grows down...
|
||||
#
|
||||
## For reference, the context record looks like this:
|
||||
##
|
||||
## typedef
|
||||
## struct {
|
||||
## UINT32 ExceptionData;
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
## UINT32 Cr0, Cr2, Cr3, Cr4;
|
||||
## UINT32 EFlags;
|
||||
## UINT32 Ldtr, Tr;
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
## UINT32 Eip;
|
||||
## UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
## } SYSTEM_CONTEXT_IA32; // 32 bit system context record
|
||||
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
pusha
|
||||
## Save interrupt state eflags register...
|
||||
pushf
|
||||
pop %eax
|
||||
## We need to determine if any extra data was pushed by the exception, and if so, save it
|
||||
## To do this, we check the exception number pushed by the stub, and cache the
|
||||
## result in a variable since we'll need this again.
|
||||
mov %eax,0x0
|
||||
cmpl $0x8,0x0
|
||||
jne ASM_PFX(CommonIdtEntry+0x20)
|
||||
movl $0x1,0x0
|
||||
jmp ASM_PFX(CommonIdtEntry+0xa8)
|
||||
cmpl $0xa,0x0
|
||||
jne ASM_PFX(CommonIdtEntry+0x35)
|
||||
movl $0x1,0x0
|
||||
jmp ASM_PFX(CommonIdtEntry+0xa8)
|
||||
cmpl $0xb,0x0
|
||||
jne ASM_PFX(CommonIdtEntry+0x4a)
|
||||
movl $0x1,0x0
|
||||
jmp ASM_PFX(CommonIdtEntry+0xa8)
|
||||
cmpl $0xc,0x0
|
||||
jne ASM_PFX(CommonIdtEntry+0x5f)
|
||||
movl $0x1,0x0
|
||||
jmp ASM_PFX(CommonIdtEntry+0xa8)
|
||||
cmpl $0xd,0x0
|
||||
jne ASM_PFX(CommonIdtEntry+0x74)
|
||||
movl $0x1,0x0
|
||||
jmp ASM_PFX(CommonIdtEntry+0xa8)
|
||||
cmpl $0xe,0x0
|
||||
jne ASM_PFX(CommonIdtEntry+0x89)
|
||||
movl $0x1,0x0
|
||||
jmp ASM_PFX(CommonIdtEntry+0xa8)
|
||||
cmpl $0x11,0x0
|
||||
jne ASM_PFX(CommonIdtEntry+0x9e)
|
||||
movl $0x1,0x0
|
||||
jmp ASM_PFX(CommonIdtEntry+0xa8)
|
||||
movl $0x0,0x0
|
||||
## If there's some extra data, save it also, and modify the saved AppEsp to effectively
|
||||
## pop this value off the application's stack.
|
||||
|
||||
cmpl $0x1,0x0
|
||||
jne ASM_PFX(CommonIdtEntry+0xc8)
|
||||
mov 0x0,%eax
|
||||
mov (%eax),%ebx
|
||||
mov %ebx,0x0
|
||||
add $0x4,%eax
|
||||
mov %eax,0x0
|
||||
jmp ASM_PFX(CommonIdtEntry+0xd2)
|
||||
movl $0x0,0x0
|
||||
## The "pushad" above pushed the debug stack esp. Since what we're actually doing
|
||||
## is building the context record on the debug stack, we need to save the pushed
|
||||
## debug ESP, and replace it with the application's last stack entry...
|
||||
mov 0xc(%esp),%eax
|
||||
mov %eax,0x0
|
||||
mov 0x0,%eax
|
||||
add $0xc,%eax
|
||||
# application stack has eflags, cs, & eip, so
|
||||
# last actual application stack entry is
|
||||
# 12 bytes into the application stack.
|
||||
mov %eax,0xc(%esp)
|
||||
## continue building context record
|
||||
## UINT32 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
|
||||
mov %ss,%eax
|
||||
push %eax
|
||||
|
||||
# CS from application is one entry back in application stack
|
||||
mov 0x0,%eax
|
||||
movzwl 0x4(%eax),%eax
|
||||
push %eax
|
||||
mov %ds,%eax
|
||||
push %eax
|
||||
mov %es,%eax
|
||||
push %eax
|
||||
mov %fs,%eax
|
||||
push %eax
|
||||
mov %gs,%eax
|
||||
push %eax
|
||||
|
||||
## UINT32 Eip;
|
||||
# Eip from application is on top of application stack
|
||||
mov 0x0,%eax
|
||||
pushl (%eax)
|
||||
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
push $0x0
|
||||
push $0x0
|
||||
sidtl (%esp)
|
||||
push $0x0
|
||||
push $0x0
|
||||
sgdtl (%esp)
|
||||
|
||||
## UINT32 Ldtr, Tr;
|
||||
xor %eax,%eax
|
||||
str %eax
|
||||
push %eax
|
||||
sldt %eax
|
||||
push %eax
|
||||
|
||||
## UINT32 EFlags;
|
||||
## Eflags from application is two entries back in application stack
|
||||
mov 0x0,%eax
|
||||
pushl 0x8(%eax)
|
||||
|
||||
## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
## insure FXSAVE/FXRSTOR is enabled in CR4...
|
||||
## ... while we're at it, make sure DE is also enabled...
|
||||
mov %cr4,%eax
|
||||
or $0x208,%eax
|
||||
mov %eax,%cr4
|
||||
push %eax
|
||||
mov %cr3,%eax
|
||||
push %eax
|
||||
mov %cr2,%eax
|
||||
push %eax
|
||||
push $0x0
|
||||
mov %cr0,%eax
|
||||
push %eax
|
||||
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
mov %db7,%eax
|
||||
push %eax
|
||||
|
||||
## clear Dr7 while executing debugger itself
|
||||
xor %eax,%eax
|
||||
mov %eax,%db7
|
||||
mov %db6,%eax
|
||||
push %eax
|
||||
|
||||
## insure all status bits in dr6 are clear...
|
||||
xor %eax,%eax
|
||||
mov %eax,%db6
|
||||
mov %db3,%eax
|
||||
push %eax
|
||||
mov %db2,%eax
|
||||
push %eax
|
||||
mov %db1,%eax
|
||||
push %eax
|
||||
mov %db0,%eax
|
||||
push %eax
|
||||
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
sub $0x200,%esp
|
||||
mov %esp,%edi
|
||||
# IMPORTANT!! The debug stack has been carefully constructed to
|
||||
# insure that esp and edi are 16 byte aligned when we get here.
|
||||
# They MUST be. If they are not, a GP fault will occur.
|
||||
fxsave (%edi)
|
||||
|
||||
## UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
## UINT32 ExceptionData;
|
||||
mov 0x0,%eax
|
||||
push %eax
|
||||
|
||||
# call to C code which will in turn call registered handler
|
||||
# pass in the vector number
|
||||
mov %esp,%eax
|
||||
push %eax
|
||||
mov 0x0,%eax
|
||||
push %eax
|
||||
call ASM_PFX(CommonIdtEntry+0x184)
|
||||
add $0x8,%esp
|
||||
|
||||
# restore context...
|
||||
## UINT32 ExceptionData;
|
||||
add $0x4,%esp
|
||||
|
||||
## FX_SAVE_STATE_IA32 FxSaveState;
|
||||
mov %esp,%esi
|
||||
fxrstor (%esi)
|
||||
add $0x200,%esp
|
||||
|
||||
## UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
pop %eax
|
||||
mov %eax,%db0
|
||||
pop %eax
|
||||
mov %eax,%db1
|
||||
pop %eax
|
||||
mov %eax,%db2
|
||||
pop %eax
|
||||
mov %eax,%db3
|
||||
|
||||
## skip restore of dr6. We cleared dr6 during the context save.
|
||||
add $0x4,%esp
|
||||
pop %eax
|
||||
mov %eax,%db7
|
||||
|
||||
## UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
pop %eax
|
||||
mov %eax,%cr0
|
||||
add $0x4,%esp
|
||||
pop %eax
|
||||
mov %eax,%cr2
|
||||
pop %eax
|
||||
mov %eax,%cr3
|
||||
pop %eax
|
||||
mov %eax,%cr4
|
||||
|
||||
## UINT32 EFlags;
|
||||
mov 0x0,%eax
|
||||
popl 0x8(%eax)
|
||||
|
||||
## UINT32 Ldtr, Tr;
|
||||
## UINT32 Gdtr[2], Idtr[2];
|
||||
## Best not let anyone mess with these particular registers...
|
||||
add $0x18,%esp
|
||||
|
||||
## UINT32 Eip;
|
||||
popl (%eax)
|
||||
|
||||
## UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs;
|
||||
## 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
|
||||
popl 0x4(%eax)
|
||||
pop %ss
|
||||
mov 0xc(%esp),%ebx
|
||||
|
||||
## The next stuff to restore is the general purpose registers that were pushed
|
||||
## using the "pushad" instruction.
|
||||
##
|
||||
## The value of ESP as stored in the context record is the application ESP
|
||||
## including the 3 entries on the application stack caused by the exception
|
||||
## itself. It may have been modified by the debug agent, so we need to
|
||||
## determine if we need to relocate the application stack.
|
||||
|
||||
mov 0x0,%eax # move the potentially modified AppEsp into ebx
|
||||
add $0xc,%eax
|
||||
cmp %eax,%ebx
|
||||
je ASM_PFX(CommonIdtEntry+0x202)
|
||||
mov 0x0,%eax
|
||||
mov (%eax),%ecx # EIP
|
||||
mov %ecx,(%ebx)
|
||||
mov 0x4(%eax),%ecx # CS
|
||||
mov %ecx,0x4(%ebx)
|
||||
mov 0x8(%eax),%ecx # EFLAGS
|
||||
mov %ecx,0x8(%ebx)
|
||||
|
||||
mov %ebx,%eax # modify the saved AppEsp to the new AppEsp
|
||||
mov %eax,0x0
|
||||
mov 0x0,%eax # restore the DebugEsp on the debug stack
|
||||
# so our "popad" will not cause a stack switch
|
||||
mov %eax,0xc(%esp)
|
||||
cmpl $0x68,0x0
|
||||
jne PhonyIretd+0xd
|
||||
## Restore eflags so when we chain, the flags will be exactly as if we were never here.
|
||||
## We gin up the stack to do an iretd so we can get ALL the flags.
|
||||
mov 0x0,%eax
|
||||
mov 0x8(%eax),%ebx
|
||||
and $0xfffffcff,%ebx # special handling for IF and TF
|
||||
push %ebx
|
||||
push %cs
|
||||
push $0x0
|
||||
iret
|
||||
|
||||
PhonyIretd:
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
popa
|
||||
|
||||
## Switch back to application stack
|
||||
mov 0x0,%esp
|
||||
jmp *0x0
|
||||
## Jump to original handler
|
||||
## UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
popa
|
||||
## Switch back to application stack
|
||||
mov 0x0,%esp
|
||||
|
||||
## We're outa here...
|
||||
iret
|
|
@ -1,509 +0,0 @@
|
|||
;/** @file
|
||||
; Low leve IA32 specific debug support functions.
|
||||
;
|
||||
; 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.
|
||||
;
|
||||
;**/
|
||||
|
||||
.586p
|
||||
.MODEL FLAT, C
|
||||
|
||||
EXCPT32_DIVIDE_ERROR EQU 0
|
||||
EXCPT32_DEBUG EQU 1
|
||||
EXCPT32_NMI EQU 2
|
||||
EXCPT32_BREAKPOINT EQU 3
|
||||
EXCPT32_OVERFLOW EQU 4
|
||||
EXCPT32_BOUND EQU 5
|
||||
EXCPT32_INVALID_OPCODE EQU 6
|
||||
EXCPT32_DOUBLE_FAULT EQU 8
|
||||
EXCPT32_INVALID_TSS EQU 10
|
||||
EXCPT32_SEG_NOT_PRESENT EQU 11
|
||||
EXCPT32_STACK_FAULT EQU 12
|
||||
EXCPT32_GP_FAULT EQU 13
|
||||
EXCPT32_PAGE_FAULT EQU 14
|
||||
EXCPT32_FP_ERROR EQU 16
|
||||
EXCPT32_ALIGNMENT_CHECK EQU 17
|
||||
EXCPT32_MACHINE_CHECK EQU 18
|
||||
EXCPT32_SIMD EQU 19
|
||||
|
||||
FXSTOR_FLAG EQU 01000000h ; bit cpuid 24 of feature flags
|
||||
|
||||
;; The FXSTOR and FXRSTOR commands are used for saving and restoring the x87,
|
||||
;; MMX, SSE, SSE2, etc registers. The initialization of the debugsupport driver
|
||||
;; MUST check the CPUID feature flags to see that these instructions are available
|
||||
;; and fail to init if they are not.
|
||||
|
||||
;; fxstor [edi]
|
||||
FXSTOR_EDI MACRO
|
||||
db 0fh, 0aeh, 00000111y ; mod = 00, reg/op = 000, r/m = 111 = [edi]
|
||||
ENDM
|
||||
|
||||
;; fxrstor [esi]
|
||||
FXRSTOR_ESI MACRO
|
||||
db 0fh, 0aeh, 00001110y ; mod = 00, reg/op = 001, r/m = 110 = [esi]
|
||||
ENDM
|
||||
.DATA
|
||||
|
||||
public OrigVector, InterruptEntryStub, StubSize, CommonIdtEntry, FxStorSupport
|
||||
|
||||
StubSize dd InterruptEntryStubEnd - InterruptEntryStub
|
||||
AppEsp dd 11111111h ; ?
|
||||
DebugEsp dd 22222222h ; ?
|
||||
ExtraPush dd 33333333h ; ?
|
||||
ExceptData dd 44444444h ; ?
|
||||
Eflags dd 55555555h ; ?
|
||||
OrigVector dd 66666666h ; ?
|
||||
|
||||
;; The declarations below define the memory region that will be used for the debug stack.
|
||||
;; The context record will be built by pushing register values onto this stack.
|
||||
;; It is imparitive that alignment be carefully managed, since the FXSTOR and
|
||||
;; FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.
|
||||
;;
|
||||
;; The stub will switch stacks from the application stack to the debuger stack
|
||||
;; and pushes the exception number.
|
||||
;;
|
||||
;; Then we building the context record on the stack. Since the stack grows down,
|
||||
;; we push the fields of the context record from the back to the front. There
|
||||
;; are 132 bytes of stack used prior allocating the 512 bytes of stack to be
|
||||
;; used as the memory buffer for the fxstor instruction. Therefore address of
|
||||
;; the buffer used for the FXSTOR instruction is &Eax - 132 - 512, which
|
||||
;; must be 16 byte aligned.
|
||||
;;
|
||||
;; We carefully locate the stack to make this happen.
|
||||
;;
|
||||
;; For reference, the context structure looks like this:
|
||||
;; struct {
|
||||
;; UINT32 ExceptionData;
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState; // 512 bytes, must be 16 byte aligned
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
;; UINT32 EFlags;
|
||||
;; UINT32 Ldtr, Tr;
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
;; UINT32 Eip;
|
||||
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
;; } SYSTEM_CONTEXT_IA32; // 32 bit system context record
|
||||
|
||||
|
||||
align 16
|
||||
DebugStackEnd db "DbgStkEnd >>>>>>" ;; 16 byte long string - must be 16 bytes to preserve alignment
|
||||
dd 1ffdh dup (000000000h) ;; 32K should be enough stack
|
||||
;; This allocation is coocked to insure
|
||||
;; that the the buffer for the FXSTORE instruction
|
||||
;; will be 16 byte aligned also.
|
||||
;;
|
||||
ExceptionNumber dd ? ;; first entry will be the vector number pushed by the stub
|
||||
|
||||
DebugStackBegin db "<<<< DbgStkBegin" ;; initial debug ESP == DebugStackBegin, set in stub
|
||||
|
||||
.CODE
|
||||
|
||||
externdef InterruptDistrubutionHub:near
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; BOOLEAN
|
||||
; FxStorSupport (
|
||||
; void
|
||||
; )
|
||||
;
|
||||
; Abstract: Returns TRUE if FxStor instructions are supported
|
||||
;
|
||||
FxStorSupport PROC C PUBLIC
|
||||
|
||||
;
|
||||
; cpuid corrupts ebx which must be preserved per the C calling convention
|
||||
;
|
||||
push ebx
|
||||
mov eax, 1
|
||||
cpuid
|
||||
mov eax, edx
|
||||
and eax, FXSTOR_FLAG
|
||||
shr eax, 24
|
||||
pop ebx
|
||||
ret
|
||||
FxStorSupport ENDP
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; void
|
||||
; Vect2Desc (
|
||||
; DESCRIPTOR * DestDesc,
|
||||
; void (*Vector) (void)
|
||||
; )
|
||||
;
|
||||
; Abstract: Encodes an IDT descriptor with the given physical address
|
||||
;
|
||||
Vect2Desc PROC C PUBLIC DestPtr:DWORD, Vector:DWORD
|
||||
|
||||
mov eax, Vector
|
||||
mov ecx, DestPtr
|
||||
mov word ptr [ecx], ax ; write bits 15..0 of offset
|
||||
mov dx, cs
|
||||
mov word ptr [ecx+2], dx ; SYS_CODE_SEL from GDT
|
||||
mov word ptr [ecx+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
|
||||
shr eax, 16
|
||||
mov word ptr [ecx+6], ax ; write bits 31..16 of offset
|
||||
|
||||
ret
|
||||
|
||||
Vect2Desc ENDP
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; InterruptEntryStub
|
||||
;
|
||||
; Abstract: This code is not a function, but is a small piece of code that is
|
||||
; copied and fixed up once for each IDT entry that is hooked.
|
||||
;
|
||||
InterruptEntryStub::
|
||||
mov AppEsp, esp ; save stack top
|
||||
mov esp, offset DebugStackBegin ; switch to debugger stack
|
||||
push 0 ; push vector number - will be modified before installed
|
||||
db 0e9h ; jump rel32
|
||||
dd 0 ; fixed up to relative address of CommonIdtEntry
|
||||
InterruptEntryStubEnd:
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; CommonIdtEntry
|
||||
;
|
||||
; Abstract: This code is not a function, but is the common part for all IDT
|
||||
; vectors.
|
||||
;
|
||||
CommonIdtEntry::
|
||||
;;
|
||||
;; At this point, the stub has saved the current application stack esp into AppEsp
|
||||
;; and switched stacks to the debug stack, where it pushed the vector number
|
||||
;;
|
||||
;; The application stack looks like this:
|
||||
;;
|
||||
;; ...
|
||||
;; (last application stack entry)
|
||||
;; eflags from interrupted task
|
||||
;; CS from interrupted task
|
||||
;; EIP from interrupted task
|
||||
;; Error code <-------------------- Only present for some exeption types
|
||||
;;
|
||||
;;
|
||||
|
||||
|
||||
;; The stub switched us to the debug stack and pushed the interrupt number.
|
||||
;;
|
||||
;; Next, construct the context record. It will be build on the debug stack by
|
||||
;; pushing the registers in the correct order so as to create the context structure
|
||||
;; on the debug stack. The context record must be built from the end back to the
|
||||
;; beginning because the stack grows down...
|
||||
;
|
||||
;; For reference, the context record looks like this:
|
||||
;;
|
||||
;; typedef
|
||||
;; struct {
|
||||
;; UINT32 ExceptionData;
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState;
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
;; UINT32 Cr0, Cr2, Cr3, Cr4;
|
||||
;; UINT32 EFlags;
|
||||
;; UINT32 Ldtr, Tr;
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
;; UINT32 Eip;
|
||||
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
;; } SYSTEM_CONTEXT_IA32; // 32 bit system context record
|
||||
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
pushad
|
||||
|
||||
;; Save interrupt state eflags register...
|
||||
pushfd
|
||||
pop eax
|
||||
mov dword ptr Eflags, eax
|
||||
|
||||
;; We need to determine if any extra data was pushed by the exception, and if so, save it
|
||||
;; To do this, we check the exception number pushed by the stub, and cache the
|
||||
;; result in a variable since we'll need this again.
|
||||
.IF ExceptionNumber == EXCPT32_DOUBLE_FAULT
|
||||
mov ExtraPush, 1
|
||||
.ELSEIF ExceptionNumber == EXCPT32_INVALID_TSS
|
||||
mov ExtraPush, 1
|
||||
.ELSEIF ExceptionNumber == EXCPT32_SEG_NOT_PRESENT
|
||||
mov ExtraPush, 1
|
||||
.ELSEIF ExceptionNumber == EXCPT32_STACK_FAULT
|
||||
mov ExtraPush, 1
|
||||
.ELSEIF ExceptionNumber == EXCPT32_GP_FAULT
|
||||
mov ExtraPush, 1
|
||||
.ELSEIF ExceptionNumber == EXCPT32_PAGE_FAULT
|
||||
mov ExtraPush, 1
|
||||
.ELSEIF ExceptionNumber == EXCPT32_ALIGNMENT_CHECK
|
||||
mov ExtraPush, 1
|
||||
.ELSE
|
||||
mov ExtraPush, 0
|
||||
.ENDIF
|
||||
|
||||
;; If there's some extra data, save it also, and modify the saved AppEsp to effectively
|
||||
;; pop this value off the application's stack.
|
||||
.IF ExtraPush == 1
|
||||
mov eax, AppEsp
|
||||
mov ebx, [eax]
|
||||
mov ExceptData, ebx
|
||||
add eax, 4
|
||||
mov AppEsp, eax
|
||||
.ELSE
|
||||
mov ExceptData, 0
|
||||
.ENDIF
|
||||
|
||||
;; The "pushad" above pushed the debug stack esp. Since what we're actually doing
|
||||
;; is building the context record on the debug stack, we need to save the pushed
|
||||
;; debug ESP, and replace it with the application's last stack entry...
|
||||
mov eax, [esp + 12]
|
||||
mov DebugEsp, eax
|
||||
mov eax, AppEsp
|
||||
add eax, 12
|
||||
; application stack has eflags, cs, & eip, so
|
||||
; last actual application stack entry is
|
||||
; 12 bytes into the application stack.
|
||||
mov [esp + 12], eax
|
||||
|
||||
;; continue building context record
|
||||
;; UINT32 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
|
||||
mov eax, ss
|
||||
push eax
|
||||
|
||||
; CS from application is one entry back in application stack
|
||||
mov eax, AppEsp
|
||||
movzx eax, word ptr [eax + 4]
|
||||
push eax
|
||||
|
||||
mov eax, ds
|
||||
push eax
|
||||
mov eax, es
|
||||
push eax
|
||||
mov eax, fs
|
||||
push eax
|
||||
mov eax, gs
|
||||
push eax
|
||||
|
||||
;; UINT32 Eip;
|
||||
; Eip from application is on top of application stack
|
||||
mov eax, AppEsp
|
||||
push dword ptr [eax]
|
||||
|
||||
;; UINT32 Gdtr[2], Idtr[2];
|
||||
push 0
|
||||
push 0
|
||||
sidt fword ptr [esp]
|
||||
push 0
|
||||
push 0
|
||||
sgdt fword ptr [esp]
|
||||
|
||||
;; UINT32 Ldtr, Tr;
|
||||
xor eax, eax
|
||||
str ax
|
||||
push eax
|
||||
sldt ax
|
||||
push eax
|
||||
|
||||
;; UINT32 EFlags;
|
||||
;; Eflags from application is two entries back in application stack
|
||||
mov eax, AppEsp
|
||||
push dword ptr [eax + 8]
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
;; insure FXSAVE/FXRSTOR is enabled in CR4...
|
||||
;; ... while we're at it, make sure DE is also enabled...
|
||||
mov eax, cr4
|
||||
or eax, 208h
|
||||
mov cr4, eax
|
||||
push eax
|
||||
mov eax, cr3
|
||||
push eax
|
||||
mov eax, cr2
|
||||
push eax
|
||||
push 0
|
||||
mov eax, cr0
|
||||
push eax
|
||||
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
mov eax, dr7
|
||||
push eax
|
||||
;; clear Dr7 while executing debugger itself
|
||||
xor eax, eax
|
||||
mov dr7, eax
|
||||
|
||||
mov eax, dr6
|
||||
push eax
|
||||
;; insure all status bits in dr6 are clear...
|
||||
xor eax, eax
|
||||
mov dr6, 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
|
||||
; IMPORTANT!! The debug stack has been carefully constructed to
|
||||
; insure that esp and edi are 16 byte aligned when we get here.
|
||||
; They MUST be. If they are not, a GP fault will occur.
|
||||
FXSTOR_EDI
|
||||
|
||||
;; UEFI calling convention for IA32 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
;; UINT32 ExceptionData;
|
||||
mov eax, ExceptData
|
||||
push eax
|
||||
|
||||
; call to C code which will in turn call registered handler
|
||||
; pass in the vector number
|
||||
mov eax, esp
|
||||
push eax
|
||||
mov eax, ExceptionNumber
|
||||
push eax
|
||||
call InterruptDistrubutionHub
|
||||
add esp, 8
|
||||
|
||||
; restore context...
|
||||
;; UINT32 ExceptionData;
|
||||
add esp, 4
|
||||
|
||||
;; FX_SAVE_STATE_IA32 FxSaveState;
|
||||
mov esi, esp
|
||||
FXRSTOR_ESI
|
||||
add esp, 512
|
||||
|
||||
;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
pop eax
|
||||
mov dr0, eax
|
||||
pop eax
|
||||
mov dr1, eax
|
||||
pop eax
|
||||
mov dr2, eax
|
||||
pop eax
|
||||
mov dr3, eax
|
||||
;; skip restore of dr6. We cleared dr6 during the context save.
|
||||
add esp, 4
|
||||
pop eax
|
||||
mov dr7, eax
|
||||
|
||||
;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4;
|
||||
pop eax
|
||||
mov cr0, eax
|
||||
add esp, 4
|
||||
pop eax
|
||||
mov cr2, eax
|
||||
pop eax
|
||||
mov cr3, eax
|
||||
pop eax
|
||||
mov cr4, eax
|
||||
|
||||
;; UINT32 EFlags;
|
||||
mov eax, AppEsp
|
||||
pop dword ptr [eax + 8]
|
||||
|
||||
;; 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 [eax]
|
||||
|
||||
;; UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs;
|
||||
;; 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 [eax + 4]
|
||||
pop ss
|
||||
|
||||
;; The next stuff to restore is the general purpose registers that were pushed
|
||||
;; using the "pushad" instruction.
|
||||
;;
|
||||
;; The value of ESP as stored in the context record is the application ESP
|
||||
;; including the 3 entries on the application stack caused by the exception
|
||||
;; itself. It may have been modified by the debug agent, so we need to
|
||||
;; determine if we need to relocate the application stack.
|
||||
|
||||
mov ebx, [esp + 12] ; move the potentially modified AppEsp into ebx
|
||||
mov eax, AppEsp
|
||||
add eax, 12
|
||||
cmp ebx, eax
|
||||
je NoAppStackMove
|
||||
|
||||
mov eax, AppEsp
|
||||
mov ecx, [eax] ; EIP
|
||||
mov [ebx], ecx
|
||||
|
||||
mov ecx, [eax + 4] ; CS
|
||||
mov [ebx + 4], ecx
|
||||
|
||||
mov ecx, [eax + 8] ; EFLAGS
|
||||
mov [ebx + 8], ecx
|
||||
|
||||
mov eax, ebx ; modify the saved AppEsp to the new AppEsp
|
||||
mov AppEsp, eax
|
||||
NoAppStackMove:
|
||||
mov eax, DebugEsp ; restore the DebugEsp on the debug stack
|
||||
; so our "popad" will not cause a stack switch
|
||||
mov [esp + 12], eax
|
||||
|
||||
cmp ExceptionNumber, 068h
|
||||
jne NoChain
|
||||
|
||||
Chain:
|
||||
|
||||
;; Restore eflags so when we chain, the flags will be exactly as if we were never here.
|
||||
;; We gin up the stack to do an iretd so we can get ALL the flags.
|
||||
mov eax, AppEsp
|
||||
mov ebx, [eax + 8]
|
||||
and ebx, NOT 300h ; special handling for IF and TF
|
||||
push ebx
|
||||
push cs
|
||||
push PhonyIretd
|
||||
iretd
|
||||
PhonyIretd:
|
||||
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
popad
|
||||
|
||||
;; Switch back to application stack
|
||||
mov esp, AppEsp
|
||||
|
||||
;; Jump to original handler
|
||||
jmp OrigVector
|
||||
|
||||
NoChain:
|
||||
;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax;
|
||||
popad
|
||||
|
||||
;; Switch back to application stack
|
||||
mov esp, AppEsp
|
||||
|
||||
;; We're outa here...
|
||||
iretd
|
||||
END
|
||||
|
||||
|
||||
|
|
@ -1,551 +0,0 @@
|
|||
///**@file
|
||||
// Low leve x64 specific debug support functions.
|
||||
//
|
||||
// Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
|
||||
// Portions copyright (c) 2008 - 2009, Apple Inc. 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.
|
||||
//
|
||||
//**/
|
||||
|
||||
ASM_GLOBAL ASM_PFX(OrigVector)
|
||||
ASM_GLOBAL ASM_PFX(InterruptEntryStub)
|
||||
ASM_GLOBAL ASM_PFX(StubSize)
|
||||
ASM_GLOBAL ASM_PFX(CommonIdtEntry)
|
||||
ASM_GLOBAL ASM_PFX(FxStorSupport)
|
||||
|
||||
.data
|
||||
|
||||
ASM_PFX(StubSize): .long ASM_PFX(InterruptEntryStubEnd) - ASM_PFX(InterruptEntryStub)
|
||||
ASM_PFX(AppRsp): .long 0x11111111 # ?
|
||||
.long 0x11111111 # ?
|
||||
ASM_PFX(DebugRsp): .long 0x22222222 # ?
|
||||
.long 0x22222222 # ?
|
||||
ASM_PFX(ExtraPush): .long 0x33333333 # ?
|
||||
.long 0x33333333 # ?
|
||||
ASM_PFX(ExceptData): .long 0x44444444 # ?
|
||||
.long 0x44444444 # ?
|
||||
ASM_PFX(Rflags): .long 0x55555555 # ?
|
||||
.long 0x55555555 # ?
|
||||
ASM_PFX(OrigVector): .long 0x66666666 # ?
|
||||
.long 0x66666666 # ?
|
||||
|
||||
// The declarations below define the memory region that will be used for the debug stack.
|
||||
// The context record will be built by pushing register values onto this stack.
|
||||
// It is imparitive that alignment be carefully managed, since the FXSTOR and
|
||||
// FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.
|
||||
//
|
||||
// The stub will switch stacks from the application stack to the debuger stack
|
||||
// and pushes the exception number.
|
||||
//
|
||||
// Then we building the context record on the stack. Since the stack grows down,
|
||||
// we push the fields of the context record from the back to the front. There
|
||||
// are 336 bytes of stack used prior allocating the 512 bytes of stack to be
|
||||
// used as the memory buffer for the fxstor instruction. Therefore address of
|
||||
// the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which
|
||||
// must be 16 byte aligned.
|
||||
//
|
||||
// We carefully locate the stack to make this happen.
|
||||
//
|
||||
// For reference, the context structure looks like this:
|
||||
// struct {
|
||||
// UINT64 ExceptionData;
|
||||
// FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned
|
||||
// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
// UINT64 RFlags;
|
||||
// UINT64 Ldtr, Tr;
|
||||
// UINT64 Gdtr[2], Idtr[2];
|
||||
// UINT64 Rip;
|
||||
// UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
// } SYSTEM_CONTEXT_X64; // 64 bit system context record
|
||||
|
||||
.p2align 4
|
||||
DebugStackEnd : .ascii "DbgStkEnd >>>>>>" # 16 byte long string - must be 16 bytes to preserve alignment
|
||||
.fill 0x1ffc, 4, 0x00000000
|
||||
# 32K should be enough stack
|
||||
# This allocation is coocked to insure
|
||||
# that the the buffer for the FXSTORE instruction
|
||||
# will be 16 byte aligned also.
|
||||
#
|
||||
ASM_PFX(ExceptionNumber): .long 0x77777777 # first entry will be the vector number pushed by the stub
|
||||
.long 0x77777777 # ?
|
||||
|
||||
DebugStackBegin : .ascii "<<<< DbgStkBegin" # initial debug ESP == DebugStackBegin, set in stub
|
||||
|
||||
|
||||
.text
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// BOOLEAN
|
||||
// FxStorSupport (
|
||||
// void
|
||||
// )
|
||||
//
|
||||
// Abstract: Returns TRUE if FxStor instructions are supported
|
||||
//
|
||||
ASM_GLOBAL ASM_PFX(FxStorSupport)
|
||||
ASM_PFX(FxStorSupport):
|
||||
//
|
||||
// cpuid corrupts rbx which must be preserved per the C calling convention
|
||||
//
|
||||
pushq %rbx
|
||||
movq $1, %rax
|
||||
cpuid
|
||||
movl %edx, %eax
|
||||
andq $0x01000000, %rax
|
||||
shrq $24, %rax
|
||||
popq %rbx
|
||||
ret
|
||||
//------------------------------------------------------------------------------
|
||||
// void
|
||||
// Vect2Desc (
|
||||
// IA32_IDT_GATE_DESCRIPTOR * DestDesc, // rcx
|
||||
// void (*Vector) (void) // rdx
|
||||
// )
|
||||
//
|
||||
// Abstract: Encodes an IDT descriptor with the given physical address
|
||||
//
|
||||
ASM_GLOBAL ASM_PFX(Vect2Desc)
|
||||
ASM_PFX(Vect2Desc):
|
||||
movq %rdx, %rax
|
||||
movw %ax, (%rcx) # write bits 15..0 of offset
|
||||
movw %cs, %dx
|
||||
movw %dx, 2(%rcx) # SYS_CODE_SEL from GDT
|
||||
movw $(0x0e00 | 0x8000), 4(%rcx) # type = 386 interrupt gate, present
|
||||
shrq $16, %rax
|
||||
movw %ax, 6(%rcx) # write bits 31..16 of offset
|
||||
shrq $16, %rax
|
||||
movl %eax, 8(%rcx) # write bits 63..32 of offset
|
||||
|
||||
ret
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// InterruptEntryStub
|
||||
//
|
||||
// Abstract: This code is not a function, but is a small piece of code that is
|
||||
// copied and fixed up once for each IDT entry that is hooked.
|
||||
//
|
||||
ASM_GLOBAL ASM_PFX(InterruptEntryStub)
|
||||
ASM_PFX(InterruptEntryStub):
|
||||
|
||||
pushq $0 # push vector number - will be modified before installed
|
||||
jmp ASM_PFX(CommonIdtEntry)
|
||||
|
||||
ASM_GLOBAL ASM_PFX(InterruptEntryStubEnd)
|
||||
ASM_PFX(InterruptEntryStubEnd):
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// CommonIdtEntry
|
||||
//
|
||||
// Abstract: This code is not a function, but is the common part for all IDT
|
||||
// vectors.
|
||||
//
|
||||
ASM_GLOBAL ASM_PFX(CommonIdtEntry)
|
||||
//
|
||||
// At this point, the stub has saved the current application stack esp into AppRsp
|
||||
// and switched stacks to the debug stack, where it pushed the vector number
|
||||
//
|
||||
// The application stack looks like this:
|
||||
//
|
||||
// ...
|
||||
// (last application stack entry)
|
||||
// [16 bytes alignment, do not care it]
|
||||
// SS from interrupted task
|
||||
// RSP from interrupted task
|
||||
// rflags from interrupted task
|
||||
// CS from interrupted task
|
||||
// RIP from interrupted task
|
||||
// Error code <-------------------- Only present for some exeption types
|
||||
//
|
||||
// Vector Number <----------------- pushed in our IDT Entry
|
||||
//
|
||||
|
||||
|
||||
// The stub switched us to the debug stack and pushed the interrupt number.
|
||||
//
|
||||
// Next, construct the context record. It will be build on the debug stack by
|
||||
// pushing the registers in the correct order so as to create the context structure
|
||||
// on the debug stack. The context record must be built from the end back to the
|
||||
// beginning because the stack grows down...
|
||||
//
|
||||
// For reference, the context record looks like this:
|
||||
//
|
||||
// typedef
|
||||
// struct {
|
||||
// UINT64 ExceptionData;
|
||||
// FX_SAVE_STATE_X64 FxSaveState;
|
||||
// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
// UINT64 Cr0, Cr2, Cr3, Cr4, Cr8;
|
||||
// UINT64 RFlags;
|
||||
// UINT64 Ldtr, Tr;
|
||||
// UINT64 Gdtr[2], Idtr[2];
|
||||
// UINT64 Rip;
|
||||
// UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
// } SYSTEM_CONTEXT_X64; // 64
|
||||
ASM_PFX(CommonIdtEntry):
|
||||
// NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp
|
||||
pushq %rax
|
||||
movq (8)(%rsp), %rax # save vector number
|
||||
movq %rax, ASM_PFX(ExceptionNumber)(%rip) # save vector number
|
||||
popq %rax
|
||||
addq $8, %rsp # pop vector number
|
||||
movq %rsp, ASM_PFX(AppRsp)(%rip) # save stack top
|
||||
movq DebugStackBegin(%rip), %rsp # switch to debugger stack
|
||||
subq $8, %rsp # leave space for vector number
|
||||
// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
pushq %r15
|
||||
pushq %r14
|
||||
pushq %r13
|
||||
pushq %r12
|
||||
pushq %r11
|
||||
pushq %r10
|
||||
pushq %r9
|
||||
pushq %r8
|
||||
pushq %rax
|
||||
pushq %rcx
|
||||
pushq %rdx
|
||||
pushq %rbx
|
||||
pushq %rsp
|
||||
pushq %rbp
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
// Save interrupt state rflags register...
|
||||
pushfq
|
||||
popq %rax
|
||||
movq %rax, ASM_PFX(Rflags)(%rip)
|
||||
// We need to determine if any extra data was pushed by the exception, and if so, save it
|
||||
// To do this, we check the exception number pushed by the stub, and cache the
|
||||
// result in a variable since we'll need this again.
|
||||
cmpl $0, ASM_PFX(ExceptionNumber)(%rip)
|
||||
jz ExtraPushOne
|
||||
cmpl $10, ASM_PFX(ExceptionNumber)(%rip)
|
||||
jz ExtraPushOne
|
||||
cmpl $11, ASM_PFX(ExceptionNumber)(%rip)
|
||||
jz ExtraPushOne
|
||||
cmpl $12, ASM_PFX(ExceptionNumber)(%rip)
|
||||
jz ExtraPushOne
|
||||
cmpl $13, ASM_PFX(ExceptionNumber)(%rip)
|
||||
jz ExtraPushOne
|
||||
cmpl $14, ASM_PFX(ExceptionNumber)(%rip)
|
||||
jz ExtraPushOne
|
||||
cmpl $17, ASM_PFX(ExceptionNumber)(%rip)
|
||||
jz ExtraPushOne
|
||||
movl $0, ASM_PFX(ExtraPush)(%rip)
|
||||
movl $0, ASM_PFX(ExceptData)(%rip)
|
||||
jmp ExtraPushDone
|
||||
ExtraPushOne:
|
||||
movl $1, ASM_PFX(ExtraPush)(%rip)
|
||||
|
||||
// If there's some extra data, save it also, and modify the saved AppRsp to effectively
|
||||
// pop this value off the application's stack.
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
movq (%rax), %rbx
|
||||
movq %rbx, ASM_PFX(ExceptData)(%rip)
|
||||
addq $8, %rax
|
||||
movq %rax, ASM_PFX(AppRsp)(%rip)
|
||||
|
||||
ExtraPushDone:
|
||||
|
||||
// The "push" above pushed the debug stack rsp. Since what we're actually doing
|
||||
// is building the context record on the debug stack, we need to save the pushed
|
||||
// debug RSP, and replace it with the application's last stack entry...
|
||||
movq 24(%rsp), %rax
|
||||
movq %rax, ASM_PFX(DebugRsp)(%rip)
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
movq 24(%rax), %rax
|
||||
# application stack has ss, rsp, rflags, cs, & rip, so
|
||||
# last actual application stack entry is saved at offset
|
||||
# 24 bytes from stack top.
|
||||
movq %rax, 24(%rsp)
|
||||
|
||||
// continue building context record
|
||||
// UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
|
||||
mov %ss, %rax
|
||||
pushq %rax
|
||||
# CS from application is one entry back in application stack
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
movzwq 8(%rax), %rax
|
||||
pushq %rax
|
||||
|
||||
mov %ds, %rax
|
||||
pushq %rax
|
||||
mov %es, %rax
|
||||
pushq %rax
|
||||
mov %fs, %rax
|
||||
pushq %rax
|
||||
mov %gs, %rax
|
||||
pushq %rax
|
||||
// UINT64 Rip;
|
||||
# Rip from application is on top of application stack
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
pushq (%rax)
|
||||
// UINT64 Gdtr[2], Idtr[2];
|
||||
push $0
|
||||
push $0
|
||||
sidtq (%rsp)
|
||||
push $0
|
||||
push $0
|
||||
sgdtq (%rsp)
|
||||
|
||||
// UINT64 Ldtr, Tr;
|
||||
xorq %rax, %rax
|
||||
str %ax
|
||||
pushq %rax
|
||||
sldt %ax
|
||||
pushq %rax
|
||||
|
||||
// UINT64 RFlags;
|
||||
// Rflags from application is two entries back in application stack
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
pushq 16(%rax)
|
||||
// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
// insure FXSAVE/FXRSTOR is enabled in CR4...
|
||||
// ... while we're at it, make sure DE is also enabled...
|
||||
movq %cr8, %rax
|
||||
pushq %rax
|
||||
movq %cr4, %rax
|
||||
orq $0x208, %rax
|
||||
movq %rax, %cr4
|
||||
pushq %rax
|
||||
movq %cr3, %rax
|
||||
pushq %rax
|
||||
movq %cr2, %rax
|
||||
pushq %rax
|
||||
push $0
|
||||
movq %cr0, %rax
|
||||
pushq %rax
|
||||
// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
movq %dr7, %rax
|
||||
pushq %rax
|
||||
// clear Dr7 while executing debugger itself
|
||||
xorq %rax, %rax
|
||||
movq %rax, %dr7
|
||||
|
||||
movq %dr6, %rax
|
||||
pushq %rax
|
||||
// insure all status bits in dr6 are clear...
|
||||
xorq %rax, %rax
|
||||
movq %rax, %dr6
|
||||
|
||||
movq %dr3, %rax
|
||||
pushq %rax
|
||||
movq %dr2, %rax
|
||||
pushq %rax
|
||||
movq %dr1, %rax
|
||||
pushq %rax
|
||||
movq %dr0, %rax
|
||||
pushq %rax
|
||||
|
||||
// FX_SAVE_STATE_X64 FxSaveState;
|
||||
subq $512, %rsp
|
||||
movq %rsp, %rdi
|
||||
# IMPORTANT!! The debug stack has been carefully constructed to
|
||||
# insure that rsp and rdi are 16 byte aligned when we get here.
|
||||
# They MUST be. If they are not, a GP fault will occur.
|
||||
|
||||
# FXSTOR_RDI
|
||||
fxsave (%rdi)
|
||||
|
||||
// UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
// UINT64 ExceptionData;
|
||||
movq ASM_PFX(ExceptData)(%rip), %rax
|
||||
pushq %rax
|
||||
|
||||
// call to C code which will in turn call registered handler
|
||||
// pass in the vector number
|
||||
movq %rsp, %rdx
|
||||
movq ASM_PFX(ExceptionNumber)(%rip), %rcx
|
||||
subq $40, %rsp
|
||||
call ASM_PFX(InterruptDistrubutionHub)
|
||||
addq $40, %rsp
|
||||
// restore context...
|
||||
// UINT64 ExceptionData;
|
||||
addq $8, %rsp
|
||||
|
||||
// FX_SAVE_STATE_X64 FxSaveState;
|
||||
movq %rsp, %rsi
|
||||
|
||||
# FXRSTOR_RSI
|
||||
fxrstor (%rsi)
|
||||
|
||||
addq $512, %rsp
|
||||
|
||||
// UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
popq %rax
|
||||
movq %rax, %dr0
|
||||
popq %rax
|
||||
movq %rax, %dr1
|
||||
popq %rax
|
||||
movq %rax, %dr2
|
||||
popq %rax
|
||||
movq %rax, %dr3
|
||||
|
||||
// skip restore of dr6. We cleared dr6 during the context save.
|
||||
addq $8, %rsp
|
||||
popq %rax
|
||||
movq %rax, %dr7
|
||||
|
||||
// UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
popq %rax
|
||||
movq %rax, %cr0
|
||||
addq $8, %rsp
|
||||
popq %rax
|
||||
movq %rax, %cr2
|
||||
popq %rax
|
||||
movq %rax, %cr3
|
||||
popq %rax
|
||||
movq %rax, %cr4
|
||||
popq %rax
|
||||
movq %rax, %cr8
|
||||
// UINT64 RFlags;
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
popq 16(%rax)
|
||||
// UINT64 Ldtr, Tr;
|
||||
// UINT64 Gdtr[2], Idtr[2];
|
||||
// Best not let anyone mess with these particular registers...
|
||||
addq $48, %rsp
|
||||
// UINT64 Rip;
|
||||
popq (%rax)
|
||||
|
||||
// UINT64 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.
|
||||
//
|
||||
|
||||
popq %rax
|
||||
# mov %rax, %gs
|
||||
popq %rax
|
||||
# mov %rax, %fs
|
||||
popq %rax
|
||||
mov %rax, %es
|
||||
popq %rax
|
||||
mov %rax, %ds
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
popq 8(%rax)
|
||||
popq %rax
|
||||
mov %rax, %ss
|
||||
## The next stuff to restore is the general purpose registers that were pushed
|
||||
## using the "push" instruction.
|
||||
##
|
||||
## The value of RSP as stored in the context record is the application RSP
|
||||
## including the 5 entries on the application stack caused by the exception
|
||||
## itself. It may have been modified by the debug agent, so we need to
|
||||
## determine if we need to relocate the application stack.
|
||||
|
||||
movq 24(%rsp), %rbx # move the potentially modified AppRsp into rbx
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
movq 24(%rax), %rax
|
||||
cmpq %rax, %rbx
|
||||
je NoAppStackMove
|
||||
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
movq (%rax), %rcx # RIP
|
||||
movq %rcx, (%rbx)
|
||||
|
||||
movq 8(%rax), %rcx # CS
|
||||
movq %rcx, 8(%rbx)
|
||||
|
||||
movq 16(%rax), %rcx # RFLAGS
|
||||
movq %rcx, 16(%rbx)
|
||||
|
||||
movq 24(%rax), %rcx # RSP
|
||||
movq %rcx, 24(%rbx)
|
||||
|
||||
movq 32(%rax), %rcx # SS
|
||||
movq %rcx, 32(%rbx)
|
||||
|
||||
movq %rbx, %rax # modify the saved AppRsp to the new AppRsp
|
||||
movq %rax, ASM_PFX(AppRsp)(%rip)
|
||||
NoAppStackMove:
|
||||
movq ASM_PFX(DebugRsp)(%rip), %rax # restore the DebugRsp on the debug stack
|
||||
# so our "pop" will not cause a stack switch
|
||||
movq %rax, 24(%rsp)
|
||||
|
||||
cmpl $0x068, ASM_PFX(ExceptionNumber)(%rip)
|
||||
jne NoChain
|
||||
|
||||
Chain:
|
||||
|
||||
// Restore rflags so when we chain, the flags will be exactly as if we were never here.
|
||||
// We gin up the stack to do an iretq so we can get ALL the flags.
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
movq 40(%rax), %rbx
|
||||
pushq %rbx
|
||||
mov %ss, %rax
|
||||
pushq %rax
|
||||
movq %rsp, %rax
|
||||
addq $16, %rax
|
||||
pushq %rax
|
||||
movq ASM_PFX(AppRsp)(%rip), %rax
|
||||
movq 16(%rax), %rbx
|
||||
andq $0xfffffffffffffcff, %rbx # special handling for IF and TF
|
||||
pushq %rbx
|
||||
mov %cs, %rax
|
||||
pushq %rax
|
||||
movq PhonyIretq(%rip), %rax
|
||||
pushq %rax
|
||||
iretq
|
||||
PhonyIretq:
|
||||
|
||||
// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %rbp
|
||||
popq %rsp
|
||||
popq %rbx
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax
|
||||
popq %r8
|
||||
popq %r9
|
||||
popq %r10
|
||||
popq %r11
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
|
||||
// Switch back to application stack
|
||||
movq ASM_PFX(AppRsp)(%rip), %rsp
|
||||
// Jump to original handler
|
||||
jmp ASM_PFX(OrigVector)
|
||||
NoChain:
|
||||
// UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
// UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
popq %rdi
|
||||
popq %rsi
|
||||
popq %rbp
|
||||
popq %rsp
|
||||
popq %rbx
|
||||
popq %rdx
|
||||
popq %rcx
|
||||
popq %rax
|
||||
popq %r8
|
||||
popq %r9
|
||||
popq %r10
|
||||
popq %r11
|
||||
popq %r12
|
||||
popq %r13
|
||||
popq %r14
|
||||
popq %r15
|
||||
|
||||
// Switch back to application stack
|
||||
movq ASM_PFX(AppRsp)(%rip), %rsp
|
||||
|
||||
// We're outa here...
|
||||
iret
|
|
@ -1,596 +0,0 @@
|
|||
;/** @file
|
||||
; Low level x64 routines used by the debug support driver.
|
||||
;
|
||||
; Copyright (c) 2007 - 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.
|
||||
;
|
||||
;**/
|
||||
|
||||
EXCPT64_DIVIDE_ERROR EQU 0
|
||||
EXCPT64_DEBUG EQU 1
|
||||
EXCPT64_NMI EQU 2
|
||||
EXCPT64_BREAKPOINT EQU 3
|
||||
EXCPT64_OVERFLOW EQU 4
|
||||
EXCPT64_BOUND EQU 5
|
||||
EXCPT64_INVALID_OPCODE EQU 6
|
||||
EXCPT64_DOUBLE_FAULT EQU 8
|
||||
EXCPT64_INVALID_TSS EQU 10
|
||||
EXCPT64_SEG_NOT_PRESENT EQU 11
|
||||
EXCPT64_STACK_FAULT EQU 12
|
||||
EXCPT64_GP_FAULT EQU 13
|
||||
EXCPT64_PAGE_FAULT EQU 14
|
||||
EXCPT64_FP_ERROR EQU 16
|
||||
EXCPT64_ALIGNMENT_CHECK EQU 17
|
||||
EXCPT64_MACHINE_CHECK EQU 18
|
||||
EXCPT64_SIMD EQU 19
|
||||
|
||||
FXSTOR_FLAG EQU 01000000h ; bit cpuid 24 of feature flags
|
||||
|
||||
;; The FXSTOR and FXRSTOR commands are used for saving and restoring the x87,
|
||||
;; MMX, SSE, SSE2, etc registers. The initialization of the debugsupport driver
|
||||
;; MUST check the CPUID feature flags to see that these instructions are available
|
||||
;; and fail to init if they are not.
|
||||
|
||||
;; fxstor [rdi]
|
||||
FXSTOR_RDI MACRO
|
||||
db 0fh, 0aeh, 00000111y ; mod = 00, reg/op = 000, r/m = 111 = [rdi]
|
||||
ENDM
|
||||
|
||||
;; fxrstor [rsi]
|
||||
FXRSTOR_RSI MACRO
|
||||
db 0fh, 0aeh, 00001110y ; mod = 00, reg/op = 001, r/m = 110 = [rsi]
|
||||
ENDM
|
||||
|
||||
data SEGMENT
|
||||
|
||||
public OrigVector, InterruptEntryStub, StubSize, CommonIdtEntry, FxStorSupport
|
||||
|
||||
StubSize dd InterruptEntryStubEnd - InterruptEntryStub
|
||||
AppRsp dq 1111111111111111h ; ?
|
||||
DebugRsp dq 2222222222222222h ; ?
|
||||
ExtraPush dq 3333333333333333h ; ?
|
||||
ExceptData dq 4444444444444444h ; ?
|
||||
Rflags dq 5555555555555555h ; ?
|
||||
OrigVector dq 6666666666666666h ; ?
|
||||
|
||||
;; The declarations below define the memory region that will be used for the debug stack.
|
||||
;; The context record will be built by pushing register values onto this stack.
|
||||
;; It is imparitive that alignment be carefully managed, since the FXSTOR and
|
||||
;; FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned.
|
||||
;;
|
||||
;; The stub will switch stacks from the application stack to the debuger stack
|
||||
;; and pushes the exception number.
|
||||
;;
|
||||
;; Then we building the context record on the stack. Since the stack grows down,
|
||||
;; we push the fields of the context record from the back to the front. There
|
||||
;; are 336 bytes of stack used prior allocating the 512 bytes of stack to be
|
||||
;; used as the memory buffer for the fxstor instruction. Therefore address of
|
||||
;; the buffer used for the FXSTOR instruction is &Eax - 336 - 512, which
|
||||
;; must be 16 byte aligned.
|
||||
;;
|
||||
;; We carefully locate the stack to make this happen.
|
||||
;;
|
||||
;; For reference, the context structure looks like this:
|
||||
;; struct {
|
||||
;; UINT64 ExceptionData;
|
||||
;; FX_SAVE_STATE_X64 FxSaveState; // 512 bytes, must be 16 byte aligned
|
||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
;; UINT64 RFlags;
|
||||
;; UINT64 Ldtr, Tr;
|
||||
;; UINT64 Gdtr[2], Idtr[2];
|
||||
;; UINT64 Rip;
|
||||
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
;; } SYSTEM_CONTEXT_X64; // 64 bit system context record
|
||||
|
||||
align 16
|
||||
DebugStackEnd db "DbgStkEnd >>>>>>" ;; 16 byte long string - must be 16 bytes to preserve alignment
|
||||
dd 1ffch dup (000000000h) ;; 32K should be enough stack
|
||||
;; This allocation is coocked to insure
|
||||
;; that the the buffer for the FXSTORE instruction
|
||||
;; will be 16 byte aligned also.
|
||||
;;
|
||||
ExceptionNumber dq ? ;; first entry will be the vector number pushed by the stub
|
||||
|
||||
DebugStackBegin db "<<<< DbgStkBegin" ;; initial debug ESP == DebugStackBegin, set in stub
|
||||
|
||||
data ENDS
|
||||
|
||||
text SEGMENT
|
||||
|
||||
externdef InterruptDistrubutionHub:near
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; BOOLEAN
|
||||
; FxStorSupport (
|
||||
; void
|
||||
; )
|
||||
;
|
||||
; Abstract: Returns TRUE if FxStor instructions are supported
|
||||
;
|
||||
FxStorSupport PROC PUBLIC
|
||||
|
||||
;
|
||||
; cpuid corrupts rbx which must be preserved per the C calling convention
|
||||
;
|
||||
push rbx
|
||||
mov rax, 1
|
||||
cpuid
|
||||
mov eax, edx
|
||||
and rax, FXSTOR_FLAG
|
||||
shr rax, 24
|
||||
pop rbx
|
||||
ret
|
||||
FxStorSupport ENDP
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; void
|
||||
; Vect2Desc (
|
||||
; IA32_IDT_GATE_DESCRIPTOR * DestDesc, // rcx
|
||||
; void (*Vector) (void) // rdx
|
||||
; )
|
||||
;
|
||||
; Abstract: Encodes an IDT descriptor with the given physical address
|
||||
;
|
||||
Vect2Desc PROC PUBLIC
|
||||
|
||||
mov rax, rdx
|
||||
mov word ptr [rcx], ax ; write bits 15..0 of offset
|
||||
mov dx, cs
|
||||
mov word ptr [rcx+2], dx ; SYS_CODE_SEL from GDT
|
||||
mov word ptr [rcx+4], 0e00h OR 8000h ; type = 386 interrupt gate, present
|
||||
shr rax, 16
|
||||
mov word ptr [rcx+6], ax ; write bits 31..16 of offset
|
||||
shr rax, 16
|
||||
mov dword ptr [rcx+8], eax ; write bits 63..32 of offset
|
||||
|
||||
ret
|
||||
|
||||
Vect2Desc ENDP
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; InterruptEntryStub
|
||||
;
|
||||
; Abstract: This code is not a function, but is a small piece of code that is
|
||||
; copied and fixed up once for each IDT entry that is hooked.
|
||||
;
|
||||
InterruptEntryStub::
|
||||
push 0 ; push vector number - will be modified before installed
|
||||
db 0e9h ; jump rel32
|
||||
dd 0 ; fixed up to relative address of CommonIdtEntry
|
||||
InterruptEntryStubEnd:
|
||||
|
||||
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; CommonIdtEntry
|
||||
;
|
||||
; Abstract: This code is not a function, but is the common part for all IDT
|
||||
; vectors.
|
||||
;
|
||||
CommonIdtEntry::
|
||||
;;
|
||||
;; At this point, the stub has saved the current application stack esp into AppRsp
|
||||
;; and switched stacks to the debug stack, where it pushed the vector number
|
||||
;;
|
||||
;; The application stack looks like this:
|
||||
;;
|
||||
;; ...
|
||||
;; (last application stack entry)
|
||||
;; [16 bytes alignment, do not care it]
|
||||
;; SS from interrupted task
|
||||
;; RSP from interrupted task
|
||||
;; rflags from interrupted task
|
||||
;; CS from interrupted task
|
||||
;; RIP from interrupted task
|
||||
;; Error code <-------------------- Only present for some exeption types
|
||||
;;
|
||||
;; Vector Number <----------------- pushed in our IDT Entry
|
||||
;;
|
||||
|
||||
|
||||
;; The stub switched us to the debug stack and pushed the interrupt number.
|
||||
;;
|
||||
;; Next, construct the context record. It will be build on the debug stack by
|
||||
;; pushing the registers in the correct order so as to create the context structure
|
||||
;; on the debug stack. The context record must be built from the end back to the
|
||||
;; beginning because the stack grows down...
|
||||
;
|
||||
;; For reference, the context record looks like this:
|
||||
;;
|
||||
;; typedef
|
||||
;; struct {
|
||||
;; UINT64 ExceptionData;
|
||||
;; FX_SAVE_STATE_X64 FxSaveState;
|
||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
;; UINT64 Cr0, Cr2, Cr3, Cr4, Cr8;
|
||||
;; UINT64 RFlags;
|
||||
;; UINT64 Ldtr, Tr;
|
||||
;; UINT64 Gdtr[2], Idtr[2];
|
||||
;; UINT64 Rip;
|
||||
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss;
|
||||
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
;; } SYSTEM_CONTEXT_X64; // 64 bit system context record
|
||||
|
||||
;; NOTE: we save rsp here to prevent compiler put rip reference cause error AppRsp
|
||||
push rax
|
||||
mov rax, qword ptr [rsp][8] ; save vector number
|
||||
mov ExceptionNumber, rax ; save vector number
|
||||
pop rax
|
||||
add rsp, 8 ; pop vector number
|
||||
mov AppRsp, rsp ; save stack top
|
||||
mov rsp, offset DebugStackBegin ; switch to debugger stack
|
||||
sub rsp, 8 ; leave space for vector number
|
||||
|
||||
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
push r15
|
||||
push r14
|
||||
push r13
|
||||
push r12
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
push rax
|
||||
push rcx
|
||||
push rdx
|
||||
push rbx
|
||||
push rsp
|
||||
push rbp
|
||||
push rsi
|
||||
push rdi
|
||||
|
||||
;; Save interrupt state rflags register...
|
||||
pushfq
|
||||
pop rax
|
||||
mov qword ptr Rflags, rax
|
||||
|
||||
;; We need to determine if any extra data was pushed by the exception, and if so, save it
|
||||
;; To do this, we check the exception number pushed by the stub, and cache the
|
||||
;; result in a variable since we'll need this again.
|
||||
cmp ExceptionNumber, EXCPT64_DOUBLE_FAULT
|
||||
jz ExtraPushOne
|
||||
cmp ExceptionNumber, EXCPT64_INVALID_TSS
|
||||
jz ExtraPushOne
|
||||
cmp ExceptionNumber, EXCPT64_SEG_NOT_PRESENT
|
||||
jz ExtraPushOne
|
||||
cmp ExceptionNumber, EXCPT64_STACK_FAULT
|
||||
jz ExtraPushOne
|
||||
cmp ExceptionNumber, EXCPT64_GP_FAULT
|
||||
jz ExtraPushOne
|
||||
cmp ExceptionNumber, EXCPT64_PAGE_FAULT
|
||||
jz ExtraPushOne
|
||||
cmp ExceptionNumber, EXCPT64_ALIGNMENT_CHECK
|
||||
jz ExtraPushOne
|
||||
mov ExtraPush, 0
|
||||
mov ExceptData, 0
|
||||
jmp ExtraPushDone
|
||||
ExtraPushOne:
|
||||
mov ExtraPush, 1
|
||||
|
||||
;; If there's some extra data, save it also, and modify the saved AppRsp to effectively
|
||||
;; pop this value off the application's stack.
|
||||
mov rax, AppRsp
|
||||
mov rbx, [rax]
|
||||
mov ExceptData, rbx
|
||||
add rax, 8
|
||||
mov AppRsp, rax
|
||||
|
||||
ExtraPushDone:
|
||||
|
||||
;; The "push" above pushed the debug stack rsp. Since what we're actually doing
|
||||
;; is building the context record on the debug stack, we need to save the pushed
|
||||
;; debug RSP, and replace it with the application's last stack entry...
|
||||
mov rax, [rsp + 24]
|
||||
mov DebugRsp, rax
|
||||
mov rax, AppRsp
|
||||
mov rax, QWORD PTR [rax + 24]
|
||||
; application stack has ss, rsp, rflags, cs, & rip, so
|
||||
; last actual application stack entry is saved at offset
|
||||
; 24 bytes from stack top.
|
||||
mov [rsp + 24], rax
|
||||
|
||||
;; continue building context record
|
||||
;; UINT64 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero
|
||||
mov rax, ss
|
||||
push rax
|
||||
|
||||
; CS from application is one entry back in application stack
|
||||
mov rax, AppRsp
|
||||
movzx rax, word ptr [rax + 8]
|
||||
push rax
|
||||
|
||||
mov rax, ds
|
||||
push rax
|
||||
mov rax, es
|
||||
push rax
|
||||
mov rax, fs
|
||||
push rax
|
||||
mov rax, gs
|
||||
push rax
|
||||
|
||||
;; UINT64 Rip;
|
||||
; Rip from application is on top of application stack
|
||||
mov rax, AppRsp
|
||||
push qword ptr [rax]
|
||||
|
||||
;; UINT64 Gdtr[2], Idtr[2];
|
||||
push 0
|
||||
push 0
|
||||
sidt fword ptr [rsp]
|
||||
push 0
|
||||
push 0
|
||||
sgdt fword ptr [rsp]
|
||||
|
||||
;; UINT64 Ldtr, Tr;
|
||||
xor rax, rax
|
||||
str ax
|
||||
push rax
|
||||
sldt ax
|
||||
push rax
|
||||
|
||||
;; UINT64 RFlags;
|
||||
;; Rflags from application is two entries back in application stack
|
||||
mov rax, AppRsp
|
||||
push qword ptr [rax + 16]
|
||||
|
||||
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
;; insure FXSAVE/FXRSTOR is enabled in CR4...
|
||||
;; ... while we're at it, make sure DE is also enabled...
|
||||
mov rax, cr8
|
||||
push rax
|
||||
mov rax, cr4
|
||||
or rax, 208h
|
||||
mov cr4, rax
|
||||
push rax
|
||||
mov rax, cr3
|
||||
push rax
|
||||
mov rax, cr2
|
||||
push rax
|
||||
push 0
|
||||
mov rax, cr0
|
||||
push rax
|
||||
|
||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
mov rax, dr7
|
||||
push rax
|
||||
;; clear Dr7 while executing debugger itself
|
||||
xor rax, rax
|
||||
mov dr7, rax
|
||||
|
||||
mov rax, dr6
|
||||
push rax
|
||||
;; insure all status bits in dr6 are clear...
|
||||
xor rax, rax
|
||||
mov dr6, rax
|
||||
|
||||
mov rax, dr3
|
||||
push rax
|
||||
mov rax, dr2
|
||||
push rax
|
||||
mov rax, dr1
|
||||
push rax
|
||||
mov rax, dr0
|
||||
push rax
|
||||
|
||||
;; FX_SAVE_STATE_X64 FxSaveState;
|
||||
sub rsp, 512
|
||||
mov rdi, rsp
|
||||
; IMPORTANT!! The debug stack has been carefully constructed to
|
||||
; insure that rsp and rdi are 16 byte aligned when we get here.
|
||||
; They MUST be. If they are not, a GP fault will occur.
|
||||
FXSTOR_RDI
|
||||
|
||||
;; UEFI calling convention for x64 requires that Direction flag in EFLAGs is clear
|
||||
cld
|
||||
|
||||
;; UINT64 ExceptionData;
|
||||
mov rax, ExceptData
|
||||
push rax
|
||||
|
||||
; call to C code which will in turn call registered handler
|
||||
; pass in the vector number
|
||||
mov rdx, rsp
|
||||
mov rcx, ExceptionNumber
|
||||
sub rsp, 40
|
||||
call InterruptDistrubutionHub
|
||||
add rsp, 40
|
||||
|
||||
; restore context...
|
||||
;; UINT64 ExceptionData;
|
||||
add rsp, 8
|
||||
|
||||
;; FX_SAVE_STATE_X64 FxSaveState;
|
||||
mov rsi, rsp
|
||||
FXRSTOR_RSI
|
||||
add rsp, 512
|
||||
|
||||
;; UINT64 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7;
|
||||
pop rax
|
||||
mov dr0, rax
|
||||
pop rax
|
||||
mov dr1, rax
|
||||
pop rax
|
||||
mov dr2, rax
|
||||
pop rax
|
||||
mov dr3, rax
|
||||
;; skip restore of dr6. We cleared dr6 during the context save.
|
||||
add rsp, 8
|
||||
pop rax
|
||||
mov dr7, rax
|
||||
|
||||
;; UINT64 Cr0, Cr1, Cr2, Cr3, Cr4, Cr8;
|
||||
pop rax
|
||||
mov cr0, rax
|
||||
add rsp, 8
|
||||
pop rax
|
||||
mov cr2, rax
|
||||
pop rax
|
||||
mov cr3, rax
|
||||
pop rax
|
||||
mov cr4, rax
|
||||
pop rax
|
||||
mov cr8, rax
|
||||
|
||||
;; UINT64 RFlags;
|
||||
mov rax, AppRsp
|
||||
pop qword ptr [rax + 16]
|
||||
|
||||
;; UINT64 Ldtr, Tr;
|
||||
;; UINT64 Gdtr[2], Idtr[2];
|
||||
;; Best not let anyone mess with these particular registers...
|
||||
add rsp, 48
|
||||
|
||||
;; UINT64 Rip;
|
||||
pop qword ptr [rax]
|
||||
|
||||
;; UINT64 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 rax
|
||||
; mov gs, rax
|
||||
pop rax
|
||||
; mov fs, rax
|
||||
pop rax
|
||||
mov es, rax
|
||||
pop rax
|
||||
mov ds, rax
|
||||
mov rax, AppRsp
|
||||
pop qword ptr [rax + 8]
|
||||
pop rax
|
||||
mov ss, rax
|
||||
|
||||
;; The next stuff to restore is the general purpose registers that were pushed
|
||||
;; using the "push" instruction.
|
||||
;;
|
||||
;; The value of RSP as stored in the context record is the application RSP
|
||||
;; including the 5 entries on the application stack caused by the exception
|
||||
;; itself. It may have been modified by the debug agent, so we need to
|
||||
;; determine if we need to relocate the application stack.
|
||||
|
||||
mov rbx, [rsp + 24] ; move the potentially modified AppRsp into rbx
|
||||
mov rax, AppRsp
|
||||
mov rax, QWORD PTR [rax + 24]
|
||||
cmp rbx, rax
|
||||
je NoAppStackMove
|
||||
|
||||
mov rax, AppRsp
|
||||
mov rcx, [rax] ; RIP
|
||||
mov [rbx], rcx
|
||||
|
||||
mov rcx, [rax + 8] ; CS
|
||||
mov [rbx + 8], rcx
|
||||
|
||||
mov rcx, [rax + 16] ; RFLAGS
|
||||
mov [rbx + 16], rcx
|
||||
|
||||
mov rcx, [rax + 24] ; RSP
|
||||
mov [rbx + 24], rcx
|
||||
|
||||
mov rcx, [rax + 32] ; SS
|
||||
mov [rbx + 32], rcx
|
||||
|
||||
mov rax, rbx ; modify the saved AppRsp to the new AppRsp
|
||||
mov AppRsp, rax
|
||||
NoAppStackMove:
|
||||
mov rax, DebugRsp ; restore the DebugRsp on the debug stack
|
||||
; so our "pop" will not cause a stack switch
|
||||
mov [rsp + 24], rax
|
||||
|
||||
cmp ExceptionNumber, 068h
|
||||
jne NoChain
|
||||
|
||||
Chain:
|
||||
|
||||
;; Restore rflags so when we chain, the flags will be exactly as if we were never here.
|
||||
;; We gin up the stack to do an iretq so we can get ALL the flags.
|
||||
mov rax, AppRsp
|
||||
mov rbx, [rax + 40]
|
||||
push rbx
|
||||
mov rax, ss
|
||||
push rax
|
||||
mov rax, rsp
|
||||
add rax, 16
|
||||
push rax
|
||||
mov rax, AppRsp
|
||||
mov rbx, [rax + 16]
|
||||
and rbx, NOT 300h ; special handling for IF and TF
|
||||
push rbx
|
||||
mov rax, cs
|
||||
push rax
|
||||
mov rax, offset PhonyIretq
|
||||
push rax
|
||||
iretq
|
||||
PhonyIretq:
|
||||
|
||||
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbp
|
||||
pop rsp
|
||||
pop rbx
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
pop r15
|
||||
|
||||
;; Switch back to application stack
|
||||
mov rsp, AppRsp
|
||||
|
||||
;; Jump to original handler
|
||||
jmp OrigVector
|
||||
|
||||
NoChain:
|
||||
;; UINT64 Rdi, Rsi, Rbp, Rsp, Rbx, Rdx, Rcx, Rax;
|
||||
;; UINT64 R8, R9, R10, R11, R12, R13, R14, R15;
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbp
|
||||
pop rsp
|
||||
pop rbx
|
||||
pop rdx
|
||||
pop rcx
|
||||
pop rax
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
pop r12
|
||||
pop r13
|
||||
pop r14
|
||||
pop r15
|
||||
|
||||
;; Switch back to application stack
|
||||
mov rsp, AppRsp
|
||||
|
||||
;; We're outa here...
|
||||
iretq
|
||||
text ENDS
|
||||
|
||||
END
|
||||
|
||||
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
## @file
|
||||
# EFI Byte Code (EBC) Debugger.
|
||||
#
|
||||
# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2007 - 2018, 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
|
||||
|
@ -68,14 +68,10 @@
|
|||
[Sources.Ia32]
|
||||
Ia32/EbcSupport.c
|
||||
Ia32/EbcLowLevel.nasm
|
||||
Ia32/EbcLowLevel.S
|
||||
Ia32/EbcLowLevel.asm
|
||||
|
||||
[Sources.X64]
|
||||
X64/EbcSupport.c
|
||||
X64/EbcLowLevel.nasm
|
||||
X64/EbcLowLevel.S
|
||||
X64/EbcLowLevel.asm
|
||||
|
||||
[Sources.IPF]
|
||||
Ipf/EbcSupport.h
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# device drivers.
|
||||
#
|
||||
# Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
# Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2006 - 2018, 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
|
||||
|
@ -43,14 +43,10 @@
|
|||
[Sources.Ia32]
|
||||
Ia32/EbcSupport.c
|
||||
Ia32/EbcLowLevel.nasm
|
||||
Ia32/EbcLowLevel.S
|
||||
Ia32/EbcLowLevel.asm
|
||||
|
||||
[Sources.X64]
|
||||
X64/EbcSupport.c
|
||||
X64/EbcLowLevel.nasm
|
||||
X64/EbcLowLevel.S
|
||||
X64/EbcLowLevel.asm
|
||||
|
||||
[Sources.IPF]
|
||||
Ipf/EbcSupport.h
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
#/** @file
|
||||
#
|
||||
# Low level IA32 specific EBC support routines.
|
||||
#
|
||||
# Copyright (c) 2007 - 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.
|
||||
#
|
||||
#**/
|
||||
|
||||
ASM_GLOBAL ASM_PFX(CopyMem)
|
||||
ASM_GLOBAL ASM_PFX(EbcInterpret)
|
||||
ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint)
|
||||
|
||||
ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative)
|
||||
ASM_PFX(EbcLLCALLEXNative):
|
||||
push %ebp
|
||||
push %ebx
|
||||
mov %esp,%ebp
|
||||
mov 0xc(%esp),%ecx
|
||||
mov 0x14(%esp),%eax
|
||||
mov 0x10(%esp),%edx
|
||||
sub %edx,%eax
|
||||
sub %eax,%esp
|
||||
mov %esp,%ebx
|
||||
push %ecx
|
||||
push %eax
|
||||
push %edx
|
||||
push %ebx
|
||||
call ASM_PFX(CopyMem)
|
||||
pop %eax
|
||||
pop %eax
|
||||
pop %eax
|
||||
pop %ecx
|
||||
call *%ecx
|
||||
mov %ebp,%esp
|
||||
mov %ebp,%esp
|
||||
pop %ebx
|
||||
pop %ebp
|
||||
ret
|
||||
|
||||
ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret)
|
||||
ASM_PFX(EbcLLEbcInterpret):
|
||||
# Construct new stack
|
||||
push %ebp
|
||||
mov %esp, %ebp
|
||||
push %esi
|
||||
push %edi
|
||||
sub $0x40, %esp
|
||||
push %eax
|
||||
mov %ebp, %esi
|
||||
add $0x8, %esi
|
||||
mov %esp, %edi
|
||||
add $0x4, %edi
|
||||
mov $0x10, %ecx
|
||||
rep movsd
|
||||
|
||||
# call C-code
|
||||
call ASM_PFX(EbcInterpret)
|
||||
add $0x44, %esp
|
||||
pop %edi
|
||||
pop %esi
|
||||
pop %ebp
|
||||
ret
|
||||
|
||||
ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint)
|
||||
ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
|
||||
# Construct new stack
|
||||
mov %eax, -0xC(%esp)
|
||||
mov 0x4(%esp), %eax
|
||||
mov %eax, -0x8(%esp)
|
||||
mov 0x8(%esp), %eax
|
||||
mov %eax, -0x4(%esp)
|
||||
# call C-code
|
||||
sub $0xC, %esp
|
||||
call ASM_PFX(ExecuteEbcImageEntryPoint)
|
||||
add $0xC, %esp
|
||||
ret
|
|
@ -1,207 +0,0 @@
|
|||
;/** @file
|
||||
;
|
||||
; This code provides low level routines that support the Virtual Machine
|
||||
; for option ROMs.
|
||||
;
|
||||
; 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.
|
||||
;
|
||||
;**/
|
||||
|
||||
page ,132
|
||||
title VM ASSEMBLY LANGUAGE ROUTINES
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; Equate files needed.
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
.XLIST
|
||||
|
||||
.LIST
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; Assembler options
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
.686p
|
||||
.model flat, C
|
||||
.code
|
||||
CopyMem PROTO Destination:PTR DWORD, Source:PTR DWORD, Count:DWORD
|
||||
EbcInterpret PROTO
|
||||
ExecuteEbcImageEntryPoint PROTO
|
||||
|
||||
;****************************************************************************
|
||||
; EbcLLCALLEXNative
|
||||
;
|
||||
; This function is called to execute an EBC CALLEX instruction
|
||||
; to native code.
|
||||
; This instruction requires that we thunk out to external native
|
||||
; code. For IA32, we simply switch stacks and jump to the
|
||||
; specified function. On return, we restore the stack pointer
|
||||
; to its original location.
|
||||
;
|
||||
; Destroys no working registers.
|
||||
;****************************************************************************
|
||||
; INT64 EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
|
||||
EbcLLCALLEXNative PROC PUBLIC
|
||||
push ebp
|
||||
push ebx
|
||||
mov ebp, esp ; standard function prolog
|
||||
|
||||
; Get function address in a register
|
||||
; mov ecx, FuncAddr => mov ecx, dword ptr [FuncAddr]
|
||||
mov ecx, dword ptr [esp + 0Ch]
|
||||
|
||||
; Set stack pointer to new value
|
||||
; mov eax, NewStackPointer => mov eax, dword ptr [NewSp]
|
||||
mov eax, dword ptr [esp + 14h]
|
||||
mov edx, dword ptr [esp + 10h]
|
||||
sub eax, edx
|
||||
sub esp, eax
|
||||
mov ebx, esp
|
||||
push ecx
|
||||
push eax
|
||||
push edx
|
||||
push ebx
|
||||
call CopyMem
|
||||
pop eax
|
||||
pop eax
|
||||
pop eax
|
||||
pop ecx
|
||||
|
||||
; Now call the external routine
|
||||
call ecx
|
||||
|
||||
; ebp is preserved by the callee. In this function it
|
||||
; equals the original esp, so set them equal
|
||||
mov esp, ebp
|
||||
|
||||
; Standard function epilog
|
||||
mov esp, ebp
|
||||
pop ebx
|
||||
pop ebp
|
||||
ret
|
||||
EbcLLCALLEXNative ENDP
|
||||
|
||||
;****************************************************************************
|
||||
; EbcLLEbcInterpret
|
||||
;
|
||||
; Begin executing an EBC image.
|
||||
;****************************************************************************
|
||||
; UINT64 EbcLLEbcInterpret(VOID)
|
||||
EbcLLEbcInterpret PROC PUBLIC
|
||||
;
|
||||
;; mov eax, 0xca112ebc
|
||||
;; mov eax, EbcEntryPoint
|
||||
;; mov ecx, EbcLLEbcInterpret
|
||||
;; jmp ecx
|
||||
;
|
||||
; Caller uses above instruction to jump here
|
||||
; The stack is below:
|
||||
; +-----------+
|
||||
; | RetAddr |
|
||||
; +-----------+
|
||||
; |EntryPoint | (EAX)
|
||||
; +-----------+
|
||||
; | Arg1 | <- EDI
|
||||
; +-----------+
|
||||
; | Arg2 |
|
||||
; +-----------+
|
||||
; | ... |
|
||||
; +-----------+
|
||||
; | Arg16 |
|
||||
; +-----------+
|
||||
; | EDI |
|
||||
; +-----------+
|
||||
; | ESI |
|
||||
; +-----------+
|
||||
; | EBP | <- EBP
|
||||
; +-----------+
|
||||
; | RetAddr | <- ESP is here
|
||||
; +-----------+
|
||||
; | Arg1 | <- ESI
|
||||
; +-----------+
|
||||
; | Arg2 |
|
||||
; +-----------+
|
||||
; | ... |
|
||||
; +-----------+
|
||||
; | Arg16 |
|
||||
; +-----------+
|
||||
;
|
||||
|
||||
; Construct new stack
|
||||
push ebp
|
||||
mov ebp, esp
|
||||
push esi
|
||||
push edi
|
||||
sub esp, 40h
|
||||
push eax
|
||||
mov esi, ebp
|
||||
add esi, 8
|
||||
mov edi, esp
|
||||
add edi, 4
|
||||
mov ecx, 16
|
||||
rep movsd
|
||||
|
||||
; call C-code
|
||||
call EbcInterpret
|
||||
add esp, 44h
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
ret
|
||||
EbcLLEbcInterpret ENDP
|
||||
|
||||
;****************************************************************************
|
||||
; EbcLLExecuteEbcImageEntryPoint
|
||||
;
|
||||
; Begin executing an EBC image.
|
||||
;****************************************************************************
|
||||
; UINT64 EbcLLExecuteEbcImageEntryPoint(VOID)
|
||||
EbcLLExecuteEbcImageEntryPoint PROC PUBLIC
|
||||
;
|
||||
;; mov eax, 0xca112ebc
|
||||
;; mov eax, EbcEntryPoint
|
||||
;; mov ecx, EbcLLExecuteEbcImageEntryPoint
|
||||
;; jmp ecx
|
||||
;
|
||||
; Caller uses above instruction to jump here
|
||||
; The stack is below:
|
||||
; +-----------+
|
||||
; | RetAddr |
|
||||
; +-----------+
|
||||
; |EntryPoint | (EAX)
|
||||
; +-----------+
|
||||
; |ImageHandle|
|
||||
; +-----------+
|
||||
; |SystemTable|
|
||||
; +-----------+
|
||||
; | RetAddr | <- ESP is here
|
||||
; +-----------+
|
||||
; |ImageHandle|
|
||||
; +-----------+
|
||||
; |SystemTable|
|
||||
; +-----------+
|
||||
;
|
||||
|
||||
; Construct new stack
|
||||
mov [esp - 0Ch], eax
|
||||
mov eax, [esp + 04h]
|
||||
mov [esp - 08h], eax
|
||||
mov eax, [esp + 08h]
|
||||
mov [esp - 04h], eax
|
||||
|
||||
; call C-code
|
||||
sub esp, 0Ch
|
||||
call ExecuteEbcImageEntryPoint
|
||||
add esp, 0Ch
|
||||
ret
|
||||
EbcLLExecuteEbcImageEntryPoint ENDP
|
||||
|
||||
END
|
|
@ -1,147 +0,0 @@
|
|||
#/** @file
|
||||
#
|
||||
# This code provides low level routines that support the Virtual Machine
|
||||
# for option ROMs.
|
||||
#
|
||||
# Copyright (c) 2007 - 2014, 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.
|
||||
#
|
||||
#**/
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Equate files needed.
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
ASM_GLOBAL ASM_PFX(CopyMem);
|
||||
ASM_GLOBAL ASM_PFX(EbcInterpret);
|
||||
ASM_GLOBAL ASM_PFX(ExecuteEbcImageEntryPoint);
|
||||
|
||||
#****************************************************************************
|
||||
# EbcLLCALLEX
|
||||
#
|
||||
# This function is called to execute an EBC CALLEX instruction.
|
||||
# This instruction requires that we thunk out to external native
|
||||
# code. For x64, we switch stacks, copy the arguments to the stack
|
||||
# and jump to the specified function.
|
||||
# On return, we restore the stack pointer to its original location.
|
||||
#
|
||||
# Destroys no working registers.
|
||||
#****************************************************************************
|
||||
# VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
|
||||
ASM_GLOBAL ASM_PFX(EbcLLCALLEXNative);
|
||||
ASM_PFX(EbcLLCALLEXNative):
|
||||
push %rbp
|
||||
push %rbx
|
||||
mov %rsp, %rbp
|
||||
# Function prolog
|
||||
|
||||
# Copy FuncAddr to a preserved register.
|
||||
mov %rcx, %rbx
|
||||
|
||||
# Set stack pointer to new value
|
||||
sub %rdx, %r8
|
||||
|
||||
#
|
||||
# Fix X64 native function call prolog. Prepare space for at least 4 arguments,
|
||||
# even if the native function's arguments are less than 4.
|
||||
#
|
||||
# From MSDN x64 Software Conventions, Overview of x64 Calling Conventions:
|
||||
# "The caller is responsible for allocating space for parameters to the
|
||||
# callee, and must always allocate sufficient space for the 4 register
|
||||
# parameters, even if the callee doesn't have that many parameters.
|
||||
# This aids in the simplicity of supporting C unprototyped functions,
|
||||
# and vararg C/C++ functions."
|
||||
#
|
||||
cmp $0x20, %r8
|
||||
jae skip_expansion
|
||||
mov $0x20, %r8
|
||||
skip_expansion:
|
||||
|
||||
sub %r8, %rsp
|
||||
|
||||
#
|
||||
# Fix X64 native function call 16-byte alignment.
|
||||
#
|
||||
# From MSDN x64 Software Conventions, Stack Usage:
|
||||
# "The stack will always be maintained 16-byte aligned, except within
|
||||
# the prolog (for example, after the return address is pushed)."
|
||||
#
|
||||
and $0xFFFFFFFFFFFFFFF0, %rsp
|
||||
|
||||
mov %rsp, %rcx
|
||||
sub $0x20, %rsp
|
||||
call ASM_PFX(CopyMem)
|
||||
add $0x20, %rsp
|
||||
|
||||
# Considering the worst case, load 4 potiential arguments
|
||||
# into registers.
|
||||
mov (%rsp), %rcx
|
||||
mov 0x8(%rsp), %rdx
|
||||
mov 0x10(%rsp), %r8
|
||||
mov 0x18(%rsp), %r9
|
||||
|
||||
# Now call the external routine
|
||||
call *%rbx
|
||||
|
||||
# Function epilog
|
||||
mov %rbp, %rsp
|
||||
pop %rbx
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
ASM_GLOBAL ASM_PFX(EbcLLEbcInterpret);
|
||||
ASM_PFX(EbcLLEbcInterpret):
|
||||
# save old parameter to stack
|
||||
mov %rcx, 0x8(%rsp)
|
||||
mov %rdx, 0x10(%rsp)
|
||||
mov %r8, 0x18(%rsp)
|
||||
mov %r9, 0x20(%rsp)
|
||||
|
||||
# Construct new stack
|
||||
push %rbp
|
||||
mov %rsp, %rbp
|
||||
push %rsi
|
||||
push %rdi
|
||||
push %rbx
|
||||
sub $0x80, %rsp
|
||||
push %r10
|
||||
mov %rbp, %rsi
|
||||
add $0x10, %rsi
|
||||
mov %rsp, %rdi
|
||||
add $0x8, %rdi
|
||||
mov $0x10, %rcx
|
||||
rep movsq
|
||||
|
||||
# build new paramater calling convention
|
||||
mov 0x18(%rsp), %r9
|
||||
mov 0x10(%rsp), %r8
|
||||
mov 0x8(%rsp), %rdx
|
||||
mov %r10, %rcx
|
||||
|
||||
# call C-code
|
||||
call ASM_PFX(EbcInterpret)
|
||||
add $0x88, %esp
|
||||
pop %rbx
|
||||
pop %rdi
|
||||
pop %rsi
|
||||
pop %rbp
|
||||
ret
|
||||
|
||||
ASM_GLOBAL ASM_PFX(EbcLLExecuteEbcImageEntryPoint);
|
||||
ASM_PFX(EbcLLExecuteEbcImageEntryPoint):
|
||||
# build new paramater calling convention
|
||||
mov %rdx, %r8
|
||||
mov %rcx, %rdx
|
||||
mov %r10, %rcx
|
||||
|
||||
# call C-code
|
||||
sub $0x28, %rsp
|
||||
call ASM_PFX(ExecuteEbcImageEntryPoint)
|
||||
add $0x28, %rsp
|
||||
ret
|
|
@ -1,246 +0,0 @@
|
|||
;/** @file
|
||||
;
|
||||
; This code provides low level routines that support the Virtual Machine.
|
||||
; for option ROMs.
|
||||
;
|
||||
; Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
; Copyright (c) 2014 Hewlett-Packard Development Company, L.P.<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.
|
||||
;
|
||||
;**/
|
||||
|
||||
page ,132
|
||||
title VM ASSEMBLY LANGUAGE ROUTINES
|
||||
|
||||
;---------------------------------------------------------------------------
|
||||
; Equate files needed.
|
||||
;---------------------------------------------------------------------------
|
||||
|
||||
.CODE
|
||||
|
||||
CopyMem PROTO Destination:PTR DWORD, Source:PTR DWORD, Count:DWORD
|
||||
EbcInterpret PROTO
|
||||
ExecuteEbcImageEntryPoint PROTO
|
||||
|
||||
;****************************************************************************
|
||||
; EbcLLCALLEX
|
||||
;
|
||||
; This function is called to execute an EBC CALLEX instruction.
|
||||
; This instruction requires that we thunk out to external native
|
||||
; code. For x64, we switch stacks, copy the arguments to the stack
|
||||
; and jump to the specified function.
|
||||
; On return, we restore the stack pointer to its original location.
|
||||
;
|
||||
; Destroys no working registers.
|
||||
;****************************************************************************
|
||||
; INT64 EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr)
|
||||
EbcLLCALLEXNative PROC PUBLIC
|
||||
push rbp
|
||||
push rbx
|
||||
mov rbp, rsp
|
||||
; Function prolog
|
||||
|
||||
; Copy FuncAddr to a preserved register.
|
||||
mov rbx, rcx
|
||||
|
||||
; Set stack pointer to new value
|
||||
sub r8, rdx
|
||||
|
||||
;
|
||||
; Fix X64 native function call prolog. Prepare space for at least 4 arguments,
|
||||
; even if the native function's arguments are less than 4.
|
||||
;
|
||||
; From MSDN x64 Software Conventions, Overview of x64 Calling Conventions:
|
||||
; "The caller is responsible for allocating space for parameters to the
|
||||
; callee, and must always allocate sufficient space for the 4 register
|
||||
; parameters, even if the callee doesn't have that many parameters.
|
||||
; This aids in the simplicity of supporting C unprototyped functions,
|
||||
; and vararg C/C++ functions."
|
||||
;
|
||||
cmp r8, 20h
|
||||
jae skip_expansion
|
||||
mov r8, 20h
|
||||
skip_expansion:
|
||||
|
||||
sub rsp, r8
|
||||
|
||||
;
|
||||
; Fix X64 native function call 16-byte alignment.
|
||||
;
|
||||
; From MSDN x64 Software Conventions, Stack Usage:
|
||||
; "The stack will always be maintained 16-byte aligned, except within
|
||||
; the prolog (for example, after the return address is pushed)."
|
||||
;
|
||||
and rsp, NOT 0fh
|
||||
|
||||
mov rcx, rsp
|
||||
sub rsp, 20h
|
||||
call CopyMem
|
||||
add rsp, 20h
|
||||
|
||||
; Considering the worst case, load 4 potiential arguments
|
||||
; into registers.
|
||||
mov rcx, qword ptr [rsp]
|
||||
mov rdx, qword ptr [rsp+8h]
|
||||
mov r8, qword ptr [rsp+10h]
|
||||
mov r9, qword ptr [rsp+18h]
|
||||
|
||||
; Now call the external routine
|
||||
call rbx
|
||||
|
||||
; Function epilog
|
||||
mov rsp, rbp
|
||||
pop rbx
|
||||
pop rbp
|
||||
ret
|
||||
EbcLLCALLEXNative ENDP
|
||||
|
||||
;****************************************************************************
|
||||
; EbcLLEbcInterpret
|
||||
;
|
||||
; Begin executing an EBC image.
|
||||
;****************************************************************************
|
||||
; UINT64 EbcLLEbcInterpret(VOID)
|
||||
EbcLLEbcInterpret PROC PUBLIC
|
||||
;
|
||||
;; mov rax, ca112ebccall2ebch
|
||||
;; mov r10, EbcEntryPoint
|
||||
;; mov r11, EbcLLEbcInterpret
|
||||
;; jmp r11
|
||||
;
|
||||
; Caller uses above instruction to jump here
|
||||
; The stack is below:
|
||||
; +-----------+
|
||||
; | RetAddr |
|
||||
; +-----------+
|
||||
; |EntryPoint | (R10)
|
||||
; +-----------+
|
||||
; | Arg1 | <- RDI
|
||||
; +-----------+
|
||||
; | Arg2 |
|
||||
; +-----------+
|
||||
; | ... |
|
||||
; +-----------+
|
||||
; | Arg16 |
|
||||
; +-----------+
|
||||
; | Dummy |
|
||||
; +-----------+
|
||||
; | RDI |
|
||||
; +-----------+
|
||||
; | RSI |
|
||||
; +-----------+
|
||||
; | RBP | <- RBP
|
||||
; +-----------+
|
||||
; | RetAddr | <- RSP is here
|
||||
; +-----------+
|
||||
; | Scratch1 | (RCX) <- RSI
|
||||
; +-----------+
|
||||
; | Scratch2 | (RDX)
|
||||
; +-----------+
|
||||
; | Scratch3 | (R8)
|
||||
; +-----------+
|
||||
; | Scratch4 | (R9)
|
||||
; +-----------+
|
||||
; | Arg5 |
|
||||
; +-----------+
|
||||
; | Arg6 |
|
||||
; +-----------+
|
||||
; | ... |
|
||||
; +-----------+
|
||||
; | Arg16 |
|
||||
; +-----------+
|
||||
;
|
||||
|
||||
; save old parameter to stack
|
||||
mov [rsp + 08h], rcx
|
||||
mov [rsp + 10h], rdx
|
||||
mov [rsp + 18h], r8
|
||||
mov [rsp + 20h], r9
|
||||
|
||||
; Construct new stack
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
push rsi
|
||||
push rdi
|
||||
push rbx
|
||||
sub rsp, 80h
|
||||
push r10
|
||||
mov rsi, rbp
|
||||
add rsi, 10h
|
||||
mov rdi, rsp
|
||||
add rdi, 8
|
||||
mov rcx, 16
|
||||
rep movsq
|
||||
|
||||
; build new paramater calling convention
|
||||
mov r9, [rsp + 18h]
|
||||
mov r8, [rsp + 10h]
|
||||
mov rdx, [rsp + 08h]
|
||||
mov rcx, r10
|
||||
|
||||
; call C-code
|
||||
call EbcInterpret
|
||||
add rsp, 88h
|
||||
pop rbx
|
||||
pop rdi
|
||||
pop rsi
|
||||
pop rbp
|
||||
ret
|
||||
EbcLLEbcInterpret ENDP
|
||||
|
||||
;****************************************************************************
|
||||
; EbcLLExecuteEbcImageEntryPoint
|
||||
;
|
||||
; Begin executing an EBC image.
|
||||
;****************************************************************************
|
||||
; UINT64 EbcLLExecuteEbcImageEntryPoint(VOID)
|
||||
EbcLLExecuteEbcImageEntryPoint PROC PUBLIC
|
||||
;
|
||||
;; mov rax, ca112ebccall2ebch
|
||||
;; mov r10, EbcEntryPoint
|
||||
;; mov r11, EbcLLExecuteEbcImageEntryPoint
|
||||
;; jmp r11
|
||||
;
|
||||
; Caller uses above instruction to jump here
|
||||
; The stack is below:
|
||||
; +-----------+
|
||||
; | RetAddr |
|
||||
; +-----------+
|
||||
; |EntryPoint | (R10)
|
||||
; +-----------+
|
||||
; |ImageHandle|
|
||||
; +-----------+
|
||||
; |SystemTable|
|
||||
; +-----------+
|
||||
; | Dummy |
|
||||
; +-----------+
|
||||
; | Dummy |
|
||||
; +-----------+
|
||||
; | RetAddr | <- RSP is here
|
||||
; +-----------+
|
||||
; |ImageHandle| (RCX)
|
||||
; +-----------+
|
||||
; |SystemTable| (RDX)
|
||||
; +-----------+
|
||||
;
|
||||
|
||||
; build new paramater calling convention
|
||||
mov r8, rdx
|
||||
mov rdx, rcx
|
||||
mov rcx, r10
|
||||
|
||||
; call C-code
|
||||
sub rsp, 28h
|
||||
call ExecuteEbcImageEntryPoint
|
||||
add rsp, 28h
|
||||
ret
|
||||
EbcLLExecuteEbcImageEntryPoint ENDP
|
||||
|
||||
END
|
||||
|
Loading…
Reference in New Issue