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