1 #------------------------------------------------------------------------------
3 # Copyright (c) 2006 - 2011, 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.
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.
20 #------------------------------------------------------------------------------
22 #include <Library/BaseLib.h>
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)
27 # define the structure of IA32_REGS
40 .set _EFLAGS, 40 #size 4
44 .set IA32_REGS_SIZE, 52
52 ASM_PFX(BackFromUserCode):
56 call L_Base1 # push eip
58 pushfw # pushfd actually
59 cli # disable interrupts
64 pushaw # pushad actually
65 .byte 0x66, 0xba # mov edx, imm32
66 ASM_PFX(ThunkAttr): .space 4
67 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl
69 movl $0x15cd2401, %eax # mov ax, 2401h & int 15h
70 cli # disable interrupts
73 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl
77 outb %al, $0x92 # deactivate A20M#
79 xorw %ax, %ax # xor eax, eax
80 movl %ss, %eax # mov ax, ss
82 lea IA32_REGS_SIZE(%esp), %bp
84 mov %ebp, (_ESP - IA32_REGS_SIZE)(%esi)
85 mov (_EIP - IA32_REGS_SIZE)(%esi), %ebx
86 shlw $4, %ax # shl eax, 4
87 addw %ax, %bp # add ebp, eax
88 .byte 0x66, 0xb8 # mov eax, imm32
91 lgdtw %cs:(SavedGdt - L_Base1)(%edi)
92 .byte 0x66, 0xb8 # mov eax, imm32
95 .byte 0xb8 # mov ax, imm16
98 .byte 0x66, 0xbc # mov esp, imm32
101 lret # return to protected mode
103 _EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start)
107 _16Gdtr: .word GdtEnd - _NullSegDesc - 1
108 _16GdtrBase: .long _NullSegDesc
112 movl %ecx, %ss # set new segment selectors
118 movl %ebp, %cr4 # real mode starts at next instruction
119 movl %esi, %ss # set up 16-bit stack segment
120 xchgw %bx, %sp # set up 16-bit stack pointer
122 call L_Base # push eip
124 popw %bp # ebp <- offset L_Base
125 .byte 0x67; # address size override
126 push (IA32_REGS_SIZE + 2)(%esp)
127 lea (L_RealMode - L_Base)(%esi), %eax
132 mov %edx, %cs:(SavedSs - L_Base)(%esi)
133 mov %bx, %cs:(SavedEsp - L_Base)(%esi)
134 lidtw %cs:(_16Idtr - L_Base)(%esi)
135 popaw # popad actually
141 lretw # transfer control to user code
143 _NullSegDesc: .quad 0
149 .byte 0x8f # 16-bit segment, 4GB limit
156 .byte 0x8f # 16-bit segment, 4GB limit
161 # @param RegSet The pointer to a IA32_DWORD_REGS structure
162 # @param Transition The pointer to the transition code
163 # @return The address of the 16-bit stack after returning from user code
165 ASM_PFX(InternalAsmThunk16):
174 movl 36(%esp), %esi # esi <- RegSet
175 movzwl _SS(%esi), %edx
177 add $(-(IA32_REGS_SIZE + 4)), %edi
178 movl %edi, %ebx # ebx <- stack offset
179 imul $0x10, %edx, %eax
180 push $(IA32_REGS_SIZE / 4)
181 addl %eax, %edi # edi <- linear address of 16-bit stack
185 movl 40(%esp), %eax # eax <- address of transition code
186 movl %edx, %esi # esi <- 16-bit stack segment
187 lea (SavedCr0 - ASM_PFX(m16Start))(%eax), %edx
191 lea (ASM_PFX(BackFromUserCode) - ASM_PFX(m16Start))(%ecx), %ecx
193 stosl # [edi] <- return address of user code
194 sgdtl (SavedGdt - SavedCr0)(%edx)
197 movl %eax, (%edx) # save CR0 in SavedCr0
198 andl $0x7ffffffe, %eax # clear PE, PG bits
200 mov %ebp, (SavedCr4 - SavedCr0)(%edx)
201 andl $0x300, %ebp # clear all but PCE and OSFXSR bits
203 pop %ecx # ecx <- selector for data segments
204 lgdtl (_16Gdtr - SavedCr0)(%edx)
206 lcall *(_EntryPoint - SavedCr0)(%edx)
209 lea -IA32_REGS_SIZE(%ebp), %eax
222 ASM_PFX(m16Size): .word ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start)
223 ASM_PFX(mThunk16Attr): .word ASM_PFX(ThunkAttr) - ASM_PFX(m16Start)
224 ASM_PFX(m16Gdt): .word _NullSegDesc - ASM_PFX(m16Start)
225 ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start)
226 ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start)