diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/arch/i386/Makefile | 2 | ||||
-rw-r--r-- | src/arch/x86/Makefile | 1 | ||||
-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.S | 66 |
12 files changed, 179 insertions, 101 deletions
diff --git a/src/arch/i386/Makefile b/src/arch/i386/Makefile index a52986048..fe3adc9ce 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 e933f4a4f..368c29f6d 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 ff64fd1a1..016652877 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 20b5ae1e7..9a847f0ff 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 5cb1ba54c..69c6ef024 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 75dcc238f..19fdbaff9 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 c9d1452b4..d59a3392c 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 565977811..2f5c252c1 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 03bbfd04a..03bbfd04a 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 8ede8d097..fa574bd72 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 011404239..011404239 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 3a585a921..f633b352b 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 |