1 #------------------------------------------------------------------------------ 2 # 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 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 <EdkIIGlueBase.h> 23 24 .globl ASM_PFX(m16Start), ASM_PFX(m16Size), ASM_PFX(mThunk16Attr), ASM_PFX(m16Gdt), ASM_PFX(m16GdtrBase), ASM_PFX(mTransition) 25 .globl ASM_PFX(InternalAsmThunk16) 26 27 ASM_PFX(m16Start): 28 29 SavedGdt: .space 6 30 31 ASM_PFX(BackFromUserCode): 32 push %ss 33 push %cs 34 .byte 0x66 35 call L_Base1 # push eip 36 L_Base1: 37 pushfw # pushfd actually 38 cli # disable interrupts 39 push %gs 40 push %fs 41 push %es 42 push %ds 43 pushaw # pushad actually 44 .byte 0x66, 0xba # mov edx, imm32 45 ASM_PFX(ThunkAttr): .space 4 46 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl 47 jz 1f 48 movl $0x15cd2401, %eax # mov ax, 2401h & int 15h 49 cli # disable interrupts 50 jnc 2f 51 1: 52 testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl 53 jz 2f 54 inb $0x92, %al 55 orb $2, %al 56 outb %al, $0x92 # deactivate A20M# 57 2: 58 xorw %ax, %ax # xor eax, eax 59 movl %ss, %eax # mov ax, ss 60 .byte 0x67, 0x66, 0x8d, 0x6c, 0x24, 0x34, 0x66 61 mov %ebp, 0xffffffd8(%esi) 62 mov 0xfffffff8(%esi), %ebx 63 shlw $4, %ax # shl eax, 4 64 addw %ax, %bp # add ebp, eax 65 .byte 0x66, 0xb8 # mov eax, imm32 66 SavedCr4: .space 4 67 movl %eax, %cr4 68 lgdtw %cs:0xfffffff2(%edi) 69 .byte 0x66, 0xb8 # mov eax, imm32 70 SavedCr0: .space 4 71 movl %eax, %cr0 72 .byte 0xb8 # mov ax, imm16 73 SavedSs: .space 2 74 movl %eax, %ss 75 .byte 0x66, 0xbc # mov esp, imm32 76 SavedEsp: .space 4 77 .byte 0x66 78 lret # return to protected mode 79 80 _EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start) 81 .word 0x8 82 _16Idtr: .word 0x3ff 83 .long 0 84 _16Gdtr: .word GdtEnd - _NullSegDesc - 1 85 _16GdtrBase: .long _NullSegDesc 86 87 ASM_PFX(ToUserCode): 88 movl %ss, %edx 89 movl %ecx, %ss # set new segment selectors 90 movl %ecx, %ds 91 movl %ecx, %es 92 movl %ecx, %fs 93 movl %ecx, %gs 94 movl %eax, %cr0 95 movl %ebp, %cr4 # real mode starts at next instruction 96 movl %esi, %ss # set up 16-bit stack segment 97 xchgw %bx, %sp # set up 16-bit stack pointer 98 .byte 0x66 99 call L_Base # push eip 100 L_Base: 101 popw %bp # ebp <- offset L_Base 102 .byte 0x67; # address size override 103 push 54(%esp) 104 lea 0xc(%esi), %eax 105 push %eax 106 lret 107 108 L_RealMode: 109 mov %edx, %cs:0xffffffc5(%esi) 110 mov %bx, %cs:0xffffffcb(%esi) 111 lidtw %cs:0xffffffd7(%esi) 112 popaw # popad actually 113 pop %ds 114 pop %es 115 pop %fs 116 pop %gs 117 popfw # popfd 118 lretw # transfer control to user code 119 120 _NullSegDesc: .quad 0 121 _16CsDesc: 122 .word -1 123 .word 0 124 .byte 0 125 .byte 0x9b 126 .byte 0x8f # 16-bit segment, 4GB limit 127 .byte 0 128 _16DsDesc: 129 .word -1 130 .word 0 131 .byte 0 132 .byte 0x93 133 .byte 0x8f # 16-bit segment, 4GB limit 134 .byte 0 135 GdtEnd: 136 137 # 138 # @param RegSet The pointer to a IA32_DWORD_REGS structure 139 # @param Transition The pointer to the transition code 140 # @return The address of the 16-bit stack after returning from user code 141 # 142 ASM_PFX(InternalAsmThunk16): 143 push %ebp 144 push %ebx 145 push %esi 146 push %edi 147 push %ds 148 push %es 149 push %fs 150 push %gs 151 movl 36(%esp), %esi # esi <- RegSet 152 movzwl 0x32(%esi), %edx 153 mov 0xc(%esi), %edi 154 add $0xffffffc8, %edi 155 movl %edi, %ebx # ebx <- stack offset 156 imul $0x10, %edx, %eax 157 push $0xd 158 addl %eax, %edi # edi <- linear address of 16-bit stack 159 pop %ecx 160 rep 161 movsl # copy RegSet 162 movl 40(%esp), %eax # eax <- address of transition code 163 movl %edx, %esi # esi <- 16-bit stack segment 164 lea 0x61(%eax), %edx 165 movl %eax, %ecx 166 andl $0xf, %ecx 167 shll $12, %eax 168 lea 0x6(%ecx), %ecx 169 movw %cx, %ax 170 stosl # [edi] <- return address of user code 171 sgdtl 0xffffff9f(%edx) 172 sidtl 0x24(%esp) 173 movl %cr0, %eax 174 movl %eax, (%edx) # save CR0 in SavedCr0 175 andl $0x7ffffffe, %eax # clear PE, PG bits 176 movl %cr4, %ebp 177 mov %ebp, 0xfffffff1(%edx) 178 andl $0x300, %ebp # clear all but PCE and OSFXSR bits 179 pushl $0x10 180 pop %ecx # ecx <- selector for data segments 181 lgdtl 0x20(%edx) 182 pushfl 183 lcall *0x14(%edx) 184 popfl 185 lidtl 0x24(%esp) 186 lea 0xffffffcc(%ebp), %eax 187 pop %gs 188 pop %fs 189 pop %es 190 pop %ds 191 pop %edi 192 pop %esi 193 pop %ebx 194 pop %ebp 195 ret 196 197 .const: 198 199 ASM_PFX(m16Size): .word ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start) 200 ASM_PFX(mThunk16Attr): .word ASM_PFX(ThunkAttr) - ASM_PFX(m16Start) 201 ASM_PFX(m16Gdt): .word _NullSegDesc - ASM_PFX(m16Start) 202 ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start) 203 ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start) 204