From 1760cf81e4b1847c6823ea3514a78dd120e19b6e Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 22 Dec 2016 15:57:14 +0800 Subject: MdePkg: Move to new location Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- Core/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm | 263 ++++++++++++++++++++++++++ 1 file changed, 263 insertions(+) create mode 100644 Core/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm (limited to 'Core/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm') diff --git a/Core/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm b/Core/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm new file mode 100644 index 0000000000..794d83159a --- /dev/null +++ b/Core/MdePkg/Library/BaseLib/Ia32/Thunk16.nasm @@ -0,0 +1,263 @@ + +#include "BaseLibInternals.h" + +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.
+; This program and the accompanying materials +; are licensed and made available under the terms and conditions of the BSD License +; which accompanies this distribution. The full text of the license may be found at +; http://opensource.org/licenses/bsd-license.php. +; +; THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +; WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +; +; Module Name: +; +; Thunk.asm +; +; Abstract: +; +; Real mode thunk +; +;------------------------------------------------------------------------------ + +global ASM_PFX(m16Size) +global ASM_PFX(mThunk16Attr) +global ASM_PFX(m16Gdt) +global ASM_PFX(m16GdtrBase) +global ASM_PFX(mTransition) +global ASM_PFX(m16Start) + +struc IA32_REGS + + ._EDI: resd 1 + ._ESI: resd 1 + ._EBP: resd 1 + ._ESP: resd 1 + ._EBX: resd 1 + ._EDX: resd 1 + ._ECX: resd 1 + ._EAX: resd 1 + ._DS: resw 1 + ._ES: resw 1 + ._FS: resw 1 + ._GS: resw 1 + ._EFLAGS: resd 1 + ._EIP: resd 1 + ._CS: resw 1 + ._SS: resw 1 + .size: + +endstruc + +;; .const + +SECTION .data + +; +; These are global constant to convey information to C code. +; +ASM_PFX(m16Size) DW ASM_PFX(InternalAsmThunk16) - ASM_PFX(m16Start) +ASM_PFX(mThunk16Attr) DW _BackFromUserCode.ThunkAttrEnd - 4 - ASM_PFX(m16Start) +ASM_PFX(m16Gdt) DW _NullSegDesc - ASM_PFX(m16Start) +ASM_PFX(m16GdtrBase) DW _16GdtrBase - ASM_PFX(m16Start) +ASM_PFX(mTransition) DW _EntryPoint - ASM_PFX(m16Start) + +SECTION .text + +ASM_PFX(m16Start): + +SavedGdt: + dw 0 + dd 0 + +;------------------------------------------------------------------------------ +; _BackFromUserCode() takes control in real mode after 'retf' has been executed +; by user code. It will be shadowed to somewhere in memory below 1MB. +;------------------------------------------------------------------------------ +_BackFromUserCode: + ; + ; The order of saved registers on the stack matches the order they appears + ; in IA32_REGS structure. This facilitates wrapper function to extract them + ; into that structure. + ; +BITS 16 + push ss + push cs + ; + ; Note: We can't use o32 on the next instruction because of a bug + ; in NASM 2.09.04 through 2.10rc1. + ; + call dword .Base ; push eip +.Base: + pushfd + cli ; disable interrupts + push gs + push fs + push es + push ds + pushad + mov edx, strict dword 0 +.ThunkAttrEnd: + test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_INT_15 + jz .1 + mov ax, 2401h + int 15h + cli ; disable interrupts + jnc .2 +.1: + test dl, THUNK_ATTRIBUTE_DISABLE_A20_MASK_KBD_CTRL + jz .2 + in al, 92h + or al, 2 + out 92h, al ; deactivate A20M# +.2: + xor eax, eax + mov ax, ss + lea ebp, [esp + IA32_REGS.size] + mov [bp - IA32_REGS.size + IA32_REGS._ESP], ebp + mov bx, [bp - IA32_REGS.size + IA32_REGS._EIP] + shl eax, 4 ; shl eax, 4 + add ebp, eax ; add ebp, eax + mov eax, strict dword 0 +.SavedCr4End: + mov cr4, eax +o32 lgdt [cs:bx + (SavedGdt - .Base)] + mov eax, strict dword 0 +.SavedCr0End: + mov cr0, eax + mov ax, strict word 0 +.SavedSsEnd: + mov ss, eax + mov esp, strict dword 0 +.SavedEspEnd: +o32 retf ; return to protected mode + +_EntryPoint: + DD _ToUserCode - ASM_PFX(m16Start) + DW 8h +_16Idtr: + DW (1 << 10) - 1 + DD 0 +_16Gdtr: + DW GdtEnd - _NullSegDesc - 1 +_16GdtrBase: + DD 0 + +;------------------------------------------------------------------------------ +; _ToUserCode() takes control in real mode before passing control to user code. +; It will be shadowed to somewhere in memory below 1MB. +;------------------------------------------------------------------------------ +_ToUserCode: +BITS 16 + mov dx, ss + mov ss, cx ; set new segment selectors + mov ds, cx + mov es, cx + mov fs, cx + mov gs, cx + mov cr0, eax ; real mode starts at next instruction + ; which (per SDM) *must* be a far JMP. + jmp 0:strict word 0 +.RealAddrEnd: + mov cr4, ebp + mov ss, si ; set up 16-bit stack segment + xchg esp, ebx ; set up 16-bit stack pointer + mov bp, [esp + IA32_REGS.size] + mov [cs:bp + (_BackFromUserCode.SavedSsEnd - 2 - _BackFromUserCode)], dx + mov [cs:bp + (_BackFromUserCode.SavedEspEnd - 4 - _BackFromUserCode)], ebx + lidt [cs:bp + (_16Idtr - _BackFromUserCode)] + + popad + pop ds + pop es + pop fs + pop gs + popfd + +o32 retf ; transfer control to user code + +ALIGN 16 +_NullSegDesc DQ 0 +_16CsDesc: + DW -1 + DW 0 + DB 0 + DB 9bh + DB 8fh ; 16-bit segment, 4GB limit + DB 0 +_16DsDesc: + DW -1 + DW 0 + DB 0 + DB 93h + DB 8fh ; 16-bit segment, 4GB limit + DB 0 +GdtEnd: + +;------------------------------------------------------------------------------ +; IA32_REGISTER_SET * +; EFIAPI +; InternalAsmThunk16 ( +; IN IA32_REGISTER_SET *RegisterSet, +; IN OUT VOID *Transition +; ); +;------------------------------------------------------------------------------ +global ASM_PFX(InternalAsmThunk16) +ASM_PFX(InternalAsmThunk16): +BITS 32 + push ebp + push ebx + push esi + push edi + push ds + push es + push fs + push gs + mov esi, [esp + 36] ; esi <- RegSet, the 1st parameter + movzx edx, word [esi + IA32_REGS._SS] + mov edi, [esi + IA32_REGS._ESP] + add edi, - (IA32_REGS.size + 4) ; reserve stack space + mov ebx, edi ; ebx <- stack offset + imul eax, edx, 16 ; eax <- edx * 16 + push IA32_REGS.size / 4 + add edi, eax ; edi <- linear address of 16-bit stack + pop ecx + rep movsd ; copy RegSet + mov eax, [esp + 40] ; eax <- address of transition code + mov esi, edx ; esi <- 16-bit stack segment + lea edx, [eax + (_BackFromUserCode.SavedCr0End - ASM_PFX(m16Start))] + mov ecx, eax + and ecx, 0fh + shl eax, 12 + lea ecx, [ecx + (_BackFromUserCode - ASM_PFX(m16Start))] + mov ax, cx + stosd ; [edi] <- return address of user code + add eax, _ToUserCode.RealAddrEnd - _BackFromUserCode + mov [edx + (_ToUserCode.RealAddrEnd - 4 - _BackFromUserCode.SavedCr0End)], eax + sgdt [edx + (SavedGdt - _BackFromUserCode.SavedCr0End)] + sidt [esp + 36] ; save IDT stack in argument space + mov eax, cr0 + mov [edx - 4], eax ; save CR0 in _BackFromUserCode.SavedCr0End - 4 + and eax, 7ffffffeh ; clear PE, PG bits + mov ebp, cr4 + mov [edx + (_BackFromUserCode.SavedCr4End - 4 - _BackFromUserCode.SavedCr0End)], ebp + and ebp, ~30h ; clear PAE, PSE bits + push 10h + pop ecx ; ecx <- selector for data segments + lgdt [edx + (_16Gdtr - _BackFromUserCode.SavedCr0End)] + pushfd ; Save df/if indeed + call dword far [edx + (_EntryPoint - _BackFromUserCode.SavedCr0End)] + popfd + lidt [esp + 36] ; restore protected mode IDTR + lea eax, [ebp - IA32_REGS.size] ; eax <- the address of IA32_REGS + pop gs + pop fs + pop es + pop ds + pop edi + pop esi + pop ebx + pop ebp + ret -- cgit v1.2.3