]> git.proxmox.com Git - mirror_edk2.git/blob - MdePkg/Library/BaseLib/Ia32/Thunk16.S
Clean up hard-coded offsets and other utter bogosity in Thunk16.S
[mirror_edk2.git] / MdePkg / Library / BaseLib / Ia32 / Thunk16.S
1 #------------------------------------------------------------------------------
2 #
3 # Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
4 # This program and the accompanying materials
5 # are licensed and made available under the terms and conditions of the BSD License
6 # which accompanies this distribution. The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php.
8 #
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 #
12 # Module Name:
13 #
14 # Thunk16.S
15 #
16 # Abstract:
17 #
18 # Real mode thunk
19 #
20 #------------------------------------------------------------------------------
21
22 #include <Library/BaseLib.h>
23
24 ASM_GLOBAL ASM_PFX(m16Start), ASM_PFX(m16Size), ASM_PFX(mThunk16Attr), ASM_PFX(m16Gdt), ASM_PFX(m16GdtrBase), ASM_PFX(mTransition)
25 ASM_GLOBAL ASM_PFX(InternalAsmThunk16)
26
27 # define the structure of IA32_REGS
28 .set _EDI, 0 #size 4
29 .set _ESI, 4 #size 4
30 .set _EBP, 8 #size 4
31 .set _ESP, 12 #size 4
32 .set _EBX, 16 #size 4
33 .set _EDX, 20 #size 4
34 .set _ECX, 24 #size 4
35 .set _EAX, 28 #size 4
36 .set _DS, 32 #size 2
37 .set _ES, 34 #size 2
38 .set _FS, 36 #size 2
39 .set _GS, 38 #size 2
40 .set _EFLAGS, 40 #size 4
41 .set _EIP, 44 #size 4
42 .set _CS, 48 #size 2
43 .set _SS, 50 #size 2
44 .set IA32_REGS_SIZE, 52
45
46 .text
47 .code16
48
49 ASM_PFX(m16Start):
50
51 SavedGdt: .space 6
52
53 ASM_PFX(BackFromUserCode):
54 push %ss
55 push %cs
56
57 calll L_Base1 # push eip
58 L_Base1:
59 pushfl
60 cli # disable interrupts
61 push %gs
62 push %fs
63 push %es
64 push %ds
65 pushal
66 .byte 0x66, 0xba # mov edx, imm32
67 ASM_PFX(ThunkAttr): .space 4
68 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl
69 jz 1f
70 movw $0x2401, %ax
71 int $0x15
72 cli # disable interrupts
73 jnc 2f
74 1:
75 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl
76 jz 2f
77 inb $0x92, %al
78 orb $2, %al
79 outb %al, $0x92 # deactivate A20M#
80 2:
81 xorl %eax, %eax
82 movw %ss, %ax
83 leal IA32_REGS_SIZE(%esp), %ebp
84 mov %ebp, (_ESP - IA32_REGS_SIZE)(%bp)
85 mov (_EIP - IA32_REGS_SIZE)(%bp), %bx
86 shll $4, %eax
87 addl %eax, %ebp
88 .byte 0x66, 0xb8 # mov eax, imm32
89 SavedCr4: .space 4
90 movl %eax, %cr4
91 lgdtl %cs:(SavedGdt - L_Base1)(%bx)
92 .byte 0x66, 0xb8 # mov eax, imm32
93 SavedCr0: .space 4
94 movl %eax, %cr0
95 .byte 0xb8 # mov ax, imm16
96 SavedSs: .space 2
97 movl %eax, %ss
98 .byte 0x66, 0xbc # mov esp, imm32
99 SavedEsp: .space 4
100 lretl # return to protected mode
101
102 _EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start)
103 .word 0x8
104 _16Idtr: .word 0x3ff
105 .long 0
106 _16Gdtr: .word GdtEnd - _NullSegDesc - 1
107 _16GdtrBase: .long _NullSegDesc
108
109 ASM_PFX(ToUserCode):
110 movw %ss, %dx
111 movw %cx, %ss # set new segment selectors
112 movw %cx, %ds
113 movw %cx, %es
114 movw %cx, %fs
115 movw %cx, %gs
116 movl %eax, %cr0
117 movl %ebp, %cr4 # real mode starts at next instruction
118 movw %si, %ss # set up 16-bit stack segment
119 xchgl %ebx, %esp # set up 16-bit stack pointer
120 calll L_Base # push eip
121 L_Base:
122 popl %ebp # ebp <- offset L_Base
123 push (IA32_REGS_SIZE + 2)(%esp)
124 lea (L_RealMode - L_Base)(%bp), %ax
125 push %ax
126 lret
127
128 L_RealMode:
129 mov %dx, %cs:(SavedSs - L_Base)(%bp)
130 mov %ebx, %cs:(SavedEsp - L_Base)(%bp)
131 lidtl %cs:(_16Idtr - L_Base)(%bp)
132 popal
133 pop %ds
134 pop %es
135 pop %fs
136 pop %gs
137 popfl
138 lretl # transfer control to user code
139
140 _NullSegDesc: .quad 0
141 _16CsDesc:
142 .word -1
143 .word 0
144 .byte 0
145 .byte 0x9b
146 .byte 0x8f # 16-bit segment, 4GB limit
147 .byte 0
148 _16DsDesc:
149 .word -1
150 .word 0
151 .byte 0
152 .byte 0x93
153 .byte 0x8f # 16-bit segment, 4GB limit
154 .byte 0
155 GdtEnd:
156
157 .code32
158 #
159 # @param RegSet The pointer to a IA32_DWORD_REGS structure
160 # @param Transition The pointer to the transition code
161 # @return The address of the 16-bit stack after returning from user code
162 #
163 ASM_PFX(InternalAsmThunk16):
164 push %ebp
165 push %ebx
166 push %esi
167 push %edi
168 push %ds
169 push %es
170 push %fs
171 push %gs
172 movl 36(%esp), %esi # esi <- RegSet
173 movzwl _SS(%esi), %edx
174 mov _ESP(%esi), %edi
175 add $(-(IA32_REGS_SIZE + 4)), %edi
176 movl %edi, %ebx # ebx <- stack offset
177 imul $0x10, %edx, %eax
178 push $(IA32_REGS_SIZE / 4)
179 addl %eax, %edi # edi <- linear address of 16-bit stack
180 pop %ecx
181 rep
182 movsl # copy RegSet
183 movl 40(%esp), %eax # eax <- address of transition code
184 movl %edx, %esi # esi <- 16-bit stack segment
185 lea (SavedCr0 - ASM_PFX(m16Start))(%eax), %edx
186 movl %eax, %ecx
187 andl $0xf, %ecx
188 shll $12, %eax
189 lea (ASM_PFX(BackFromUserCode) - ASM_PFX(m16Start))(%ecx), %ecx
190 movw %cx, %ax
191 stosl # [edi] <- return address of user code
192 sgdtl (SavedGdt - SavedCr0)(%edx)
193 sidtl 0x24(%esp)
194 movl %cr0, %eax
195 movl %eax, (%edx) # save CR0 in SavedCr0
196 andl $0x7ffffffe, %eax # clear PE, PG bits
197 movl %cr4, %ebp
198 mov %ebp, (SavedCr4 - SavedCr0)(%edx)
199 andl $0xffffffcf, %ebp # clear PAE, PSE bits
200 pushl $0x10
201 pop %ecx # ecx <- selector for data segments
202 lgdtl (_16Gdtr - SavedCr0)(%edx)
203 pushfl
204 lcall *(_EntryPoint - SavedCr0)(%edx)
205 popfl
206 lidtl 0x24(%esp)
207 lea -IA32_REGS_SIZE(%ebp), %eax
208 pop %gs
209 pop %fs
210 pop %es
211 pop %ds
212 pop %edi
213 pop %esi
214 pop %ebx
215 pop %ebp
216 ret
217
218 .const:
219
220 ASM_PFX(m16Size): .word ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start)
221 ASM_PFX(mThunk16Attr): .word ASM_PFX(ThunkAttr) - ASM_PFX(m16Start)
222 ASM_PFX(m16Gdt): .word _NullSegDesc - ASM_PFX(m16Start)
223 ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start)
224 ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start)