david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[comboot] Support COMBOOT in 64-bit builds

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2016-04-14 16:48:41 +01:00
parent 4afb758423
commit 5e5450c2d0
12 changed files with 180 additions and 102 deletions

View 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
#

View 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

View 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

View 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",

View 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

View 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 );

View File

@ -19,79 +19,82 @@
FILE_LICENCE ( GPL2_OR_LATER )
.text
.arch i386
.code32
#include "librm.h"
.text
.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
call _phys_to_virt
mov %eax, (com32_helper_function)
#ifdef __x86_64__
/* Save external COM32 stack pointer */
movl %esp, (com32_external_esp)
.code64
/* Copy arguments to caller-save registers */
movl 12(%esp), %eax
movl 8(%esp), %ecx
movl 4(%esp), %edx
/* Preserve registers which are callee-save for COM32 (i386 API) */
pushq %rdi
pushq %rsi
pushq %rbp
/* Switch to internal stack */
movl (com32_internal_esp), %esp
/* Extract parameters from stack */
movl 28(%rsp), %edi
movl 32(%rsp), %esi
movl 36(%rsp), %edx
/* Copy arguments to internal stack */
pushl %eax
pushl %ecx
pushl %edx
/* Align stack pointer */
movq %rsp, %rbp
andq $~0x07, %rsp
call *(com32_helper_function)
/* Call helper function */
movslq %eax, %rax
call *%rax
/* Clean up stack */
addl $12, %esp
/* Restore stack pointer */
movq %rbp, %rsp
/* Save internal stack pointer and restore external stack pointer */
movl %esp, (com32_internal_esp)
movl (com32_external_esp), %esp
/* Restore registers */
popq %rbp
popq %rsi
popq %rdi
#else /* _x86_64 */
/* Call helper function */
pushl 12(%esp)
pushl 12(%esp)
pushl 12(%esp)
call *%eax
addl $12, %esp
#endif /* _x86_64 */
/* Switch to external flat physical address space */
call _virt_to_phys
call _virt_to_phys
.code32
/* Reenable interrupts and return */
sti
ret
.data
/* Internal iPXE virtual address space %esp */
.globl com32_internal_esp
.lcomm com32_internal_esp, 4
/* External flat physical address space %esp */
.globl com32_external_esp
.lcomm com32_external_esp, 4
/* Function pointer of helper to call */
.lcomm com32_helper_function, 4

View 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"

View File

@ -37,4 +37,3 @@ source: dd 0
dd shuffle_len
num_shuffle_descriptors equ 1

View 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)
*