iPXE
com32_call.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
3 *
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.
8 *
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.
13 *
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
17 * 02110-1301, USA.
18 */
19
20/**
21 * @file SYSLINUX COM32 helpers
22 *
23 */
24
25FILE_LICENCE ( GPL2_OR_LATER );
26
27#include <stdint.h>
28#include <realmode.h>
29#include <comboot.h>
30#include <assert.h>
31#include <ipxe/uaccess.h>
32
34#define com32_regs __use_data16 ( com32_regs )
35
37#define com32_int_vector __use_data16 ( com32_int_vector )
38
40#define com32_farcall_proc __use_data16 ( com32_farcall_proc )
41
42uint16_t __bss16 ( com32_saved_sp );
43
44/**
45 * Interrupt call helper
46 */
47void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
48
49 DBGC ( &com32_regs, "COM32 INT%x in %#08lx out %#08lx\n",
50 interrupt, inregs_phys, outregs_phys );
51
52 memcpy ( &com32_regs, phys_to_virt ( inregs_phys ),
53 sizeof ( com32sys_t ) );
54
56
58 REAL_CODE ( /* Save all registers */
59 "pushal\n\t"
60 "pushw %%ds\n\t"
61 "pushw %%es\n\t"
62 "pushw %%fs\n\t"
63 "pushw %%gs\n\t"
64 /* Mask off unsafe flags */
65 "movl (com32_regs + 40), %%eax\n\t"
66 "andl $0x200cd7, %%eax\n\t"
67 "movl %%eax, (com32_regs + 40)\n\t"
68 /* Load com32_regs into the actual registers */
69 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
70 "movw $com32_regs, %%sp\n\t"
71 "popw %%gs\n\t"
72 "popw %%fs\n\t"
73 "popw %%es\n\t"
74 "popw %%ds\n\t"
75 "popal\n\t"
76 "popfl\n\t"
77 "movw %%ss:(com32_saved_sp), %%sp\n\t"
78 /* patch INT instruction */
79 "pushw %%ax\n\t"
80 "movb %%ss:(com32_int_vector), %%al\n\t"
81 "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t"
82 /* perform a jump to avoid problems with cache
83 * consistency in self-modifying code on some CPUs (486)
84 */
85 "jmp 1f\n"
86 "1:\n\t"
87 "popw %%ax\n\t"
88 "com32_intcall_instr:\n\t"
89 /* INT instruction to be patched */
90 "int $0xFF\n\t"
91 /* Copy regs back to com32_regs */
92 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
93 "movw $(com32_regs + 44), %%sp\n\t"
94 "pushfl\n\t"
95 "pushal\n\t"
96 "pushw %%ds\n\t"
97 "pushw %%es\n\t"
98 "pushw %%fs\n\t"
99 "pushw %%gs\n\t"
100 "movw %%ss:(com32_saved_sp), %%sp\n\t"
101 /* Restore registers */
102 "popw %%gs\n\t"
103 "popw %%fs\n\t"
104 "popw %%es\n\t"
105 "popw %%ds\n\t"
106 "popal\n\t")
107 : : );
108
109 if ( outregs_phys ) {
110 memcpy ( phys_to_virt ( outregs_phys ),
111 &com32_regs, sizeof ( com32sys_t ) );
112 }
113}
114
115/**
116 * Farcall helper
117 */
118void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
119
120 DBGC ( &com32_regs, "COM32 farcall %04x:%04x in %#08lx out %#08lx\n",
121 ( proc >> 16 ), ( proc & 0xffff ), inregs_phys, outregs_phys );
122
123 memcpy ( &com32_regs, phys_to_virt ( inregs_phys ),
124 sizeof ( com32sys_t ) );
125
126 com32_farcall_proc = proc;
127
129 REAL_CODE ( /* Save all registers */
130 "pushal\n\t"
131 "pushw %%ds\n\t"
132 "pushw %%es\n\t"
133 "pushw %%fs\n\t"
134 "pushw %%gs\n\t"
135 /* Mask off unsafe flags */
136 "movl (com32_regs + 40), %%eax\n\t"
137 "andl $0x200cd7, %%eax\n\t"
138 "movl %%eax, (com32_regs + 40)\n\t"
139 /* Load com32_regs into the actual registers */
140 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
141 "movw $com32_regs, %%sp\n\t"
142 "popw %%gs\n\t"
143 "popw %%fs\n\t"
144 "popw %%es\n\t"
145 "popw %%ds\n\t"
146 "popal\n\t"
147 "popfl\n\t"
148 "movw %%ss:(com32_saved_sp), %%sp\n\t"
149 /* Call procedure */
150 "lcall *%%ss:(com32_farcall_proc)\n\t"
151 /* Copy regs back to com32_regs */
152 "movw %%sp, %%ss:(com32_saved_sp)\n\t"
153 "movw $(com32_regs + 44), %%sp\n\t"
154 "pushfl\n\t"
155 "pushal\n\t"
156 "pushw %%ds\n\t"
157 "pushw %%es\n\t"
158 "pushw %%fs\n\t"
159 "pushw %%gs\n\t"
160 "movw %%ss:(com32_saved_sp), %%sp\n\t"
161 /* Restore registers */
162 "popw %%gs\n\t"
163 "popw %%fs\n\t"
164 "popw %%es\n\t"
165 "popw %%ds\n\t"
166 "popal\n\t")
167 : : );
168
169 if ( outregs_phys ) {
170 memcpy ( phys_to_virt ( outregs_phys ),
171 &com32_regs, sizeof ( com32sys_t ) );
172 }
173}
174
175/**
176 * CDECL farcall helper
177 */
178int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
179 int32_t eax;
180
181 DBGC ( &com32_regs, "COM32 cfarcall %04x:%04x params %#08lx+%#zx\n",
182 ( proc >> 16 ), ( proc & 0xffff ), stack, stacksz );
183
184 copy_to_rm_stack ( phys_to_virt ( stack ), stacksz );
185 com32_farcall_proc = proc;
186
188 REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" )
189 : "=a" (eax)
190 :
191 : "ecx", "edx" );
192
193 remove_from_rm_stack ( NULL, stacksz );
194
195 return eax;
196}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
#define __asmcall
Declare a function with standard calling conventions.
Definition compiler.h:15
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
unsigned short uint16_t
Definition stdint.h:11
unsigned int uint32_t
Definition stdint.h:12
unsigned long physaddr_t
Definition stdint.h:20
signed int int32_t
Definition stdint.h:17
unsigned char uint8_t
Definition stdint.h:10
uint32_t eax
Definition string.h:235
Assertions.
void __asmcall com32_intcall(uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys)
Interrupt call helper.
Definition com32_call.c:47
int __asmcall com32_cfarcall(uint32_t proc, physaddr_t stack, size_t stacksz)
CDECL farcall helper.
Definition com32_call.c:178
void __asmcall com32_farcall(uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys)
Farcall helper.
Definition com32_call.c:118
#define com32_regs
Definition com32_call.c:34
#define com32_farcall_proc
Definition com32_call.c:40
#define com32_int_vector
Definition com32_call.c:37
SYSLINUX COMBOOT.
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
void * memcpy(void *dest, const void *src, size_t len) __nonnull
Access to external ("user") memory.
#define REAL_CODE(asm_code_str)
Definition libkir.h:226
#define __bss16(variable)
Definition libkir.h:16
uint16_t copy_to_rm_stack(const void *data, size_t size)
Allocate space on the real-mode stack and copy data there.
Definition librm_mgmt.c:67
void remove_from_rm_stack(void *data, size_t size)
Deallocate space on the real-mode stack, optionally copying back data.
Definition librm_mgmt.c:82
void interrupt(int intr, struct interrupt_frame32 *frame32, struct interrupt_frame64 *frame64)
Interrupt handler.
Definition librm_mgmt.c:251
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")