diff --git a/src/arch/i386/interface/pxe/pxe_call.c b/src/arch/i386/interface/pxe/pxe_call.c index 8ecacf1d..834ca738 100644 --- a/src/arch/i386/interface/pxe/pxe_call.c +++ b/src/arch/i386/interface/pxe/pxe_call.c @@ -298,6 +298,31 @@ void pxe_api_call ( struct i386_all_regs *ix86 ) { ix86->regs.ax = ret; } +/** + * Dispatch PXE loader call + * + * @v es:di Address of PXE parameter block + * @ret ax PXE exit code + */ +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 ( ¶ms, uparams, 0, sizeof ( params ) ); + + /* Set default status in case child routine fails to do so */ + params.Status = PXENV_STATUS_FAILURE; + + /* Call UNDI loader */ + ret = undi_loader ( ¶ms ); + + /* Copy modified parameter block back to caller and return */ + copy_to_user ( uparams, 0, ¶ms, sizeof ( params ) ); + ix86->regs.ax = ret; +} + /** * Hook INT 1A for PXE * diff --git a/src/interface/pxe/pxe_loader.c b/src/interface/pxe/pxe_loader.c index d72838fd..1f2f8ca6 100644 --- a/src/interface/pxe/pxe_loader.c +++ b/src/interface/pxe/pxe_loader.c @@ -1,11 +1,5 @@ -/** @file - * - * PXE UNDI loader - * - */ - /* - * Copyright (C) 2004 Michael Brown . + * Copyright (C) 2007 Michael Brown . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -22,65 +16,37 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#warning "Currently broken" -#if 0 +#include #include "pxe.h" +#include "pxe_call.h" + +/** @file + * + * PXE UNDI loader + * + */ /* PXENV_UNDI_LOADER * - * Status: working - * - * NOTE: This is not a genuine PXE API call; the loader has a separate - * entry point. However, to simplify the mapping of the PXE API to - * the internal Etherboot API, both are directed through the same - * interface. */ PXENV_EXIT_t undi_loader ( struct s_UNDI_LOADER *undi_loader ) { - uint32_t loader_phys = virt_to_phys ( undi_loader ); - DBG ( "PXENV_UNDI_LOADER" ); - - /* Set UNDI DS as our real-mode stack */ - use_undi_ds_for_rm_stack ( undi_loader->undi_ds ); + DBG ( "[PXENV_UNDI_LOADER]" ); - /* FIXME: These lines are borrowed from main.c. There should - * probably be a single initialise() function that does all - * this, but it's currently split interestingly between main() - * and main_loop()... - */ + /* Perform one-time initialisation (e.g. heap) */ + initialise(); + /* Set up PXE data structures */ + pxe_init_structures(); - /* CHECKME: Our init functions have probably already been - called by the ROM prefix's call to setup(), haven't - they? */ + /* Fill in UNDI loader structure */ + undi_loader->PXEptr.segment = rm_ds; + undi_loader->PXEptr.offset = + ( ( unsigned ) & __from_text16 ( ppxe ) ); + undi_loader->PXENVptr.segment = rm_ds; + undi_loader->PXENVptr.offset = + ( ( unsigned ) & __from_text16 ( pxenv ) ); - - - /* We have relocated; the loader pointer is now invalid */ - undi_loader = phys_to_virt ( loader_phys ); - - /* Install PXE stack to area specified by NBP */ - install_pxe_stack ( VIRTUAL ( undi_loader->undi_cs, 0 ) ); - - /* Call pxenv_start_undi to set parameters. Why the hell PXE - * requires these parameters to be provided twice is beyond - * the wit of any sane man. Don't worry if it fails; the NBP - * should call PXENV_START_UNDI separately anyway. - */ - pxenv_start_undi ( &undi_loader->u.start_undi ); - /* Unhook stack; the loader is not meant to hook int 1a etc, - * but the call the pxenv_start_undi will cause it to happen. - */ - - /* FIXME: can't use ENSURE_CAN_UNLOAD() thanks to newer gcc's - * barfing on unnamed struct/unions. */ - /* ENSURE_CAN_UNLOAD ( undi_loader ); */ - - /* Fill in addresses of !PXE and PXENV+ structures */ - PTR_TO_SEGOFF16 ( &pxe_stack->pxe, undi_loader->pxe_ptr ); - PTR_TO_SEGOFF16 ( &pxe_stack->pxenv, undi_loader->pxenv_ptr ); - - undi_loader->u.Status = PXENV_STATUS_SUCCESS; + undi_loader->Status = PXENV_STATUS_SUCCESS; return PXENV_EXIT_SUCCESS; } -#endif diff --git a/src/interface/pxe/pxe_preboot.c b/src/interface/pxe/pxe_preboot.c index b2ae5372..b4e2206a 100644 --- a/src/interface/pxe/pxe_preboot.c +++ b/src/interface/pxe/pxe_preboot.c @@ -45,6 +45,9 @@ */ static char *pxe_ris_filename = NULL; +/* Avoid dragging in isapnp.o unnecessarily */ +uint16_t isapnp_read_port; + /** * UNLOAD BASE CODE STACK * @@ -180,9 +183,6 @@ PXENV_EXIT_t pxenv_restart_tftp ( struct s_PXENV_TFTP_READ_FILE * Status: working */ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) { - unsigned int isapnp_read_port; - unsigned int isapnp_csn; - unsigned int pci_busdevfn; unsigned int bus_type; unsigned int location; struct net_device *netdev; @@ -190,26 +190,25 @@ PXENV_EXIT_t pxenv_start_undi ( struct s_PXENV_START_UNDI *start_undi ) { DBG ( "PXENV_START_UNDI %04x:%04x:%04x", start_undi->AX, start_undi->BX, start_undi->DX ); - /* Probe for devices, etc. */ - startup(); - - /* Determine bus type and location */ - isapnp_read_port = start_undi->DX; - isapnp_csn = start_undi->BX; - pci_busdevfn = start_undi->AX; - - /* Use a heuristic to decide whether we are PCI or ISAPnP */ - if ( ( isapnp_read_port >= ISAPNP_READ_PORT_MIN ) && - ( isapnp_read_port <= ISAPNP_READ_PORT_MAX ) && - ( isapnp_csn >= ISAPNP_CSN_MIN ) && - ( isapnp_csn <= ISAPNP_CSN_MAX ) ) { + /* 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 = isapnp_csn; + 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 = pci_busdevfn; + 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 ) {