pxe.c revision 199767f8919635c4928607450d9e0abb932109ce
/*-
* Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org>
* Copyright (c) 2000 Paul Saab <ps@freebsd.org>
* Copyright (c) 2000 John Baldwin <jhb@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
*/
#include <stand.h>
#include <string.h>
#include <stdarg.h>
#include <netinet/in_systm.h>
#include <net.h>
#include <netif.h>
#include <nfsv2.h>
#include <iodesc.h>
#include <bootp.h>
#include <bootstrap.h>
#include "btxv86.h"
#include "pxe.h"
/*
* Allocate the PXE buffers statically instead of sticking grimy fingers into
* BTX's private data area. The scratch buffer is used to send information to
* the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS.
*/
#define PXE_BUFFER_SIZE 0x2000
#define PXE_TFTP_BUFFER_SIZE 512
static char scratch_buffer[PXE_BUFFER_SIZE];
static char data_buffer[PXE_BUFFER_SIZE];
static int pxe_debug = 0;
static int pxe_sock = -1;
static int pxe_opens = 0;
void pxe_enable(void *pxeinfo);
static void pxenv_call(int func);
static void bangpxe_call(int func);
static int pxe_init(void);
static void pxe_cleanup(void);
static void pxe_setnfshandle(char *rootpath);
static void pxe_perror(int error);
#ifdef OLD_NFSV2
#else
#endif
extern struct netif_stats pxe_st[];
extern u_int16_t __bangpxeseg;
extern u_int16_t __bangpxeoff;
extern void __bangpxeentry(void);
extern u_int16_t __pxenvseg;
extern u_int16_t __pxenvoff;
extern void __pxenventry(void);
/* dif_unit dif_nsel dif_stats dif_private */
{0, 1, &pxe_st[0], 0}
};
struct netif_driver pxenetif = {
"pxenet",
};
struct netif_driver *netif_drivers[] = {
&pxenetif,
};
"pxe",
};
/*
* This function is called by the loader to enable PXE support if we
* are booted by PXE. The passed in pointer is a pointer to the
* PXENV+ structure.
*/
void
pxe_enable(void *pxeinfo)
{
}
/*
* return true if pxe structures are found/initialized,
* also figures out our IP information via the pxe cached info struct
*/
static int
pxe_init(void)
{
int counter;
return (0);
/* look for "PXENV+" */
return (0);
}
/* make sure the size is something we can handle */
printf("PXENV+ structure too large, ignoring\n");
return (0);
}
/*
* do byte checksum:
* add up each byte in the structure, the total should be 0
*/
checksum = 0;
if (checksum != 0) {
printf("PXENV+ structure failed checksum, ignoring\n");
return (0);
}
/*
* PXENV+ passed, so use that if !PXE is not available or
* the checksum fails.
*/
for (;;) {
break;
}
checksum = 0;
counter++)
if (checksum != 0) {
break;
}
break;
}
}
printf("\nPXE version %d.%d, real mode entry point ",
if (pxe_call == bangpxe_call)
printf("@%04x:%04x\n",
else
printf("@%04x:%04x\n",
return (0);
}
return (1);
}
static int
{
return (EIO);
}
static int
{
char *devname; /* Device part of file name (or NULL). */
char temp[FNAME_SIZE];
int error = 0;
int i;
/* On first open, do netif open, mount, etc. */
if (pxe_opens == 0) {
/* Find network interface. */
if (pxe_sock < 0) {
if (pxe_sock < 0) {
printf("pxe_open: netif_open() failed\n");
return (ENXIO);
}
if (pxe_debug)
printf("pxe_open: netif_open() succeeded\n");
}
/*
* the proper information, fall back to the server
* which brought us to life and a default rootpath.
*/
#ifdef LOADER_NFS_SUPPORT
if (!rootpath[0])
#endif
if (rootpath[i] == ':')
break;
rootpath[i++] = '\0';
}
}
#ifdef LOADER_NFS_SUPPORT
#else
#endif
}
}
}
pxe_opens++;
return (error);
}
static int
{
#ifdef PXE_DEBUG
if (pxe_debug)
#endif
/* On last close, do netif close, etc. */
/* Extra close call? */
if (pxe_opens <= 0)
return (0);
pxe_opens--;
/* Not last close? */
if (pxe_opens > 0)
return(0);
#ifdef LOADER_NFS_SUPPORT
/* get an NFS filehandle for our root filesystem */
#endif
if (pxe_sock >= 0) {
#ifdef PXE_DEBUG
if (pxe_debug)
printf("pxe_close: calling netif_close()\n");
#endif
pxe_sock = -1;
}
return (0);
}
static int
{
char line[255];
return (0);
rootpath);
return (pager_output(line));
}
static void
pxe_cleanup(void)
{
#ifdef PXE_DEBUG
#endif
return;
#ifdef PXE_DEBUG
printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n",
#endif
#ifdef PXE_DEBUG
printf("pxe_cleanup: UNLOAD_STACK failed %x\n",
#endif
}
void
pxe_perror(int err)
{
return;
}
#ifdef LOADER_NFS_SUPPORT
/*
* Reach inside the libstand NFS code and dig out an NFS handle
* for the root filesystem.
*/
#ifdef OLD_NFSV2
struct nfs_iodesc {
/* structure truncated here */
};
extern struct nfs_iodesc nfs_root_node;
extern int rpc_port;
static void
{
struct iodesc *d;
int error;
if (!(d = socktodesc(pxe_sock)))
return;
nfs_root_node.iodesc = d;
}
static void
pxe_setnfshandle(char *rootpath)
{
int i;
/*
* If NFS files were never opened, we need to do mount call
* ourselves. Use nfs_root_node.iodesc as flag indicating
* previous NFS usage.
*/
buf[0] = 'X';
}
#else /* !OLD_NFSV2 */
#define NFS_V3MAXFHSIZE 64
struct nfs_iodesc {
/* structure truncated */
};
extern struct nfs_iodesc nfs_root_node;
extern int rpc_port;
static void
{
struct iodesc *d;
int error;
if (!(d = socktodesc(pxe_sock)))
return;
nfs_root_node.fh)) != 0) {
nfs_root_node.fhsize = 0;
}
nfs_root_node.iodesc = d;
}
static void
pxe_setnfshandle(char *rootpath)
{
int i;
/*
* If NFS files were never opened, we need to do mount call
* ourselves. Use nfs_root_node.iodesc as flag indicating
* previous NFS usage.
*/
buf[0] = 'X';
}
#endif /* OLD_NFSV2 */
#endif /* LOADER_NFS_SUPPORT */
void
pxenv_call(int func)
{
#ifdef PXE_DEBUG
if (pxe_debug)
#endif
v86int();
}
void
bangpxe_call(int func)
{
#ifdef PXE_DEBUG
if (pxe_debug)
#endif
v86int();
}
getsecs()
{
time_t n = 0;
time(&n);
return n;
}
static int
{
return 1;
}
static int
{
return -1;
return -1;
}
return 0;
}
static void
{
if (udpclose_p->status != 0)
}
static void
{
int i;
for (i = 0; i < 6; ++i)
}
static int
{
return len;
}
static int
{
return len;
}
{
udpwrite_p->gw = 0;
else
#if 0
/* XXX - I dont know why we need this. */
delay(1000);
#endif
if (udpwrite_p->status != 0) {
/* XXX: This happens a lot. It shouldn't. */
return -1;
}
return len;
}
{
#if 0
/* XXX - I dont know why we need this. */
delay(1000);
#endif
/* XXX: This happens a lot. It shouldn't. */
return -1;
}
return udpread_p->buffer_size;
}