/* $OpenBSD: pxe_call.S,v 1.4 2006/01/02 00:26:29 tom Exp $ */ /* $NetBSD: pxe_call.S,v 1.2 2002/03/27 17:24:22 kanaoka Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. * All rights reserved. * * Written by Jason R. Thorpe for Wasabi Systems, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed for the NetBSD Project by * Wasabi Systems, Inc. * 4. The name of Wasabi Systems, Inc. may not be used to endorse * or promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Low level PXE BIOS call glue. */ #include #include #include "gidt.h" ENTRY(pxecall_bangpxe) .code32 pushl %ebp movl %esp, %ebp pushl %ebx pushl %ecx pushl %edx /* For simplicity, just move all 32 bits. */ movl 8(%ebp), %ebx pushw _C_LABEL(pxe_command_buf_seg) pushw _C_LABEL(pxe_command_buf_off) pushw %bx call prot_to_real /* Enter real mode */ .code16 sti /* The encoding is: 0x9a offlo offhi seglo seghi */ lcall $0, $0xffff .globl _C_LABEL(bangpxe_off) _C_LABEL(bangpxe_off) = . - 4 .globl _C_LABEL(bangpxe_seg) _C_LABEL(bangpxe_seg) = . - 2 cli call real_to_prot /* Leave real mode */ .code32 add $6, %esp popl %edx popl %ecx popl %ebx popl %ebp ret ENTRY(pxecall_pxenv) .code32 pushl %ebp movl %esp, %ebp pushl %ebx pushl %ecx pushl %edx pushl %edi /* * Using the PXENV+ calling convention, the (16 bit) function * number is passed in %bx, with the address of the command * buffer in %es:%di. */ movl 8(%ebp), %ebx /* For simplicity, just move all 32 bits. */ /* * prot_to_real() will set %es to BOOTSEG, so we just need to set * %(e)di up here. Remember to relocate it! */ movl $_C_LABEL(pxe_command_buf), %edi subl $LINKADDR, %edi call prot_to_real /* Enter real mode */ .code16 /* The encoding is: 0x9a offlo offhi seglo seghi */ lcall $0, $0xffff .globl _C_LABEL(pxenv_off) _C_LABEL(pxenv_off) = . - 4 .globl _C_LABEL(pxenv_seg) _C_LABEL(pxenv_seg) = . - 2 call real_to_prot /* Leave real mode */ .code32 popl %edi popl %edx popl %ecx popl %ebx popl %ebp ret /* * prot_to_real() * * Switch the processor back into real mode. */ .globl prot_to_real prot_to_real: .code32 ljmp $S16TEXT, $p2r16 - LINKADDR p2r16: .code16 movw $S16DATA, %ax movw %ax, %ds movw %ax, %es movl %cr0, %eax /* Disable protected mode */ andl $~CR0_PE, %eax movl %eax, %cr0 /* reload real cs:ip */ data32 ljmp $(LINKADDR >> 4), $p2r16real - LINKADDR p2r16real: xorw %ax, %ax /* Reset segment registers: */ movw %ax, %ss /* %ss: for our stack */ movw $LINKADDR >> 4, %ax /* We're linked to LINKADDR/16:0000 */ movw %ax, %ds /* %ds: so we can get at Idtr_real */ .extern Idtr_real data32 addr32 lidt (Idtr_real - LINKADDR); /* Set up IDT for real mode */ movw %cs, %ax movw %ax, %ds movw %ax, %es /* Set %ds = %es = %cs */ /* * We were called from 32-bit mode, so there's a 32-bit * return address on the stack. No segment. This is within * the flat memory model, so we need to adjust it back so * that it's relative to our 16-bit %cs. */ popl %eax subl $LINKADDR, %eax pushw %ax ret /* * real_to_prot() * * Switch the processor back into protected mode. */ .globl real_to_prot real_to_prot: .code16 movw $LINKADDR >> 4, %ax /* We're linked to LINKADDR/16:0000 */ movw %ax, %ds data32 addr32 lgdt (Gdtr - LINKADDR) /* Reload the GDT */ movl %cr0, %eax /* Enable protected mode */ orl $CR0_PE, %eax movl %eax, %cr0 data32 ljmp $S32TEXT, $r2p32 /* Reload %cs, flush pipeline */ r2p32: .code32 /* Reload 32-bit %ds, %ss, %es */ movl $S32DATA, %eax mov %ax, %ds mov %ax, %ss mov %ax, %es /* Load IDT for debugger and DOS/BIOS interface */ .extern Idtr lidt Idtr xorl %eax, %eax popw %ax /* 16-bit return addr on stack */ addl $LINKADDR, %eax pushl %eax /* Now have correct 32-bit ret addr */ ret .end