1 /* $OpenBSD: pxe_call.S,v 1.4 2006/01/02 00:26:29 tom Exp $ */
2 /* $NetBSD: pxe_call.S,v 1.2 2002/03/27 17:24:22 kanaoka Exp $ */
3
4 /*
5 * Copyright 2001 Wasabi Systems, Inc.
6 * All rights reserved.
7 *
8 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed for the NetBSD Project by
21 * Wasabi Systems, Inc.
22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23 * or promote products derived from this software without specific prior
24 * written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Low level PXE BIOS call glue.
41 */
42
43 #include <machine/asm.h>
44 #include <assym.h>
45
46 #include "gidt.h"
47
48 ENTRY(pxecall_bangpxe)
49 .code32
50 pushl %ebp
51 movl %esp, %ebp
52 pushl %ebx
53 pushl %ecx
54 pushl %edx
55
56 /* For simplicity, just move all 32 bits. */
57 movl 8(%ebp), %ebx
58
59 pushw _C_LABEL(pxe_command_buf_seg)
60 pushw _C_LABEL(pxe_command_buf_off)
61 pushw %bx
62
63 call prot_to_real /* Enter real mode */
64 .code16
65
66 sti
67 /* The encoding is: 0x9a offlo offhi seglo seghi */
68 lcall $0, $0xffff
69 .globl _C_LABEL(bangpxe_off)
70 _C_LABEL(bangpxe_off) = . - 4
71 .globl _C_LABEL(bangpxe_seg)
72 _C_LABEL(bangpxe_seg) = . - 2
73
74 cli
75 call real_to_prot /* Leave real mode */
76 .code32
77
78 add $6, %esp
79
80 popl %edx
81 popl %ecx
82 popl %ebx
83 popl %ebp
84 ret
85
86 ENTRY(pxecall_pxenv)
87 .code32
88 pushl %ebp
89 movl %esp, %ebp
90 pushl %ebx
91 pushl %ecx
92 pushl %edx
93 pushl %edi
94
95 /*
96 * Using the PXENV+ calling convention, the (16 bit) function
97 * number is passed in %bx, with the address of the command
98 * buffer in %es:%di.
99 */
100 movl 8(%ebp), %ebx /* For simplicity, just move all 32 bits. */
101
102 /*
103 * prot_to_real() will set %es to BOOTSEG, so we just need to set
104 * %(e)di up here. Remember to relocate it!
105 */
106 movl $_C_LABEL(pxe_command_buf), %edi
107 subl $LINKADDR, %edi
108
109 call prot_to_real /* Enter real mode */
110 .code16
111
112 /* The encoding is: 0x9a offlo offhi seglo seghi */
113 lcall $0, $0xffff
114 .globl _C_LABEL(pxenv_off)
115 _C_LABEL(pxenv_off) = . - 4
116 .globl _C_LABEL(pxenv_seg)
117 _C_LABEL(pxenv_seg) = . - 2
118
119 call real_to_prot /* Leave real mode */
120 .code32
121
122 popl %edi
123 popl %edx
124 popl %ecx
125 popl %ebx
126 popl %ebp
127 ret
128
129 /*
130 * prot_to_real()
131 *
132 * Switch the processor back into real mode.
133 */
134 .globl prot_to_real
135 prot_to_real:
136 .code32
137 ljmp $S16TEXT, $p2r16 - LINKADDR
138 p2r16:
139 .code16
140
141 movw $S16DATA, %ax
142 movw %ax, %ds
143 movw %ax, %es
144
145 movl %cr0, %eax /* Disable protected mode */
146 andl $~CR0_PE, %eax
147 movl %eax, %cr0
148
149 /* reload real cs:ip */
150 data32 ljmp $(LINKADDR >> 4), $p2r16real - LINKADDR
151 p2r16real:
152 xorw %ax, %ax /* Reset segment registers: */
153 movw %ax, %ss /* %ss: for our stack */
154
155 movw $LINKADDR >> 4, %ax /* We're linked to LINKADDR/16:0000 */
156 movw %ax, %ds /* %ds: so we can get at Idtr_real */
157
158 .extern Idtr_real
159 data32 addr32 lidt (Idtr_real - LINKADDR); /* Set up IDT for real mode */
160
161 movw %cs, %ax
162 movw %ax, %ds
163 movw %ax, %es /* Set %ds = %es = %cs */
164
165 /*
166 * We were called from 32-bit mode, so there's a 32-bit
167 * return address on the stack. No segment. This is within
168 * the flat memory model, so we need to adjust it back so
169 * that it's relative to our 16-bit %cs.
170 */
171 popl %eax
172 subl $LINKADDR, %eax
173 pushw %ax
174 ret
175
176 /*
177 * real_to_prot()
178 *
179 * Switch the processor back into protected mode.
180 */
181 .globl real_to_prot
182 real_to_prot:
183 .code16
184
185 movw $LINKADDR >> 4, %ax /* We're linked to LINKADDR/16:0000 */
186 movw %ax, %ds
187 data32 addr32 lgdt (Gdtr - LINKADDR) /* Reload the GDT */
188
189 movl %cr0, %eax /* Enable protected mode */
190 orl $CR0_PE, %eax
191 movl %eax, %cr0
192
193 data32 ljmp $S32TEXT, $r2p32 /* Reload %cs, flush pipeline */
194 r2p32:
195 .code32
196 /* Reload 32-bit %ds, %ss, %es */
197 movl $S32DATA, %eax
198 mov %ax, %ds
199 mov %ax, %ss
200 mov %ax, %es
201
202 /* Load IDT for debugger and DOS/BIOS interface */
203 .extern Idtr
204 lidt Idtr
205
206 xorl %eax, %eax
207 popw %ax /* 16-bit return addr on stack */
208 addl $LINKADDR, %eax
209 pushl %eax /* Now have correct 32-bit ret addr */
210 ret
211
212 .end