pxe.c revision 116451
158713Sjhb/* 258713Sjhb * Copyright (c) 2000 Alfred Perlstein <alfred@freebsd.org> 358713Sjhb * All rights reserved. 458713Sjhb * Copyright (c) 2000 Paul Saab <ps@freebsd.org> 558713Sjhb * All rights reserved. 658713Sjhb * Copyright (c) 2000 John Baldwin <jhb@freebsd.org> 758713Sjhb * All rights reserved. 858713Sjhb * 958713Sjhb * Redistribution and use in source and binary forms, with or without 1058713Sjhb * modification, are permitted provided that the following conditions 1158713Sjhb * are met: 1258713Sjhb * 1. Redistributions of source code must retain the above copyright 1358713Sjhb * notice, this list of conditions and the following disclaimer. 1458713Sjhb * 2. Redistributions in binary form must reproduce the above copyright 1558713Sjhb * notice, this list of conditions and the following disclaimer in the 1658713Sjhb * documentation and/or other materials provided with the distribution. 1758713Sjhb * 1858713Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1958713Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2058713Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2158713Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2258713Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2358713Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2458713Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2558713Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2658713Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2758713Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2858713Sjhb * SUCH DAMAGE. 2958713Sjhb * 3058713Sjhb * $FreeBSD: head/sys/boot/i386/libi386/pxe.c 116451 2003-06-16 20:48:56Z iedowse $ 3158713Sjhb */ 3258713Sjhb 3358713Sjhb#include <stand.h> 3459768Sps#include <string.h> 3559768Sps#include <stdarg.h> 3658713Sjhb 3759087Sps#include <netinet/in_systm.h> 3859087Sps#include <netinet/in.h> 3959087Sps#include <netinet/udp.h> 4059087Sps 4159087Sps#include <net.h> 4259087Sps#include <netif.h> 4365498Smsmith#include <nfsv2.h> 4465498Smsmith#include <iodesc.h> 4559087Sps 4664527Sps#include <bootp.h> 4758713Sjhb#include <bootstrap.h> 4858713Sjhb#include "btxv86.h" 4958993Sps#include "pxe.h" 5058713Sjhb 5158713Sjhb/* 5258713Sjhb * Allocate the PXE buffers statically instead of sticking grimy fingers into 5358713Sjhb * BTX's private data area. The scratch buffer is used to send information to 5458713Sjhb * the PXE BIOS, and the data buffer is used to receive data from the PXE BIOS. 5558713Sjhb */ 5658993Sps#define PXE_BUFFER_SIZE 0x2000 5758993Sps#define PXE_TFTP_BUFFER_SIZE 512 5858993Spsstatic char scratch_buffer[PXE_BUFFER_SIZE]; 5958993Spsstatic char data_buffer[PXE_BUFFER_SIZE]; 6058713Sjhb 6159390Spsstatic pxenv_t *pxenv_p = NULL; /* PXENV+ */ 6259390Spsstatic pxe_t *pxe_p = NULL; /* !PXE */ 6359087Spsstatic BOOTPLAYER bootplayer; /* PXE Cached information. */ 6458713Sjhb 6564187Sjhbstatic int pxe_debug = 0; 6659087Spsstatic int pxe_sock = -1; 6759087Spsstatic int pxe_opens = 0; 6859087Sps 6958713Sjhbvoid pxe_enable(void *pxeinfo); 7059644Spsstatic void (*pxe_call)(int func); 7159644Spsstatic void pxenv_call(int func); 7259644Spsstatic void bangpxe_call(int func); 7359087Sps 7458713Sjhbstatic int pxe_init(void); 7559087Spsstatic int pxe_strategy(void *devdata, int flag, daddr_t dblk, 7664187Sjhb size_t size, char *buf, size_t *rsize); 7758713Sjhbstatic int pxe_open(struct open_file *f, ...); 7858713Sjhbstatic int pxe_close(struct open_file *f); 7958713Sjhbstatic void pxe_print(int verbose); 8059390Spsstatic void pxe_cleanup(void); 8165498Smsmithstatic void pxe_setnfshandle(char *rootpath); 8258713Sjhb 8358713Sjhbstatic void pxe_perror(int error); 8459087Spsstatic int pxe_netif_match(struct netif *nif, void *machdep_hint); 8559087Spsstatic int pxe_netif_probe(struct netif *nif, void *machdep_hint); 8659087Spsstatic void pxe_netif_init(struct iodesc *desc, void *machdep_hint); 8759087Spsstatic int pxe_netif_get(struct iodesc *desc, void *pkt, size_t len, 8859087Sps time_t timeout); 8959087Spsstatic int pxe_netif_put(struct iodesc *desc, void *pkt, size_t len); 9059087Spsstatic void pxe_netif_end(struct netif *nif); 9158713Sjhb 9259087Spsextern struct netif_stats pxe_st[]; 9359644Spsextern u_int16_t __bangpxeseg; 9459644Spsextern u_int16_t __bangpxeoff; 9559644Spsextern void __bangpxeentry(void); 9659644Spsextern u_int16_t __pxenvseg; 9759644Spsextern u_int16_t __pxenvoff; 9859644Spsextern void __pxenventry(void); 9958713Sjhb 10059087Spsstruct netif_dif pxe_ifs[] = { 10159087Sps/* dif_unit dif_nsel dif_stats dif_private */ 10259087Sps {0, 1, &pxe_st[0], 0} 10359087Sps}; 10458713Sjhb 10559087Spsstruct netif_stats pxe_st[NENTS(pxe_ifs)]; 10659087Sps 10759087Spsstruct netif_driver pxenetif = { 10859087Sps "pxenet", 10959087Sps pxe_netif_match, 11059087Sps pxe_netif_probe, 11159087Sps pxe_netif_init, 11259087Sps pxe_netif_get, 11359087Sps pxe_netif_put, 11459087Sps pxe_netif_end, 11559087Sps pxe_ifs, 11659087Sps NENTS(pxe_ifs) 11759087Sps}; 11859087Sps 11959087Spsstruct netif_driver *netif_drivers[] = { 12059087Sps &pxenetif, 12159087Sps NULL 12259087Sps}; 12359087Sps 12458713Sjhbstruct devsw pxedisk = { 12558713Sjhb "pxe", 12658713Sjhb DEVT_NET, 12758713Sjhb pxe_init, 12858713Sjhb pxe_strategy, 12958713Sjhb pxe_open, 13058713Sjhb pxe_close, 13158713Sjhb noioctl, 13259408Sps pxe_print, 13359408Sps pxe_cleanup 13458713Sjhb}; 13558713Sjhb 13658713Sjhb/* 13758713Sjhb * This function is called by the loader to enable PXE support if we 13858713Sjhb * are booted by PXE. The passed in pointer is a pointer to the 13958713Sjhb * PXENV+ structure. 14058713Sjhb */ 14158713Sjhbvoid 14258713Sjhbpxe_enable(void *pxeinfo) 14358713Sjhb{ 14459644Sps pxenv_p = (pxenv_t *)pxeinfo; 14559644Sps pxe_p = (pxe_t *)PTOV(pxenv_p->PXEPtr.segment * 16 + 14659644Sps pxenv_p->PXEPtr.offset); 14759644Sps pxe_call = NULL; 14858713Sjhb} 14958713Sjhb 15058713Sjhb/* 15158713Sjhb * return true if pxe structures are found/initialized, 15258713Sjhb * also figures out our IP information via the pxe cached info struct 15358713Sjhb */ 15458713Sjhbstatic int 15558713Sjhbpxe_init(void) 15658713Sjhb{ 15758713Sjhb t_PXENV_GET_CACHED_INFO *gci_p; 15858713Sjhb int counter; 15958713Sjhb uint8_t checksum; 16058713Sjhb uint8_t *checkptr; 16158713Sjhb 16258713Sjhb if(pxenv_p == NULL) 16358713Sjhb return (0); 16458713Sjhb 16558713Sjhb /* look for "PXENV+" */ 16659456Sps if (bcmp((void *)pxenv_p->Signature, S_SIZE("PXENV+"))) { 16759456Sps pxenv_p = NULL; 16858713Sjhb return (0); 16959456Sps } 17058713Sjhb 17158713Sjhb /* make sure the size is something we can handle */ 17258713Sjhb if (pxenv_p->Length > sizeof(*pxenv_p)) { 17358713Sjhb printf("PXENV+ structure too large, ignoring\n"); 17458713Sjhb pxenv_p = NULL; 17558713Sjhb return (0); 17658713Sjhb } 17758713Sjhb 17858713Sjhb /* 17958713Sjhb * do byte checksum: 18058713Sjhb * add up each byte in the structure, the total should be 0 18158713Sjhb */ 18258713Sjhb checksum = 0; 18358713Sjhb checkptr = (uint8_t *) pxenv_p; 18458713Sjhb for (counter = 0; counter < pxenv_p->Length; counter++) 18558713Sjhb checksum += *checkptr++; 18658713Sjhb if (checksum != 0) { 18758713Sjhb printf("PXENV+ structure failed checksum, ignoring\n"); 18858713Sjhb pxenv_p = NULL; 18958713Sjhb return (0); 19058713Sjhb } 19159390Sps 19259644Sps 19359644Sps /* 19459644Sps * PXENV+ passed, so use that if !PXE is not available or 19559644Sps * the checksum fails. 19659644Sps */ 19759644Sps pxe_call = pxenv_call; 19859644Sps if (pxenv_p->Version >= 0x0200) { 19959644Sps for (;;) { 20059644Sps if (bcmp((void *)pxe_p->Signature, S_SIZE("!PXE"))) { 20159644Sps pxe_p = NULL; 20259644Sps break; 20359644Sps } 20459644Sps checksum = 0; 20559644Sps checkptr = (uint8_t *)pxe_p; 20659644Sps for (counter = 0; counter < pxe_p->StructLength; 20759644Sps counter++) 20859644Sps checksum += *checkptr++; 20959644Sps if (checksum != 0) { 21059644Sps pxe_p = NULL; 21159644Sps break; 21259644Sps } 21359644Sps pxe_call = bangpxe_call; 21459644Sps break; 21559644Sps } 21659390Sps } 21759644Sps 21859644Sps printf("\nPXE version %d.%d, real mode entry point ", 21959644Sps (uint8_t) (pxenv_p->Version >> 8), 22059644Sps (uint8_t) (pxenv_p->Version & 0xFF)); 22159644Sps if (pxe_call == bangpxe_call) 22259644Sps printf("@%04x:%04x\n", 22359644Sps pxe_p->EntryPointSP.segment, 22459644Sps pxe_p->EntryPointSP.offset); 22559644Sps else 22659644Sps printf("@%04x:%04x\n", 22759644Sps pxenv_p->RMEntry.segment, pxenv_p->RMEntry.offset); 22859390Sps 22958713Sjhb gci_p = (t_PXENV_GET_CACHED_INFO *) scratch_buffer; 23058713Sjhb bzero(gci_p, sizeof(*gci_p)); 23158713Sjhb gci_p->PacketType = PXENV_PACKET_TYPE_BINL_REPLY; 23258713Sjhb pxe_call(PXENV_GET_CACHED_INFO); 23358713Sjhb if (gci_p->Status != 0) { 23458713Sjhb pxe_perror(gci_p->Status); 23559455Sps pxe_p = NULL; 23658713Sjhb return (0); 23758713Sjhb } 23859087Sps bcopy(PTOV((gci_p->Buffer.segment << 4) + gci_p->Buffer.offset), 23959087Sps &bootplayer, gci_p->BufferSize); 24058713Sjhb return (1); 24158713Sjhb} 24258713Sjhb 24359087Sps 24459087Spsstatic int 24559087Spspxe_strategy(void *devdata, int flag, daddr_t dblk, size_t size, 24664187Sjhb char *buf, size_t *rsize) 24758713Sjhb{ 24859087Sps return (EIO); 24958713Sjhb} 25058713Sjhb 25159087Spsstatic int 25259087Spspxe_open(struct open_file *f, ...) 25358713Sjhb{ 25459087Sps va_list args; 25559087Sps char *devname; /* Device part of file name (or NULL). */ 25659686Sps char temp[FNAME_SIZE]; 25759087Sps int error = 0; 25859686Sps int i; 25959686Sps 26059087Sps va_start(args, f); 26159087Sps devname = va_arg(args, char*); 26259087Sps va_end(args); 26359087Sps 26459087Sps /* On first open, do netif open, mount, etc. */ 26559087Sps if (pxe_opens == 0) { 26659087Sps /* Find network interface. */ 26759087Sps if (pxe_sock < 0) { 26859087Sps pxe_sock = netif_open(devname); 26959087Sps if (pxe_sock < 0) { 27059087Sps printf("pxe_open: netif_open() failed\n"); 27159087Sps return (ENXIO); 27259087Sps } 27364187Sjhb if (pxe_debug) 27459087Sps printf("pxe_open: netif_open() succeeded\n"); 27559087Sps } 27659686Sps if (rootip.s_addr == 0) { 27759686Sps /* 27859686Sps * Do a bootp/dhcp request to find out where our 27959686Sps * NFS/TFTP server is. Even if we dont get back 28059686Sps * the proper information, fall back to the server 28159686Sps * which brought us to life and a default rootpath. 28259686Sps */ 28364527Sps bootp(pxe_sock, BOOTP_PXE); 28459768Sps if (rootip.s_addr == 0) 28559686Sps rootip.s_addr = bootplayer.sip; 28659768Sps if (!rootpath[1]) 28759686Sps strcpy(rootpath, PXENFSROOTPATH); 28859686Sps 289116451Siedowse for (i = 0; rootpath[i] != '\0' && i < FNAME_SIZE; i++) 29068362Sps if (rootpath[i] == ':') 29159686Sps break; 292116451Siedowse if (i && i != FNAME_SIZE && rootpath[i] == ':') { 29368362Sps rootpath[i++] = '\0'; 29468362Sps if (inet_addr(&rootpath[0]) != INADDR_NONE) 29568362Sps rootip.s_addr = inet_addr(&rootpath[0]); 29659686Sps bcopy(&rootpath[i], &temp[0], strlen(&rootpath[i])+1); 29759686Sps bcopy(&temp[0], &rootpath[0], strlen(&rootpath[i])+1); 29859686Sps } 29959686Sps printf("pxe_open: server addr: %s\n", inet_ntoa(rootip)); 30059686Sps printf("pxe_open: server path: %s\n", rootpath); 30159686Sps printf("pxe_open: gateway ip: %s\n", inet_ntoa(gateip)); 30264522Sps 30365498Smsmith setenv("boot.netif.ip", inet_ntoa(myip), 1); 30465498Smsmith setenv("boot.netif.netmask", intoa(netmask), 1); 30565498Smsmith setenv("boot.netif.gateway", inet_ntoa(gateip), 1); 30665498Smsmith if (bootplayer.Hardware == ETHER_TYPE) { 30765498Smsmith sprintf(temp, "%6D", bootplayer.CAddr, ":"); 30865498Smsmith setenv("boot.netif.hwaddr", temp, 1); 30965498Smsmith } 31065498Smsmith setenv("boot.nfsroot.server", inet_ntoa(rootip), 1); 31165498Smsmith setenv("boot.nfsroot.path", rootpath, 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; 41765498Smsmith 41865498Smsmithstatic void 41965498Smsmithpxe_setnfshandle(char *rootpath) 42065498Smsmith{ 42165498Smsmith int i; 42265498Smsmith u_char *fh; 42365498Smsmith char buf[2 * NFS_FHSIZE + 3], *cp; 42465498Smsmith 42565498Smsmith fh = &nfs_root_node.fh[0]; 42665498Smsmith buf[0] = 'X'; 42765498Smsmith cp = &buf[1]; 42865498Smsmith for (i = 0; i < NFS_FHSIZE; i++, cp += 2) 42965498Smsmith sprintf(cp, "%02x", fh[i]); 43065498Smsmith sprintf(cp, "X"); 43165498Smsmith setenv("boot.nfsroot.nfshandle", buf, 1); 43265498Smsmith} 43365498Smsmith 43458713Sjhbvoid 43559644Spspxenv_call(int func) 43658713Sjhb{ 43759644Sps#ifdef PXE_DEBUG 43864187Sjhb if (pxe_debug) 43959644Sps printf("pxenv_call %x\n", func); 44059644Sps#endif 44159644Sps 44258713Sjhb bzero(&v86, sizeof(v86)); 44358713Sjhb bzero(data_buffer, sizeof(data_buffer)); 44459390Sps 44559644Sps __pxenvseg = pxenv_p->RMEntry.segment; 44659644Sps __pxenvoff = pxenv_p->RMEntry.offset; 44759390Sps 44859390Sps v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 44959644Sps v86.es = VTOPSEG(scratch_buffer); 45059644Sps v86.edi = VTOPOFF(scratch_buffer); 45159644Sps v86.addr = (VTOPSEG(__pxenventry) << 16) | VTOPOFF(__pxenventry); 45259644Sps v86.ebx = func; 45359644Sps v86int(); 45459644Sps v86.ctl = V86_FLAGS; 45559644Sps} 45659644Sps 45759644Spsvoid 45859644Spsbangpxe_call(int func) 45959644Sps{ 46059644Sps#ifdef PXE_DEBUG 46164187Sjhb if (pxe_debug) 46259644Sps printf("bangpxe_call %x\n", func); 46359644Sps#endif 46459644Sps 46559644Sps bzero(&v86, sizeof(v86)); 46659644Sps bzero(data_buffer, sizeof(data_buffer)); 46759644Sps 46859644Sps __bangpxeseg = pxe_p->EntryPointSP.segment; 46959644Sps __bangpxeoff = pxe_p->EntryPointSP.offset; 47059644Sps 47159644Sps v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS; 47259390Sps v86.edx = VTOPSEG(scratch_buffer); 47359390Sps v86.eax = VTOPOFF(scratch_buffer); 47459644Sps v86.addr = (VTOPSEG(__bangpxeentry) << 16) | VTOPOFF(__bangpxeentry); 47559390Sps v86.ebx = func; 47658713Sjhb v86int(); 47759390Sps v86.ctl = V86_FLAGS; 47858713Sjhb} 47958713Sjhb 48059087Sps 48159087Spstime_t 48259087Spsgetsecs() 48358713Sjhb{ 48459087Sps time_t n = 0; 48559087Sps time(&n); 48659087Sps return n; 48758713Sjhb} 48858713Sjhb 48958713Sjhbstatic int 49059087Spspxe_netif_match(struct netif *nif, void *machdep_hint) 49158713Sjhb{ 49259087Sps return 1; 49358713Sjhb} 49458713Sjhb 49559087Sps 49658713Sjhbstatic int 49759087Spspxe_netif_probe(struct netif *nif, void *machdep_hint) 49858713Sjhb{ 49959087Sps t_PXENV_UDP_OPEN *udpopen_p = (t_PXENV_UDP_OPEN *)scratch_buffer; 50059456Sps 50159644Sps if (pxe_call == NULL) 50259456Sps return -1; 50359456Sps 50459087Sps bzero(udpopen_p, sizeof(*udpopen_p)); 50559087Sps udpopen_p->src_ip = bootplayer.yip; 50659087Sps pxe_call(PXENV_UDP_OPEN); 50758713Sjhb 50859390Sps if (udpopen_p->status != 0) { 50959087Sps printf("pxe_netif_probe: failed %x\n", udpopen_p->status); 51059390Sps return -1; 51159390Sps } 51259087Sps return 0; 51358713Sjhb} 51458713Sjhb 51559087Spsstatic void 51659087Spspxe_netif_end(struct netif *nif) 51758713Sjhb{ 51859087Sps t_PXENV_UDP_CLOSE *udpclose_p = (t_PXENV_UDP_CLOSE *)scratch_buffer; 51959087Sps bzero(udpclose_p, sizeof(*udpclose_p)); 52058713Sjhb 52159087Sps pxe_call(PXENV_UDP_CLOSE); 52259087Sps if (udpclose_p->status != 0) 52359087Sps printf("pxe_end failed %x\n", udpclose_p->status); 52458713Sjhb} 52558713Sjhb 52659087Spsstatic void 52759087Spspxe_netif_init(struct iodesc *desc, void *machdep_hint) 52858713Sjhb{ 52959686Sps int i; 53059686Sps for (i = 0; i < 6; ++i) 53159686Sps desc->myea[i] = bootplayer.CAddr[i]; 53259686Sps desc->xid = bootplayer.ident; 53358713Sjhb} 53458713Sjhb 53558713Sjhbstatic int 53659087Spspxe_netif_get(struct iodesc *desc, void *pkt, size_t len, time_t timeout) 53758713Sjhb{ 53859087Sps return len; 53958713Sjhb} 54058713Sjhb 54158713Sjhbstatic int 54259087Spspxe_netif_put(struct iodesc *desc, void *pkt, size_t len) 54358713Sjhb{ 54459087Sps return len; 54558713Sjhb} 54658713Sjhb 54759087Spsssize_t 54859087Spssendudp(struct iodesc *h, void *pkt, size_t len) 54958713Sjhb{ 55059087Sps t_PXENV_UDP_WRITE *udpwrite_p = (t_PXENV_UDP_WRITE *)scratch_buffer; 55159087Sps bzero(udpwrite_p, sizeof(*udpwrite_p)); 55259087Sps 55359686Sps udpwrite_p->ip = h->destip.s_addr; 55459087Sps udpwrite_p->dst_port = h->destport; 55559087Sps udpwrite_p->src_port = h->myport; 55659087Sps udpwrite_p->buffer_size = len; 55759087Sps udpwrite_p->buffer.segment = VTOPSEG(pkt); 55859087Sps udpwrite_p->buffer.offset = VTOPOFF(pkt); 55958713Sjhb 56074265Sps if (netmask == 0 || SAMENET(myip, h->destip, netmask)) 56174265Sps udpwrite_p->gw = 0; 56274265Sps else 56374265Sps udpwrite_p->gw = gateip.s_addr; 56474265Sps 56559087Sps pxe_call(PXENV_UDP_WRITE); 56658713Sjhb 56759390Sps#if 0 56859087Sps /* XXX - I dont know why we need this. */ 56959087Sps delay(1000); 57059390Sps#endif 57159390Sps if (udpwrite_p->status != 0) { 57259673Sps /* XXX: This happens a lot. It shouldn't. */ 57359673Sps if (udpwrite_p->status != 1) 57459673Sps printf("sendudp failed %x\n", udpwrite_p->status); 57559390Sps return -1; 57659390Sps } 57759087Sps return len; 57858713Sjhb} 57958713Sjhb 58059087Spsssize_t 58159087Spsreadudp(struct iodesc *h, void *pkt, size_t len, time_t timeout) 58258713Sjhb{ 58359087Sps t_PXENV_UDP_READ *udpread_p = (t_PXENV_UDP_READ *)scratch_buffer; 58459087Sps struct udphdr *uh = NULL; 58559087Sps 58659087Sps uh = (struct udphdr *) pkt - 1; 58759087Sps bzero(udpread_p, sizeof(*udpread_p)); 58859087Sps 58959686Sps udpread_p->dest_ip = h->myip.s_addr; 59059087Sps udpread_p->d_port = h->myport; 59159087Sps udpread_p->buffer_size = len; 59259087Sps udpread_p->buffer.segment = VTOPSEG(data_buffer); 59359087Sps udpread_p->buffer.offset = VTOPOFF(data_buffer); 59458713Sjhb 59559087Sps pxe_call(PXENV_UDP_READ); 59658713Sjhb 59759390Sps#if 0 59859087Sps /* XXX - I dont know why we need this. */ 59959087Sps delay(1000); 60059390Sps#endif 60159390Sps if (udpread_p->status != 0) { 60259390Sps /* XXX: This happens a lot. It shouldn't. */ 60359390Sps if (udpread_p->status != 1) 60459390Sps printf("readudp failed %x\n", udpread_p->status); 60559390Sps return -1; 60659390Sps } 60759087Sps bcopy(data_buffer, pkt, udpread_p->buffer_size); 60859087Sps uh->uh_sport = udpread_p->s_port; 60959087Sps return udpread_p->buffer_size; 61058713Sjhb} 611