1 #------------------------------------------------------------------------------
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.
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
53 ASM_PFX(BackFromUserCode):
57 calll L_Base1 # push eip
60 cli # disable interrupts
66 .byte 0x66, 0xba # mov edx, imm32
67 ASM_PFX(ThunkAttr): .space 4
68 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl
72 cli # disable interrupts
75 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl
79 outb %al, $0x92 # deactivate A20M#
83 leal IA32_REGS_SIZE(%esp), %ebp
84 mov %ebp, (_ESP - IA32_REGS_SIZE)(%bp)
85 mov (_EIP - IA32_REGS_SIZE)(%bp), %bx
88 .byte 0x66, 0xb8 # mov eax, imm32
91 lgdtl %cs:(SavedGdt - L_Base1)(%bx)
92 .byte 0x66, 0xb8 # mov eax, imm32
95 .byte 0xb8 # mov ax, imm16
98 .byte 0x66, 0xbc # mov esp, imm32
100 lretl # return to protected mode
102 _EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start)
106 _16Gdtr: .word GdtEnd - _NullSegDesc - 1
107 _16GdtrBase: .long _NullSegDesc
111 movw %cx, %ss # set new segment selectors
116 movl %eax, %cr0 # real mode starts at next instruction
117 # which (per SDM) *must* be a far JMP.
118 ljmpw $0,$0 # will be filled in by InternalAsmThunk16
119 L_Base: # to point here.
121 movw %si, %ss # set up 16-bit stack segment
122 xchgl %ebx, %esp # set up 16-bit stack pointer
124 movw IA32_REGS_SIZE(%esp), %bp # get BackToUserCode address from stack
125 mov %dx, %cs:(SavedSs - ASM_PFX(BackFromUserCode))(%bp)
126 mov %ebx, %cs:(SavedEsp - ASM_PFX(BackFromUserCode))(%bp)
127 lidtl %cs:(_16Idtr - ASM_PFX(BackFromUserCode))(%bp)
134 lretl # transfer control to user code
136 _NullSegDesc: .quad 0
142 .byte 0x8f # 16-bit segment, 4GB limit
149 .byte 0x8f # 16-bit segment, 4GB limit
155 # @param RegSet The pointer to a IA32_DWORD_REGS structure
156 # @param Transition The pointer to the transition code
157 # @return The address of the 16-bit stack after returning from user code
159 ASM_PFX(InternalAsmThunk16):
168 movl 36(%esp), %esi # esi <- RegSet
169 movzwl _SS(%esi), %edx
171 add $(-(IA32_REGS_SIZE + 4)), %edi
172 movl %edi, %ebx # ebx <- stack offset
173 imul $0x10, %edx, %eax
174 push $(IA32_REGS_SIZE / 4)
175 addl %eax, %edi # edi <- linear address of 16-bit stack
179 movl 40(%esp), %eax # eax <- address of transition code
180 movl %edx, %esi # esi <- 16-bit stack segment
181 lea (SavedCr0 - ASM_PFX(m16Start))(%eax), %edx
185 lea (ASM_PFX(BackFromUserCode) - ASM_PFX(m16Start))(%ecx), %ecx
187 stosl # [edi] <- return address of user code
188 addl $(L_Base - ASM_PFX(BackFromUserCode)), %eax
189 movl %eax, (L_Base - SavedCr0 - 4)(%edx)
190 sgdtl (SavedGdt - SavedCr0)(%edx)
193 movl %eax, (%edx) # save CR0 in SavedCr0
194 andl $0x7ffffffe, %eax # clear PE, PG bits
196 mov %ebp, (SavedCr4 - SavedCr0)(%edx)
197 andl $0xffffffcf, %ebp # clear PAE, PSE bits
199 pop %ecx # ecx <- selector for data segments
200 lgdtl (_16Gdtr - SavedCr0)(%edx)
202 lcall *(_EntryPoint - SavedCr0)(%edx)
205 lea -IA32_REGS_SIZE(%ebp), %eax
218 ASM_PFX(m16Size): .word ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start)
219 ASM_PFX(mThunk16Attr): .word ASM_PFX(ThunkAttr) - ASM_PFX(m16Start)
220 ASM_PFX(m16Gdt): .word _NullSegDesc - ASM_PFX(m16Start)
221 ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start)
222 ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start)