diff --git a/src/system/boot/platform/pxe_ia32/Jamfile b/src/system/boot/platform/pxe_ia32/Jamfile index 50bf47b7cf..b68e79d608 100644 --- a/src/system/boot/platform/pxe_ia32/Jamfile +++ b/src/system/boot/platform/pxe_ia32/Jamfile @@ -42,6 +42,7 @@ local bios_ia32_edid_src = KernelMergeObject boot_platform_pxe_ia32.o : pxe_stage2.S smp_trampoline.S + pxe_bios.S devices.cpp network.cpp pxe_undi.cpp diff --git a/src/system/boot/platform/pxe_ia32/pxe_bios.S b/src/system/boot/platform/pxe_ia32/pxe_bios.S new file mode 100644 index 0000000000..0f21edb100 --- /dev/null +++ b/src/system/boot/platform/pxe_ia32/pxe_bios.S @@ -0,0 +1,108 @@ +/* +** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. +** Copyright 2006, Marcus Overhagen, marcus@overhagen.de. All rights reserved. +** Distributed under the terms of the Haiku License. +*/ + + +/** This file contains code to call PXE BIOS functions out of a protected + * mode environment. It doesn't use the virtual86 mode - it switches + * to real mode, make the BIOS call, and switch back to protected + * mode again. It's meant to be used in a single-threaded boot loader, + * not in a multi-tasking operating system. + * It relies on the real mode segment descriptors found in pxe_stage1.S, + * and uses support functions from ../bios_ia32/bios.S + */ + +#define FUNCTION(x) .globl x ; x ## : + +#define REAL_MODE_STACK 0x9000 + // the location of the stack in real mode + +#define SAVED_ESP 0x10000 +#define SAVED_CR3 0x10004 +#define SAVED_EAX 0x10008 +#define SAVED_ES 0x1000c +#define SAVED_FLAGS 0x10010 + // we're overwriting the start of our boot loader to hold some + // temporary values - the first 1024 bytes of it are used at + // startup only, and we avoid some linking issues this way + + +.text +.code32 + + +/** void call_pxe_bios(...) + * Does a call to the PXE BIOS functions in real mode. + */ + +FUNCTION(call_pxe_bios) + pushal + pushfl + + // make sure the correct IDT is in place + lidt idt_descriptor + + // get the interrupt vector and patch the instruction at the target address + movl 40(%esp), %eax + + // Fills registers from the passed in structure + // Since switch_to_real_mode() clobbers %eax, we have to handle + // it specially here (by temporarily storing it to an arbitrary + // memory location, SAVED_EAX) + movl 44(%esp), %ebp + + movl (%ebp), %eax + movl %eax, SAVED_EAX + movl 4(%ebp), %ebx + movl 8(%ebp), %ecx + movl 12(%ebp), %edx + movl 16(%ebp), %esi + movl 20(%ebp), %edi + movw 24(%ebp), %ax + movw %ax, SAVED_ES + + call switch_to_real_mode + + .code16 + + // restore %eax and %es from saved location + movl (SAVED_EAX - 0x10000), %eax + movw (SAVED_ES - 0x10000), %es + + // call the PXE hook + + + + // we're interested in the flags state as well + pushf + + // save %eax from the call + movl %eax, (SAVED_EAX - 0x10000) + + // save flags from the call + pop %ax + movw %ax, (SAVED_FLAGS - 0x10000) + + // back to protected mode + call switch_to_protected_mode + .code32 + + // store the register state into the structure that has been passed in + movl 44(%esp), %eax + + movl %ebx, 4(%eax) + movl %ecx, 8(%eax) + movl %edx, 12(%eax) + movl %esi, 16(%eax) + movl %edi, 20(%eax) + movl SAVED_EAX, %ecx // special handling for %eax and flags + movl %ecx, (%eax) + movw SAVED_FLAGS, %cx + movw %cx, 26(%eax) + + popfl + popal + + ret