summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2016-04-14 17:48:41 +0200
committerMichael Brown2016-04-15 16:31:36 +0200
commit5e5450c2d04e6f976ea4cef5db50e136d4a06282 (patch)
tree21a059921d77d68d0508f984a0667d84c1666e12
parent[pool] Fix check for reopenable pooled connections (diff)
downloadipxe-5e5450c2d04e6f976ea4cef5db50e136d4a06282.tar.gz
ipxe-5e5450c2d04e6f976ea4cef5db50e136d4a06282.tar.xz
ipxe-5e5450c2d04e6f976ea4cef5db50e136d4a06282.zip
[comboot] Support COMBOOT in 64-bit builds
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/arch/i386/Makefile2
-rw-r--r--src/arch/x86/Makefile1
-rw-r--r--src/arch/x86/image/com32.c (renamed from src/arch/i386/image/com32.c)72
-rw-r--r--src/arch/x86/image/comboot.c (renamed from src/arch/i386/image/comboot.c)12
-rw-r--r--src/arch/x86/include/comboot.h (renamed from src/arch/i386/include/comboot.h)6
-rw-r--r--src/arch/x86/interface/syslinux/com32_call.c (renamed from src/arch/i386/interface/syslinux/com32_call.c)17
-rw-r--r--src/arch/x86/interface/syslinux/com32_wrapper.S (renamed from src/arch/i386/interface/syslinux/com32_wrapper.S)99
-rw-r--r--src/arch/x86/interface/syslinux/comboot_call.c (renamed from src/arch/i386/interface/syslinux/comboot_call.c)4
-rw-r--r--src/arch/x86/interface/syslinux/comboot_resolv.c (renamed from src/arch/i386/interface/syslinux/comboot_resolv.c)0
-rw-r--r--src/arch/x86/tests/comboot/shuffle-simple.asm (renamed from src/arch/i386/tests/comboot/shuffle-simple.asm)1
-rw-r--r--src/arch/x86/tests/comboot/version.asm (renamed from src/arch/i386/tests/comboot/version.asm)0
-rw-r--r--src/arch/x86/transitions/librm.S66
12 files changed, 179 insertions, 101 deletions
diff --git a/src/arch/i386/Makefile b/src/arch/i386/Makefile
index a5298604..fe3adc9c 100644
--- a/src/arch/i386/Makefile
+++ b/src/arch/i386/Makefile
@@ -83,9 +83,7 @@ endif
# i386-specific directories containing source files
#
SRCDIRS += arch/i386/core
-SRCDIRS += arch/i386/image
SRCDIRS += arch/i386/tests
-SRCDIRS += arch/i386/interface/syslinux
# Include common x86 Makefile
#
diff --git a/src/arch/x86/Makefile b/src/arch/x86/Makefile
index e933f4a4..368c29f6 100644
--- a/src/arch/x86/Makefile
+++ b/src/arch/x86/Makefile
@@ -16,6 +16,7 @@ SRCDIRS += arch/x86/interface/pxe
SRCDIRS += arch/x86/interface/pxeparent
SRCDIRS += arch/x86/interface/efi
SRCDIRS += arch/x86/interface/vmware
+SRCDIRS += arch/x86/interface/syslinux
SRCDIRS += arch/x86/prefix
SRCDIRS += arch/x86/hci/commands
SRCDIRS += arch/x86/drivers/xen
diff --git a/src/arch/i386/image/com32.c b/src/arch/x86/image/com32.c
index ff64fd1a..01665287 100644
--- a/src/arch/i386/image/com32.c
+++ b/src/arch/x86/image/com32.c
@@ -76,8 +76,6 @@ static int com32_exec_loop ( struct image *image ) {
assert ( avail_mem_top != 0 );
- com32_external_esp = phys_to_virt ( avail_mem_top );
-
/* Hook COMBOOT API interrupts */
hook_comboot_interrupts();
@@ -88,34 +86,44 @@ static int com32_exec_loop ( struct image *image ) {
*/
unregister_image ( image );
- __asm__ __volatile__ (
- "movl %%esp, (com32_internal_esp)\n\t" /* Save internal virtual address space ESP */
- "movl (com32_external_esp), %%esp\n\t" /* Switch to COM32 ESP (top of available memory) */
- "call _virt_to_phys\n\t" /* Switch to flat physical address space */
- "sti\n\t" /* Enable interrupts */
- "pushl %0\n\t" /* Pointer to CDECL helper function */
- "pushl %1\n\t" /* Pointer to FAR call helper function */
- "pushl %2\n\t" /* Size of low memory bounce buffer */
- "pushl %3\n\t" /* Pointer to low memory bounce buffer */
- "pushl %4\n\t" /* Pointer to INT call helper function */
- "pushl %5\n\t" /* Pointer to the command line arguments */
- "pushl $6\n\t" /* Number of additional arguments */
- "call *%6\n\t" /* Execute image */
- "cli\n\t" /* Disable interrupts */
- "call _phys_to_virt\n\t" /* Switch back to internal virtual address space */
- "movl (com32_internal_esp), %%esp\n\t" /* Switch back to internal stack */
- :
- :
- /* %0 */ "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
- /* %1 */ "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
- /* %2 */ "r" ( get_fbms() * 1024 - (COM32_BOUNCE_SEG << 4) ),
- /* %3 */ "i" ( COM32_BOUNCE_SEG << 4 ),
- /* %4 */ "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
- /* %5 */ "r" ( virt_to_phys ( image->cmdline ?
- image->cmdline : "" ) ),
- /* %6 */ "r" ( COM32_START_PHYS )
- :
- "memory" );
+ __asm__ __volatile__ ( PHYS_CODE (
+ /* Preserve registers */
+ "pushal\n\t"
+ /* Preserve stack pointer */
+ "subl $4, %k0\n\t"
+ "movl %%esp, (%k0)\n\t"
+ /* Switch to COM32 stack */
+ "movl %k0, %%esp\n\t"
+ /* Enable interrupts */
+ "sti\n\t"
+ /* Construct stack frame */
+ "pushl %k1\n\t"
+ "pushl %k2\n\t"
+ "pushl %k3\n\t"
+ "pushl %k4\n\t"
+ "pushl %k5\n\t"
+ "pushl %k6\n\t"
+ "pushl $6\n\t"
+ /* Call COM32 entry point */
+ "movl %k7, %k0\n\t"
+ "call *%k0\n\t"
+ /* Disable interrupts */
+ "cli\n\t"
+ /* Restore stack pointer */
+ "movl 24(%%esp), %%esp\n\t"
+ /* Restore registers */
+ "popal\n\t" )
+ :
+ : "r" ( avail_mem_top ),
+ "r" ( virt_to_phys ( com32_cfarcall_wrapper ) ),
+ "r" ( virt_to_phys ( com32_farcall_wrapper ) ),
+ "r" ( get_fbms() * 1024 - ( COM32_BOUNCE_SEG << 4 ) ),
+ "i" ( COM32_BOUNCE_SEG << 4 ),
+ "r" ( virt_to_phys ( com32_intcall_wrapper ) ),
+ "r" ( virt_to_phys ( image->cmdline ?
+ image->cmdline : "" ) ),
+ "i" ( COM32_START_PHYS )
+ : "memory" );
DBGC ( image, "COM32 %p: returned\n", image );
break;
@@ -147,7 +155,7 @@ static int com32_exec_loop ( struct image *image ) {
/**
* Check image name extension
- *
+ *
* @v image COM32 image
* @ret rc Return status code
*/
@@ -155,7 +163,7 @@ static int com32_identify ( struct image *image ) {
const char *ext;
static const uint8_t magic[] = { 0xB8, 0xFF, 0x4C, 0xCD, 0x21 };
uint8_t buf[5];
-
+
if ( image->len >= 5 ) {
/* Check for magic number
* mov eax,21cd4cffh
diff --git a/src/arch/i386/image/comboot.c b/src/arch/x86/image/comboot.c
index 20b5ae1e..9a847f0f 100644
--- a/src/arch/i386/image/comboot.c
+++ b/src/arch/x86/image/comboot.c
@@ -64,7 +64,7 @@ struct comboot_psp {
/**
* Copy command line to PSP
- *
+ *
* @v image COMBOOT image
*/
static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr ) {
@@ -97,7 +97,7 @@ static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr )
/**
* Initialize PSP
- *
+ *
* @v image COMBOOT image
* @v seg_userptr segment to initialize
*/
@@ -213,7 +213,7 @@ static int comboot_exec_loop ( struct image *image ) {
/**
* Check image name extension
- *
+ *
* @v image COMBOOT image
* @ret rc Return status code
*/
@@ -254,7 +254,7 @@ static int comboot_prepare_segment ( struct image *image )
seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
/* Allow etra 0x100 bytes before image for PSP */
- filesz = image->len + 0x100;
+ filesz = image->len + 0x100;
/* Ensure the entire 64k segment is free */
memsz = 0xFFFF;
@@ -289,7 +289,7 @@ static int comboot_probe ( struct image *image ) {
/* Check if this is a COMBOOT image */
if ( ( rc = comboot_identify ( image ) ) != 0 ) {
-
+
return rc;
}
@@ -304,7 +304,7 @@ static int comboot_probe ( struct image *image ) {
*/
static int comboot_exec ( struct image *image ) {
int rc;
-
+
/* Sanity check for filesize */
if( image->len >= 0xFF00 ) {
DBGC( image, "COMBOOT %p: image too large\n",
diff --git a/src/arch/i386/include/comboot.h b/src/arch/x86/include/comboot.h
index 5cb1ba54..69c6ef02 100644
--- a/src/arch/i386/include/comboot.h
+++ b/src/arch/x86/include/comboot.h
@@ -29,7 +29,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define COMBOOT_FEATURE_LOCAL_BOOT (1 << 0)
#define COMBOOT_FEATURE_IDLE_LOOP (1 << 1)
-/** Maximum number of shuffle descriptors for
+/** Maximum number of shuffle descriptors for
* shuffle and boot functions
* (INT 22h AX=0012h, 001Ah, 001Bh)
*/
@@ -102,7 +102,7 @@ typedef struct {
extern void hook_comboot_interrupts ( );
extern void unhook_comboot_interrupts ( );
-/* These are not the correct prototypes, but it doens't matter,
+/* These are not the correct prototypes, but it doens't matter,
* as we only ever get the address of these functions;
* they are only called from COM32 code running in PHYS_CODE
*/
@@ -116,8 +116,6 @@ extern int comboot_resolv ( const char *name, struct in_addr *address );
/* setjmp/longjmp context buffer used to return after loading an image */
extern rmjmp_buf comboot_return;
-extern void *com32_external_esp;
-
#define COMBOOT_EXIT 1
#define COMBOOT_EXIT_RUN_KERNEL 2
#define COMBOOT_EXIT_COMMAND 3
diff --git a/src/arch/i386/interface/syslinux/com32_call.c b/src/arch/x86/interface/syslinux/com32_call.c
index 75dcc238..19fdbaff 100644
--- a/src/arch/i386/interface/syslinux/com32_call.c
+++ b/src/arch/x86/interface/syslinux/com32_call.c
@@ -46,6 +46,9 @@ uint16_t __bss16 ( com32_saved_sp );
*/
void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
+ DBGC ( &com32_regs, "COM32 INT%x in %#08lx out %#08lx\n",
+ interrupt, inregs_phys, outregs_phys );
+
memcpy_user ( virt_to_user( &com32_regs ), 0,
phys_to_user ( inregs_phys ), 0,
sizeof(com32sys_t) );
@@ -76,7 +79,7 @@ void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physad
/* patch INT instruction */
"pushw %%ax\n\t"
"movb %%ss:(com32_int_vector), %%al\n\t"
- "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t"
+ "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t"
/* perform a jump to avoid problems with cache
* consistency in self-modifying code on some CPUs (486)
*/
@@ -106,7 +109,7 @@ void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physad
if ( outregs_phys ) {
memcpy_user ( phys_to_user ( outregs_phys ), 0,
- virt_to_user( &com32_regs ), 0,
+ virt_to_user( &com32_regs ), 0,
sizeof(com32sys_t) );
}
}
@@ -116,6 +119,9 @@ void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physad
*/
void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
+ DBGC ( &com32_regs, "COM32 farcall %04x:%04x in %#08lx out %#08lx\n",
+ ( proc >> 16 ), ( proc & 0xffff ), inregs_phys, outregs_phys );
+
memcpy_user ( virt_to_user( &com32_regs ), 0,
phys_to_user ( inregs_phys ), 0,
sizeof(com32sys_t) );
@@ -165,7 +171,7 @@ void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t
if ( outregs_phys ) {
memcpy_user ( phys_to_user ( outregs_phys ), 0,
- virt_to_user( &com32_regs ), 0,
+ virt_to_user( &com32_regs ), 0,
sizeof(com32sys_t) );
}
}
@@ -176,13 +182,16 @@ void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t
int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
int32_t eax;
+ DBGC ( &com32_regs, "COM32 cfarcall %04x:%04x params %#08lx+%#zx\n",
+ ( proc >> 16 ), ( proc & 0xffff ), stack, stacksz );
+
copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz );
com32_farcall_proc = proc;
__asm__ __volatile__ (
REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" )
: "=a" (eax)
- :
+ :
: "ecx", "edx" );
remove_user_from_rm_stack ( 0, stacksz );
diff --git a/src/arch/i386/interface/syslinux/com32_wrapper.S b/src/arch/x86/interface/syslinux/com32_wrapper.S
index c9d1452b..d59a3392 100644
--- a/src/arch/i386/interface/syslinux/com32_wrapper.S
+++ b/src/arch/x86/interface/syslinux/com32_wrapper.S
@@ -19,79 +19,82 @@
FILE_LICENCE ( GPL2_OR_LATER )
+#include "librm.h"
+
.text
- .arch i386
- .code32
+ .code32
.globl com32_farcall_wrapper
com32_farcall_wrapper:
+ movl $VIRTUAL(com32_farcall), %eax
+ jmp com32_wrapper
- movl $com32_farcall, %eax
- jmp com32_wrapper
-
-
+ .code32
.globl com32_cfarcall_wrapper
com32_cfarcall_wrapper:
+ movl $VIRTUAL(com32_cfarcall), %eax
+ jmp com32_wrapper
- movl $com32_cfarcall, %eax
- jmp com32_wrapper
-
-
+ .code32
.globl com32_intcall_wrapper
com32_intcall_wrapper:
+ movl $VIRTUAL(com32_intcall), %eax
+ /* fall through */
- movl $com32_intcall, %eax
- /*jmp com32_wrapper*/ /* fall through */
-
+ .code32
com32_wrapper:
+
+ /* Disable interrupts */
cli
/* Switch to internal virtual address space */
- call _phys_to_virt
-
- mov %eax, (com32_helper_function)
+ call _phys_to_virt
- /* Save external COM32 stack pointer */
- movl %esp, (com32_external_esp)
+#ifdef __x86_64__
- /* Copy arguments to caller-save registers */
- movl 12(%esp), %eax
- movl 8(%esp), %ecx
- movl 4(%esp), %edx
+ .code64
- /* Switch to internal stack */
- movl (com32_internal_esp), %esp
+ /* Preserve registers which are callee-save for COM32 (i386 API) */
+ pushq %rdi
+ pushq %rsi
+ pushq %rbp
- /* Copy arguments to internal stack */
- pushl %eax
- pushl %ecx
- pushl %edx
+ /* Extract parameters from stack */
+ movl 28(%rsp), %edi
+ movl 32(%rsp), %esi
+ movl 36(%rsp), %edx
- call *(com32_helper_function)
+ /* Align stack pointer */
+ movq %rsp, %rbp
+ andq $~0x07, %rsp
- /* Clean up stack */
- addl $12, %esp
+ /* Call helper function */
+ movslq %eax, %rax
+ call *%rax
- /* Save internal stack pointer and restore external stack pointer */
- movl %esp, (com32_internal_esp)
- movl (com32_external_esp), %esp
+ /* Restore stack pointer */
+ movq %rbp, %rsp
- /* Switch to external flat physical address space */
- call _virt_to_phys
-
- sti
- ret
+ /* Restore registers */
+ popq %rbp
+ popq %rsi
+ popq %rdi
+#else /* _x86_64 */
- .data
+ /* Call helper function */
+ pushl 12(%esp)
+ pushl 12(%esp)
+ pushl 12(%esp)
+ call *%eax
+ addl $12, %esp
-/* Internal iPXE virtual address space %esp */
-.globl com32_internal_esp
-.lcomm com32_internal_esp, 4
+#endif /* _x86_64 */
-/* External flat physical address space %esp */
-.globl com32_external_esp
-.lcomm com32_external_esp, 4
+ /* Switch to external flat physical address space */
+ call _virt_to_phys
+ .code32
-/* Function pointer of helper to call */
-.lcomm com32_helper_function, 4
+ /* Reenable interrupts and return */
+ sti
+ ret
diff --git a/src/arch/i386/interface/syslinux/comboot_call.c b/src/arch/x86/interface/syslinux/comboot_call.c
index 56597781..2f5c252c 100644
--- a/src/arch/i386/interface/syslinux/comboot_call.c
+++ b/src/arch/x86/interface/syslinux/comboot_call.c
@@ -489,7 +489,7 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
struct in_addr addr;
copy_from_user ( hostname, hostname_u, 0, len + 1 );
-
+
/* TODO:
* "If the hostname does not contain a dot (.), the
* local domain name is automatically appended."
@@ -519,7 +519,7 @@ static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
/* Jump to real-mode entry point */
__asm__ __volatile__ (
- REAL_CODE (
+ REAL_CODE (
"pushw %0\n\t"
"popw %%ds\n\t"
"pushl %1\n\t"
diff --git a/src/arch/i386/interface/syslinux/comboot_resolv.c b/src/arch/x86/interface/syslinux/comboot_resolv.c
index 03bbfd04..03bbfd04 100644
--- a/src/arch/i386/interface/syslinux/comboot_resolv.c
+++ b/src/arch/x86/interface/syslinux/comboot_resolv.c
diff --git a/src/arch/i386/tests/comboot/shuffle-simple.asm b/src/arch/x86/tests/comboot/shuffle-simple.asm
index 8ede8d09..fa574bd7 100644
--- a/src/arch/i386/tests/comboot/shuffle-simple.asm
+++ b/src/arch/x86/tests/comboot/shuffle-simple.asm
@@ -37,4 +37,3 @@ source: dd 0
dd shuffle_len
num_shuffle_descriptors equ 1
-
diff --git a/src/arch/i386/tests/comboot/version.asm b/src/arch/x86/tests/comboot/version.asm
index 01140423..01140423 100644
--- a/src/arch/i386/tests/comboot/version.asm
+++ b/src/arch/x86/tests/comboot/version.asm
diff --git a/src/arch/x86/transitions/librm.S b/src/arch/x86/transitions/librm.S
index 3a585a92..f633b352 100644
--- a/src/arch/x86/transitions/librm.S
+++ b/src/arch/x86/transitions/librm.S
@@ -567,9 +567,10 @@ phys_to_prot:
popl %eax
ret
- /* Expose as _phys_to_virt for use by COMBOOT */
+.if32 /* Expose as _phys_to_virt for use by COMBOOT, if applicable */
.globl _phys_to_virt
.equ _phys_to_virt, phys_to_prot
+.endif
/****************************************************************************
* prot_to_phys (protected-mode near call, 32-bit virtual return address)
@@ -615,9 +616,10 @@ prot_to_phys:
popl %eax
ret
- /* Expose as _virt_to_phys for use by COMBOOT */
+.if32 /* Expose as _virt_to_phys for use by COMBOOT, if applicable */
.globl _virt_to_phys
.equ _virt_to_phys, prot_to_phys
+.endif
/****************************************************************************
* intr_to_prot (protected-mode near call, 32-bit virtual return address)
@@ -1203,6 +1205,66 @@ phys_call:
ret $( PHC_OFFSET_END - PHC_OFFSET_PARAMS )
/****************************************************************************
+ * phys_to_long (protected-mode near call, 32-bit physical return address)
+ *
+ * Used by COMBOOT.
+ *
+ ****************************************************************************
+ */
+ .if64
+
+ .section ".text.phys_to_long", "ax", @progbits
+ .code32
+phys_to_long:
+
+ /* Switch to virtual addresses */
+ call phys_to_prot
+
+ /* Convert to 32-bit virtual return address */
+ pushl %eax
+ movl VIRTUAL(virt_offset), %eax
+ subl %eax, 4(%esp)
+ popl %eax
+
+ /* Switch to long mode and return */
+ jmp prot_to_long
+
+ /* Expose as _phys_to_virt for use by COMBOOT */
+ .globl _phys_to_virt
+ .equ _phys_to_virt, phys_to_long
+
+ .endif
+
+/****************************************************************************
+ * long_to_phys (long-mode near call, 64-bit virtual return address)
+ *
+ * Used by COMBOOT.
+ *
+ ****************************************************************************
+ */
+ .if64
+
+ .section ".text.long_to_phys", "ax", @progbits
+ .code64
+long_to_phys:
+
+ /* Switch to protected mode */
+ call long_to_prot
+ .code32
+
+ /* Convert to 32-bit virtual return address */
+ popl (%esp)
+
+ /* Switch to physical addresses and return */
+ jmp prot_to_phys
+
+ /* Expose as _virt_to_phys for use by COMBOOT */
+ .globl _virt_to_phys
+ .equ _virt_to_phys, long_to_phys
+
+ .endif
+
+/****************************************************************************
* flatten_real_mode (real-mode near call)
*
* Switch to flat real mode