xref: /openbsd/sys/arch/amd64/stand/libsa/pxe_call.S (revision 7b36286a)
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
48ENTRY(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
86ENTRY(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
135prot_to_real:
136	.code32
137	ljmp	$S16TEXT, $p2r16 - LINKADDR
138p2r16:
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
151p2r16real:
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
182real_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 */
194r2p32:
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
213