]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[comboot] Support COMBOOT in 64-bit builds
authorMichael Brown <mcb30@ipxe.org>
Thu, 14 Apr 2016 15:48:41 +0000 (16:48 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 15 Apr 2016 14:31:36 +0000 (15:31 +0100)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
12 files changed:
src/arch/i386/Makefile
src/arch/x86/Makefile
src/arch/x86/image/com32.c [moved from src/arch/i386/image/com32.c with 77% similarity]
src/arch/x86/image/comboot.c [moved from src/arch/i386/image/comboot.c with 99% similarity]
src/arch/x86/include/comboot.h [moved from src/arch/i386/include/comboot.h with 96% similarity]
src/arch/x86/interface/syslinux/com32_call.c [moved from src/arch/i386/interface/syslinux/com32_call.c with 91% similarity]
src/arch/x86/interface/syslinux/com32_wrapper.S [moved from src/arch/i386/interface/syslinux/com32_wrapper.S with 51% similarity]
src/arch/x86/interface/syslinux/comboot_call.c [moved from src/arch/i386/interface/syslinux/comboot_call.c with 99% similarity]
src/arch/x86/interface/syslinux/comboot_resolv.c [moved from src/arch/i386/interface/syslinux/comboot_resolv.c with 100% similarity]
src/arch/x86/tests/comboot/shuffle-simple.asm [moved from src/arch/i386/tests/comboot/shuffle-simple.asm with 99% similarity]
src/arch/x86/tests/comboot/version.asm [moved from src/arch/i386/tests/comboot/version.asm with 100% similarity]
src/arch/x86/transitions/librm.S

index a52986048ee5c106ff3e99b3633f31986ecb6a61..fe3adc9ce43629c87ad66c3af983fe2e2df19147 100644 (file)
@@ -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
 #
index e933f4a4f48cc27a59c7f6a39d6847d0dd6cde49..368c29f6dfbf3483b4c36ab7a28aa4eb06ab1520 100644 (file)
@@ -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
similarity index 77%
rename from src/arch/i386/image/com32.c
rename to src/arch/x86/image/com32.c
index ff64fd1a1611c8cc8130e2b7e503838b226af3fb..01665287746a97ada67264d86cfd252f9958815d 100644 (file)
@@ -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
similarity index 99%
rename from src/arch/i386/image/comboot.c
rename to src/arch/x86/image/comboot.c
index 20b5ae1e79b9a51b2324f07146aa02e3af907e77..9a847f0ff09b1659b3307a6a136eeb150d78d644 100644 (file)
@@ -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",
similarity index 96%
rename from src/arch/i386/include/comboot.h
rename to src/arch/x86/include/comboot.h
index 5cb1ba54c958ff6d2c0a37321c11f1f1115856f7..69c6ef024ab412e8f650a36cced9d924c70c8b1c 100644 (file)
@@ -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
similarity index 91%
rename from src/arch/i386/interface/syslinux/com32_call.c
rename to src/arch/x86/interface/syslinux/com32_call.c
index 75dcc238f1e14ddeb9982325c81a6a9e0a83148a..19fdbaff9c47660817ba02859d30937167f05b82 100644 (file)
@@ -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 );
similarity index 51%
rename from src/arch/i386/interface/syslinux/com32_wrapper.S
rename to src/arch/x86/interface/syslinux/com32_wrapper.S
index c9d1452b421b1c17bd027fa4a97d2d8ff879afa4..d59a3392c2cc4dfca75c1858780f106510769634 100644 (file)
 
 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
similarity index 99%
rename from src/arch/i386/interface/syslinux/comboot_call.c
rename to src/arch/x86/interface/syslinux/comboot_call.c
index 565977811d1d08f76c06a88e6098d4d05653deac..2f5c252c1147d053a15267aae90b6e3359b34884 100644 (file)
@@ -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"
similarity index 99%
rename from src/arch/i386/tests/comboot/shuffle-simple.asm
rename to src/arch/x86/tests/comboot/shuffle-simple.asm
index 8ede8d0976a3d18ee2a2692cba858524fcbbdedc..fa574bd72401d90d504bd5a231dddd75cba4bb6d 100644 (file)
@@ -37,4 +37,3 @@ source:       dd 0
        dd shuffle_len
 
 num_shuffle_descriptors equ 1
-
index 3a585a9211aaf134c89c7a43968b325b2b6250a0..f633b352bac2b9ebd9e2593d9215ac1ae1587f53 100644 (file)
@@ -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)
@@ -1202,6 +1204,66 @@ phys_call:
        /* Return and discard function parameters */
        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)
  *