#ifndef ASSEMBLY
/** Declare a function with standard calling conventions */
-#define __asmcall __attribute__ (( cdecl, regparm(0) ))
+#define __asmcall __attribute__ (( used, cdecl, regparm(0) ))
/**
* Declare a function with libgcc implicit linkage
__asm__ __volatile__ (
TEXT16_CODE ( "\nint20_wrapper:\n\t"
- "pushl %0\n\t"
- "call prot_call\n\t"
+ VIRT_CALL ( int20 )
"clc\n\t"
"call patch_cf\n\t"
- "iret\n\t" )
- : : "i" ( int20 ) );
+ "iret\n\t" ) );
hook_bios_interrupt ( 0x20, ( intptr_t ) int20_wrapper, &int20_vector );
__asm__ __volatile__ (
TEXT16_CODE ( "\nint21_wrapper:\n\t"
- "pushl %0\n\t"
- "call prot_call\n\t"
+ VIRT_CALL ( int21 )
"clc\n\t"
"call patch_cf\n\t"
- "iret\n\t" )
- : : "i" ( int21 ) );
+ "iret\n\t" ) );
hook_bios_interrupt ( 0x21, ( intptr_t ) int21_wrapper, &int21_vector );
__asm__ __volatile__ (
TEXT16_CODE ( "\nint22_wrapper:\n\t"
- "pushl %0\n\t"
- "call prot_call\n\t"
+ VIRT_CALL ( int22 )
"clc\n\t"
"call patch_cf\n\t"
- "iret\n\t" )
- : : "i" ( int22) );
+ "iret\n\t" ) );
hook_bios_interrupt ( 0x22, ( intptr_t ) int22_wrapper, &int22_vector );
}
__asm__ __volatile__ (
TEXT16_CODE ( ".globl dump_regs\n\t"
"\ndump_regs:\n\t"
- "pushl $_dump_regs\n\t"
- "call prot_call\n\t"
- "ret\n\t" ) : : );
+ VIRT_CALL ( _dump_regs )
+ "ret\n\t" ) );
printf ( "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
"ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
#define LONG_DS 0x40
#endif
-#ifndef ASSEMBLY
+#ifdef ASSEMBLY
+
+/**
+ * Call C function from real-mode code
+ *
+ * @v function C function
+ */
+.macro virtcall function
+ pushl $\function
+ call prot_call
+.endm
+
+#else /* ASSEMBLY */
#ifdef UACCESS_LIBRM
#define UACCESS_PREFIX_librm
#define UACCESS_PREFIX_librm __librm_
#endif
+/**
+ * Call C function from real-mode code
+ *
+ * @v function C function
+ */
+#define VIRT_CALL( function ) \
+ "pushl $( " #function " )\n\t" \
+ "call prot_call\n\t"
+
/* Variables in librm.S */
extern unsigned long virt_offset;
__asm__ __volatile__ (
TEXT16_CODE ( "\nint16_wrapper:\n\t"
"pushfw\n\t"
- "cmpb $0, %%cs:bios_inject_lock\n\t"
+ "cmpb $0, %cs:bios_inject_lock\n\t"
"jnz 1f\n\t"
- "pushl %0\n\t"
- "call prot_call\n\t"
+ VIRT_CALL ( bios_inject )
"\n1:\n\t"
"popfw\n\t"
- "ljmp *%%cs:int16_vector\n\t" )
- : : "i" ( bios_inject ) );
+ "ljmp *%cs:int16_vector\n\t" ) );
/* Hook INT 16 */
hook_bios_interrupt ( 0x16, ( ( intptr_t ) int16_wrapper ),
put_real ( flag, BDA_SEG, BDA_REBOOT );
/* Jump to system reset vector */
- __asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : : );
+ __asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) );
}
PROVIDE_REBOOT ( pcbios, reboot, bios_reboot );
/* Clear OF, set CF, call int13() */
"orb $0, %%al\n\t"
"stc\n\t"
- "pushl %0\n\t"
- "call prot_call\n\t"
+ VIRT_CALL ( int13 )
/* Chain if OF not set */
"jo 1f\n\t"
"pushfw\n\t"
"\n3:\n\t"
"movw %%bp, %%sp\n\t"
"popw %%bp\n\t"
- "iret\n\t" )
- : : "i" ( int13 ) );
+ "iret\n\t" ) : : );
hook_bios_interrupt ( 0x13, ( intptr_t ) int13_wrapper, &int13_vector );
}
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+#include <librm.h>
+
.arch i386
/****************************************************************************
.section ".text16", "ax", @progbits
.code16
pxenv_entry:
- pushl $pxe_api_call
- call prot_call
+ virtcall pxe_api_call
lret
.size pxenv_entry, . - pxenv_entry
FILE_LICENCE ( GPL2_ONLY )
+#include <librm.h>
+
.equ BOOTSEG, 0x07C0 /* original address of boot-sector */
.equ SYSSEG, 0x1000 /* system loaded at SYSSEG<<4 */
lret
.section ".text16", "awx", @progbits
1:
- pushl $main
- call prot_call
+ /* Run iPXE */
+ virtcall main
/* Uninstall iPXE */
call uninstall
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+#include <librm.h>
+
/* Initial temporary stack size */
#define EXE_STACK_SIZE 0x400
movl %esi, cmdline_phys
/* Run iPXE */
- pushl $main
- call prot_call
+ virtcall main
/* Uninstall iPXE */
call uninstall
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+#include <librm.h>
+
.text
.arch i386
.section ".prefix", "awx", @progbits
lret
.section ".text16", "awx", @progbits
1:
- pushl $main
- call prot_call
+ /* Run iPXE */
+ virtcall main
/* Uninstall iPXE */
call uninstall
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+#include <librm.h>
+
.arch i386
/* Image compression enabled */
* ready for the copy to the new location.
*/
progress " relocate\n"
- pushl $relocate
- call prot_call
+ virtcall relocate
/* Jump back to .prefix segment */
pushw $1f
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+#include <librm.h>
+
#define BZI_LOAD_HIGH_ADDR 0x100000
.text
movl %ecx, initrd_len
/* Run iPXE */
- pushl $main
- call prot_call
+ virtcall main
/* Uninstall iPXE */
call uninstall
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+#include <librm.h>
+
.text
.arch i386
.code16
lret
.section ".text16", "awx", @progbits
1:
- pushl $main
- call prot_call
+ /* Run iPXE */
+ virtcall main
/* Uninstall iPXE */
call uninstall
.org 0
.code16
+#include <librm.h>
#include <undi.h>
#define STACK_MAGIC ( 'L' + ( 'R' << 8 ) + ( 'E' << 16 ) + ( 'T' << 24 ) )
movl %ecx, cached_dhcpack_phys
/* Run main program */
- pushl $main
- call prot_call
+ virtcall main
/* Uninstall iPXE */
call uninstall
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+#include <librm.h>
#include <config/general.h>
#include <config/branding.h>
#endif /* AUTOBOOT_ROM_FILTER */
.endif
- /* Call main() */
- pushl $main
- call prot_call
+ /* Run iPXE */
+ virtcall main
/* Set up flat real mode for return to BIOS */
call flatten_real_mode
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
+#include <librm.h>
+
.text
.code16
.arch i386
.section ".text16", "ax", @progbits
1:
/* Call UNDI loader C code */
- pushl $pxe_loader_call
- call prot_call
+ virtcall pxe_loader_call
1: /* Restore registers and return */
popw %bx
addl $gdt, gdt_base
/* Initialise IDT */
- pushl $init_idt
- call prot_call
+ virtcall init_idt
/* Restore registers */
negl %edi
movb $0x8f, real_cs + 6
movb $0x8f, real_ds + 6
/* Call dummy protected-mode function */
- pushl $flatten_dummy
- call prot_call
+ virtcall flatten_dummy
/* Restore GDT */
movb $0x00, real_cs + 6
movb $0x00, real_ds + 6
static struct profiler prot_call_profiler __profiler = { .name = "prot_call" };
/**
- * Dummy protected-mode function
+ * Dummy function for profiling tests
*/
-static void librm_test_prot_call ( void ) {
+static __asmcall void librm_test_call ( struct i386_all_regs *ix86 __unused ) {
/* Do nothing */
}
/* Profile complete real-mode call cycle */
for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
profile_start ( &real_call_profiler );
- __asm__ __volatile__ ( REAL_CODE ( "" ) : : );
+ __asm__ __volatile__ ( REAL_CODE ( "" ) );
profile_stop ( &real_call_profiler );
}
for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
__asm__ __volatile__ ( REAL_CODE ( "rdtsc\n\t"
"movl %k0, %k2\n\t"
- "pushl %k3\n\t"
- "call prot_call\n\t"
+ VIRT_CALL ( librm_test_call )
"rdtsc\n\t" )
: "=a" ( stopped ), "=d" ( discard_d ),
- "=R" ( started )
- : "i" ( librm_test_prot_call ) );
+ "=R" ( started ) : );
profile_start_at ( &prot_call_profiler, started );
profile_stop_at ( &prot_call_profiler, stopped );
}
#ifndef ASSEMBLY
/** Declare a function with standard calling conventions */
-#define __asmcall __attribute__ (( regparm(0) ))
+#define __asmcall __attribute__ (( used, regparm(0) ))
/** Declare a function with libgcc implicit linkage */
#define __libgcc