+++ /dev/null
-#------------------------------------------------------------------------------\r
-#\r
-# Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>\r
-# This program and the accompanying materials\r
-# are licensed and made available under the terms and conditions of the BSD License\r
-# which accompanies this distribution. The full text of the license may be found at\r
-# http://opensource.org/licenses/bsd-license.php.\r
-#\r
-# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-#\r
-# Module Name:\r
-#\r
-# Thunk16.S\r
-#\r
-# Abstract:\r
-#\r
-# Real mode thunk\r
-#\r
-#------------------------------------------------------------------------------\r
-\r
-#include <Library/BaseLib.h>\r
-\r
-ASM_GLOBAL ASM_PFX(m16Start), ASM_PFX(m16Size), ASM_PFX(mThunk16Attr), ASM_PFX(m16Gdt), ASM_PFX(m16GdtrBase), ASM_PFX(mTransition)\r
-ASM_GLOBAL ASM_PFX(InternalAsmThunk16)\r
-\r
-# define the structure of IA32_REGS\r
-.set _EDI, 0 #size 4\r
-.set _ESI, 4 #size 4\r
-.set _EBP, 8 #size 4\r
-.set _ESP, 12 #size 4\r
-.set _EBX, 16 #size 4\r
-.set _EDX, 20 #size 4\r
-.set _ECX, 24 #size 4\r
-.set _EAX, 28 #size 4\r
-.set _DS, 32 #size 2\r
-.set _ES, 34 #size 2\r
-.set _FS, 36 #size 2\r
-.set _GS, 38 #size 2\r
-.set _EFLAGS, 40 #size 4\r
-.set _EIP, 44 #size 4\r
-.set _CS, 48 #size 2\r
-.set _SS, 50 #size 2\r
-.set IA32_REGS_SIZE, 52\r
-\r
- .text\r
- .code16\r
-\r
-ASM_PFX(m16Start):\r
-\r
-SavedGdt: .space 6\r
-\r
-ASM_PFX(BackFromUserCode):\r
- push %ss\r
- push %cs\r
-\r
- calll L_Base1 # push eip\r
-L_Base1:\r
- pushfl\r
- cli # disable interrupts\r
- push %gs\r
- push %fs\r
- push %es\r
- push %ds\r
- pushal\r
- .byte 0x66, 0xba # mov edx, imm32\r
-ASM_PFX(ThunkAttr): .space 4\r
- testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15, %dl\r
- jz 1f\r
- movw $0x2401, %ax\r
- int $0x15\r
- cli # disable interrupts\r
- jnc 2f\r
-1:\r
- testb $THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL, %dl\r
- jz 2f\r
- inb $0x92, %al\r
- orb $2, %al\r
- outb %al, $0x92 # deactivate A20M#\r
-2:\r
- xorl %eax, %eax\r
- movw %ss, %ax\r
- leal IA32_REGS_SIZE(%esp), %ebp\r
- mov %ebp, (_ESP - IA32_REGS_SIZE)(%bp)\r
- mov (_EIP - IA32_REGS_SIZE)(%bp), %bx\r
- shll $4, %eax\r
- addl %eax, %ebp\r
- .byte 0x66, 0xb8 # mov eax, imm32\r
-SavedCr4: .space 4\r
- movl %eax, %cr4\r
- lgdtl %cs:(SavedGdt - L_Base1)(%bx)\r
- .byte 0x66, 0xb8 # mov eax, imm32\r
-SavedCr0: .space 4\r
- movl %eax, %cr0\r
- .byte 0xb8 # mov ax, imm16\r
-SavedSs: .space 2\r
- movl %eax, %ss\r
- .byte 0x66, 0xbc # mov esp, imm32\r
-SavedEsp: .space 4\r
- lretl # return to protected mode\r
-\r
-_EntryPoint: .long ASM_PFX(ToUserCode) - ASM_PFX(m16Start)\r
- .word 0x8\r
-_16Idtr: .word 0x3ff\r
- .long 0\r
-_16Gdtr: .word GdtEnd - _NullSegDesc - 1\r
-_16GdtrBase: .long _NullSegDesc\r
-\r
-ASM_PFX(ToUserCode):\r
- movw %ss, %dx\r
- movw %cx, %ss # set new segment selectors\r
- movw %cx, %ds\r
- movw %cx, %es\r
- movw %cx, %fs\r
- movw %cx, %gs\r
- movl %eax, %cr0 # real mode starts at next instruction\r
- # which (per SDM) *must* be a far JMP.\r
- ljmpw $0,$0 # will be filled in by InternalAsmThunk16\r
-L_Base: # to point here.\r
- movl %ebp, %cr4\r
- movw %si, %ss # set up 16-bit stack segment\r
- xchgl %ebx, %esp # set up 16-bit stack pointer\r
-\r
- movw IA32_REGS_SIZE(%esp), %bp # get BackToUserCode address from stack\r
- mov %dx, %cs:(SavedSs - ASM_PFX(BackFromUserCode))(%bp)\r
- mov %ebx, %cs:(SavedEsp - ASM_PFX(BackFromUserCode))(%bp)\r
- lidtl %cs:(_16Idtr - ASM_PFX(BackFromUserCode))(%bp)\r
- popal\r
- pop %ds\r
- pop %es\r
- pop %fs\r
- pop %gs\r
- popfl\r
- lretl # transfer control to user code\r
-\r
-_NullSegDesc: .quad 0\r
-_16CsDesc:\r
- .word -1\r
- .word 0\r
- .byte 0\r
- .byte 0x9b\r
- .byte 0x8f # 16-bit segment, 4GB limit\r
- .byte 0\r
-_16DsDesc:\r
- .word -1\r
- .word 0\r
- .byte 0\r
- .byte 0x93\r
- .byte 0x8f # 16-bit segment, 4GB limit\r
- .byte 0\r
-GdtEnd:\r
-\r
- .code32\r
-#\r
-# @param RegSet The pointer to a IA32_DWORD_REGS structure\r
-# @param Transition The pointer to the transition code\r
-# @return The address of the 16-bit stack after returning from user code\r
-#\r
-ASM_PFX(InternalAsmThunk16):\r
- push %ebp\r
- push %ebx\r
- push %esi\r
- push %edi\r
- push %ds\r
- push %es\r
- push %fs\r
- push %gs\r
- movl 36(%esp), %esi # esi <- RegSet\r
- movzwl _SS(%esi), %edx\r
- mov _ESP(%esi), %edi\r
- add $(-(IA32_REGS_SIZE + 4)), %edi\r
- movl %edi, %ebx # ebx <- stack offset\r
- imul $0x10, %edx, %eax\r
- push $(IA32_REGS_SIZE / 4)\r
- addl %eax, %edi # edi <- linear address of 16-bit stack\r
- pop %ecx\r
- rep\r
- movsl # copy RegSet\r
- movl 40(%esp), %eax # eax <- address of transition code\r
- movl %edx, %esi # esi <- 16-bit stack segment\r
- lea (SavedCr0 - ASM_PFX(m16Start))(%eax), %edx\r
- movl %eax, %ecx\r
- andl $0xf, %ecx\r
- shll $12, %eax\r
- lea (ASM_PFX(BackFromUserCode) - ASM_PFX(m16Start))(%ecx), %ecx\r
- movw %cx, %ax\r
- stosl # [edi] <- return address of user code\r
- addl $(L_Base - ASM_PFX(BackFromUserCode)), %eax\r
- movl %eax, (L_Base - SavedCr0 - 4)(%edx)\r
- sgdtl (SavedGdt - SavedCr0)(%edx)\r
- sidtl 0x24(%esp)\r
- movl %cr0, %eax\r
- movl %eax, (%edx) # save CR0 in SavedCr0\r
- andl $0x7ffffffe, %eax # clear PE, PG bits\r
- movl %cr4, %ebp\r
- mov %ebp, (SavedCr4 - SavedCr0)(%edx)\r
- andl $0xffffffcf, %ebp # clear PAE, PSE bits\r
- pushl $0x10\r
- pop %ecx # ecx <- selector for data segments\r
- lgdtl (_16Gdtr - SavedCr0)(%edx)\r
- pushfl\r
- lcall *(_EntryPoint - SavedCr0)(%edx)\r
- popfl\r
- lidtl 0x24(%esp)\r
- lea -IA32_REGS_SIZE(%ebp), %eax\r
- pop %gs\r
- pop %fs\r
- pop %es\r
- pop %ds\r
- pop %edi\r
- pop %esi\r
- pop %ebx\r
- pop %ebp\r
- ret\r
-\r
- .const:\r
-\r
-ASM_PFX(m16Size): .word ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start)\r
-ASM_PFX(mThunk16Attr): .word ASM_PFX(ThunkAttr) - ASM_PFX(m16Start)\r
-ASM_PFX(m16Gdt): .word _NullSegDesc - ASM_PFX(m16Start)\r
-ASM_PFX(m16GdtrBase): .word _16GdtrBase - ASM_PFX(m16Start)\r
-ASM_PFX(mTransition): .word _EntryPoint - ASM_PFX(m16Start)\r