From 033b7497db0d920bdc9f776ef3a65a7b65723ff0 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 20 Nov 2007 18:51:54 -0800 Subject: [PATCH] Add support for thunking cdecl/stdcall-style real-mode code Add support for thunking cdecl/stdcall-style 16-bit functions which pass parameters on the stack. This is necessary in order to be able to call PnPBIOS functions without using the (rather scary) PM interface. --- com32.inc | 64 +++++++++++++++++++++++++++++++++++++++++++++++---- com32/include/com32.h | 5 +++- com32/lib/Makefile | 2 +- com32/lib/sys/entry.S | 10 ++++---- comboot.doc | 9 +++++++- 5 files changed, 78 insertions(+), 12 deletions(-) diff --git a/com32.inc b/com32.inc index c4a1faa..47f104b 100644 --- a/com32.inc +++ b/com32.inc @@ -1,6 +1,6 @@ ;; ----------------------------------------------------------------------- ;; -;; Copyright 1994-2006 H. Peter Anvin - All Rights Reserved +;; Copyright 1994-2007 H. Peter Anvin - All Rights Reserved ;; ;; 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 @@ -164,12 +164,13 @@ com32_call_start: ; Now everything is set up for interrupts... + push dword com32_cfarcall ; Cfarcall entry point push dword com32_farcall ; Farcall entry point push dword (1 << 16) ; 64K bounce buffer push dword (comboot_seg << 4) ; Bounce buffer address push dword com32_intcall ; Intcall entry point push dword command_line ; Command line pointer - push dword 5 ; Argument count + push dword 6 ; Argument count sti ; Interrupts OK now call pm_entry ; Run the program... ; ... on return, fall through to com32_exit ... @@ -232,7 +233,7 @@ com32_int_rm: jmp com32_enter_pm ; Go back to PM ; -; 16-bit system call handling code +; 16-bit intcall/farcall handling code ; com32_sys_rm: pop gs @@ -253,7 +254,18 @@ com32_sys_rm: push es push fs push gs - mov ebx,com32_sys_resume + mov ebx,com32_syscall.resume + jmp com32_enter_pm + +; +; 16-bit cfarcall handing code +; +com32_cfar_rm: + retf +.return: + mov sp,[cs:Com32SysSP] + mov [cs:RealModeEAX],eax + mov ebx,com32_cfarcall.resume jmp com32_enter_pm ; @@ -335,7 +347,7 @@ com32_syscall: ; 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.) -com32_sys_resume: +.resume: movzx esi,word [word RealModeSSSP] movzx eax,word [word RealModeSSSP+2] mov edi,[esp+12*4] ; Dest regs @@ -354,11 +366,53 @@ com32_sys_resume: 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. +; +com32_cfarcall: + pushfd + pushad + + cld + mov ecx,[esp+12*4] ; Size of stack frame + + movzx edi,word [word RealModeSSSP] + movzx ebx,word [word RealModeSSSP+2] + mov [word Com32SysSP],di + sub edi,ecx ; Allocate space for stack frame + and edi,~3 ; Round + sub edi,4*2 ; Return pointer, return value + mov [word RealModeSSSP],di + shl ebx,4 + add edi,ebx ; Create linear address + + mov eax,[esp+10*4] ; CS:IP + stosd ; Save to stack frame + mov eax,com32_cfar_rm.return ; Return seg:off + stosd + mov esi,[esp+11*4] ; Stack frame + mov eax,ecx ; Copy the stack frame + rep movsd + mov ecx,eax + and ecx,3 + rep movsb + + mov bx,com32_cfar_rm + jmp com32_enter_rm + +.resume: + popad + mov eax,[word RealModeEAX] + popfd + ret + bits 16 section .bss1 alignb 4 RealModeSSSP resd 1 ; Real-mode SS:SP +RealModeEAX resd 1 ; Real mode EAX PMESP resd 1 ; Protected-mode ESP Com32SysSP resw 1 ; SP saved during COM32 syscall diff --git a/com32/include/com32.h b/com32/include/com32.h index 264f609..7e61897 100644 --- a/com32/include/com32.h +++ b/com32/include/com32.h @@ -74,14 +74,17 @@ extern struct com32_sys_args { void *cs_bounce; uint32_t cs_bounce_size; void __cdecl (*cs_farcall)(uint32_t, const com32sys_t *, com32sys_t *); + int __cdecl (*cs_cfarcall)(uint32_t, const void *, uint32_t); } __com32; /* * System call wrapper functions */ void __intcall(uint8_t __i, const com32sys_t *__sr, com32sys_t *__dr); -void __farcall(uint16_t __es, uint16_t __eo, +void __farcall(uint16_t __cs, uint16_t __ip, const com32sys_t *__sr, com32sys_t *__dr); +int __cfarcall(uint16_t __cs, uint16_t __ip, + const void *__stack, uint32_t __stack_size); extern const com32sys_t __com32_zero_regs; /* diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 991d588..1cde067 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -24,7 +24,7 @@ LIBOBJS = \ libgcc/__muldi3.o libgcc/__udivmoddi4.o libgcc/__umoddi3.o \ libgcc/__divdi3.o libgcc/__moddi3.o \ \ - sys/intcall.o sys/farcall.o sys/zeroregs.o \ + sys/intcall.o sys/farcall.o sys/cfarcall.o sys/zeroregs.o \ sys/entry.o sys/exit.o sys/argv.o sys/times.o \ sys/fileinfo.o sys/opendev.o sys/read.o sys/write.o sys/ftell.o \ sys/close.o sys/open.o sys/fileread.o sys/fileclose.o \ diff --git a/com32/lib/sys/entry.S b/com32/lib/sys/entry.S index be42c8b..c959c09 100644 --- a/com32/lib/sys/entry.S +++ b/com32/lib/sys/entry.S @@ -1,6 +1,6 @@ # ----------------------------------------------------------------------- # -# Copyright 2003-2004 H. Peter Anvin - All Rights Reserved +# Copyright 2003-2007 H. Peter Anvin - All Rights Reserved # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation @@ -27,7 +27,9 @@ # COM32 start up code - must be linked first in the binary - +/* Number of arguments in our version of the entry structure */ +#define COM32_ARGS 6 + .section ".init","ax" .globl _start .type _start, @function @@ -49,7 +51,7 @@ _start: # Copy COM32 invocation parameters leal 4(%esp),%esi # Argument list movl $__com32,%edi - movl $5,%ecx + movl $COM32_ARGS,%ecx movl %esp,-4(%edi) # Save the initial stack ptr cmpl (%esi),%ecx jbe 1f @@ -87,4 +89,4 @@ _start: .globl __entry_esp __entry_esp: .space 4 .globl __com32 -__com32: .space 4*6 +__com32: .space 4*(COM32_ARGS+1) diff --git a/comboot.doc b/comboot.doc index 3c806c3..2939f9b 100644 --- a/comboot.doc +++ b/comboot.doc @@ -85,6 +85,7 @@ The following arguments are passed to the program on the stack: [ESP+16] dword Pointer to low memory bounce buffer [ESP+20] dword Size of low memory bounce buffer [ESP+24] dword Pointer to FAR call helper function (new in 2.05) + [ESP+28] dword Pointer to CDECL helper function (new in 3.xx) This corresponds to the following C prototype, available in the file com32/include/com32.h: @@ -95,7 +96,9 @@ int _start(unsigned int __nargs, void (*__intcall)(uint8_t, com32sys_t *, com32sys_t *), void *__bounce_ptr, unsigned int __bounce_len, - void (*__farcall)(uint32_t, uint16_t, com32sys_t *, com32sys_t *)); + void (*__farcall)(uint32_t, com32sys_t *, com32sys_t *), + int (*__cfarcall)(uint32_t, void *, size_t) + ); The intcall helper function can be used to issue BIOS or SYSLINUX API calls, and takes the interrupt number as first argument. The second @@ -138,6 +141,10 @@ The farcall helper function behaves similarly, but takes as its first argument the CS:IP (in the form (CS << 16) + IP) of procedure to be invoked via a FAR CALL. +The cfarcall helper function takes (CS << 16)+IP, a pointer to a stack +frame, a size of that stack frame, and returns the return value of EAX +(which may need to be appropriate truncated by the user.) + ++++ SYSLINUX API CALLS +++ -- 2.7.4