00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 FILE_LICENCE ( GPL2_OR_LATER );
00025
00026 #include <stdint.h>
00027 #include <realmode.h>
00028 #include <comboot.h>
00029 #include <assert.h>
00030 #include <gpxe/uaccess.h>
00031
00032 static com32sys_t __bss16 ( com32_regs );
00033 #define com32_regs __use_data16 ( com32_regs )
00034
00035 static uint8_t __bss16 ( com32_int_vector );
00036 #define com32_int_vector __use_data16 ( com32_int_vector )
00037
00038 static uint32_t __bss16 ( com32_farcall_proc );
00039 #define com32_farcall_proc __use_data16 ( com32_farcall_proc )
00040
00041 uint16_t __bss16 ( com32_saved_sp );
00042
00043
00044
00045
00046 void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
00047
00048 memcpy_user ( virt_to_user( &com32_regs ), 0,
00049 phys_to_user ( inregs_phys ), 0,
00050 sizeof(com32sys_t) );
00051
00052 com32_int_vector = interrupt;
00053
00054 __asm__ __volatile__ (
00055 REAL_CODE (
00056 "pushal\n\t"
00057 "pushw %%ds\n\t"
00058 "pushw %%es\n\t"
00059 "pushw %%fs\n\t"
00060 "pushw %%gs\n\t"
00061
00062 "movl (com32_regs + 40), %%eax\n\t"
00063 "andl $0x200cd7, %%eax\n\t"
00064 "movl %%eax, (com32_regs + 40)\n\t"
00065
00066 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
00067 "movw $com32_regs, %%sp\n\t"
00068 "popw %%gs\n\t"
00069 "popw %%fs\n\t"
00070 "popw %%es\n\t"
00071 "popw %%ds\n\t"
00072 "popal\n\t"
00073 "popfl\n\t"
00074 "movw %%ss:(com32_saved_sp), %%sp\n\t"
00075
00076 "pushw %%ax\n\t"
00077 "movb %%ss:(com32_int_vector), %%al\n\t"
00078 "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t"
00079
00080
00081
00082 "jmp 1f\n"
00083 "1:\n\t"
00084 "popw %%ax\n\t"
00085 "com32_intcall_instr:\n\t"
00086
00087 "int $0xFF\n\t"
00088
00089 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
00090 "movw $(com32_regs + 44), %%sp\n\t"
00091 "pushfl\n\t"
00092 "pushal\n\t"
00093 "pushw %%ds\n\t"
00094 "pushw %%es\n\t"
00095 "pushw %%fs\n\t"
00096 "pushw %%gs\n\t"
00097 "movw %%ss:(com32_saved_sp), %%sp\n\t"
00098
00099 "popw %%gs\n\t"
00100 "popw %%fs\n\t"
00101 "popw %%es\n\t"
00102 "popw %%ds\n\t"
00103 "popal\n\t")
00104 : : );
00105
00106 if ( outregs_phys ) {
00107 memcpy_user ( phys_to_user ( outregs_phys ), 0,
00108 virt_to_user( &com32_regs ), 0,
00109 sizeof(com32sys_t) );
00110 }
00111 }
00112
00113
00114
00115
00116 void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
00117
00118 memcpy_user ( virt_to_user( &com32_regs ), 0,
00119 phys_to_user ( inregs_phys ), 0,
00120 sizeof(com32sys_t) );
00121
00122 com32_farcall_proc = proc;
00123
00124 __asm__ __volatile__ (
00125 REAL_CODE (
00126 "pushal\n\t"
00127 "pushw %%ds\n\t"
00128 "pushw %%es\n\t"
00129 "pushw %%fs\n\t"
00130 "pushw %%gs\n\t"
00131
00132 "movl (com32_regs + 40), %%eax\n\t"
00133 "andl $0x200cd7, %%eax\n\t"
00134 "movl %%eax, (com32_regs + 40)\n\t"
00135
00136 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
00137 "movw $com32_regs, %%sp\n\t"
00138 "popw %%gs\n\t"
00139 "popw %%fs\n\t"
00140 "popw %%es\n\t"
00141 "popw %%ds\n\t"
00142 "popal\n\t"
00143 "popfl\n\t"
00144 "movw %%ss:(com32_saved_sp), %%sp\n\t"
00145
00146 "lcall *%%ss:(com32_farcall_proc)\n\t"
00147
00148 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
00149 "movw $(com32_regs + 44), %%sp\n\t"
00150 "pushfl\n\t"
00151 "pushal\n\t"
00152 "pushw %%ds\n\t"
00153 "pushw %%es\n\t"
00154 "pushw %%fs\n\t"
00155 "pushw %%gs\n\t"
00156 "movw %%ss:(com32_saved_sp), %%sp\n\t"
00157
00158 "popw %%gs\n\t"
00159 "popw %%fs\n\t"
00160 "popw %%es\n\t"
00161 "popw %%ds\n\t"
00162 "popal\n\t")
00163 : : );
00164
00165 if ( outregs_phys ) {
00166 memcpy_user ( phys_to_user ( outregs_phys ), 0,
00167 virt_to_user( &com32_regs ), 0,
00168 sizeof(com32sys_t) );
00169 }
00170 }
00171
00172
00173
00174
00175 int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
00176 int32_t eax;
00177
00178 copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz );
00179 com32_farcall_proc = proc;
00180
00181 __asm__ __volatile__ (
00182 REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" )
00183 : "=a" (eax)
00184 :
00185 : "ecx", "edx" );
00186
00187 remove_user_from_rm_stack ( 0, stacksz );
00188
00189 return eax;
00190 }