pxe.c revision 145209
1119482Sobrien/*- 258713Sjhb * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org> 358713Sjhb * Copyright (c) 2000 Paul Saab <ps@freebsd.org> 458713Sjhb * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> 558713Sjhb * All rights reserved. 658713Sjhb * 758713Sjhb * Redistribution and use in source and binary forms, with or without 858713Sjhb * modification, are permitted provided that the following conditions 958713Sjhb * are met: 1058713Sjhb * 1. Redistributions of source code must retain the above copyright 1158713Sjhb * notice, this list of conditions and the following disclaimer. 1258713Sjhb * 2. Redistributions in binary form must reproduce the above copyright 1358713Sjhb * notice, this list of conditions and the following disclaimer in the 1458713Sjhb * documentation and/or other materials provided with the distribution. 1558713Sjhb * 1658713Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1758713Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1858713Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1958713Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2058713Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2158713Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2258713Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2358713Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2458713Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2558713Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2658713Sjhb * SUCH DAMAGE. 2758713Sjhb */ 2858713Sjhb 29119482Sobrien#include <sys/cdefs.h> 30119482Sobrien__FBSDID("$FreeBSD: head/sys/boot/i386/libi386/pxe.c 145209 2005-04-17 21:38:22Z wollman $"); 31119482Sobrien 3258713Sjhb#include <stand.h> 3359768Sps#include <string.h> 3459768Sps#include <stdarg.h> 3558713Sjhb 3659087Sps#include <netinet/in_systm.h> 3759087Sps#include <netinet/in.h> 3859087Sps#include <netinet/udp.h> 3959087Sps 4059087Sps#include <net.h> 4159087Sps#include <netif.h> 4265498Smsmith#include <nfsv2.h> 4365498Smsmith#include <iodesc.h> 4459087Sps 4564527Sps#include <bootp.h> 4658713Sjhb#include <bootstrap.h> 4758713Sjhb#include "btxv86.h" 4858993Sps#include "pxe.h" 4958713Sjhb 5058713Sjhb/* 5158713Sjhb * Allocate the PXE buffers statically instead of sticking grimy fingers into 5258713Sjhb * BTX's private data area. The scratch buffer is used to send information to 5358713Sjhb * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS. 5458713Sjhb */ 5558993Sps#define PXE_BUFFER_SIZE 0x2000 5658993Sps#define PXE_TFTP_BUFFER_SIZE 512 5758993Spsstatic char scratch_buffer[PXE_BUFFER_SIZE]; 5858993Spsstatic char data_buffer[PXE_BUFFER_SIZE]; 5958713Sjhb 6059390Spsstatic pxenv_t *pxenv_p = NULL; /* PXENV+ */ 6159390Spsstatic pxe_t *pxe_p = NULL; /* !PXE */ 6259087Spsstatic BOOTPLAYER bootplayer; /* PXE Cached information. */ 6358713Sjhb 6464187Sjhbstatic int pxe_debug = 0; 6559087Spsstatic int pxe_sock = -1; 6659087Spsstatic int pxe_opens = 0; 6759087Sps 6858713Sjhbvoid pxe_enable(void *pxeinfo); 6959644Spsstatic void (*pxe_call)(int func); 7059644Spsstatic void pxenv_call(int func); 7159644Spsstatic void bangpxe_call(int func); 7259087Sps 7358713Sjhbstatic int pxe_init(void); 7459087Spsstatic int pxe_strategy(void *devdata, int flag, daddr_t dblk, 7564187Sjhb size_t size, char *buf, size_t *rsize); 7658713Sjhbstatic int pxe_open(struct open_file *f, ...); 7758713Sjhbstatic int pxe_close(struct open_file *f); 7858713Sjhbstatic void pxe_print(int verbose); 7959390Spsstatic void pxe_cleanup(void); 8065498Smsmithstatic void pxe_setnfshandle(char *rootpath); 8158713Sjhb 8258713Sjhbstatic void pxe_perror(int error); 8359087Spsstatic int pxe_netif_match(struct netif *nif, void *machdep_hint); 8459087Spsstatic int pxe_netif_probe(struct netif *nif, void *machdep_hint); 8559087Spsstatic void pxe_netif_init(struct iodesc *desc, void *machdep_hint); 8659087Spsstatic int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, 8759087Sps time_t timeout); 8859087Spsstatic int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len); 8959087Spsstatic void pxe_netif_end(struct netif *nif); 9058713Sjhb 9159087Spsextern struct netif_stats pxe_st[]; 9259644Spsextern u_int16_t __bangpxeseg; 9359644Spsextern u_int16_t __bangpxeoff; 9459644Spsextern void __bangpxeentry(void); 9559644Spsextern u_int16_t __pxenvseg; 9659644Spsextern u_int16_t __pxenvoff; 9759644Spsextern void __pxenventry(void); 9858713Sjhb 9959087Spsstruct netif_dif pxe_ifs[] = { 10059087Sps/* dif_unit dif_nsel dif_stats dif_private */ 10159087Sps {0, 1, &pxe_st[0], 0} 10259087Sps}; 10358713Sjhb 10459087Spsstruct netif_stats pxe_st[NENTS(pxe_ifs)]; 10559087Sps 10659087Spsstruct netif_driver pxenetif = { 10759087Sps "pxenet", 10859087Sps pxe_netif_match, 10959087Sps pxe_netif_probe, 11059087Sps pxe_netif_init, 11159087Sps pxe_netif_get, 11259087Sps pxe_netif_put, 11359087Sps pxe_netif_end, 11459087Sps pxe_ifs, 11559087Sps NENTS(pxe_ifs) 11659087Sps}; 11759087Sps 11859087Spsstruct netif_driver *netif_drivers[] = { 11959087Sps &pxenetif, 12059087Sps NULL 12159087Sps}; 12259087Sps 12358713Sjhbstruct devsw pxedisk = { 12458713Sjhb "pxe", 12558713Sjhb DEVT_NET, 12658713Sjhb pxe_init, 12758713Sjhb pxe_strategy, 12858713Sjhb pxe_open, 12958713Sjhb pxe_close, 13058713Sjhb noioctl, 13159408Sps pxe_print, 13259408Sps pxe_cleanup 13358713Sjhb}; 13458713Sjhb 13558713Sjhb/* 13658713Sjhb * This function is called by the loader to enable PXE support if we 13758713Sjhb * are booted by PXE. The passed in pointer is a pointer to the 13858713Sjhb * PXENV+ structure. 13958713Sjhb */ 14058713Sjhbvoid 14158713Sjhbpxe_enable(void *pxeinfo) 14258713Sjhb{ 14359644Sps pxenv_p = (pxenv_t *)pxeinfo; 14459644Sps pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 + 14559644Sps pxenv_p->PXEPtr.offset); 14659644Sps pxe_call = NULL; 14758713Sjhb} 14858713Sjhb 14958713Sjhb/* 15058713Sjhb * return true if pxe structures are found/initialized, 15158713Sjhb * also figures out our IP information via the pxe cached info struct 15258713Sjhb */ 15358713Sjhbstatic int 15458713Sjhbpxe_init(void) 15558713Sjhb{ 15658713Sjhb t_PXENV_GET_CACHED_INFO *gci_p; 15758713Sjhb int counter; 15858713Sjhb uint8_t checksum; 15958713Sjhb uint8_t *checkptr; 16058713Sjhb 16158713Sjhb if(pxenv_p == NULL) 16258713Sjhb return (0); 16358713Sjhb 16458713Sjhb /* look for "PXENV+" */ 16559456Sps if (bcmp((void *)pxenv_p->Signature, S_SIZE("PXENV+"))) { 16659456Sps pxenv_p = NULL; 16758713Sjhb return (0); 16859456Sps } 16958713Sjhb 17058713Sjhb /* make sure the size is something we can handle */ 17158713Sjhb if (pxenv_p->Length > sizeof(*pxenv_p)) { 17258713Sjhb printf("PXENV+ structure too large, ignoring\n"); 17358713Sjhb pxenv_p = NULL; 17458713Sjhb return (0); 17558713Sjhb } 17658713Sjhb 17758713Sjhb /* 17858713Sjhb * do byte checksum: 17958713Sjhb * add up each byte in the structure, the total should be 0 18058713Sjhb */ 18158713Sjhb checksum = 0; 18258713Sjhb checkptr = (uint8_t *) pxenv_p; 18358713Sjhb for (counter = 0; counter < pxenv_p->Length; counter++) 18458713Sjhb checksum += *checkptr++; 18558713Sjhb if (checksum != 0) { 18658713Sjhb printf("PXENV+ structure failed checksum, ignoring\n"); 18758713Sjhb pxenv_p = NULL; 18858713Sjhb return (0); 18958713Sjhb } 19059390Sps 19159644Sps 19259644Sps /* 19359644Sps * PXENV+ passed, so use that if !PXE is not available or 19459644Sps * the checksum fails. 19559644Sps */ 19659644Sps pxe_call = pxenv_call; 19759644Sps if (pxenv_p->Version >= 0x0200) { 19859644Sps for (;;) { 19959644Sps if (bcmp((void *)pxe_p->Signature, S_SIZE("!PXE"))) { 20059644Sps pxe_p = NULL; 20159644Sps break; 20259644Sps } 20359644Sps checksum = 0; 20459644Sps checkptr = (uint8_t *)pxe_p; 20559644Sps for (counter = 0; counter < pxe_p->StructLength; 20659644Sps counter++) 20759644Sps checksum += *checkptr++; 20859644Sps if (checksum != 0) { 20959644Sps pxe_p = NULL; 21059644Sps break; 21159644Sps } 21259644Sps pxe_call = bangpxe_call; 21359644Sps break; 21459644Sps } 21559390Sps } 21659644Sps 21759644Sps printf("\nPXE version %d.%d, real mode entry point ", 21859644Sps (uint8_t) (pxenv_p->Version >> 8), 21959644Sps (uint8_t) (pxenv_p->Version & 0xFF)); 22059644Sps if (pxe_call == bangpxe_call) 22159644Sps printf("@%04x:%04x\n", 22259644Sps pxe_p->EntryPointSP.segment, 22359644Sps pxe_p->EntryPointSP.offset); 22459644Sps else 22559644Sps printf("@%04x:%04x\n", 22659644Sps pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset); 22759390Sps 22858713Sjhb gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer; 22958713Sjhb bzero(gci_p, sizeof(*gci_p)); 23058713Sjhb gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; 23158713Sjhb pxe_call(PXENV_GET_CACHED_INFO); 23258713Sjhb if (gci_p->Status != 0) { 23358713Sjhb pxe_perror(gci_p->Status); 23459455Sps pxe_p = NULL; 23558713Sjhb return (0); 23658713Sjhb } 23759087Sps bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset), 23859087Sps &bootplayer, gci_p->BufferSize); 23958713Sjhb return (1); 24058713Sjhb} 24158713Sjhb 24259087Sps 24359087Spsstatic int 24459087Spspxe_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 24564187Sjhb char *buf, size_t *rsize) 24658713Sjhb{ 24759087Sps return (EIO); 24858713Sjhb} 24958713Sjhb 25059087Spsstatic int 25159087Spspxe_open(struct open_file *f, ...) 25258713Sjhb{ 25359087Sps va_list args; 25459087Sps char *devname; /* Device part of file name (or NULL). */ 25559686Sps char temp[FNAME_SIZE]; 25659087Sps int error = 0; 25759686Sps int i; 25859686Sps 25959087Sps va_start(args, f); 26059087Sps devname = va_arg(args, char*); 26159087Sps va_end(args); 26259087Sps 26359087Sps /* On first open, do netif open, mount, etc. */ 26459087Sps if (pxe_opens == 0) { 26559087Sps /* Find network interface. */ 26659087Sps if (pxe_sock < 0) { 26759087Sps pxe_sock = netif_open(devname); 26859087Sps if (pxe_sock < 0) { 26959087Sps printf("pxe_open: netif_open() failed\n"); 27059087Sps return (ENXIO); 27159087Sps } 27264187Sjhb if (pxe_debug) 27359087Sps printf("pxe_open: netif_open() succeeded\n"); 27459087Sps } 27559686Sps if (rootip.s_addr == 0) { 27659686Sps /* 27759686Sps * Do a bootp/dhcp request to find out where our 27859686Sps * NFS/TFTP server is. Even if we dont get back 27959686Sps * the proper information, fall back to the server 28059686Sps * which brought us to life and a default rootpath. 28159686Sps */ 28264527Sps bootp(pxe_sock, BOOTP_PXE); 28359768Sps if (rootip.s_addr == 0) 28459686Sps rootip.s_addr = bootplayer.sip; 28559768Sps if (!rootpath[1]) 28659686Sps strcpy(rootpath, PXENFSROOTPATH); 28759686Sps 288116451Siedowse for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) 28968362Sps if (rootpath[i] == ':') 29059686Sps break; 291116451Siedowse if (i && i != FNAME_SIZE && rootpath[i] == ':') { 29268362Sps rootpath[i++] = '\0'; 29368362Sps if (inet_addr(&rootpath[0]) != INADDR_NONE) 29468362Sps rootip.s_addr = inet_addr(&rootpath[0]); 29559686Sps bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1); 29659686Sps bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); 29759686Sps } 29859686Sps printf("pxe_open: server addr: %s\n", inet_ntoa(rootip)); 29959686Sps printf("pxe_open: server path: %s\n", rootpath); 30059686Sps printf("pxe_open: gateway ip: %s\n", inet_ntoa(gateip)); 30164522Sps 30265498Smsmith setenv("boot.netif.ip", inet_ntoa(myip), 1); 30365498Smsmith setenv("boot.netif.netmask", intoa(netmask), 1); 30465498Smsmith setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 30565498Smsmith if (bootplayer.Hardware == ETHER_TYPE) { 30665498Smsmith sprintf(temp, "%6D", bootplayer.CAddr, ":"); 30765498Smsmith setenv("boot.netif.hwaddr", temp, 1); 30865498Smsmith } 30965498Smsmith setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 31065498Smsmith setenv("boot.nfsroot.path", rootpath, 1); 311145209Swollman setenv("dhcp.host-name", hostname, 1); 31259686Sps } 31359087Sps } 31459087Sps pxe_opens++; 31559087Sps f->f_devdata = &pxe_sock; 31659087Sps return (error); 31758713Sjhb} 31858713Sjhb 31959087Spsstatic int 32059087Spspxe_close(struct open_file *f) 32158713Sjhb{ 32258713Sjhb 32359087Sps#ifdef PXE_DEBUG 32464187Sjhb if (pxe_debug) 32559087Sps printf("pxe_close: opens=%d\n", pxe_opens); 32659087Sps#endif 32758713Sjhb 32859087Sps /* On last close, do netif close, etc. */ 32959087Sps f->f_devdata = NULL; 33059087Sps /* Extra close call? */ 33159087Sps if (pxe_opens <= 0) 33259087Sps return (0); 33359087Sps pxe_opens--; 33459087Sps /* Not last close? */ 33559087Sps if (pxe_opens > 0) 33659087Sps return(0); 33759686Sps 33865498Smsmith /* get an NFS filehandle for our root filesystem */ 33965498Smsmith pxe_setnfshandle(rootpath); 34065498Smsmith 34159087Sps if (pxe_sock >= 0) { 34265498Smsmith 34359087Sps#ifdef PXE_DEBUG 34464187Sjhb if (pxe_debug) 34559087Sps printf("pxe_close: calling netif_close()\n"); 34659087Sps#endif 34759087Sps netif_close(pxe_sock); 34859087Sps pxe_sock = -1; 34959087Sps } 35059087Sps return (0); 35159087Sps} 35258713Sjhb 35359087Spsstatic void 35459087Spspxe_print(int verbose) 35559087Sps{ 35659644Sps if (pxe_call != NULL) { 35759087Sps if (*bootplayer.Sname == '\0') { 35859087Sps printf(" "IP_STR":%s\n", 35959087Sps IP_ARGS(htonl(bootplayer.sip)), 36059087Sps bootplayer.bootfile); 36159087Sps } else { 36259087Sps printf(" %s:%s\n", bootplayer.Sname, 36359087Sps bootplayer.bootfile); 36459087Sps } 36559087Sps } 36658713Sjhb 36759087Sps return; 36858713Sjhb} 36958713Sjhb 37059390Spsstatic void 37159390Spspxe_cleanup(void) 37259390Sps{ 37364187Sjhb#ifdef PXE_DEBUG 37459390Sps t_PXENV_UNLOAD_STACK *unload_stack_p = 37559390Sps (t_PXENV_UNLOAD_STACK *)scratch_buffer; 37659390Sps t_PXENV_UNDI_SHUTDOWN *undi_shutdown_p = 37759390Sps (t_PXENV_UNDI_SHUTDOWN *)scratch_buffer; 37864187Sjhb#endif 37959087Sps 38059644Sps if (pxe_call == NULL) 38159455Sps return; 38259455Sps 38359408Sps pxe_call(PXENV_UNDI_SHUTDOWN); 38459855Sps 38559855Sps#ifdef PXE_DEBUG 38664187Sjhb if (pxe_debug && undi_shutdown_p->Status != 0) 38759644Sps printf("pxe_cleanup: UNDI_SHUTDOWN failed %x\n", 38859855Sps undi_shutdown_p->Status); 38959855Sps#endif 39059408Sps 39159390Sps pxe_call(PXENV_UNLOAD_STACK); 39259855Sps 39359855Sps#ifdef PXE_DEBUG 39464187Sjhb if (pxe_debug && unload_stack_p->Status != 0) 39559644Sps printf("pxe_cleanup: UNLOAD_STACK failed %x\n", 39659408Sps unload_stack_p->Status); 39759855Sps#endif 39859390Sps} 39959390Sps 40058713Sjhbvoid 40158713Sjhbpxe_perror(int err) 40258713Sjhb{ 40358713Sjhb return; 40458713Sjhb} 40558713Sjhb 40665498Smsmith/* 40765498Smsmith * Reach inside the libstand NFS code and dig out an NFS handle 40865498Smsmith * for the root filesystem. 40965498Smsmith */ 41065498Smsmithstruct nfs_iodesc { 41165498Smsmith struct iodesc *iodesc; 41265498Smsmith off_t off; 41365498Smsmith u_char fh[NFS_FHSIZE]; 41465498Smsmith /* structure truncated here */ 41565498Smsmith}; 41665498Smsmithextern struct nfs_iodesc nfs_root_node; 417143476Skanextern int rpc_port; 41865498Smsmith 41965498Smsmithstatic void 420143476Skanpxe_rpcmountcall() 421143476Skan{ 422143476Skan struct iodesc *d; 423143476Skan int error; 424143476Skan 425143476Skan if (!(d = socktodesc(pxe_sock))) 426143476Skan return; 427143476Skan d->myport = htons(--rpc_port); 428143476Skan d->destip = rootip; 429143476Skan if ((error = nfs_getrootfh(d, rootpath, nfs_root_node.fh)) != 0) 430143476Skan printf("NFS MOUNT RPC error: %d\n", error); 431143476Skan nfs_root_node.iodesc = d; 432143476Skan} 433143476Skan 434143476Skanstatic void 43565498Smsmithpxe_setnfshandle(char *rootpath) 43665498Smsmith{ 43765498Smsmith int i; 43865498Smsmith u_char *fh; 43965498Smsmith char buf[2 * NFS_FHSIZE + 3], *cp; 44065498Smsmith 441143476Skan /* 442143476Skan * If NFS files were never opened, we need to do mount call 443143476Skan * ourselves. Use nfs_root_node.iodesc as flag indicating 444143476Skan * previous NFS usage. 445143476Skan */ 446143476Skan if (nfs_root_node.iodesc == NULL) 447143476Skan pxe_rpcmountcall(); 448143476Skan 44965498Smsmith fh = &nfs_root_node.fh[0]; 45065498Smsmith buf[0] = 'X'; 45165498Smsmith cp = &buf[1]; 45265498Smsmith for (i = 0; i < NFS_FHSIZE; i++, cp += 2) 45365498Smsmith sprintf(cp, "%02x", fh[i]); 45465498Smsmith sprintf(cp, "X"); 45565498Smsmith setenv("boot.nfsroot.nfshandle", buf, 1); 45665498Smsmith} 45765498Smsmith 45858713Sjhbvoid 45959644Spspxenv_call(int func) 46058713Sjhb{ 46159644Sps#ifdef PXE_DEBUG 46264187Sjhb if (pxe_debug) 46359644Sps printf("pxenv_call %x\n", func); 46459644Sps#endif 46559644Sps 46658713Sjhb bzero(&v86, sizeof(v86)); 46758713Sjhb bzero(data_buffer, sizeof(data_buffer)); 46859390Sps 46959644Sps __pxenvseg = pxenv_p->RMEntry.segment; 47059644Sps __pxenvoff = pxenv_p->RMEntry.offset; 47159390Sps 47259390Sps v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 47359644Sps v86.es = VTOPSEG(scratch_buffer); 47459644Sps v86.edi = VTOPOFF(scratch_buffer); 47559644Sps v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry); 47659644Sps v86.ebx = func; 47759644Sps v86int(); 47859644Sps v86.ctl = V86_FLAGS; 47959644Sps} 48059644Sps 48159644Spsvoid 48259644Spsbangpxe_call(int func) 48359644Sps{ 48459644Sps#ifdef PXE_DEBUG 48564187Sjhb if (pxe_debug) 48659644Sps printf("bangpxe_call %x\n", func); 48759644Sps#endif 48859644Sps 48959644Sps bzero(&v86, sizeof(v86)); 49059644Sps bzero(data_buffer, sizeof(data_buffer)); 49159644Sps 49259644Sps __bangpxeseg = pxe_p->EntryPointSP.segment; 49359644Sps __bangpxeoff = pxe_p->EntryPointSP.offset; 49459644Sps 49559644Sps v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 49659390Sps v86.edx = VTOPSEG(scratch_buffer); 49759390Sps v86.eax = VTOPOFF(scratch_buffer); 49859644Sps v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry); 49959390Sps v86.ebx = func; 50058713Sjhb v86int(); 50159390Sps v86.ctl = V86_FLAGS; 50258713Sjhb} 50358713Sjhb 50459087Sps 50559087Spstime_t 50659087Spsgetsecs() 50758713Sjhb{ 50859087Sps time_t n = 0; 50959087Sps time(&n); 51059087Sps return n; 51158713Sjhb} 51258713Sjhb 51358713Sjhbstatic int 51459087Spspxe_netif_match(struct netif *nif, void *machdep_hint) 51558713Sjhb{ 51659087Sps return 1; 51758713Sjhb} 51858713Sjhb 51959087Sps 52058713Sjhbstatic int 52159087Spspxe_netif_probe(struct netif *nif, void *machdep_hint) 52258713Sjhb{ 52359087Sps t_PXENV_UDP_OPEN *udpopen_p = (t_PXENV_UDP_OPEN *)scratch_buffer; 52459456Sps 52559644Sps if (pxe_call == NULL) 52659456Sps return -1; 52759456Sps 52859087Sps bzero(udpopen_p, sizeof(*udpopen_p)); 52959087Sps udpopen_p->src_ip = bootplayer.yip; 53059087Sps pxe_call(PXENV_UDP_OPEN); 53158713Sjhb 53259390Sps if (udpopen_p->status != 0) { 53359087Sps printf("pxe_netif_probe: failed %x\n", udpopen_p->status); 53459390Sps return -1; 53559390Sps } 53659087Sps return 0; 53758713Sjhb} 53858713Sjhb 53959087Spsstatic void 54059087Spspxe_netif_end(struct netif *nif) 54158713Sjhb{ 54259087Sps t_PXENV_UDP_CLOSE *udpclose_p = (t_PXENV_UDP_CLOSE *)scratch_buffer; 54359087Sps bzero(udpclose_p, sizeof(*udpclose_p)); 54458713Sjhb 54559087Sps pxe_call(PXENV_UDP_CLOSE); 54659087Sps if (udpclose_p->status != 0) 54759087Sps printf("pxe_end failed %x\n", udpclose_p->status); 54858713Sjhb} 54958713Sjhb 55059087Spsstatic void 55159087Spspxe_netif_init(struct iodesc *desc, void *machdep_hint) 55258713Sjhb{ 55359686Sps int i; 55459686Sps for (i = 0; i < 6; ++i) 55559686Sps desc->myea[i] = bootplayer.CAddr[i]; 55659686Sps desc->xid = bootplayer.ident; 55758713Sjhb} 55858713Sjhb 55958713Sjhbstatic int 56059087Spspxe_netif_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 56158713Sjhb{ 56259087Sps return len; 56358713Sjhb} 56458713Sjhb 56558713Sjhbstatic int 56659087Spspxe_netif_put(struct iodesc *desc, void *pkt, size_t len) 56758713Sjhb{ 56859087Sps return len; 56958713Sjhb} 57058713Sjhb 57159087Spsssize_t 57259087Spssendudp(struct iodesc *h, void *pkt, size_t len) 57358713Sjhb{ 57459087Sps t_PXENV_UDP_WRITE *udpwrite_p = (t_PXENV_UDP_WRITE *)scratch_buffer; 57559087Sps bzero(udpwrite_p, sizeof(*udpwrite_p)); 57659087Sps 57759686Sps udpwrite_p->ip = h->destip.s_addr; 57859087Sps udpwrite_p->dst_port = h->destport; 57959087Sps udpwrite_p->src_port = h->myport; 58059087Sps udpwrite_p->buffer_size = len; 58159087Sps udpwrite_p->buffer.segment = VTOPSEG(pkt); 58259087Sps udpwrite_p->buffer.offset = VTOPOFF(pkt); 58358713Sjhb 58474265Sps if (netmask == 0 || SAMENET(myip, h->destip, netmask)) 58574265Sps udpwrite_p->gw = 0; 58674265Sps else 58774265Sps udpwrite_p->gw = gateip.s_addr; 58874265Sps 58959087Sps pxe_call(PXENV_UDP_WRITE); 59058713Sjhb 59159390Sps#if 0 59259087Sps /* XXX - I dont know why we need this. */ 59359087Sps delay(1000); 59459390Sps#endif 59559390Sps if (udpwrite_p->status != 0) { 59659673Sps /* XXX: This happens a lot. It shouldn't. */ 59759673Sps if (udpwrite_p->status != 1) 59859673Sps printf("sendudp failed %x\n", udpwrite_p->status); 59959390Sps return -1; 60059390Sps } 60159087Sps return len; 60258713Sjhb} 60358713Sjhb 60459087Spsssize_t 60559087Spsreadudp(struct iodesc *h, void *pkt, size_t len, time_t timeout) 60658713Sjhb{ 60759087Sps t_PXENV_UDP_READ *udpread_p = (t_PXENV_UDP_READ *)scratch_buffer; 60859087Sps struct udphdr *uh = NULL; 60959087Sps 61059087Sps uh = (struct udphdr *) pkt - 1; 61159087Sps bzero(udpread_p, sizeof(*udpread_p)); 61259087Sps 61359686Sps udpread_p->dest_ip = h->myip.s_addr; 61459087Sps udpread_p->d_port = h->myport; 61559087Sps udpread_p->buffer_size = len; 61659087Sps udpread_p->buffer.segment = VTOPSEG(data_buffer); 61759087Sps udpread_p->buffer.offset = VTOPOFF(data_buffer); 61858713Sjhb 61959087Sps pxe_call(PXENV_UDP_READ); 62058713Sjhb 62159390Sps#if 0 62259087Sps /* XXX - I dont know why we need this. */ 62359087Sps delay(1000); 62459390Sps#endif 62559390Sps if (udpread_p->status != 0) { 62659390Sps /* XXX: This happens a lot. It shouldn't. */ 62759390Sps if (udpread_p->status != 1) 62859390Sps printf("readudp failed %x\n", udpread_p->status); 62959390Sps return -1; 63059390Sps } 63159087Sps bcopy(data_buffer, pkt, udpread_p->buffer_size); 63259087Sps uh->uh_sport = udpread_p->s_port; 63359087Sps return udpread_p->buffer_size; 63458713Sjhb} 635