]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseLib/Ia32/Thunk16.S
ca72d0b544ea24e48765979abb03a80866f6c378
[mirror_edk2.git] / MdePkg / Library / BaseLib / Ia32 / Thunk16.S
1 //
2 // Include common header file for this module.
3 //
4 #include "CommonHeader.h"
5
6 #------------------------------------------------------------------------------
7 #
8 # Copyright (c) 2006, Intel Corporation
9 # All rights reserved. This program and the accompanying materials
10 # are licensed and made available under the terms and conditions of the BSD License
11 # which accompanies this distribution. The full text of the license may be found at
12 # http://opensource.org/licenses/bsd-license.php
13 #
14 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #
17 # Module Name:
18 #
19 # Thunk16.S
20 #
21 # Abstract:
22 #
23 # Real mode thunk
24 #
25 #------------------------------------------------------------------------------
26
27 .globl ASM_PFX(m16Start), ASM_PFX(m16Size), ASM_PFX(mThunk16Attr), ASM_PFX(m16Gdt), ASM_PFX(m16GdtrBase), ASM_PFX(mTransition)
28 .globl ASM_PFX(InternalAsmThunk16)
29
30 ASM_PFX(m16Start):
31
32 SavedGdt: .space 6
33
34 ASM_PFX(BackFromUserCode):
35 push %ss
36 push %cs
37 .byte 0x66
38 call L_Base1 # push eip
39 L_Base1:
40 pushfw # pushfd actually
41 cli # disable interrupts
42 push %gs
43 push %fs
44 push %es
45 push %ds
46 pushaw # pushad actually
47 .byte 0x66, 0xba # mov edx, imm32
48 ASM_PFX(ThunkAttr): .space 4
49 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl
50 jz 1f
51 movl $0x15cd2401, %eax # mov ax, 2401h & int 15h
52 cli # disable interrupts
53 jnc 2f
54 1:
55 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl
56 jz 2f
57 inb $0x92, %al
58 orb $2, %al
59 outb %al, $0x92 # deactivate A20M#
60 2:
61 movl %ss, %eax
62 .byte 0x67, 0x66, 0x8d, 0x6c, 0x24, 0x34, 0x66
63 mov %ebp, 0xffffffd8(%esi)
64 mov 0xfffffff8(%esi), %ebx
65 shlw $4, %ax # shl eax, 4
66 addw %ax, %bp # add ebp, eax
67 .byte 0x66, 0xb8 # mov eax, imm32
68 SavedCr4: .space 4
69 movl %eax, %cr4
70 lgdtw %cs:0xfffffff2(%edi)
71 .byte 0x66, 0xb8 # mov eax, imm32
72 SavedCr0: .space 4
73 movl %eax, %cr0
74 .byte 0xb8 # mov ax, imm16
75 SavedSs: .space 2
76 movl %eax, %ss
77 .byte 0x66, 0xbc # mov esp, imm32
78 SavedEsp: .space 4
79 .byte 0x66
80 lret # return to protected mode
81
82 _EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start)
83 .word 0x8
84 _16Idtr: .word 0x3ff
85 .long 0
86 _16Gdtr: .word GdtEnd - _NullSegDesc - 1
87 _16GdtrBase: .long _NullSegDesc
88
89 ASM_PFX(ToUserCode):
90 movl %ss, %edx
91 movl %ecx, %ss # set new segment selectors
92 movl %ecx, %ds
93 movl %ecx, %es
94 movl %ecx, %fs
95 movl %ecx, %gs
96 movl %eax, %cr0
97 movl %ebp, %cr4 # real mode starts at next instruction
98 movl %esi, %ss # set up 16-bit stack segment
99 xchgw %bx, %sp # set up 16-bit stack pointer
100 .byte 0x66
101 call L_Base # push eip
102 L_Base:
103 popw %bp # ebp <- offset L_Base
104 addr16 pushl 36(%si)
105 .byte 0x36
106 lea 0xc(%esi), %eax
107 push %eax
108 lret
109
110 L_RealMode:
111 mov %edx, %cs:0xffffffc5(%esi)
112 mov %bx, %cs:0xffffffcb(%esi)
113 lidtw %cs:0xffffffd7(%esi)
114 popaw # popad actually
115 pop %ds
116 pop %es
117 pop %fs
118 pop %gs
119 popfw # popfd
120 lretw # transfer control to user code
121
122 _NullSegDesc: .quad 0
123 _16CsDesc:
124 .word -1
125 .word 0
126 .byte 0
127 .byte 0x9b
128 .byte 0x8f # 16-bit segment, 4GB limit
129 .byte 0
130 _16DsDesc:
131 .word -1
132 .word 0
133 .byte 0
134 .byte 0x93
135 .byte 0x8f # 16-bit segment, 4GB limit
136 .byte 0
137 GdtEnd:
138
139 #
140 # @param RegSet Pointer to a IA32_DWORD_REGS structure
141 # @param Transition Pointer to the transition code
142 # @return The address of the 16-bit stack after returning from user code
143 #
144 ASM_PFX(InternalAsmThunk16):
145 push %ebp
146 push %ebx
147 push %esi
148 push %edi
149 push %ds
150 push %es
151 push %fs
152 push %gs
153 movl 36(%esp), %esi # esi <- RegSet
154 movzwl 0x32(%esi), %edx
155 mov 0xc(%esi), %edi
156 add $0xffffffc8, %edi
157 movl %edi, %ebx # ebx <- stack offset
158 imul $0x10, %edx, %eax
159 push $0xd
160 addl %eax, %edi # edi <- linear address of 16-bit stack
161 pop %ecx
162 rep
163 movsl # copy RegSet
164 movl 40(%esp), %eax # eax <- address of transition code
165 movl %edx, %esi # esi <- 16-bit stack segment
166 lea 0x5e(%eax), %edx
167 movl %eax, %ecx
168 andl $0xf, %ecx
169 shll $12, %eax
170 lea 0x6(%ecx), %ecx
171 movw %cx, %ax
172 stosl # [edi] <- return address of user code
173 sgdtl 0xffffffa2(%edx)
174 sidtl 0x24(%esp)
175 movl %cr0, %eax
176 movl %eax, (%edx) # save CR0 in SavedCr0
177 andl $0x7ffffffe, %eax # clear PE, PG bits
178 movl %cr4, %ebp
179 mov %ebp, 0xfffffff1(%edx)
180 andl $0x300, %ebp # clear all but PCE and OSFXSR bits
181 pushl $0x10
182 pop %ecx # ecx <- selector for data segments
183 lgdtl 0x20(%edx)
184 pushfl
185 lcall *0x14(%edx)
186 popfl
187 lidtl 0x24(%esp)
188 lea 0xffffffcc(%ebp), %eax
189 pop %gs
190 pop %fs
191 pop %es
192 pop %ds
193 pop %edi
194 pop %esi
195 pop %ebx
196 pop %ebp
197 ret
198
199 .const:
200
201 ASM_PFX(m16Size): .word _InternalAsmThunk16 - ASM_PFX(m16Start)
202 ASM_PFX(mThunk16Attr): .word _ThunkAttr - ASM_PFX(m16Start)
203 ASM_PFX(m16Gdt): .word _NullSegDesc - ASM_PFX(m16Start)
204 ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start)
205 ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start)