2 * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 * @file SYSLINUX COM32 helpers
25 FILE_LICENCE ( GPL2_OR_LATER );
31 #include <ipxe/uaccess.h>
33 static com32sys_t __bss16 ( com32_regs );
34 #define com32_regs __use_data16 ( com32_regs )
36 static uint8_t __bss16 ( com32_int_vector );
37 #define com32_int_vector __use_data16 ( com32_int_vector )
39 static uint32_t __bss16 ( com32_farcall_proc );
40 #define com32_farcall_proc __use_data16 ( com32_farcall_proc )
42 uint16_t __bss16 ( com32_saved_sp );
45 * Interrupt call helper
47 void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
49 memcpy_user ( virt_to_user( &com32_regs ), 0,
50 phys_to_user ( inregs_phys ), 0,
53 com32_int_vector = interrupt;
55 __asm__ __volatile__ (
56 REAL_CODE ( /* Save all registers */
62 /* Mask off unsafe flags */
63 "movl (com32_regs + 40), %%eax\n\t"
64 "andl $0x200cd7, %%eax\n\t"
65 "movl %%eax, (com32_regs + 40)\n\t"
66 /* Load com32_regs into the actual registers */
67 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
68 "movw $com32_regs, %%sp\n\t"
75 "movw %%ss:(com32_saved_sp), %%sp\n\t"
76 /* patch INT instruction */
78 "movb %%ss:(com32_int_vector), %%al\n\t"
79 "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t"
80 /* perform a jump to avoid problems with cache
81 * consistency in self-modifying code on some CPUs (486)
86 "com32_intcall_instr:\n\t"
87 /* INT instruction to be patched */
89 /* Copy regs back to com32_regs */
90 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
91 "movw $(com32_regs + 44), %%sp\n\t"
98 "movw %%ss:(com32_saved_sp), %%sp\n\t"
99 /* Restore registers */
107 if ( outregs_phys ) {
108 memcpy_user ( phys_to_user ( outregs_phys ), 0,
109 virt_to_user( &com32_regs ), 0,
110 sizeof(com32sys_t) );
117 void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
119 memcpy_user ( virt_to_user( &com32_regs ), 0,
120 phys_to_user ( inregs_phys ), 0,
121 sizeof(com32sys_t) );
123 com32_farcall_proc = proc;
125 __asm__ __volatile__ (
126 REAL_CODE ( /* Save all registers */
132 /* Mask off unsafe flags */
133 "movl (com32_regs + 40), %%eax\n\t"
134 "andl $0x200cd7, %%eax\n\t"
135 "movl %%eax, (com32_regs + 40)\n\t"
136 /* Load com32_regs into the actual registers */
137 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
138 "movw $com32_regs, %%sp\n\t"
145 "movw %%ss:(com32_saved_sp), %%sp\n\t"
147 "lcall *%%ss:(com32_farcall_proc)\n\t"
148 /* Copy regs back to com32_regs */
149 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
150 "movw $(com32_regs + 44), %%sp\n\t"
157 "movw %%ss:(com32_saved_sp), %%sp\n\t"
158 /* Restore registers */
166 if ( outregs_phys ) {
167 memcpy_user ( phys_to_user ( outregs_phys ), 0,
168 virt_to_user( &com32_regs ), 0,
169 sizeof(com32sys_t) );
174 * CDECL farcall helper
176 int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
179 copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz );
180 com32_farcall_proc = proc;
182 __asm__ __volatile__ (
183 REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" )
188 remove_user_from_rm_stack ( 0, stacksz );