mirror of https://github.com/acidanthera/audk.git
237 lines
6.6 KiB
ArmAsm
237 lines
6.6 KiB
ArmAsm
#*****************************************************************************
|
|
#*
|
|
#* Copyright (c) 2008, Intel Corporation
|
|
#* All rights reserved. This program and the accompanying materials
|
|
#* are licensed and made available under the terms and conditions of the BSD License
|
|
#* which accompanies this distribution. The full text of the license may be found at
|
|
#* http://opensource.org/licenses/bsd-license.php
|
|
#*
|
|
#* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
#* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
#*
|
|
#* Module Name:
|
|
#*
|
|
#* Thunk.S
|
|
#*
|
|
#* Abstract:
|
|
#*
|
|
#* Real mode thunk
|
|
#*
|
|
#*****************************************************************************
|
|
#include <EfiBind.h>
|
|
|
|
|
|
|
|
.data
|
|
|
|
.globl ASM_PFX(mCode16Size)
|
|
|
|
.data
|
|
mCode16Size: .long _Code16End - _Code16Addr
|
|
|
|
|
|
NullSegSel: .quad 0
|
|
_16CsSegSel:
|
|
.word -1
|
|
.word 0
|
|
.byte 0
|
|
.byte 0x9b
|
|
.byte 0x8f #16-bit segment
|
|
.byte 0
|
|
_16DsSegSel:
|
|
.word -1
|
|
.word 0
|
|
.byte 0
|
|
.byte 0x93
|
|
.byte 0x8f #16-bit segment
|
|
.byte 0
|
|
|
|
_16Gdtr:
|
|
.word _16Gdtr - NullSegSel - 1
|
|
.long NullSegSel
|
|
.code:
|
|
|
|
#IA32_REGS STRUC 4t
|
|
#_EDI DD ?
|
|
#_ESI DD ?
|
|
#_EBP DD ?
|
|
#_ESP DD ?
|
|
#_EBX DD ?
|
|
#_EDX DD ?
|
|
#_ECX DD ?
|
|
#_EAX DD ?
|
|
#_DS DW ?
|
|
#_ES DW ?
|
|
#_FS DW ?
|
|
#_GS DW ?
|
|
#_RFLAGS DQ ?
|
|
#_EIP DD ?
|
|
#_CS DW ?
|
|
#_SS DW ?
|
|
#IA32_REGS ENDS
|
|
|
|
#_STK16 STRUC 1t
|
|
#RetEip DD ?
|
|
#RetCs DW ?
|
|
#ThunkFlags DW ?
|
|
#SavedGdtr FWORD ?
|
|
#Resvd1 DW ?
|
|
#SavedCr0 DD ?
|
|
#SavedCr4 DD ?
|
|
#_STK16 ENDS
|
|
|
|
ASM_PFX(Thunk16):
|
|
push %rbp
|
|
push %rbx
|
|
push %rsi
|
|
push %rdi
|
|
push %r12
|
|
push %r13
|
|
push %r14
|
|
push %r15
|
|
pushq %fs
|
|
pushq %gs
|
|
movl %ds,%r12d
|
|
movl %es,%r13d
|
|
movl %ss,%r14d
|
|
mov %rsp,%r15
|
|
mov %rcx,%rsi
|
|
movzwq 0x36(%rsi),%r10 #movzx r10, (IA32_REGS ptr [rsi])._SS
|
|
xor %rdi,%rdi
|
|
mov 0xc(%rsi),%edi #mov edi, (IA32_REGS ptr [rsi])._ESP
|
|
add $0xffffffffffffffb0,%rdi #add rdi, - sizeof (IA32_REGS) - sizeof (_STK16)
|
|
push %rdi
|
|
imul $0x10,%r10,%rax
|
|
add %rax,%rdi
|
|
pushq $0xe #push sizeof (IA32_REGS) / 4
|
|
pop %rcx
|
|
rep movsl %ds:(%rsi),%es:(%rdi)
|
|
pop %rbx #rbx <- 16-bit stack offset
|
|
lea Label,%eax #42 <_Thunk16+0x42>
|
|
stos %eax,%es:(%rdi)
|
|
movl %cs,%eax #return segment
|
|
stos %ax,%es:(%rdi)
|
|
mov %edx,%eax #THUNK Flags
|
|
stos %ax,%es:(%rdi)
|
|
sgdt 0x58(%rsp) #save GDTR
|
|
mov 0x58(%rsp),%rax
|
|
stos %rax,%es:(%rdi)
|
|
mov %cr0,%rax #save CR0
|
|
mov %eax,%esi #esi <- CR0 to set
|
|
stos %eax,%es:(%rdi)
|
|
mov %cr4,%rax #save CR4
|
|
stos %eax,%es:(%rdi)
|
|
sidt 0x58(%rsp) #save IDTR
|
|
and $0x7ffffffe,%esi #clear PE & PG bits
|
|
mov %r10,%rdi #rdi <- 16-bit stack segment
|
|
shl $0x10,%r8
|
|
push %r8 #far jmp address
|
|
lea Label_16Bit,%eax
|
|
push %rax
|
|
movw $0x8,0x4(%rsp)
|
|
lgdt _16Gdtr #bugbug: may not match.
|
|
lret
|
|
Label_16Bit:
|
|
.byte 0x66
|
|
movl $0xc0000080,%ecx
|
|
mov %rsi,%cr0 #disable PE & PG
|
|
rdmsr
|
|
and $0xfe,%ah
|
|
wrmsr #clear LME bit
|
|
mov %cr4,%rax
|
|
and $0xcf,%al #clear PAE & PSE
|
|
mov %rax,%cr4
|
|
lret
|
|
|
|
Label:
|
|
xor %rax,%rax
|
|
movl %ss,%eax
|
|
shl $0x4,%eax
|
|
add %esp,%eax
|
|
mov %r15,%rsp
|
|
lidt 0x58(%rsp)
|
|
movl %r12d,%ds
|
|
movl %r13d,%es
|
|
movl %r14d,%ss
|
|
popq %gs
|
|
popq %fs
|
|
pop %r15
|
|
pop %r14
|
|
pop %r13
|
|
pop %r12
|
|
pop %rdi
|
|
pop %rsi
|
|
pop %rbx
|
|
pop %rbp
|
|
retq
|
|
|
|
|
|
.align 0x10
|
|
|
|
_Code16Addr:
|
|
ASM_PFX(RealMode):
|
|
movl %edi,%ss
|
|
mov %bx,%sp #set up 16-bit stack
|
|
.byte 0x2e
|
|
.byte 0x0f
|
|
.byte 0x01
|
|
.byte 0x1e
|
|
.word _16Idtr - _Code16Addr #lidt _16Idtr
|
|
.byte 0x66
|
|
.byte 0x61 #popad
|
|
.byte 0x1f #pop ds
|
|
.byte 0x07 #pop es
|
|
popq %fs
|
|
popq %gs
|
|
add $0x8,%esp #skip RFLAGS
|
|
.byte 0x67 #test [esp + 0eh], 1
|
|
.byte 0xf7
|
|
.byte 0x44
|
|
.byte 0x24
|
|
.byte 0x0e
|
|
.byte 0x01
|
|
.byte 0x00
|
|
jz 1f
|
|
pushfq #pushf, actually
|
|
1:
|
|
.byte 0x0e #push cs
|
|
.byte 0x68 #push /iw
|
|
.word FarCallRet - _Code16Addr
|
|
jz 2f
|
|
.byte 0x66
|
|
ljmp *6(%esp)
|
|
2:
|
|
.byte 0x66
|
|
ljmp *4(%esp)
|
|
FarCallRet:
|
|
.byte 0x66
|
|
push $0x00 #push a dword of zero
|
|
.byte 0x66
|
|
pushf #pushfd, actually
|
|
pushq %gs
|
|
pushq %fs
|
|
.byte 0x06 #push %es
|
|
.byte 0x1e #push %ds
|
|
.byte 0x66
|
|
.byte 0x60
|
|
cli
|
|
.byte 0x66 #sizeof (IA32_REGS) = 13 * 4 = 52
|
|
lgdt 64(%esp) #lgdt (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedGdtr
|
|
.byte 0x66
|
|
mov 76(%esp), %eax
|
|
mov %rax, %cr4
|
|
.byte 0x66
|
|
mov $0xc0000080, %ecx
|
|
rdmsr
|
|
orb $1, %ah
|
|
wrmsr
|
|
.byte 0x66
|
|
mov 72(%esp), %eax
|
|
mov %rax, %cr0 #restore CR0
|
|
.byte 0x66
|
|
ljmpl *52(%esp)
|
|
|
|
_16Idtr:
|
|
.word 0x3ff #FWORD (1 SHL 10) - 1
|
|
.byte 0x00
|