;***************************************************************************** ;* ;* Copyright (c) 2006 - 2011, 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 ;* ;***************************************************************************** .686p EXTERNDEF C mCode16Size:DWORD CONST SEGMENT FLAT "DATA" READONLY mCode16Size DD _TEXT16SIZE CONST ENDS _DATA SEGMENT FLAT "DATA" NullSegSel DQ 0 _16BitCsSel LABEL QWORD DW -1 DW 0 DB 0 DB 9bh DB 8fh ; 16-bit segment DB 0 _16BitSsSel LABEL QWORD DW -1 DW 0 DB 0 DB 93h DB 8fh ; 16-bit segment DB 0 _16Gdtr LABEL FWORD DW $ - offset NullSegSel - 1 DD offset NullSegSel _DATA ENDS _TEXT SEGMENT FLAT "CODE" PARA STACK_PARAM_SIZE EQU 16 IA32_REGS STRUC 4t _EDI DD ? _ESI DD ? _EBP DD ? _ESP DD ? _EBX DD ? _EDX DD ? _ECX DD ? _EAX DD ? _DS DW ? _ES DW ? _FS DW ? _GS DW ? _EFLAGS DD ? _EIP DD ? _CS DW ? _SS DW ? IA32_REGS ENDS _STK16 STRUC 1t RetEip DD ? RetCs DW ? ThunkFlags DW ? SavedEsp DD ? SavedSs DW ? SavedGdtr FWORD ? SavedCr0 DD ? SavedCr4 DD ? _STK16 ENDS ASSUME ds:_DATA __Thunk16 PROC USES ebp ebx esi edi ds es fs gs ASSUME esi:PTR IA32_REGS mov esi, [esp + 36] movzx edx, [esi]._SS mov edi, [esi]._ESP add edi, - sizeof (_STK16) - sizeof (IA32_REGS) push edi ; save stack offset imul eax, edx, 16 ; eax <- edx*16 add edi, eax ; edi <- linear address of 16-bit stack push sizeof (IA32_REGS) / 4 pop ecx rep movsd ; copy context to 16-bit stack ; copy eflags to stack frame mov eax, [esi - sizeof(IA32_REGS)]._EFLAGS mov [edi - sizeof(IA32_REGS) - STACK_PARAM_SIZE - 4], eax pop ebx ; ebx <- 16-bit stack offset mov eax, offset @F ; return offset stosd mov eax, cs ; return segment stosw mov eax, [esp + 40] ; THUNK flags stosw mov eax, esp stosd ; save esp mov eax, ss ; save ss stosw sgdt fword ptr [edi] ; save GDTR sidt fword ptr [esp + 36] ; save IDTR mov esi, cr0 mov [edi + 6], esi ; save CR0 and esi, NOT 80000001h ; esi <- CR0 to set mov eax, cr4 mov [edi + 10], eax ; save CR4 and al, NOT 30h ; clear PAE & PSE mov edi, edx ; edi <- 16-bit stack segment mov edx, [esp + 44] shl edx, 16 push edx pop edx mov dx, _16BitSsSel - NullSegSel lgdt _16Gdtr ; load 16-bit GDTR DB 0eah DD offset @16Bit DW _16BitCsSel - NullSegSel ; jmp far 8:@16Bit @16Bit: mov ss, dx mov cr0, esi ; disable protected mode mov cr4, eax ; disable PAE & PSE db 67h, 0FFh, 06Ch, 024h, 0FCh ; jmp dword ptr [esp-4] @@: xor eax, eax mov ax, ss shl eax, 4 add eax, esp ; eax <- address of 16-bit stack lss esp, fword ptr (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedEsp lidt fword ptr [esp + 36] ; restore IDTR ret __Thunk16 ENDP _TEXT ENDS _TEXT16 SEGMENT USE16 "CODE" PARA _Code16Addr PROC C _Code16Addr ENDP RealMode PROC mov ss, di ; set up stack mov esp, ebx lidt fword ptr cs:[_16Idtr - _Code16Addr] popad pop ds pop es pop fs pop gs sub esp, (sizeof(IA32_REGS) - 12) + STACK_PARAM_SIZE + 4 popfd test (_STK16 ptr [esp + STACK_PARAM_SIZE + sizeof(IA32_REGS)]).ThunkFlags, 1 jz @F pushf ; push Flags when it's INT# @@: push cs ; push @FarCallRet - _Code16Addr DB 68h ; push /iw DW @FarCallRet - _Code16Addr jz @F jmp fword ptr [esp + 6 + STACK_PARAM_SIZE + sizeof(IA32_REGS) - 8] @@: jmp fword ptr [esp + 4 + STACK_PARAM_SIZE + sizeof(IA32_REGS) - 8] @FarCallRet: add esp, (sizeof(IA32_REGS) - 12) + STACK_PARAM_SIZE + 4 pushfd push gs push fs push es push ds pushad cli DB 66h lgdt (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedGdtr mov eax, (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedCr4 mov cr4, eax mov eax, (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedCr0 mov cr0, eax ; restore CR0 jmp fword ptr (_STK16 ptr [esp + sizeof (IA32_REGS)]).RetEip RealMode ENDP _16Idtr FWORD (1 SHL 10) - 1 _TEXT16END: _TEXT16SIZE = _TEXT16END - _Code16Addr _TEXT16 ENDS END