summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/arch/i386/interface
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/ipxe/src/arch/i386/interface')
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c112
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c16
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c52
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c65
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c70
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c92
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c1993
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13con.c284
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c182
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c123
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c203
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c142
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c542
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c354
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S221
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c65
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c346
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c55
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c387
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c597
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c474
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c1084
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c283
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/syslinux/com32_call.c191
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S97
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c717
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_resolv.c61
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/vmware/guestinfo.c271
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c332
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c138
-rw-r--r--qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c62
31 files changed, 0 insertions, 9611 deletions
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c
deleted file mode 100644
index 50b19cb81..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/apm.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2013 Marin Hannache <ipxe@mareo.fr>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/**
- * @file
- *
- * Advanced Power Management
- *
- */
-
-#include <errno.h>
-#include <realmode.h>
-#include <ipxe/reboot.h>
-
-/**
- * Power off the computer using APM
- *
- * @ret rc Return status code
- */
-static int apm_poweroff ( void ) {
- uint16_t apm_version;
- uint16_t apm_signature;
- uint16_t apm_flags;
- uint16_t carry;
-
- /* APM check */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
- "adc %%edx,0\n\t" )
- : "=a" ( apm_version ), "=b" ( apm_signature ),
- "=c" ( apm_flags ), "=d" ( carry )
- : "a" ( 0x5300 ), "b" ( 0x0000 ),
- "d" ( 0x0000 ) );
- if ( carry ) {
- DBG ( "APM not present\n" );
- return -ENOTSUP;
- }
- if ( apm_signature != 0x504d ) { /* signature 'PM' */
- DBG ( "APM not present\n" );
- return -ENOTSUP;
- }
- if ( apm_version < 0x0101 ) { /* Need version 1.1+ */
- DBG ( "APM 1.1+ not supported\n" );
- return -ENOTSUP;
- }
- if ( ( apm_flags & 0x8 ) == 0x8 ) {
- DBG ( "APM power management disabled\n" );
- return -EPERM;
- }
- DBG2 ( "APM check completed\n" );
-
- /* APM initialisation */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
- "adc %%edx,0\n\t" )
- : "=d" ( carry )
- : "a" ( 0x5301 ), "b" ( 0x0000 ),
- "d" ( 0x0000 ) );
- if ( carry ) {
- DBG ( "APM initialisation failed\n" );
- return -EIO;
- }
- DBG2 ( "APM initialisation completed\n" );
-
- /* Set APM driver version */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
- "adc %%edx,0\n\t" )
- : "=d" ( carry )
- : "a" ( 0x530e ), "b" ( 0x0000 ),
- "c" ( 0x0101 ), "d" ( 0x0000 ) );
- if ( carry ) {
- DBG ( "APM setting driver version failed\n" );
- return -EIO;
- }
- DBG2 ( "APM driver version set\n" );
-
- /* Setting power state to off */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x15\n\t"
- "adc %%edx,0\n\t" )
- : "=d" ( carry )
- : "a" ( 0x5307 ), "b" ( 0x0001 ),
- "c" ( 0x0003 ), "d" ( 0x0000) );
- if ( carry ) {
- DBG ( "APM setting power state failed\n" );
- return -ENOTTY;
- }
-
- /* Should never happen */
- return -ECANCELED;
-}
-
-PROVIDE_REBOOT ( pcbios, poweroff, apm_poweroff );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c
deleted file mode 100644
index f1ba8297b..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_nap.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <ipxe/nap.h>
-#include <realmode.h>
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/**
- * Save power by halting the CPU until the next interrupt
- *
- */
-static void bios_cpu_nap ( void ) {
- __asm__ __volatile__ ( "sti\n\t"
- "hlt\n\t"
- "cli\n\t" );
-}
-
-PROVIDE_NAP ( pcbios, cpu_nap, bios_cpu_nap );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c
deleted file mode 100644
index 10a1ecb89..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_reboot.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2010 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * Standard PC-BIOS reboot mechanism
- *
- */
-
-#include <ipxe/reboot.h>
-#include <realmode.h>
-#include <bios.h>
-
-/**
- * Reboot system
- *
- * @v warm Perform a warm reboot
- */
-static void bios_reboot ( int warm ) {
- uint16_t flag;
-
- /* Configure BIOS for cold/warm reboot */
- flag = ( warm ? BDA_REBOOT_WARM : 0 );
- put_real ( flag, BDA_SEG, BDA_REBOOT );
-
- /* Jump to system reset vector */
- __asm__ __volatile__ ( REAL_CODE ( "ljmp $0xf000, $0xfff0" ) : : );
-}
-
-PROVIDE_REBOOT ( pcbios, reboot, bios_reboot );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c
deleted file mode 100644
index a8c0fc325..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_smbios.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/smbios.h>
-#include <realmode.h>
-#include <pnpbios.h>
-
-/** @file
- *
- * System Management BIOS
- *
- */
-
-/**
- * Find SMBIOS
- *
- * @v smbios SMBIOS entry point descriptor structure to fill in
- * @ret rc Return status code
- */
-static int bios_find_smbios ( struct smbios *smbios ) {
- struct smbios_entry entry;
- int rc;
-
- /* Scan through BIOS segment to find SMBIOS entry point */
- if ( ( rc = find_smbios_entry ( real_to_user ( BIOS_SEG, 0 ), 0x10000,
- &entry ) ) != 0 )
- return rc;
-
- /* Fill in entry point descriptor structure */
- smbios->address = phys_to_user ( entry.smbios_address );
- smbios->len = entry.smbios_len;
- smbios->count = entry.smbios_count;
- smbios->version = SMBIOS_VERSION ( entry.major, entry.minor );
-
- return 0;
-}
-
-PROVIDE_SMBIOS ( pcbios, find_smbios, bios_find_smbios );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c
deleted file mode 100644
index 3299c9aae..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/bios_timer.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * BIOS timer
- *
- */
-
-#include <ipxe/timer.h>
-#include <realmode.h>
-#include <bios.h>
-
-/**
- * Get current system time in ticks
- *
- * @ret ticks Current time, in ticks
- *
- * Use direct memory access to BIOS variables, longword 0040:006C
- * (ticks today) and byte 0040:0070 (midnight crossover flag) instead
- * of calling timeofday BIOS interrupt.
- */
-static unsigned long bios_currticks ( void ) {
- static int days = 0;
- uint32_t ticks;
- uint8_t midnight;
-
- /* Re-enable interrupts so that the timer interrupt can occur */
- __asm__ __volatile__ ( "sti\n\t"
- "nop\n\t"
- "nop\n\t"
- "cli\n\t" );
-
- get_real ( ticks, BDA_SEG, 0x006c );
- get_real ( midnight, BDA_SEG, 0x0070 );
-
- if ( midnight ) {
- midnight = 0;
- put_real ( midnight, BDA_SEG, 0x0070 );
- days += 0x1800b0;
- }
-
- return ( days + ticks );
-}
-
-PROVIDE_TIMER_INLINE ( pcbios, udelay );
-PROVIDE_TIMER ( pcbios, currticks, bios_currticks );
-PROVIDE_TIMER_INLINE ( pcbios, ticks_per_sec );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c
deleted file mode 100644
index 3b8e80438..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/biosint.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#include <errno.h>
-#include <realmode.h>
-#include <biosint.h>
-
-/**
- * @file BIOS interrupts
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/**
- * Hook INT vector
- *
- * @v interrupt INT number
- * @v handler Offset within .text16 to interrupt handler
- * @v chain_vector Vector for chaining to previous handler
- *
- * Hooks in an i386 INT handler. The handler itself must reside
- * within the .text16 segment. @c chain_vector will be filled in with
- * the address of the previously-installed handler for this interrupt;
- * the handler should probably exit by ljmping via this vector.
- */
-void hook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
- struct segoff *chain_vector ) {
- struct segoff vector = {
- .segment = rm_cs,
- .offset = handler,
- };
-
- DBG ( "Hooking INT %#02x to %04x:%04x\n",
- interrupt, rm_cs, handler );
-
- if ( ( chain_vector->segment != 0 ) ||
- ( chain_vector->offset != 0 ) ) {
- /* Already hooked; do nothing */
- DBG ( "...already hooked\n" );
- return;
- }
-
- copy_from_real ( chain_vector, 0, ( interrupt * 4 ),
- sizeof ( *chain_vector ) );
- DBG ( "...chaining to %04x:%04x\n",
- chain_vector->segment, chain_vector->offset );
- if ( DBG_LOG ) {
- char code[64];
- copy_from_real ( code, chain_vector->segment,
- chain_vector->offset, sizeof ( code ) );
- DBG_HDA ( *chain_vector, code, sizeof ( code ) );
- }
-
- copy_to_real ( 0, ( interrupt * 4 ), &vector, sizeof ( vector ) );
- hooked_bios_interrupts++;
-}
-
-/**
- * Unhook INT vector
- *
- * @v interrupt INT number
- * @v handler Offset within .text16 to interrupt handler
- * @v chain_vector Vector containing address of previous handler
- *
- * Unhooks an i386 interrupt handler hooked by hook_i386_vector().
- * Note that this operation may fail, if some external code has hooked
- * the vector since we hooked in our handler. If it fails, it means
- * that it is not possible to unhook our handler, and we must leave it
- * (and its chaining vector) resident in memory.
- */
-int unhook_bios_interrupt ( unsigned int interrupt, unsigned int handler,
- struct segoff *chain_vector ) {
- struct segoff vector;
-
- DBG ( "Unhooking INT %#02x from %04x:%04x\n",
- interrupt, rm_cs, handler );
-
- copy_from_real ( &vector, 0, ( interrupt * 4 ), sizeof ( vector ) );
- if ( ( vector.segment != rm_cs ) || ( vector.offset != handler ) ) {
- DBG ( "...cannot unhook; vector points to %04x:%04x\n",
- vector.segment, vector.offset );
- return -EBUSY;
- }
-
- DBG ( "...restoring to %04x:%04x\n",
- chain_vector->segment, chain_vector->offset );
- copy_to_real ( 0, ( interrupt * 4 ), chain_vector,
- sizeof ( *chain_vector ) );
-
- chain_vector->segment = 0;
- chain_vector->offset = 0;
- hooked_bios_interrupts--;
- return 0;
-}
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c
deleted file mode 100644
index f0450da90..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13.c
+++ /dev/null
@@ -1,1993 +0,0 @@
-/*
- * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <byteswap.h>
-#include <errno.h>
-#include <assert.h>
-#include <ipxe/list.h>
-#include <ipxe/blockdev.h>
-#include <ipxe/io.h>
-#include <ipxe/open.h>
-#include <ipxe/uri.h>
-#include <ipxe/process.h>
-#include <ipxe/xfer.h>
-#include <ipxe/retry.h>
-#include <ipxe/timer.h>
-#include <ipxe/acpi.h>
-#include <ipxe/sanboot.h>
-#include <ipxe/device.h>
-#include <ipxe/pci.h>
-#include <ipxe/iso9660.h>
-#include <ipxe/eltorito.h>
-#include <realmode.h>
-#include <bios.h>
-#include <biosint.h>
-#include <bootsector.h>
-#include <int13.h>
-
-/** @file
- *
- * INT 13 emulation
- *
- * This module provides a mechanism for exporting block devices via
- * the BIOS INT 13 disk interrupt interface.
- *
- */
-
-/**
- * Overall timeout for INT 13 commands (independent of underlying device
- *
- * Underlying devices should ideally never become totally stuck.
- * However, if they do, then the INT 13 mechanism provides no means
- * for the caller to cancel the operation, and the machine appears to
- * hang. Use an overall timeout for all commands to avoid this
- * problem and bounce timeout failures to the caller.
- */
-#define INT13_COMMAND_TIMEOUT ( 15 * TICKS_PER_SEC )
-
-/** An INT 13 emulated drive */
-struct int13_drive {
- /** Reference count */
- struct refcnt refcnt;
- /** List of all registered drives */
- struct list_head list;
-
- /** Block device URI */
- struct uri *uri;
- /** Underlying block device interface */
- struct interface block;
-
- /** BIOS in-use drive number (0x00-0xff) */
- unsigned int drive;
- /** BIOS natural drive number (0x00-0xff)
- *
- * This is the drive number that would have been assigned by
- * 'naturally' appending the drive to the end of the BIOS
- * drive list.
- *
- * If the emulated drive replaces a preexisting drive, this is
- * the drive number that the preexisting drive gets remapped
- * to.
- */
- unsigned int natural_drive;
-
- /** Block device capacity */
- struct block_device_capacity capacity;
- /** INT 13 emulated blocksize shift
- *
- * To allow for emulation of CD-ROM access, this represents
- * the left-shift required to translate from INT 13 blocks to
- * underlying blocks.
- */
- unsigned int blksize_shift;
-
- /** Number of cylinders
- *
- * The cylinder number field in an INT 13 call is ten bits
- * wide, giving a maximum of 1024 cylinders. Conventionally,
- * when the 7.8GB limit of a CHS address is exceeded, it is
- * the number of cylinders that is increased beyond the
- * addressable limit.
- */
- unsigned int cylinders;
- /** Number of heads
- *
- * The head number field in an INT 13 call is eight bits wide,
- * giving a maximum of 256 heads. However, apparently all
- * versions of MS-DOS up to and including Win95 fail with 256
- * heads, so the maximum encountered in practice is 255.
- */
- unsigned int heads;
- /** Number of sectors per track
- *
- * The sector number field in an INT 13 call is six bits wide,
- * giving a maximum of 63 sectors, since sector numbering
- * (unlike head and cylinder numbering) starts at 1, not 0.
- */
- unsigned int sectors_per_track;
-
- /** Drive is a CD-ROM */
- int is_cdrom;
- /** Address of El Torito boot catalog (if any) */
- unsigned int boot_catalog;
-
- /** Underlying device status, if in error */
- int block_rc;
- /** Status of last operation */
- int last_status;
-};
-
-/** Vector for chaining to other INT 13 handlers */
-static struct segoff __text16 ( int13_vector );
-#define int13_vector __use_text16 ( int13_vector )
-
-/** Assembly wrapper */
-extern void int13_wrapper ( void );
-
-/** Dummy floppy disk parameter table */
-static struct int13_fdd_parameters __data16 ( int13_fdd_params ) = {
- /* 512 bytes per sector */
- .bytes_per_sector = 0x02,
- /* Highest sectors per track that we ever return */
- .sectors_per_track = 48,
-};
-#define int13_fdd_params __use_data16 ( int13_fdd_params )
-
-/** List of registered emulated drives */
-static LIST_HEAD ( int13s );
-
-/**
- * Equipment word
- *
- * This is a cached copy of the BIOS Data Area equipment word at
- * 40:10.
- */
-static uint16_t equipment_word;
-
-/**
- * Number of BIOS floppy disk drives
- *
- * This is derived from the equipment word. It is held in .text16 to
- * allow for easy access by the INT 13,08 wrapper.
- */
-static uint8_t __text16 ( num_fdds );
-#define num_fdds __use_text16 ( num_fdds )
-
-/**
- * Number of BIOS hard disk drives
- *
- * This is a cached copy of the BIOS Data Area number of hard disk
- * drives at 40:75. It is held in .text16 to allow for easy access by
- * the INT 13,08 wrapper.
- */
-static uint8_t __text16 ( num_drives );
-#define num_drives __use_text16 ( num_drives )
-
-/**
- * Calculate INT 13 drive sector size
- *
- * @v int13 Emulated drive
- * @ret blksize Sector size
- */
-static inline size_t int13_blksize ( struct int13_drive *int13 ) {
- return ( int13->capacity.blksize << int13->blksize_shift );
-}
-
-/**
- * Calculate INT 13 drive capacity
- *
- * @v int13 Emulated drive
- * @ret blocks Number of blocks
- */
-static inline uint64_t int13_capacity ( struct int13_drive *int13 ) {
- return ( int13->capacity.blocks >> int13->blksize_shift );
-}
-
-/**
- * Calculate INT 13 drive capacity (limited to 32 bits)
- *
- * @v int13 Emulated drive
- * @ret blocks Number of blocks
- */
-static inline uint32_t int13_capacity32 ( struct int13_drive *int13 ) {
- uint64_t capacity = int13_capacity ( int13 );
- return ( ( capacity <= 0xffffffffUL ) ? capacity : 0xffffffff );
-}
-
-/**
- * Test if INT 13 drive is a floppy disk drive
- *
- * @v int13 Emulated drive
- * @ret is_fdd Emulated drive is a floppy disk
- */
-static inline int int13_is_fdd ( struct int13_drive *int13 ) {
- return ( ! ( int13->drive & 0x80 ) );
-}
-
-/** An INT 13 command */
-struct int13_command {
- /** Status */
- int rc;
- /** INT 13 drive */
- struct int13_drive *int13;
- /** Underlying block device interface */
- struct interface block;
- /** Command timeout timer */
- struct retry_timer timer;
-};
-
-/**
- * Record INT 13 drive capacity
- *
- * @v command INT 13 command
- * @v capacity Block device capacity
- */
-static void int13_command_capacity ( struct int13_command *command,
- struct block_device_capacity *capacity ) {
- memcpy ( &command->int13->capacity, capacity,
- sizeof ( command->int13->capacity ) );
-}
-
-/**
- * Close INT 13 command
- *
- * @v command INT 13 command
- * @v rc Reason for close
- */
-static void int13_command_close ( struct int13_command *command, int rc ) {
- intf_restart ( &command->block, rc );
- stop_timer ( &command->timer );
- command->rc = rc;
-}
-
-/**
- * Handle INT 13 command timer expiry
- *
- * @v timer Timer
- */
-static void int13_command_expired ( struct retry_timer *timer,
- int over __unused ) {
- struct int13_command *command =
- container_of ( timer, struct int13_command, timer );
-
- int13_command_close ( command, -ETIMEDOUT );
-}
-
-/** INT 13 command interface operations */
-static struct interface_operation int13_command_op[] = {
- INTF_OP ( intf_close, struct int13_command *, int13_command_close ),
- INTF_OP ( block_capacity, struct int13_command *,
- int13_command_capacity ),
-};
-
-/** INT 13 command interface descriptor */
-static struct interface_descriptor int13_command_desc =
- INTF_DESC ( struct int13_command, block, int13_command_op );
-
-/**
- * Open (or reopen) INT 13 emulated drive underlying block device
- *
- * @v int13 Emulated drive
- * @ret rc Return status code
- */
-static int int13_reopen_block ( struct int13_drive *int13 ) {
- int rc;
-
- /* Close any existing block device */
- intf_restart ( &int13->block, -ECONNRESET );
-
- /* Open block device */
- if ( ( rc = xfer_open_uri ( &int13->block, int13->uri ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x could not reopen block "
- "device: %s\n", int13->drive, strerror ( rc ) );
- int13->block_rc = rc;
- return rc;
- }
-
- /* Clear block device error status */
- int13->block_rc = 0;
-
- return 0;
-}
-
-/**
- * Prepare to issue INT 13 command
- *
- * @v command INT 13 command
- * @v int13 Emulated drive
- * @ret rc Return status code
- */
-static int int13_command_start ( struct int13_command *command,
- struct int13_drive *int13 ) {
- int rc;
-
- /* Sanity check */
- assert ( command->int13 == NULL );
- assert ( ! timer_running ( &command->timer ) );
-
- /* Reopen block device if necessary */
- if ( ( int13->block_rc != 0 ) &&
- ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
- return rc;
-
- /* Initialise command */
- command->rc = -EINPROGRESS;
- command->int13 = int13;
- start_timer_fixed ( &command->timer, INT13_COMMAND_TIMEOUT );
-
- /* Wait for block control interface to become ready */
- while ( ( command->rc == -EINPROGRESS ) &&
- ( xfer_window ( &int13->block ) == 0 ) ) {
- step();
- }
-
- return ( ( command->rc == -EINPROGRESS ) ?
- int13->block_rc : command->rc );
-}
-
-/**
- * Wait for INT 13 command to complete
- *
- * @v command INT 13 command
- * @ret rc Return status code
- */
-static int int13_command_wait ( struct int13_command *command ) {
-
- /* Sanity check */
- assert ( timer_running ( &command->timer ) );
-
- /* Wait for command to complete */
- while ( command->rc == -EINPROGRESS )
- step();
-
- assert ( ! timer_running ( &command->timer ) );
- return command->rc;
-}
-
-/**
- * Terminate INT 13 command
- *
- * @v command INT 13 command
- */
-static void int13_command_stop ( struct int13_command *command ) {
- stop_timer ( &command->timer );
- command->int13 = NULL;
-}
-
-/** The single active INT 13 command */
-static struct int13_command int13_command = {
- .block = INTF_INIT ( int13_command_desc ),
- .timer = TIMER_INIT ( int13_command_expired ),
-};
-
-/**
- * Read from or write to INT 13 drive
- *
- * @v int13 Emulated drive
- * @v lba Starting logical block address
- * @v count Number of logical blocks
- * @v buffer Data buffer
- * @v block_rw Block read/write method
- * @ret rc Return status code
- */
-static int int13_rw ( struct int13_drive *int13, uint64_t lba,
- unsigned int count, userptr_t buffer,
- int ( * block_rw ) ( struct interface *control,
- struct interface *data,
- uint64_t lba, unsigned int count,
- userptr_t buffer, size_t len ) ) {
- struct int13_command *command = &int13_command;
- unsigned int frag_count;
- size_t frag_len;
- int rc;
-
- /* Translate to underlying blocksize */
- lba <<= int13->blksize_shift;
- count <<= int13->blksize_shift;
-
- while ( count ) {
-
- /* Determine fragment length */
- frag_count = count;
- if ( frag_count > int13->capacity.max_count )
- frag_count = int13->capacity.max_count;
- frag_len = ( int13->capacity.blksize * frag_count );
-
- /* Issue command */
- if ( ( ( rc = int13_command_start ( command, int13 ) ) != 0 ) ||
- ( ( rc = block_rw ( &int13->block, &command->block, lba,
- frag_count, buffer,
- frag_len ) ) != 0 ) ||
- ( ( rc = int13_command_wait ( command ) ) != 0 ) ) {
- int13_command_stop ( command );
- return rc;
- }
- int13_command_stop ( command );
-
- /* Move to next fragment */
- lba += frag_count;
- count -= frag_count;
- buffer = userptr_add ( buffer, frag_len );
- }
-
- return 0;
-}
-
-/**
- * Read INT 13 drive capacity
- *
- * @v int13 Emulated drive
- * @ret rc Return status code
- */
-static int int13_read_capacity ( struct int13_drive *int13 ) {
- struct int13_command *command = &int13_command;
- int rc;
-
- /* Issue command */
- if ( ( ( rc = int13_command_start ( command, int13 ) ) != 0 ) ||
- ( ( rc = block_read_capacity ( &int13->block,
- &command->block ) ) != 0 ) ||
- ( ( rc = int13_command_wait ( command ) ) != 0 ) ) {
- int13_command_stop ( command );
- return rc;
- }
-
- int13_command_stop ( command );
- return 0;
-}
-
-/**
- * Parse ISO9660 parameters
- *
- * @v int13 Emulated drive
- * @v scratch Scratch area for single-sector reads
- * @ret rc Return status code
- *
- * Reads and parses ISO9660 parameters, if present.
- */
-static int int13_parse_iso9660 ( struct int13_drive *int13, void *scratch ) {
- static const struct iso9660_primary_descriptor_fixed primary_check = {
- .type = ISO9660_TYPE_PRIMARY,
- .id = ISO9660_ID,
- };
- struct iso9660_primary_descriptor *primary = scratch;
- static const struct eltorito_descriptor_fixed boot_check = {
- .type = ISO9660_TYPE_BOOT,
- .id = ISO9660_ID,
- .version = 1,
- .system_id = "EL TORITO SPECIFICATION",
- };
- struct eltorito_descriptor *boot = scratch;
- unsigned int blksize;
- unsigned int blksize_shift;
- int rc;
-
- /* Calculate required blocksize shift */
- blksize = int13_blksize ( int13 );
- blksize_shift = 0;
- while ( blksize < ISO9660_BLKSIZE ) {
- blksize <<= 1;
- blksize_shift++;
- }
- if ( blksize > ISO9660_BLKSIZE ) {
- /* Do nothing if the blksize is invalid for CD-ROM access */
- return 0;
- }
-
- /* Read primary volume descriptor */
- if ( ( rc = int13_rw ( int13,
- ( ISO9660_PRIMARY_LBA << blksize_shift ), 1,
- virt_to_user ( primary ), block_read ) ) != 0 ){
- DBGC ( int13, "INT13 drive %02x could not read ISO9660 "
- "primary volume descriptor: %s\n",
- int13->drive, strerror ( rc ) );
- return rc;
- }
-
- /* Do nothing unless this is an ISO image */
- if ( memcmp ( primary, &primary_check, sizeof ( primary_check ) ) != 0 )
- return 0;
- DBGC ( int13, "INT13 drive %02x contains an ISO9660 filesystem; "
- "treating as CD-ROM\n", int13->drive );
- int13->is_cdrom = 1;
-
- /* Read boot record volume descriptor */
- if ( ( rc = int13_rw ( int13,
- ( ELTORITO_LBA << blksize_shift ), 1,
- virt_to_user ( boot ), block_read ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x could not read El Torito boot "
- "record volume descriptor: %s\n",
- int13->drive, strerror ( rc ) );
- return rc;
- }
-
- /* Check for an El Torito boot catalog */
- if ( memcmp ( boot, &boot_check, sizeof ( boot_check ) ) == 0 ) {
- int13->boot_catalog = boot->sector;
- DBGC ( int13, "INT13 drive %02x has an El Torito boot catalog "
- "at LBA %08x\n", int13->drive, int13->boot_catalog );
- } else {
- DBGC ( int13, "INT13 drive %02x has no El Torito boot "
- "catalog\n", int13->drive );
- }
-
- /* Configure drive for no-emulation CD-ROM access */
- int13->blksize_shift += blksize_shift;
-
- return 0;
-}
-
-/**
- * Guess INT 13 hard disk drive geometry
- *
- * @v int13 Emulated drive
- * @v scratch Scratch area for single-sector reads
- * @ret heads Guessed number of heads
- * @ret sectors Guessed number of sectors per track
- * @ret rc Return status code
- *
- * Guesses the drive geometry by inspecting the partition table.
- */
-static int int13_guess_geometry_hdd ( struct int13_drive *int13, void *scratch,
- unsigned int *heads,
- unsigned int *sectors ) {
- struct master_boot_record *mbr = scratch;
- struct partition_table_entry *partition;
- unsigned int i;
- int rc;
-
- /* Default guess is xx/255/63 */
- *heads = 255;
- *sectors = 63;
-
- /* Read partition table */
- if ( ( rc = int13_rw ( int13, 0, 1, virt_to_user ( mbr ),
- block_read ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x could not read "
- "partition table to guess geometry: %s\n",
- int13->drive, strerror ( rc ) );
- return rc;
- }
- DBGC2 ( int13, "INT13 drive %02x has MBR:\n", int13->drive );
- DBGC2_HDA ( int13, 0, mbr, sizeof ( *mbr ) );
- DBGC ( int13, "INT13 drive %02x has signature %08x\n",
- int13->drive, mbr->signature );
-
- /* Scan through partition table and modify guesses for
- * heads and sectors_per_track if we find any used
- * partitions.
- */
- for ( i = 0 ; i < 4 ; i++ ) {
- partition = &mbr->partitions[i];
- if ( ! partition->type )
- continue;
- *heads = ( PART_HEAD ( partition->chs_end ) + 1 );
- *sectors = PART_SECTOR ( partition->chs_end );
- DBGC ( int13, "INT13 drive %02x guessing C/H/S xx/%d/%d based "
- "on partition %d\n",
- int13->drive, *heads, *sectors, ( i + 1 ) );
- }
-
- return 0;
-}
-
-/** Recognised floppy disk geometries */
-static const struct int13_fdd_geometry int13_fdd_geometries[] = {
- INT13_FDD_GEOMETRY ( 40, 1, 8 ),
- INT13_FDD_GEOMETRY ( 40, 1, 9 ),
- INT13_FDD_GEOMETRY ( 40, 2, 8 ),
- INT13_FDD_GEOMETRY ( 40, 1, 9 ),
- INT13_FDD_GEOMETRY ( 80, 2, 8 ),
- INT13_FDD_GEOMETRY ( 80, 2, 9 ),
- INT13_FDD_GEOMETRY ( 80, 2, 15 ),
- INT13_FDD_GEOMETRY ( 80, 2, 18 ),
- INT13_FDD_GEOMETRY ( 80, 2, 20 ),
- INT13_FDD_GEOMETRY ( 80, 2, 21 ),
- INT13_FDD_GEOMETRY ( 82, 2, 21 ),
- INT13_FDD_GEOMETRY ( 83, 2, 21 ),
- INT13_FDD_GEOMETRY ( 80, 2, 22 ),
- INT13_FDD_GEOMETRY ( 80, 2, 23 ),
- INT13_FDD_GEOMETRY ( 80, 2, 24 ),
- INT13_FDD_GEOMETRY ( 80, 2, 36 ),
- INT13_FDD_GEOMETRY ( 80, 2, 39 ),
- INT13_FDD_GEOMETRY ( 80, 2, 40 ),
- INT13_FDD_GEOMETRY ( 80, 2, 44 ),
- INT13_FDD_GEOMETRY ( 80, 2, 48 ),
-};
-
-/**
- * Guess INT 13 floppy disk drive geometry
- *
- * @v int13 Emulated drive
- * @ret heads Guessed number of heads
- * @ret sectors Guessed number of sectors per track
- * @ret rc Return status code
- *
- * Guesses the drive geometry by inspecting the disk size.
- */
-static int int13_guess_geometry_fdd ( struct int13_drive *int13,
- unsigned int *heads,
- unsigned int *sectors ) {
- unsigned int blocks = int13_capacity ( int13 );
- const struct int13_fdd_geometry *geometry;
- unsigned int cylinders;
- unsigned int i;
-
- /* Look for a match against a known geometry */
- for ( i = 0 ; i < ( sizeof ( int13_fdd_geometries ) /
- sizeof ( int13_fdd_geometries[0] ) ) ; i++ ) {
- geometry = &int13_fdd_geometries[i];
- cylinders = INT13_FDD_CYLINDERS ( geometry );
- *heads = INT13_FDD_HEADS ( geometry );
- *sectors = INT13_FDD_SECTORS ( geometry );
- if ( ( cylinders * (*heads) * (*sectors) ) == blocks ) {
- DBGC ( int13, "INT13 drive %02x guessing C/H/S "
- "%d/%d/%d based on size %dK\n", int13->drive,
- cylinders, *heads, *sectors, ( blocks / 2 ) );
- return 0;
- }
- }
-
- /* Otherwise, assume a partial disk image in the most common
- * format (1440K, 80/2/18).
- */
- *heads = 2;
- *sectors = 18;
- DBGC ( int13, "INT13 drive %02x guessing C/H/S xx/%d/%d based on size "
- "%dK\n", int13->drive, *heads, *sectors, ( blocks / 2 ) );
- return 0;
-}
-
-/**
- * Guess INT 13 drive geometry
- *
- * @v int13 Emulated drive
- * @v scratch Scratch area for single-sector reads
- * @ret rc Return status code
- */
-static int int13_guess_geometry ( struct int13_drive *int13, void *scratch ) {
- unsigned int guessed_heads;
- unsigned int guessed_sectors;
- unsigned int blocks;
- unsigned int blocks_per_cyl;
- int rc;
-
- /* Don't even try when the blksize is invalid for C/H/S access */
- if ( int13_blksize ( int13 ) != INT13_BLKSIZE )
- return 0;
-
- /* Guess geometry according to drive type */
- if ( int13_is_fdd ( int13 ) ) {
- if ( ( rc = int13_guess_geometry_fdd ( int13, &guessed_heads,
- &guessed_sectors )) != 0)
- return rc;
- } else {
- if ( ( rc = int13_guess_geometry_hdd ( int13, scratch,
- &guessed_heads,
- &guessed_sectors )) != 0)
- return rc;
- }
-
- /* Apply guesses if no geometry already specified */
- if ( ! int13->heads )
- int13->heads = guessed_heads;
- if ( ! int13->sectors_per_track )
- int13->sectors_per_track = guessed_sectors;
- if ( ! int13->cylinders ) {
- /* Avoid attempting a 64-bit divide on a 32-bit system */
- blocks = int13_capacity32 ( int13 );
- blocks_per_cyl = ( int13->heads * int13->sectors_per_track );
- assert ( blocks_per_cyl != 0 );
- int13->cylinders = ( blocks / blocks_per_cyl );
- if ( int13->cylinders > 1024 )
- int13->cylinders = 1024;
- }
-
- return 0;
-}
-
-/**
- * Update BIOS drive count
- */
-static void int13_sync_num_drives ( void ) {
- struct int13_drive *int13;
- uint8_t *counter;
- uint8_t max_drive;
- uint8_t required;
-
- /* Get current drive counts */
- get_real ( equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
- get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
- num_fdds = ( ( equipment_word & 0x0001 ) ?
- ( ( ( equipment_word >> 6 ) & 0x3 ) + 1 ) : 0 );
-
- /* Ensure count is large enough to cover all of our emulated drives */
- list_for_each_entry ( int13, &int13s, list ) {
- counter = ( int13_is_fdd ( int13 ) ? &num_fdds : &num_drives );
- max_drive = int13->drive;
- if ( max_drive < int13->natural_drive )
- max_drive = int13->natural_drive;
- required = ( ( max_drive & 0x7f ) + 1 );
- if ( *counter < required ) {
- *counter = required;
- DBGC ( int13, "INT13 drive %02x added to drive count: "
- "%d HDDs, %d FDDs\n",
- int13->drive, num_drives, num_fdds );
- }
- }
-
- /* Update current drive count */
- equipment_word &= ~( ( 0x3 << 6 ) | 0x0001 );
- if ( num_fdds ) {
- equipment_word |= ( 0x0001 |
- ( ( ( num_fdds - 1 ) & 0x3 ) << 6 ) );
- }
- put_real ( equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
- put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
-}
-
-/**
- * Check number of drives
- */
-static void int13_check_num_drives ( void ) {
- uint16_t check_equipment_word;
- uint8_t check_num_drives;
-
- get_real ( check_equipment_word, BDA_SEG, BDA_EQUIPMENT_WORD );
- get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
- if ( ( check_equipment_word != equipment_word ) ||
- ( check_num_drives != num_drives ) ) {
- int13_sync_num_drives();
- }
-}
-
-/**
- * INT 13, 00 - Reset disk system
- *
- * @v int13 Emulated drive
- * @ret status Status code
- */
-static int int13_reset ( struct int13_drive *int13,
- struct i386_all_regs *ix86 __unused ) {
- int rc;
-
- DBGC2 ( int13, "Reset drive\n" );
-
- /* Reopen underlying block device */
- if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
- return -INT13_STATUS_RESET_FAILED;
-
- /* Check that block device is functional */
- if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
- return -INT13_STATUS_RESET_FAILED;
-
- return 0;
-}
-
-/**
- * INT 13, 01 - Get status of last operation
- *
- * @v int13 Emulated drive
- * @ret status Status code
- */
-static int int13_get_last_status ( struct int13_drive *int13,
- struct i386_all_regs *ix86 __unused ) {
- DBGC2 ( int13, "Get status of last operation\n" );
- return int13->last_status;
-}
-
-/**
- * Read / write sectors
- *
- * @v int13 Emulated drive
- * @v al Number of sectors to read or write (must be nonzero)
- * @v ch Low bits of cylinder number
- * @v cl (bits 7:6) High bits of cylinder number
- * @v cl (bits 5:0) Sector number
- * @v dh Head number
- * @v es:bx Data buffer
- * @v block_rw Block read/write method
- * @ret status Status code
- * @ret al Number of sectors read or written
- */
-static int int13_rw_sectors ( struct int13_drive *int13,
- struct i386_all_regs *ix86,
- int ( * block_rw ) ( struct interface *control,
- struct interface *data,
- uint64_t lba,
- unsigned int count,
- userptr_t buffer,
- size_t len ) ) {
- unsigned int cylinder, head, sector;
- unsigned long lba;
- unsigned int count;
- userptr_t buffer;
- int rc;
-
- /* Validate blocksize */
- if ( int13_blksize ( int13 ) != INT13_BLKSIZE ) {
- DBGC ( int13, "\nINT 13 drive %02x invalid blocksize (%zd) "
- "for non-extended read/write\n",
- int13->drive, int13_blksize ( int13 ) );
- return -INT13_STATUS_INVALID;
- }
-
- /* Calculate parameters */
- cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
- head = ix86->regs.dh;
- sector = ( ix86->regs.cl & 0x3f );
- if ( ( cylinder >= int13->cylinders ) ||
- ( head >= int13->heads ) ||
- ( sector < 1 ) || ( sector > int13->sectors_per_track ) ) {
- DBGC ( int13, "C/H/S %d/%d/%d out of range for geometry "
- "%d/%d/%d\n", cylinder, head, sector, int13->cylinders,
- int13->heads, int13->sectors_per_track );
- return -INT13_STATUS_INVALID;
- }
- lba = ( ( ( ( cylinder * int13->heads ) + head )
- * int13->sectors_per_track ) + sector - 1 );
- count = ix86->regs.al;
- buffer = real_to_user ( ix86->segs.es, ix86->regs.bx );
-
- DBGC2 ( int13, "C/H/S %d/%d/%d = LBA %08lx <-> %04x:%04x (count %d)\n",
- cylinder, head, sector, lba, ix86->segs.es, ix86->regs.bx,
- count );
-
- /* Read from / write to block device */
- if ( ( rc = int13_rw ( int13, lba, count, buffer, block_rw ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x I/O failed: %s\n",
- int13->drive, strerror ( rc ) );
- return -INT13_STATUS_READ_ERROR;
- }
-
- return 0;
-}
-
-/**
- * INT 13, 02 - Read sectors
- *
- * @v int13 Emulated drive
- * @v al Number of sectors to read (must be nonzero)
- * @v ch Low bits of cylinder number
- * @v cl (bits 7:6) High bits of cylinder number
- * @v cl (bits 5:0) Sector number
- * @v dh Head number
- * @v es:bx Data buffer
- * @ret status Status code
- * @ret al Number of sectors read
- */
-static int int13_read_sectors ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- DBGC2 ( int13, "Read: " );
- return int13_rw_sectors ( int13, ix86, block_read );
-}
-
-/**
- * INT 13, 03 - Write sectors
- *
- * @v int13 Emulated drive
- * @v al Number of sectors to write (must be nonzero)
- * @v ch Low bits of cylinder number
- * @v cl (bits 7:6) High bits of cylinder number
- * @v cl (bits 5:0) Sector number
- * @v dh Head number
- * @v es:bx Data buffer
- * @ret status Status code
- * @ret al Number of sectors written
- */
-static int int13_write_sectors ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- DBGC2 ( int13, "Write: " );
- return int13_rw_sectors ( int13, ix86, block_write );
-}
-
-/**
- * INT 13, 08 - Get drive parameters
- *
- * @v int13 Emulated drive
- * @ret status Status code
- * @ret ch Low bits of maximum cylinder number
- * @ret cl (bits 7:6) High bits of maximum cylinder number
- * @ret cl (bits 5:0) Maximum sector number
- * @ret dh Maximum head number
- * @ret dl Number of drives
- */
-static int int13_get_parameters ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- unsigned int max_cylinder = int13->cylinders - 1;
- unsigned int max_head = int13->heads - 1;
- unsigned int max_sector = int13->sectors_per_track; /* sic */
-
- DBGC2 ( int13, "Get drive parameters\n" );
-
- /* Validate blocksize */
- if ( int13_blksize ( int13 ) != INT13_BLKSIZE ) {
- DBGC ( int13, "\nINT 13 drive %02x invalid blocksize (%zd) "
- "for non-extended parameters\n",
- int13->drive, int13_blksize ( int13 ) );
- return -INT13_STATUS_INVALID;
- }
-
- /* Common parameters */
- ix86->regs.ch = ( max_cylinder & 0xff );
- ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
- ix86->regs.dh = max_head;
- ix86->regs.dl = ( int13_is_fdd ( int13 ) ? num_fdds : num_drives );
-
- /* Floppy-specific parameters */
- if ( int13_is_fdd ( int13 ) ) {
- ix86->regs.bl = INT13_FDD_TYPE_1M44;
- ix86->segs.es = rm_ds;
- ix86->regs.di = __from_data16 ( &int13_fdd_params );
- }
-
- return 0;
-}
-
-/**
- * INT 13, 15 - Get disk type
- *
- * @v int13 Emulated drive
- * @ret ah Type code
- * @ret cx:dx Sector count
- * @ret status Status code / disk type
- */
-static int int13_get_disk_type ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- uint32_t blocks;
-
- DBGC2 ( int13, "Get disk type\n" );
-
- if ( int13_is_fdd ( int13 ) ) {
- return INT13_DISK_TYPE_FDD;
- } else {
- blocks = int13_capacity32 ( int13 );
- ix86->regs.cx = ( blocks >> 16 );
- ix86->regs.dx = ( blocks & 0xffff );
- return INT13_DISK_TYPE_HDD;
- }
-}
-
-/**
- * INT 13, 41 - Extensions installation check
- *
- * @v int13 Emulated drive
- * @v bx 0x55aa
- * @ret bx 0xaa55
- * @ret cx Extensions API support bitmap
- * @ret status Status code / API version
- */
-static int int13_extension_check ( struct int13_drive *int13 __unused,
- struct i386_all_regs *ix86 ) {
- if ( ix86->regs.bx == 0x55aa ) {
- DBGC2 ( int13, "INT13 extensions installation check\n" );
- ix86->regs.bx = 0xaa55;
- ix86->regs.cx = ( INT13_EXTENSION_LINEAR |
- INT13_EXTENSION_EDD |
- INT13_EXTENSION_64BIT );
- return INT13_EXTENSION_VER_3_0;
- } else {
- return -INT13_STATUS_INVALID;
- }
-}
-
-/**
- * Extended read / write
- *
- * @v int13 Emulated drive
- * @v ds:si Disk address packet
- * @v block_rw Block read/write method
- * @ret status Status code
- */
-static int int13_extended_rw ( struct int13_drive *int13,
- struct i386_all_regs *ix86,
- int ( * block_rw ) ( struct interface *control,
- struct interface *data,
- uint64_t lba,
- unsigned int count,
- userptr_t buffer,
- size_t len ) ) {
- struct int13_disk_address addr;
- uint8_t bufsize;
- uint64_t lba;
- unsigned long count;
- userptr_t buffer;
- int rc;
-
- /* Extended reads are not allowed on floppy drives.
- * ELTORITO.SYS seems to assume that we are really a CD-ROM if
- * we support extended reads for a floppy drive.
- */
- if ( int13_is_fdd ( int13 ) )
- return -INT13_STATUS_INVALID;
-
- /* Get buffer size */
- get_real ( bufsize, ix86->segs.ds,
- ( ix86->regs.si + offsetof ( typeof ( addr ), bufsize ) ) );
- if ( bufsize < offsetof ( typeof ( addr ), buffer_phys ) ) {
- DBGC2 ( int13, "<invalid buffer size %#02x\n>\n", bufsize );
- return -INT13_STATUS_INVALID;
- }
-
- /* Read parameters from disk address structure */
- memset ( &addr, 0, sizeof ( addr ) );
- copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, bufsize );
- lba = addr.lba;
- DBGC2 ( int13, "LBA %08llx <-> ", ( ( unsigned long long ) lba ) );
- if ( ( addr.count == 0xff ) ||
- ( ( addr.buffer.segment == 0xffff ) &&
- ( addr.buffer.offset == 0xffff ) ) ) {
- buffer = phys_to_user ( addr.buffer_phys );
- DBGC2 ( int13, "%08llx",
- ( ( unsigned long long ) addr.buffer_phys ) );
- } else {
- buffer = real_to_user ( addr.buffer.segment,
- addr.buffer.offset );
- DBGC2 ( int13, "%04x:%04x", addr.buffer.segment,
- addr.buffer.offset );
- }
- if ( addr.count <= 0x7f ) {
- count = addr.count;
- } else if ( addr.count == 0xff ) {
- count = addr.long_count;
- } else {
- DBGC2 ( int13, " <invalid count %#02x>\n", addr.count );
- return -INT13_STATUS_INVALID;
- }
- DBGC2 ( int13, " (count %ld)\n", count );
-
- /* Read from / write to block device */
- if ( ( rc = int13_rw ( int13, lba, count, buffer, block_rw ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x extended I/O failed: %s\n",
- int13->drive, strerror ( rc ) );
- /* Record that no blocks were transferred successfully */
- addr.count = 0;
- put_real ( addr.count, ix86->segs.ds,
- ( ix86->regs.si +
- offsetof ( typeof ( addr ), count ) ) );
- return -INT13_STATUS_READ_ERROR;
- }
-
- return 0;
-}
-
-/**
- * INT 13, 42 - Extended read
- *
- * @v int13 Emulated drive
- * @v ds:si Disk address packet
- * @ret status Status code
- */
-static int int13_extended_read ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- DBGC2 ( int13, "Extended read: " );
- return int13_extended_rw ( int13, ix86, block_read );
-}
-
-/**
- * INT 13, 43 - Extended write
- *
- * @v int13 Emulated drive
- * @v ds:si Disk address packet
- * @ret status Status code
- */
-static int int13_extended_write ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- DBGC2 ( int13, "Extended write: " );
- return int13_extended_rw ( int13, ix86, block_write );
-}
-
-/**
- * INT 13, 44 - Verify sectors
- *
- * @v int13 Emulated drive
- * @v ds:si Disk address packet
- * @ret status Status code
- */
-static int int13_extended_verify ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- struct int13_disk_address addr;
- uint64_t lba;
- unsigned long count;
-
- /* Read parameters from disk address structure */
- if ( DBG_EXTRA ) {
- copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
- sizeof ( addr ));
- lba = addr.lba;
- count = addr.count;
- DBGC2 ( int13, "Verify: LBA %08llx (count %ld)\n",
- ( ( unsigned long long ) lba ), count );
- }
-
- /* We have no mechanism for verifying sectors */
- return -INT13_STATUS_INVALID;
-}
-
-/**
- * INT 13, 44 - Extended seek
- *
- * @v int13 Emulated drive
- * @v ds:si Disk address packet
- * @ret status Status code
- */
-static int int13_extended_seek ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- struct int13_disk_address addr;
- uint64_t lba;
- unsigned long count;
-
- /* Read parameters from disk address structure */
- if ( DBG_EXTRA ) {
- copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si,
- sizeof ( addr ));
- lba = addr.lba;
- count = addr.count;
- DBGC2 ( int13, "Seek: LBA %08llx (count %ld)\n",
- ( ( unsigned long long ) lba ), count );
- }
-
- /* Ignore and return success */
- return 0;
-}
-
-/**
- * Build device path information
- *
- * @v int13 Emulated drive
- * @v dpi Device path information
- * @ret rc Return status code
- */
-static int int13_device_path_info ( struct int13_drive *int13,
- struct edd_device_path_information *dpi ) {
- struct device *device;
- struct device_description *desc;
- unsigned int i;
- uint8_t sum = 0;
- int rc;
-
- /* Reopen block device if necessary */
- if ( ( int13->block_rc != 0 ) &&
- ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
- return rc;
-
- /* Get underlying hardware device */
- device = identify_device ( &int13->block );
- if ( ! device ) {
- DBGC ( int13, "INT13 drive %02x cannot identify hardware "
- "device\n", int13->drive );
- return -ENODEV;
- }
-
- /* Fill in bus type and interface path */
- desc = &device->desc;
- switch ( desc->bus_type ) {
- case BUS_TYPE_PCI:
- dpi->host_bus_type.type = EDD_BUS_TYPE_PCI;
- dpi->interface_path.pci.bus = PCI_BUS ( desc->location );
- dpi->interface_path.pci.slot = PCI_SLOT ( desc->location );
- dpi->interface_path.pci.function = PCI_FUNC ( desc->location );
- dpi->interface_path.pci.channel = 0xff; /* unused */
- break;
- default:
- DBGC ( int13, "INT13 drive %02x unrecognised bus type %d\n",
- int13->drive, desc->bus_type );
- return -ENOTSUP;
- }
-
- /* Get EDD block device description */
- if ( ( rc = edd_describe ( &int13->block, &dpi->interface_type,
- &dpi->device_path ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x cannot identify block device: "
- "%s\n", int13->drive, strerror ( rc ) );
- return rc;
- }
-
- /* Fill in common fields and fix checksum */
- dpi->key = EDD_DEVICE_PATH_INFO_KEY;
- dpi->len = sizeof ( *dpi );
- for ( i = 0 ; i < sizeof ( *dpi ) ; i++ )
- sum += *( ( ( uint8_t * ) dpi ) + i );
- dpi->checksum -= sum;
-
- return 0;
-}
-
-/**
- * INT 13, 48 - Get extended parameters
- *
- * @v int13 Emulated drive
- * @v ds:si Drive parameter table
- * @ret status Status code
- */
-static int int13_get_extended_parameters ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- struct int13_disk_parameters params;
- struct segoff address;
- size_t len = sizeof ( params );
- uint16_t bufsize;
- int rc;
-
- /* Get buffer size */
- get_real ( bufsize, ix86->segs.ds,
- ( ix86->regs.si + offsetof ( typeof ( params ), bufsize )));
-
- DBGC2 ( int13, "Get extended drive parameters to %04x:%04x+%02x\n",
- ix86->segs.ds, ix86->regs.si, bufsize );
-
- /* Build drive parameters */
- memset ( &params, 0, sizeof ( params ) );
- params.flags = INT13_FL_DMA_TRANSPARENT;
- if ( ( int13->cylinders < 1024 ) &&
- ( int13_capacity ( int13 ) <= INT13_MAX_CHS_SECTORS ) ) {
- params.flags |= INT13_FL_CHS_VALID;
- }
- params.cylinders = int13->cylinders;
- params.heads = int13->heads;
- params.sectors_per_track = int13->sectors_per_track;
- params.sectors = int13_capacity ( int13 );
- params.sector_size = int13_blksize ( int13 );
- memset ( &params.dpte, 0xff, sizeof ( params.dpte ) );
- if ( ( rc = int13_device_path_info ( int13, &params.dpi ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x could not provide device "
- "path information: %s\n",
- int13->drive, strerror ( rc ) );
- len = offsetof ( typeof ( params ), dpi );
- }
-
- /* Calculate returned "buffer size" (which will be less than
- * the length actually copied if device path information is
- * present).
- */
- if ( bufsize < offsetof ( typeof ( params ), dpte ) )
- return -INT13_STATUS_INVALID;
- if ( bufsize < offsetof ( typeof ( params ), dpi ) ) {
- params.bufsize = offsetof ( typeof ( params ), dpte );
- } else {
- params.bufsize = offsetof ( typeof ( params ), dpi );
- }
-
- DBGC ( int13, "INT 13 drive %02x described using extended "
- "parameters:\n", int13->drive );
- address.segment = ix86->segs.ds;
- address.offset = ix86->regs.si;
- DBGC_HDA ( int13, address, &params, len );
-
- /* Return drive parameters */
- if ( len > bufsize )
- len = bufsize;
- copy_to_real ( ix86->segs.ds, ix86->regs.si, &params, len );
-
- return 0;
-}
-
-/**
- * INT 13, 4b - Get status or terminate CD-ROM emulation
- *
- * @v int13 Emulated drive
- * @v ds:si Specification packet
- * @ret status Status code
- */
-static int int13_cdrom_status_terminate ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- struct int13_cdrom_specification specification;
-
- DBGC2 ( int13, "Get CD-ROM emulation status to %04x:%04x%s\n",
- ix86->segs.ds, ix86->regs.si,
- ( ix86->regs.al ? "" : " and terminate" ) );
-
- /* Fail if we are not a CD-ROM */
- if ( ! int13->is_cdrom ) {
- DBGC ( int13, "INT13 drive %02x is not a CD-ROM\n",
- int13->drive );
- return -INT13_STATUS_INVALID;
- }
-
- /* Build specification packet */
- memset ( &specification, 0, sizeof ( specification ) );
- specification.size = sizeof ( specification );
- specification.drive = int13->drive;
-
- /* Return specification packet */
- copy_to_real ( ix86->segs.ds, ix86->regs.si, &specification,
- sizeof ( specification ) );
-
- return 0;
-}
-
-
-/**
- * INT 13, 4d - Read CD-ROM boot catalog
- *
- * @v int13 Emulated drive
- * @v ds:si Command packet
- * @ret status Status code
- */
-static int int13_cdrom_read_boot_catalog ( struct int13_drive *int13,
- struct i386_all_regs *ix86 ) {
- struct int13_cdrom_boot_catalog_command command;
- int rc;
-
- /* Read parameters from command packet */
- copy_from_real ( &command, ix86->segs.ds, ix86->regs.si,
- sizeof ( command ) );
- DBGC2 ( int13, "Read CD-ROM boot catalog to %08x\n", command.buffer );
-
- /* Fail if we have no boot catalog */
- if ( ! int13->boot_catalog ) {
- DBGC ( int13, "INT13 drive %02x has no boot catalog\n",
- int13->drive );
- return -INT13_STATUS_INVALID;
- }
-
- /* Read from boot catalog */
- if ( ( rc = int13_rw ( int13, ( int13->boot_catalog + command.start ),
- command.count, phys_to_user ( command.buffer ),
- block_read ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x could not read boot catalog: "
- "%s\n", int13->drive, strerror ( rc ) );
- return -INT13_STATUS_READ_ERROR;
- }
-
- return 0;
-}
-
-/**
- * INT 13 handler
- *
- */
-static __asmcall void int13 ( struct i386_all_regs *ix86 ) {
- int command = ix86->regs.ah;
- unsigned int bios_drive = ix86->regs.dl;
- struct int13_drive *int13;
- int status;
-
- /* Check BIOS hasn't killed off our drive */
- int13_check_num_drives();
-
- list_for_each_entry ( int13, &int13s, list ) {
-
- if ( bios_drive != int13->drive ) {
- /* Remap any accesses to this drive's natural number */
- if ( bios_drive == int13->natural_drive ) {
- DBGC2 ( int13, "INT13,%02x (%02x) remapped to "
- "(%02x)\n", ix86->regs.ah,
- bios_drive, int13->drive );
- ix86->regs.dl = int13->drive;
- return;
- } else if ( ( ( bios_drive & 0x7f ) == 0x7f ) &&
- ( command == INT13_CDROM_STATUS_TERMINATE )
- && int13->is_cdrom ) {
- /* Catch non-drive-specific CD-ROM calls */
- } else {
- continue;
- }
- }
-
- DBGC2 ( int13, "INT13,%02x (%02x): ",
- ix86->regs.ah, bios_drive );
-
- switch ( command ) {
- case INT13_RESET:
- status = int13_reset ( int13, ix86 );
- break;
- case INT13_GET_LAST_STATUS:
- status = int13_get_last_status ( int13, ix86 );
- break;
- case INT13_READ_SECTORS:
- status = int13_read_sectors ( int13, ix86 );
- break;
- case INT13_WRITE_SECTORS:
- status = int13_write_sectors ( int13, ix86 );
- break;
- case INT13_GET_PARAMETERS:
- status = int13_get_parameters ( int13, ix86 );
- break;
- case INT13_GET_DISK_TYPE:
- status = int13_get_disk_type ( int13, ix86 );
- break;
- case INT13_EXTENSION_CHECK:
- status = int13_extension_check ( int13, ix86 );
- break;
- case INT13_EXTENDED_READ:
- status = int13_extended_read ( int13, ix86 );
- break;
- case INT13_EXTENDED_WRITE:
- status = int13_extended_write ( int13, ix86 );
- break;
- case INT13_EXTENDED_VERIFY:
- status = int13_extended_verify ( int13, ix86 );
- break;
- case INT13_EXTENDED_SEEK:
- status = int13_extended_seek ( int13, ix86 );
- break;
- case INT13_GET_EXTENDED_PARAMETERS:
- status = int13_get_extended_parameters ( int13, ix86 );
- break;
- case INT13_CDROM_STATUS_TERMINATE:
- status = int13_cdrom_status_terminate ( int13, ix86 );
- break;
- case INT13_CDROM_READ_BOOT_CATALOG:
- status = int13_cdrom_read_boot_catalog ( int13, ix86 );
- break;
- default:
- DBGC2 ( int13, "*** Unrecognised INT13 ***\n" );
- status = -INT13_STATUS_INVALID;
- break;
- }
-
- /* Store status for INT 13,01 */
- int13->last_status = status;
-
- /* Negative status indicates an error */
- if ( status < 0 ) {
- status = -status;
- DBGC ( int13, "INT13,%02x (%02x) failed with status "
- "%02x\n", ix86->regs.ah, int13->drive, status );
- } else {
- ix86->flags &= ~CF;
- }
- ix86->regs.ah = status;
-
- /* Set OF to indicate to wrapper not to chain this call */
- ix86->flags |= OF;
-
- return;
- }
-}
-
-/**
- * Hook INT 13 handler
- *
- */
-static void int13_hook_vector ( void ) {
- /* Assembly wrapper to call int13(). int13() sets OF if we
- * should not chain to the previous handler. (The wrapper
- * clears CF and OF before calling int13()).
- */
- __asm__ __volatile__ (
- TEXT16_CODE ( "\nint13_wrapper:\n\t"
- /* Preserve %ax and %dx for future reference */
- "pushw %%bp\n\t"
- "movw %%sp, %%bp\n\t"
- "pushw %%ax\n\t"
- "pushw %%dx\n\t"
- /* Clear OF, set CF, call int13() */
- "orb $0, %%al\n\t"
- "stc\n\t"
- "pushl %0\n\t"
- "pushw %%cs\n\t"
- "call prot_call\n\t"
- /* Chain if OF not set */
- "jo 1f\n\t"
- "pushfw\n\t"
- "lcall *%%cs:int13_vector\n\t"
- "\n1:\n\t"
- /* Overwrite flags for iret */
- "pushfw\n\t"
- "popw 6(%%bp)\n\t"
- /* Fix up %dl:
- *
- * INT 13,15 : do nothing if hard disk
- * INT 13,08 : load with number of drives
- * all others: restore original value
- */
- "cmpb $0x15, -1(%%bp)\n\t"
- "jne 2f\n\t"
- "testb $0x80, -4(%%bp)\n\t"
- "jnz 3f\n\t"
- "\n2:\n\t"
- "movb -4(%%bp), %%dl\n\t"
- "cmpb $0x08, -1(%%bp)\n\t"
- "jne 3f\n\t"
- "testb $0x80, %%dl\n\t"
- "movb %%cs:num_drives, %%dl\n\t"
- "jnz 3f\n\t"
- "movb %%cs:num_fdds, %%dl\n\t"
- /* Return */
- "\n3:\n\t"
- "movw %%bp, %%sp\n\t"
- "popw %%bp\n\t"
- "iret\n\t" )
- : : "i" ( int13 ) );
-
- hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
- &int13_vector );
-}
-
-/**
- * Unhook INT 13 handler
- */
-static void int13_unhook_vector ( void ) {
- unhook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
- &int13_vector );
-}
-
-/**
- * Check INT13 emulated drive flow control window
- *
- * @v int13 Emulated drive
- */
-static size_t int13_block_window ( struct int13_drive *int13 __unused ) {
-
- /* We are never ready to receive data via this interface.
- * This prevents objects that support both block and stream
- * interfaces from attempting to send us stream data.
- */
- return 0;
-}
-
-/**
- * Handle INT 13 emulated drive underlying block device closing
- *
- * @v int13 Emulated drive
- * @v rc Reason for close
- */
-static void int13_block_close ( struct int13_drive *int13, int rc ) {
-
- /* Any closing is an error from our point of view */
- if ( rc == 0 )
- rc = -ENOTCONN;
-
- DBGC ( int13, "INT13 drive %02x went away: %s\n",
- int13->drive, strerror ( rc ) );
-
- /* Record block device error code */
- int13->block_rc = rc;
-
- /* Shut down interfaces */
- intf_restart ( &int13->block, rc );
-}
-
-/** INT 13 drive interface operations */
-static struct interface_operation int13_block_op[] = {
- INTF_OP ( xfer_window, struct int13_drive *, int13_block_window ),
- INTF_OP ( intf_close, struct int13_drive *, int13_block_close ),
-};
-
-/** INT 13 drive interface descriptor */
-static struct interface_descriptor int13_block_desc =
- INTF_DESC ( struct int13_drive, block, int13_block_op );
-
-/**
- * Free INT 13 emulated drive
- *
- * @v refcnt Reference count
- */
-static void int13_free ( struct refcnt *refcnt ) {
- struct int13_drive *int13 =
- container_of ( refcnt, struct int13_drive, refcnt );
-
- uri_put ( int13->uri );
- free ( int13 );
-}
-
-/**
- * Hook INT 13 emulated drive
- *
- * @v uri URI
- * @v drive Drive number
- * @ret rc Return status code
- *
- * Registers the drive with the INT 13 emulation subsystem, and hooks
- * the INT 13 interrupt vector (if not already hooked).
- */
-static int int13_hook ( struct uri *uri, unsigned int drive ) {
- struct int13_drive *int13;
- unsigned int natural_drive;
- void *scratch;
- int rc;
-
- /* Calculate natural drive number */
- int13_sync_num_drives();
- natural_drive = ( ( drive & 0x80 ) ? ( num_drives | 0x80 ) : num_fdds );
-
- /* Check that drive number is not in use */
- list_for_each_entry ( int13, &int13s, list ) {
- if ( int13->drive == drive ) {
- rc = -EADDRINUSE;
- goto err_in_use;
- }
- }
-
- /* Allocate and initialise structure */
- int13 = zalloc ( sizeof ( *int13 ) );
- if ( ! int13 ) {
- rc = -ENOMEM;
- goto err_zalloc;
- }
- ref_init ( &int13->refcnt, int13_free );
- intf_init ( &int13->block, &int13_block_desc, &int13->refcnt );
- int13->uri = uri_get ( uri );
- int13->drive = drive;
- int13->natural_drive = natural_drive;
-
- /* Open block device interface */
- if ( ( rc = int13_reopen_block ( int13 ) ) != 0 )
- goto err_reopen_block;
-
- /* Read device capacity */
- if ( ( rc = int13_read_capacity ( int13 ) ) != 0 )
- goto err_read_capacity;
-
- /* Allocate scratch area */
- scratch = malloc ( int13_blksize ( int13 ) );
- if ( ! scratch )
- goto err_alloc_scratch;
-
- /* Parse parameters, if present */
- if ( ( rc = int13_parse_iso9660 ( int13, scratch ) ) != 0 )
- goto err_parse_iso9660;
-
- /* Give drive a default geometry */
- if ( ( rc = int13_guess_geometry ( int13, scratch ) ) != 0 )
- goto err_guess_geometry;
-
- DBGC ( int13, "INT13 drive %02x (naturally %02x) registered with C/H/S "
- "geometry %d/%d/%d\n", int13->drive, int13->natural_drive,
- int13->cylinders, int13->heads, int13->sectors_per_track );
-
- /* Hook INT 13 vector if not already hooked */
- if ( list_empty ( &int13s ) ) {
- int13_hook_vector();
- devices_get();
- }
-
- /* Add to list of emulated drives */
- list_add ( &int13->list, &int13s );
-
- /* Update BIOS drive count */
- int13_sync_num_drives();
-
- free ( scratch );
- return 0;
-
- err_guess_geometry:
- err_parse_iso9660:
- free ( scratch );
- err_alloc_scratch:
- err_read_capacity:
- err_reopen_block:
- intf_shutdown ( &int13->block, rc );
- ref_put ( &int13->refcnt );
- err_zalloc:
- err_in_use:
- return rc;
-}
-
-/**
- * Find INT 13 emulated drive by drive number
- *
- * @v drive Drive number
- * @ret int13 Emulated drive, or NULL
- */
-static struct int13_drive * int13_find ( unsigned int drive ) {
- struct int13_drive *int13;
-
- list_for_each_entry ( int13, &int13s, list ) {
- if ( int13->drive == drive )
- return int13;
- }
- return NULL;
-}
-
-/**
- * Unhook INT 13 emulated drive
- *
- * @v drive Drive number
- *
- * Unregisters the drive from the INT 13 emulation subsystem. If this
- * is the last emulated drive, the INT 13 vector is unhooked (if
- * possible).
- */
-static void int13_unhook ( unsigned int drive ) {
- struct int13_drive *int13;
-
- /* Find drive */
- int13 = int13_find ( drive );
- if ( ! int13 ) {
- DBG ( "INT13 cannot find emulated drive %02x\n", drive );
- return;
- }
-
- /* Shut down interfaces */
- intf_shutdown ( &int13->block, 0 );
-
- /* Remove from list of emulated drives */
- list_del ( &int13->list );
-
- /* Should adjust BIOS drive count, but it's difficult
- * to do so reliably.
- */
-
- DBGC ( int13, "INT13 drive %02x unregistered\n", int13->drive );
-
- /* Unhook INT 13 vector if no more drives */
- if ( list_empty ( &int13s ) ) {
- devices_put();
- int13_unhook_vector();
- }
-
- /* Drop list's reference to drive */
- ref_put ( &int13->refcnt );
-}
-
-/**
- * Load and verify master boot record from INT 13 drive
- *
- * @v drive Drive number
- * @v address Boot code address to fill in
- * @ret rc Return status code
- */
-static int int13_load_mbr ( unsigned int drive, struct segoff *address ) {
- uint8_t status;
- int discard_b, discard_c, discard_d;
- uint16_t magic;
-
- /* Use INT 13, 02 to read the MBR */
- address->segment = 0;
- address->offset = 0x7c00;
- __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
- "pushl %%ebx\n\t"
- "popw %%bx\n\t"
- "popw %%es\n\t"
- "stc\n\t"
- "sti\n\t"
- "int $0x13\n\t"
- "sti\n\t" /* BIOS bugs */
- "jc 1f\n\t"
- "xorw %%ax, %%ax\n\t"
- "\n1:\n\t"
- "popw %%es\n\t" )
- : "=a" ( status ), "=b" ( discard_b ),
- "=c" ( discard_c ), "=d" ( discard_d )
- : "a" ( 0x0201 ), "b" ( *address ),
- "c" ( 1 ), "d" ( drive ) );
- if ( status ) {
- DBG ( "INT13 drive %02x could not read MBR (status %02x)\n",
- drive, status );
- return -EIO;
- }
-
- /* Check magic signature */
- get_real ( magic, address->segment,
- ( address->offset +
- offsetof ( struct master_boot_record, magic ) ) );
- if ( magic != INT13_MBR_MAGIC ) {
- DBG ( "INT13 drive %02x does not contain a valid MBR\n",
- drive );
- return -ENOEXEC;
- }
-
- return 0;
-}
-
-/** El Torito boot catalog command packet */
-static struct int13_cdrom_boot_catalog_command __data16 ( eltorito_cmd ) = {
- .size = sizeof ( struct int13_cdrom_boot_catalog_command ),
- .count = 1,
- .buffer = 0x7c00,
- .start = 0,
-};
-#define eltorito_cmd __use_data16 ( eltorito_cmd )
-
-/** El Torito disk address packet */
-static struct int13_disk_address __bss16 ( eltorito_address );
-#define eltorito_address __use_data16 ( eltorito_address )
-
-/**
- * Load and verify El Torito boot record from INT 13 drive
- *
- * @v drive Drive number
- * @v address Boot code address to fill in
- * @ret rc Return status code
- */
-static int int13_load_eltorito ( unsigned int drive, struct segoff *address ) {
- struct {
- struct eltorito_validation_entry valid;
- struct eltorito_boot_entry boot;
- } __attribute__ (( packed )) catalog;
- uint8_t status;
-
- /* Use INT 13, 4d to read the boot catalog */
- __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
- "sti\n\t"
- "int $0x13\n\t"
- "sti\n\t" /* BIOS bugs */
- "jc 1f\n\t"
- "xorw %%ax, %%ax\n\t"
- "\n1:\n\t" )
- : "=a" ( status )
- : "a" ( 0x4d00 ), "d" ( drive ),
- "S" ( __from_data16 ( &eltorito_cmd ) ) );
- if ( status ) {
- DBG ( "INT13 drive %02x could not read El Torito boot catalog "
- "(status %02x)\n", drive, status );
- return -EIO;
- }
- copy_from_user ( &catalog, phys_to_user ( eltorito_cmd.buffer ), 0,
- sizeof ( catalog ) );
-
- /* Sanity checks */
- if ( catalog.valid.platform_id != ELTORITO_PLATFORM_X86 ) {
- DBG ( "INT13 drive %02x El Torito specifies unknown platform "
- "%02x\n", drive, catalog.valid.platform_id );
- return -ENOEXEC;
- }
- if ( catalog.boot.indicator != ELTORITO_BOOTABLE ) {
- DBG ( "INT13 drive %02x El Torito is not bootable\n", drive );
- return -ENOEXEC;
- }
- if ( catalog.boot.media_type != ELTORITO_NO_EMULATION ) {
- DBG ( "INT13 drive %02x El Torito requires emulation "
- "type %02x\n", drive, catalog.boot.media_type );
- return -ENOTSUP;
- }
- DBG ( "INT13 drive %02x El Torito boot image at LBA %08x (count %d)\n",
- drive, catalog.boot.start, catalog.boot.length );
- address->segment = ( catalog.boot.load_segment ?
- catalog.boot.load_segment : 0x7c0 );
- address->offset = 0;
- DBG ( "INT13 drive %02x El Torito boot image loads at %04x:%04x\n",
- drive, address->segment, address->offset );
-
- /* Use INT 13, 42 to read the boot image */
- eltorito_address.bufsize =
- offsetof ( typeof ( eltorito_address ), buffer_phys );
- eltorito_address.count = catalog.boot.length;
- eltorito_address.buffer = *address;
- eltorito_address.lba = catalog.boot.start;
- __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
- "sti\n\t"
- "int $0x13\n\t"
- "sti\n\t" /* BIOS bugs */
- "jc 1f\n\t"
- "xorw %%ax, %%ax\n\t"
- "\n1:\n\t" )
- : "=a" ( status )
- : "a" ( 0x4200 ), "d" ( drive ),
- "S" ( __from_data16 ( &eltorito_address ) ) );
- if ( status ) {
- DBG ( "INT13 drive %02x could not read El Torito boot image "
- "(status %02x)\n", drive, status );
- return -EIO;
- }
-
- return 0;
-}
-
-/**
- * Attempt to boot from an INT 13 drive
- *
- * @v drive Drive number
- * @ret rc Return status code
- *
- * This boots from the specified INT 13 drive by loading the Master
- * Boot Record to 0000:7c00 and jumping to it. INT 18 is hooked to
- * capture an attempt by the MBR to boot the next device. (This is
- * the closest thing to a return path from an MBR).
- *
- * Note that this function can never return success, by definition.
- */
-static int int13_boot ( unsigned int drive ) {
- struct memory_map memmap;
- struct segoff address;
- int rc;
-
- /* Look for a usable boot sector */
- if ( ( ( rc = int13_load_mbr ( drive, &address ) ) != 0 ) &&
- ( ( rc = int13_load_eltorito ( drive, &address ) ) != 0 ) )
- return rc;
-
- /* Dump out memory map prior to boot, if memmap debugging is
- * enabled. Not required for program flow, but we have so
- * many problems that turn out to be memory-map related that
- * it's worth doing.
- */
- get_memmap ( &memmap );
-
- /* Jump to boot sector */
- if ( ( rc = call_bootsector ( address.segment, address.offset,
- drive ) ) != 0 ) {
- DBG ( "INT13 drive %02x boot returned: %s\n",
- drive, strerror ( rc ) );
- return rc;
- }
-
- return -ECANCELED; /* -EIMPOSSIBLE */
-}
-
-/** A boot firmware table generated by iPXE */
-union xbft_table {
- /** ACPI header */
- struct acpi_description_header acpi;
- /** Padding */
- char pad[768];
-};
-
-/** The boot firmware table generated by iPXE */
-static union xbft_table __bss16 ( xbftab ) __attribute__ (( aligned ( 16 ) ));
-#define xbftab __use_data16 ( xbftab )
-
-/**
- * Describe INT 13 emulated drive for SAN-booted operating system
- *
- * @v drive Drive number
- * @ret rc Return status code
- */
-static int int13_describe ( unsigned int drive ) {
- struct int13_drive *int13;
- struct segoff xbft_address;
- int rc;
-
- /* Find drive */
- int13 = int13_find ( drive );
- if ( ! int13 ) {
- DBG ( "INT13 cannot find emulated drive %02x\n", drive );
- return -ENODEV;
- }
-
- /* Reopen block device if necessary */
- if ( ( int13->block_rc != 0 ) &&
- ( ( rc = int13_reopen_block ( int13 ) ) != 0 ) )
- return rc;
-
- /* Clear table */
- memset ( &xbftab, 0, sizeof ( xbftab ) );
-
- /* Fill in common parameters */
- strncpy ( xbftab.acpi.oem_id, "FENSYS",
- sizeof ( xbftab.acpi.oem_id ) );
- strncpy ( xbftab.acpi.oem_table_id, "iPXE",
- sizeof ( xbftab.acpi.oem_table_id ) );
-
- /* Fill in remaining parameters */
- if ( ( rc = acpi_describe ( &int13->block, &xbftab.acpi,
- sizeof ( xbftab ) ) ) != 0 ) {
- DBGC ( int13, "INT13 drive %02x could not create ACPI "
- "description: %s\n", int13->drive, strerror ( rc ) );
- return rc;
- }
-
- /* Fix up ACPI checksum */
- acpi_fix_checksum ( &xbftab.acpi );
- xbft_address.segment = rm_ds;
- xbft_address.offset = __from_data16 ( &xbftab );
- DBGC ( int13, "INT13 drive %02x described using boot firmware "
- "table:\n", int13->drive );
- DBGC_HDA ( int13, xbft_address, &xbftab,
- le32_to_cpu ( xbftab.acpi.length ) );
-
- return 0;
-}
-
-PROVIDE_SANBOOT_INLINE ( pcbios, san_default_drive );
-PROVIDE_SANBOOT ( pcbios, san_hook, int13_hook );
-PROVIDE_SANBOOT ( pcbios, san_unhook, int13_unhook );
-PROVIDE_SANBOOT ( pcbios, san_boot, int13_boot );
-PROVIDE_SANBOOT ( pcbios, san_describe, int13_describe );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13con.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13con.c
deleted file mode 100644
index 2414c6909..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/int13con.c
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <ipxe/console.h>
-#include <ipxe/init.h>
-#include <realmode.h>
-#include <int13.h>
-#include <config/console.h>
-
-/** @file
- *
- * INT13 disk log console
- *
- */
-
-/* Set default console usage if applicable */
-#if ! ( defined ( CONSOLE_INT13 ) && CONSOLE_EXPLICIT ( CONSOLE_INT13 ) )
-#undef CONSOLE_INT13
-#define CONSOLE_INT13 ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
-#endif
-
-/** Disk drive number */
-#define INT13CON_DRIVE 0x80
-
-/** Log partition type */
-#define INT13CON_PARTITION_TYPE 0xe0
-
-/** Maximum number of outstanding unwritten characters */
-#define INT13CON_MAX_UNWRITTEN 64
-
-/** Log partition header */
-struct int13con_header {
- /** Magic signature */
- char magic[10];
-} __attribute__ (( packed ));
-
-/** Log partition magic signature */
-#define INT13CON_MAGIC "iPXE LOG\n\n"
-
-/** Sector buffer */
-static uint8_t __bss16_array ( int13con_buffer, [INT13_BLKSIZE] );
-#define int13con_buffer __use_data16 ( int13con_buffer )
-
-/** Disk address packet */
-static struct int13_disk_address __bss16 ( int13con_address );
-#define int13con_address __use_data16 ( int13con_address )
-
-/** Current LBA */
-static uint64_t int13con_lba;
-
-/** Maximum LBA */
-static uint64_t int13con_max_lba;
-
-/** Current offset within sector */
-static size_t int13con_offset;
-
-/** Number of unwritten characters */
-static size_t int13con_unwritten;
-
-struct console_driver int13con __console_driver;
-
-/**
- * Read/write disk sector
- *
- * @v op Operation
- * @v lba Logical block address
- * @ret rc Return status code
- */
-static int int13con_rw ( unsigned int op, uint64_t lba ) {
- uint8_t error;
-
- /* Construct disk address packet */
- int13con_address.bufsize = sizeof ( int13con_address );
- int13con_address.count = 1;
- int13con_address.buffer.segment = rm_ds;
- int13con_address.buffer.offset = __from_data16 ( int13con_buffer );
- int13con_address.lba = lba;
-
- /* Issue INT13 */
- __asm__ ( REAL_CODE ( "int $0x13\n\t" )
- : "=a" ( error )
- : "0" ( op << 8 ), "d" ( INT13CON_DRIVE ),
- "S" ( __from_data16 ( &int13con_address ) ) );
- if ( error ) {
- DBG ( "INT13CON operation %04x failed: %02x\n",
- op, error );
- return -EIO;
- }
-
- return 0;
-}
-
-/**
- * Write character to console
- *
- * @v character Character
- */
-static void int13con_putchar ( int character ) {
- static int busy;
- int rc;
-
- /* Ignore if we are already mid-logging */
- if ( busy )
- return;
- busy = 1;
-
- /* Write character to buffer */
- int13con_buffer[int13con_offset++] = character;
- int13con_unwritten++;
-
- /* Write sector to disk, if applicable */
- if ( ( int13con_offset == INT13_BLKSIZE ) ||
- ( int13con_unwritten == INT13CON_MAX_UNWRITTEN ) ||
- ( character == '\n' ) ) {
-
- /* Write sector to disk */
- if ( ( rc = int13con_rw ( INT13_EXTENDED_WRITE,
- int13con_lba ) ) != 0 ) {
- DBG ( "INT13CON could not write log\n" );
- /* Ignore and continue; there's nothing we can do */
- }
-
- /* Reset count of unwritten characters */
- int13con_unwritten = 0;
- }
-
- /* Move to next sector, if applicable */
- if ( int13con_offset == INT13_BLKSIZE ) {
-
- /* Disable console if we have run out of space */
- if ( int13con_lba >= int13con_max_lba )
- int13con.disabled = 1;
-
- /* Clear log buffer */
- memset ( int13con_buffer, 0, sizeof ( int13con_buffer ) );
- int13con_offset = 0;
-
- /* Move to next sector */
- int13con_lba++;
- }
-
- /* Clear busy flag */
- busy = 0;
-}
-
-/**
- * Find log partition
- *
- * @ret rc Return status code
- */
-static int int13con_find ( void ) {
- struct master_boot_record *mbr =
- ( ( struct master_boot_record * ) int13con_buffer );
- struct int13con_header *hdr =
- ( ( struct int13con_header * ) int13con_buffer );
- struct partition_table_entry part[4];
- unsigned int i;
- int rc;
-
- /* Read MBR */
- if ( ( rc = int13con_rw ( INT13_EXTENDED_READ, 0 ) ) != 0 ) {
- DBG ( "INT13CON could not read MBR: %s\n", strerror ( rc ) );
- return rc;
- }
-
- /* Check MBR magic */
- if ( mbr->magic != INT13_MBR_MAGIC ) {
- DBG ( "INT13CON incorrect MBR magic\n" );
- DBG2_HDA ( 0, mbr, sizeof ( *mbr ) );
- return -EINVAL;
- }
-
- /* Look for magic partition */
- memcpy ( part, mbr->partitions, sizeof ( part ) );
- for ( i = 0 ; i < ( sizeof ( part ) / sizeof ( part[0] ) ) ; i++ ) {
-
- /* Skip partitions of the wrong type */
- if ( part[i].type != INT13CON_PARTITION_TYPE )
- continue;
-
- /* Read partition header */
- if ( ( rc = int13con_rw ( INT13_EXTENDED_READ,
- part[i].start ) ) != 0 ) {
- DBG ( "INT13CON partition %d could not read header: "
- "%s\n", ( i + 1 ), strerror ( rc ) );
- continue;
- }
-
- /* Check partition header */
- if ( memcmp ( hdr->magic, INT13CON_MAGIC,
- sizeof ( hdr->magic ) ) != 0 ) {
- DBG ( "INT13CON partition %d bad magic\n", ( i + 1 ) );
- DBG2_HDA ( 0, hdr, sizeof ( *hdr ) );
- continue;
- }
-
- /* Found log partition */
- DBG ( "INT13CON partition %d at [%08x,%08x)\n", ( i + 1 ),
- part[i].start, ( part[i].start + part[i].length ) );
- int13con_lba = part[i].start;
- int13con_max_lba = ( part[i].start + part[i].length - 1 );
-
- /* Initialise log buffer */
- memset ( &int13con_buffer[ sizeof ( *hdr ) ], 0,
- ( sizeof ( int13con_buffer ) - sizeof ( *hdr ) ) );
- int13con_offset = sizeof ( hdr->magic );
-
- return 0;
- }
-
- DBG ( "INT13CON found no log partition\n" );
- return -ENOENT;
-}
-
-/**
- * Initialise INT13 console
- *
- */
-static void int13con_init ( void ) {
- uint8_t error;
- uint16_t check;
- unsigned int discard_c;
- unsigned int discard_d;
- int rc;
-
- /* Check for INT13 extensions */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x13\n\t"
- "setc %%al\n\t" )
- : "=a" ( error ), "=b" ( check ),
- "=c" ( discard_c ), "=d" ( discard_d )
- : "0" ( INT13_EXTENSION_CHECK << 8 ),
- "1" ( 0x55aa ), "3" ( INT13CON_DRIVE ) );
- if ( error || ( check != 0xaa55 ) ) {
- DBG ( "INT13CON missing extensions (%02x,%04x)\n",
- error, check );
- return;
- }
-
- /* Locate log partition */
- if ( ( rc = int13con_find() ) != 0)
- return;
-
- /* Enable console */
- int13con.disabled = 0;
-}
-
-/**
- * INT13 console initialisation function
- */
-struct init_fn int13con_init_fn __init_fn ( INIT_CONSOLE ) = {
- .initialise = int13con_init,
-};
-
-/** INT13 console driver */
-struct console_driver int13con __console_driver = {
- .putchar = int13con_putchar,
- .disabled = CONSOLE_DISABLED,
- .usage = CONSOLE_INT13,
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
deleted file mode 100644
index 957f8e324..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/**
- * @file
- *
- * External memory allocation
- *
- */
-
-#include <limits.h>
-#include <errno.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/hidemem.h>
-#include <ipxe/io.h>
-#include <ipxe/memblock.h>
-#include <ipxe/umalloc.h>
-
-/** Alignment of external allocated memory */
-#define EM_ALIGN ( 4 * 1024 )
-
-/** Equivalent of NOWHERE for user pointers */
-#define UNOWHERE ( ~UNULL )
-
-/** An external memory block */
-struct external_memory {
- /** Size of this memory block (excluding this header) */
- size_t size;
- /** Block is currently in use */
- int used;
-};
-
-/** Top of heap */
-static userptr_t top = UNULL;
-
-/** Bottom of heap (current lowest allocated block) */
-static userptr_t bottom = UNULL;
-
-/** Remaining space on heap */
-static size_t heap_size;
-
-/**
- * Initialise external heap
- *
- */
-static void init_eheap ( void ) {
- userptr_t base;
-
- heap_size = largest_memblock ( &base );
- bottom = top = userptr_add ( base, heap_size );
- DBG ( "External heap grows downwards from %lx (size %zx)\n",
- user_to_phys ( top, 0 ), heap_size );
-}
-
-/**
- * Collect free blocks
- *
- */
-static void ecollect_free ( void ) {
- struct external_memory extmem;
- size_t len;
-
- /* Walk the free list and collect empty blocks */
- while ( bottom != top ) {
- copy_from_user ( &extmem, bottom, -sizeof ( extmem ),
- sizeof ( extmem ) );
- if ( extmem.used )
- break;
- DBG ( "EXTMEM freeing [%lx,%lx)\n", user_to_phys ( bottom, 0 ),
- user_to_phys ( bottom, extmem.size ) );
- len = ( extmem.size + sizeof ( extmem ) );
- bottom = userptr_add ( bottom, len );
- heap_size += len;
- }
-}
-
-/**
- * Reallocate external memory
- *
- * @v old_ptr Memory previously allocated by umalloc(), or UNULL
- * @v new_size Requested size
- * @ret new_ptr Allocated memory, or UNULL
- *
- * Calling realloc() with a new size of zero is a valid way to free a
- * memory block.
- */
-static userptr_t memtop_urealloc ( userptr_t ptr, size_t new_size ) {
- struct external_memory extmem;
- userptr_t new = ptr;
- size_t align;
-
- /* (Re)initialise external memory allocator if necessary */
- if ( bottom == top )
- init_eheap();
-
- /* Get block properties into extmem */
- if ( ptr && ( ptr != UNOWHERE ) ) {
- /* Determine old size */
- copy_from_user ( &extmem, ptr, -sizeof ( extmem ),
- sizeof ( extmem ) );
- } else {
- /* Create a zero-length block */
- if ( heap_size < sizeof ( extmem ) ) {
- DBG ( "EXTMEM out of space\n" );
- return UNULL;
- }
- ptr = bottom = userptr_add ( bottom, -sizeof ( extmem ) );
- heap_size -= sizeof ( extmem );
- DBG ( "EXTMEM allocating [%lx,%lx)\n",
- user_to_phys ( ptr, 0 ), user_to_phys ( ptr, 0 ) );
- extmem.size = 0;
- }
- extmem.used = ( new_size > 0 );
-
- /* Expand/shrink block if possible */
- if ( ptr == bottom ) {
- /* Update block */
- if ( new_size > ( heap_size - extmem.size ) ) {
- DBG ( "EXTMEM out of space\n" );
- return UNULL;
- }
- new = userptr_add ( ptr, - ( new_size - extmem.size ) );
- align = ( user_to_phys ( new, 0 ) & ( EM_ALIGN - 1 ) );
- new_size += align;
- new = userptr_add ( new, -align );
- DBG ( "EXTMEM expanding [%lx,%lx) to [%lx,%lx)\n",
- user_to_phys ( ptr, 0 ),
- user_to_phys ( ptr, extmem.size ),
- user_to_phys ( new, 0 ),
- user_to_phys ( new, new_size ));
- memmove_user ( new, 0, ptr, 0, ( ( extmem.size < new_size ) ?
- extmem.size : new_size ) );
- bottom = new;
- heap_size -= ( new_size - extmem.size );
- extmem.size = new_size;
- } else {
- /* Cannot expand; can only pretend to shrink */
- if ( new_size > extmem.size ) {
- /* Refuse to expand */
- DBG ( "EXTMEM cannot expand [%lx,%lx)\n",
- user_to_phys ( ptr, 0 ),
- user_to_phys ( ptr, extmem.size ) );
- return UNULL;
- }
- }
-
- /* Write back block properties */
- copy_to_user ( new, -sizeof ( extmem ), &extmem,
- sizeof ( extmem ) );
-
- /* Collect any free blocks and update hidden memory region */
- ecollect_free();
- hide_umalloc ( user_to_phys ( bottom, ( ( bottom == top ) ?
- 0 : -sizeof ( extmem ) ) ),
- user_to_phys ( top, 0 ) );
-
- return ( new_size ? new : UNOWHERE );
-}
-
-PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c
deleted file mode 100644
index 34efa0b39..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/pcibios.c
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <ipxe/pci.h>
-#include <realmode.h>
-
-/** @file
- *
- * PCI configuration space access via PCI BIOS
- *
- */
-
-/**
- * Determine number of PCI buses within system
- *
- * @ret num_bus Number of buses
- */
-static int pcibios_num_bus ( void ) {
- int discard_a, discard_D;
- uint8_t max_bus;
-
- /* We issue this call using flat real mode, to work around a
- * bug in some HP BIOSes.
- */
- __asm__ __volatile__ ( REAL_CODE ( "call flatten_real_mode\n\t"
- "stc\n\t"
- "int $0x1a\n\t"
- "jnc 1f\n\t"
- "xorw %%cx, %%cx\n\t"
- "\n1:\n\t" )
- : "=c" ( max_bus ), "=a" ( discard_a ),
- "=D" ( discard_D )
- : "a" ( PCIBIOS_INSTALLATION_CHECK >> 16 ),
- "D" ( 0 )
- : "ebx", "edx" );
-
- return ( max_bus + 1 );
-}
-
-/**
- * Read configuration space via PCI BIOS
- *
- * @v pci PCI device
- * @v command PCI BIOS command
- * @v value Value read
- * @ret rc Return status code
- */
-int pcibios_read ( struct pci_device *pci, uint32_t command, uint32_t *value ){
- int discard_b, discard_D;
- int status;
-
- __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
- "int $0x1a\n\t"
- "jnc 1f\n\t"
- "xorl %%eax, %%eax\n\t"
- "decl %%eax\n\t"
- "movl %%eax, %%ecx\n\t"
- "\n1:\n\t" )
- : "=a" ( status ), "=b" ( discard_b ),
- "=c" ( *value ), "=D" ( discard_D )
- : "a" ( command >> 16 ), "D" ( command ),
- "b" ( pci->busdevfn )
- : "edx" );
-
- return ( ( status >> 8 ) & 0xff );
-}
-
-/**
- * Write configuration space via PCI BIOS
- *
- * @v pci PCI device
- * @v command PCI BIOS command
- * @v value Value to be written
- * @ret rc Return status code
- */
-int pcibios_write ( struct pci_device *pci, uint32_t command, uint32_t value ){
- int discard_b, discard_c, discard_D;
- int status;
-
- __asm__ __volatile__ ( REAL_CODE ( "stc\n\t"
- "int $0x1a\n\t"
- "jnc 1f\n\t"
- "movb $0xff, %%ah\n\t"
- "\n1:\n\t" )
- : "=a" ( status ), "=b" ( discard_b ),
- "=c" ( discard_c ), "=D" ( discard_D )
- : "a" ( command >> 16 ), "D" ( command ),
- "b" ( pci->busdevfn ), "c" ( value )
- : "edx" );
-
- return ( ( status >> 8 ) & 0xff );
-}
-
-PROVIDE_PCIAPI ( pcbios, pci_num_bus, pcibios_num_bus );
-PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_byte );
-PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_word );
-PROVIDE_PCIAPI_INLINE ( pcbios, pci_read_config_dword );
-PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_byte );
-PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_word );
-PROVIDE_PCIAPI_INLINE ( pcbios, pci_write_config_dword );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c
deleted file mode 100644
index 9aab03c03..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_entropy.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * RTC-based entropy source
- *
- */
-
-#include <stdint.h>
-#include <string.h>
-#include <biosint.h>
-#include <pic8259.h>
-#include <rtc.h>
-#include <ipxe/entropy.h>
-
-/** RTC "interrupt triggered" flag */
-static uint8_t __text16 ( rtc_flag );
-#define rtc_flag __use_text16 ( rtc_flag )
-
-/** RTC interrupt handler */
-extern void rtc_isr ( void );
-
-/** Previous RTC interrupt handler */
-static struct segoff rtc_old_handler;
-
-/**
- * Hook RTC interrupt handler
- *
- */
-static void rtc_hook_isr ( void ) {
-
- /* RTC interrupt handler */
- __asm__ __volatile__ (
- TEXT16_CODE ( "\nrtc_isr:\n\t"
- /* Preserve registers */
- "pushw %%ax\n\t"
- /* Set "interrupt triggered" flag */
- "cs movb $0x01, %c0\n\t"
- /* Read RTC status register C to
- * acknowledge interrupt
- */
- "movb %3, %%al\n\t"
- "outb %%al, %1\n\t"
- "inb %2\n\t"
- /* Send EOI */
- "movb $0x20, %%al\n\t"
- "outb %%al, $0xa0\n\t"
- "outb %%al, $0x20\n\t"
- /* Restore registers and return */
- "popw %%ax\n\t"
- "iret\n\t" )
- :
- : "p" ( __from_text16 ( &rtc_flag ) ),
- "i" ( CMOS_ADDRESS ), "i" ( CMOS_DATA ),
- "i" ( RTC_STATUS_C ) );
-
- hook_bios_interrupt ( RTC_INT, ( unsigned int ) rtc_isr,
- &rtc_old_handler );
-}
-
-/**
- * Unhook RTC interrupt handler
- *
- */
-static void rtc_unhook_isr ( void ) {
- int rc;
-
- rc = unhook_bios_interrupt ( RTC_INT, ( unsigned int ) rtc_isr,
- &rtc_old_handler );
- assert ( rc == 0 ); /* Should always be able to unhook */
-}
-
-/**
- * Enable RTC interrupts
- *
- */
-static void rtc_enable_int ( void ) {
- uint8_t status_b;
-
- /* Set Periodic Interrupt Enable bit in status register B */
- outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
- status_b = inb ( CMOS_DATA );
- outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
- outb ( ( status_b | RTC_STATUS_B_PIE ), CMOS_DATA );
-
- /* Re-enable NMI and reset to default address */
- outb ( CMOS_DEFAULT_ADDRESS, CMOS_ADDRESS );
- inb ( CMOS_DATA ); /* Discard; may be needed on some platforms */
-}
-
-/**
- * Disable RTC interrupts
- *
- */
-static void rtc_disable_int ( void ) {
- uint8_t status_b;
-
- /* Clear Periodic Interrupt Enable bit in status register B */
- outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
- status_b = inb ( CMOS_DATA );
- outb ( ( RTC_STATUS_B | CMOS_DISABLE_NMI ), CMOS_ADDRESS );
- outb ( ( status_b & ~RTC_STATUS_B_PIE ), CMOS_DATA );
-
- /* Re-enable NMI and reset to default address */
- outb ( CMOS_DEFAULT_ADDRESS, CMOS_ADDRESS );
- inb ( CMOS_DATA ); /* Discard; may be needed on some platforms */
-}
-
-/**
- * Enable entropy gathering
- *
- * @ret rc Return status code
- */
-static int rtc_entropy_enable ( void ) {
-
- rtc_hook_isr();
- enable_irq ( RTC_IRQ );
- rtc_enable_int();
-
- return 0;
-}
-
-/**
- * Disable entropy gathering
- *
- */
-static void rtc_entropy_disable ( void ) {
-
- rtc_disable_int();
- disable_irq ( RTC_IRQ );
- rtc_unhook_isr();
-}
-
-/**
- * Measure a single RTC tick
- *
- * @ret delta Length of RTC tick (in TSC units)
- */
-uint8_t rtc_sample ( void ) {
- uint32_t before;
- uint32_t after;
- uint32_t temp;
-
- __asm__ __volatile__ (
- REAL_CODE ( /* Enable interrupts */
- "sti\n\t"
- /* Wait for RTC interrupt */
- "cs movb %b2, %c4\n\t"
- "\n1:\n\t"
- "cs xchgb %b2, %c4\n\t" /* Serialize */
- "testb %b2, %b2\n\t"
- "jz 1b\n\t"
- /* Read "before" TSC */
- "rdtsc\n\t"
- /* Store "before" TSC on stack */
- "pushl %0\n\t"
- /* Wait for another RTC interrupt */
- "xorb %b2, %b2\n\t"
- "cs movb %b2, %c4\n\t"
- "\n1:\n\t"
- "cs xchgb %b2, %c4\n\t" /* Serialize */
- "testb %b2, %b2\n\t"
- "jz 1b\n\t"
- /* Read "after" TSC */
- "rdtsc\n\t"
- /* Retrieve "before" TSC on stack */
- "popl %1\n\t"
- /* Disable interrupts */
- "cli\n\t"
- )
- : "=a" ( after ), "=d" ( before ), "=q" ( temp )
- : "2" ( 0 ), "p" ( __from_text16 ( &rtc_flag ) ) );
-
- return ( after - before );
-}
-
-PROVIDE_ENTROPY_INLINE ( rtc, min_entropy_per_sample );
-PROVIDE_ENTROPY ( rtc, entropy_enable, rtc_entropy_enable );
-PROVIDE_ENTROPY ( rtc, entropy_disable, rtc_entropy_disable );
-PROVIDE_ENTROPY_INLINE ( rtc, get_noise );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c
deleted file mode 100644
index cdbeac8d5..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/rtc_time.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * RTC-based time source
- *
- */
-
-#include <stdint.h>
-#include <time.h>
-#include <rtc.h>
-#include <ipxe/time.h>
-
-/**
- * Read RTC register
- *
- * @v address Register address
- * @ret data Data
- */
-static unsigned int rtc_readb ( int address ) {
- outb ( address, CMOS_ADDRESS );
- return inb ( CMOS_DATA );
-}
-
-/**
- * Check if RTC update is in progress
- *
- * @ret is_busy RTC update is in progress
- */
-static int rtc_is_busy ( void ) {
- return ( rtc_readb ( RTC_STATUS_A ) & RTC_STATUS_A_UPDATE_IN_PROGRESS );
-}
-
-/**
- * Read RTC BCD register
- *
- * @v address Register address
- * @ret value Value
- */
-static unsigned int rtc_readb_bcd ( int address ) {
- unsigned int bcd;
-
- bcd = rtc_readb ( address );
- return ( bcd - ( 6 * ( bcd >> 4 ) ) );
-}
-
-/**
- * Read RTC time
- *
- * @ret time Time, in seconds
- */
-static time_t rtc_read_time ( void ) {
- unsigned int status_b;
- int is_binary;
- int is_24hour;
- unsigned int ( * read_component ) ( int address );
- struct tm tm;
- int is_pm;
- unsigned int hour;
- time_t time;
-
- /* Wait for any in-progress update to complete */
- while ( rtc_is_busy() ) {}
-
- /* Determine RTC mode */
- status_b = rtc_readb ( RTC_STATUS_B );
- is_binary = ( status_b & RTC_STATUS_B_BINARY );
- is_24hour = ( status_b & RTC_STATUS_B_24_HOUR );
- read_component = ( is_binary ? rtc_readb : rtc_readb_bcd );
-
- /* Read time values */
- tm.tm_sec = read_component ( RTC_SEC );
- tm.tm_min = read_component ( RTC_MIN );
- hour = read_component ( RTC_HOUR );
- if ( ! is_24hour ) {
- is_pm = ( hour >= 80 );
- hour = ( ( ( ( hour & 0x7f ) % 80 ) % 12 ) +
- ( is_pm ? 12 : 0 ) );
- }
- tm.tm_hour = hour;
- tm.tm_mday = read_component ( RTC_MDAY );
- tm.tm_mon = ( read_component ( RTC_MON ) - 1 );
- tm.tm_year = ( read_component ( RTC_YEAR ) +
- 100 /* Assume we are in the 21st century, since
- * this code was written in 2012 */ );
-
- DBGC ( RTC_STATUS_A, "RTCTIME is %04d-%02d-%02d %02d:%02d:%02d "
- "(%s,%d-hour)\n", ( tm.tm_year + 1900 ), ( tm.tm_mon + 1 ),
- tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
- ( is_binary ? "binary" : "BCD" ), ( is_24hour ? 24 : 12 ) );
-
- /* Convert to seconds since the Epoch */
- time = mktime ( &tm );
-
- return time;
-}
-
-/**
- * Get current time in seconds
- *
- * @ret time Time, in seconds
- */
-static time_t rtc_now ( void ) {
- time_t time = 0;
- time_t last_time;
-
- /* Read time until we get two matching values in a row, in
- * case we end up reading a corrupted value in the middle of
- * an update.
- */
- do {
- last_time = time;
- time = rtc_read_time();
- } while ( time != last_time );
-
- return time;
-}
-
-PROVIDE_TIME ( rtc, time_now, rtc_now );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c b/qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c
deleted file mode 100644
index 9cf2bf29e..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pcbios/vesafb.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/*
- * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * VESA frame buffer console
- *
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <limits.h>
-#include <realmode.h>
-#include <ipxe/console.h>
-#include <ipxe/io.h>
-#include <ipxe/ansicol.h>
-#include <ipxe/fbcon.h>
-#include <ipxe/vesafb.h>
-#include <config/console.h>
-
-/* Avoid dragging in BIOS console if not otherwise used */
-extern struct console_driver bios_console;
-struct console_driver bios_console __attribute__ (( weak ));
-
-/* Disambiguate the various error causes */
-#define EIO_FAILED __einfo_error ( EINFO_EIO_FAILED )
-#define EINFO_EIO_FAILED \
- __einfo_uniqify ( EINFO_EIO, 0x01, \
- "Function call failed" )
-#define EIO_HARDWARE __einfo_error ( EINFO_EIO_HARDWARE )
-#define EINFO_EIO_HARDWARE \
- __einfo_uniqify ( EINFO_EIO, 0x02, \
- "Not supported in current configuration" )
-#define EIO_MODE __einfo_error ( EINFO_EIO_MODE )
-#define EINFO_EIO_MODE \
- __einfo_uniqify ( EINFO_EIO, 0x03, \
- "Invalid in current video mode" )
-#define EIO_VBE( code ) \
- EUNIQ ( EINFO_EIO, (code), EIO_FAILED, EIO_HARDWARE, EIO_MODE )
-
-/* Set default console usage if applicable */
-#if ! ( defined ( CONSOLE_VESAFB ) && CONSOLE_EXPLICIT ( CONSOLE_VESAFB ) )
-#undef CONSOLE_VESAFB
-#define CONSOLE_VESAFB ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_LOG )
-#endif
-
-/** Font corresponding to selected character width and height */
-#define VESAFB_FONT VBE_FONT_8x16
-
-/* Forward declaration */
-struct console_driver vesafb_console __console_driver;
-
-/** A VESA frame buffer */
-struct vesafb {
- /** Frame buffer console */
- struct fbcon fbcon;
- /** Physical start address */
- physaddr_t start;
- /** Pixel geometry */
- struct fbcon_geometry pixel;
- /** Margin */
- struct fbcon_margin margin;
- /** Colour mapping */
- struct fbcon_colour_map map;
- /** Font definition */
- struct fbcon_font font;
- /** Saved VGA mode */
- uint8_t saved_mode;
-};
-
-/** The VESA frame buffer */
-static struct vesafb vesafb;
-
-/** Base memory buffer used for VBE calls */
-union vbe_buffer {
- /** VBE controller information block */
- struct vbe_controller_info controller;
- /** VBE mode information block */
- struct vbe_mode_info mode;
-};
-static union vbe_buffer __bss16 ( vbe_buf );
-#define vbe_buf __use_data16 ( vbe_buf )
-
-/**
- * Convert VBE status code to iPXE status code
- *
- * @v status VBE status code
- * @ret rc Return status code
- */
-static int vesafb_rc ( unsigned int status ) {
- unsigned int code;
-
- if ( ( status & 0xff ) != 0x4f )
- return -ENOTSUP;
- code = ( ( status >> 8 ) & 0xff );
- return ( code ? -EIO_VBE ( code ) : 0 );
-}
-
-/**
- * Get font definition
- *
- */
-static void vesafb_font ( void ) {
- struct segoff font;
-
- /* Get font information
- *
- * Working around gcc bugs is icky here. The value we want is
- * returned in %ebp, but there's no way to specify %ebp in an
- * output constraint. We can't put %ebp in the clobber list,
- * because this tends to cause random build failures on some
- * gcc versions. We can't manually push/pop %ebp and return
- * the value via a generic register output constraint, because
- * gcc might choose to use %ebp to satisfy that constraint
- * (and we have no way to prevent it from so doing).
- *
- * Work around this hideous mess by using %ecx and %edx as the
- * output registers, since they get clobbered anyway.
- */
- __asm__ __volatile__ ( REAL_CODE ( "pushw %%bp\n\t" /* gcc bug */
- "int $0x10\n\t"
- "movw %%es, %%cx\n\t"
- "movw %%bp, %%dx\n\t"
- "popw %%bp\n\t" /* gcc bug */ )
- : "=c" ( font.segment ),
- "=d" ( font.offset )
- : "a" ( VBE_GET_FONT ),
- "b" ( VESAFB_FONT ) );
- DBGC ( &vbe_buf, "VESAFB has font %04x at %04x:%04x\n",
- VESAFB_FONT, font.segment, font.offset );
- vesafb.font.start = real_to_user ( font.segment, font.offset );
-}
-
-/**
- * Get VBE mode list
- *
- * @ret mode_numbers Mode number list (terminated with VBE_MODE_END)
- * @ret rc Return status code
- *
- * The caller is responsible for eventually freeing the mode list.
- */
-static int vesafb_mode_list ( uint16_t **mode_numbers ) {
- struct vbe_controller_info *controller = &vbe_buf.controller;
- userptr_t video_mode_ptr;
- uint16_t mode_number;
- uint16_t status;
- size_t len;
- int rc;
-
- /* Avoid returning uninitialised data on error */
- *mode_numbers = NULL;
-
- /* Get controller information block */
- controller->vbe_signature = 0;
- __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
- : "=a" ( status )
- : "a" ( VBE_CONTROLLER_INFO ),
- "D" ( __from_data16 ( controller ) )
- : "memory", "ebx", "edx" );
- if ( ( rc = vesafb_rc ( status ) ) != 0 ) {
- DBGC ( &vbe_buf, "VESAFB could not get controller information: "
- "[%04x] %s\n", status, strerror ( rc ) );
- return rc;
- }
- if ( controller->vbe_signature != VBE_CONTROLLER_SIGNATURE ) {
- DBGC ( &vbe_buf, "VESAFB invalid controller signature "
- "\"%c%c%c%c\"\n", ( controller->vbe_signature >> 0 ),
- ( controller->vbe_signature >> 8 ),
- ( controller->vbe_signature >> 16 ),
- ( controller->vbe_signature >> 24 ) );
- DBGC_HDA ( &vbe_buf, 0, controller, sizeof ( *controller ) );
- return -EINVAL;
- }
- DBGC ( &vbe_buf, "VESAFB found VBE version %d.%d with mode list at "
- "%04x:%04x\n", controller->vbe_major_version,
- controller->vbe_minor_version,
- controller->video_mode_ptr.segment,
- controller->video_mode_ptr.offset );
-
- /* Calculate length of mode list */
- video_mode_ptr = real_to_user ( controller->video_mode_ptr.segment,
- controller->video_mode_ptr.offset );
- len = 0;
- do {
- copy_from_user ( &mode_number, video_mode_ptr, len,
- sizeof ( mode_number ) );
- len += sizeof ( mode_number );
- } while ( mode_number != VBE_MODE_END );
-
- /* Allocate and fill mode list */
- *mode_numbers = malloc ( len );
- if ( ! *mode_numbers )
- return -ENOMEM;
- copy_from_user ( *mode_numbers, video_mode_ptr, 0, len );
-
- return 0;
-}
-
-/**
- * Get video mode information
- *
- * @v mode_number Mode number
- * @ret rc Return status code
- */
-static int vesafb_mode_info ( unsigned int mode_number ) {
- struct vbe_mode_info *mode = &vbe_buf.mode;
- uint16_t status;
- int rc;
-
- /* Get mode information */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
- : "=a" ( status )
- : "a" ( VBE_MODE_INFO ),
- "c" ( mode_number ),
- "D" ( __from_data16 ( mode ) )
- : "memory" );
- if ( ( rc = vesafb_rc ( status ) ) != 0 ) {
- DBGC ( &vbe_buf, "VESAFB could not get mode %04x information: "
- "[%04x] %s\n", mode_number, status, strerror ( rc ) );
- return rc;
- }
- DBGC ( &vbe_buf, "VESAFB mode %04x %dx%d %dbpp(%d:%d:%d:%d) model "
- "%02x [x%d]%s%s%s%s%s\n", mode_number, mode->x_resolution,
- mode->y_resolution, mode->bits_per_pixel, mode->rsvd_mask_size,
- mode->red_mask_size, mode->green_mask_size, mode->blue_mask_size,
- mode->memory_model, ( mode->number_of_image_pages + 1 ),
- ( ( mode->mode_attributes & VBE_MODE_ATTR_SUPPORTED ) ?
- "" : " [unsupported]" ),
- ( ( mode->mode_attributes & VBE_MODE_ATTR_TTY ) ?
- " [tty]" : "" ),
- ( ( mode->mode_attributes & VBE_MODE_ATTR_GRAPHICS ) ?
- "" : " [text]" ),
- ( ( mode->mode_attributes & VBE_MODE_ATTR_LINEAR ) ?
- "" : " [nonlinear]" ),
- ( ( mode->mode_attributes & VBE_MODE_ATTR_TRIPLE_BUF ) ?
- " [buf]" : "" ) );
-
- return 0;
-}
-
-/**
- * Set video mode
- *
- * @v mode_number Mode number
- * @ret rc Return status code
- */
-static int vesafb_set_mode ( unsigned int mode_number ) {
- struct vbe_mode_info *mode = &vbe_buf.mode;
- uint16_t status;
- int rc;
-
- /* Get mode information */
- if ( ( rc = vesafb_mode_info ( mode_number ) ) != 0 )
- return rc;
-
- /* Record mode parameters */
- vesafb.start = mode->phys_base_ptr;
- vesafb.pixel.width = mode->x_resolution;
- vesafb.pixel.height = mode->y_resolution;
- vesafb.pixel.len = ( ( mode->bits_per_pixel + 7 ) / 8 );
- vesafb.pixel.stride = mode->bytes_per_scan_line;
- DBGC ( &vbe_buf, "VESAFB mode %04x has frame buffer at %08x\n",
- mode_number, mode->phys_base_ptr );
-
- /* Initialise font colours */
- vesafb.map.red_scale = ( 8 - mode->red_mask_size );
- vesafb.map.green_scale = ( 8 - mode->green_mask_size );
- vesafb.map.blue_scale = ( 8 - mode->blue_mask_size );
- vesafb.map.red_lsb = mode->red_field_position;
- vesafb.map.green_lsb = mode->green_field_position;
- vesafb.map.blue_lsb = mode->blue_field_position;
-
- /* Select this mode */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
- : "=a" ( status )
- : "a" ( VBE_SET_MODE ),
- "b" ( mode_number ) );
- if ( ( rc = vesafb_rc ( status ) ) != 0 ) {
- DBGC ( &vbe_buf, "VESAFB could not set mode %04x: [%04x] %s\n",
- mode_number, status, strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
-
-/**
- * Select video mode
- *
- * @v mode_numbers Mode number list (terminated with VBE_MODE_END)
- * @v min_width Minimum required width (in pixels)
- * @v min_height Minimum required height (in pixels)
- * @v min_bpp Minimum required colour depth (in bits per pixel)
- * @ret mode_number Mode number, or negative error
- */
-static int vesafb_select_mode ( const uint16_t *mode_numbers,
- unsigned int min_width, unsigned int min_height,
- unsigned int min_bpp ) {
- struct vbe_mode_info *mode = &vbe_buf.mode;
- int best_mode_number = -ENOENT;
- unsigned int best_score = INT_MAX;
- unsigned int score;
- uint16_t mode_number;
- int rc;
-
- /* Find the first suitable mode */
- while ( ( mode_number = *(mode_numbers++) ) != VBE_MODE_END ) {
-
- /* Force linear mode variant */
- mode_number |= VBE_MODE_LINEAR;
-
- /* Get mode information */
- if ( ( rc = vesafb_mode_info ( mode_number ) ) != 0 )
- continue;
-
- /* Skip unusable modes */
- if ( ( mode->mode_attributes & ( VBE_MODE_ATTR_SUPPORTED |
- VBE_MODE_ATTR_GRAPHICS |
- VBE_MODE_ATTR_LINEAR ) ) !=
- ( VBE_MODE_ATTR_SUPPORTED | VBE_MODE_ATTR_GRAPHICS |
- VBE_MODE_ATTR_LINEAR ) ) {
- continue;
- }
- if ( mode->memory_model != VBE_MODE_MODEL_DIRECT_COLOUR )
- continue;
-
- /* Skip modes not meeting the requirements */
- if ( ( mode->x_resolution < min_width ) ||
- ( mode->y_resolution < min_height ) ||
- ( mode->bits_per_pixel < min_bpp ) ) {
- continue;
- }
-
- /* Select this mode if it has the best (i.e. lowest)
- * score. We choose the scoring system to favour
- * modes close to the specified width and height;
- * within modes of the same width and height we prefer
- * a higher colour depth.
- */
- score = ( ( mode->x_resolution * mode->y_resolution ) -
- mode->bits_per_pixel );
- if ( score < best_score ) {
- best_mode_number = mode_number;
- best_score = score;
- }
- }
-
- if ( best_mode_number >= 0 ) {
- DBGC ( &vbe_buf, "VESAFB selected mode %04x\n",
- best_mode_number );
- } else {
- DBGC ( &vbe_buf, "VESAFB found no suitable mode\n" );
- }
-
- return best_mode_number;
-}
-
-/**
- * Restore video mode
- *
- */
-static void vesafb_restore ( void ) {
- uint32_t discard_a;
-
- /* Restore saved VGA mode */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
- : "=a" ( discard_a )
- : "a" ( VBE_SET_VGA_MODE | vesafb.saved_mode ) );
- DBGC ( &vbe_buf, "VESAFB restored VGA mode %#02x\n",
- vesafb.saved_mode );
-}
-
-/**
- * Initialise VESA frame buffer
- *
- * @v config Console configuration, or NULL to reset
- * @ret rc Return status code
- */
-static int vesafb_init ( struct console_configuration *config ) {
- uint32_t discard_b;
- uint16_t *mode_numbers;
- unsigned int xgap;
- unsigned int ygap;
- unsigned int left;
- unsigned int right;
- unsigned int top;
- unsigned int bottom;
- int mode_number;
- int rc;
-
- /* Record current VGA mode */
- __asm__ __volatile__ ( REAL_CODE ( "int $0x10" )
- : "=a" ( vesafb.saved_mode ), "=b" ( discard_b )
- : "a" ( VBE_GET_VGA_MODE ) );
- DBGC ( &vbe_buf, "VESAFB saved VGA mode %#02x\n", vesafb.saved_mode );
-
- /* Get VESA mode list */
- if ( ( rc = vesafb_mode_list ( &mode_numbers ) ) != 0 )
- goto err_mode_list;
-
- /* Select mode */
- if ( ( mode_number = vesafb_select_mode ( mode_numbers, config->width,
- config->height,
- config->depth ) ) < 0 ) {
- rc = mode_number;
- goto err_select_mode;
- }
-
- /* Set mode */
- if ( ( rc = vesafb_set_mode ( mode_number ) ) != 0 )
- goto err_set_mode;
-
- /* Calculate margin. If the actual screen size is larger than
- * the requested screen size, then update the margins so that
- * the margin remains relative to the requested screen size.
- * (As an exception, if a zero margin was specified then treat
- * this as meaning "expand to edge of actual screen".)
- */
- xgap = ( vesafb.pixel.width - config->width );
- ygap = ( vesafb.pixel.height - config->height );
- left = ( xgap / 2 );
- right = ( xgap - left );
- top = ( ygap / 2 );
- bottom = ( ygap - top );
- vesafb.margin.left = ( config->left + ( config->left ? left : 0 ) );
- vesafb.margin.right = ( config->right + ( config->right ? right : 0 ) );
- vesafb.margin.top = ( config->top + ( config->top ? top : 0 ) );
- vesafb.margin.bottom =
- ( config->bottom + ( config->bottom ? bottom : 0 ) );
-
- /* Get font data */
- vesafb_font();
-
- /* Initialise frame buffer console */
- if ( ( rc = fbcon_init ( &vesafb.fbcon, phys_to_user ( vesafb.start ),
- &vesafb.pixel, &vesafb.margin, &vesafb.map,
- &vesafb.font, config->pixbuf ) ) != 0 )
- goto err_fbcon_init;
-
- free ( mode_numbers );
- return 0;
-
- fbcon_fini ( &vesafb.fbcon );
- err_fbcon_init:
- err_set_mode:
- vesafb_restore();
- err_select_mode:
- free ( mode_numbers );
- err_mode_list:
- return rc;
-}
-
-/**
- * Finalise VESA frame buffer
- *
- */
-static void vesafb_fini ( void ) {
-
- /* Finalise frame buffer console */
- fbcon_fini ( &vesafb.fbcon );
-
- /* Restore saved VGA mode */
- vesafb_restore();
-}
-
-/**
- * Print a character to current cursor position
- *
- * @v character Character
- */
-static void vesafb_putchar ( int character ) {
-
- fbcon_putchar ( &vesafb.fbcon, character );
-}
-
-/**
- * Configure console
- *
- * @v config Console configuration, or NULL to reset
- * @ret rc Return status code
- */
-static int vesafb_configure ( struct console_configuration *config ) {
- int rc;
-
- /* Reset console, if applicable */
- if ( ! vesafb_console.disabled ) {
- vesafb_fini();
- bios_console.disabled &= ~CONSOLE_DISABLED_OUTPUT;
- ansicol_reset_magic();
- }
- vesafb_console.disabled = CONSOLE_DISABLED;
-
- /* Do nothing more unless we have a usable configuration */
- if ( ( config == NULL ) ||
- ( config->width == 0 ) || ( config->height == 0 ) ) {
- return 0;
- }
-
- /* Initialise VESA frame buffer */
- if ( ( rc = vesafb_init ( config ) ) != 0 )
- return rc;
-
- /* Mark console as enabled */
- vesafb_console.disabled = 0;
- bios_console.disabled |= CONSOLE_DISABLED_OUTPUT;
-
- /* Set magic colour to transparent if we have a background picture */
- if ( config->pixbuf )
- ansicol_set_magic_transparent();
-
- return 0;
-}
-
-/** VESA frame buffer console driver */
-struct console_driver vesafb_console __console_driver = {
- .usage = CONSOLE_VESAFB,
- .putchar = vesafb_putchar,
- .configure = vesafb_configure,
- .disabled = CONSOLE_DISABLED,
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c
deleted file mode 100644
index 104313666..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_call.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <ipxe/uaccess.h>
-#include <ipxe/init.h>
-#include <ipxe/profile.h>
-#include <setjmp.h>
-#include <registers.h>
-#include <biosint.h>
-#include <pxe.h>
-#include <pxe_call.h>
-
-/** @file
- *
- * PXE API entry point
- */
-
-/* Disambiguate the various error causes */
-#define EINFO_EPXENBP \
- __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \
- "External PXE NBP error" )
-#define EPXENBP( status ) EPLATFORM ( EINFO_EPXENBP, status )
-
-/** Vector for chaining INT 1A */
-extern struct segoff __text16 ( pxe_int_1a_vector );
-#define pxe_int_1a_vector __use_text16 ( pxe_int_1a_vector )
-
-/** INT 1A handler */
-extern void pxe_int_1a ( void );
-
-/** INT 1A hooked flag */
-static int int_1a_hooked = 0;
-
-/** PXENV_UNDI_TRANSMIT API call profiler */
-static struct profiler pxe_api_tx_profiler __profiler =
- { .name = "pxeapi.tx" };
-
-/** PXENV_UNDI_ISR API call profiler */
-static struct profiler pxe_api_isr_profiler __profiler =
- { .name = "pxeapi.isr" };
-
-/** PXE unknown API call profiler
- *
- * This profiler can be used to measure the overhead of a dummy PXE
- * API call.
- */
-static struct profiler pxe_api_unknown_profiler __profiler =
- { .name = "pxeapi.unknown" };
-
-/** Miscellaneous PXE API call profiler */
-static struct profiler pxe_api_misc_profiler __profiler =
- { .name = "pxeapi.misc" };
-
-/**
- * Handle an unknown PXE API call
- *
- * @v pxenv_unknown Pointer to a struct s_PXENV_UNKNOWN
- * @ret #PXENV_EXIT_FAILURE Always
- * @err #PXENV_STATUS_UNSUPPORTED Always
- */
-static PXENV_EXIT_t pxenv_unknown ( struct s_PXENV_UNKNOWN *pxenv_unknown ) {
- pxenv_unknown->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
-}
-
-/** Unknown PXE API call list */
-struct pxe_api_call pxenv_unknown_api __pxe_api_call =
- PXE_API_CALL ( PXENV_UNKNOWN, pxenv_unknown, struct s_PXENV_UNKNOWN );
-
-/**
- * Locate PXE API call
- *
- * @v opcode Opcode
- * @ret call PXE API call, or NULL
- */
-static struct pxe_api_call * find_pxe_api_call ( uint16_t opcode ) {
- struct pxe_api_call *call;
-
- for_each_table_entry ( call, PXE_API_CALLS ) {
- if ( call->opcode == opcode )
- return call;
- }
- return NULL;
-}
-
-/**
- * Determine applicable profiler (for debugging)
- *
- * @v opcode PXE opcode
- * @ret profiler Profiler
- */
-static struct profiler * pxe_api_profiler ( unsigned int opcode ) {
-
- /* Determine applicable profiler */
- switch ( opcode ) {
- case PXENV_UNDI_TRANSMIT:
- return &pxe_api_tx_profiler;
- case PXENV_UNDI_ISR:
- return &pxe_api_isr_profiler;
- case PXENV_UNKNOWN:
- return &pxe_api_unknown_profiler;
- default:
- return &pxe_api_misc_profiler;
- }
-}
-
-/**
- * Dispatch PXE API call
- *
- * @v bx PXE opcode
- * @v es:di Address of PXE parameter block
- * @ret ax PXE exit code
- */
-__asmcall void pxe_api_call ( struct i386_all_regs *ix86 ) {
- uint16_t opcode = ix86->regs.bx;
- userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di );
- struct profiler *profiler = pxe_api_profiler ( opcode );
- struct pxe_api_call *call;
- union u_PXENV_ANY params;
- PXENV_EXIT_t ret;
-
- /* Start profiling */
- profile_start ( profiler );
-
- /* Locate API call */
- call = find_pxe_api_call ( opcode );
- if ( ! call ) {
- DBGC ( &pxe_netdev, "PXENV_UNKNOWN_%04x\n", opcode );
- call = &pxenv_unknown_api;
- }
-
- /* Copy parameter block from caller */
- copy_from_user ( &params, uparams, 0, call->params_len );
-
- /* Set default status in case child routine fails to do so */
- params.Status = PXENV_STATUS_FAILURE;
-
- /* Hand off to relevant API routine */
- ret = call->entry ( &params );
-
- /* Copy modified parameter block back to caller and return */
- copy_to_user ( uparams, 0, &params, call->params_len );
- ix86->regs.ax = ret;
-
- /* Stop profiling, if applicable */
- profile_stop ( profiler );
-}
-
-/**
- * Dispatch weak PXE API call with PXE stack available
- *
- * @v ix86 Registers for PXE call
- * @ret present Zero (PXE stack present)
- */
-int pxe_api_call_weak ( struct i386_all_regs *ix86 ) {
- pxe_api_call ( ix86 );
- return 0;
-}
-
-/**
- * Dispatch PXE loader call
- *
- * @v es:di Address of PXE parameter block
- * @ret ax PXE exit code
- */
-__asmcall void pxe_loader_call ( struct i386_all_regs *ix86 ) {
- userptr_t uparams = real_to_user ( ix86->segs.es, ix86->regs.di );
- struct s_UNDI_LOADER params;
- PXENV_EXIT_t ret;
-
- /* Copy parameter block from caller */
- copy_from_user ( &params, uparams, 0, sizeof ( params ) );
-
- /* Fill in ROM segment address */
- ppxe.UNDIROMID.segment = ix86->segs.ds;
-
- /* Set default status in case child routine fails to do so */
- params.Status = PXENV_STATUS_FAILURE;
-
- /* Call UNDI loader */
- ret = undi_loader ( &params );
-
- /* Copy modified parameter block back to caller and return */
- copy_to_user ( uparams, 0, &params, sizeof ( params ) );
- ix86->regs.ax = ret;
-}
-
-/**
- * Calculate byte checksum as used by PXE
- *
- * @v data Data
- * @v size Length of data
- * @ret sum Checksum
- */
-static uint8_t pxe_checksum ( void *data, size_t size ) {
- uint8_t *bytes = data;
- uint8_t sum = 0;
-
- while ( size-- ) {
- sum += *bytes++;
- }
- return sum;
-}
-
-/**
- * Initialise !PXE and PXENV+ structures
- *
- */
-static void pxe_init_structures ( void ) {
- uint32_t rm_cs_phys = ( rm_cs << 4 );
- uint32_t rm_ds_phys = ( rm_ds << 4 );
-
- /* Fill in missing segment fields */
- ppxe.EntryPointSP.segment = rm_cs;
- ppxe.EntryPointESP.segment = rm_cs;
- ppxe.Stack.segment_address = rm_ds;
- ppxe.Stack.Physical_address = rm_ds_phys;
- ppxe.UNDIData.segment_address = rm_ds;
- ppxe.UNDIData.Physical_address = rm_ds_phys;
- ppxe.UNDICode.segment_address = rm_cs;
- ppxe.UNDICode.Physical_address = rm_cs_phys;
- ppxe.UNDICodeWrite.segment_address = rm_cs;
- ppxe.UNDICodeWrite.Physical_address = rm_cs_phys;
- pxenv.RMEntry.segment = rm_cs;
- pxenv.StackSeg = rm_ds;
- pxenv.UNDIDataSeg = rm_ds;
- pxenv.UNDICodeSeg = rm_cs;
- pxenv.PXEPtr.segment = rm_cs;
-
- /* Update checksums */
- ppxe.StructCksum -= pxe_checksum ( &ppxe, sizeof ( ppxe ) );
- pxenv.Checksum -= pxe_checksum ( &pxenv, sizeof ( pxenv ) );
-}
-
-/** PXE structure initialiser */
-struct init_fn pxe_init_fn __init_fn ( INIT_NORMAL ) = {
- .initialise = pxe_init_structures,
-};
-
-/**
- * Activate PXE stack
- *
- * @v netdev Net device to use as PXE net device
- */
-void pxe_activate ( struct net_device *netdev ) {
-
- /* Ensure INT 1A is hooked */
- if ( ! int_1a_hooked ) {
- hook_bios_interrupt ( 0x1a, ( unsigned int ) pxe_int_1a,
- &pxe_int_1a_vector );
- devices_get();
- int_1a_hooked = 1;
- }
-
- /* Set PXE network device */
- pxe_set_netdev ( netdev );
-}
-
-/**
- * Deactivate PXE stack
- *
- * @ret rc Return status code
- */
-int pxe_deactivate ( void ) {
- int rc;
-
- /* Clear PXE network device */
- pxe_set_netdev ( NULL );
-
- /* Ensure INT 1A is unhooked, if possible */
- if ( int_1a_hooked ) {
- if ( ( rc = unhook_bios_interrupt ( 0x1a,
- (unsigned int) pxe_int_1a,
- &pxe_int_1a_vector ))!= 0){
- DBG ( "Could not unhook INT 1A: %s\n",
- strerror ( rc ) );
- return rc;
- }
- devices_put();
- int_1a_hooked = 0;
- }
-
- return 0;
-}
-
-/** Jump buffer for PXENV_RESTART_TFTP */
-rmjmp_buf pxe_restart_nbp;
-
-/**
- * Start PXE NBP at 0000:7c00
- *
- * @ret rc Return status code
- */
-int pxe_start_nbp ( void ) {
- int jmp;
- int discard_b, discard_c, discard_d, discard_D;
- uint16_t status;
-
- /* Allow restarting NBP via PXENV_RESTART_TFTP */
- jmp = rmsetjmp ( pxe_restart_nbp );
- if ( jmp )
- DBG ( "Restarting NBP (%x)\n", jmp );
-
- /* Far call to PXE NBP */
- __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
- "movw %%cx, %%es\n\t"
- "pushw %%es\n\t"
- "pushw %%di\n\t"
- "sti\n\t"
- "lcall $0, $0x7c00\n\t"
- "popl %%ebp\n\t" /* discard */
- "popl %%ebp\n\t" /* gcc bug */ )
- : "=a" ( status ), "=b" ( discard_b ),
- "=c" ( discard_c ), "=d" ( discard_d ),
- "=D" ( discard_D )
- : "a" ( 0 ), "b" ( __from_text16 ( &pxenv ) ),
- "c" ( rm_cs ),
- "d" ( virt_to_phys ( &pxenv ) ),
- "D" ( __from_text16 ( &ppxe ) )
- : "esi", "memory" );
- if ( status )
- return -EPXENBP ( status );
-
- return 0;
-}
-
-REQUIRING_SYMBOL ( pxe_api_call );
-REQUIRE_OBJECT ( pxe_preboot );
-REQUIRE_OBJECT ( pxe_undi );
-REQUIRE_OBJECT ( pxe_udp );
-REQUIRE_OBJECT ( pxe_tftp );
-REQUIRE_OBJECT ( pxe_file );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S
deleted file mode 100644
index 07852cd50..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_entry.S
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
-
- .arch i386
-
-/****************************************************************************
- * !PXE structure
- ****************************************************************************
- */
- .section ".text16.data", "aw", @progbits
- .globl ppxe
- .align 16
-ppxe:
- .ascii "!PXE" /* Signature */
- .byte pxe_length /* StructLength */
- .byte 0 /* StructCksum */
- .byte 0 /* StructRev */
- .byte 0 /* reserved_1 */
- .word undiheader, 0 /* UNDIROMID */
- .word 0, 0 /* BaseROMID */
- .word pxe_entry_sp, 0 /* EntryPointSP */
- .word pxe_entry_esp, 0 /* EntryPointESP */
- .word -1, -1 /* StatusCallout */
- .byte 0 /* reserved_2 */
- .byte SegDescCnt /* SegDescCnt */
- .word 0 /* FirstSelector */
-pxe_segments:
- .word 0, 0, 0, _data16_memsz /* Stack */
- .word 0, 0, 0, _data16_memsz /* UNDIData */
- .word 0, 0, 0, _text16_memsz /* UNDICode */
- .word 0, 0, 0, _text16_memsz /* UNDICodeWrite */
- .word 0, 0, 0, 0 /* BC_Data */
- .word 0, 0, 0, 0 /* BC_Code */
- .word 0, 0, 0, 0 /* BC_CodeWrite */
- .equ SegDescCnt, ( ( . - pxe_segments ) / 8 )
- .equ pxe_length, . - ppxe
- .size ppxe, . - ppxe
-
- /* Define undiheader=0 as a weak symbol for non-ROM builds */
- .section ".weak", "a", @nobits
- .weak undiheader
-undiheader:
-
-/****************************************************************************
- * PXENV+ structure
- ****************************************************************************
- */
- .section ".text16.data", "aw", @progbits
- .globl pxenv
- .align 16
-pxenv:
- .ascii "PXENV+" /* Signature */
- .word 0x0201 /* Version */
- .byte pxenv_length /* Length */
- .byte 0 /* Checksum */
- .word pxenv_entry, 0 /* RMEntry */
- .long 0 /* PMEntry */
- .word 0 /* PMSelector */
- .word 0 /* StackSeg */
- .word _data16_memsz /* StackSize */
- .word 0 /* BC_CodeSeg */
- .word 0 /* BC_CodeSize */
- .word 0 /* BC_DataSeg */
- .word 0 /* BC_DataSize */
- .word 0 /* UNDIDataSeg */
- .word _data16_memsz /* UNDIDataSize */
- .word 0 /* UNDICodeSeg */
- .word _text16_memsz /* UNDICodeSize */
- .word ppxe, 0 /* PXEPtr */
- .equ pxenv_length, . - pxenv
- .size pxenv, . - pxenv
-
-/****************************************************************************
- * pxenv_entry (16-bit far call)
- *
- * PXE API call PXENV+ entry point
- *
- * Parameters:
- * %es:di : Far pointer to PXE parameter structure
- * %bx : PXE API call
- * Returns:
- * %ax : PXE exit status
- * Corrupts:
- * none
- ****************************************************************************
- */
- /* Wyse Streaming Manager server (WLDRM13.BIN) assumes that
- * the PXENV+ entry point is at UNDI_CS:0000; apparently,
- * somebody at Wyse has difficulty distinguishing between the
- * words "may" and "must"...
- */
- .section ".text16.null", "ax", @progbits
- .code16
-pxenv_null_entry:
- jmp pxenv_entry
-
- .section ".text16", "ax", @progbits
- .code16
-pxenv_entry:
- pushl $pxe_api_call
- pushw %cs
- call prot_call
- addl $4, %esp
- lret
- .size pxenv_entry, . - pxenv_entry
-
-/****************************************************************************
- * pxe_entry
- *
- * PXE API call !PXE entry point
- *
- * Parameters:
- * stack : Far pointer to PXE parameter structure
- * stack : PXE API call
- * Returns:
- * %ax : PXE exit status
- * Corrupts:
- * none
- ****************************************************************************
- */
- .section ".text16", "ax", @progbits
- .code16
-pxe_entry:
-pxe_entry_sp:
- /* Preserve original %esp */
- pushl %esp
- /* Zero high word of %esp to allow use of common code */
- movzwl %sp, %esp
- jmp pxe_entry_common
-pxe_entry_esp:
- /* Preserve %esp to match behaviour of pxe_entry_sp */
- pushl %esp
-pxe_entry_common:
- /* Save PXENV+ API call registers */
- pushw %es
- pushw %di
- pushw %bx
- /* Load !PXE parameters from stack into PXENV+ registers */
- addr32 movw 18(%esp), %bx
- movw %bx, %es
- addr32 movw 16(%esp), %di
- addr32 movw 14(%esp), %bx
- /* Make call as for PXENV+ */
- pushw %cs
- call pxenv_entry
- /* Restore PXENV+ registers */
- popw %bx
- popw %di
- popw %es
- /* Restore original %esp and return */
- popl %esp
- lret
- .size pxe_entry, . - pxe_entry
-
-/****************************************************************************
- * pxe_int_1a
- *
- * PXE INT 1A handler
- *
- * Parameters:
- * %ax : 0x5650
- * Returns:
- * %ax : 0x564e
- * %es:bx : Far pointer to the PXENV+ structure
- * %edx : Physical address of the PXENV+ structure
- * CF cleared
- * Corrupts:
- * none
- ****************************************************************************
- */
- .section ".text16", "ax", @progbits
- .code16
- .globl pxe_int_1a
-pxe_int_1a:
- pushfw
- cmpw $0x5650, %ax
- jne 1f
- /* INT 1A,5650 - PXE installation check */
- xorl %edx, %edx
- movw %cs, %dx
- movw %dx, %es
- movw $pxenv, %bx
- shll $4, %edx
- addl $pxenv, %edx
- movw $0x564e, %ax
- pushw %bp
- movw %sp, %bp
- andb $~0x01, 8(%bp) /* Clear CF on return */
- popw %bp
- popfw
- iret
-1: /* INT 1A,other - pass through */
- popfw
- ljmp *%cs:pxe_int_1a_vector
-
- .section ".text16.data", "aw", @progbits
- .globl pxe_int_1a_vector
-pxe_int_1a_vector: .long 0
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c
deleted file mode 100644
index f92dae0d1..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_exit_hook.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/** @file
- *
- * PXE exit hook
- *
- */
-
-/*
- * Copyright (C) 2010 Shao Miller <shao.miller@yrdsb.edu.on.ca>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <realmode.h>
-#include <pxe.h>
-
-/** PXE exit hook */
-extern segoff_t __data16 ( pxe_exit_hook );
-#define pxe_exit_hook __use_data16 ( pxe_exit_hook )
-
-/**
- * FILE EXIT HOOK
- *
- * @v file_exit_hook Pointer to a struct
- * s_PXENV_FILE_EXIT_HOOK
- * @v s_PXENV_FILE_EXIT_HOOK::Hook SEG16:OFF16 to jump to
- * @ret #PXENV_EXIT_SUCCESS Successfully set hook
- * @ret #PXENV_EXIT_FAILURE We're not an NBP build
- * @ret s_PXENV_FILE_EXIT_HOOK::Status PXE status code
- *
- */
-static PXENV_EXIT_t
-pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK *file_exit_hook ) {
- DBG ( "PXENV_FILE_EXIT_HOOK" );
-
- /* We'll jump to the specified SEG16:OFF16 during exit */
- pxe_exit_hook.segment = file_exit_hook->Hook.segment;
- pxe_exit_hook.offset = file_exit_hook->Hook.offset;
- file_exit_hook->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/** PXE file API */
-struct pxe_api_call pxe_file_api_exit_hook __pxe_api_call =
- PXE_API_CALL ( PXENV_FILE_EXIT_HOOK, pxenv_file_exit_hook,
- struct s_PXENV_FILE_EXIT_HOOK );
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c
deleted file mode 100644
index 456ffb5fd..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_file.c
+++ /dev/null
@@ -1,346 +0,0 @@
-/** @file
- *
- * PXE FILE API
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <byteswap.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/posix_io.h>
-#include <ipxe/features.h>
-#include <pxe.h>
-#include <realmode.h>
-
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-FEATURE ( FEATURE_MISC, "PXEXT", DHCP_EB_FEATURE_PXE_EXT, 2 );
-
-/**
- * FILE OPEN
- *
- * @v file_open Pointer to a struct s_PXENV_FILE_OPEN
- * @v s_PXENV_FILE_OPEN::FileName URL of file to open
- * @ret #PXENV_EXIT_SUCCESS File was opened
- * @ret #PXENV_EXIT_FAILURE File was not opened
- * @ret s_PXENV_FILE_OPEN::Status PXE status code
- * @ret s_PXENV_FILE_OPEN::FileHandle Handle of opened file
- *
- */
-static PXENV_EXIT_t pxenv_file_open ( struct s_PXENV_FILE_OPEN *file_open ) {
- userptr_t filename;
- size_t filename_len;
- int fd;
-
- DBG ( "PXENV_FILE_OPEN" );
-
- /* Copy name from external program, and open it */
- filename = real_to_user ( file_open->FileName.segment,
- file_open->FileName.offset );
- filename_len = strlen_user ( filename, 0 );
- {
- char uri_string[ filename_len + 1 ];
-
- copy_from_user ( uri_string, filename, 0,
- sizeof ( uri_string ) );
- DBG ( " %s", uri_string );
- fd = open ( uri_string );
- }
-
- if ( fd < 0 ) {
- file_open->Status = PXENV_STATUS ( fd );
- return PXENV_EXIT_FAILURE;
- }
-
- DBG ( " as file %d", fd );
-
- file_open->FileHandle = fd;
- file_open->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * FILE CLOSE
- *
- * @v file_close Pointer to a struct s_PXENV_FILE_CLOSE
- * @v s_PXENV_FILE_CLOSE::FileHandle File handle
- * @ret #PXENV_EXIT_SUCCESS File was closed
- * @ret #PXENV_EXIT_FAILURE File was not closed
- * @ret s_PXENV_FILE_CLOSE::Status PXE status code
- *
- */
-static PXENV_EXIT_t pxenv_file_close ( struct s_PXENV_FILE_CLOSE *file_close ) {
-
- DBG ( "PXENV_FILE_CLOSE %d", file_close->FileHandle );
-
- close ( file_close->FileHandle );
- file_close->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * FILE SELECT
- *
- * @v file_select Pointer to a struct s_PXENV_FILE_SELECT
- * @v s_PXENV_FILE_SELECT::FileHandle File handle
- * @ret #PXENV_EXIT_SUCCESS File has been checked for readiness
- * @ret #PXENV_EXIT_FAILURE File has not been checked for readiness
- * @ret s_PXENV_FILE_SELECT::Status PXE status code
- * @ret s_PXENV_FILE_SELECT::Ready Indication of readiness
- *
- */
-static PXENV_EXIT_t
-pxenv_file_select ( struct s_PXENV_FILE_SELECT *file_select ) {
- fd_set fdset;
- int ready;
-
- DBG ( "PXENV_FILE_SELECT %d", file_select->FileHandle );
-
- FD_ZERO ( &fdset );
- FD_SET ( file_select->FileHandle, &fdset );
- if ( ( ready = select ( &fdset, 0 ) ) < 0 ) {
- file_select->Status = PXENV_STATUS ( ready );
- return PXENV_EXIT_FAILURE;
- }
-
- file_select->Ready = ( ready ? RDY_READ : 0 );
- file_select->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * FILE READ
- *
- * @v file_read Pointer to a struct s_PXENV_FILE_READ
- * @v s_PXENV_FILE_READ::FileHandle File handle
- * @v s_PXENV_FILE_READ::BufferSize Size of data buffer
- * @v s_PXENV_FILE_READ::Buffer Data buffer
- * @ret #PXENV_EXIT_SUCCESS Data has been read from file
- * @ret #PXENV_EXIT_FAILURE Data has not been read from file
- * @ret s_PXENV_FILE_READ::Status PXE status code
- * @ret s_PXENV_FILE_READ::Ready Indication of readiness
- * @ret s_PXENV_FILE_READ::BufferSize Length of data read
- *
- */
-static PXENV_EXIT_t pxenv_file_read ( struct s_PXENV_FILE_READ *file_read ) {
- userptr_t buffer;
- ssize_t len;
-
- DBG ( "PXENV_FILE_READ %d to %04x:%04x+%04x", file_read->FileHandle,
- file_read->Buffer.segment, file_read->Buffer.offset,
- file_read->BufferSize );
-
- buffer = real_to_user ( file_read->Buffer.segment,
- file_read->Buffer.offset );
- if ( ( len = read_user ( file_read->FileHandle, buffer, 0,
- file_read->BufferSize ) ) < 0 ) {
- file_read->Status = PXENV_STATUS ( len );
- return PXENV_EXIT_FAILURE;
- }
-
- DBG ( " read %04zx", ( ( size_t ) len ) );
-
- file_read->BufferSize = len;
- file_read->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * GET FILE SIZE
- *
- * @v get_file_size Pointer to a struct s_PXENV_GET_FILE_SIZE
- * @v s_PXENV_GET_FILE_SIZE::FileHandle File handle
- * @ret #PXENV_EXIT_SUCCESS File size has been determined
- * @ret #PXENV_EXIT_FAILURE File size has not been determined
- * @ret s_PXENV_GET_FILE_SIZE::Status PXE status code
- * @ret s_PXENV_GET_FILE_SIZE::FileSize Size of file
- */
-static PXENV_EXIT_t
-pxenv_get_file_size ( struct s_PXENV_GET_FILE_SIZE *get_file_size ) {
- ssize_t filesize;
-
- DBG ( "PXENV_GET_FILE_SIZE %d", get_file_size->FileHandle );
-
- filesize = fsize ( get_file_size->FileHandle );
- if ( filesize < 0 ) {
- get_file_size->Status = PXENV_STATUS ( filesize );
- return PXENV_EXIT_FAILURE;
- }
-
- DBG ( " is %zd", ( ( size_t ) filesize ) );
-
- get_file_size->FileSize = filesize;
- get_file_size->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * FILE EXEC
- *
- * @v file_exec Pointer to a struct s_PXENV_FILE_EXEC
- * @v s_PXENV_FILE_EXEC::Command Command to execute
- * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
- * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
- * @ret s_PXENV_FILE_EXEC::Status PXE status code
- *
- */
-static PXENV_EXIT_t pxenv_file_exec ( struct s_PXENV_FILE_EXEC *file_exec ) {
- userptr_t command;
- size_t command_len;
- int rc;
-
- DBG ( "PXENV_FILE_EXEC" );
-
- /* Copy name from external program, and exec it */
- command = real_to_user ( file_exec->Command.segment,
- file_exec->Command.offset );
- command_len = strlen_user ( command, 0 );
- {
- char command_string[ command_len + 1 ];
-
- copy_from_user ( command_string, command, 0,
- sizeof ( command_string ) );
- DBG ( " %s", command_string );
-
- if ( ( rc = system ( command_string ) ) != 0 ) {
- file_exec->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
- }
-
- file_exec->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * FILE CMDLINE
- *
- * @v file_cmdline Pointer to a struct s_PXENV_FILE_CMDLINE
- * @v s_PXENV_FILE_CMDLINE::Buffer Buffer to contain command line
- * @v s_PXENV_FILE_CMDLINE::BufferSize Size of buffer
- * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
- * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
- * @ret s_PXENV_FILE_EXEC::Status PXE status code
- * @ret s_PXENV_FILE_EXEC::BufferSize Length of command line (including NUL)
- *
- */
-static PXENV_EXIT_t
-pxenv_file_cmdline ( struct s_PXENV_FILE_CMDLINE *file_cmdline ) {
- userptr_t buffer;
- size_t max_len;
- size_t len;
-
- DBG ( "PXENV_FILE_CMDLINE to %04x:%04x+%04x \"%s\"\n",
- file_cmdline->Buffer.segment, file_cmdline->Buffer.offset,
- file_cmdline->BufferSize, pxe_cmdline );
-
- buffer = real_to_user ( file_cmdline->Buffer.segment,
- file_cmdline->Buffer.offset );
- len = file_cmdline->BufferSize;
- max_len = ( pxe_cmdline ?
- ( strlen ( pxe_cmdline ) + 1 /* NUL */ ) : 0 );
- if ( len > max_len )
- len = max_len;
- copy_to_user ( buffer, 0, pxe_cmdline, len );
- file_cmdline->BufferSize = max_len;
-
- file_cmdline->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * FILE API CHECK
- *
- * @v file_exec Pointer to a struct s_PXENV_FILE_API_CHECK
- * @v s_PXENV_FILE_API_CHECK::Magic Inbound magic number (0x91d447b2)
- * @ret #PXENV_EXIT_SUCCESS Command was executed successfully
- * @ret #PXENV_EXIT_FAILURE Command was not executed successfully
- * @ret s_PXENV_FILE_API_CHECK::Status PXE status code
- * @ret s_PXENV_FILE_API_CHECK::Magic Outbound magic number (0xe9c17b20)
- * @ret s_PXENV_FILE_API_CHECK::Provider "iPXE" (0x45585067)
- * @ret s_PXENV_FILE_API_CHECK::APIMask API function bitmask
- * @ret s_PXENV_FILE_API_CHECK::Flags Reserved
- *
- */
-static PXENV_EXIT_t
-pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ) {
- struct pxe_api_call *call;
- unsigned int mask = 0;
- unsigned int offset;
-
- DBG ( "PXENV_FILE_API_CHECK" );
-
- /* Check for magic value */
- if ( file_api_check->Magic != 0x91d447b2 ) {
- file_api_check->Status = PXENV_STATUS_BAD_FUNC;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Check for required parameter size */
- if ( file_api_check->Size < sizeof ( *file_api_check ) ) {
- file_api_check->Status = PXENV_STATUS_OUT_OF_RESOURCES;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Determine supported calls */
- for_each_table_entry ( call, PXE_API_CALLS ) {
- offset = ( call->opcode - PXENV_FILE_MIN );
- if ( offset <= ( PXENV_FILE_MAX - PXENV_FILE_MIN ) )
- mask |= ( 1 << offset );
- }
-
- /* Fill in parameters */
- file_api_check->Size = sizeof ( *file_api_check );
- file_api_check->Magic = 0xe9c17b20;
- file_api_check->Provider = 0x45585067; /* "iPXE" */
- file_api_check->APIMask = mask;
- file_api_check->Flags = 0; /* None defined */
-
- file_api_check->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/** PXE file API */
-struct pxe_api_call pxe_file_api[] __pxe_api_call = {
- PXE_API_CALL ( PXENV_FILE_OPEN, pxenv_file_open,
- struct s_PXENV_FILE_OPEN ),
- PXE_API_CALL ( PXENV_FILE_CLOSE, pxenv_file_close,
- struct s_PXENV_FILE_CLOSE ),
- PXE_API_CALL ( PXENV_FILE_SELECT, pxenv_file_select,
- struct s_PXENV_FILE_SELECT ),
- PXE_API_CALL ( PXENV_FILE_READ, pxenv_file_read,
- struct s_PXENV_FILE_READ ),
- PXE_API_CALL ( PXENV_GET_FILE_SIZE, pxenv_get_file_size,
- struct s_PXENV_GET_FILE_SIZE ),
- PXE_API_CALL ( PXENV_FILE_EXEC, pxenv_file_exec,
- struct s_PXENV_FILE_EXEC ),
- PXE_API_CALL ( PXENV_FILE_CMDLINE, pxenv_file_cmdline,
- struct s_PXENV_FILE_CMDLINE ),
- PXE_API_CALL ( PXENV_FILE_API_CHECK, pxenv_file_api_check,
- struct s_PXENV_FILE_API_CHECK ),
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c
deleted file mode 100644
index e6a2e072a..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_loader.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <ipxe/init.h>
-#include "pxe.h"
-#include "pxe_call.h"
-
-/** @file
- *
- * PXE UNDI loader
- *
- */
-
-/* PXENV_UNDI_LOADER
- *
- */
-PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ) {
-
- /* Perform one-time initialisation (e.g. heap) */
- initialise();
-
- DBG ( "[PXENV_UNDI_LOADER to CS %04x DS %04x]",
- undi_loader->UNDI_CS, undi_loader->UNDI_DS );
-
- /* Fill in UNDI loader structure */
- undi_loader->PXEptr.segment = rm_cs;
- undi_loader->PXEptr.offset = __from_text16 ( &ppxe );
- undi_loader->PXENVptr.segment = rm_cs;
- undi_loader->PXENVptr.offset = __from_text16 ( &pxenv );
-
- undi_loader->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c
deleted file mode 100644
index 6e09080bc..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_preboot.c
+++ /dev/null
@@ -1,387 +0,0 @@
-/** @file
- *
- * PXE Preboot API
- *
- */
-
-/* PXE API interface for Etherboot.
- *
- * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <setjmp.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/dhcp.h>
-#include <ipxe/fakedhcp.h>
-#include <ipxe/device.h>
-#include <ipxe/netdevice.h>
-#include <ipxe/isapnp.h>
-#include <ipxe/init.h>
-#include <ipxe/if_ether.h>
-#include <basemem_packet.h>
-#include <biosint.h>
-#include "pxe.h"
-#include "pxe_call.h"
-
-/* Avoid dragging in isapnp.o unnecessarily */
-uint16_t isapnp_read_port;
-
-/** Zero-based versions of PXENV_GET_CACHED_INFO::PacketType */
-enum pxe_cached_info_indices {
- CACHED_INFO_DHCPDISCOVER = ( PXENV_PACKET_TYPE_DHCP_DISCOVER - 1 ),
- CACHED_INFO_DHCPACK = ( PXENV_PACKET_TYPE_DHCP_ACK - 1 ),
- CACHED_INFO_BINL = ( PXENV_PACKET_TYPE_CACHED_REPLY - 1 ),
- NUM_CACHED_INFOS
-};
-
-/** A cached DHCP packet */
-union pxe_cached_info {
- struct dhcphdr dhcphdr;
- /* This buffer must be *exactly* the size of a BOOTPLAYER_t
- * structure, otherwise WinPE will die horribly. It takes the
- * size of *our* buffer and feeds it in to us as the size of
- * one of *its* buffers. If our buffer is larger than it
- * expects, we therefore end up overwriting part of its data
- * segment, since it tells us to do so. (D'oh!)
- *
- * Note that a BOOTPLAYER_t is not necessarily large enough to
- * hold a DHCP packet; this is a flaw in the PXE spec.
- */
- BOOTPLAYER_t packet;
-} __attribute__ (( packed ));
-
-/** A PXE DHCP packet creator */
-struct pxe_dhcp_packet_creator {
- /** Create DHCP packet
- *
- * @v netdev Network device
- * @v data Buffer for DHCP packet
- * @v max_len Size of DHCP packet buffer
- * @ret rc Return status code
- */
- int ( * create ) ( struct net_device *netdev, void *data,
- size_t max_len );
-};
-
-/** PXE DHCP packet creators */
-static struct pxe_dhcp_packet_creator pxe_dhcp_packet_creators[] = {
- [CACHED_INFO_DHCPDISCOVER] = { create_fakedhcpdiscover },
- [CACHED_INFO_DHCPACK] = { create_fakedhcpack },
- [CACHED_INFO_BINL] = { create_fakepxebsack },
-};
-
-/**
- * Name PXENV_GET_CACHED_INFO packet type
- *
- * @v packet_type Packet type
- * @ret name Name of packet type
- */
-static inline __attribute__ (( always_inline )) const char *
-pxenv_get_cached_info_name ( int packet_type ) {
- switch ( packet_type ) {
- case PXENV_PACKET_TYPE_DHCP_DISCOVER:
- return "DHCPDISCOVER";
- case PXENV_PACKET_TYPE_DHCP_ACK:
- return "DHCPACK";
- case PXENV_PACKET_TYPE_CACHED_REPLY:
- return "BINL";
- default:
- return "<INVALID>";
- }
-}
-
-/* The case in which the caller doesn't supply a buffer is really
- * awkward to support given that we have multiple sources of options,
- * and that we don't actually store the DHCP packets. (We may not
- * even have performed DHCP; we may have obtained all configuration
- * from non-volatile stored options or from the command line.)
- *
- * Some NBPs rely on the buffers we provide being persistent, so we
- * can't just use the temporary packet buffer. 4.5kB of base memory
- * always wasted just because some clients are too lazy to provide
- * their own buffers...
- */
-static union pxe_cached_info __bss16_array ( cached_info, [NUM_CACHED_INFOS] );
-#define cached_info __use_data16 ( cached_info )
-
-/**
- * UNLOAD BASE CODE STACK
- *
- * @v None -
- * @ret ...
- *
- */
-static PXENV_EXIT_t
-pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) {
- DBGC ( &pxe_netdev, "PXENV_UNLOAD_STACK\n" );
-
- unload_stack->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_GET_CACHED_INFO
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_get_cached_info ( struct s_PXENV_GET_CACHED_INFO *get_cached_info ) {
- struct pxe_dhcp_packet_creator *creator;
- union pxe_cached_info *info;
- unsigned int idx;
- size_t len;
- userptr_t buffer;
- int rc;
-
- DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO %s to %04x:%04x+%x",
- pxenv_get_cached_info_name ( get_cached_info->PacketType ),
- get_cached_info->Buffer.segment,
- get_cached_info->Buffer.offset, get_cached_info->BufferSize );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_GET_CACHED_INFO called with no "
- "network device\n" );
- get_cached_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Sanity check */
- idx = ( get_cached_info->PacketType - 1 );
- if ( idx >= NUM_CACHED_INFOS ) {
- DBGC ( &pxe_netdev, " bad PacketType %d\n",
- get_cached_info->PacketType );
- goto err;
- }
- info = &cached_info[idx];
-
- /* Construct DHCP packet */
- creator = &pxe_dhcp_packet_creators[idx];
- if ( ( rc = creator->create ( pxe_netdev, info,
- sizeof ( *info ) ) ) != 0 ) {
- DBGC ( &pxe_netdev, " failed to build packet: %s\n",
- strerror ( rc ) );
- goto err;
- }
-
- /* Copy packet (if applicable) */
- len = get_cached_info->BufferSize;
- if ( len == 0 ) {
- /* Point client at our cached buffer.
- *
- * To add to the fun, Intel decided at some point in
- * the evolution of the PXE specification to add the
- * BufferLimit field, which we are meant to fill in
- * with the length of our packet buffer, so that the
- * caller can safely modify the boot server reply
- * packet stored therein. However, this field was not
- * present in earlier versions of the PXE spec, and
- * there is at least one PXE NBP (Altiris) which
- * allocates only exactly enough space for this
- * earlier, shorter version of the structure. If we
- * actually fill in the BufferLimit field, we
- * therefore risk trashing random areas of the
- * caller's memory. If we *don't* fill it in, then
- * the caller is at liberty to assume that whatever
- * random value happened to be in that location
- * represents the length of the buffer we've just
- * passed back to it.
- *
- * Since older PXE stacks won't fill this field in
- * anyway, it's probably safe to assume that no
- * callers actually rely on it, so we choose to not
- * fill it in.
- */
- get_cached_info->Buffer.segment = rm_ds;
- get_cached_info->Buffer.offset = __from_data16 ( info );
- get_cached_info->BufferSize = sizeof ( *info );
- DBGC ( &pxe_netdev, " using %04x:%04x+%04x['%x']",
- get_cached_info->Buffer.segment,
- get_cached_info->Buffer.offset,
- get_cached_info->BufferSize,
- get_cached_info->BufferLimit );
- } else {
- /* Copy packet to client buffer */
- if ( len > sizeof ( *info ) )
- len = sizeof ( *info );
- if ( len < sizeof ( *info ) )
- DBGC ( &pxe_netdev, " buffer may be too short" );
- buffer = real_to_user ( get_cached_info->Buffer.segment,
- get_cached_info->Buffer.offset );
- copy_to_user ( buffer, 0, info, len );
- get_cached_info->BufferSize = len;
- }
-
- DBGC ( &pxe_netdev, "\n" );
- get_cached_info->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-
- err:
- get_cached_info->Status = PXENV_STATUS_OUT_OF_RESOURCES;
- return PXENV_EXIT_FAILURE;
-}
-
-/* PXENV_RESTART_TFTP
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE *restart_tftp ) {
- PXENV_EXIT_t tftp_exit;
-
- DBGC ( &pxe_netdev, "PXENV_RESTART_TFTP\n" );
-
- /* Words cannot describe the complete mismatch between the PXE
- * specification and any possible version of reality...
- */
- restart_tftp->Buffer = PXE_LOAD_PHYS; /* Fixed by spec, apparently */
- restart_tftp->BufferSize = ( 0xa0000 - PXE_LOAD_PHYS ); /* Near enough */
- tftp_exit = pxenv_tftp_read_file ( restart_tftp );
- if ( tftp_exit != PXENV_EXIT_SUCCESS )
- return tftp_exit;
-
- /* Restart NBP */
- rmlongjmp ( pxe_restart_nbp, PXENV_RESTART_TFTP );
-}
-
-/* PXENV_START_UNDI
- *
- * Status: working
- */
-static PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
- unsigned int bus_type;
- unsigned int location;
- struct net_device *netdev;
-
- DBGC ( &pxe_netdev, "PXENV_START_UNDI %04x:%04x:%04x\n",
- start_undi->AX, start_undi->BX, start_undi->DX );
-
- /* Determine bus type and location. Use a heuristic to decide
- * whether we are PCI or ISAPnP
- */
- if ( ( start_undi->DX >= ISAPNP_READ_PORT_MIN ) &&
- ( start_undi->DX <= ISAPNP_READ_PORT_MAX ) &&
- ( start_undi->BX >= ISAPNP_CSN_MIN ) &&
- ( start_undi->BX <= ISAPNP_CSN_MAX ) ) {
- bus_type = BUS_TYPE_ISAPNP;
- location = start_undi->BX;
- /* Record ISAPnP read port for use by isapnp.c */
- isapnp_read_port = start_undi->DX;
- } else {
- bus_type = BUS_TYPE_PCI;
- location = start_undi->AX;
- }
-
- /* Probe for devices, etc. */
- startup();
-
- /* Look for a matching net device */
- netdev = find_netdev_by_location ( bus_type, location );
- if ( ! netdev ) {
- DBGC ( &pxe_netdev, "PXENV_START_UNDI could not find matching "
- "net device\n" );
- start_undi->Status = PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC;
- return PXENV_EXIT_FAILURE;
- }
- DBGC ( &pxe_netdev, "PXENV_START_UNDI found net device %s\n",
- netdev->name );
-
- /* Activate PXE */
- pxe_activate ( netdev );
-
- start_undi->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_STOP_UNDI
- *
- * Status: working
- */
-static PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) {
- DBGC ( &pxe_netdev, "PXENV_STOP_UNDI\n" );
-
- /* Deactivate PXE */
- pxe_deactivate();
-
- /* Prepare for unload */
- shutdown_boot();
-
- /* Check to see if we still have any hooked interrupts */
- if ( hooked_bios_interrupts != 0 ) {
- DBGC ( &pxe_netdev, "PXENV_STOP_UNDI failed: %d interrupts "
- "still hooked\n", hooked_bios_interrupts );
- stop_undi->Status = PXENV_STATUS_KEEP_UNDI;
- return PXENV_EXIT_FAILURE;
- }
-
- stop_undi->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_START_BASE
- *
- * Status: won't implement (requires major structural changes)
- */
-static PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base ) {
- DBGC ( &pxe_netdev, "PXENV_START_BASE\n" );
-
- start_base->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
-}
-
-/* PXENV_STOP_BASE
- *
- * Status: working
- */
-static PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base ) {
- DBGC ( &pxe_netdev, "PXENV_STOP_BASE\n" );
-
- /* The only time we will be called is when the NBP is trying
- * to shut down the PXE stack. There's nothing we need to do
- * in this call.
- */
-
- stop_base->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/** PXE preboot API */
-struct pxe_api_call pxe_preboot_api[] __pxe_api_call = {
- PXE_API_CALL ( PXENV_UNLOAD_STACK, pxenv_unload_stack,
- struct s_PXENV_UNLOAD_STACK ),
- PXE_API_CALL ( PXENV_GET_CACHED_INFO, pxenv_get_cached_info,
- struct s_PXENV_GET_CACHED_INFO ),
- PXE_API_CALL ( PXENV_RESTART_TFTP, pxenv_restart_tftp,
- struct s_PXENV_TFTP_READ_FILE ),
- PXE_API_CALL ( PXENV_START_UNDI, pxenv_start_undi,
- struct s_PXENV_START_UNDI ),
- PXE_API_CALL ( PXENV_STOP_UNDI, pxenv_stop_undi,
- struct s_PXENV_STOP_UNDI ),
- PXE_API_CALL ( PXENV_START_BASE, pxenv_start_base,
- struct s_PXENV_START_BASE ),
- PXE_API_CALL ( PXENV_STOP_BASE, pxenv_stop_base,
- struct s_PXENV_STOP_BASE ),
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c
deleted file mode 100644
index 068d8a7b2..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_tftp.c
+++ /dev/null
@@ -1,597 +0,0 @@
-/** @file
- *
- * PXE TFTP API
- *
- */
-
-/*
- * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <byteswap.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/in.h>
-#include <ipxe/tftp.h>
-#include <ipxe/iobuf.h>
-#include <ipxe/xfer.h>
-#include <ipxe/open.h>
-#include <ipxe/process.h>
-#include <ipxe/uri.h>
-#include <realmode.h>
-#include <pxe.h>
-
-/** A PXE TFTP connection */
-struct pxe_tftp_connection {
- /** Data transfer interface */
- struct interface xfer;
- /** Data buffer */
- userptr_t buffer;
- /** Size of data buffer */
- size_t size;
- /** Starting offset of data buffer */
- size_t start;
- /** File position */
- size_t offset;
- /** Maximum file position */
- size_t max_offset;
- /** Block size */
- size_t blksize;
- /** Block index */
- unsigned int blkidx;
- /** Overall return status code */
- int rc;
-};
-
-/**
- * Close PXE TFTP connection
- *
- * @v pxe_tftp PXE TFTP connection
- * @v rc Final status code
- */
-static void pxe_tftp_close ( struct pxe_tftp_connection *pxe_tftp, int rc ) {
- intf_shutdown ( &pxe_tftp->xfer, rc );
- pxe_tftp->rc = rc;
-}
-
-/**
- * Check flow control window
- *
- * @v pxe_tftp PXE TFTP connection
- * @ret len Length of window
- */
-static size_t pxe_tftp_xfer_window ( struct pxe_tftp_connection *pxe_tftp ) {
-
- return pxe_tftp->blksize;
-}
-
-/**
- * Receive new data
- *
- * @v pxe_tftp PXE TFTP connection
- * @v iobuf I/O buffer
- * @v meta Transfer metadata
- * @ret rc Return status code
- */
-static int pxe_tftp_xfer_deliver ( struct pxe_tftp_connection *pxe_tftp,
- struct io_buffer *iobuf,
- struct xfer_metadata *meta ) {
- size_t len = iob_len ( iobuf );
- int rc = 0;
-
- /* Calculate new buffer position */
- if ( meta->flags & XFER_FL_ABS_OFFSET )
- pxe_tftp->offset = 0;
- pxe_tftp->offset += meta->offset;
-
- /* Copy data block to buffer */
- if ( len == 0 ) {
- /* No data (pure seek); treat as success */
- } else if ( pxe_tftp->offset < pxe_tftp->start ) {
- DBG ( " buffer underrun at %zx (min %zx)",
- pxe_tftp->offset, pxe_tftp->start );
- rc = -ENOBUFS;
- } else if ( ( pxe_tftp->offset + len ) >
- ( pxe_tftp->start + pxe_tftp->size ) ) {
- DBG ( " buffer overrun at %zx (max %zx)",
- ( pxe_tftp->offset + len ),
- ( pxe_tftp->start + pxe_tftp->size ) );
- rc = -ENOBUFS;
- } else {
- copy_to_user ( pxe_tftp->buffer,
- ( pxe_tftp->offset - pxe_tftp->start ),
- iobuf->data, len );
- }
-
- /* Calculate new buffer position */
- pxe_tftp->offset += len;
-
- /* Record maximum offset as the file size */
- if ( pxe_tftp->max_offset < pxe_tftp->offset )
- pxe_tftp->max_offset = pxe_tftp->offset;
-
- /* Terminate transfer on error */
- if ( rc != 0 )
- pxe_tftp_close ( pxe_tftp, rc );
-
- free_iob ( iobuf );
- return rc;
-}
-
-/** PXE TFTP connection interface operations */
-static struct interface_operation pxe_tftp_xfer_ops[] = {
- INTF_OP ( xfer_deliver, struct pxe_tftp_connection *,
- pxe_tftp_xfer_deliver ),
- INTF_OP ( xfer_window, struct pxe_tftp_connection *,
- pxe_tftp_xfer_window ),
- INTF_OP ( intf_close, struct pxe_tftp_connection *, pxe_tftp_close ),
-};
-
-/** PXE TFTP connection interface descriptor */
-static struct interface_descriptor pxe_tftp_xfer_desc =
- INTF_DESC ( struct pxe_tftp_connection, xfer, pxe_tftp_xfer_ops );
-
-/** The PXE TFTP connection */
-static struct pxe_tftp_connection pxe_tftp = {
- .xfer = INTF_INIT ( pxe_tftp_xfer_desc ),
-};
-
-/**
- * Maximum length of a PXE TFTP URI
- *
- * The PXE TFTP API provides 128 characters for the filename; the
- * extra 128 bytes allow for the remainder of the URI.
- */
-#define PXE_TFTP_URI_LEN 256
-
-/**
- * Open PXE TFTP connection
- *
- * @v ipaddress IP address
- * @v port TFTP server port
- * @v filename File name
- * @v blksize Requested block size
- * @ret rc Return status code
- */
-static int pxe_tftp_open ( IP4_t ipaddress, UDP_PORT_t port,
- UINT8_t *filename, UINT16_t blksize ) {
- struct in_addr address;
- struct uri *uri;
- int rc;
-
- /* Reset PXE TFTP connection structure */
- memset ( &pxe_tftp, 0, sizeof ( pxe_tftp ) );
- intf_init ( &pxe_tftp.xfer, &pxe_tftp_xfer_desc, NULL );
- if ( blksize < TFTP_DEFAULT_BLKSIZE )
- blksize = TFTP_DEFAULT_BLKSIZE;
- pxe_tftp.blksize = blksize;
- pxe_tftp.rc = -EINPROGRESS;
-
- /* Construct URI */
- address.s_addr = ipaddress;
- DBG ( " %s", inet_ntoa ( address ) );
- if ( port )
- DBG ( ":%d", ntohs ( port ) );
- DBG ( ":%s", filename );
- uri = tftp_uri ( address, ntohs ( port ), ( ( char * ) filename ) );
- if ( ! uri ) {
- DBG ( " could not create URI\n" );
- return -ENOMEM;
- }
-
- /* Open PXE TFTP connection */
- if ( ( rc = xfer_open_uri ( &pxe_tftp.xfer, uri ) ) != 0 ) {
- DBG ( " could not open (%s)\n", strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
-
-/**
- * TFTP OPEN
- *
- * @v tftp_open Pointer to a struct s_PXENV_TFTP_OPEN
- * @v s_PXENV_TFTP_OPEN::ServerIPAddress TFTP server IP address
- * @v s_PXENV_TFTP_OPEN::GatewayIPAddress Relay agent IP address, or 0.0.0.0
- * @v s_PXENV_TFTP_OPEN::FileName Name of file to open
- * @v s_PXENV_TFTP_OPEN::TFTPPort TFTP server UDP port
- * @v s_PXENV_TFTP_OPEN::PacketSize TFTP blksize option to request
- * @ret #PXENV_EXIT_SUCCESS File was opened
- * @ret #PXENV_EXIT_FAILURE File was not opened
- * @ret s_PXENV_TFTP_OPEN::Status PXE status code
- * @ret s_PXENV_TFTP_OPEN::PacketSize Negotiated blksize
- * @err #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE Requested blksize too small
- *
- * Opens a TFTP connection for downloading a file a block at a time
- * using pxenv_tftp_read().
- *
- * If s_PXENV_TFTP_OPEN::GatewayIPAddress is 0.0.0.0, normal IP
- * routing will take place. See the relevant
- * @ref pxe_routing "implementation note" for more details.
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- *
- * @note According to the PXE specification version 2.1, this call
- * "opens a file for reading/writing", though how writing is to be
- * achieved without the existence of an API call %pxenv_tftp_write()
- * is not made clear.
- *
- * @note Despite the existence of the numerous statements within the
- * PXE specification of the form "...if a TFTP/MTFTP or UDP connection
- * is active...", you cannot use pxenv_tftp_open() and
- * pxenv_tftp_read() to read a file via MTFTP; only via plain old
- * TFTP. If you want to use MTFTP, use pxenv_tftp_read_file()
- * instead. Astute readers will note that, since
- * pxenv_tftp_read_file() is an atomic operation from the point of
- * view of the PXE API, it is conceptually impossible to issue any
- * other PXE API call "if an MTFTP connection is active".
- */
-static PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
- int rc;
-
- DBG ( "PXENV_TFTP_OPEN" );
-
- /* Guard against callers that fail to close before re-opening */
- pxe_tftp_close ( &pxe_tftp, 0 );
-
- /* Open connection */
- if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress,
- tftp_open->TFTPPort,
- tftp_open->FileName,
- tftp_open->PacketSize ) ) != 0 ) {
- tftp_open->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- /* Wait for OACK to arrive so that we have the block size */
- while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
- ( pxe_tftp.max_offset == 0 ) ) {
- step();
- }
- pxe_tftp.blksize = xfer_window ( &pxe_tftp.xfer );
- tftp_open->PacketSize = pxe_tftp.blksize;
- DBG ( " blksize=%d", tftp_open->PacketSize );
-
- /* EINPROGRESS is normal; we don't wait for the whole transfer */
- if ( rc == -EINPROGRESS )
- rc = 0;
-
- tftp_open->Status = PXENV_STATUS ( rc );
- return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
-}
-
-/**
- * TFTP CLOSE
- *
- * @v tftp_close Pointer to a struct s_PXENV_TFTP_CLOSE
- * @ret #PXENV_EXIT_SUCCESS File was closed successfully
- * @ret #PXENV_EXIT_FAILURE File was not closed
- * @ret s_PXENV_TFTP_CLOSE::Status PXE status code
- * @err None -
- *
- * Close a connection previously opened with pxenv_tftp_open(). You
- * must have previously opened a connection with pxenv_tftp_open().
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- */
-static PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) {
- DBG ( "PXENV_TFTP_CLOSE" );
-
- pxe_tftp_close ( &pxe_tftp, 0 );
- tftp_close->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * TFTP READ
- *
- * @v tftp_read Pointer to a struct s_PXENV_TFTP_READ
- * @v s_PXENV_TFTP_READ::Buffer Address of data buffer
- * @ret #PXENV_EXIT_SUCCESS Data was read successfully
- * @ret #PXENV_EXIT_FAILURE Data was not read
- * @ret s_PXENV_TFTP_READ::Status PXE status code
- * @ret s_PXENV_TFTP_READ::PacketNumber TFTP packet number
- * @ret s_PXENV_TFTP_READ::BufferSize Length of data written into buffer
- *
- * Reads a single packet from a connection previously opened with
- * pxenv_tftp_open() into the data buffer pointed to by
- * s_PXENV_TFTP_READ::Buffer. You must have previously opened a
- * connection with pxenv_tftp_open(). The data written into
- * s_PXENV_TFTP_READ::Buffer is just the file data; the various
- * network headers have already been removed.
- *
- * The buffer must be large enough to contain a packet of the size
- * negotiated via the s_PXENV_TFTP_OPEN::PacketSize field in the
- * pxenv_tftp_open() call. It is worth noting that the PXE
- * specification does @b not require the caller to fill in
- * s_PXENV_TFTP_READ::BufferSize before calling pxenv_tftp_read(), so
- * the PXE stack is free to ignore whatever value the caller might
- * place there and just assume that the buffer is large enough. That
- * said, it may be worth the caller always filling in
- * s_PXENV_TFTP_READ::BufferSize to guard against PXE stacks that
- * mistake it for an input parameter.
- *
- * The length of the TFTP data packet will be returned via
- * s_PXENV_TFTP_READ::BufferSize. If this length is less than the
- * blksize negotiated via s_PXENV_TFTP_OPEN::PacketSize in the call to
- * pxenv_tftp_open(), this indicates that the block is the last block
- * in the file. Note that zero is a valid length for
- * s_PXENV_TFTP_READ::BufferSize, and will occur when the length of
- * the file is a multiple of the blksize.
- *
- * The PXE specification doesn't actually state that calls to
- * pxenv_tftp_read() will return the data packets in strict sequential
- * order, though most PXE stacks will probably do so. The sequence
- * number of the packet will be returned in
- * s_PXENV_TFTP_READ::PacketNumber. The first packet in the file has
- * a sequence number of one, not zero.
- *
- * To guard against flawed PXE stacks, the caller should probably set
- * s_PXENV_TFTP_READ::PacketNumber to one less than the expected
- * returned value (i.e. set it to zero for the first call to
- * pxenv_tftp_read() and then re-use the returned s_PXENV_TFTP_READ
- * parameter block for subsequent calls without modifying
- * s_PXENV_TFTP_READ::PacketNumber between calls). The caller should
- * also guard against potential problems caused by flawed
- * implementations returning the occasional duplicate packet, by
- * checking that the value returned in s_PXENV_TFTP_READ::PacketNumber
- * is as expected (i.e. one greater than that returned from the
- * previous call to pxenv_tftp_read()).
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- */
-static PXENV_EXIT_t pxenv_tftp_read ( struct s_PXENV_TFTP_READ *tftp_read ) {
- int rc;
-
- DBG ( "PXENV_TFTP_READ to %04x:%04x",
- tftp_read->Buffer.segment, tftp_read->Buffer.offset );
-
- /* Read single block into buffer */
- pxe_tftp.buffer = real_to_user ( tftp_read->Buffer.segment,
- tftp_read->Buffer.offset );
- pxe_tftp.size = pxe_tftp.blksize;
- pxe_tftp.start = pxe_tftp.offset;
- while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
- ( pxe_tftp.offset == pxe_tftp.start ) )
- step();
- pxe_tftp.buffer = UNULL;
- tftp_read->BufferSize = ( pxe_tftp.offset - pxe_tftp.start );
- tftp_read->PacketNumber = ++pxe_tftp.blkidx;
-
- /* EINPROGRESS is normal if we haven't reached EOF yet */
- if ( rc == -EINPROGRESS )
- rc = 0;
-
- tftp_read->Status = PXENV_STATUS ( rc );
- return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
-}
-
-/**
- * TFTP/MTFTP read file
- *
- * @v tftp_read_file Pointer to a struct s_PXENV_TFTP_READ_FILE
- * @v s_PXENV_TFTP_READ_FILE::FileName File name
- * @v s_PXENV_TFTP_READ_FILE::BufferSize Size of the receive buffer
- * @v s_PXENV_TFTP_READ_FILE::Buffer Address of the receive buffer
- * @v s_PXENV_TFTP_READ_FILE::ServerIPAddress TFTP server IP address
- * @v s_PXENV_TFTP_READ_FILE::GatewayIPAddress Relay agent IP address
- * @v s_PXENV_TFTP_READ_FILE::McastIPAddress File's multicast IP address
- * @v s_PXENV_TFTP_READ_FILE::TFTPClntPort Client multicast UDP port
- * @v s_PXENV_TFTP_READ_FILE::TFTPSrvPort Server multicast UDP port
- * @v s_PXENV_TFTP_READ_FILE::TFTPOpenTimeOut Time to wait for first packet
- * @v s_PXENV_TFTP_READ_FILE::TFTPReopenDelay MTFTP inactivity timeout
- * @ret #PXENV_EXIT_SUCCESS File downloaded successfully
- * @ret #PXENV_EXIT_FAILURE File not downloaded
- * @ret s_PXENV_TFTP_READ_FILE::Status PXE status code
- * @ret s_PXENV_TFTP_READ_FILE::BufferSize Length of downloaded file
- *
- * Downloads an entire file via either TFTP or MTFTP into the buffer
- * pointed to by s_PXENV_TFTP_READ_FILE::Buffer.
- *
- * The PXE specification does not make it clear how the caller
- * requests that MTFTP be used rather than TFTP (or vice versa). One
- * reasonable guess is that setting
- * s_PXENV_TFTP_READ_FILE::McastIPAddress to 0.0.0.0 would cause TFTP
- * to be used instead of MTFTP, though it is conceivable that some PXE
- * stacks would interpret that as "use the DHCP-provided multicast IP
- * address" instead. Some PXE stacks will not implement MTFTP at all,
- * and will always use TFTP.
- *
- * It is not specified whether or not
- * s_PXENV_TFTP_READ_FILE::TFTPSrvPort will be used as the TFTP server
- * port for TFTP (rather than MTFTP) downloads. Callers should assume
- * that the only way to access a TFTP server on a non-standard port is
- * to use pxenv_tftp_open() and pxenv_tftp_read().
- *
- * If s_PXENV_TFTP_READ_FILE::GatewayIPAddress is 0.0.0.0, normal IP
- * routing will take place. See the relevant
- * @ref pxe_routing "implementation note" for more details.
- *
- * It is interesting to note that s_PXENV_TFTP_READ_FILE::Buffer is an
- * #ADDR32_t type, i.e. nominally a flat physical address. Some PXE
- * NBPs (e.g. NTLDR) are known to call pxenv_tftp_read_file() in real
- * mode with s_PXENV_TFTP_READ_FILE::Buffer set to an address above
- * 1MB. This means that PXE stacks must be prepared to write to areas
- * outside base memory. Exactly how this is to be achieved is not
- * specified, though using INT 15,87 is as close to a standard method
- * as any, and should probably be used. Switching to protected-mode
- * in order to access high memory will fail if pxenv_tftp_read_file()
- * is called in V86 mode; it is reasonably to expect that a V86
- * monitor would intercept the relatively well-defined INT 15,87 if it
- * wants the PXE stack to be able to write to high memory.
- *
- * Things get even more interesting if pxenv_tftp_read_file() is
- * called in protected mode, because there is then absolutely no way
- * for the PXE stack to write to an absolute physical address. You
- * can't even get around the problem by creating a special "access
- * everything" segment in the s_PXE data structure, because the
- * #SEGDESC_t descriptors are limited to 64kB in size.
- *
- * Previous versions of the PXE specification (e.g. WfM 1.1a) provide
- * a separate API call, %pxenv_tftp_read_file_pmode(), specifically to
- * work around this problem. The s_PXENV_TFTP_READ_FILE_PMODE
- * parameter block splits s_PXENV_TFTP_READ_FILE::Buffer into
- * s_PXENV_TFTP_READ_FILE_PMODE::BufferSelector and
- * s_PXENV_TFTP_READ_FILE_PMODE::BufferOffset, i.e. it provides a
- * protected-mode segment:offset address for the data buffer. This
- * API call is no longer present in version 2.1 of the PXE
- * specification.
- *
- * Etherboot makes the assumption that s_PXENV_TFTP_READ_FILE::Buffer
- * is an offset relative to the caller's data segment, when
- * pxenv_tftp_read_file() is called in protected mode.
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- */
-PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
- *tftp_read_file ) {
- int rc;
-
- DBG ( "PXENV_TFTP_READ_FILE to %08x+%x", tftp_read_file->Buffer,
- tftp_read_file->BufferSize );
-
- /* Open TFTP file */
- if ( ( rc = pxe_tftp_open ( tftp_read_file->ServerIPAddress, 0,
- tftp_read_file->FileName, 0 ) ) != 0 ) {
- tftp_read_file->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- /* Read entire file */
- pxe_tftp.buffer = phys_to_user ( tftp_read_file->Buffer );
- pxe_tftp.size = tftp_read_file->BufferSize;
- while ( ( rc = pxe_tftp.rc ) == -EINPROGRESS )
- step();
- pxe_tftp.buffer = UNULL;
- tftp_read_file->BufferSize = pxe_tftp.max_offset;
-
- /* Close TFTP file */
- pxe_tftp_close ( &pxe_tftp, rc );
-
- tftp_read_file->Status = PXENV_STATUS ( rc );
- return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
-}
-
-/**
- * TFTP GET FILE SIZE
- *
- * @v tftp_get_fsize Pointer to a struct s_PXENV_TFTP_GET_FSIZE
- * @v s_PXENV_TFTP_GET_FSIZE::ServerIPAddress TFTP server IP address
- * @v s_PXENV_TFTP_GET_FSIZE::GatewayIPAddress Relay agent IP address
- * @v s_PXENV_TFTP_GET_FSIZE::FileName File name
- * @ret #PXENV_EXIT_SUCCESS File size was determined successfully
- * @ret #PXENV_EXIT_FAILURE File size was not determined
- * @ret s_PXENV_TFTP_GET_FSIZE::Status PXE status code
- * @ret s_PXENV_TFTP_GET_FSIZE::FileSize File size
- *
- * Determine the size of a file on a TFTP server. This uses the
- * "tsize" TFTP option, and so will not work with a TFTP server that
- * does not support TFTP options, or that does not support the "tsize"
- * option.
- *
- * The PXE specification states that this API call will @b not open a
- * TFTP connection for subsequent use with pxenv_tftp_read(). (This
- * is somewhat daft, since the only way to obtain the file size via
- * the "tsize" option involves issuing a TFTP open request, but that's
- * life.)
- *
- * You cannot call pxenv_tftp_get_fsize() while a TFTP or UDP
- * connection is open.
- *
- * If s_PXENV_TFTP_GET_FSIZE::GatewayIPAddress is 0.0.0.0, normal IP
- * routing will take place. See the relevant
- * @ref pxe_routing "implementation note" for more details.
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- *
- * @note There is no way to specify the TFTP server port with this API
- * call. Though you can open a file using a non-standard TFTP server
- * port (via s_PXENV_TFTP_OPEN::TFTPPort or, potentially,
- * s_PXENV_TFTP_READ_FILE::TFTPSrvPort), you can only get the size of
- * a file from a TFTP server listening on the standard TFTP port.
- * "Consistency" is not a word in Intel's vocabulary.
- */
-static PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
- *tftp_get_fsize ) {
- int rc;
-
- DBG ( "PXENV_TFTP_GET_FSIZE" );
-
- /* Open TFTP file */
- if ( ( rc = pxe_tftp_open ( tftp_get_fsize->ServerIPAddress, 0,
- tftp_get_fsize->FileName, 0 ) ) != 0 ) {
- tftp_get_fsize->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- /* Wait for initial seek to arrive, and record size */
- while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
- ( pxe_tftp.max_offset == 0 ) ) {
- step();
- }
- tftp_get_fsize->FileSize = pxe_tftp.max_offset;
- DBG ( " fsize=%d", tftp_get_fsize->FileSize );
-
- /* EINPROGRESS is normal; we don't wait for the whole transfer */
- if ( rc == -EINPROGRESS )
- rc = 0;
-
- /* Close TFTP file */
- pxe_tftp_close ( &pxe_tftp, rc );
-
- tftp_get_fsize->Status = PXENV_STATUS ( rc );
- return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
-}
-
-/** PXE TFTP API */
-struct pxe_api_call pxe_tftp_api[] __pxe_api_call = {
- PXE_API_CALL ( PXENV_TFTP_OPEN, pxenv_tftp_open,
- struct s_PXENV_TFTP_OPEN ),
- PXE_API_CALL ( PXENV_TFTP_CLOSE, pxenv_tftp_close,
- struct s_PXENV_TFTP_CLOSE ),
- PXE_API_CALL ( PXENV_TFTP_READ, pxenv_tftp_read,
- struct s_PXENV_TFTP_READ ),
- PXE_API_CALL ( PXENV_TFTP_READ_FILE, pxenv_tftp_read_file,
- struct s_PXENV_TFTP_READ_FILE ),
- PXE_API_CALL ( PXENV_TFTP_GET_FSIZE, pxenv_tftp_get_fsize,
- struct s_PXENV_TFTP_GET_FSIZE ),
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c
deleted file mode 100644
index 071cb59db..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_udp.c
+++ /dev/null
@@ -1,474 +0,0 @@
-/** @file
- *
- * PXE UDP API
- *
- */
-
-#include <string.h>
-#include <byteswap.h>
-#include <ipxe/iobuf.h>
-#include <ipxe/xfer.h>
-#include <ipxe/udp.h>
-#include <ipxe/uaccess.h>
-#include <ipxe/process.h>
-#include <realmode.h>
-#include <pxe.h>
-
-/*
- * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** A PXE UDP pseudo-header */
-struct pxe_udp_pseudo_header {
- /** Source IP address */
- IP4_t src_ip;
- /** Source port */
- UDP_PORT_t s_port;
- /** Destination IP address */
- IP4_t dest_ip;
- /** Destination port */
- UDP_PORT_t d_port;
-} __attribute__ (( packed ));
-
-/** A PXE UDP connection */
-struct pxe_udp_connection {
- /** Data transfer interface to UDP stack */
- struct interface xfer;
- /** Local address */
- struct sockaddr_in local;
- /** List of received packets */
- struct list_head list;
-};
-
-/**
- * Receive PXE UDP data
- *
- * @v pxe_udp PXE UDP connection
- * @v iobuf I/O buffer
- * @v meta Data transfer metadata
- * @ret rc Return status code
- *
- * Receives a packet as part of the current pxenv_udp_read()
- * operation.
- */
-static int pxe_udp_deliver ( struct pxe_udp_connection *pxe_udp,
- struct io_buffer *iobuf,
- struct xfer_metadata *meta ) {
- struct pxe_udp_pseudo_header *pshdr;
- struct sockaddr_in *sin_src;
- struct sockaddr_in *sin_dest;
- int rc;
-
- /* Extract metadata */
- assert ( meta );
- sin_src = ( struct sockaddr_in * ) meta->src;
- assert ( sin_src );
- assert ( sin_src->sin_family == AF_INET );
- sin_dest = ( struct sockaddr_in * ) meta->dest;
- assert ( sin_dest );
- assert ( sin_dest->sin_family == AF_INET );
-
- /* Construct pseudo-header */
- if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *pshdr ) ) ) != 0 ) {
- DBG ( "PXE could not prepend pseudo-header\n" );
- rc = -ENOMEM;
- goto drop;
- }
- pshdr = iob_push ( iobuf, sizeof ( *pshdr ) );
- pshdr->src_ip = sin_src->sin_addr.s_addr;
- pshdr->s_port = sin_src->sin_port;
- pshdr->dest_ip = sin_dest->sin_addr.s_addr;
- pshdr->d_port = sin_dest->sin_port;
-
- /* Add to queue */
- list_add_tail ( &iobuf->list, &pxe_udp->list );
-
- return 0;
-
- drop:
- free_iob ( iobuf );
- return rc;
-}
-
-/** PXE UDP data transfer interface operations */
-static struct interface_operation pxe_udp_xfer_operations[] = {
- INTF_OP ( xfer_deliver, struct pxe_udp_connection *, pxe_udp_deliver ),
-};
-
-/** PXE UDP data transfer interface descriptor */
-static struct interface_descriptor pxe_udp_xfer_desc =
- INTF_DESC ( struct pxe_udp_connection, xfer, pxe_udp_xfer_operations );
-
-/** The PXE UDP connection */
-static struct pxe_udp_connection pxe_udp = {
- .xfer = INTF_INIT ( pxe_udp_xfer_desc ),
- .local = {
- .sin_family = AF_INET,
- },
- .list = LIST_HEAD_INIT ( pxe_udp.list ),
-};
-
-/**
- * UDP OPEN
- *
- * @v pxenv_udp_open Pointer to a struct s_PXENV_UDP_OPEN
- * @v s_PXENV_UDP_OPEN::src_ip IP address of this station, or 0.0.0.0
- * @ret #PXENV_EXIT_SUCCESS Always
- * @ret s_PXENV_UDP_OPEN::Status PXE status code
- * @err #PXENV_STATUS_UDP_OPEN UDP connection already open
- * @err #PXENV_STATUS_OUT_OF_RESOURCES Could not open connection
- *
- * Prepares the PXE stack for communication using pxenv_udp_write()
- * and pxenv_udp_read().
- *
- * The IP address supplied in s_PXENV_UDP_OPEN::src_ip will be
- * recorded and used as the local station's IP address for all further
- * communication, including communication by means other than
- * pxenv_udp_write() and pxenv_udp_read(). (If
- * s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the local station's IP address
- * will remain unchanged.)
- *
- * You can only have one open UDP connection at a time. This is not a
- * meaningful restriction, since pxenv_udp_write() and
- * pxenv_udp_read() allow you to specify arbitrary local and remote
- * ports and an arbitrary remote address for each packet. According
- * to the PXE specifiation, you cannot have a UDP connection open at
- * the same time as a TFTP connection; this restriction does not apply
- * to Etherboot.
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- *
- * @note The PXE specification does not make it clear whether the IP
- * address supplied in s_PXENV_UDP_OPEN::src_ip should be used only
- * for this UDP connection, or retained for all future communication.
- * The latter seems more consistent with typical PXE stack behaviour.
- *
- * @note Etherboot currently ignores the s_PXENV_UDP_OPEN::src_ip
- * parameter.
- *
- */
-static PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN *pxenv_udp_open ) {
- int rc;
-
- DBG ( "PXENV_UDP_OPEN" );
-
- /* Record source IP address */
- pxe_udp.local.sin_addr.s_addr = pxenv_udp_open->src_ip;
- DBG ( " %s\n", inet_ntoa ( pxe_udp.local.sin_addr ) );
-
- /* Open promiscuous UDP connection */
- intf_restart ( &pxe_udp.xfer, 0 );
- if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) {
- DBG ( "PXENV_UDP_OPEN could not open promiscuous socket: %s\n",
- strerror ( rc ) );
- pxenv_udp_open->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- pxenv_udp_open->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * UDP CLOSE
- *
- * @v pxenv_udp_close Pointer to a struct s_PXENV_UDP_CLOSE
- * @ret #PXENV_EXIT_SUCCESS Always
- * @ret s_PXENV_UDP_CLOSE::Status PXE status code
- * @err None -
- *
- * Closes a UDP connection opened with pxenv_udp_open().
- *
- * You can only have one open UDP connection at a time. You cannot
- * have a UDP connection open at the same time as a TFTP connection.
- * You cannot use pxenv_udp_close() to close a TFTP connection; use
- * pxenv_tftp_close() instead.
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- *
- */
-static PXENV_EXIT_t
-pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) {
- struct io_buffer *iobuf;
- struct io_buffer *tmp;
-
- DBG ( "PXENV_UDP_CLOSE\n" );
-
- /* Close UDP connection */
- intf_restart ( &pxe_udp.xfer, 0 );
-
- /* Discard any received packets */
- list_for_each_entry_safe ( iobuf, tmp, &pxe_udp.list, list ) {
- list_del ( &iobuf->list );
- free_iob ( iobuf );
- }
-
- pxenv_udp_close->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * UDP WRITE
- *
- * @v pxenv_udp_write Pointer to a struct s_PXENV_UDP_WRITE
- * @v s_PXENV_UDP_WRITE::ip Destination IP address
- * @v s_PXENV_UDP_WRITE::gw Relay agent IP address, or 0.0.0.0
- * @v s_PXENV_UDP_WRITE::src_port Source UDP port, or 0
- * @v s_PXENV_UDP_WRITE::dst_port Destination UDP port
- * @v s_PXENV_UDP_WRITE::buffer_size Length of the UDP payload
- * @v s_PXENV_UDP_WRITE::buffer Address of the UDP payload
- * @ret #PXENV_EXIT_SUCCESS Packet was transmitted successfully
- * @ret #PXENV_EXIT_FAILURE Packet could not be transmitted
- * @ret s_PXENV_UDP_WRITE::Status PXE status code
- * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open
- * @err #PXENV_STATUS_UNDI_TRANSMIT_ERROR Could not transmit packet
- *
- * Transmits a single UDP packet. A valid IP and UDP header will be
- * prepended to the payload in s_PXENV_UDP_WRITE::buffer; the buffer
- * should not contain precomputed IP and UDP headers, nor should it
- * contain space allocated for these headers. The first byte of the
- * buffer will be transmitted as the first byte following the UDP
- * header.
- *
- * If s_PXENV_UDP_WRITE::gw is 0.0.0.0, normal IP routing will take
- * place. See the relevant @ref pxe_routing "implementation note" for
- * more details.
- *
- * If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used.
- *
- * You must have opened a UDP connection with pxenv_udp_open() before
- * calling pxenv_udp_write().
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- *
- * @note Etherboot currently ignores the s_PXENV_UDP_WRITE::gw
- * parameter.
- *
- */
-static PXENV_EXIT_t
-pxenv_udp_write ( struct s_PXENV_UDP_WRITE *pxenv_udp_write ) {
- struct sockaddr_in dest;
- struct xfer_metadata meta = {
- .src = ( struct sockaddr * ) &pxe_udp.local,
- .dest = ( struct sockaddr * ) &dest,
- .netdev = pxe_netdev,
- };
- size_t len;
- struct io_buffer *iobuf;
- userptr_t buffer;
- int rc;
-
- DBG ( "PXENV_UDP_WRITE" );
-
- /* Construct destination socket address */
- memset ( &dest, 0, sizeof ( dest ) );
- dest.sin_family = AF_INET;
- dest.sin_addr.s_addr = pxenv_udp_write->ip;
- dest.sin_port = pxenv_udp_write->dst_port;
-
- /* Set local (source) port. PXE spec says source port is 2069
- * if not specified. Really, this ought to be set at UDP open
- * time but hey, we didn't design this API.
- */
- pxe_udp.local.sin_port = pxenv_udp_write->src_port;
- if ( ! pxe_udp.local.sin_port )
- pxe_udp.local.sin_port = htons ( 2069 );
-
- /* FIXME: we ignore the gateway specified, since we're
- * confident of being able to do our own routing. We should
- * probably allow for multiple gateways.
- */
-
- /* Allocate and fill data buffer */
- len = pxenv_udp_write->buffer_size;
- iobuf = xfer_alloc_iob ( &pxe_udp.xfer, len );
- if ( ! iobuf ) {
- DBG ( " out of memory\n" );
- pxenv_udp_write->Status = PXENV_STATUS_OUT_OF_RESOURCES;
- return PXENV_EXIT_FAILURE;
- }
- buffer = real_to_user ( pxenv_udp_write->buffer.segment,
- pxenv_udp_write->buffer.offset );
- copy_from_user ( iob_put ( iobuf, len ), buffer, 0, len );
-
- DBG ( " %04x:%04x+%x %d->%s:%d\n", pxenv_udp_write->buffer.segment,
- pxenv_udp_write->buffer.offset, pxenv_udp_write->buffer_size,
- ntohs ( pxenv_udp_write->src_port ),
- inet_ntoa ( dest.sin_addr ),
- ntohs ( pxenv_udp_write->dst_port ) );
-
- /* Transmit packet */
- if ( ( rc = xfer_deliver ( &pxe_udp.xfer, iobuf, &meta ) ) != 0 ) {
- DBG ( "PXENV_UDP_WRITE could not transmit: %s\n",
- strerror ( rc ) );
- pxenv_udp_write->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- pxenv_udp_write->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/**
- * UDP READ
- *
- * @v pxenv_udp_read Pointer to a struct s_PXENV_UDP_READ
- * @v s_PXENV_UDP_READ::dest_ip Destination IP address, or 0.0.0.0
- * @v s_PXENV_UDP_READ::d_port Destination UDP port, or 0
- * @v s_PXENV_UDP_READ::buffer_size Size of the UDP payload buffer
- * @v s_PXENV_UDP_READ::buffer Address of the UDP payload buffer
- * @ret #PXENV_EXIT_SUCCESS A packet has been received
- * @ret #PXENV_EXIT_FAILURE No packet has been received
- * @ret s_PXENV_UDP_READ::Status PXE status code
- * @ret s_PXENV_UDP_READ::src_ip Source IP address
- * @ret s_PXENV_UDP_READ::dest_ip Destination IP address
- * @ret s_PXENV_UDP_READ::s_port Source UDP port
- * @ret s_PXENV_UDP_READ::d_port Destination UDP port
- * @ret s_PXENV_UDP_READ::buffer_size Length of UDP payload
- * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open
- * @err #PXENV_STATUS_FAILURE No packet was ready to read
- *
- * Receive a single UDP packet. This is a non-blocking call; if no
- * packet is ready to read, the call will return instantly with
- * s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE.
- *
- * If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to
- * any IP address will be accepted and may be returned to the caller.
- *
- * If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP
- * port will be accepted and may be returned to the caller.
- *
- * You must have opened a UDP connection with pxenv_udp_open() before
- * calling pxenv_udp_read().
- *
- * On x86, you must set the s_PXE::StatusCallout field to a nonzero
- * value before calling this function in protected mode. You cannot
- * call this function with a 32-bit stack segment. (See the relevant
- * @ref pxe_x86_pmode16 "implementation note" for more details.)
- *
- * @note The PXE specification (version 2.1) does not state that we
- * should fill in s_PXENV_UDP_READ::dest_ip and
- * s_PXENV_UDP_READ::d_port, but Microsoft Windows' NTLDR program
- * expects us to do so, and will fail if we don't.
- *
- */
-static PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ *pxenv_udp_read ) {
- struct in_addr dest_ip_wanted = { .s_addr = pxenv_udp_read->dest_ip };
- struct in_addr dest_ip;
- struct io_buffer *iobuf;
- struct pxe_udp_pseudo_header *pshdr;
- uint16_t d_port_wanted = pxenv_udp_read->d_port;
- uint16_t d_port;
- userptr_t buffer;
- size_t len;
-
- /* Try receiving a packet, if the queue is empty */
- if ( list_empty ( &pxe_udp.list ) )
- step();
-
- /* Remove first packet from the queue */
- iobuf = list_first_entry ( &pxe_udp.list, struct io_buffer, list );
- if ( ! iobuf ) {
- /* No packet received */
- DBG2 ( "PXENV_UDP_READ\n" );
- goto no_packet;
- }
- list_del ( &iobuf->list );
-
- /* Strip pseudo-header */
- assert ( iob_len ( iobuf ) >= sizeof ( *pshdr ) );
- pshdr = iobuf->data;
- iob_pull ( iobuf, sizeof ( *pshdr ) );
- dest_ip.s_addr = pshdr->dest_ip;
- d_port = pshdr->d_port;
- DBG ( "PXENV_UDP_READ" );
-
- /* Filter on destination address and/or port */
- if ( dest_ip_wanted.s_addr &&
- ( dest_ip_wanted.s_addr != dest_ip.s_addr ) ) {
- DBG ( " wrong IP %s", inet_ntoa ( dest_ip ) );
- DBG ( " (wanted %s)\n", inet_ntoa ( dest_ip_wanted ) );
- goto drop;
- }
- if ( d_port_wanted && ( d_port_wanted != d_port ) ) {
- DBG ( " wrong port %d", htons ( d_port ) );
- DBG ( " (wanted %d)\n", htons ( d_port_wanted ) );
- goto drop;
- }
-
- /* Copy packet to buffer and record length */
- buffer = real_to_user ( pxenv_udp_read->buffer.segment,
- pxenv_udp_read->buffer.offset );
- len = iob_len ( iobuf );
- if ( len > pxenv_udp_read->buffer_size )
- len = pxenv_udp_read->buffer_size;
- copy_to_user ( buffer, 0, iobuf->data, len );
- pxenv_udp_read->buffer_size = len;
-
- /* Fill in source/dest information */
- pxenv_udp_read->src_ip = pshdr->src_ip;
- pxenv_udp_read->s_port = pshdr->s_port;
- pxenv_udp_read->dest_ip = pshdr->dest_ip;
- pxenv_udp_read->d_port = pshdr->d_port;
-
- DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment,
- pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size,
- inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->src_ip ) ));
- DBG ( "%d<-%s:%d\n", ntohs ( pxenv_udp_read->s_port ),
- inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ),
- ntohs ( pxenv_udp_read->d_port ) );
-
- /* Free I/O buffer */
- free_iob ( iobuf );
-
- pxenv_udp_read->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-
- drop:
- free_iob ( iobuf );
- no_packet:
- pxenv_udp_read->Status = PXENV_STATUS_FAILURE;
- return PXENV_EXIT_FAILURE;
-}
-
-/** PXE UDP API */
-struct pxe_api_call pxe_udp_api[] __pxe_api_call = {
- PXE_API_CALL ( PXENV_UDP_OPEN, pxenv_udp_open,
- struct s_PXENV_UDP_OPEN ),
- PXE_API_CALL ( PXENV_UDP_CLOSE, pxenv_udp_close,
- struct s_PXENV_UDP_CLOSE ),
- PXE_API_CALL ( PXENV_UDP_WRITE, pxenv_udp_write,
- struct s_PXENV_UDP_WRITE ),
- PXE_API_CALL ( PXENV_UDP_READ, pxenv_udp_read,
- struct s_PXENV_UDP_READ ),
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c b/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c
deleted file mode 100644
index 2eb68178a..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxe/pxe_undi.c
+++ /dev/null
@@ -1,1084 +0,0 @@
-/** @file
- *
- * PXE UNDI API
- *
- */
-
-/*
- * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <byteswap.h>
-#include <basemem_packet.h>
-#include <ipxe/netdevice.h>
-#include <ipxe/iobuf.h>
-#include <ipxe/device.h>
-#include <ipxe/pci.h>
-#include <ipxe/if_ether.h>
-#include <ipxe/ip.h>
-#include <ipxe/arp.h>
-#include <ipxe/rarp.h>
-#include <ipxe/profile.h>
-#include "pxe.h"
-
-/**
- * Count of outstanding transmitted packets
- *
- * This is incremented each time PXENV_UNDI_TRANSMIT is called, and
- * decremented each time that PXENV_UNDI_ISR is called with the TX
- * queue empty, stopping when the count reaches zero. This allows us
- * to provide a pessimistic approximation of TX completion events to
- * the PXE NBP simply by monitoring the netdev's TX queue.
- */
-static int undi_tx_count = 0;
-
-struct net_device *pxe_netdev = NULL;
-
-/** Transmit profiler */
-static struct profiler undi_tx_profiler __profiler = { .name = "undi.tx" };
-
-/**
- * Set network device as current PXE network device
- *
- * @v netdev Network device, or NULL
- */
-void pxe_set_netdev ( struct net_device *netdev ) {
-
- if ( pxe_netdev ) {
- netdev_rx_unfreeze ( pxe_netdev );
- netdev_put ( pxe_netdev );
- }
-
- pxe_netdev = NULL;
-
- if ( netdev )
- pxe_netdev = netdev_get ( netdev );
-}
-
-/**
- * Open PXE network device
- *
- * @ret rc Return status code
- */
-static int pxe_netdev_open ( void ) {
- int rc;
-
- assert ( pxe_netdev != NULL );
-
- if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 )
- return rc;
-
- netdev_rx_freeze ( pxe_netdev );
- netdev_irq ( pxe_netdev, 1 );
-
- return 0;
-}
-
-/**
- * Close PXE network device
- *
- */
-static void pxe_netdev_close ( void ) {
-
- assert ( pxe_netdev != NULL );
- netdev_rx_unfreeze ( pxe_netdev );
- netdev_irq ( pxe_netdev, 0 );
- netdev_close ( pxe_netdev );
- undi_tx_count = 0;
-}
-
-/**
- * Dump multicast address list
- *
- * @v mcast PXE multicast address list
- */
-static void pxe_dump_mcast_list ( struct s_PXENV_UNDI_MCAST_ADDRESS *mcast ) {
- struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
- unsigned int i;
-
- for ( i = 0 ; i < mcast->MCastAddrCount ; i++ ) {
- DBGC ( &pxe_netdev, " %s",
- ll_protocol->ntoa ( mcast->McastAddr[i] ) );
- }
-}
-
-/* PXENV_UNDI_STARTUP
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_STARTUP called with no "
- "network device\n" );
- undi_startup->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- undi_startup->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_CLEANUP
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_CLEANUP called with no "
- "network device\n" );
- undi_cleanup->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Close network device */
- pxe_netdev_close();
-
- undi_cleanup->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_INITIALIZE
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE *undi_initialize ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE protocolini %08x\n",
- undi_initialize->ProtocolIni );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_INITIALIZE called with no "
- "network device\n" );
- undi_initialize->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- undi_initialize->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_RESET_ADAPTER
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET *undi_reset_adapter ) {
- int rc;
-
- DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER" );
- pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf );
- DBGC ( &pxe_netdev, "\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER called with no "
- "network device\n" );
- undi_reset_adapter->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Close and reopen network device */
- pxe_netdev_close();
- if ( ( rc = pxe_netdev_open() ) != 0 ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_RESET_ADAPTER could not "
- "reopen %s: %s\n", pxe_netdev->name, strerror ( rc ) );
- undi_reset_adapter->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- undi_reset_adapter->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_SHUTDOWN
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN *undi_shutdown ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_SHUTDOWN called with no "
- "network device\n" );
- undi_shutdown->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Close network device */
- pxe_netdev_close();
-
- undi_shutdown->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_OPEN
- *
- * Status: working
- */
-static PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
- int rc;
-
- DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN flag %04x filter %04x",
- undi_open->OpenFlag, undi_open->PktFilter );
- pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf );
- DBGC ( &pxe_netdev, "\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN called with no "
- "network device\n" );
- undi_open->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Open network device */
- if ( ( rc = pxe_netdev_open() ) != 0 ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_OPEN could not open %s: %s\n",
- pxe_netdev->name, strerror ( rc ) );
- undi_open->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- undi_open->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_CLOSE
- *
- * Status: working
- */
-static PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_CLOSE called with no "
- "network device\n" );
- undi_close->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Close network device */
- pxe_netdev_close();
-
- undi_close->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_TRANSMIT
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_transmit ( struct s_PXENV_UNDI_TRANSMIT *undi_transmit ) {
- struct s_PXENV_UNDI_TBD tbd;
- struct DataBlk *datablk;
- struct io_buffer *iobuf;
- struct net_protocol *net_protocol;
- struct ll_protocol *ll_protocol;
- char destaddr[MAX_LL_ADDR_LEN];
- const void *ll_dest;
- size_t len;
- unsigned int i;
- int rc;
-
- /* Start profiling */
- profile_start ( &undi_tx_profiler );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_TRANSMIT called with no "
- "network device\n" );
- undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT" );
-
- /* Forcibly enable interrupts and freeze receive queue
- * processing at this point, to work around callers that never
- * call PXENV_UNDI_OPEN before attempting to use the UNDI API.
- */
- if ( ! netdev_rx_frozen ( pxe_netdev ) ) {
- netdev_rx_freeze ( pxe_netdev );
- netdev_irq ( pxe_netdev, 1 );
- }
-
- /* Identify network-layer protocol */
- switch ( undi_transmit->Protocol ) {
- case P_IP: net_protocol = &ipv4_protocol; break;
- case P_ARP: net_protocol = &arp_protocol; break;
- case P_RARP: net_protocol = &rarp_protocol; break;
- case P_UNKNOWN:
- net_protocol = NULL;
- break;
- default:
- DBGC2 ( &pxe_netdev, " %02x invalid protocol\n",
- undi_transmit->Protocol );
- undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
- return PXENV_EXIT_FAILURE;
- }
- DBGC2 ( &pxe_netdev, " %s",
- ( net_protocol ? net_protocol->name : "RAW" ) );
-
- /* Calculate total packet length */
- copy_from_real ( &tbd, undi_transmit->TBD.segment,
- undi_transmit->TBD.offset, sizeof ( tbd ) );
- len = tbd.ImmedLength;
- DBGC2 ( &pxe_netdev, " %04x:%04x+%x", tbd.Xmit.segment, tbd.Xmit.offset,
- tbd.ImmedLength );
- for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
- datablk = &tbd.DataBlock[i];
- len += datablk->TDDataLen;
- DBGC2 ( &pxe_netdev, " %04x:%04x+%x",
- datablk->TDDataPtr.segment, datablk->TDDataPtr.offset,
- datablk->TDDataLen );
- }
-
- /* Allocate and fill I/O buffer */
- iobuf = alloc_iob ( MAX_LL_HEADER_LEN +
- ( ( len > IOB_ZLEN ) ? len : IOB_ZLEN ) );
- if ( ! iobuf ) {
- DBGC2 ( &pxe_netdev, " could not allocate iobuf\n" );
- undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
- return PXENV_EXIT_FAILURE;
- }
- iob_reserve ( iobuf, MAX_LL_HEADER_LEN );
- copy_from_real ( iob_put ( iobuf, tbd.ImmedLength ), tbd.Xmit.segment,
- tbd.Xmit.offset, tbd.ImmedLength );
- for ( i = 0 ; i < tbd.DataBlkCount ; i++ ) {
- datablk = &tbd.DataBlock[i];
- copy_from_real ( iob_put ( iobuf, datablk->TDDataLen ),
- datablk->TDDataPtr.segment,
- datablk->TDDataPtr.offset,
- datablk->TDDataLen );
- }
-
- /* Add link-layer header, if required to do so */
- if ( net_protocol != NULL ) {
-
- /* Calculate destination address */
- ll_protocol = pxe_netdev->ll_protocol;
- if ( undi_transmit->XmitFlag == XMT_DESTADDR ) {
- copy_from_real ( destaddr,
- undi_transmit->DestAddr.segment,
- undi_transmit->DestAddr.offset,
- ll_protocol->ll_addr_len );
- ll_dest = destaddr;
- DBGC2 ( &pxe_netdev, " DEST %s",
- ll_protocol->ntoa ( ll_dest ) );
- } else {
- ll_dest = pxe_netdev->ll_broadcast;
- DBGC2 ( &pxe_netdev, " BCAST" );
- }
-
- /* Add link-layer header */
- if ( ( rc = ll_protocol->push ( pxe_netdev, iobuf, ll_dest,
- pxe_netdev->ll_addr,
- net_protocol->net_proto ))!=0){
- DBGC2 ( &pxe_netdev, " could not add link-layer "
- "header: %s\n", strerror ( rc ) );
- free_iob ( iobuf );
- undi_transmit->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
- }
-
- /* Flag transmission as in-progress. Do this before starting
- * to transmit the packet, because the ISR may trigger before
- * we return from netdev_tx().
- */
- undi_tx_count++;
-
- /* Transmit packet */
- DBGC2 ( &pxe_netdev, "\n" );
- if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) {
- DBGC2 ( &pxe_netdev, "PXENV_UNDI_TRANSMIT could not transmit: "
- "%s\n", strerror ( rc ) );
- undi_tx_count--;
- undi_transmit->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- profile_stop ( &undi_tx_profiler );
- undi_transmit->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_SET_MCAST_ADDRESS
- *
- * Status: working (for NICs that support receive-all-multicast)
- */
-static PXENV_EXIT_t
-pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS
- *undi_set_mcast_address ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS" );
- pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf );
- DBGC ( &pxe_netdev, "\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_SET_MCAST_ADDRESS called with "
- "no network device\n" );
- undi_set_mcast_address->Status =
- PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_SET_STATION_ADDRESS
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
- *undi_set_station_address ) {
- struct ll_protocol *ll_protocol;
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS called "
- "with no network device\n" );
- undi_set_station_address->Status =
- PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- ll_protocol = pxe_netdev->ll_protocol;
- DBGC ( &pxe_netdev, "PXENV_UNDI_SET_STATION_ADDRESS %s",
- ll_protocol->ntoa ( undi_set_station_address->StationAddress ) );
-
- /* If adapter is open, the change will have no effect; return
- * an error
- */
- if ( netdev_is_open ( pxe_netdev ) ) {
- DBGC ( &pxe_netdev, " failed: netdev is open\n" );
- undi_set_station_address->Status =
- PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Update MAC address */
- memcpy ( pxe_netdev->ll_addr,
- &undi_set_station_address->StationAddress,
- ll_protocol->ll_addr_len );
-
- DBGC ( &pxe_netdev, "\n" );
- undi_set_station_address->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_SET_PACKET_FILTER
- *
- * Status: won't implement (would require driver API changes for no
- * real benefit)
- */
-static PXENV_EXIT_t
-pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER
- *undi_set_packet_filter ) {
-
- DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER %02x\n",
- undi_set_packet_filter->filter );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_SET_PACKET_FILTER called with "
- "no network device\n" );
- undi_set_packet_filter->Status =
- PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Pretend that we succeeded, otherwise the 3Com DOS UNDI
- * driver refuses to load. (We ignore the filter value in the
- * PXENV_UNDI_OPEN call anyway.)
- */
- undi_set_packet_filter->Status = PXENV_STATUS_SUCCESS;
-
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_GET_INFORMATION
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
- *undi_get_information ) {
- struct device *dev;
- struct ll_protocol *ll_protocol;
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION called with no "
- "network device\n" );
- undi_get_information->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_INFORMATION" );
-
- /* Fill in information */
- dev = pxe_netdev->dev;
- ll_protocol = pxe_netdev->ll_protocol;
- undi_get_information->BaseIo = dev->desc.ioaddr;
- undi_get_information->IntNumber =
- ( netdev_irq_supported ( pxe_netdev ) ? dev->desc.irq : 0 );
- /* Cheat: assume all cards can cope with this */
- undi_get_information->MaxTranUnit = ETH_MAX_MTU;
- undi_get_information->HwType = ntohs ( ll_protocol->ll_proto );
- undi_get_information->HwAddrLen = ll_protocol->ll_addr_len;
- assert ( ll_protocol->ll_addr_len <=
- sizeof ( undi_get_information->CurrentNodeAddress ) );
- memcpy ( &undi_get_information->CurrentNodeAddress,
- pxe_netdev->ll_addr,
- sizeof ( undi_get_information->CurrentNodeAddress ) );
- ll_protocol->init_addr ( pxe_netdev->hw_addr,
- &undi_get_information->PermNodeAddress );
- undi_get_information->ROMAddress = 0;
- /* nic.rom_info->rom_segment; */
- /* We only provide the ability to receive or transmit a single
- * packet at a time. This is a bootloader, not an OS.
- */
- undi_get_information->RxBufCt = 1;
- undi_get_information->TxBufCt = 1;
-
- DBGC ( &pxe_netdev, " io %04x irq %d mtu %d %s %s\n",
- undi_get_information->BaseIo, undi_get_information->IntNumber,
- undi_get_information->MaxTranUnit, ll_protocol->name,
- ll_protocol->ntoa ( &undi_get_information->CurrentNodeAddress ));
- undi_get_information->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_GET_STATISTICS
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS
- *undi_get_statistics ) {
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS called with no "
- "network device\n" );
- undi_get_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_STATISTICS" );
-
- /* Report statistics */
- undi_get_statistics->XmtGoodFrames = pxe_netdev->tx_stats.good;
- undi_get_statistics->RcvGoodFrames = pxe_netdev->rx_stats.good;
- undi_get_statistics->RcvCRCErrors = pxe_netdev->rx_stats.bad;
- undi_get_statistics->RcvResourceErrors = pxe_netdev->rx_stats.bad;
- DBGC ( &pxe_netdev, " txok %d rxok %d rxcrc %d rxrsrc %d\n",
- undi_get_statistics->XmtGoodFrames,
- undi_get_statistics->RcvGoodFrames,
- undi_get_statistics->RcvCRCErrors,
- undi_get_statistics->RcvResourceErrors );
-
- undi_get_statistics->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_CLEAR_STATISTICS
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS
- *undi_clear_statistics ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_CLEAR_STATISTICS called with "
- "no network device\n" );
- undi_clear_statistics->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- /* Clear statistics */
- memset ( &pxe_netdev->tx_stats, 0, sizeof ( pxe_netdev->tx_stats ) );
- memset ( &pxe_netdev->rx_stats, 0, sizeof ( pxe_netdev->rx_stats ) );
-
- undi_clear_statistics->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_INITIATE_DIAGS
- *
- * Status: won't implement (would require driver API changes for no
- * real benefit)
- */
-static PXENV_EXIT_t
-pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS
- *undi_initiate_diags ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_INITIATE_DIAGS called with no "
- "network device\n" );
- undi_initiate_diags->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- undi_initiate_diags->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
-}
-
-/* PXENV_UNDI_FORCE_INTERRUPT
- *
- * Status: won't implement (would require driver API changes for no
- * perceptible benefit)
- */
-static PXENV_EXIT_t
-pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT
- *undi_force_interrupt ) {
- DBGC ( &pxe_netdev,
- "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" );
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_FORCE_INTERRUPT called with no "
- "network device\n" );
- undi_force_interrupt->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
-}
-
-/* PXENV_UNDI_GET_MCAST_ADDRESS
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS
- *undi_get_mcast_address ) {
- struct ll_protocol *ll_protocol;
- struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr };
- int rc;
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS called with "
- "no network device\n" );
- undi_get_mcast_address->Status =
- PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_MCAST_ADDRESS %s",
- inet_ntoa ( ip ) );
-
- /* Hash address using the network device's link-layer protocol */
- ll_protocol = pxe_netdev->ll_protocol;
- if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip,
- undi_get_mcast_address->MediaAddr ))!=0){
- DBGC ( &pxe_netdev, " failed: %s\n", strerror ( rc ) );
- undi_get_mcast_address->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
- DBGC ( &pxe_netdev, "=>%s\n",
- ll_protocol->ntoa ( undi_get_mcast_address->MediaAddr ) );
-
- undi_get_mcast_address->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_GET_NIC_TYPE
- *
- * Status: working
- */
-static PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
- *undi_get_nic_type ) {
- struct device *dev;
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE called with "
- "no network device\n" );
- undi_get_nic_type->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_NIC_TYPE" );
-
- /* Fill in information */
- memset ( &undi_get_nic_type->info, 0,
- sizeof ( undi_get_nic_type->info ) );
- dev = pxe_netdev->dev;
- switch ( dev->desc.bus_type ) {
- case BUS_TYPE_PCI: {
- struct pci_nic_info *info = &undi_get_nic_type->info.pci;
-
- undi_get_nic_type->NicType = PCI_NIC;
- info->Vendor_ID = dev->desc.vendor;
- info->Dev_ID = dev->desc.device;
- info->Base_Class = PCI_BASE_CLASS ( dev->desc.class );
- info->Sub_Class = PCI_SUB_CLASS ( dev->desc.class );
- info->Prog_Intf = PCI_PROG_INTF ( dev->desc.class );
- info->BusDevFunc = dev->desc.location;
- /* Earlier versions of the PXE specification do not
- * have the SubVendor_ID and SubDevice_ID fields. It
- * is possible that some NBPs will not provide space
- * for them, and so we must not fill them in.
- */
- DBGC ( &pxe_netdev, " PCI %02x:%02x.%x %04x:%04x "
- "('%04x:%04x') %02x%02x%02x rev %02x\n",
- PCI_BUS ( info->BusDevFunc ),
- PCI_SLOT ( info->BusDevFunc ),
- PCI_FUNC ( info->BusDevFunc ), info->Vendor_ID,
- info->Dev_ID, info->SubVendor_ID, info->SubDevice_ID,
- info->Base_Class, info->Sub_Class, info->Prog_Intf,
- info->Rev );
- break; }
- case BUS_TYPE_ISAPNP: {
- struct pnp_nic_info *info = &undi_get_nic_type->info.pnp;
-
- undi_get_nic_type->NicType = PnP_NIC;
- info->EISA_Dev_ID = ( ( dev->desc.vendor << 16 ) |
- dev->desc.device );
- info->CardSelNum = dev->desc.location;
- /* Cheat: remaining fields are probably unnecessary,
- * and would require adding extra code to isapnp.c.
- */
- DBGC ( &pxe_netdev, " ISAPnP CSN %04x %08x %02x%02x%02x\n",
- info->CardSelNum, info->EISA_Dev_ID,
- info->Base_Class, info->Sub_Class, info->Prog_Intf );
- break; }
- default:
- DBGC ( &pxe_netdev, " failed: unknown bus type\n" );
- undi_get_nic_type->Status = PXENV_STATUS_FAILURE;
- return PXENV_EXIT_FAILURE;
- }
-
- undi_get_nic_type->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_GET_IFACE_INFO
- *
- * Status: working
- */
-static PXENV_EXIT_t
-pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO
- *undi_get_iface_info ) {
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO called with "
- "no network device\n" );
- undi_get_iface_info->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- DBGC ( &pxe_netdev, "PXENV_UNDI_GET_IFACE_INFO" );
-
- /* Just hand back some info, doesn't really matter what it is.
- * Most PXE stacks seem to take this approach.
- */
- snprintf ( ( char * ) undi_get_iface_info->IfaceType,
- sizeof ( undi_get_iface_info->IfaceType ), "DIX+802.3" );
- undi_get_iface_info->LinkSpeed = 10000000; /* 10 Mbps */
- undi_get_iface_info->ServiceFlags =
- ( SUPPORTED_BROADCAST | SUPPORTED_MULTICAST |
- SUPPORTED_SET_STATION_ADDRESS | SUPPORTED_RESET |
- SUPPORTED_OPEN_CLOSE );
- if ( netdev_irq_supported ( pxe_netdev ) )
- undi_get_iface_info->ServiceFlags |= SUPPORTED_IRQ;
- memset ( undi_get_iface_info->Reserved, 0,
- sizeof(undi_get_iface_info->Reserved) );
-
- DBGC ( &pxe_netdev, " %s %dbps flags %08x\n",
- undi_get_iface_info->IfaceType, undi_get_iface_info->LinkSpeed,
- undi_get_iface_info->ServiceFlags );
- undi_get_iface_info->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_GET_STATE
- *
- * Status: impossible due to opcode collision
- */
-
-/* PXENV_UNDI_ISR
- *
- * Status: working
- */
-static PXENV_EXIT_t pxenv_undi_isr ( struct s_PXENV_UNDI_ISR *undi_isr ) {
- struct io_buffer *iobuf;
- size_t len;
- struct ll_protocol *ll_protocol;
- const void *ll_dest;
- const void *ll_source;
- uint16_t net_proto;
- unsigned int flags;
- size_t ll_hlen;
- struct net_protocol *net_protocol;
- unsigned int prottype;
- int rc;
-
- /* Use a different debug colour, since UNDI ISR messages are
- * likely to be interspersed amongst other UNDI messages.
- */
-
- /* Sanity check */
- if ( ! pxe_netdev ) {
- DBGC ( &pxenv_undi_isr, "PXENV_UNDI_ISR called with "
- "no network device\n" );
- undi_isr->Status = PXENV_STATUS_UNDI_INVALID_STATE;
- return PXENV_EXIT_FAILURE;
- }
-
- DBGC2 ( &pxenv_undi_isr, "PXENV_UNDI_ISR" );
-
- /* Just in case some idiot actually looks at these fields when
- * we weren't meant to fill them in...
- */
- undi_isr->BufferLength = 0;
- undi_isr->FrameLength = 0;
- undi_isr->FrameHeaderLength = 0;
- undi_isr->ProtType = 0;
- undi_isr->PktType = 0;
-
- switch ( undi_isr->FuncFlag ) {
- case PXENV_UNDI_ISR_IN_START :
- DBGC2 ( &pxenv_undi_isr, " START" );
-
- /* Call poll(). This should acknowledge the device
- * interrupt and queue up any received packet.
- */
- net_poll();
-
- /* A 100% accurate determination of "OURS" vs "NOT
- * OURS" is difficult to achieve without invasive and
- * unpleasant changes to the driver model. We settle
- * for always returning "OURS" if interrupts are
- * currently enabled.
- *
- * Returning "NOT OURS" when interrupts are disabled
- * allows us to avoid a potential interrupt storm when
- * we are on a shared interrupt line; if we were to
- * always return "OURS" then the other device's ISR
- * may never be called.
- */
- if ( netdev_irq_enabled ( pxe_netdev ) ) {
- DBGC2 ( &pxenv_undi_isr, " OURS" );
- undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
- } else {
- DBGC2 ( &pxenv_undi_isr, " NOT OURS" );
- undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_NOT_OURS;
- }
-
- /* Disable interrupts */
- netdev_irq ( pxe_netdev, 0 );
-
- break;
- case PXENV_UNDI_ISR_IN_PROCESS :
- case PXENV_UNDI_ISR_IN_GET_NEXT :
- DBGC2 ( &pxenv_undi_isr, " %s",
- ( ( undi_isr->FuncFlag == PXENV_UNDI_ISR_IN_PROCESS ) ?
- "PROCESS" : "GET_NEXT" ) );
-
- /* Some dumb NBPs (e.g. emBoot's winBoot/i) never call
- * PXENV_UNDI_ISR with FuncFlag=PXENV_UNDI_ISR_START;
- * they just sit in a tight polling loop merrily
- * violating the PXE spec with repeated calls to
- * PXENV_UNDI_ISR_IN_PROCESS. Force extra polls to
- * cope with these out-of-spec clients.
- */
- net_poll();
-
- /* If we have not yet marked a TX as complete, and the
- * netdev TX queue is empty, report the TX completion.
- */
- if ( undi_tx_count && list_empty ( &pxe_netdev->tx_queue ) ) {
- DBGC2 ( &pxenv_undi_isr, " TXC" );
- undi_tx_count--;
- undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_TRANSMIT;
- break;
- }
-
- /* Remove first packet from netdev RX queue */
- iobuf = netdev_rx_dequeue ( pxe_netdev );
- if ( ! iobuf ) {
- DBGC2 ( &pxenv_undi_isr, " DONE" );
- /* No more packets remaining */
- undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
- /* Re-enable interrupts */
- netdev_irq ( pxe_netdev, 1 );
- break;
- }
-
- /* Copy packet to base memory buffer */
- len = iob_len ( iobuf );
- DBGC2 ( &pxenv_undi_isr, " RX" );
- if ( len > sizeof ( basemem_packet ) ) {
- /* Should never happen */
- DBGC2 ( &pxenv_undi_isr, " overlength (%zx)", len );
- len = sizeof ( basemem_packet );
- }
- memcpy ( basemem_packet, iobuf->data, len );
-
- /* Strip link-layer header */
- ll_protocol = pxe_netdev->ll_protocol;
- if ( ( rc = ll_protocol->pull ( pxe_netdev, iobuf, &ll_dest,
- &ll_source, &net_proto,
- &flags ) ) != 0 ) {
- /* Assume unknown net_proto and no ll_source */
- net_proto = 0;
- ll_source = NULL;
- }
- ll_hlen = ( len - iob_len ( iobuf ) );
-
- /* Determine network-layer protocol */
- switch ( net_proto ) {
- case htons ( ETH_P_IP ):
- net_protocol = &ipv4_protocol;
- prottype = P_IP;
- break;
- case htons ( ETH_P_ARP ):
- net_protocol = &arp_protocol;
- prottype = P_ARP;
- break;
- case htons ( ETH_P_RARP ):
- net_protocol = &rarp_protocol;
- prottype = P_RARP;
- break;
- default:
- net_protocol = NULL;
- prottype = P_UNKNOWN;
- break;
- }
-
- /* Fill in UNDI_ISR structure */
- undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_RECEIVE;
- undi_isr->BufferLength = len;
- undi_isr->FrameLength = len;
- undi_isr->FrameHeaderLength = ll_hlen;
- undi_isr->Frame.segment = rm_ds;
- undi_isr->Frame.offset = __from_data16 ( basemem_packet );
- undi_isr->ProtType = prottype;
- if ( flags & LL_BROADCAST ) {
- undi_isr->PktType = P_BROADCAST;
- } else if ( flags & LL_MULTICAST ) {
- undi_isr->PktType = P_MULTICAST;
- } else {
- undi_isr->PktType = P_DIRECTED;
- }
- DBGC2 ( &pxenv_undi_isr, " %04x:%04x+%x(%x) %s hlen %d",
- undi_isr->Frame.segment, undi_isr->Frame.offset,
- undi_isr->BufferLength, undi_isr->FrameLength,
- ( net_protocol ? net_protocol->name : "RAW" ),
- undi_isr->FrameHeaderLength );
-
- /* Free packet */
- free_iob ( iobuf );
- break;
- default :
- DBGC2 ( &pxenv_undi_isr, " INVALID(%04x)\n",
- undi_isr->FuncFlag );
-
- /* Should never happen */
- undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_DONE;
- undi_isr->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
- return PXENV_EXIT_FAILURE;
- }
-
- DBGC2 ( &pxenv_undi_isr, "\n" );
- undi_isr->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/** PXE UNDI API */
-struct pxe_api_call pxe_undi_api[] __pxe_api_call = {
- PXE_API_CALL ( PXENV_UNDI_STARTUP, pxenv_undi_startup,
- struct s_PXENV_UNDI_STARTUP ),
- PXE_API_CALL ( PXENV_UNDI_CLEANUP, pxenv_undi_cleanup,
- struct s_PXENV_UNDI_CLEANUP ),
- PXE_API_CALL ( PXENV_UNDI_INITIALIZE, pxenv_undi_initialize,
- struct s_PXENV_UNDI_INITIALIZE ),
- PXE_API_CALL ( PXENV_UNDI_RESET_ADAPTER, pxenv_undi_reset_adapter,
- struct s_PXENV_UNDI_RESET ),
- PXE_API_CALL ( PXENV_UNDI_SHUTDOWN, pxenv_undi_shutdown,
- struct s_PXENV_UNDI_SHUTDOWN ),
- PXE_API_CALL ( PXENV_UNDI_OPEN, pxenv_undi_open,
- struct s_PXENV_UNDI_OPEN ),
- PXE_API_CALL ( PXENV_UNDI_CLOSE, pxenv_undi_close,
- struct s_PXENV_UNDI_CLOSE ),
- PXE_API_CALL ( PXENV_UNDI_TRANSMIT, pxenv_undi_transmit,
- struct s_PXENV_UNDI_TRANSMIT ),
- PXE_API_CALL ( PXENV_UNDI_SET_MCAST_ADDRESS,
- pxenv_undi_set_mcast_address,
- struct s_PXENV_UNDI_SET_MCAST_ADDRESS ),
- PXE_API_CALL ( PXENV_UNDI_SET_STATION_ADDRESS,
- pxenv_undi_set_station_address,
- struct s_PXENV_UNDI_SET_STATION_ADDRESS ),
- PXE_API_CALL ( PXENV_UNDI_SET_PACKET_FILTER,
- pxenv_undi_set_packet_filter,
- struct s_PXENV_UNDI_SET_PACKET_FILTER ),
- PXE_API_CALL ( PXENV_UNDI_GET_INFORMATION, pxenv_undi_get_information,
- struct s_PXENV_UNDI_GET_INFORMATION ),
- PXE_API_CALL ( PXENV_UNDI_GET_STATISTICS, pxenv_undi_get_statistics,
- struct s_PXENV_UNDI_GET_STATISTICS ),
- PXE_API_CALL ( PXENV_UNDI_CLEAR_STATISTICS, pxenv_undi_clear_statistics,
- struct s_PXENV_UNDI_CLEAR_STATISTICS ),
- PXE_API_CALL ( PXENV_UNDI_INITIATE_DIAGS, pxenv_undi_initiate_diags,
- struct s_PXENV_UNDI_INITIATE_DIAGS ),
- PXE_API_CALL ( PXENV_UNDI_FORCE_INTERRUPT, pxenv_undi_force_interrupt,
- struct s_PXENV_UNDI_FORCE_INTERRUPT ),
- PXE_API_CALL ( PXENV_UNDI_GET_MCAST_ADDRESS,
- pxenv_undi_get_mcast_address,
- struct s_PXENV_UNDI_GET_MCAST_ADDRESS ),
- PXE_API_CALL ( PXENV_UNDI_GET_NIC_TYPE, pxenv_undi_get_nic_type,
- struct s_PXENV_UNDI_GET_NIC_TYPE ),
- PXE_API_CALL ( PXENV_UNDI_GET_IFACE_INFO, pxenv_undi_get_iface_info,
- struct s_PXENV_UNDI_GET_IFACE_INFO ),
- PXE_API_CALL ( PXENV_UNDI_ISR, pxenv_undi_isr,
- struct s_PXENV_UNDI_ISR ),
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c b/qemu/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c
deleted file mode 100644
index 0b6be9a03..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/pxeparent/pxeparent.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <ipxe/dhcp.h>
-#include <ipxe/profile.h>
-#include <pxeparent.h>
-#include <pxe_api.h>
-#include <pxe_types.h>
-#include <pxe.h>
-
-/** @file
- *
- * Call interface to parent PXE stack
- *
- */
-
-/* Disambiguate the various error causes */
-#define EINFO_EPXECALL \
- __einfo_uniqify ( EINFO_EPLATFORM, 0x01, \
- "External PXE API error" )
-#define EPXECALL( status ) EPLATFORM ( EINFO_EPXECALL, status )
-
-/** A parent PXE API call profiler */
-struct pxeparent_profiler {
- /** Total time spent performing REAL_CALL() */
- struct profiler total;
- /** Time spent transitioning to real mode */
- struct profiler p2r;
- /** Time spent in external code */
- struct profiler ext;
- /** Time spent transitioning back to protected mode */
- struct profiler r2p;
-};
-
-/** PXENV_UNDI_TRANSMIT profiler */
-static struct pxeparent_profiler pxeparent_tx_profiler __profiler = {
- { .name = "pxeparent.tx" },
- { .name = "pxeparent.tx_p2r" },
- { .name = "pxeparent.tx_ext" },
- { .name = "pxeparent.tx_r2p" },
-};
-
-/** PXENV_UNDI_ISR profiler
- *
- * Note that this profiler will not see calls to
- * PXENV_UNDI_ISR_IN_START, which are handled by the UNDI ISR and do
- * not go via pxeparent_call().
- */
-static struct pxeparent_profiler pxeparent_isr_profiler __profiler = {
- { .name = "pxeparent.isr" },
- { .name = "pxeparent.isr_p2r" },
- { .name = "pxeparent.isr_ext" },
- { .name = "pxeparent.isr_r2p" },
-};
-
-/** PXE unknown API call profiler
- *
- * This profiler can be used to measure the overhead of a dummy PXE
- * API call.
- */
-static struct pxeparent_profiler pxeparent_unknown_profiler __profiler = {
- { .name = "pxeparent.unknown" },
- { .name = "pxeparent.unknown_p2r" },
- { .name = "pxeparent.unknown_ext" },
- { .name = "pxeparent.unknown_r2p" },
-};
-
-/** Miscellaneous PXE API call profiler */
-static struct pxeparent_profiler pxeparent_misc_profiler __profiler = {
- { .name = "pxeparent.misc" },
- { .name = "pxeparent.misc_p2r" },
- { .name = "pxeparent.misc_ext" },
- { .name = "pxeparent.misc_r2p" },
-};
-
-/**
- * Name PXE API call
- *
- * @v function API call number
- * @ret name API call name
- */
-static inline __attribute__ (( always_inline )) const char *
-pxeparent_function_name ( unsigned int function ) {
- switch ( function ) {
- case PXENV_START_UNDI:
- return "PXENV_START_UNDI";
- case PXENV_STOP_UNDI:
- return "PXENV_STOP_UNDI";
- case PXENV_UNDI_STARTUP:
- return "PXENV_UNDI_STARTUP";
- case PXENV_UNDI_CLEANUP:
- return "PXENV_UNDI_CLEANUP";
- case PXENV_UNDI_INITIALIZE:
- return "PXENV_UNDI_INITIALIZE";
- case PXENV_UNDI_RESET_ADAPTER:
- return "PXENV_UNDI_RESET_ADAPTER";
- case PXENV_UNDI_SHUTDOWN:
- return "PXENV_UNDI_SHUTDOWN";
- case PXENV_UNDI_OPEN:
- return "PXENV_UNDI_OPEN";
- case PXENV_UNDI_CLOSE:
- return "PXENV_UNDI_CLOSE";
- case PXENV_UNDI_TRANSMIT:
- return "PXENV_UNDI_TRANSMIT";
- case PXENV_UNDI_SET_MCAST_ADDRESS:
- return "PXENV_UNDI_SET_MCAST_ADDRESS";
- case PXENV_UNDI_SET_STATION_ADDRESS:
- return "PXENV_UNDI_SET_STATION_ADDRESS";
- case PXENV_UNDI_SET_PACKET_FILTER:
- return "PXENV_UNDI_SET_PACKET_FILTER";
- case PXENV_UNDI_GET_INFORMATION:
- return "PXENV_UNDI_GET_INFORMATION";
- case PXENV_UNDI_GET_STATISTICS:
- return "PXENV_UNDI_GET_STATISTICS";
- case PXENV_UNDI_CLEAR_STATISTICS:
- return "PXENV_UNDI_CLEAR_STATISTICS";
- case PXENV_UNDI_INITIATE_DIAGS:
- return "PXENV_UNDI_INITIATE_DIAGS";
- case PXENV_UNDI_FORCE_INTERRUPT:
- return "PXENV_UNDI_FORCE_INTERRUPT";
- case PXENV_UNDI_GET_MCAST_ADDRESS:
- return "PXENV_UNDI_GET_MCAST_ADDRESS";
- case PXENV_UNDI_GET_NIC_TYPE:
- return "PXENV_UNDI_GET_NIC_TYPE";
- case PXENV_UNDI_GET_IFACE_INFO:
- return "PXENV_UNDI_GET_IFACE_INFO";
- /*
- * Duplicate case value; this is a bug in the PXE specification.
- *
- * case PXENV_UNDI_GET_STATE:
- * return "PXENV_UNDI_GET_STATE";
- */
- case PXENV_UNDI_ISR:
- return "PXENV_UNDI_ISR";
- case PXENV_GET_CACHED_INFO:
- return "PXENV_GET_CACHED_INFO";
- default:
- return "UNKNOWN API CALL";
- }
-}
-
-/**
- * Determine applicable profiler pair (for debugging)
- *
- * @v function API call number
- * @ret profiler Profiler
- */
-static struct pxeparent_profiler * pxeparent_profiler ( unsigned int function ){
-
- /* Determine applicable profiler */
- switch ( function ) {
- case PXENV_UNDI_TRANSMIT:
- return &pxeparent_tx_profiler;
- case PXENV_UNDI_ISR:
- return &pxeparent_isr_profiler;
- case PXENV_UNKNOWN:
- return &pxeparent_unknown_profiler;
- default:
- return &pxeparent_misc_profiler;
- }
-}
-
-/**
- * PXE parent parameter block
- *
- * Used as the parameter block for all parent PXE API calls. Resides
- * in base memory.
- */
-static union u_PXENV_ANY __bss16 ( pxeparent_params );
-#define pxeparent_params __use_data16 ( pxeparent_params )
-
-/** PXE parent entry point
- *
- * Used as the indirection vector for all parent PXE API calls. Resides in
- * base memory.
- */
-SEGOFF16_t __bss16 ( pxeparent_entry_point );
-#define pxeparent_entry_point __use_data16 ( pxeparent_entry_point )
-
-/**
- * Issue parent PXE API call
- *
- * @v entry Parent PXE stack entry point
- * @v function API call number
- * @v params PXE parameter block
- * @v params_len Length of PXE parameter block
- * @ret rc Return status code
- */
-int pxeparent_call ( SEGOFF16_t entry, unsigned int function,
- void *params, size_t params_len ) {
- struct pxeparent_profiler *profiler = pxeparent_profiler ( function );
- PXENV_EXIT_t exit;
- unsigned long started;
- unsigned long stopped;
- int discard_D;
- int rc;
-
- /* Copy parameter block and entry point */
- assert ( params_len <= sizeof ( pxeparent_params ) );
- memcpy ( &pxeparent_params, params, params_len );
- memcpy ( &pxeparent_entry_point, &entry, sizeof ( entry ) );
-
- /* Call real-mode entry point. This calling convention will
- * work with both the !PXE and the PXENV+ entry points.
- */
- profile_start ( &profiler->total );
- __asm__ __volatile__ ( REAL_CODE ( "pushl %%ebp\n\t" /* gcc bug */
- "rdtsc\n\t"
- "pushl %%eax\n\t"
- "pushw %%es\n\t"
- "pushw %%di\n\t"
- "pushw %%bx\n\t"
- "lcall *pxeparent_entry_point\n\t"
- "movw %%ax, %%bx\n\t"
- "rdtsc\n\t"
- "addw $6, %%sp\n\t"
- "popl %%edx\n\t"
- "popl %%ebp\n\t" /* gcc bug */ )
- : "=a" ( stopped ), "=d" ( started ),
- "=b" ( exit ), "=D" ( discard_D )
- : "b" ( function ),
- "D" ( __from_data16 ( &pxeparent_params ) )
- : "ecx", "esi" );
- profile_stop ( &profiler->total );
- profile_start_at ( &profiler->p2r, profile_started ( &profiler->total));
- profile_stop_at ( &profiler->p2r, started );
- profile_start_at ( &profiler->ext, started );
- profile_stop_at ( &profiler->ext, stopped );
- profile_start_at ( &profiler->r2p, stopped );
- profile_stop_at ( &profiler->r2p, profile_stopped ( &profiler->total ));
-
- /* Determine return status code based on PXENV_EXIT and
- * PXENV_STATUS
- */
- rc = ( ( exit == PXENV_EXIT_SUCCESS ) ?
- 0 : -EPXECALL ( pxeparent_params.Status ) );
-
- /* If anything goes wrong, print as much debug information as
- * it's possible to give.
- */
- if ( rc != 0 ) {
- SEGOFF16_t rm_params = {
- .segment = rm_ds,
- .offset = __from_data16 ( &pxeparent_params ),
- };
-
- DBG ( "PXEPARENT %s failed: %s\n",
- pxeparent_function_name ( function ), strerror ( rc ) );
- DBG ( "PXEPARENT parameters at %04x:%04x length "
- "%#02zx, entry point at %04x:%04x\n",
- rm_params.segment, rm_params.offset, params_len,
- pxeparent_entry_point.segment,
- pxeparent_entry_point.offset );
- DBG ( "PXEPARENT parameters provided:\n" );
- DBG_HDA ( rm_params, params, params_len );
- DBG ( "PXEPARENT parameters returned:\n" );
- DBG_HDA ( rm_params, &pxeparent_params, params_len );
- }
-
- /* Copy parameter block back */
- memcpy ( params, &pxeparent_params, params_len );
-
- return rc;
-}
-
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/com32_call.c b/qemu/roms/ipxe/src/arch/i386/interface/syslinux/com32_call.c
deleted file mode 100644
index 75dcc238f..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/com32_call.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-/**
- * @file SYSLINUX COM32 helpers
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdint.h>
-#include <realmode.h>
-#include <comboot.h>
-#include <assert.h>
-#include <ipxe/uaccess.h>
-
-static com32sys_t __bss16 ( com32_regs );
-#define com32_regs __use_data16 ( com32_regs )
-
-static uint8_t __bss16 ( com32_int_vector );
-#define com32_int_vector __use_data16 ( com32_int_vector )
-
-static uint32_t __bss16 ( com32_farcall_proc );
-#define com32_farcall_proc __use_data16 ( com32_farcall_proc )
-
-uint16_t __bss16 ( com32_saved_sp );
-
-/**
- * Interrupt call helper
- */
-void __asmcall com32_intcall ( uint8_t interrupt, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
-
- memcpy_user ( virt_to_user( &com32_regs ), 0,
- phys_to_user ( inregs_phys ), 0,
- sizeof(com32sys_t) );
-
- com32_int_vector = interrupt;
-
- __asm__ __volatile__ (
- REAL_CODE ( /* Save all registers */
- "pushal\n\t"
- "pushw %%ds\n\t"
- "pushw %%es\n\t"
- "pushw %%fs\n\t"
- "pushw %%gs\n\t"
- /* Mask off unsafe flags */
- "movl (com32_regs + 40), %%eax\n\t"
- "andl $0x200cd7, %%eax\n\t"
- "movl %%eax, (com32_regs + 40)\n\t"
- /* Load com32_regs into the actual registers */
- "movw %%sp, %%ss:(com32_saved_sp)\n\t"
- "movw $com32_regs, %%sp\n\t"
- "popw %%gs\n\t"
- "popw %%fs\n\t"
- "popw %%es\n\t"
- "popw %%ds\n\t"
- "popal\n\t"
- "popfl\n\t"
- "movw %%ss:(com32_saved_sp), %%sp\n\t"
- /* patch INT instruction */
- "pushw %%ax\n\t"
- "movb %%ss:(com32_int_vector), %%al\n\t"
- "movb %%al, %%cs:(com32_intcall_instr + 1)\n\t"
- /* perform a jump to avoid problems with cache
- * consistency in self-modifying code on some CPUs (486)
- */
- "jmp 1f\n"
- "1:\n\t"
- "popw %%ax\n\t"
- "com32_intcall_instr:\n\t"
- /* INT instruction to be patched */
- "int $0xFF\n\t"
- /* Copy regs back to com32_regs */
- "movw %%sp, %%ss:(com32_saved_sp)\n\t"
- "movw $(com32_regs + 44), %%sp\n\t"
- "pushfl\n\t"
- "pushal\n\t"
- "pushw %%ds\n\t"
- "pushw %%es\n\t"
- "pushw %%fs\n\t"
- "pushw %%gs\n\t"
- "movw %%ss:(com32_saved_sp), %%sp\n\t"
- /* Restore registers */
- "popw %%gs\n\t"
- "popw %%fs\n\t"
- "popw %%es\n\t"
- "popw %%ds\n\t"
- "popal\n\t")
- : : );
-
- if ( outregs_phys ) {
- memcpy_user ( phys_to_user ( outregs_phys ), 0,
- virt_to_user( &com32_regs ), 0,
- sizeof(com32sys_t) );
- }
-}
-
-/**
- * Farcall helper
- */
-void __asmcall com32_farcall ( uint32_t proc, physaddr_t inregs_phys, physaddr_t outregs_phys ) {
-
- memcpy_user ( virt_to_user( &com32_regs ), 0,
- phys_to_user ( inregs_phys ), 0,
- sizeof(com32sys_t) );
-
- com32_farcall_proc = proc;
-
- __asm__ __volatile__ (
- REAL_CODE ( /* Save all registers */
- "pushal\n\t"
- "pushw %%ds\n\t"
- "pushw %%es\n\t"
- "pushw %%fs\n\t"
- "pushw %%gs\n\t"
- /* Mask off unsafe flags */
- "movl (com32_regs + 40), %%eax\n\t"
- "andl $0x200cd7, %%eax\n\t"
- "movl %%eax, (com32_regs + 40)\n\t"
- /* Load com32_regs into the actual registers */
- "movw %%sp, %%ss:(com32_saved_sp)\n\t"
- "movw $com32_regs, %%sp\n\t"
- "popw %%gs\n\t"
- "popw %%fs\n\t"
- "popw %%es\n\t"
- "popw %%ds\n\t"
- "popal\n\t"
- "popfl\n\t"
- "movw %%ss:(com32_saved_sp), %%sp\n\t"
- /* Call procedure */
- "lcall *%%ss:(com32_farcall_proc)\n\t"
- /* Copy regs back to com32_regs */
- "movw %%sp, %%ss:(com32_saved_sp)\n\t"
- "movw $(com32_regs + 44), %%sp\n\t"
- "pushfl\n\t"
- "pushal\n\t"
- "pushw %%ds\n\t"
- "pushw %%es\n\t"
- "pushw %%fs\n\t"
- "pushw %%gs\n\t"
- "movw %%ss:(com32_saved_sp), %%sp\n\t"
- /* Restore registers */
- "popw %%gs\n\t"
- "popw %%fs\n\t"
- "popw %%es\n\t"
- "popw %%ds\n\t"
- "popal\n\t")
- : : );
-
- if ( outregs_phys ) {
- memcpy_user ( phys_to_user ( outregs_phys ), 0,
- virt_to_user( &com32_regs ), 0,
- sizeof(com32sys_t) );
- }
-}
-
-/**
- * CDECL farcall helper
- */
-int __asmcall com32_cfarcall ( uint32_t proc, physaddr_t stack, size_t stacksz ) {
- int32_t eax;
-
- copy_user_to_rm_stack ( phys_to_user ( stack ), stacksz );
- com32_farcall_proc = proc;
-
- __asm__ __volatile__ (
- REAL_CODE ( "lcall *%%ss:(com32_farcall_proc)\n\t" )
- : "=a" (eax)
- :
- : "ecx", "edx" );
-
- remove_user_from_rm_stack ( 0, stacksz );
-
- return eax;
-}
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S b/qemu/roms/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S
deleted file mode 100644
index c9d1452b4..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/com32_wrapper.S
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER )
-
- .text
- .arch i386
- .code32
-
- .globl com32_farcall_wrapper
-com32_farcall_wrapper:
-
- movl $com32_farcall, %eax
- jmp com32_wrapper
-
-
- .globl com32_cfarcall_wrapper
-com32_cfarcall_wrapper:
-
- movl $com32_cfarcall, %eax
- jmp com32_wrapper
-
-
- .globl com32_intcall_wrapper
-com32_intcall_wrapper:
-
- movl $com32_intcall, %eax
- /*jmp com32_wrapper*/ /* fall through */
-
-com32_wrapper:
- cli
-
- /* Switch to internal virtual address space */
- call _phys_to_virt
-
- mov %eax, (com32_helper_function)
-
- /* Save external COM32 stack pointer */
- movl %esp, (com32_external_esp)
-
- /* Copy arguments to caller-save registers */
- movl 12(%esp), %eax
- movl 8(%esp), %ecx
- movl 4(%esp), %edx
-
- /* Switch to internal stack */
- movl (com32_internal_esp), %esp
-
- /* Copy arguments to internal stack */
- pushl %eax
- pushl %ecx
- pushl %edx
-
- call *(com32_helper_function)
-
- /* Clean up stack */
- addl $12, %esp
-
- /* Save internal stack pointer and restore external stack pointer */
- movl %esp, (com32_internal_esp)
- movl (com32_external_esp), %esp
-
- /* Switch to external flat physical address space */
- call _virt_to_phys
-
- sti
- ret
-
-
- .data
-
-/* Internal iPXE virtual address space %esp */
-.globl com32_internal_esp
-.lcomm com32_internal_esp, 4
-
-/* External flat physical address space %esp */
-.globl com32_external_esp
-.lcomm com32_external_esp, 4
-
-/* Function pointer of helper to call */
-.lcomm com32_helper_function, 4
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c b/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c
deleted file mode 100644
index 69d94c407..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_call.c
+++ /dev/null
@@ -1,717 +0,0 @@
-/*
- * Copyright (C) 2008 Daniel Verkamp <daniel@drv.nu>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-/**
- * @file SYSLINUX COMBOOT API
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <errno.h>
-#include <realmode.h>
-#include <biosint.h>
-#include <ipxe/console.h>
-#include <stdlib.h>
-#include <comboot.h>
-#include <bzimage.h>
-#include <pxe_call.h>
-#include <setjmp.h>
-#include <string.h>
-#include <ipxe/posix_io.h>
-#include <ipxe/process.h>
-#include <ipxe/serial.h>
-#include <ipxe/init.h>
-#include <ipxe/image.h>
-#include <ipxe/version.h>
-#include <usr/imgmgmt.h>
-
-/** The "SYSLINUX" version string */
-static char __bss16_array ( syslinux_version, [32] );
-#define syslinux_version __use_data16 ( syslinux_version )
-
-/** The "SYSLINUX" copyright string */
-static char __data16_array ( syslinux_copyright, [] ) = " http://ipxe.org";
-#define syslinux_copyright __use_data16 ( syslinux_copyright )
-
-static char __data16_array ( syslinux_configuration_file, [] ) = "";
-#define syslinux_configuration_file __use_data16 ( syslinux_configuration_file )
-
-/** Feature flags */
-static uint8_t __data16 ( comboot_feature_flags ) = COMBOOT_FEATURE_IDLE_LOOP;
-#define comboot_feature_flags __use_data16 ( comboot_feature_flags )
-
-typedef union {
- syslinux_pm_regs pm; syslinux_rm_regs rm;
-} syslinux_regs;
-
-/** Initial register values for INT 22h AX=1Ah and 1Bh */
-static syslinux_regs __text16 ( comboot_initial_regs );
-#define comboot_initial_regs __use_text16 ( comboot_initial_regs )
-
-static struct segoff __text16 ( int20_vector );
-#define int20_vector __use_text16 ( int20_vector )
-
-static struct segoff __text16 ( int21_vector );
-#define int21_vector __use_text16 ( int21_vector )
-
-static struct segoff __text16 ( int22_vector );
-#define int22_vector __use_text16 ( int22_vector )
-
-extern void int20_wrapper ( void );
-extern void int21_wrapper ( void );
-extern void int22_wrapper ( void );
-
-/* setjmp/longjmp context buffer used to return after loading an image */
-rmjmp_buf comboot_return;
-
-/* Mode flags set by INT 22h AX=0017h */
-static uint16_t comboot_graphics_mode = 0;
-
-/**
- * Print a string with a particular terminator
- */
-static void print_user_string ( unsigned int segment, unsigned int offset, char terminator ) {
- int i = 0;
- char c;
- userptr_t str = real_to_user ( segment, offset );
- for ( ; ; ) {
- copy_from_user ( &c, str, i, 1 );
- if ( c == terminator ) break;
- putchar ( c );
- i++;
- }
-}
-
-
-/**
- * Perform a series of memory copies from a list in low memory
- */
-static void shuffle ( unsigned int list_segment, unsigned int list_offset, unsigned int count )
-{
- comboot_shuffle_descriptor shuf[COMBOOT_MAX_SHUFFLE_DESCRIPTORS];
- unsigned int i;
-
- /* Copy shuffle descriptor list so it doesn't get overwritten */
- copy_from_user ( shuf, real_to_user ( list_segment, list_offset ), 0,
- count * sizeof( comboot_shuffle_descriptor ) );
-
- /* Do the copies */
- for ( i = 0; i < count; i++ ) {
- userptr_t src_u = phys_to_user ( shuf[ i ].src );
- userptr_t dest_u = phys_to_user ( shuf[ i ].dest );
-
- if ( shuf[ i ].src == 0xFFFFFFFF ) {
- /* Fill with 0 instead of copying */
- memset_user ( dest_u, 0, 0, shuf[ i ].len );
- } else if ( shuf[ i ].dest == 0xFFFFFFFF ) {
- /* Copy new list of descriptors */
- count = shuf[ i ].len / sizeof( comboot_shuffle_descriptor );
- assert ( count <= COMBOOT_MAX_SHUFFLE_DESCRIPTORS );
- copy_from_user ( shuf, src_u, 0, shuf[ i ].len );
- i = -1;
- } else {
- /* Regular copy */
- memmove_user ( dest_u, 0, src_u, 0, shuf[ i ].len );
- }
- }
-}
-
-
-/**
- * Set default text mode
- */
-void comboot_force_text_mode ( void ) {
- if ( comboot_graphics_mode & COMBOOT_VIDEO_VESA ) {
- /* Set VGA mode 3 via VESA VBE mode set */
- __asm__ __volatile__ (
- REAL_CODE (
- "mov $0x4F02, %%ax\n\t"
- "mov $0x03, %%bx\n\t"
- "int $0x10\n\t"
- )
- : : );
- } else if ( comboot_graphics_mode & COMBOOT_VIDEO_GRAPHICS ) {
- /* Set VGA mode 3 via standard VGA mode set */
- __asm__ __volatile__ (
- REAL_CODE (
- "mov $0x03, %%ax\n\t"
- "int $0x10\n\t"
- )
- : : );
- }
-
- comboot_graphics_mode = 0;
-}
-
-
-/**
- * Fetch kernel and optional initrd
- */
-static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
- struct image *kernel;
- struct image *initrd;
- char *initrd_file;
- int rc;
-
- /* Find initrd= parameter, if any */
- if ( ( initrd_file = strstr ( cmdline, "initrd=" ) ) != NULL ) {
- char *initrd_end;
-
- /* skip "initrd=" */
- initrd_file += 7;
-
- /* Find terminating space, if any, and replace with NUL */
- initrd_end = strchr ( initrd_file, ' ' );
- if ( initrd_end )
- *initrd_end = '\0';
-
- DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file );
-
- /* Fetch initrd */
- if ( ( rc = imgdownload_string ( initrd_file, 0,
- &initrd ) ) != 0 ) {
- DBG ( "COMBOOT: could not fetch initrd: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- /* Restore space after initrd name, if applicable */
- if ( initrd_end )
- *initrd_end = ' ';
- }
-
- DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
-
- /* Fetch kernel */
- if ( ( rc = imgdownload_string ( kernel_file, 0, &kernel ) ) != 0 ) {
- DBG ( "COMBOOT: could not fetch kernel: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- /* Replace comboot image with kernel */
- if ( ( rc = image_replace ( kernel ) ) != 0 ) {
- DBG ( "COMBOOT: could not replace with kernel: %s\n",
- strerror ( rc ) );
- return rc;
- }
-
- return 0;
-}
-
-
-/**
- * Terminate program interrupt handler
- */
-static __asmcall void int20 ( struct i386_all_regs *ix86 __unused ) {
- rmlongjmp ( comboot_return, COMBOOT_EXIT );
-}
-
-
-/**
- * DOS-compatible API
- */
-static __asmcall void int21 ( struct i386_all_regs *ix86 ) {
- ix86->flags |= CF;
-
- switch ( ix86->regs.ah ) {
- case 0x00:
- case 0x4C: /* Terminate program */
- rmlongjmp ( comboot_return, COMBOOT_EXIT );
- break;
-
- case 0x01: /* Get Key with Echo */
- case 0x08: /* Get Key without Echo */
- /* TODO: handle extended characters? */
- ix86->regs.al = getchar( );
-
- /* Enter */
- if ( ix86->regs.al == 0x0A )
- ix86->regs.al = 0x0D;
-
- if ( ix86->regs.ah == 0x01 )
- putchar ( ix86->regs.al );
-
- ix86->flags &= ~CF;
- break;
-
- case 0x02: /* Write Character */
- putchar ( ix86->regs.dl );
- ix86->flags &= ~CF;
- break;
-
- case 0x04: /* Write Character to Serial Port */
- if ( serial_console.base ) {
- uart_transmit ( &serial_console, ix86->regs.dl );
- ix86->flags &= ~CF;
- }
- break;
-
- case 0x09: /* Write DOS String to Console */
- print_user_string ( ix86->segs.ds, ix86->regs.dx, '$' );
- ix86->flags &= ~CF;
- break;
-
- case 0x0B: /* Check Keyboard */
- if ( iskey() )
- ix86->regs.al = 0xFF;
- else
- ix86->regs.al = 0x00;
-
- ix86->flags &= ~CF;
- break;
-
- case 0x30: /* Check DOS Version */
- /* Bottom halves all 0; top halves spell "SYSLINUX" */
- ix86->regs.eax = 0x59530000;
- ix86->regs.ebx = 0x4C530000;
- ix86->regs.ecx = 0x4E490000;
- ix86->regs.edx = 0x58550000;
- ix86->flags &= ~CF;
- break;
-
- default:
- DBG ( "COMBOOT unknown int21 function %02x\n", ix86->regs.ah );
- break;
- }
-}
-
-
-/**
- * Dispatch PXE API call weakly
- *
- * @v ix86 Registers for PXE call
- * @ret present Zero if the PXE stack is present, nonzero if not
- *
- * A successful return only indicates that the PXE stack was available
- * for dispatching the call; it says nothing about the success of
- * whatever the call asked for.
- */
-__weak int pxe_api_call_weak ( struct i386_all_regs *ix86 __unused ) {
- return -1;
-}
-
-/**
- * SYSLINUX API
- */
-static __asmcall void int22 ( struct i386_all_regs *ix86 ) {
- ix86->flags |= CF;
-
- switch ( ix86->regs.ax ) {
- case 0x0001: /* Get Version */
-
- /* Number of INT 22h API functions available */
- ix86->regs.ax = 0x001D;
-
- /* SYSLINUX version number */
- ix86->regs.ch = 0; /* major */
- ix86->regs.cl = 0; /* minor */
-
- /* SYSLINUX derivative ID */
- ix86->regs.dl = BZI_LOADER_TYPE_IPXE;
-
- /* SYSLINUX version */
- snprintf ( syslinux_version, sizeof ( syslinux_version ),
- "\r\niPXE %s", product_version );
-
- /* SYSLINUX version and copyright strings */
- ix86->segs.es = rm_ds;
- ix86->regs.si = ( ( unsigned ) __from_data16 ( syslinux_version ) );
- ix86->regs.di = ( ( unsigned ) __from_data16 ( syslinux_copyright ) );
-
- ix86->flags &= ~CF;
- break;
-
- case 0x0002: /* Write String */
- print_user_string ( ix86->segs.es, ix86->regs.bx, '\0' );
- ix86->flags &= ~CF;
- break;
-
- case 0x0003: /* Run command */
- {
- userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
- int len = strlen_user ( cmd_u, 0 );
- char cmd[len + 1];
- copy_from_user ( cmd, cmd_u, 0, len + 1 );
- DBG ( "COMBOOT: executing command '%s'\n", cmd );
- system ( cmd );
- DBG ( "COMBOOT: exiting after executing command...\n" );
- rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
- }
- break;
-
- case 0x0004: /* Run default command */
- /* FIXME: just exit for now */
- rmlongjmp ( comboot_return, COMBOOT_EXIT_COMMAND );
- break;
-
- case 0x0005: /* Force text mode */
- comboot_force_text_mode ( );
- ix86->flags &= ~CF;
- break;
-
- case 0x0006: /* Open file */
- {
- int fd;
- userptr_t file_u = real_to_user ( ix86->segs.es, ix86->regs.si );
- int len = strlen_user ( file_u, 0 );
- char file[len + 1];
-
- copy_from_user ( file, file_u, 0, len + 1 );
-
- if ( file[0] == '\0' ) {
- DBG ( "COMBOOT: attempted open with empty file name\n" );
- break;
- }
-
- DBG ( "COMBOOT: opening file '%s'\n", file );
-
- fd = open ( file );
-
- if ( fd < 0 ) {
- DBG ( "COMBOOT: error opening file %s\n", file );
- break;
- }
-
- /* This relies on the fact that a iPXE POSIX fd will
- * always fit in 16 bits.
- */
-#if (POSIX_FD_MAX > 65535)
-#error POSIX_FD_MAX too large
-#endif
- ix86->regs.si = (uint16_t) fd;
-
- ix86->regs.cx = COMBOOT_FILE_BLOCKSZ;
- ix86->regs.eax = fsize ( fd );
- ix86->flags &= ~CF;
- }
- break;
-
- case 0x0007: /* Read file */
- {
- int fd = ix86->regs.si;
- int len = ix86->regs.cx * COMBOOT_FILE_BLOCKSZ;
- int rc;
- fd_set fds;
- userptr_t buf = real_to_user ( ix86->segs.es, ix86->regs.bx );
-
- /* Wait for data ready to read */
- FD_ZERO ( &fds );
- FD_SET ( fd, &fds );
-
- select ( &fds, 1 );
-
- rc = read_user ( fd, buf, 0, len );
- if ( rc < 0 ) {
- DBG ( "COMBOOT: read failed\n" );
- ix86->regs.si = 0;
- break;
- }
-
- ix86->regs.ecx = rc;
- ix86->flags &= ~CF;
- }
- break;
-
- case 0x0008: /* Close file */
- {
- int fd = ix86->regs.si;
- close ( fd );
- ix86->flags &= ~CF;
- }
- break;
-
- case 0x0009: /* Call PXE Stack */
- if ( pxe_api_call_weak ( ix86 ) != 0 )
- ix86->flags |= CF;
- else
- ix86->flags &= ~CF;
- break;
-
- case 0x000A: /* Get Derivative-Specific Information */
-
- /* iPXE has its own derivative ID, so there is no defined
- * output here; just return AL for now */
- ix86->regs.al = BZI_LOADER_TYPE_IPXE;
- ix86->flags &= ~CF;
- break;
-
- case 0x000B: /* Get Serial Console Configuration */
- if ( serial_console.base ) {
- ix86->regs.dx = ( ( intptr_t ) serial_console.base );
- ix86->regs.cx = serial_console.divisor;
- ix86->regs.bx = 0;
- ix86->flags &= ~CF;
- }
- break;
-
- case 0x000C: /* Perform final cleanup */
- shutdown_boot();
- break;
-
- case 0x000E: /* Get configuration file name */
- /* FIXME: stub */
- ix86->segs.es = rm_ds;
- ix86->regs.bx = ( ( unsigned ) __from_data16 ( syslinux_configuration_file ) );
- ix86->flags &= ~CF;
- break;
-
- case 0x000F: /* Get IPAPPEND strings */
- /* FIXME: stub */
- ix86->regs.cx = 0;
- ix86->segs.es = 0;
- ix86->regs.bx = 0;
- ix86->flags &= ~CF;
- break;
-
- case 0x0010: /* Resolve hostname */
- {
- userptr_t hostname_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
- int len = strlen_user ( hostname_u, 0 );
- char hostname[len];
- struct in_addr addr;
-
- copy_from_user ( hostname, hostname_u, 0, len + 1 );
-
- /* TODO:
- * "If the hostname does not contain a dot (.), the
- * local domain name is automatically appended."
- */
-
- comboot_resolv ( hostname, &addr );
-
- ix86->regs.eax = addr.s_addr;
- ix86->flags &= ~CF;
- }
- break;
-
- case 0x0011: /* Maximum number of shuffle descriptors */
- ix86->regs.cx = COMBOOT_MAX_SHUFFLE_DESCRIPTORS;
- ix86->flags &= ~CF;
- break;
-
- case 0x0012: /* Cleanup, shuffle and boot */
- if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS )
- break;
-
- /* Perform final cleanup */
- shutdown_boot();
-
- /* Perform sequence of copies */
- shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx );
-
- /* Jump to real-mode entry point */
- __asm__ __volatile__ (
- REAL_CODE (
- "pushw %0\n\t"
- "popw %%ds\n\t"
- "pushl %1\n\t"
- "lret\n\t"
- )
- :
- : "r" ( ix86->segs.ds ),
- "r" ( ix86->regs.ebp ),
- "d" ( ix86->regs.ebx ),
- "S" ( ix86->regs.esi ) );
-
- assert ( 0 ); /* Execution should never reach this point */
-
- break;
-
- case 0x0013: /* Idle loop call */
- step ( );
- ix86->flags &= ~CF;
- break;
-
- case 0x0015: /* Get feature flags */
- ix86->segs.es = rm_ds;
- ix86->regs.bx = ( ( unsigned ) __from_data16 ( &comboot_feature_flags ) );
- ix86->regs.cx = 1; /* Number of feature flag bytes */
- ix86->flags &= ~CF;
- break;
-
- case 0x0016: /* Run kernel image */
- {
- userptr_t file_u = real_to_user ( ix86->segs.ds, ix86->regs.si );
- userptr_t cmd_u = real_to_user ( ix86->segs.es, ix86->regs.bx );
- int file_len = strlen_user ( file_u, 0 );
- int cmd_len = strlen_user ( cmd_u, 0 );
- char file[file_len + 1];
- char cmd[cmd_len + 1];
-
- copy_from_user ( file, file_u, 0, file_len + 1 );
- copy_from_user ( cmd, cmd_u, 0, cmd_len + 1 );
-
- DBG ( "COMBOOT: run kernel %s %s\n", file, cmd );
- comboot_fetch_kernel ( file, cmd );
- /* Technically, we should return if we
- * couldn't load the kernel, but it's not safe
- * to do that since we have just overwritten
- * part of the COMBOOT program's memory space.
- */
- DBG ( "COMBOOT: exiting to run kernel...\n" );
- rmlongjmp ( comboot_return, COMBOOT_EXIT_RUN_KERNEL );
- }
- break;
-
- case 0x0017: /* Report video mode change */
- comboot_graphics_mode = ix86->regs.bx;
- ix86->flags &= ~CF;
- break;
-
- case 0x0018: /* Query custom font */
- /* FIXME: stub */
- ix86->regs.al = 0;
- ix86->segs.es = 0;
- ix86->regs.bx = 0;
- ix86->flags &= ~CF;
- break;
-
- case 0x001B: /* Cleanup, shuffle and boot to real mode */
- if ( ix86->regs.cx > COMBOOT_MAX_SHUFFLE_DESCRIPTORS )
- break;
-
- /* Perform final cleanup */
- shutdown_boot();
-
- /* Perform sequence of copies */
- shuffle ( ix86->segs.es, ix86->regs.di, ix86->regs.cx );
-
- /* Copy initial register values to .text16 */
- memcpy_user ( real_to_user ( rm_cs, (unsigned) __from_text16 ( &comboot_initial_regs ) ), 0,
- real_to_user ( ix86->segs.ds, ix86->regs.si ), 0,
- sizeof(syslinux_rm_regs) );
-
- /* Load initial register values */
- __asm__ __volatile__ (
- REAL_CODE (
- /* Point SS:SP at the register value structure */
- "pushw %%cs\n\t"
- "popw %%ss\n\t"
- "movw $comboot_initial_regs, %%sp\n\t"
-
- /* Segment registers */
- "popw %%es\n\t"
- "popw %%ax\n\t" /* Skip CS */
- "popw %%ds\n\t"
- "popw %%ax\n\t" /* Skip SS for now */
- "popw %%fs\n\t"
- "popw %%gs\n\t"
-
- /* GP registers */
- "popl %%eax\n\t"
- "popl %%ecx\n\t"
- "popl %%edx\n\t"
- "popl %%ebx\n\t"
- "popl %%ebp\n\t" /* Skip ESP for now */
- "popl %%ebp\n\t"
- "popl %%esi\n\t"
- "popl %%edi\n\t"
-
- /* Load correct SS:ESP */
- "movw $(comboot_initial_regs + 6), %%sp\n\t"
- "popw %%ss\n\t"
- "movl %%cs:(comboot_initial_regs + 28), %%esp\n\t"
-
- "ljmp *%%cs:(comboot_initial_regs + 44)\n\t"
- )
- : : );
-
- break;
-
- case 0x001C: /* Get pointer to auxilliary data vector */
- /* FIXME: stub */
- ix86->regs.cx = 0; /* Size of the ADV */
- ix86->flags &= ~CF;
- break;
-
- case 0x001D: /* Write auxilliary data vector */
- /* FIXME: stub */
- ix86->flags &= ~CF;
- break;
-
- default:
- DBG ( "COMBOOT unknown int22 function %04x\n", ix86->regs.ax );
- break;
- }
-}
-
-/**
- * Hook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h)
- */
-void hook_comboot_interrupts ( ) {
-
- __asm__ __volatile__ (
- TEXT16_CODE ( "\nint20_wrapper:\n\t"
- "pushl %0\n\t"
- "pushw %%cs\n\t"
- "call prot_call\n\t"
- "addw $4, %%sp\n\t"
- "call patch_cf\n\t"
- "iret\n\t" )
- : : "i" ( int20 ) );
-
- hook_bios_interrupt ( 0x20, ( unsigned int ) int20_wrapper,
- &int20_vector );
-
- __asm__ __volatile__ (
- TEXT16_CODE ( "\nint21_wrapper:\n\t"
- "pushl %0\n\t"
- "pushw %%cs\n\t"
- "call prot_call\n\t"
- "addw $4, %%sp\n\t"
- "call patch_cf\n\t"
- "iret\n\t" )
- : : "i" ( int21 ) );
-
- hook_bios_interrupt ( 0x21, ( unsigned int ) int21_wrapper,
- &int21_vector );
-
- __asm__ __volatile__ (
- TEXT16_CODE ( "\nint22_wrapper:\n\t"
- "pushl %0\n\t"
- "pushw %%cs\n\t"
- "call prot_call\n\t"
- "addw $4, %%sp\n\t"
- "call patch_cf\n\t"
- "iret\n\t" )
- : : "i" ( int22) );
-
- hook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper,
- &int22_vector );
-}
-
-/**
- * Unhook BIOS interrupts related to COMBOOT API (INT 20h, 21h, 22h)
- */
-void unhook_comboot_interrupts ( ) {
-
- unhook_bios_interrupt ( 0x20, ( unsigned int ) int20_wrapper,
- &int20_vector );
-
- unhook_bios_interrupt ( 0x21, ( unsigned int ) int21_wrapper,
- &int21_vector );
-
- unhook_bios_interrupt ( 0x22, ( unsigned int ) int22_wrapper,
- &int22_vector );
-}
-
-/* Avoid dragging in serial console support unconditionally */
-struct uart serial_console __attribute__ (( weak ));
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_resolv.c b/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_resolv.c
deleted file mode 100644
index 03bbfd04a..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/syslinux/comboot_resolv.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <errno.h>
-#include <comboot.h>
-#include <ipxe/in.h>
-#include <ipxe/list.h>
-#include <ipxe/process.h>
-#include <ipxe/resolv.h>
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-struct comboot_resolver {
- struct interface intf;
- int rc;
- struct in_addr addr;
-};
-
-static void comboot_resolv_close ( struct comboot_resolver *comboot_resolver,
- int rc ) {
- comboot_resolver->rc = rc;
- intf_shutdown ( &comboot_resolver->intf, rc );
-}
-
-static void comboot_resolv_done ( struct comboot_resolver *comboot_resolver,
- struct sockaddr *sa ) {
- struct sockaddr_in *sin;
-
- if ( sa->sa_family == AF_INET ) {
- sin = ( ( struct sockaddr_in * ) sa );
- comboot_resolver->addr = sin->sin_addr;
- }
-}
-
-static struct interface_operation comboot_resolv_op[] = {
- INTF_OP ( intf_close, struct comboot_resolver *, comboot_resolv_close ),
- INTF_OP ( resolv_done, struct comboot_resolver *, comboot_resolv_done ),
-};
-
-static struct interface_descriptor comboot_resolv_desc =
- INTF_DESC ( struct comboot_resolver, intf, comboot_resolv_op );
-
-static struct comboot_resolver comboot_resolver = {
- .intf = INTF_INIT ( comboot_resolv_desc ),
-};
-
-int comboot_resolv ( const char *name, struct in_addr *address ) {
- int rc;
-
- comboot_resolver.rc = -EINPROGRESS;
- comboot_resolver.addr.s_addr = 0;
-
- if ( ( rc = resolv ( &comboot_resolver.intf, name, NULL ) ) != 0 )
- return rc;
-
- while ( comboot_resolver.rc == -EINPROGRESS )
- step();
-
- if ( ! comboot_resolver.addr.s_addr )
- return -EAFNOSUPPORT;
-
- *address = comboot_resolver.addr;
- return comboot_resolver.rc;
-}
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestinfo.c b/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestinfo.c
deleted file mode 100644
index a0530c8d1..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestinfo.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-/** @file
- *
- * VMware GuestInfo settings
- *
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <ipxe/init.h>
-#include <ipxe/settings.h>
-#include <ipxe/netdevice.h>
-#include <ipxe/guestrpc.h>
-
-/** GuestInfo GuestRPC channel */
-static int guestinfo_channel;
-
-/**
- * Fetch value of typed GuestInfo setting
- *
- * @v settings Settings block
- * @v setting Setting to fetch
- * @v type Setting type to attempt (or NULL for default)
- * @v data Buffer to fill with setting data
- * @v len Length of buffer
- * @ret found Setting found in GuestInfo
- * @ret len Length of setting data, or negative error
- */
-static int guestinfo_fetch_type ( struct settings *settings,
- struct setting *setting,
- const struct setting_type *type,
- void *data, size_t len, int *found ) {
- const char *parent_name = settings->parent->name;
- char command[ 24 /* "info-get guestinfo.ipxe." */ +
- strlen ( parent_name ) + 1 /* "." */ +
- strlen ( setting->name ) + 1 /* "." */ +
- ( type ? strlen ( type->name ) : 0 ) + 1 /* NUL */ ];
- struct setting *predefined;
- char *info;
- int info_len;
- int check_len;
- int ret;
-
- /* Construct info-get command */
- snprintf ( command, sizeof ( command ),
- "info-get guestinfo.ipxe.%s%s%s%s%s",
- parent_name, ( parent_name[0] ? "." : "" ), setting->name,
- ( type ? "." : "" ), ( type ? type->name : "" ) );
-
- /* Check for existence and obtain length of GuestInfo value */
- info_len = guestrpc_command ( guestinfo_channel, command, NULL, 0 );
- if ( info_len < 0 ) {
- ret = info_len;
- goto err_get_info_len;
- }
-
- /* Mark as found */
- *found = 1;
-
- /* Determine default type if necessary */
- if ( ! type ) {
- predefined = find_setting ( setting->name );
- type = ( predefined ? predefined->type : &setting_type_string );
- }
- assert ( type != NULL );
-
- /* Allocate temporary block to hold GuestInfo value */
- info = zalloc ( info_len + 1 /* NUL */ );
- if ( ! info ) {
- DBGC ( settings, "GuestInfo %p could not allocate %d bytes\n",
- settings, info_len );
- ret = -ENOMEM;
- goto err_alloc;
- }
- info[info_len] = '\0';
-
- /* Fetch GuestInfo value */
- check_len = guestrpc_command ( guestinfo_channel, command,
- info, info_len );
- if ( check_len < 0 ) {
- ret = check_len;
- goto err_get_info;
- }
- if ( check_len != info_len ) {
- DBGC ( settings, "GuestInfo %p length mismatch (expected %d, "
- "got %d)\n", settings, info_len, check_len );
- ret = -EIO;
- goto err_get_info;
- }
- DBGC2 ( settings, "GuestInfo %p found %s = \"%s\"\n",
- settings, &command[9] /* Skip "info-get " */, info );
-
- /* Parse GuestInfo value according to type */
- ret = setting_parse ( type, info, data, len );
- if ( ret < 0 ) {
- DBGC ( settings, "GuestInfo %p could not parse \"%s\" as %s: "
- "%s\n", settings, info, type->name, strerror ( ret ) );
- goto err_parse;
- }
-
- err_parse:
- err_get_info:
- free ( info );
- err_alloc:
- err_get_info_len:
- return ret;
-}
-
-/**
- * Fetch value of GuestInfo setting
- *
- * @v settings Settings block
- * @v setting Setting to fetch
- * @v data Buffer to fill with setting data
- * @v len Length of buffer
- * @ret len Length of setting data, or negative error
- */
-static int guestinfo_fetch ( struct settings *settings,
- struct setting *setting,
- void *data, size_t len ) {
- struct setting_type *type;
- int found = 0;
- int ret;
-
- /* Try default type first */
- ret = guestinfo_fetch_type ( settings, setting, NULL,
- data, len, &found );
- if ( found )
- return ret;
-
- /* Otherwise, try all possible types */
- for_each_table_entry ( type, SETTING_TYPES ) {
- ret = guestinfo_fetch_type ( settings, setting, type,
- data, len, &found );
- if ( found )
- return ret;
- }
-
- /* Not found */
- return -ENOENT;
-}
-
-/** GuestInfo settings operations */
-static struct settings_operations guestinfo_settings_operations = {
- .fetch = guestinfo_fetch,
-};
-
-/** GuestInfo settings */
-static struct settings guestinfo_settings = {
- .refcnt = NULL,
- .siblings = LIST_HEAD_INIT ( guestinfo_settings.siblings ),
- .children = LIST_HEAD_INIT ( guestinfo_settings.children ),
- .op = &guestinfo_settings_operations,
-};
-
-/** Initialise GuestInfo settings */
-static void guestinfo_init ( void ) {
- int rc;
-
- /* Open GuestRPC channel */
- guestinfo_channel = guestrpc_open();
- if ( guestinfo_channel < 0 ) {
- rc = guestinfo_channel;
- DBG ( "GuestInfo could not open channel: %s\n",
- strerror ( rc ) );
- return;
- }
-
- /* Register root GuestInfo settings */
- if ( ( rc = register_settings ( &guestinfo_settings, NULL,
- "vmware" ) ) != 0 ) {
- DBG ( "GuestInfo could not register settings: %s\n",
- strerror ( rc ) );
- return;
- }
-}
-
-/** GuestInfo settings initialiser */
-struct init_fn guestinfo_init_fn __init_fn ( INIT_NORMAL ) = {
- .initialise = guestinfo_init,
-};
-
-/**
- * Create per-netdevice GuestInfo settings
- *
- * @v netdev Network device
- * @ret rc Return status code
- */
-static int guestinfo_net_probe ( struct net_device *netdev ) {
- struct settings *settings;
- int rc;
-
- /* Do nothing unless we have a GuestInfo channel available */
- if ( guestinfo_channel < 0 )
- return 0;
-
- /* Allocate and initialise settings block */
- settings = zalloc ( sizeof ( *settings ) );
- if ( ! settings ) {
- rc = -ENOMEM;
- goto err_alloc;
- }
- settings_init ( settings, &guestinfo_settings_operations, NULL, NULL );
-
- /* Register settings */
- if ( ( rc = register_settings ( settings, netdev_settings ( netdev ),
- "vmware" ) ) != 0 ) {
- DBGC ( settings, "GuestInfo %p could not register for %s: %s\n",
- settings, netdev->name, strerror ( rc ) );
- goto err_register;
- }
- DBGC ( settings, "GuestInfo %p registered for %s\n",
- settings, netdev->name );
-
- return 0;
-
- err_register:
- free ( settings );
- err_alloc:
- return rc;
-}
-
-/**
- * Remove per-netdevice GuestInfo settings
- *
- * @v netdev Network device
- */
-static void guestinfo_net_remove ( struct net_device *netdev ) {
- struct settings *parent = netdev_settings ( netdev );
- struct settings *settings;
-
- list_for_each_entry ( settings, &parent->children, siblings ) {
- if ( settings->op == &guestinfo_settings_operations ) {
- DBGC ( settings, "GuestInfo %p unregistered for %s\n",
- settings, netdev->name );
- unregister_settings ( settings );
- free ( settings );
- return;
- }
- }
-}
-
-/** GuestInfo per-netdevice driver */
-struct net_driver guestinfo_net_driver __net_driver = {
- .name = "GuestInfo",
- .probe = guestinfo_net_probe,
- .remove = guestinfo_net_remove,
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c b/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c
deleted file mode 100644
index ef7ee8151..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/vmware/guestrpc.c
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * VMware GuestRPC mechanism
- *
- */
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <ipxe/vmware.h>
-#include <ipxe/guestrpc.h>
-
-/* Disambiguate the various error causes */
-#define EPROTO_OPEN __einfo_error ( EINFO_EPROTO_OPEN )
-#define EINFO_EPROTO_OPEN \
- __einfo_uniqify ( EINFO_EPROTO, 0x00, "GuestRPC open failed" )
-#define EPROTO_COMMAND_LEN __einfo_error ( EINFO_EPROTO_COMMAND_LEN )
-#define EINFO_EPROTO_COMMAND_LEN \
- __einfo_uniqify ( EINFO_EPROTO, 0x01, "GuestRPC command length failed" )
-#define EPROTO_COMMAND_DATA __einfo_error ( EINFO_EPROTO_COMMAND_DATA )
-#define EINFO_EPROTO_COMMAND_DATA \
- __einfo_uniqify ( EINFO_EPROTO, 0x02, "GuestRPC command data failed" )
-#define EPROTO_REPLY_LEN __einfo_error ( EINFO_EPROTO_REPLY_LEN )
-#define EINFO_EPROTO_REPLY_LEN \
- __einfo_uniqify ( EINFO_EPROTO, 0x03, "GuestRPC reply length failed" )
-#define EPROTO_REPLY_DATA __einfo_error ( EINFO_EPROTO_REPLY_DATA )
-#define EINFO_EPROTO_REPLY_DATA \
- __einfo_uniqify ( EINFO_EPROTO, 0x04, "GuestRPC reply data failed" )
-#define EPROTO_REPLY_FINISH __einfo_error ( EINFO_EPROTO_REPLY_FINISH )
-#define EINFO_EPROTO_REPLY_FINISH \
- __einfo_uniqify ( EINFO_EPROTO, 0x05, "GuestRPC reply finish failed" )
-#define EPROTO_CLOSE __einfo_error ( EINFO_EPROTO_CLOSE )
-#define EINFO_EPROTO_CLOSE \
- __einfo_uniqify ( EINFO_EPROTO, 0x06, "GuestRPC close failed" )
-
-/**
- * Open GuestRPC channel
- *
- * @ret channel Channel number, or negative error
- */
-int guestrpc_open ( void ) {
- uint16_t channel;
- uint32_t discard_b;
- uint32_t status;
-
- /* Issue GuestRPC command */
- status = vmware_cmd_guestrpc ( 0, GUESTRPC_OPEN, GUESTRPC_MAGIC,
- &channel, &discard_b );
- if ( status != GUESTRPC_OPEN_SUCCESS ) {
- DBGC ( GUESTRPC_MAGIC, "GuestRPC open failed: status %08x\n",
- status );
- return -EPROTO_OPEN;
- }
-
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d opened\n", channel );
- return channel;
-}
-
-/**
- * Send GuestRPC command length
- *
- * @v channel Channel number
- * @v len Command length
- * @ret rc Return status code
- */
-static int guestrpc_command_len ( int channel, size_t len ) {
- uint16_t discard_d;
- uint32_t discard_b;
- uint32_t status;
-
- /* Issue GuestRPC command */
- status = vmware_cmd_guestrpc ( channel, GUESTRPC_COMMAND_LEN, len,
- &discard_d, &discard_b );
- if ( status != GUESTRPC_COMMAND_LEN_SUCCESS ) {
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d send command "
- "length %zd failed: status %08x\n",
- channel, len, status );
- return -EPROTO_COMMAND_LEN;
- }
-
- return 0;
-}
-
-/**
- * Send GuestRPC command data
- *
- * @v channel Channel number
- * @v data Command data
- * @ret rc Return status code
- */
-static int guestrpc_command_data ( int channel, uint32_t data ) {
- uint16_t discard_d;
- uint32_t discard_b;
- uint32_t status;
-
- /* Issue GuestRPC command */
- status = vmware_cmd_guestrpc ( channel, GUESTRPC_COMMAND_DATA, data,
- &discard_d, &discard_b );
- if ( status != GUESTRPC_COMMAND_DATA_SUCCESS ) {
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d send command "
- "data %08x failed: status %08x\n",
- channel, data, status );
- return -EPROTO_COMMAND_DATA;
- }
-
- return 0;
-}
-
-/**
- * Receive GuestRPC reply length
- *
- * @v channel Channel number
- * @ret reply_id Reply ID
- * @ret len Reply length, or negative error
- */
-static int guestrpc_reply_len ( int channel, uint16_t *reply_id ) {
- uint32_t len;
- uint32_t status;
-
- /* Issue GuestRPC command */
- status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_LEN, 0,
- reply_id, &len );
- if ( status != GUESTRPC_REPLY_LEN_SUCCESS ) {
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d receive reply "
- "length failed: status %08x\n", channel, status );
- return -EPROTO_REPLY_LEN;
- }
-
- return len;
-}
-
-/**
- * Receive GuestRPC reply data
- *
- * @v channel Channel number
- * @v reply_id Reply ID
- * @ret data Reply data
- * @ret rc Return status code
- */
-static int guestrpc_reply_data ( int channel, uint16_t reply_id,
- uint32_t *data ) {
- uint16_t discard_d;
- uint32_t status;
-
- /* Issue GuestRPC command */
- status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_DATA, reply_id,
- &discard_d, data );
- if ( status != GUESTRPC_REPLY_DATA_SUCCESS ) {
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d receive reply "
- "%d data failed: status %08x\n",
- channel, reply_id, status );
- return -EPROTO_REPLY_DATA;
- }
-
- return 0;
-}
-
-/**
- * Finish receiving GuestRPC reply
- *
- * @v channel Channel number
- * @v reply_id Reply ID
- * @ret rc Return status code
- */
-static int guestrpc_reply_finish ( int channel, uint16_t reply_id ) {
- uint16_t discard_d;
- uint32_t discard_b;
- uint32_t status;
-
- /* Issue GuestRPC command */
- status = vmware_cmd_guestrpc ( channel, GUESTRPC_REPLY_FINISH, reply_id,
- &discard_d, &discard_b );
- if ( status != GUESTRPC_REPLY_FINISH_SUCCESS ) {
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d finish reply %d "
- "failed: status %08x\n", channel, reply_id, status );
- return -EPROTO_REPLY_FINISH;
- }
-
- return 0;
-}
-
-/**
- * Close GuestRPC channel
- *
- * @v channel Channel number
- */
-void guestrpc_close ( int channel ) {
- uint16_t discard_d;
- uint32_t discard_b;
- uint32_t status;
-
- /* Issue GuestRPC command */
- status = vmware_cmd_guestrpc ( channel, GUESTRPC_CLOSE, 0,
- &discard_d, &discard_b );
- if ( status != GUESTRPC_CLOSE_SUCCESS ) {
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d close failed: "
- "status %08x\n", channel, status );
- return;
- }
-
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d closed\n", channel );
-}
-
-/**
- * Issue GuestRPC command
- *
- * @v channel Channel number
- * @v command Command
- * @v reply Reply buffer
- * @v reply_len Length of reply buffer
- * @ret len Length of reply, or negative error
- *
- * The actual length of the reply will be returned even if the buffer
- * was too small.
- */
-int guestrpc_command ( int channel, const char *command, char *reply,
- size_t reply_len ) {
- const uint8_t *command_bytes = ( ( const void * ) command );
- uint8_t *reply_bytes = ( ( void * ) reply );
- size_t command_len = strlen ( command );
- int orig_reply_len = reply_len;
- uint16_t status;
- uint8_t *status_bytes = ( ( void * ) &status );
- size_t status_len = sizeof ( status );
- uint32_t data;
- uint16_t reply_id;
- int len;
- int remaining;
- unsigned int i;
- int rc;
-
- DBGC2 ( GUESTRPC_MAGIC, "GuestRPC channel %d issuing command:\n",
- channel );
- DBGC2_HDA ( GUESTRPC_MAGIC, 0, command, command_len );
-
- /* Sanity check */
- assert ( ( reply != NULL ) || ( reply_len == 0 ) );
-
- /* Send command length */
- if ( ( rc = guestrpc_command_len ( channel, command_len ) ) < 0 )
- return rc;
-
- /* Send command data */
- while ( command_len ) {
- data = 0;
- for ( i = sizeof ( data ) ; i ; i-- ) {
- if ( command_len ) {
- data = ( ( data & ~0xff ) |
- *(command_bytes++) );
- command_len--;
- }
- data = ( ( data << 24 ) | ( data >> 8 ) );
- }
- if ( ( rc = guestrpc_command_data ( channel, data ) ) < 0 )
- return rc;
- }
-
- /* Receive reply length */
- if ( ( len = guestrpc_reply_len ( channel, &reply_id ) ) < 0 ) {
- rc = len;
- return rc;
- }
-
- /* Receive reply */
- for ( remaining = len ; remaining > 0 ; remaining -= sizeof ( data ) ) {
- if ( ( rc = guestrpc_reply_data ( channel, reply_id,
- &data ) ) < 0 ) {
- return rc;
- }
- for ( i = sizeof ( data ) ; i ; i-- ) {
- if ( status_len ) {
- *(status_bytes++) = ( data & 0xff );
- status_len--;
- len--;
- } else if ( reply_len ) {
- *(reply_bytes++) = ( data & 0xff );
- reply_len--;
- }
- data = ( ( data << 24 ) | ( data >> 8 ) );
- }
- }
-
- /* Finish receiving RPC reply */
- if ( ( rc = guestrpc_reply_finish ( channel, reply_id ) ) < 0 )
- return rc;
-
- DBGC2 ( GUESTRPC_MAGIC, "GuestRPC channel %d received reply (id %d, "
- "length %d):\n", channel, reply_id, len );
- DBGC2_HDA ( GUESTRPC_MAGIC, 0, &status, sizeof ( status ) );
- DBGC2_HDA ( GUESTRPC_MAGIC, sizeof ( status ), reply,
- ( ( len < orig_reply_len ) ? len : orig_reply_len ) );
-
- /* Check reply status */
- if ( status != GUESTRPC_SUCCESS ) {
- DBGC ( GUESTRPC_MAGIC, "GuestRPC channel %d command failed "
- "(status %04x, reply id %d, reply length %d):\n",
- channel, status, reply_id, len );
- DBGC_HDA ( GUESTRPC_MAGIC, 0, command, command_len );
- DBGC_HDA ( GUESTRPC_MAGIC, 0, &status, sizeof ( status ) );
- DBGC_HDA ( GUESTRPC_MAGIC, sizeof ( status ), reply,
- ( ( len < orig_reply_len ) ? len : orig_reply_len ));
- return -EIO;
- }
-
- return len;
-}
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c b/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c
deleted file mode 100644
index f7df4f75b..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmconsole.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * VMware logfile console
- *
- */
-
-#include <string.h>
-#include <ipxe/console.h>
-#include <ipxe/lineconsole.h>
-#include <ipxe/init.h>
-#include <ipxe/guestrpc.h>
-#include <config/console.h>
-
-/** VMware logfile console buffer size */
-#define VMCONSOLE_BUFSIZE 128
-
-/* Set default console usage if applicable */
-#if ! ( defined ( CONSOLE_VMWARE ) && CONSOLE_EXPLICIT ( CONSOLE_VMWARE ) )
-#undef CONSOLE_VMWARE
-#define CONSOLE_VMWARE ( CONSOLE_USAGE_ALL & ~CONSOLE_USAGE_TUI )
-#endif
-
-/** VMware logfile console GuestRPC channel */
-static int vmconsole_channel;
-
-/** VMware logfile console line buffer */
-static struct {
- char prefix[4];
- char message[VMCONSOLE_BUFSIZE];
-} vmconsole_buffer = {
- .prefix = "log ",
-};
-
-/** VMware logfile console ANSI escape sequence handlers */
-static struct ansiesc_handler vmconsole_handlers[] = {
- { 0, NULL }
-};
-
-/** VMware logfile line console */
-static struct line_console vmconsole_line = {
- .buffer = vmconsole_buffer.message,
- .len = sizeof ( vmconsole_buffer.message ),
- .ctx = {
- .handlers = vmconsole_handlers,
- },
-};
-
-/** VMware logfile console recursion marker */
-static int vmconsole_entered;
-
-/**
- * Print a character to VMware logfile console
- *
- * @v character Character to be printed
- */
-static void vmconsole_putchar ( int character ) {
- int rc;
-
- /* Ignore if we are already mid-logging */
- if ( vmconsole_entered )
- return;
-
- /* Fill line buffer */
- if ( line_putchar ( &vmconsole_line, character ) == 0 )
- return;
-
- /* Guard against re-entry */
- vmconsole_entered = 1;
-
- /* Send log message */
- if ( ( rc = guestrpc_command ( vmconsole_channel,
- vmconsole_buffer.prefix, NULL, 0 ) ) <0){
- DBG ( "VMware console could not send log message: %s\n",
- strerror ( rc ) );
- }
-
- /* Clear re-entry flag */
- vmconsole_entered = 0;
-}
-
-/** VMware logfile console driver */
-struct console_driver vmconsole __console_driver = {
- .putchar = vmconsole_putchar,
- .disabled = CONSOLE_DISABLED,
- .usage = CONSOLE_VMWARE,
-};
-
-/**
- * Initialise VMware logfile console
- *
- */
-static void vmconsole_init ( void ) {
- int rc;
-
- /* Attempt to open console */
- vmconsole_channel = guestrpc_open();
- if ( vmconsole_channel < 0 ) {
- rc = vmconsole_channel;
- DBG ( "VMware console could not be initialised: %s\n",
- strerror ( rc ) );
- return;
- }
-
- /* Mark console as available */
- vmconsole.disabled = 0;
-}
-
-/**
- * VMware logfile console initialisation function
- */
-struct init_fn vmconsole_init_fn __init_fn ( INIT_CONSOLE ) = {
- .initialise = vmconsole_init,
-};
diff --git a/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c b/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c
deleted file mode 100644
index a415465fb..000000000
--- a/qemu/roms/ipxe/src/arch/i386/interface/vmware/vmware.c
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- *
- * You can also choose to distribute this program under the terms of
- * the Unmodified Binary Distribution Licence (as given in the file
- * COPYING.UBDL), provided that you have satisfied its requirements.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
-
-/** @file
- *
- * VMware backdoor mechanism
- *
- * Based on the unofficial documentation at
- *
- * http://sites.google.com/site/chitchatvmback/backdoor
- *
- */
-
-#include <stdint.h>
-#include <errno.h>
-#include <ipxe/vmware.h>
-
-/**
- * Detect VMware presence
- *
- * @ret rc Return status code
- */
-int vmware_present ( void ) {
- uint32_t version;
- uint32_t magic;
- uint32_t product_type;
-
- /* Perform backdoor call */
- vmware_cmd_get_version ( &version, &magic, &product_type );
-
- /* Check for VMware presence */
- if ( magic != VMW_MAGIC ) {
- DBGC ( VMW_MAGIC, "VMware not present\n" );
- return -ENOENT;
- }
-
- DBGC ( VMW_MAGIC, "VMware product type %04x version %08x detected\n",
- product_type, version );
- return 0;
-}