diff options
Diffstat (limited to 'contrib/syslinux-4.02/core/callback.inc')
-rw-r--r-- | contrib/syslinux-4.02/core/callback.inc | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/contrib/syslinux-4.02/core/callback.inc b/contrib/syslinux-4.02/core/callback.inc new file mode 100644 index 0000000..d98d800 --- /dev/null +++ b/contrib/syslinux-4.02/core/callback.inc @@ -0,0 +1,215 @@ +;; ----------------------------------------------------------------------- +;; +;; Copyright 1994-2009 H. Peter Anvin - All Rights Reserved +;; Copyright 2009 Intel Corporation; author: H. Peter Anvin +;; +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, Inc., 53 Temple Place Ste 330, +;; Boston MA 02111-1307, USA; either version 2 of the License, or +;; (at your option) any later version; incorporated herein by reference. +;; +;; ----------------------------------------------------------------------- + +;; +;; callback.inc +;; +;; Callbacks from 32-bit mode to 16-bit mode +;; + +; +; 16-bit intcall/farcall handling code +; + +; +; 32-bit support code +; + bits 32 + section .text + +; +; Intcall/farcall invocation. We manifest a structure on the real-mode stack, +; containing the com32sys_t structure from <com32.h> as well as +; the following entries (from low to high address): +; - Target offset +; - Target segment +; - Return offset +; - Return segment (== real mode cs == 0) +; - Return flags +; + global core_farcall +core_farcall: + mov eax,[esp+1*4] ; CS:IP + jmp core_syscall + + global core_intcall +core_intcall: + movzx eax,byte [esp+1*4] ; INT number + mov eax,[eax*4] ; Get CS:IP from low memory + +core_syscall: + pushfd ; Save IF among other things... + push ebx + push ebp + push esi + push edi + push dword [CallbackSP] + + cld + + movzx edi,word [word RealModeSSSP] + movzx ebx,word [word RealModeSSSP+2] + sub edi,54 ; Allocate 54 bytes + mov [word RealModeSSSP],di + shl ebx,4 + add edi,ebx ; Create linear address + + mov esi,[esp+8*4] ; Source regs + xor ecx,ecx + mov cl,11 ; 44 bytes to copy + rep movsd + + ; EAX is already set up to be CS:IP + stosd ; Save in stack frame + mov eax,.rm_return ; Return seg:offs + stosd ; Save in stack frame + mov eax,[edi-12] ; Return flags + and eax,0x200ed7 ; Mask (potentially) unsafe flags + mov [edi-12],eax ; Primary flags entry + stosw ; Return flags + + mov bx,.rm + jmp enter_rm ; Go to real mode + + bits 16 + section .text16 +.rm: + mov ax,sp + add ax,9*4+4*2 + mov [CallbackSP],ax + pop gs + pop fs + pop es + pop ds + popad + popfd + retf ; Invoke routine + +.rm_return: + ; We clean up SP here because we don't know if the + ; routine returned with RET, RETF or IRET + mov sp,[cs:CallbackSP] + pushfd + pushad + push ds + push es + push fs + push gs + mov ebx,.pm_return + jmp enter_pm + + ; On return, the 44-byte return structure is on the + ; real-mode stack, plus the 10 additional bytes used + ; by the target address (see above.) + bits 32 + section .text +.pm_return: + movzx esi,word [word RealModeSSSP] + movzx eax,word [word RealModeSSSP+2] + mov edi,[esp+9*4] ; Dest regs + shl eax,4 + add esi,eax ; Create linear address + and edi,edi ; NULL pointer? + jnz .do_copy +.no_copy: mov edi,esi ; Do a dummy copy-to-self +.do_copy: xor ecx,ecx + mov cl,11 ; 44 bytes + rep movsd ; Copy register block + + add dword [word RealModeSSSP],54 + ; Remove from stack + + pop dword [CallbackSP] + pop edi + pop esi + pop ebp + pop ebx + popfd + ret ; Return to 32-bit program + +; +; Cfarcall invocation. We copy the stack frame to the real-mode stack, +; followed by the return CS:IP and the CS:IP of the target function. +; The value of IF is copied from the calling routine. +; + global core_cfarcall +core_cfarcall: + pushfd ; Save IF among other things... + push ebx + push ebp + push esi + push edi + push dword [CallbackSP] + + cld + mov ecx,[esp+9*4] ; Size of stack frame + + movzx edi,word [word RealModeSSSP] + movzx ebx,word [word RealModeSSSP+2] + mov [word CallbackSP],di + sub edi,ecx ; Allocate space for stack frame + and edi,~3 ; Round + sub edi,4*3 ; Return pointer, return value, EFLAGS + mov [word RealModeSSSP],di + shl ebx,4 + add edi,ebx ; Create linear address + + mov eax,[esp+5*4] ; EFLAGS from entry + and eax,0x202 ; IF only + stosd + mov eax,[esp+7*4] ; CS:IP + stosd ; Save to stack frame + mov eax,.rm_return ; Return seg:off + stosd + mov esi,[esp+8*4] ; Stack frame + mov eax,ecx ; Copy the stack frame + shr ecx,2 + rep movsd + mov ecx,eax + and ecx,3 + rep movsb + + mov bx,.rm + jmp enter_rm + + bits 16 + section .text16 +.rm: + popfd + retf +.rm_return: + mov sp,[cs:CallbackSP] + mov esi,eax + mov ebx,.pm_return + jmp enter_pm + + bits 32 + section .text +.pm_return: + mov eax,esi + ; EDX already set up to be the RM return value + pop dword [CallbackSP] + pop ebx + pop ebp + pop esi + pop edi + popfd + ret + + bits 16 + section .bss16 + alignb 4 +CallbackSP resd 1 ; SP saved during callback + + bits 16 + section .text16 |