summaryrefslogtreecommitdiff
path: root/gpxe/src/arch/i386/interface
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2016-02-09 18:08:47 -0800
committerH. Peter Anvin <hpa@zytor.com>2016-02-09 18:08:47 -0800
commitf2f897a1762fab84d2905f32b1c15dd7b42abb56 (patch)
treea38f51d3f1fcbf44afddb4736d549c12eaf491be /gpxe/src/arch/i386/interface
parent72d2959272b4616f17a97667e6dfa9d06bf109a3 (diff)
downloadsyslinux-f2f897a1762fab84d2905f32b1c15dd7b42abb56.tar.gz
gpxe: delete long since obsolete snapshot of gPXE
gPXE has been deprecated in favor of iPXE for many, many years now. It is much better than users get it directly from the iPXE project, since we should no longer need any special modifications for Syslinux use. Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'gpxe/src/arch/i386/interface')
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/abft.c62
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/aoeboot.c78
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_nap.c16
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_smbios.c86
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/bios_timer.c65
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/biosint.c92
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c73
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/ibft.c451
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/int13.c715
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/iscsiboot.c75
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/keepsan.c26
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c202
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/pcibios.c115
-rw-r--r--gpxe/src/arch/i386/interface/pcbios/sbft.c105
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_call.c509
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_entry.S216
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_errors.c103
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_file.c306
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_loader.c50
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_preboot.c357
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_tftp.c586
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_udp.c405
-rw-r--r--gpxe/src/arch/i386/interface/pxe/pxe_undi.c791
-rw-r--r--gpxe/src/arch/i386/interface/pxeparent/pxeparent.c201
-rw-r--r--gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c69
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/com32_call.c190
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S94
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/comboot_call.c716
-rw-r--r--gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c60
29 files changed, 0 insertions, 6814 deletions
diff --git a/gpxe/src/arch/i386/interface/pcbios/abft.c b/gpxe/src/arch/i386/interface/pcbios/abft.c
deleted file mode 100644
index 86941728..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/abft.c
+++ /dev/null
@@ -1,62 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <realmode.h>
-#include <gpxe/aoe.h>
-#include <gpxe/netdevice.h>
-#include <gpxe/abft.h>
-
-/** @file
- *
- * AoE Boot Firmware Table
- *
- */
-
-#define abftab __use_data16 ( abftab )
-/** The aBFT used by gPXE */
-struct abft_table __data16 ( abftab ) __attribute__ (( aligned ( 16 ) )) = {
- /* ACPI header */
- .acpi = {
- .signature = ABFT_SIG,
- .length = sizeof ( abftab ),
- .revision = 1,
- .oem_id = "FENSYS",
- .oem_table_id = "gPXE",
- },
-};
-
-/**
- * Fill in all variable portions of aBFT
- *
- * @v aoe AoE session
- */
-void abft_fill_data ( struct aoe_session *aoe ) {
-
- /* Fill in boot parameters */
- abftab.shelf = aoe->major;
- abftab.slot = aoe->minor;
- memcpy ( abftab.mac, aoe->netdev->ll_addr, sizeof ( abftab.mac ) );
-
- /* Update checksum */
- acpi_fix_checksum ( &abftab.acpi );
-
- DBG ( "AoE boot firmware table:\n" );
- DBG_HD ( &abftab, sizeof ( abftab ) );
-}
diff --git a/gpxe/src/arch/i386/interface/pcbios/aoeboot.c b/gpxe/src/arch/i386/interface/pcbios/aoeboot.c
deleted file mode 100644
index 2670b15d..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/aoeboot.c
+++ /dev/null
@@ -1,78 +0,0 @@
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <gpxe/aoe.h>
-#include <gpxe/ata.h>
-#include <gpxe/netdevice.h>
-#include <gpxe/sanboot.h>
-#include <gpxe/abft.h>
-#include <int13.h>
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-static int aoeboot ( const char *root_path ) {
- struct ata_device *ata;
- struct int13_drive *drive;
- int rc;
-
- ata = zalloc ( sizeof ( *ata ) );
- if ( ! ata ) {
- rc = -ENOMEM;
- goto err_alloc_ata;
- }
- drive = zalloc ( sizeof ( *drive ) );
- if ( ! drive ) {
- rc = -ENOMEM;
- goto err_alloc_drive;
- }
-
- /* FIXME: ugly, ugly hack */
- struct net_device *netdev = last_opened_netdev();
-
- if ( ( rc = aoe_attach ( ata, netdev, root_path ) ) != 0 ) {
- printf ( "Could not attach AoE device: %s\n",
- strerror ( rc ) );
- goto err_attach;
- }
- if ( ( rc = init_atadev ( ata ) ) != 0 ) {
- printf ( "Could not initialise AoE device: %s\n",
- strerror ( rc ) );
- goto err_init;
- }
-
- /* FIXME: ugly, ugly hack */
- struct aoe_session *aoe =
- container_of ( ata->backend, struct aoe_session, refcnt );
- abft_fill_data ( aoe );
-
- drive->blockdev = &ata->blockdev;
-
- register_int13_drive ( drive );
- printf ( "Registered as BIOS drive %#02x\n", drive->drive );
- printf ( "Booting from BIOS drive %#02x\n", drive->drive );
- rc = int13_boot ( drive->drive );
- printf ( "Boot failed\n" );
-
- /* Leave drive registered, if instructed to do so */
- if ( keep_san() )
- return rc;
-
- printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
- unregister_int13_drive ( drive );
-
- err_init:
- aoe_detach ( ata );
- err_attach:
- free ( drive );
- err_alloc_drive:
- free ( ata );
- err_alloc_ata:
- return rc;
-}
-
-struct sanboot_protocol aoe_sanboot_protocol __sanboot_protocol = {
- .prefix = "aoe:",
- .boot = aoeboot,
-};
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_nap.c b/gpxe/src/arch/i386/interface/pcbios/bios_nap.c
deleted file mode 100644
index e38cac7a..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/bios_nap.c
+++ /dev/null
@@ -1,16 +0,0 @@
-#include <gpxe/nap.h>
-#include <realmode.h>
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-/**
- * Save power by halting the CPU until the next interrupt
- *
- */
-static void bios_cpu_nap ( void ) {
- __asm__ __volatile__ ( REAL_CODE ( "sti\n\t"
- "hlt\n\t"
- "cli\n\t" ) : : );
-}
-
-PROVIDE_NAP ( pcbios, cpu_nap, bios_cpu_nap );
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c b/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c
deleted file mode 100644
index 094214bd..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/bios_smbios.c
+++ /dev/null
@@ -1,86 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <gpxe/uaccess.h>
-#include <gpxe/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 ) {
- union {
- struct smbios_entry entry;
- uint8_t bytes[256]; /* 256 is maximum length possible */
- } u;
- static unsigned int offset = 0;
- size_t len;
- unsigned int i;
- uint8_t sum;
-
- /* Try to find SMBIOS */
- for ( ; offset < 0x10000 ; offset += 0x10 ) {
-
- /* Read start of header and verify signature */
- copy_from_real ( &u.entry, BIOS_SEG, offset,
- sizeof ( u.entry ));
- if ( u.entry.signature != SMBIOS_SIGNATURE )
- continue;
-
- /* Read whole header and verify checksum */
- len = u.entry.len;
- copy_from_real ( &u.bytes, BIOS_SEG, offset, len );
- for ( i = 0 , sum = 0 ; i < len ; i++ ) {
- sum += u.bytes[i];
- }
- if ( sum != 0 ) {
- DBG ( "SMBIOS at %04x:%04x has bad checksum %02x\n",
- BIOS_SEG, offset, sum );
- continue;
- }
-
- /* Fill result structure */
- DBG ( "Found SMBIOS v%d.%d entry point at %04x:%04x\n",
- u.entry.major, u.entry.minor, BIOS_SEG, offset );
- smbios->address = phys_to_user ( u.entry.smbios_address );
- smbios->len = u.entry.smbios_len;
- smbios->count = u.entry.smbios_count;
- return 0;
- }
-
- DBG ( "No SMBIOS found\n" );
- return -ENODEV;
-}
-
-PROVIDE_SMBIOS ( pcbios, find_smbios, bios_find_smbios );
diff --git a/gpxe/src/arch/i386/interface/pcbios/bios_timer.c b/gpxe/src/arch/i386/interface/pcbios/bios_timer.c
deleted file mode 100644
index 8ecf7c12..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/bios_timer.c
+++ /dev/null
@@ -1,65 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-/** @file
- *
- * BIOS timer
- *
- */
-
-#include <gpxe/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__ ( REAL_CODE ( "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/gpxe/src/arch/i386/interface/pcbios/biosint.c b/gpxe/src/arch/i386/interface/pcbios/biosint.c
deleted file mode 100644
index a193defa..00000000
--- a/gpxe/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 );
-
-/**
- * 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/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c b/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c
deleted file mode 100644
index b1cbc337..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/ib_srpboot.c
+++ /dev/null
@@ -1,73 +0,0 @@
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <gpxe/sanboot.h>
-#include <int13.h>
-#include <gpxe/srp.h>
-#include <gpxe/sbft.h>
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-static int ib_srpboot ( const char *root_path ) {
- struct scsi_device *scsi;
- struct int13_drive *drive;
- int rc;
-
- scsi = zalloc ( sizeof ( *scsi ) );
- if ( ! scsi ) {
- rc = -ENOMEM;
- goto err_alloc_scsi;
- }
- drive = zalloc ( sizeof ( *drive ) );
- if ( ! drive ) {
- rc = -ENOMEM;
- goto err_alloc_drive;
- }
-
- if ( ( rc = srp_attach ( scsi, root_path ) ) != 0 ) {
- printf ( "Could not attach IB_SRP device: %s\n",
- strerror ( rc ) );
- goto err_attach;
- }
- if ( ( rc = init_scsidev ( scsi ) ) != 0 ) {
- printf ( "Could not initialise IB_SRP device: %s\n",
- strerror ( rc ) );
- goto err_init;
- }
-
- drive->blockdev = &scsi->blockdev;
-
- /* FIXME: ugly, ugly hack */
- struct srp_device *srp =
- container_of ( scsi->backend, struct srp_device, refcnt );
- sbft_fill_data ( srp );
-
- register_int13_drive ( drive );
- printf ( "Registered as BIOS drive %#02x\n", drive->drive );
- printf ( "Booting from BIOS drive %#02x\n", drive->drive );
- rc = int13_boot ( drive->drive );
- printf ( "Boot failed\n" );
-
- /* Leave drive registered, if instructed to do so */
- if ( keep_san() )
- return rc;
-
- printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
- unregister_int13_drive ( drive );
-
- err_init:
- srp_detach ( scsi );
- err_attach:
- free ( drive );
- err_alloc_drive:
- free ( scsi );
- err_alloc_scsi:
- return rc;
-}
-
-struct sanboot_protocol ib_srp_sanboot_protocol __sanboot_protocol = {
- .prefix = "ib_srp:",
- .boot = ib_srpboot,
-};
diff --git a/gpxe/src/arch/i386/interface/pcbios/ibft.c b/gpxe/src/arch/i386/interface/pcbios/ibft.c
deleted file mode 100644
index adf8e6b9..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/ibft.c
+++ /dev/null
@@ -1,451 +0,0 @@
-/*
- * Copyright Fen Systems Ltd. 2007. Portions of this code are derived
- * from IBM Corporation Sample Programs. Copyright IBM Corporation
- * 2004, 2007. All rights reserved.
- *
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
- * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
- * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- */
-
-FILE_LICENCE ( BSD2 );
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <byteswap.h>
-#include <realmode.h>
-#include <gpxe/pci.h>
-#include <gpxe/acpi.h>
-#include <gpxe/in.h>
-#include <gpxe/netdevice.h>
-#include <gpxe/ethernet.h>
-#include <gpxe/dhcp.h>
-#include <gpxe/iscsi.h>
-#include <gpxe/ibft.h>
-
-/** @file
- *
- * iSCSI boot firmware table
- *
- * The information in this file is derived from the document "iSCSI
- * Boot Firmware Table (iBFT)" as published by IBM at
- *
- * ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf
- *
- */
-
-#define ibftab __use_data16 ( ibftab )
-/** The iBFT used by gPXE */
-struct gpxe_ibft __data16 ( ibftab ) = {
- /* Table header */
- .table = {
- /* ACPI header */
- .acpi = {
- .signature = IBFT_SIG,
- .length = sizeof ( ibftab ),
- .revision = 1,
- .oem_id = "FENSYS",
- .oem_table_id = "gPXE",
- },
- /* Control block */
- .control = {
- .header = {
- .structure_id = IBFT_STRUCTURE_ID_CONTROL,
- .version = 1,
- .length = sizeof ( ibftab.table.control ),
- .flags = 0,
- },
- .initiator = offsetof ( typeof ( ibftab ), initiator ),
- .nic_0 = offsetof ( typeof ( ibftab ), nic ),
- .target_0 = offsetof ( typeof ( ibftab ), target ),
- },
- },
- /* iSCSI initiator information */
- .initiator = {
- .header = {
- .structure_id = IBFT_STRUCTURE_ID_INITIATOR,
- .version = 1,
- .length = sizeof ( ibftab.initiator ),
- .flags = ( IBFT_FL_INITIATOR_BLOCK_VALID |
- IBFT_FL_INITIATOR_FIRMWARE_BOOT_SELECTED ),
- },
- },
- /* NIC information */
- .nic = {
- .header = {
- .structure_id = IBFT_STRUCTURE_ID_NIC,
- .version = 1,
- .length = sizeof ( ibftab.nic ),
- .flags = ( IBFT_FL_NIC_BLOCK_VALID |
- IBFT_FL_NIC_FIRMWARE_BOOT_SELECTED ),
- },
- },
- /* iSCSI target information */
- .target = {
- .header = {
- .structure_id = IBFT_STRUCTURE_ID_TARGET,
- .version = 1,
- .length = sizeof ( ibftab.target ),
- .flags = ( IBFT_FL_TARGET_BLOCK_VALID |
- IBFT_FL_TARGET_FIRMWARE_BOOT_SELECTED ),
- },
- },
-};
-
-/**
- * Fill in an IP address field within iBFT
- *
- * @v ipaddr IP address field
- * @v in IPv4 address
- */
-static void ibft_set_ipaddr ( struct ibft_ipaddr *ipaddr, struct in_addr in ) {
- memset ( ipaddr, 0, sizeof ( ipaddr ) );
- if ( in.s_addr ) {
- ipaddr->in = in;
- ipaddr->ones = 0xffff;
- }
-}
-
-/**
- * Fill in an IP address within iBFT from configuration setting
- *
- * @v ipaddr IP address field
- * @v setting Configuration setting
- * @v tag DHCP option tag
- */
-static void ibft_set_ipaddr_option ( struct ibft_ipaddr *ipaddr,
- struct setting *setting ) {
- struct in_addr in = { 0 };
- fetch_ipv4_setting ( NULL, setting, &in );
- ibft_set_ipaddr ( ipaddr, in );
-}
-
-/**
- * Read IP address from iBFT (for debugging)
- *
- * @v strings iBFT string block descriptor
- * @v string String field
- * @ret ipaddr IP address string
- */
-static const char * ibft_ipaddr ( struct ibft_ipaddr *ipaddr ) {
- return inet_ntoa ( ipaddr->in );
-}
-
-/**
- * Allocate a string within iBFT
- *
- * @v strings iBFT string block descriptor
- * @v string String field to fill in
- * @v len Length of string to allocate (excluding NUL)
- * @ret rc Return status code
- */
-static int ibft_alloc_string ( struct ibft_string_block *strings,
- struct ibft_string *string, size_t len ) {
- char *dest;
- unsigned int remaining;
-
- dest = ( ( ( char * ) strings->table ) + strings->offset );
- remaining = ( strings->table->acpi.length - strings->offset );
- if ( len >= remaining )
- return -ENOMEM;
-
- string->offset = strings->offset;
- string->length = len;
- strings->offset += ( len + 1 );
- return 0;
-}
-
-/**
- * Fill in a string field within iBFT
- *
- * @v strings iBFT string block descriptor
- * @v string String field
- * @v data String to fill in, or NULL
- * @ret rc Return status code
- */
-static int ibft_set_string ( struct ibft_string_block *strings,
- struct ibft_string *string, const char *data ) {
- char *dest;
- int rc;
-
- if ( ! data )
- return 0;
-
- if ( ( rc = ibft_alloc_string ( strings, string,
- strlen ( data ) ) ) != 0 )
- return rc;
- dest = ( ( ( char * ) strings->table ) + string->offset );
- strcpy ( dest, data );
-
- return 0;
-}
-
-/**
- * Fill in a string field within iBFT from configuration setting
- *
- * @v strings iBFT string block descriptor
- * @v string String field
- * @v setting Configuration setting
- * @ret rc Return status code
- */
-static int ibft_set_string_option ( struct ibft_string_block *strings,
- struct ibft_string *string,
- struct setting *setting ) {
- int len;
- char *dest;
- int rc;
-
- len = fetch_setting_len ( NULL, setting );
- if ( len < 0 ) {
- string->offset = 0;
- string->length = 0;
- return 0;
- }
-
- if ( ( rc = ibft_alloc_string ( strings, string, len ) ) != 0 )
- return rc;
- dest = ( ( ( char * ) strings->table ) + string->offset );
- fetch_string_setting ( NULL, setting, dest, ( len + 1 ) );
- return 0;
-}
-
-/**
- * Read string from iBFT (for debugging)
- *
- * @v strings iBFT string block descriptor
- * @v string String field
- * @ret data String content (or "<empty>")
- */
-static const char * ibft_string ( struct ibft_string_block *strings,
- struct ibft_string *string ) {
- return ( string->offset ?
- ( ( ( char * ) strings->table ) + string->offset ) : NULL );
-}
-
-/**
- * Fill in NIC portion of iBFT
- *
- * @v nic NIC portion of iBFT
- * @v strings iBFT string block descriptor
- * @v netdev Network device
- * @ret rc Return status code
- */
-static int ibft_fill_nic ( struct ibft_nic *nic,
- struct ibft_string_block *strings,
- struct net_device *netdev ) {
- struct ll_protocol *ll_protocol = netdev->ll_protocol;
- struct in_addr netmask_addr = { 0 };
- unsigned int netmask_count = 0;
- int rc;
-
- /* Extract values from DHCP configuration */
- ibft_set_ipaddr_option ( &nic->ip_address, &ip_setting );
- DBG ( "iBFT NIC IP = %s\n", ibft_ipaddr ( &nic->ip_address ) );
- ibft_set_ipaddr_option ( &nic->gateway, &gateway_setting );
- DBG ( "iBFT NIC gateway = %s\n", ibft_ipaddr ( &nic->gateway ) );
- ibft_set_ipaddr_option ( &nic->dns[0], &dns_setting );
- DBG ( "iBFT NIC DNS = %s\n", ibft_ipaddr ( &nic->dns[0] ) );
- if ( ( rc = ibft_set_string_option ( strings, &nic->hostname,
- &hostname_setting ) ) != 0 )
- return rc;
- DBG ( "iBFT NIC hostname = %s\n",
- ibft_string ( strings, &nic->hostname ) );
-
- /* Derive subnet mask prefix from subnet mask */
- fetch_ipv4_setting ( NULL, &netmask_setting, &netmask_addr );
- while ( netmask_addr.s_addr ) {
- if ( netmask_addr.s_addr & 0x1 )
- netmask_count++;
- netmask_addr.s_addr >>= 1;
- }
- nic->subnet_mask_prefix = netmask_count;
- DBG ( "iBFT NIC subnet = /%d\n", nic->subnet_mask_prefix );
-
- /* Extract values from net-device configuration */
- if ( ( rc = ll_protocol->eth_addr ( netdev->ll_addr,
- nic->mac_address ) ) != 0 ) {
- DBG ( "Could not determine iBFT MAC: %s\n", strerror ( rc ) );
- return rc;
- }
- DBG ( "iBFT NIC MAC = %s\n", eth_ntoa ( nic->mac_address ) );
- nic->pci_bus_dev_func = netdev->dev->desc.location;
- DBG ( "iBFT NIC PCI = %04x\n", nic->pci_bus_dev_func );
-
- return 0;
-}
-
-/**
- * Fill in Initiator portion of iBFT
- *
- * @v initiator Initiator portion of iBFT
- * @v strings iBFT string block descriptor
- * @ret rc Return status code
- */
-static int ibft_fill_initiator ( struct ibft_initiator *initiator,
- struct ibft_string_block *strings ) {
- const char *initiator_iqn = iscsi_initiator_iqn();
- int rc;
-
- if ( ( rc = ibft_set_string ( strings, &initiator->initiator_name,
- initiator_iqn ) ) != 0 )
- return rc;
- DBG ( "iBFT initiator hostname = %s\n",
- ibft_string ( strings, &initiator->initiator_name ) );
-
- return 0;
-}
-
-/**
- * Fill in Target CHAP portion of iBFT
- *
- * @v target Target portion of iBFT
- * @v strings iBFT string block descriptor
- * @v iscsi iSCSI session
- * @ret rc Return status code
- */
-static int ibft_fill_target_chap ( struct ibft_target *target,
- struct ibft_string_block *strings,
- struct iscsi_session *iscsi ) {
- int rc;
-
- if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_FORWARD_REQUIRED ) )
- return 0;
-
- assert ( iscsi->initiator_username );
- assert ( iscsi->initiator_password );
-
- target->chap_type = IBFT_CHAP_ONE_WAY;
- if ( ( rc = ibft_set_string ( strings, &target->chap_name,
- iscsi->initiator_username ) ) != 0 )
- return rc;
- DBG ( "iBFT target username = %s\n",
- ibft_string ( strings, &target->chap_name ) );
- if ( ( rc = ibft_set_string ( strings, &target->chap_secret,
- iscsi->initiator_password ) ) != 0 )
- return rc;
- DBG ( "iBFT target password = <redacted>\n" );
-
- return 0;
-}
-
-/**
- * Fill in Target Reverse CHAP portion of iBFT
- *
- * @v target Target portion of iBFT
- * @v strings iBFT string block descriptor
- * @v iscsi iSCSI session
- * @ret rc Return status code
- */
-static int ibft_fill_target_reverse_chap ( struct ibft_target *target,
- struct ibft_string_block *strings,
- struct iscsi_session *iscsi ) {
- int rc;
-
- if ( ! ( iscsi->status & ISCSI_STATUS_AUTH_REVERSE_REQUIRED ) )
- return 0;
-
- assert ( iscsi->initiator_username );
- assert ( iscsi->initiator_password );
- assert ( iscsi->target_username );
- assert ( iscsi->target_password );
-
- target->chap_type = IBFT_CHAP_MUTUAL;
- if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_name,
- iscsi->target_username ) ) != 0 )
- return rc;
- DBG ( "iBFT target reverse username = %s\n",
- ibft_string ( strings, &target->chap_name ) );
- if ( ( rc = ibft_set_string ( strings, &target->reverse_chap_secret,
- iscsi->target_password ) ) != 0 )
- return rc;
- DBG ( "iBFT target reverse password = <redacted>\n" );
-
- return 0;
-}
-
-/**
- * Fill in Target portion of iBFT
- *
- * @v target Target portion of iBFT
- * @v strings iBFT string block descriptor
- * @v iscsi iSCSI session
- * @ret rc Return status code
- */
-static int ibft_fill_target ( struct ibft_target *target,
- struct ibft_string_block *strings,
- struct iscsi_session *iscsi ) {
- struct sockaddr_in *sin_target =
- ( struct sockaddr_in * ) &iscsi->target_sockaddr;
- int rc;
-
- /* Fill in Target values */
- ibft_set_ipaddr ( &target->ip_address, sin_target->sin_addr );
- DBG ( "iBFT target IP = %s\n", ibft_ipaddr ( &target->ip_address ) );
- target->socket = ntohs ( sin_target->sin_port );
- DBG ( "iBFT target port = %d\n", target->socket );
- if ( ( rc = ibft_set_string ( strings, &target->target_name,
- iscsi->target_iqn ) ) != 0 )
- return rc;
- DBG ( "iBFT target name = %s\n",
- ibft_string ( strings, &target->target_name ) );
- if ( ( rc = ibft_fill_target_chap ( target, strings, iscsi ) ) != 0 )
- return rc;
- if ( ( rc = ibft_fill_target_reverse_chap ( target, strings,
- iscsi ) ) != 0 )
- return rc;
-
- return 0;
-}
-
-/**
- * Fill in all variable portions of iBFT
- *
- * @v netdev Network device
- * @v initiator_iqn Initiator IQN
- * @v st_target Target socket address
- * @v target_iqn Target IQN
- * @ret rc Return status code
- *
- */
-int ibft_fill_data ( struct net_device *netdev,
- struct iscsi_session *iscsi ) {
- struct ibft_string_block strings = {
- .table = &ibftab.table,
- .offset = offsetof ( typeof ( ibftab ), strings ),
- };
- int rc;
-
- /* Fill in NIC, Initiator and Target portions */
- if ( ( rc = ibft_fill_nic ( &ibftab.nic, &strings, netdev ) ) != 0 )
- return rc;
- if ( ( rc = ibft_fill_initiator ( &ibftab.initiator,
- &strings ) ) != 0 )
- return rc;
- if ( ( rc = ibft_fill_target ( &ibftab.target, &strings,
- iscsi ) ) != 0 )
- return rc;
-
- /* Update checksum */
- acpi_fix_checksum ( &ibftab.table.acpi );
-
- return 0;
-}
diff --git a/gpxe/src/arch/i386/interface/pcbios/int13.c b/gpxe/src/arch/i386/interface/pcbios/int13.c
deleted file mode 100644
index 87b613a8..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/int13.c
+++ /dev/null
@@ -1,715 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdint.h>
-#include <limits.h>
-#include <byteswap.h>
-#include <errno.h>
-#include <assert.h>
-#include <gpxe/list.h>
-#include <gpxe/blockdev.h>
-#include <gpxe/memmap.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.
- *
- */
-
-/** 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 );
-
-/** List of registered emulated drives */
-static LIST_HEAD ( drives );
-
-/**
- * Number of BIOS drives
- *
- * Note that this is the number of drives in the system as a whole
- * (i.e. a mirror of the counter at 40:75), rather than a count of the
- * number of emulated drives.
- */
-static uint8_t num_drives;
-
-/**
- * Update BIOS drive count
- */
-static void int13_set_num_drives ( void ) {
- struct int13_drive *drive;
-
- /* Get current drive count */
- get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
-
- /* Ensure count is large enough to cover all of our emulated drives */
- list_for_each_entry ( drive, &drives, list ) {
- if ( num_drives <= ( drive->drive & 0x7f ) )
- num_drives = ( ( drive->drive & 0x7f ) + 1 );
- }
-
- /* Update current drive count */
- put_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
-}
-
-/**
- * Check number of drives
- */
-static void int13_check_num_drives ( void ) {
- uint8_t check_num_drives;
-
- get_real ( check_num_drives, BDA_SEG, BDA_NUM_DRIVES );
- if ( check_num_drives != num_drives ) {
- int13_set_num_drives();
- DBG ( "INT13 fixing up number of drives from %d to %d\n",
- check_num_drives, num_drives );
- }
-}
-
-/**
- * INT 13, 00 - Reset disk system
- *
- * @v drive Emulated drive
- * @ret status Status code
- */
-static int int13_reset ( struct int13_drive *drive __unused,
- struct i386_all_regs *ix86 __unused ) {
- DBG ( "Reset drive\n" );
- return 0;
-}
-
-/**
- * INT 13, 01 - Get status of last operation
- *
- * @v drive Emulated drive
- * @ret status Status code
- */
-static int int13_get_last_status ( struct int13_drive *drive,
- struct i386_all_regs *ix86 __unused ) {
- DBG ( "Get status of last operation\n" );
- return drive->last_status;
-}
-
-/**
- * Read / write sectors
- *
- * @v drive 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 io Read / write method
- * @ret status Status code
- * @ret al Number of sectors read or written
- */
-static int int13_rw_sectors ( struct int13_drive *drive,
- struct i386_all_regs *ix86,
- int ( * io ) ( struct block_device *blockdev,
- uint64_t block,
- unsigned long count,
- userptr_t buffer ) ) {
- struct block_device *blockdev = drive->blockdev;
- unsigned int cylinder, head, sector;
- unsigned long lba;
- unsigned int count;
- userptr_t buffer;
- int rc;
-
- /* Validate blocksize */
- if ( blockdev->blksize != INT13_BLKSIZE ) {
- DBG ( "Invalid blocksize (%zd) for non-extended read/write\n",
- blockdev->blksize );
- return -INT13_STATUS_INVALID;
- }
-
- /* Calculate parameters */
- cylinder = ( ( ( ix86->regs.cl & 0xc0 ) << 2 ) | ix86->regs.ch );
- assert ( cylinder < drive->cylinders );
- head = ix86->regs.dh;
- assert ( head < drive->heads );
- sector = ( ix86->regs.cl & 0x3f );
- assert ( ( sector >= 1 ) && ( sector <= drive->sectors_per_track ) );
- lba = ( ( ( ( cylinder * drive->heads ) + head )
- * drive->sectors_per_track ) + sector - 1 );
- count = ix86->regs.al;
- buffer = real_to_user ( ix86->segs.es, ix86->regs.bx );
-
- DBG ( "C/H/S %d/%d/%d = LBA %#lx <-> %04x:%04x (count %d)\n", cylinder,
- head, sector, lba, ix86->segs.es, ix86->regs.bx, count );
-
- /* Read from / write to block device */
- if ( ( rc = io ( blockdev, lba, count, buffer ) ) != 0 ) {
- DBG ( "INT 13 failed: %s\n", strerror ( rc ) );
- return -INT13_STATUS_READ_ERROR;
- }
-
- return 0;
-}
-
-/**
- * INT 13, 02 - Read sectors
- *
- * @v drive 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 *drive,
- struct i386_all_regs *ix86 ) {
- DBG ( "Read: " );
- return int13_rw_sectors ( drive, ix86, drive->blockdev->op->read );
-}
-
-/**
- * INT 13, 03 - Write sectors
- *
- * @v drive 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 *drive,
- struct i386_all_regs *ix86 ) {
- DBG ( "Write: " );
- return int13_rw_sectors ( drive, ix86, drive->blockdev->op->write );
-}
-
-/**
- * INT 13, 08 - Get drive parameters
- *
- * @v drive 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 *drive,
- struct i386_all_regs *ix86 ) {
- unsigned int max_cylinder = drive->cylinders - 1;
- unsigned int max_head = drive->heads - 1;
- unsigned int max_sector = drive->sectors_per_track; /* sic */
-
- DBG ( "Get drive parameters\n" );
-
- ix86->regs.ch = ( max_cylinder & 0xff );
- ix86->regs.cl = ( ( ( max_cylinder >> 8 ) << 6 ) | max_sector );
- ix86->regs.dh = max_head;
- get_real ( ix86->regs.dl, BDA_SEG, BDA_NUM_DRIVES );
- return 0;
-}
-
-/**
- * INT 13, 15 - Get disk type
- *
- * @v drive 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 *drive,
- struct i386_all_regs *ix86 ) {
- uint32_t blocks;
-
- DBG ( "Get disk type\n" );
- blocks = ( ( drive->blockdev->blocks <= 0xffffffffUL ) ?
- drive->blockdev->blocks : 0xffffffffUL );
- ix86->regs.cx = ( blocks >> 16 );
- ix86->regs.dx = ( blocks & 0xffff );
- return INT13_DISK_TYPE_HDD;
-}
-
-/**
- * INT 13, 41 - Extensions installation check
- *
- * @v drive 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 *drive __unused,
- struct i386_all_regs *ix86 ) {
- if ( ix86->regs.bx == 0x55aa ) {
- DBG ( "INT 13 extensions installation check\n" );
- ix86->regs.bx = 0xaa55;
- ix86->regs.cx = INT13_EXTENSION_LINEAR;
- return INT13_EXTENSION_VER_1_X;
- } else {
- return -INT13_STATUS_INVALID;
- }
-}
-
-/**
- * Extended read / write
- *
- * @v drive Emulated drive
- * @v ds:si Disk address packet
- * @v io Read / write method
- * @ret status Status code
- */
-static int int13_extended_rw ( struct int13_drive *drive,
- struct i386_all_regs *ix86,
- int ( * io ) ( struct block_device *blockdev,
- uint64_t block,
- unsigned long count,
- userptr_t buffer ) ) {
- struct block_device *blockdev = drive->blockdev;
- struct int13_disk_address addr;
- uint64_t lba;
- unsigned long count;
- userptr_t buffer;
- int rc;
-
- /* Read parameters from disk address structure */
- copy_from_real ( &addr, ix86->segs.ds, ix86->regs.si, sizeof ( addr ));
- lba = addr.lba;
- count = addr.count;
- buffer = real_to_user ( addr.buffer.segment, addr.buffer.offset );
-
- DBG ( "LBA %#llx <-> %04x:%04x (count %ld)\n", (unsigned long long)lba,
- addr.buffer.segment, addr.buffer.offset, count );
-
- /* Read from / write to block device */
- if ( ( rc = io ( blockdev, lba, count, buffer ) ) != 0 ) {
- DBG ( "INT 13 failed: %s\n", strerror ( rc ) );
- return -INT13_STATUS_READ_ERROR;
- }
-
- return 0;
-}
-
-/**
- * INT 13, 42 - Extended read
- *
- * @v drive Emulated drive
- * @v ds:si Disk address packet
- * @ret status Status code
- */
-static int int13_extended_read ( struct int13_drive *drive,
- struct i386_all_regs *ix86 ) {
- DBG ( "Extended read: " );
- return int13_extended_rw ( drive, ix86, drive->blockdev->op->read );
-}
-
-/**
- * INT 13, 43 - Extended write
- *
- * @v drive Emulated drive
- * @v ds:si Disk address packet
- * @ret status Status code
- */
-static int int13_extended_write ( struct int13_drive *drive,
- struct i386_all_regs *ix86 ) {
- DBG ( "Extended write: " );
- return int13_extended_rw ( drive, ix86, drive->blockdev->op->write );
-}
-
-/**
- * INT 13, 48 - Get extended parameters
- *
- * @v drive Emulated drive
- * @v ds:si Drive parameter table
- * @ret status Status code
- */
-static int int13_get_extended_parameters ( struct int13_drive *drive,
- struct i386_all_regs *ix86 ) {
- struct int13_disk_parameters params = {
- .bufsize = sizeof ( params ),
- .flags = INT13_FL_DMA_TRANSPARENT,
- .cylinders = drive->cylinders,
- .heads = drive->heads,
- .sectors_per_track = drive->sectors_per_track,
- .sectors = drive->blockdev->blocks,
- .sector_size = drive->blockdev->blksize,
- };
-
- DBG ( "Get extended drive parameters to %04x:%04x\n",
- ix86->segs.ds, ix86->regs.si );
-
- copy_to_real ( ix86->segs.ds, ix86->regs.si, &params,
- sizeof ( params ) );
- 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 *drive;
- int status;
-
- /* Check BIOS hasn't killed off our drive */
- int13_check_num_drives();
-
- list_for_each_entry ( drive, &drives, list ) {
-
- if ( bios_drive != drive->drive ) {
- /* Remap any accesses to this drive's natural number */
- if ( bios_drive == drive->natural_drive ) {
- DBG ( "INT 13,%04x (%02x) remapped to "
- "(%02x)\n", ix86->regs.ax,
- bios_drive, drive->drive );
- ix86->regs.dl = drive->drive;
- return;
- }
- continue;
- }
-
- DBG ( "INT 13,%04x (%02x): ", ix86->regs.ax, drive->drive );
-
- switch ( command ) {
- case INT13_RESET:
- status = int13_reset ( drive, ix86 );
- break;
- case INT13_GET_LAST_STATUS:
- status = int13_get_last_status ( drive, ix86 );
- break;
- case INT13_READ_SECTORS:
- status = int13_read_sectors ( drive, ix86 );
- break;
- case INT13_WRITE_SECTORS:
- status = int13_write_sectors ( drive, ix86 );
- break;
- case INT13_GET_PARAMETERS:
- status = int13_get_parameters ( drive, ix86 );
- break;
- case INT13_GET_DISK_TYPE:
- status = int13_get_disk_type ( drive, ix86 );
- break;
- case INT13_EXTENSION_CHECK:
- status = int13_extension_check ( drive, ix86 );
- break;
- case INT13_EXTENDED_READ:
- status = int13_extended_read ( drive, ix86 );
- break;
- case INT13_EXTENDED_WRITE:
- status = int13_extended_write ( drive, ix86 );
- break;
- case INT13_GET_EXTENDED_PARAMETERS:
- status = int13_get_extended_parameters ( drive, ix86 );
- break;
- default:
- DBG ( "*** Unrecognised INT 13 ***\n" );
- status = -INT13_STATUS_INVALID;
- break;
- }
-
- /* Store status for INT 13,01 */
- drive->last_status = status;
-
- /* Negative status indicates an error */
- if ( status < 0 ) {
- status = -status;
- DBG ( "INT 13 returning failure status %x\n", 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 hook_int13 ( 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
- * INT 13,08 : load with number of drives
- * all others: restore original value
- */
- "cmpb $0x15, -1(%%bp)\n\t"
- "je 2f\n\t"
- "movb -4(%%bp), %%dl\n\t"
- "cmpb $0x08, -1(%%bp)\n\t"
- "jne 2f\n\t"
- "pushw %%ds\n\t"
- "pushw %1\n\t"
- "popw %%ds\n\t"
- "movb %c2, %%dl\n\t"
- "popw %%ds\n\t"
- /* Return */
- "\n2:\n\t"
- "movw %%bp, %%sp\n\t"
- "popw %%bp\n\t"
- "iret\n\t" )
- : : "i" ( int13 ), "i" ( BDA_SEG ), "i" ( BDA_NUM_DRIVES ) );
-
- hook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
- &int13_vector );
-}
-
-/**
- * Unhook INT 13 handler
- */
-static void unhook_int13 ( void ) {
- unhook_bios_interrupt ( 0x13, ( unsigned int ) int13_wrapper,
- &int13_vector );
-}
-
-/**
- * Guess INT 13 drive geometry
- *
- * @v drive Emulated drive
- *
- * Guesses the drive geometry by inspecting the partition table.
- */
-static void guess_int13_geometry ( struct int13_drive *drive ) {
- struct master_boot_record mbr;
- struct partition_table_entry *partition;
- unsigned int guessed_heads = 255;
- unsigned int guessed_sectors_per_track = 63;
- unsigned long blocks;
- unsigned long blocks_per_cyl;
- unsigned int i;
-
- /* Don't even try when the blksize is invalid for C/H/S access */
- if ( drive->blockdev->blksize != INT13_BLKSIZE )
- return;
-
- /* Scan through partition table and modify guesses for heads
- * and sectors_per_track if we find any used partitions.
- */
- if ( drive->blockdev->op->read ( drive->blockdev, 0, 1,
- virt_to_user ( &mbr ) ) == 0 ) {
- for ( i = 0 ; i < 4 ; i++ ) {
- partition = &mbr.partitions[i];
- if ( ! partition->type )
- continue;
- guessed_heads =
- ( PART_HEAD ( partition->chs_end ) + 1 );
- guessed_sectors_per_track =
- PART_SECTOR ( partition->chs_end );
- DBG ( "Guessing C/H/S xx/%d/%d based on partition "
- "%d\n", guessed_heads,
- guessed_sectors_per_track, ( i + 1 ) );
- }
- } else {
- DBG ( "Could not read partition table to guess geometry\n" );
- }
-
- /* Apply guesses if no geometry already specified */
- if ( ! drive->heads )
- drive->heads = guessed_heads;
- if ( ! drive->sectors_per_track )
- drive->sectors_per_track = guessed_sectors_per_track;
- if ( ! drive->cylinders ) {
- /* Avoid attempting a 64-bit divide on a 32-bit system */
- blocks = ( ( drive->blockdev->blocks <= ULONG_MAX ) ?
- drive->blockdev->blocks : ULONG_MAX );
- blocks_per_cyl = ( drive->heads * drive->sectors_per_track );
- assert ( blocks_per_cyl != 0 );
- drive->cylinders = ( blocks / blocks_per_cyl );
- if ( drive->cylinders > 1024 )
- drive->cylinders = 1024;
- }
-}
-
-/**
- * Register INT 13 emulated drive
- *
- * @v drive Emulated drive
- *
- * Registers the drive with the INT 13 emulation subsystem, and hooks
- * the INT 13 interrupt vector (if not already hooked).
- *
- * The underlying block device must be valid. A drive number and
- * geometry will be assigned if left blank.
- */
-void register_int13_drive ( struct int13_drive *drive ) {
- uint8_t num_drives;
-
- /* Give drive a default geometry if none specified */
- guess_int13_geometry ( drive );
-
- /* Assign natural drive number */
- get_real ( num_drives, BDA_SEG, BDA_NUM_DRIVES );
- drive->natural_drive = ( num_drives | 0x80 );
-
- /* Assign drive number */
- if ( ( drive->drive & 0xff ) == 0xff ) {
- /* Drive number == -1 => use natural drive number */
- drive->drive = drive->natural_drive;
- } else {
- /* Use specified drive number (+0x80 if necessary) */
- drive->drive |= 0x80;
- }
-
- DBG ( "Registered INT13 drive %02x (naturally %02x) with C/H/S "
- "geometry %d/%d/%d\n", drive->drive, drive->natural_drive,
- drive->cylinders, drive->heads, drive->sectors_per_track );
-
- /* Hook INT 13 vector if not already hooked */
- if ( list_empty ( &drives ) )
- hook_int13();
-
- /* Add to list of emulated drives */
- list_add ( &drive->list, &drives );
-
- /* Update BIOS drive count */
- int13_set_num_drives();
-}
-
-/**
- * Unregister INT 13 emulated drive
- *
- * @v drive Emulated drive
- *
- * Unregisters the drive from the INT 13 emulation subsystem. If this
- * is the last emulated drive, the INT 13 vector is unhooked (if
- * possible).
- */
-void unregister_int13_drive ( struct int13_drive *drive ) {
- /* Remove from list of emulated drives */
- list_del ( &drive->list );
-
- /* Should adjust BIOS drive count, but it's difficult to do so
- * reliably.
- */
-
- DBG ( "Unregistered INT13 drive %02x\n", drive->drive );
-
- /* Unhook INT 13 vector if no more drives */
- if ( list_empty ( &drives ) )
- unhook_int13();
-}
-
-/**
- * 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.
- */
-int int13_boot ( unsigned int drive ) {
- struct memory_map memmap;
- int status, signature;
- int discard_c, discard_d;
- int rc;
-
- DBG ( "Booting from INT 13 drive %02x\n", drive );
-
- /* Use INT 13 to read the boot sector */
- __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
- "pushw $0\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"
- "xorl %%eax, %%eax\n\t"
- "\n1:\n\t"
- "movzwl %%es:0x7dfe, %%ebx\n\t"
- "popw %%es\n\t" )
- : "=a" ( status ), "=b" ( signature ),
- "=c" ( discard_c ), "=d" ( discard_d )
- : "a" ( 0x0201 ), "b" ( 0x7c00 ),
- "c" ( 1 ), "d" ( drive ) );
- if ( status )
- return -EIO;
-
- /* Check signature is correct */
- if ( signature != be16_to_cpu ( 0x55aa ) ) {
- DBG ( "Invalid disk signature %#04x (should be 0x55aa)\n",
- cpu_to_be16 ( signature ) );
- return -ENOEXEC;
- }
-
- /* 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 ( 0x0, 0x7c00, drive ) ) != 0 ) {
- DBG ( "INT 13 drive %02x boot returned: %s\n",
- drive, strerror ( rc ) );
- return rc;
- }
-
- return -ECANCELED; /* -EIMPOSSIBLE */
-}
diff --git a/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c b/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c
deleted file mode 100644
index 00efd8ff..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/iscsiboot.c
+++ /dev/null
@@ -1,75 +0,0 @@
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <gpxe/iscsi.h>
-#include <gpxe/netdevice.h>
-#include <gpxe/ibft.h>
-#include <gpxe/sanboot.h>
-#include <int13.h>
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-static int iscsiboot ( const char *root_path ) {
- struct scsi_device *scsi;
- struct int13_drive *drive;
- int rc;
-
- scsi = zalloc ( sizeof ( *scsi ) );
- if ( ! scsi ) {
- rc = -ENOMEM;
- goto err_alloc_scsi;
- }
- drive = zalloc ( sizeof ( *drive ) );
- if ( ! drive ) {
- rc = -ENOMEM;
- goto err_alloc_drive;
- }
-
- if ( ( rc = iscsi_attach ( scsi, root_path ) ) != 0 ) {
- printf ( "Could not attach iSCSI device: %s\n",
- strerror ( rc ) );
- goto err_attach;
- }
- if ( ( rc = init_scsidev ( scsi ) ) != 0 ) {
- printf ( "Could not initialise iSCSI device: %s\n",
- strerror ( rc ) );
- goto err_init;
- }
-
- drive->blockdev = &scsi->blockdev;
-
- /* FIXME: ugly, ugly hack */
- struct net_device *netdev = last_opened_netdev();
- struct iscsi_session *iscsi =
- container_of ( scsi->backend, struct iscsi_session, refcnt );
- ibft_fill_data ( netdev, iscsi );
-
- register_int13_drive ( drive );
- printf ( "Registered as BIOS drive %#02x\n", drive->drive );
- printf ( "Booting from BIOS drive %#02x\n", drive->drive );
- rc = int13_boot ( drive->drive );
- printf ( "Boot failed\n" );
-
- /* Leave drive registered, if instructed to do so */
- if ( keep_san() )
- return rc;
-
- printf ( "Unregistering BIOS drive %#02x\n", drive->drive );
- unregister_int13_drive ( drive );
-
- err_init:
- iscsi_detach ( scsi );
- err_attach:
- free ( drive );
- err_alloc_drive:
- free ( scsi );
- err_alloc_scsi:
- return rc;
-}
-
-struct sanboot_protocol iscsi_sanboot_protocol __sanboot_protocol = {
- .prefix = "iscsi:",
- .boot = iscsiboot,
-};
diff --git a/gpxe/src/arch/i386/interface/pcbios/keepsan.c b/gpxe/src/arch/i386/interface/pcbios/keepsan.c
deleted file mode 100644
index 904e017d..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/keepsan.c
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <stdint.h>
-#include <stdio.h>
-#include <gpxe/settings.h>
-#include <gpxe/dhcp.h>
-#include <gpxe/init.h>
-#include <gpxe/sanboot.h>
-#include <usr/autoboot.h>
-
-struct setting keep_san_setting __setting = {
- .name = "keep-san",
- .description = "Preserve SAN connection",
- .tag = DHCP_EB_KEEP_SAN,
- .type = &setting_type_int8,
-};
-
-int keep_san ( void ) {
- int keep_san;
-
- keep_san = fetch_intz_setting ( NULL, &keep_san_setting );
- if ( ! keep_san )
- return 0;
-
- printf ( "Preserving connection to SAN disk\n" );
- shutdown_exit_flags |= SHUTDOWN_KEEP_DEVICES;
- return 1;
-}
diff --git a/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c b/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
deleted file mode 100644
index 0645fe63..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/memtop_umalloc.c
+++ /dev/null
@@ -1,202 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-/**
- * @file
- *
- * External memory allocation
- *
- */
-
-#include <limits.h>
-#include <errno.h>
-#include <gpxe/uaccess.h>
-#include <gpxe/hidemem.h>
-#include <gpxe/memmap.h>
-#include <gpxe/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;
-
-/**
- * Initialise external heap
- *
- * @ret rc Return status code
- */
-static int init_eheap ( void ) {
- struct memory_map memmap;
- unsigned long heap_size = 0;
- unsigned int i;
-
- DBG ( "Allocating external heap\n" );
-
- get_memmap ( &memmap );
- for ( i = 0 ; i < memmap.count ; i++ ) {
- struct memory_region *region = &memmap.regions[i];
- unsigned long r_start, r_end;
- unsigned long r_size;
-
- DBG ( "Considering [%llx,%llx)\n", region->start, region->end);
-
- /* Truncate block to 4GB */
- if ( region->start > UINT_MAX ) {
- DBG ( "...starts after 4GB\n" );
- continue;
- }
- r_start = region->start;
- if ( region->end > UINT_MAX ) {
- DBG ( "...end truncated to 4GB\n" );
- r_end = 0; /* =4GB, given the wraparound */
- } else {
- r_end = region->end;
- }
-
- /* Use largest block */
- r_size = ( r_end - r_start );
- if ( r_size > heap_size ) {
- DBG ( "...new best block found\n" );
- top = bottom = phys_to_user ( r_end );
- heap_size = r_size;
- }
- }
-
- if ( ! heap_size ) {
- DBG ( "No external heap available\n" );
- return -ENOMEM;
- }
-
- DBG ( "External heap grows downwards from %lx\n",
- user_to_phys ( top, 0 ) );
- return 0;
-}
-
-/**
- * Collect free blocks
- *
- */
-static void ecollect_free ( void ) {
- struct external_memory extmem;
-
- /* 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 ) );
- bottom = userptr_add ( bottom,
- ( extmem.size + sizeof ( extmem ) ) );
- }
-}
-
-/**
- * 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;
- int rc;
-
- /* Initialise external memory allocator if necessary */
- if ( bottom == top ) {
- if ( ( rc = init_eheap() ) != 0 )
- return UNULL;
- }
-
- /* 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 */
- ptr = bottom = userptr_add ( bottom, -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 */
- 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 ) );
- extmem.size = new_size;
- bottom = new;
- } 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, -sizeof ( extmem ) ),
- user_to_phys ( top, 0 ) );
-
- return ( new_size ? new : UNOWHERE );
-}
-
-PROVIDE_UMALLOC ( memtop, urealloc, memtop_urealloc );
diff --git a/gpxe/src/arch/i386/interface/pcbios/pcibios.c b/gpxe/src/arch/i386/interface/pcbios/pcibios.c
deleted file mode 100644
index f2c3880c..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/pcibios.c
+++ /dev/null
@@ -1,115 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdint.h>
-#include <gpxe/pci.h>
-#include <realmode.h>
-
-/** @file
- *
- * PCI configuration space access via PCI BIOS
- *
- */
-
-/**
- * Determine maximum PCI bus number within system
- *
- * @ret max_bus Maximum bus number
- */
-static int pcibios_max_bus ( void ) {
- int discard_a, discard_D;
- uint8_t max_bus;
-
- __asm__ __volatile__ ( REAL_CODE ( "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;
-}
-
-/**
- * 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 ( pci->bus, pci->devfn ) )
- : "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 ( pci->bus, pci->devfn ) ),
- "c" ( value )
- : "edx" );
-
- return ( ( status >> 8 ) & 0xff );
-}
-
-PROVIDE_PCIAPI ( pcbios, pci_max_bus, pcibios_max_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/gpxe/src/arch/i386/interface/pcbios/sbft.c b/gpxe/src/arch/i386/interface/pcbios/sbft.c
deleted file mode 100644
index 12927c77..00000000
--- a/gpxe/src/arch/i386/interface/pcbios/sbft.c
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2009 Fen Systems Ltd <mbrown@fensystems.co.uk>.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-FILE_LICENCE ( BSD2 );
-
-/** @file
- *
- * SRP boot firmware table
- *
- */
-
-#include <assert.h>
-#include <realmode.h>
-#include <gpxe/srp.h>
-#include <gpxe/ib_srp.h>
-#include <gpxe/acpi.h>
-#include <gpxe/sbft.h>
-
-#define sbftab __use_data16 ( sbftab )
-/** The sBFT used by gPXE */
-struct gpxe_sbft __data16 ( sbftab ) = {
- /* Table header */
- .table = {
- /* ACPI header */
- .acpi = {
- .signature = SBFT_SIG,
- .length = sizeof ( sbftab ),
- .revision = 1,
- .oem_id = "FENSYS",
- .oem_table_id = "gPXE",
- },
- .scsi_offset = offsetof ( typeof ( sbftab ), scsi ),
- .srp_offset = offsetof ( typeof ( sbftab ), srp ),
- .ib_offset = offsetof ( typeof ( sbftab ), ib ),
- },
-};
-
-/**
- * Fill in all variable portions of sBFT
- *
- * @v srp SRP device
- * @ret rc Return status code
- */
-int sbft_fill_data ( struct srp_device *srp ) {
- struct sbft_scsi_subtable *sbft_scsi = &sbftab.scsi;
- struct sbft_srp_subtable *sbft_srp = &sbftab.srp;
- struct sbft_ib_subtable *sbft_ib = &sbftab.ib;
- struct ib_srp_parameters *ib_params;
- struct segoff rm_sbftab = {
- .segment = rm_ds,
- .offset = __from_data16 ( &sbftab ),
- };
-
- /* Fill in the SCSI subtable */
- memcpy ( &sbft_scsi->lun, &srp->lun, sizeof ( sbft_scsi->lun ) );
-
- /* Fill in the SRP subtable */
- memcpy ( &sbft_srp->port_ids, &srp->port_ids,
- sizeof ( sbft_srp->port_ids ) );
-
- /* Fill in the IB subtable */
- assert ( srp->transport == &ib_srp_transport );
- ib_params = ib_srp_params ( srp );
- memcpy ( &sbft_ib->sgid, &ib_params->sgid, sizeof ( sbft_ib->sgid ) );
- memcpy ( &sbft_ib->dgid, &ib_params->dgid, sizeof ( sbft_ib->dgid ) );
- memcpy ( &sbft_ib->service_id, &ib_params->service_id,
- sizeof ( sbft_ib->service_id ) );
- sbft_ib->pkey = ib_params->pkey;
-
- /* Update checksum */
- acpi_fix_checksum ( &sbftab.table.acpi );
-
- DBGC ( &sbftab, "SRP Boot Firmware Table at %04x:%04x:\n",
- rm_sbftab.segment, rm_sbftab.offset );
- DBGC_HDA ( &sbftab, rm_sbftab, &sbftab, sizeof ( sbftab ) );
-
- return 0;
-}
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_call.c b/gpxe/src/arch/i386/interface/pxe/pxe_call.c
deleted file mode 100644
index 66a9b1e2..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_call.c
+++ /dev/null
@@ -1,509 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <gpxe/uaccess.h>
-#include <gpxe/init.h>
-#include <registers.h>
-#include <biosint.h>
-#include <pxe.h>
-#include <pxe_call.h>
-
-/** @file
- *
- * PXE API entry point
- */
-
-/** 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;
-
-/** A function pointer to hold any PXE API call
- *
- * Used by pxe_api_call() to avoid large swathes of duplicated code.
- */
-union pxenv_call {
- PXENV_EXIT_t ( * any ) ( union u_PXENV_ANY * );
- PXENV_EXIT_t ( * unknown ) ( struct s_PXENV_UNKNOWN * );
- PXENV_EXIT_t ( * unload_stack ) ( struct s_PXENV_UNLOAD_STACK * );
- PXENV_EXIT_t ( * get_cached_info )
- ( struct s_PXENV_GET_CACHED_INFO * );
- PXENV_EXIT_t ( * restart_tftp ) ( struct s_PXENV_TFTP_READ_FILE * );
- PXENV_EXIT_t ( * start_undi ) ( struct s_PXENV_START_UNDI * );
- PXENV_EXIT_t ( * stop_undi ) ( struct s_PXENV_STOP_UNDI * );
- PXENV_EXIT_t ( * start_base ) ( struct s_PXENV_START_BASE * );
- PXENV_EXIT_t ( * stop_base ) ( struct s_PXENV_STOP_BASE * );
- PXENV_EXIT_t ( * tftp_open ) ( struct s_PXENV_TFTP_OPEN * );
- PXENV_EXIT_t ( * tftp_close ) ( struct s_PXENV_TFTP_CLOSE * );
- PXENV_EXIT_t ( * tftp_read ) ( struct s_PXENV_TFTP_READ * );
- PXENV_EXIT_t ( * tftp_read_file ) ( struct s_PXENV_TFTP_READ_FILE * );
- PXENV_EXIT_t ( * tftp_get_fsize ) ( struct s_PXENV_TFTP_GET_FSIZE * );
- PXENV_EXIT_t ( * udp_open ) ( struct s_PXENV_UDP_OPEN * );
- PXENV_EXIT_t ( * udp_close ) ( struct s_PXENV_UDP_CLOSE * );
- PXENV_EXIT_t ( * udp_write ) ( struct s_PXENV_UDP_WRITE * );
- PXENV_EXIT_t ( * udp_read ) ( struct s_PXENV_UDP_READ * );
- PXENV_EXIT_t ( * undi_startup ) ( struct s_PXENV_UNDI_STARTUP * );
- PXENV_EXIT_t ( * undi_cleanup ) ( struct s_PXENV_UNDI_CLEANUP * );
- PXENV_EXIT_t ( * undi_initialize )
- ( struct s_PXENV_UNDI_INITIALIZE * );
- PXENV_EXIT_t ( * undi_reset_adapter ) ( struct s_PXENV_UNDI_RESET * );
- PXENV_EXIT_t ( * undi_shutdown ) ( struct s_PXENV_UNDI_SHUTDOWN * );
- PXENV_EXIT_t ( * undi_open ) ( struct s_PXENV_UNDI_OPEN * );
- PXENV_EXIT_t ( * undi_close ) ( struct s_PXENV_UNDI_CLOSE * );
- PXENV_EXIT_t ( * undi_transmit ) ( struct s_PXENV_UNDI_TRANSMIT * );
- PXENV_EXIT_t ( * undi_set_mcast_address )
- ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS * );
- PXENV_EXIT_t ( * undi_set_station_address )
- ( struct s_PXENV_UNDI_SET_STATION_ADDRESS * );
- PXENV_EXIT_t ( * undi_set_packet_filter )
- ( struct s_PXENV_UNDI_SET_PACKET_FILTER * );
- PXENV_EXIT_t ( * undi_get_information )
- ( struct s_PXENV_UNDI_GET_INFORMATION * );
- PXENV_EXIT_t ( * undi_get_statistics )
- ( struct s_PXENV_UNDI_GET_STATISTICS * );
- PXENV_EXIT_t ( * undi_clear_statistics )
- ( struct s_PXENV_UNDI_CLEAR_STATISTICS * );
- PXENV_EXIT_t ( * undi_initiate_diags )
- ( struct s_PXENV_UNDI_INITIATE_DIAGS * );
- PXENV_EXIT_t ( * undi_force_interrupt )
- ( struct s_PXENV_UNDI_FORCE_INTERRUPT * );
- PXENV_EXIT_t ( * undi_get_mcast_address )
- ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS * );
- PXENV_EXIT_t ( * undi_get_nic_type )
- ( struct s_PXENV_UNDI_GET_NIC_TYPE * );
- PXENV_EXIT_t ( * undi_get_iface_info )
- ( struct s_PXENV_UNDI_GET_IFACE_INFO * );
- PXENV_EXIT_t ( * undi_get_state ) ( struct s_PXENV_UNDI_GET_STATE * );
- PXENV_EXIT_t ( * undi_isr ) ( struct s_PXENV_UNDI_ISR * );
- PXENV_EXIT_t ( * file_open ) ( struct s_PXENV_FILE_OPEN * );
- PXENV_EXIT_t ( * file_close ) ( struct s_PXENV_FILE_CLOSE * );
- PXENV_EXIT_t ( * file_select ) ( struct s_PXENV_FILE_SELECT * );
- PXENV_EXIT_t ( * file_read ) ( struct s_PXENV_FILE_READ * );
- PXENV_EXIT_t ( * get_file_size ) ( struct s_PXENV_GET_FILE_SIZE * );
- PXENV_EXIT_t ( * file_exec ) ( struct s_PXENV_FILE_EXEC * );
- PXENV_EXIT_t ( * file_api_check ) ( struct s_PXENV_FILE_API_CHECK * );
- PXENV_EXIT_t ( * file_exit_hook ) ( struct s_PXENV_FILE_EXIT_HOOK * );
-};
-
-/**
- * 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;
-}
-
-/**
- * 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 ) {
- int opcode = ix86->regs.bx;
- userptr_t parameters = real_to_user ( ix86->segs.es, ix86->regs.di );
- size_t param_len;
- union u_PXENV_ANY pxenv_any;
- union pxenv_call pxenv_call;
- PXENV_EXIT_t ret;
-
- switch ( opcode ) {
- case PXENV_UNLOAD_STACK:
- pxenv_call.unload_stack = pxenv_unload_stack;
- param_len = sizeof ( pxenv_any.unload_stack );
- break;
- case PXENV_GET_CACHED_INFO:
- pxenv_call.get_cached_info = pxenv_get_cached_info;
- param_len = sizeof ( pxenv_any.get_cached_info );
- break;
- case PXENV_RESTART_TFTP:
- pxenv_call.restart_tftp = pxenv_restart_tftp;
- param_len = sizeof ( pxenv_any.restart_tftp );
- break;
- case PXENV_START_UNDI:
- pxenv_call.start_undi = pxenv_start_undi;
- param_len = sizeof ( pxenv_any.start_undi );
- break;
- case PXENV_STOP_UNDI:
- pxenv_call.stop_undi = pxenv_stop_undi;
- param_len = sizeof ( pxenv_any.stop_undi );
- break;
- case PXENV_START_BASE:
- pxenv_call.start_base = pxenv_start_base;
- param_len = sizeof ( pxenv_any.start_base );
- break;
- case PXENV_STOP_BASE:
- pxenv_call.stop_base = pxenv_stop_base;
- param_len = sizeof ( pxenv_any.stop_base );
- break;
- case PXENV_TFTP_OPEN:
- pxenv_call.tftp_open = pxenv_tftp_open;
- param_len = sizeof ( pxenv_any.tftp_open );
- break;
- case PXENV_TFTP_CLOSE:
- pxenv_call.tftp_close = pxenv_tftp_close;
- param_len = sizeof ( pxenv_any.tftp_close );
- break;
- case PXENV_TFTP_READ:
- pxenv_call.tftp_read = pxenv_tftp_read;
- param_len = sizeof ( pxenv_any.tftp_read );
- break;
- case PXENV_TFTP_READ_FILE:
- pxenv_call.tftp_read_file = pxenv_tftp_read_file;
- param_len = sizeof ( pxenv_any.tftp_read_file );
- break;
- case PXENV_TFTP_GET_FSIZE:
- pxenv_call.tftp_get_fsize = pxenv_tftp_get_fsize;
- param_len = sizeof ( pxenv_any.tftp_get_fsize );
- break;
- case PXENV_UDP_OPEN:
- pxenv_call.udp_open = pxenv_udp_open;
- param_len = sizeof ( pxenv_any.udp_open );
- break;
- case PXENV_UDP_CLOSE:
- pxenv_call.udp_close = pxenv_udp_close;
- param_len = sizeof ( pxenv_any.udp_close );
- break;
- case PXENV_UDP_WRITE:
- pxenv_call.udp_write = pxenv_udp_write;
- param_len = sizeof ( pxenv_any.udp_write );
- break;
- case PXENV_UDP_READ:
- pxenv_call.udp_read = pxenv_udp_read;
- param_len = sizeof ( pxenv_any.udp_read );
- break;
- case PXENV_UNDI_STARTUP:
- pxenv_call.undi_startup = pxenv_undi_startup;
- param_len = sizeof ( pxenv_any.undi_startup );
- break;
- case PXENV_UNDI_CLEANUP:
- pxenv_call.undi_cleanup = pxenv_undi_cleanup;
- param_len = sizeof ( pxenv_any.undi_cleanup );
- break;
- case PXENV_UNDI_INITIALIZE:
- pxenv_call.undi_initialize = pxenv_undi_initialize;
- param_len = sizeof ( pxenv_any.undi_initialize );
- break;
- case PXENV_UNDI_RESET_ADAPTER:
- pxenv_call.undi_reset_adapter = pxenv_undi_reset_adapter;
- param_len = sizeof ( pxenv_any.undi_reset_adapter );
- break;
- case PXENV_UNDI_SHUTDOWN:
- pxenv_call.undi_shutdown = pxenv_undi_shutdown;
- param_len = sizeof ( pxenv_any.undi_shutdown );
- break;
- case PXENV_UNDI_OPEN:
- pxenv_call.undi_open = pxenv_undi_open;
- param_len = sizeof ( pxenv_any.undi_open );
- break;
- case PXENV_UNDI_CLOSE:
- pxenv_call.undi_close = pxenv_undi_close;
- param_len = sizeof ( pxenv_any.undi_close );
- break;
- case PXENV_UNDI_TRANSMIT:
- pxenv_call.undi_transmit = pxenv_undi_transmit;
- param_len = sizeof ( pxenv_any.undi_transmit );
- break;
- case PXENV_UNDI_SET_MCAST_ADDRESS:
- pxenv_call.undi_set_mcast_address =
- pxenv_undi_set_mcast_address;
- param_len = sizeof ( pxenv_any.undi_set_mcast_address );
- break;
- case PXENV_UNDI_SET_STATION_ADDRESS:
- pxenv_call.undi_set_station_address =
- pxenv_undi_set_station_address;
- param_len = sizeof ( pxenv_any.undi_set_station_address );
- break;
- case PXENV_UNDI_SET_PACKET_FILTER:
- pxenv_call.undi_set_packet_filter =
- pxenv_undi_set_packet_filter;
- param_len = sizeof ( pxenv_any.undi_set_packet_filter );
- break;
- case PXENV_UNDI_GET_INFORMATION:
- pxenv_call.undi_get_information = pxenv_undi_get_information;
- param_len = sizeof ( pxenv_any.undi_get_information );
- break;
- case PXENV_UNDI_GET_STATISTICS:
- pxenv_call.undi_get_statistics = pxenv_undi_get_statistics;
- param_len = sizeof ( pxenv_any.undi_get_statistics );
- break;
- case PXENV_UNDI_CLEAR_STATISTICS:
- pxenv_call.undi_clear_statistics = pxenv_undi_clear_statistics;
- param_len = sizeof ( pxenv_any.undi_clear_statistics );
- break;
- case PXENV_UNDI_INITIATE_DIAGS:
- pxenv_call.undi_initiate_diags = pxenv_undi_initiate_diags;
- param_len = sizeof ( pxenv_any.undi_initiate_diags );
- break;
- case PXENV_UNDI_FORCE_INTERRUPT:
- pxenv_call.undi_force_interrupt = pxenv_undi_force_interrupt;
- param_len = sizeof ( pxenv_any.undi_force_interrupt );
- break;
- case PXENV_UNDI_GET_MCAST_ADDRESS:
- pxenv_call.undi_get_mcast_address =
- pxenv_undi_get_mcast_address;
- param_len = sizeof ( pxenv_any.undi_get_mcast_address );
- break;
- case PXENV_UNDI_GET_NIC_TYPE:
- pxenv_call.undi_get_nic_type = pxenv_undi_get_nic_type;
- param_len = sizeof ( pxenv_any.undi_get_nic_type );
- break;
- case PXENV_UNDI_GET_IFACE_INFO:
- pxenv_call.undi_get_iface_info = pxenv_undi_get_iface_info;
- param_len = sizeof ( pxenv_any.undi_get_iface_info );
- break;
- case PXENV_UNDI_ISR:
- pxenv_call.undi_isr = pxenv_undi_isr;
- param_len = sizeof ( pxenv_any.undi_isr );
- break;
- case PXENV_FILE_OPEN:
- pxenv_call.file_open = pxenv_file_open;
- param_len = sizeof ( pxenv_any.file_open );
- break;
- case PXENV_FILE_CLOSE:
- pxenv_call.file_close = pxenv_file_close;
- param_len = sizeof ( pxenv_any.file_close );
- break;
- case PXENV_FILE_SELECT:
- pxenv_call.file_select = pxenv_file_select;
- param_len = sizeof ( pxenv_any.file_select );
- break;
- case PXENV_FILE_READ:
- pxenv_call.file_read = pxenv_file_read;
- param_len = sizeof ( pxenv_any.file_read );
- break;
- case PXENV_GET_FILE_SIZE:
- pxenv_call.get_file_size = pxenv_get_file_size;
- param_len = sizeof ( pxenv_any.get_file_size );
- break;
- case PXENV_FILE_EXEC:
- pxenv_call.file_exec = pxenv_file_exec;
- param_len = sizeof ( pxenv_any.file_exec );
- break;
- case PXENV_FILE_API_CHECK:
- pxenv_call.file_api_check = pxenv_file_api_check;
- param_len = sizeof ( pxenv_any.file_api_check );
- break;
- case PXENV_FILE_EXIT_HOOK:
- pxenv_call.file_exit_hook = pxenv_file_exit_hook;
- param_len = sizeof ( pxenv_any.file_exit_hook );
- break;
- default:
- DBG ( "PXENV_UNKNOWN_%hx", opcode );
- pxenv_call.unknown = pxenv_unknown;
- param_len = sizeof ( pxenv_any.unknown );
- break;
- }
-
- /* Copy parameter block from caller */
- copy_from_user ( &pxenv_any, parameters, 0, param_len );
-
- /* Set default status in case child routine fails to do so */
- pxenv_any.Status = PXENV_STATUS_FAILURE;
-
- /* Hand off to relevant API routine */
- DBG ( "[" );
- ret = pxenv_call.any ( &pxenv_any );
- if ( pxenv_any.Status != PXENV_STATUS_SUCCESS ) {
- DBG ( " %02x", pxenv_any.Status );
- }
- if ( ret != PXENV_EXIT_SUCCESS ) {
- DBG ( ret == PXENV_EXIT_FAILURE ? " err" : " ??" );
- }
- DBG ( "]" );
-
- /* Copy modified parameter block back to caller and return */
- copy_to_user ( parameters, 0, &pxenv_any, param_len );
- ix86->regs.ax = ret;
-}
-
-/**
- * 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 );
- 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;
- }
- int_1a_hooked = 0;
- }
-
- return 0;
-}
-
-/**
- * Start PXE NBP at 0000:7c00
- *
- * @ret rc Return status code
- */
-int pxe_start_nbp ( void ) {
- int discard_b, discard_c, discard_d, discard_D;
- uint16_t rc;
-
- /* Far call to PXE NBP */
- __asm__ __volatile__ ( REAL_CODE ( "movw %%cx, %%es\n\t"
- "pushw %%es\n\t"
- "pushw %%di\n\t"
- "sti\n\t"
- "lcall $0, $0x7c00\n\t"
- "addw $4, %%sp\n\t" )
- : "=a" ( rc ), "=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", "ebp", "memory" );
-
- return rc;
-}
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_entry.S b/gpxe/src/arch/i386/interface/pxe/pxe_entry.S
deleted file mode 100644
index 0d3a57cd..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_entry.S
+++ /dev/null
@@ -1,216 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER )
-
- .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/gpxe/src/arch/i386/interface/pxe/pxe_errors.c b/gpxe/src/arch/i386/interface/pxe/pxe_errors.c
deleted file mode 100644
index f884ef8a..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_errors.c
+++ /dev/null
@@ -1,103 +0,0 @@
-#include <errno.h>
-#include <gpxe/errortab.h>
-
-/*
- * This table was generated from the relevant section of errno.h using
- *
- * perl -ne 'if ( /(PXENV_STATUS_(\S+))/ ) {
- * $code = $1; $msg = $2;
- * $msg =~ s/_/ /g; $msg = ucfirst lc $msg;
- * $msg =~ s/(tftp|udp|arp|undi|bis|binl|pxenv|pxe|dhcp)/uc $1/ieg;
- * print "\t{ $code, \"$msg\" },\n";
- * }'
- *
- * followed by a little manual tweaking.
- *
- */
-struct errortab pxe_errortab[] __errortab = {
- { PXENV_STATUS_SUCCESS, "Success" },
- { PXENV_STATUS_FAILURE, "Failure" },
- { PXENV_STATUS_BAD_FUNC, "Bad function" },
- { PXENV_STATUS_UNSUPPORTED, "Unsupported function" },
- { PXENV_STATUS_KEEP_UNDI, "Keep UNDI" },
- { PXENV_STATUS_KEEP_ALL, "Keep all" },
- { PXENV_STATUS_OUT_OF_RESOURCES, "Out of resources" },
- { PXENV_STATUS_ARP_TIMEOUT, "ARP timeout" },
- { PXENV_STATUS_UDP_CLOSED, "UDP closed" },
- { PXENV_STATUS_UDP_OPEN, "UDP open" },
- { PXENV_STATUS_TFTP_CLOSED, "TFTP closed" },
- { PXENV_STATUS_TFTP_OPEN, "TFTP open" },
- { PXENV_STATUS_MCOPY_PROBLEM, "Memory copy problem" },
- { PXENV_STATUS_BIS_INTEGRITY_FAILURE, "BIS integrity failure" },
- { PXENV_STATUS_BIS_VALIDATE_FAILURE, "BIS validation failure" },
- { PXENV_STATUS_BIS_INIT_FAILURE, "BIS init failure" },
- { PXENV_STATUS_BIS_SHUTDOWN_FAILURE, "BIS shutdown failure" },
- { PXENV_STATUS_BIS_GBOA_FAILURE, "BIS GBOA failure" },
- { PXENV_STATUS_BIS_FREE_FAILURE, "BIS free failure" },
- { PXENV_STATUS_BIS_GSI_FAILURE, "BIS GSI failure" },
- { PXENV_STATUS_BIS_BAD_CKSUM, "BIS bad checksum" },
- { PXENV_STATUS_TFTP_CANNOT_ARP_ADDRESS, "TFTP cannot ARP address" },
- { PXENV_STATUS_TFTP_OPEN_TIMEOUT, "TFTP open timeout" },
- { PXENV_STATUS_TFTP_UNKNOWN_OPCODE, "TFTP unknown opcode" },
- { PXENV_STATUS_TFTP_READ_TIMEOUT, "TFTP read timeout" },
- { PXENV_STATUS_TFTP_ERROR_OPCODE, "TFTP error opcode" },
- { PXENV_STATUS_TFTP_CANNOT_OPEN_CONNECTION,
- "TFTP cannot open connection" },
- { PXENV_STATUS_TFTP_CANNOT_READ_FROM_CONNECTION,
- "TFTP cannot read from connection" },
- { PXENV_STATUS_TFTP_TOO_MANY_PACKAGES, "TFTP too many packages" },
- { PXENV_STATUS_TFTP_FILE_NOT_FOUND, "TFTP file not found" },
- { PXENV_STATUS_TFTP_ACCESS_VIOLATION, "TFTP access violation" },
- { PXENV_STATUS_TFTP_NO_MCAST_ADDRESS, "TFTP no mcast address" },
- { PXENV_STATUS_TFTP_NO_FILESIZE, "TFTP no filesize" },
- { PXENV_STATUS_TFTP_INVALID_PACKET_SIZE, "TFTP invalid packet size" },
- { PXENV_STATUS_DHCP_TIMEOUT, "DHCP timeout" },
- { PXENV_STATUS_DHCP_NO_IP_ADDRESS, "DHCP no ip address" },
- { PXENV_STATUS_DHCP_NO_BOOTFILE_NAME, "DHCP no bootfile name" },
- { PXENV_STATUS_DHCP_BAD_IP_ADDRESS, "DHCP bad ip address" },
- { PXENV_STATUS_UNDI_INVALID_FUNCTION, "UNDI invalid function" },
- { PXENV_STATUS_UNDI_MEDIATEST_FAILED, "UNDI mediatest failed" },
- { PXENV_STATUS_UNDI_CANNOT_INIT_NIC_FOR_MCAST,
- "UNDI cannot initialise NIC for multicast" },
- { PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC,
- "UNDI cannot initialise NIC" },
- { PXENV_STATUS_UNDI_CANNOT_INITIALIZE_PHY,
- "UNDI cannot initialise PHY" },
- { PXENV_STATUS_UNDI_CANNOT_READ_CONFIG_DATA,
- "UNDI cannot read config data" },
- { PXENV_STATUS_UNDI_CANNOT_READ_INIT_DATA,
- "UNDI cannot read init data" },
- { PXENV_STATUS_UNDI_BAD_MAC_ADDRESS, "UNDI bad MAC address" },
- { PXENV_STATUS_UNDI_BAD_EEPROM_CHECKSUM, "UNDI bad EEPROM checksum" },
- { PXENV_STATUS_UNDI_ERROR_SETTING_ISR, "UNDI error setting ISR" },
- { PXENV_STATUS_UNDI_INVALID_STATE, "UNDI invalid state" },
- { PXENV_STATUS_UNDI_TRANSMIT_ERROR, "UNDI transmit error" },
- { PXENV_STATUS_UNDI_INVALID_PARAMETER, "UNDI invalid parameter" },
- { PXENV_STATUS_BSTRAP_PROMPT_MENU, "Bootstrap prompt menu" },
- { PXENV_STATUS_BSTRAP_MCAST_ADDR, "Bootstrap mcast addr" },
- { PXENV_STATUS_BSTRAP_MISSING_LIST, "Bootstrap missing list" },
- { PXENV_STATUS_BSTRAP_NO_RESPONSE, "Bootstrap no response" },
- { PXENV_STATUS_BSTRAP_FILE_TOO_BIG, "Bootstrap file too big" },
- { PXENV_STATUS_BINL_CANCELED_BY_KEYSTROKE,
- "BINL canceled by keystroke" },
- { PXENV_STATUS_BINL_NO_PXE_SERVER, "BINL no PXE server" },
- { PXENV_STATUS_NOT_AVAILABLE_IN_PMODE,
- "Not available in protected mode" },
- { PXENV_STATUS_NOT_AVAILABLE_IN_RMODE, "Not available in real mode" },
- { PXENV_STATUS_BUSD_DEVICE_NOT_SUPPORTED,
- "BUSD device not supported" },
- { PXENV_STATUS_LOADER_NO_FREE_BASE_MEMORY,
- "Loader no free base memory" },
- { PXENV_STATUS_LOADER_NO_BC_ROMID, "Loader no Base Code ROM ID" },
- { PXENV_STATUS_LOADER_BAD_BC_ROMID, "Loader bad Base Code ROM ID" },
- { PXENV_STATUS_LOADER_BAD_BC_RUNTIME_IMAGE,
- "Loader bad Base Code runtime image" },
- { PXENV_STATUS_LOADER_NO_UNDI_ROMID, "Loader no UNDI ROM ID" },
- { PXENV_STATUS_LOADER_BAD_UNDI_ROMID, "Loader bad UNDI ROM ID" },
- { PXENV_STATUS_LOADER_BAD_UNDI_DRIVER_IMAGE,
- "Loader bad UNDI driver image" },
- { PXENV_STATUS_LOADER_NO_PXE_STRUCT, "Loader no !PXE struct" },
- { PXENV_STATUS_LOADER_NO_PXENV_STRUCT, "Loader no PXENV+ struct" },
- { PXENV_STATUS_LOADER_UNDI_START, "Loader UNDI start" },
- { PXENV_STATUS_LOADER_BC_START, "Loader Base Code start" },
-};
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_file.c b/gpxe/src/arch/i386/interface/pxe/pxe_file.c
deleted file mode 100644
index 8d832123..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_file.c
+++ /dev/null
@@ -1,306 +0,0 @@
-/** @file
- *
- * PXE FILE API
- *
- */
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <byteswap.h>
-#include <gpxe/uaccess.h>
-#include <gpxe/posix_io.h>
-#include <gpxe/features.h>
-#include <pxe.h>
-#include <realmode.h>
-
-/*
- * Copyright (C) 2007 Michael Brown <mbrown@fensystems.co.uk>.
- * Portions (C) 2010 Shao Miller <shao.miller@yrdsb.edu.on.ca>.
- * [PXE exit hook logic]
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-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
- *
- */
-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
- *
- */
-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
- *
- */
-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
- *
- */
-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
- */
-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
- *
- */
-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;
-}
-
-segoff_t __data16 ( pxe_exit_hook ) = { 0, 0 };
-#define pxe_exit_hook __use_data16 ( pxe_exit_hook )
-
-/**
- * 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 "gPXE" (0x45585067)
- * @ret s_PXENV_FILE_API_CHECK::APIMask API function bitmask
- * @ret s_PXENV_FILE_API_CHECK::Flags Reserved
- *
- */
-PXENV_EXIT_t pxenv_file_api_check ( struct s_PXENV_FILE_API_CHECK *file_api_check ) {
- DBG ( "PXENV_FILE_API_CHECK" );
-
- if ( file_api_check->Magic != 0x91d447b2 ) {
- file_api_check->Status = PXENV_STATUS_BAD_FUNC;
- return PXENV_EXIT_FAILURE;
- } else if ( file_api_check->Size <
- sizeof(struct s_PXENV_FILE_API_CHECK) ) {
- file_api_check->Status = PXENV_STATUS_OUT_OF_RESOURCES;
- return PXENV_EXIT_FAILURE;
- } else {
- file_api_check->Status = PXENV_STATUS_SUCCESS;
- file_api_check->Size = sizeof(struct s_PXENV_FILE_API_CHECK);
- file_api_check->Magic = 0xe9c17b20;
- file_api_check->Provider = 0x45585067; /* "gPXE" */
- file_api_check->APIMask = 0x0000007f; /* Functions e0-e6 */
- /* Check to see if we have a PXE exit hook */
- if ( pxe_exit_hook.segment | pxe_exit_hook.offset )
- /* Function e7, also */
- file_api_check->APIMask |= 0x00000080;
- file_api_check->Flags = 0; /* None defined */
- return PXENV_EXIT_SUCCESS;
- }
-}
-
-/**
- * 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
- *
- */
-PXENV_EXIT_t pxenv_file_exit_hook ( struct s_PXENV_FILE_EXIT_HOOK
- *file_exit_hook ) {
- DBG ( "PXENV_FILE_EXIT_HOOK" );
-
- /* Check to see if we have a PXE exit hook */
- if ( pxe_exit_hook.segment | pxe_exit_hook.offset ) {
- /* 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;
- }
-
- DBG ( " not NBP" );
- file_exit_hook->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
-}
-
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_loader.c b/gpxe/src/arch/i386/interface/pxe/pxe_loader.c
deleted file mode 100644
index b35caf77..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_loader.c
+++ /dev/null
@@ -1,50 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <gpxe/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/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c b/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c
deleted file mode 100644
index 3939c7bf..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_preboot.c
+++ /dev/null
@@ -1,357 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdint.h>
-#include <string.h>
-#include <stdlib.h>
-#include <gpxe/uaccess.h>
-#include <gpxe/dhcp.h>
-#include <gpxe/fakedhcp.h>
-#include <gpxe/device.h>
-#include <gpxe/netdevice.h>
-#include <gpxe/isapnp.h>
-#include <gpxe/init.h>
-#include <gpxe/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 },
-};
-
-/* 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 )
-
-/**
- * Set PXE cached TFTP filename
- *
- * @v filename TFTP filename
- *
- * This is a bug-for-bug compatibility hack needed in order to work
- * with Microsoft Remote Installation Services (RIS). The filename
- * used in a call to PXENV_RESTART_TFTP or PXENV_TFTP_READ_FILE must
- * be returned as the DHCP filename in subsequent calls to
- * PXENV_GET_CACHED_INFO.
- */
-void pxe_set_cached_filename ( const unsigned char *filename ) {
- memcpy ( cached_info[CACHED_INFO_DHCPACK].dhcphdr.file, filename,
- sizeof ( cached_info[CACHED_INFO_DHCPACK].dhcphdr.file ) );
- memcpy ( cached_info[CACHED_INFO_BINL].dhcphdr.file, filename,
- sizeof ( cached_info[CACHED_INFO_BINL].dhcphdr.file ) );
-}
-
-/**
- * UNLOAD BASE CODE STACK
- *
- * @v None -
- * @ret ...
- *
- */
-PXENV_EXIT_t pxenv_unload_stack ( struct s_PXENV_UNLOAD_STACK *unload_stack ) {
- DBG ( "PXENV_UNLOAD_STACK" );
-
- unload_stack->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_GET_CACHED_INFO
- *
- * Status: working
- */
-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;
-
- DBG ( "PXENV_GET_CACHED_INFO %d", get_cached_info->PacketType );
-
- DBG ( " to %04x:%04x+%x", get_cached_info->Buffer.segment,
- get_cached_info->Buffer.offset, get_cached_info->BufferSize );
-
- /* Sanity check */
- idx = ( get_cached_info->PacketType - 1 );
- if ( idx >= NUM_CACHED_INFOS ) {
- DBG ( " bad PacketType" );
- goto err;
- }
- info = &cached_info[idx];
-
- /* Construct cached version of packet, if not already constructed. */
- if ( ! info->dhcphdr.op ) {
- /* Construct DHCP packet */
- creator = &pxe_dhcp_packet_creators[idx];
- if ( ( rc = creator->create ( pxe_netdev, info,
- sizeof ( *info ) ) ) != 0 ) {
- DBG ( " failed to build packet" );
- goto err;
- }
- }
-
- 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 );
- DBG ( " returning %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 ) )
- DBG ( " 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;
- }
-
- 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
- */
-PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE
- *restart_tftp ) {
- PXENV_EXIT_t tftp_exit;
-
- DBG ( "PXENV_RESTART_TFTP " );
-
- /* Intel bug-for-bug hack */
- pxe_set_cached_filename ( restart_tftp->FileName );
-
- /* 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;
-
- /* Fire up the new NBP */
- restart_tftp->Status = pxe_start_nbp();
-
- /* Not sure what "SUCCESS" actually means, since we can only
- * return if the new NBP failed to boot...
- */
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_START_UNDI
- *
- * Status: working
- */
-PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) {
- unsigned int bus_type;
- unsigned int location;
- struct net_device *netdev;
-
- DBG ( "PXENV_START_UNDI %04x:%04x:%04x",
- 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 ) {
- DBG ( " no net device found" );
- start_undi->Status = PXENV_STATUS_UNDI_CANNOT_INITIALIZE_NIC;
- return PXENV_EXIT_FAILURE;
- }
- DBG ( " using netdev %s", netdev->name );
-
- /* Activate PXE */
- pxe_activate ( netdev );
-
- start_undi->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_STOP_UNDI
- *
- * Status: working
- */
-PXENV_EXIT_t pxenv_stop_undi ( struct s_PXENV_STOP_UNDI *stop_undi ) {
- DBG ( "PXENV_STOP_UNDI" );
-
- /* Deactivate PXE */
- pxe_deactivate();
-
- /* Prepare for unload */
- shutdown ( SHUTDOWN_BOOT );
-
- /* Check to see if we still have any hooked interrupts */
- if ( hooked_bios_interrupts != 0 ) {
- DBG ( "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)
- */
-PXENV_EXIT_t pxenv_start_base ( struct s_PXENV_START_BASE *start_base ) {
- DBG ( "PXENV_START_BASE" );
-
- start_base->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
-}
-
-/* PXENV_STOP_BASE
- *
- * Status: working
- */
-PXENV_EXIT_t pxenv_stop_base ( struct s_PXENV_STOP_BASE *stop_base ) {
- DBG ( "PXENV_STOP_BASE" );
-
- /* 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;
-}
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c b/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c
deleted file mode 100644
index 0e3ca3c5..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_tftp.c
+++ /dev/null
@@ -1,586 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <errno.h>
-#include <byteswap.h>
-#include <gpxe/uaccess.h>
-#include <gpxe/in.h>
-#include <gpxe/tftp.h>
-#include <gpxe/xfer.h>
-#include <gpxe/open.h>
-#include <gpxe/process.h>
-#include <pxe.h>
-
-/** A PXE TFTP connection */
-struct pxe_tftp_connection {
- /** Data transfer interface */
- struct xfer_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;
-};
-
-/** The PXE TFTP connection */
-static struct pxe_tftp_connection pxe_tftp = {
- .xfer = XFER_INIT ( &null_xfer_ops ),
-};
-
-/**
- * Close PXE TFTP connection
- *
- * @v rc Final status code
- */
-static void pxe_tftp_close ( int rc ) {
- xfer_nullify ( &pxe_tftp.xfer );
- xfer_close ( &pxe_tftp.xfer, rc );
- pxe_tftp.rc = rc;
-}
-
-/**
- * Receive new data
- *
- * @v xfer Data transfer interface
- * @v iobuf I/O buffer
- * @v meta Transfer metadata
- * @ret rc Return status code
- */
-static int pxe_tftp_xfer_deliver_iob ( struct xfer_interface *xfer __unused,
- struct io_buffer *iobuf,
- struct xfer_metadata *meta ) {
- size_t len = iob_len ( iobuf );
- int rc = 0;
-
- /* Calculate new buffer position */
- if ( meta->whence != SEEK_CUR )
- 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 ( rc );
-
- free_iob ( iobuf );
- return rc;
-}
-
-/**
- * Handle close() event
- *
- * @v xfer Data transfer interface
- * @v rc Reason for close
- */
-static void pxe_tftp_xfer_close ( struct xfer_interface *xfer __unused,
- int rc ) {
- pxe_tftp_close ( rc );
-}
-
-static struct xfer_interface_operations pxe_tftp_xfer_ops = {
- .close = pxe_tftp_xfer_close,
- .vredirect = xfer_vreopen,
- .window = unlimited_xfer_window,
- .alloc_iob = default_xfer_alloc_iob,
- .deliver_iob = pxe_tftp_xfer_deliver_iob,
- .deliver_raw = xfer_deliver_as_iob,
-};
-
-/**
- * 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 ( uint32_t ipaddress, unsigned int port,
- const unsigned char *filename, size_t blksize,
- int sizeonly ) {
- char uri_string[PXE_TFTP_URI_LEN];
- struct in_addr address;
- int rc;
-
- /* Intel bug-for-bug hack */
- pxe_set_cached_filename ( filename );
-
- /* Reset PXE TFTP connection structure */
- memset ( &pxe_tftp, 0, sizeof ( pxe_tftp ) );
- xfer_init ( &pxe_tftp.xfer, &pxe_tftp_xfer_ops, NULL );
- pxe_tftp.rc = -EINPROGRESS;
-
- /* Construct URI string */
- address.s_addr = ipaddress;
- if ( ! port )
- port = htons ( TFTP_PORT );
- if ( blksize < TFTP_DEFAULT_BLKSIZE )
- blksize = TFTP_DEFAULT_BLKSIZE;
- snprintf ( uri_string, sizeof ( uri_string ),
- "tftp%s://%s:%d%s%s?blksize=%zd",
- sizeonly ? "size" : "",
- inet_ntoa ( address ), ntohs ( port ),
- ( ( filename[0] == '/' ) ? "" : "/" ), filename, blksize );
- DBG ( " %s", uri_string );
-
- /* Open PXE TFTP connection */
- if ( ( rc = xfer_open_uri_string ( &pxe_tftp.xfer,
- uri_string ) ) != 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".
- */
-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 ( 0 );
-
- /* Open connection */
- if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress,
- tftp_open->TFTPPort,
- tftp_open->FileName,
- tftp_open->PacketSize,
- 0) ) != 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.)
- */
-PXENV_EXIT_t pxenv_tftp_close ( struct s_PXENV_TFTP_CLOSE *tftp_close ) {
- DBG ( "PXENV_TFTP_CLOSE" );
-
- pxe_tftp_close ( 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.)
- */
-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.)
- *
- * @note Microsoft's NTLDR assumes that the filename passed in via
- * s_PXENV_TFTP_READ_FILE::FileName will be stored in the "file" field
- * of the stored DHCPACK packet, whence it will be returned via any
- * subsequent calls to pxenv_get_cached_info(). Though this is
- * essentially a bug in the Intel PXE implementation (not, for once,
- * in the specification!), it is a bug that Microsoft relies upon, and
- * so we implement this bug-for-bug compatibility by overwriting the
- * filename stored DHCPACK packet with the filename passed in
- * s_PXENV_TFTP_READ_FILE::FileName.
- *
- */
-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 ) ) != 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 ( 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.
- */
-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, 1 ) ) != 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 ( rc );
-
- tftp_get_fsize->Status = PXENV_STATUS ( rc );
- return ( rc ? PXENV_EXIT_FAILURE : PXENV_EXIT_SUCCESS );
-}
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_udp.c b/gpxe/src/arch/i386/interface/pxe/pxe_udp.c
deleted file mode 100644
index f4702201..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_udp.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/** @file
- *
- * PXE UDP API
- *
- */
-
-#include <string.h>
-#include <byteswap.h>
-#include <gpxe/xfer.h>
-#include <gpxe/udp.h>
-#include <gpxe/uaccess.h>
-#include <gpxe/process.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-/** A PXE UDP connection */
-struct pxe_udp_connection {
- /** Data transfer interface to UDP stack */
- struct xfer_interface xfer;
- /** Local address */
- struct sockaddr_in local;
- /** Current PXENV_UDP_READ parameter block */
- struct s_PXENV_UDP_READ *pxenv_udp_read;
-};
-
-/**
- * Receive PXE UDP data
- *
- * @v xfer Data transfer interface
- * @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_iob ( struct xfer_interface *xfer,
- struct io_buffer *iobuf,
- struct xfer_metadata *meta ) {
- struct pxe_udp_connection *pxe_udp =
- container_of ( xfer, struct pxe_udp_connection, xfer );
- struct s_PXENV_UDP_READ *pxenv_udp_read = pxe_udp->pxenv_udp_read;
- struct sockaddr_in *sin_src;
- struct sockaddr_in *sin_dest;
- userptr_t buffer;
- size_t len;
- int rc = 0;
-
- if ( ! pxenv_udp_read ) {
- DBG ( "PXE discarded UDP packet\n" );
- rc = -ENOBUFS;
- goto done;
- }
-
- /* 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 */
- assert ( meta );
- sin_src = ( struct sockaddr_in * ) meta->src;
- assert ( sin_src );
- assert ( sin_src->sin_family == AF_INET );
- pxenv_udp_read->src_ip = sin_src->sin_addr.s_addr;
- pxenv_udp_read->s_port = sin_src->sin_port;
- sin_dest = ( struct sockaddr_in * ) meta->dest;
- assert ( sin_dest );
- assert ( sin_dest->sin_family == AF_INET );
- pxenv_udp_read->dest_ip = sin_dest->sin_addr.s_addr;
- pxenv_udp_read->d_port = sin_dest->sin_port;
-
- /* Mark as received */
- pxe_udp->pxenv_udp_read = NULL;
-
- done:
- free_iob ( iobuf );
- return rc;
-}
-
-/** PXE UDP data transfer interface operations */
-static struct xfer_interface_operations pxe_udp_xfer_operations = {
- .close = ignore_xfer_close,
- .vredirect = ignore_xfer_vredirect,
- .window = unlimited_xfer_window,
- .alloc_iob = default_xfer_alloc_iob,
- .deliver_iob = pxe_udp_deliver_iob,
- .deliver_raw = xfer_deliver_as_iob,
-};
-
-/** The PXE UDP connection */
-static struct pxe_udp_connection pxe_udp = {
- .xfer = XFER_INIT ( &pxe_udp_xfer_operations ),
- .local = {
- .sin_family = AF_INET,
- },
-};
-
-/**
- * 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.
- *
- */
-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", inet_ntoa ( pxe_udp.local.sin_addr ) );
-
- /* Open promiscuous UDP connection */
- xfer_close ( &pxe_udp.xfer, 0 );
- if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) {
- 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.)
- *
- */
-PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE *pxenv_udp_close ) {
- DBG ( "PXENV_UDP_CLOSE" );
-
- /* Close UDP connection */
- xfer_close ( &pxe_udp.xfer, 0 );
-
- 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.
- *
- */
-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 ) {
- 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", 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_iob_meta ( &pxe_udp.xfer, iobuf,
- &meta ) ) != 0 ) {
- 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.
- *
- */
-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;
- uint16_t d_port_wanted = pxenv_udp_read->d_port;
- uint16_t d_port;
-
- DBG ( "PXENV_UDP_READ" );
-
- /* Try receiving a packet */
- pxe_udp.pxenv_udp_read = pxenv_udp_read;
- step();
- if ( pxe_udp.pxenv_udp_read ) {
- /* No packet received */
- pxe_udp.pxenv_udp_read = NULL;
- goto no_packet;
- }
- dest_ip.s_addr = pxenv_udp_read->dest_ip;
- d_port = pxenv_udp_read->d_port;
-
- /* 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)", inet_ntoa ( dest_ip_wanted ) );
- goto no_packet;
- }
- if ( d_port_wanted && ( d_port_wanted != d_port ) ) {
- DBG ( " wrong port %d ", htons ( d_port ) );
- DBG ( " (wanted %d)", htons ( d_port_wanted ) );
- goto no_packet;
- }
-
- 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", ntohs ( pxenv_udp_read->s_port ),
- inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ),
- ntohs ( pxenv_udp_read->d_port ) );
-
- pxenv_udp_read->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-
- no_packet:
- pxenv_udp_read->Status = PXENV_STATUS_FAILURE;
- return PXENV_EXIT_FAILURE;
-}
diff --git a/gpxe/src/arch/i386/interface/pxe/pxe_undi.c b/gpxe/src/arch/i386/interface/pxe/pxe_undi.c
deleted file mode 100644
index c9b67c06..00000000
--- a/gpxe/src/arch/i386/interface/pxe/pxe_undi.c
+++ /dev/null
@@ -1,791 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <byteswap.h>
-#include <basemem_packet.h>
-#include <gpxe/netdevice.h>
-#include <gpxe/iobuf.h>
-#include <gpxe/device.h>
-#include <gpxe/pci.h>
-#include <gpxe/if_ether.h>
-#include <gpxe/ip.h>
-#include <gpxe/arp.h>
-#include <gpxe/rarp.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;
-
-/**
- * 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_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;
-
- if ( ( rc = netdev_open ( pxe_netdev ) ) != 0 )
- return rc;
-
- netdev_irq ( pxe_netdev, 1 );
- return 0;
-}
-
-/**
- * Close PXE network device
- *
- */
-static void pxe_netdev_close ( void ) {
- 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++ ) {
- DBG ( " %s", ll_protocol->ntoa ( mcast->McastAddr[i] ) );
- }
-}
-
-/* PXENV_UNDI_STARTUP
- *
- * Status: working
- */
-PXENV_EXIT_t pxenv_undi_startup ( struct s_PXENV_UNDI_STARTUP *undi_startup ) {
- DBG ( "PXENV_UNDI_STARTUP\n" );
-
- undi_startup->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_CLEANUP
- *
- * Status: working
- */
-PXENV_EXIT_t pxenv_undi_cleanup ( struct s_PXENV_UNDI_CLEANUP *undi_cleanup ) {
- DBG ( "PXENV_UNDI_CLEANUP\n" );
-
- pxe_netdev_close();
-
- undi_cleanup->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_INITIALIZE
- *
- * Status: working
- */
-PXENV_EXIT_t pxenv_undi_initialize ( struct s_PXENV_UNDI_INITIALIZE
- *undi_initialize ) {
- DBG ( "PXENV_UNDI_INITIALIZE protocolini %08x\n",
- undi_initialize->ProtocolIni );
-
- undi_initialize->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_RESET_ADAPTER
- *
- * Status: working
- */
-PXENV_EXIT_t pxenv_undi_reset_adapter ( struct s_PXENV_UNDI_RESET
- *undi_reset_adapter ) {
- int rc;
-
- DBG ( "PXENV_UNDI_RESET_ADAPTER" );
- pxe_dump_mcast_list ( &undi_reset_adapter->R_Mcast_Buf );
- DBG ( "\n" );
-
- pxe_netdev_close();
- if ( ( rc = pxe_netdev_open() ) != 0 ) {
- DBG ( "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
- */
-PXENV_EXIT_t pxenv_undi_shutdown ( struct s_PXENV_UNDI_SHUTDOWN
- *undi_shutdown ) {
- DBG ( "PXENV_UNDI_SHUTDOWN\n" );
-
- pxe_netdev_close();
-
- undi_shutdown->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_OPEN
- *
- * Status: working
- */
-PXENV_EXIT_t pxenv_undi_open ( struct s_PXENV_UNDI_OPEN *undi_open ) {
- int rc;
-
- DBG ( "PXENV_UNDI_OPEN flag %04x filter %04x",
- undi_open->OpenFlag, undi_open->PktFilter );
- pxe_dump_mcast_list ( &undi_open->R_Mcast_Buf );
- DBG ( "\n" );
-
- if ( ( rc = pxe_netdev_open() ) != 0 ) {
- DBG ( "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
- */
-PXENV_EXIT_t pxenv_undi_close ( struct s_PXENV_UNDI_CLOSE *undi_close ) {
- DBG ( "PXENV_UNDI_CLOSE\n" );
-
- pxe_netdev_close();
-
- undi_close->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_TRANSMIT
- *
- * Status: working
- */
-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 = pxe_netdev->ll_protocol;
- char destaddr[MAX_LL_ADDR_LEN];
- const void *ll_dest;
- size_t ll_hlen = ll_protocol->ll_header_len;
- size_t len;
- unsigned int i;
- int rc;
-
- DBG2 ( "PXENV_UNDI_TRANSMIT" );
-
- /* Forcibly enable interrupts at this point, to work around
- * callers that never call PXENV_UNDI_OPEN before attempting
- * to use the UNDI API.
- */
- 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;
- ll_hlen = 0;
- break;
- default:
- DBG2 ( " %02x invalid protocol\n", undi_transmit->Protocol );
- undi_transmit->Status = PXENV_STATUS_UNDI_INVALID_PARAMETER;
- return PXENV_EXIT_FAILURE;
- }
- DBG2 ( " %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;
- DBG2 ( " %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;
- DBG2 ( " %04x:%04x+%x", datablk->TDDataPtr.segment,
- datablk->TDDataPtr.offset, datablk->TDDataLen );
- }
-
- /* Allocate and fill I/O buffer */
- iobuf = alloc_iob ( ll_hlen + len );
- if ( ! iobuf ) {
- DBG2 ( " could not allocate iobuf\n" );
- undi_transmit->Status = PXENV_STATUS_OUT_OF_RESOURCES;
- return PXENV_EXIT_FAILURE;
- }
- iob_reserve ( iobuf, ll_hlen );
- 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 */
- 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;
- DBG2 ( " DEST %s", ll_protocol->ntoa ( ll_dest ) );
- } else {
- ll_dest = pxe_netdev->ll_broadcast;
- DBG2 ( " BCAST" );
- }
-
- /* Add link-layer header */
- if ( ( rc = ll_protocol->push ( pxe_netdev, iobuf, ll_dest,
- pxe_netdev->ll_addr,
- net_protocol->net_proto ))!=0){
- DBG2 ( " 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 */
- DBG2 ( "\n" );
- if ( ( rc = netdev_tx ( pxe_netdev, iobuf ) ) != 0 ) {
- DBG2 ( "PXENV_UNDI_TRANSMIT could not transmit: %s\n",
- strerror ( rc ) );
- undi_tx_count--;
- undi_transmit->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
-
- undi_transmit->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_SET_MCAST_ADDRESS
- *
- * Status: working (for NICs that support receive-all-multicast)
- */
-PXENV_EXIT_t
-pxenv_undi_set_mcast_address ( struct s_PXENV_UNDI_SET_MCAST_ADDRESS
- *undi_set_mcast_address ) {
- DBG ( "PXENV_UNDI_SET_MCAST_ADDRESS" );
- pxe_dump_mcast_list ( &undi_set_mcast_address->R_Mcast_Buf );
- DBG ( "\n" );
-
- undi_set_mcast_address->Status = PXENV_STATUS_SUCCESS;
- return PXENV_EXIT_SUCCESS;
-}
-
-/* PXENV_UNDI_SET_STATION_ADDRESS
- *
- * Status: working
- */
-PXENV_EXIT_t
-pxenv_undi_set_station_address ( struct s_PXENV_UNDI_SET_STATION_ADDRESS
- *undi_set_station_address ) {
- struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
-
- DBG ( "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 ( pxe_netdev->state & NETDEV_OPEN ) {
- DBG ( " 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 );
-
- DBG ( "\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)
- */
-PXENV_EXIT_t
-pxenv_undi_set_packet_filter ( struct s_PXENV_UNDI_SET_PACKET_FILTER
- *undi_set_packet_filter ) {
-
- DBG ( "PXENV_UNDI_SET_PACKET_FILTER %02x\n",
- undi_set_packet_filter->filter );
-
- /* 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
- */
-PXENV_EXIT_t pxenv_undi_get_information ( struct s_PXENV_UNDI_GET_INFORMATION
- *undi_get_information ) {
- struct device *dev = pxe_netdev->dev;
- struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
- size_t ll_addr_len = ll_protocol->ll_addr_len;
-
- DBG ( "PXENV_UNDI_GET_INFORMATION" );
-
- undi_get_information->BaseIo = dev->desc.ioaddr;
- undi_get_information->IntNumber = dev->desc.irq;
- /* 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_addr_len;
- assert ( 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;
-
- DBG ( " 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
- */
-PXENV_EXIT_t pxenv_undi_get_statistics ( struct s_PXENV_UNDI_GET_STATISTICS
- *undi_get_statistics ) {
- DBG ( "PXENV_UNDI_GET_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;
-
- DBG ( " 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
- */
-PXENV_EXIT_t pxenv_undi_clear_statistics ( struct s_PXENV_UNDI_CLEAR_STATISTICS
- *undi_clear_statistics ) {
- DBG ( "PXENV_UNDI_CLEAR_STATISTICS\n" );
-
- 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)
- */
-PXENV_EXIT_t pxenv_undi_initiate_diags ( struct s_PXENV_UNDI_INITIATE_DIAGS
- *undi_initiate_diags ) {
- DBG ( "PXENV_UNDI_INITIATE_DIAGS failed: unsupported\n" );
-
- 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)
- */
-PXENV_EXIT_t pxenv_undi_force_interrupt ( struct s_PXENV_UNDI_FORCE_INTERRUPT
- *undi_force_interrupt ) {
- DBG ( "PXENV_UNDI_FORCE_INTERRUPT failed: unsupported\n" );
-
- undi_force_interrupt->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
-}
-
-/* PXENV_UNDI_GET_MCAST_ADDRESS
- *
- * Status: working
- */
-PXENV_EXIT_t
-pxenv_undi_get_mcast_address ( struct s_PXENV_UNDI_GET_MCAST_ADDRESS
- *undi_get_mcast_address ) {
- struct ll_protocol *ll_protocol = pxe_netdev->ll_protocol;
- struct in_addr ip = { .s_addr = undi_get_mcast_address->InetAddr };
- int rc;
-
- DBG ( "PXENV_UNDI_GET_MCAST_ADDRESS %s", inet_ntoa ( ip ) );
-
- if ( ( rc = ll_protocol->mc_hash ( AF_INET, &ip,
- undi_get_mcast_address->MediaAddr ))!=0){
- DBG ( " failed: %s\n", strerror ( rc ) );
- undi_get_mcast_address->Status = PXENV_STATUS ( rc );
- return PXENV_EXIT_FAILURE;
- }
- DBG ( "=>%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
- */
-PXENV_EXIT_t pxenv_undi_get_nic_type ( struct s_PXENV_UNDI_GET_NIC_TYPE
- *undi_get_nic_type ) {
- struct device *dev = pxe_netdev->dev;
-
- DBG ( "PXENV_UNDI_GET_NIC_TYPE" );
-
- memset ( &undi_get_nic_type->info, 0,
- sizeof ( undi_get_nic_type->info ) );
-
- 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;
- /* Cheat: remaining fields are probably unnecessary,
- * and would require adding extra code to pci.c.
- */
- undi_get_nic_type->info.pci.SubVendor_ID = 0xffff;
- undi_get_nic_type->info.pci.SubDevice_ID = 0xffff;
- DBG ( " 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.
- */
- DBG ( " 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:
- DBG ( " 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
- */
-PXENV_EXIT_t pxenv_undi_get_iface_info ( struct s_PXENV_UNDI_GET_IFACE_INFO
- *undi_get_iface_info ) {
- DBG ( "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 | SUPPORTED_IRQ );
- memset ( undi_get_iface_info->Reserved, 0,
- sizeof(undi_get_iface_info->Reserved) );
-
- DBG ( " %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
- */
-PXENV_EXIT_t pxenv_undi_get_state ( struct s_PXENV_UNDI_GET_STATE
- *undi_get_state ) {
- DBG ( "PXENV_UNDI_GET_STATE failed: unsupported\n" );
-
- undi_get_state->Status = PXENV_STATUS_UNSUPPORTED;
- return PXENV_EXIT_FAILURE;
-};
-
-/* PXENV_UNDI_ISR
- *
- * Status: working
- */
-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;
- size_t ll_hlen;
- struct net_protocol *net_protocol;
- unsigned int prottype;
- int rc;
-
- /* Use coloured debug, since UNDI ISR messages are likely to
- * be interspersed amongst other UNDI messages.
- */
- 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.
- */
- netdev_poll ( pxe_netdev );
-
- /* Disable interrupts to avoid interrupt storm */
- netdev_irq ( pxe_netdev, 0 );
-
- /* Always say it was ours for the sake of simplicity */
- DBGC2 ( &pxenv_undi_isr, " OURS" );
- undi_isr->FuncFlag = PXENV_UNDI_ISR_OUT_OURS;
- 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.
- */
- netdev_poll ( pxe_netdev );
-
- /* 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 )) !=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;
- undi_isr->PktType = XMT_DESTADDR;
- 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;
-}
diff --git a/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c b/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c
deleted file mode 100644
index 582db5d2..00000000
--- a/gpxe/src/arch/i386/interface/pxeparent/pxeparent.c
+++ /dev/null
@@ -1,201 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <gpxe/dhcp.h>
-#include <pxeparent.h>
-#include <pxe_api.h>
-#include <pxe_types.h>
-#include <pxe.h>
-
-/** @file
- *
- * Call interface to parent PXE stack
- *
- */
-
-/**
- * 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";
- }
-}
-
-/**
- * PXE parent parameter block
- *
- * Used as the paramter 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 ) {
- PXENV_EXIT_t exit;
- int discard_b, 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.
- */
- __asm__ __volatile__ ( REAL_CODE ( "pushw %%es\n\t"
- "pushw %%di\n\t"
- "pushw %%bx\n\t"
- "lcall *pxeparent_entry_point\n\t"
- "addw $6, %%sp\n\t" )
- : "=a" ( exit ), "=b" ( discard_b ),
- "=D" ( discard_D )
- : "b" ( function ),
- "D" ( __from_data16 ( &pxeparent_params ) )
- : "ecx", "edx", "esi", "ebp" );
-
- /* PXE API calls may rudely change the status of A20 and not
- * bother to restore it afterwards. Intel is known to be
- * guilty of this.
- *
- * Note that we will return to this point even if A20 gets
- * screwed up by the parent PXE stack, because Etherboot always
- * resides in an even megabyte of RAM.
- */
- gateA20_set();
-
- /* Determine return status code based on PXENV_EXIT and
- * PXENV_STATUS
- */
- if ( exit == PXENV_EXIT_SUCCESS ) {
- rc = 0;
- } else {
- rc = -pxeparent_params.Status;
- /* Paranoia; don't return success for the combination
- * of PXENV_EXIT_FAILURE but PXENV_STATUS_SUCCESS
- */
- if ( rc == 0 )
- rc = -EIO;
- }
-
- /* 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/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c b/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c
deleted file mode 100644
index 66059437..00000000
--- a/gpxe/src/arch/i386/interface/pxeparent/pxeparent_dhcp.c
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2009 Joshua Oreman <oremanj@rwcr.net>.
- *
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <string.h>
-#include <gpxe/dhcp.h>
-#include <gpxe/netdevice.h>
-#include <undipreload.h>
-#include <pxeparent.h>
-#include <realmode.h>
-#include <pxe_api.h>
-
-/**
- * Present cached DHCP packet if it exists
- */
-void __weak_impl ( get_cached_dhcpack ) ( void ) {
- struct undi_device *undi;
- struct s_PXENV_GET_CACHED_INFO get_cached_info;
- int rc;
-
- /* Use preloaded UNDI device to get at PXE entry point */
- undi = &preloaded_undi;
- if ( ! undi->entry.segment ) {
- DBG ( "PXEDHCP no preloaded UNDI device found\n" );
- return;
- }
-
- /* Check that stack is available to get cached info */
- if ( ! ( undi->flags & UNDI_FL_KEEP_ALL ) ) {
- DBG ( "PXEDHCP stack was unloaded, no cache available\n" );
- return;
- }
-
- /* Obtain cached DHCP packet */
- memset ( &get_cached_info, 0, sizeof ( get_cached_info ) );
- get_cached_info.PacketType = PXENV_PACKET_TYPE_DHCP_ACK;
-
- if ( ( rc = pxeparent_call ( undi->entry, PXENV_GET_CACHED_INFO,
- &get_cached_info,
- sizeof ( get_cached_info ) ) ) != 0 ) {
- DBG ( "PXEDHCP GET_CACHED_INFO failed: %s\n", strerror ( rc ) );
- return;
- }
-
- DBG ( "PXEDHCP got cached info at %04x:%04x length %d\n",
- get_cached_info.Buffer.segment, get_cached_info.Buffer.offset,
- get_cached_info.BufferSize );
-
- /* Present cached DHCP packet */
- store_cached_dhcpack ( real_to_user ( get_cached_info.Buffer.segment,
- get_cached_info.Buffer.offset ),
- get_cached_info.BufferSize );
-}
diff --git a/gpxe/src/arch/i386/interface/syslinux/com32_call.c b/gpxe/src/arch/i386/interface/syslinux/com32_call.c
deleted file mode 100644
index d2c3f918..00000000
--- a/gpxe/src/arch/i386/interface/syslinux/com32_call.c
+++ /dev/null
@@ -1,190 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/**
- * @file SYSLINUX COM32 helpers
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <stdint.h>
-#include <realmode.h>
-#include <comboot.h>
-#include <assert.h>
-#include <gpxe/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/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S b/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S
deleted file mode 100644
index 5c5bd139..00000000
--- a/gpxe/src/arch/i386/interface/syslinux/com32_wrapper.S
+++ /dev/null
@@ -1,94 +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., 675 Mass Ave, Cambridge, MA 02139, 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:
-
- /* 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
-
- ret
-
-
- .data
-
-/* Internal gPXE 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/gpxe/src/arch/i386/interface/syslinux/comboot_call.c b/gpxe/src/arch/i386/interface/syslinux/comboot_call.c
deleted file mode 100644
index 0a17bf13..00000000
--- a/gpxe/src/arch/i386/interface/syslinux/comboot_call.c
+++ /dev/null
@@ -1,716 +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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/**
- * @file SYSLINUX COMBOOT API
- *
- */
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-#include <errno.h>
-#include <realmode.h>
-#include <biosint.h>
-#include <console.h>
-#include <stdlib.h>
-#include <comboot.h>
-#include <bzimage.h>
-#include <pxe_call.h>
-#include <setjmp.h>
-#include <string.h>
-#include <gpxe/posix_io.h>
-#include <gpxe/process.h>
-#include <gpxe/serial.h>
-#include <gpxe/init.h>
-#include <gpxe/image.h>
-#include <usr/imgmgmt.h>
-#include "config/console.h"
-#include "config/serial.h"
-
-/** The "SYSLINUX" version string */
-static char __data16_array ( syslinux_version, [] ) = "gPXE " VERSION;
-#define syslinux_version __use_data16 ( syslinux_version )
-
-/** The "SYSLINUX" copyright string */
-static char __data16_array ( syslinux_copyright, [] ) = "http://etherboot.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;
-
-/* Replacement image when exiting with COMBOOT_EXIT_RUN_KERNEL */
-struct image *comboot_replacement_image;
-
-/* 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 = NULL;
- struct image *initrd = NULL;
- 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 );
-
- /* Allocate and fetch initrd */
- initrd = alloc_image();
- if ( ! initrd ) {
- DBG ( "COMBOOT: could not allocate initrd\n" );
- rc = -ENOMEM;
- goto out;
- }
- if ( ( rc = imgfetch ( initrd, initrd_file,
- register_image ) ) != 0 ) {
- DBG ( "COMBOOT: could not fetch initrd: %s\n",
- strerror ( rc ) );
- goto out;
- }
-
- /* Restore space after initrd name, if applicable */
- if ( initrd_end )
- *initrd_end = ' ';
- }
-
- DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
-
- /* Allocate and fetch kernel */
- kernel = alloc_image();
- if ( ! kernel ) {
- DBG ( "COMBOOT: could not allocate kernel\n" );
- rc = -ENOMEM;
- goto out;
- }
- if ( ( rc = imgfetch ( kernel, kernel_file,
- register_image ) ) != 0 ) {
- DBG ( "COMBOOT: could not fetch kernel: %s\n",
- strerror ( rc ) );
- goto out;
- }
- if ( ( rc = image_set_cmdline ( kernel, cmdline ) ) != 0 ) {
- DBG ( "COMBOOT: could not set kernel command line: %s\n",
- strerror ( rc ) );
- goto out;
- }
-
- /* Store kernel as replacement image */
- assert ( comboot_replacement_image == NULL );
- comboot_replacement_image = image_get ( kernel );
-
- out:
- /* Drop image references unconditionally; either we want to
- * discard them, or they have been registered and we should
- * drop out local reference.
- */
- image_put ( kernel );
- image_put ( initrd );
- return rc;
-}
-
-
-/**
- * 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 */
- serial_putc ( 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;
- }
-}
-
-
-/**
- * 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_GPXE;
-
- /* 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 gPXE 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 */
-
- /* gPXE has its own derivative ID, so there is no defined
- * output here; just return AL for now */
- ix86->regs.al = BZI_LOADER_TYPE_GPXE;
- ix86->flags &= ~CF;
- break;
-
- case 0x000B: /* Get Serial Console Configuration */
-#if defined(CONSOLE_SERIAL) && !defined(COMPRESERVE)
- ix86->regs.dx = COMCONSOLE;
- ix86->regs.cx = 115200 / COMSPEED;
- ix86->regs.bx = 0;
-#else
- ix86->regs.dx = 0;
-#endif
-
- ix86->flags &= ~CF;
- 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 ( 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 ( 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"
- "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"
- "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"
- "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 );
-}
diff --git a/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c b/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c
deleted file mode 100644
index 30ac502e..00000000
--- a/gpxe/src/arch/i386/interface/syslinux/comboot_resolv.c
+++ /dev/null
@@ -1,60 +0,0 @@
-#include <errno.h>
-#include <comboot.h>
-#include <gpxe/in.h>
-#include <gpxe/list.h>
-#include <gpxe/process.h>
-#include <gpxe/resolv.h>
-
-FILE_LICENCE ( GPL2_OR_LATER );
-
-static int comboot_resolv_rc;
-static struct in_addr comboot_resolv_addr;
-
-static void comboot_resolv_done ( struct resolv_interface *resolv,
- struct sockaddr *sa, int rc ) {
- struct sockaddr_in *sin;
-
- resolv_unplug ( resolv );
-
- if ( rc != 0 ) {
- comboot_resolv_rc = rc;
- return;
- }
-
- if ( sa->sa_family != AF_INET ) {
- comboot_resolv_rc = -EAFNOSUPPORT;
- return;
- }
-
- sin = ( ( struct sockaddr_in * ) sa );
- comboot_resolv_addr = sin->sin_addr;
-
- comboot_resolv_rc = 0;
-}
-
-static struct resolv_interface_operations comboot_resolv_ops = {
- .done = comboot_resolv_done,
-};
-
-static struct resolv_interface comboot_resolver = {
- .intf = {
- .dest = &null_resolv.intf,
- .refcnt = NULL,
- },
- .op = &comboot_resolv_ops,
-};
-
-int comboot_resolv ( const char *name, struct in_addr *address ) {
- int rc;
-
- comboot_resolv_rc = -EINPROGRESS;
-
- if ( ( rc = resolv ( &comboot_resolver, name, NULL ) ) != 0 )
- return rc;
-
- while ( comboot_resolv_rc == -EINPROGRESS )
- step();
-
- *address = comboot_resolv_addr;
- return comboot_resolv_rc;
-}