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