summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-11-20 18:51:54 -0800
committerH. Peter Anvin <hpa@zytor.com>2007-11-20 18:51:54 -0800
commit033b7497db0d920bdc9f776ef3a65a7b65723ff0 (patch)
tree4406117dcc52d863b53c79cd3d41fa395cc79c50
parent0188c20b01e4c5702108390eae6ea60a0af0a8e5 (diff)
downloadsyslinux-033b7497db0d920bdc9f776ef3a65a7b65723ff0.tar.gz
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.
-rw-r--r--com32.inc64
-rw-r--r--com32/include/com32.h5
-rw-r--r--com32/lib/Makefile2
-rw-r--r--com32/lib/sys/entry.S10
-rw-r--r--comboot.doc9
5 files changed, 78 insertions, 12 deletions
diff --git a/com32.inc b/com32.inc
index c4a1faa2..47f104b4 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 264f6091..7e618977 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 991d5882..1cde067d 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 be42c8b2..c959c091 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 3c806c3b..2939f9b7 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 +++