# 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
#
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
assert ( avail_mem_top != 0 );
- com32_external_esp = phys_to_virt ( avail_mem_top );
-
/* Hook COMBOOT API interrupts */
hook_comboot_interrupts();
*/
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;
/**
* Check image name extension
- *
+ *
* @v image COM32 image
* @ret rc Return status code
*/
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
/**
* Copy command line to PSP
- *
+ *
* @v image COMBOOT image
*/
static void comboot_copy_cmdline ( struct image * image, userptr_t seg_userptr ) {
/**
* Initialize PSP
- *
+ *
* @v image COMBOOT image
* @v seg_userptr segment to initialize
*/
/**
* Check image name extension
- *
+ *
* @v image COMBOOT image
* @ret rc Return status code
*/
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;
/* Check if this is a COMBOOT image */
if ( ( rc = comboot_identify ( image ) ) != 0 ) {
-
+
return rc;
}
*/
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",
#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)
*/
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
*/
/* 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
*/
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) );
/* 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)
*/
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) );
}
}
*/
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) );
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) );
}
}
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 );
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
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."
/* Jump to real-mode entry point */
__asm__ __volatile__ (
- REAL_CODE (
+ REAL_CODE (
"pushw %0\n\t"
"popw %%ds\n\t"
"pushl %1\n\t"
dd shuffle_len
num_shuffle_descriptors equ 1
-
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)
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)
/* 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)
*